/** * Handle request_header events for user agent extraction. * * Extract the "request_headers" field (a list) from the transactions's * data provider instance, then loop through the list, looking for the * "User-Agent" field. If found, the value is parsed and used to update the * connection object fields. * * @param[in] ib IronBee object * @param[in,out] tx Transaction. * @param[in] event Event type * @param[in] data Callback data (not used) * * @returns Status code */ static ib_status_t modua_user_agent(ib_engine_t *ib, ib_tx_t *tx, ib_state_event_type_t event, void *data) { assert(ib != NULL); assert(tx != NULL); assert(tx->data != NULL); assert(event == request_header_finished_event); ib_field_t *req_agent = NULL; ib_status_t rc = IB_OK; const ib_list_t *bs_list; const ib_bytestr_t *bs; /* Extract the User-Agent header field from the provider instance */ rc = ib_data_get(tx->data, "request_headers:User-Agent", &req_agent); if ( (req_agent == NULL) || (rc != IB_OK) ) { ib_log_debug_tx(tx, "request_header_finished_event: No user agent"); return IB_OK; } if (req_agent->type != IB_FTYPE_LIST) { ib_log_error_tx(tx, "Expected request_headers:User-Agent to " "return list of values."); return IB_EINVAL; } rc = ib_field_value_type(req_agent, ib_ftype_list_out(&bs_list), IB_FTYPE_LIST); if (rc != IB_OK) { ib_log_error_tx(tx, "Cannot retrieve request_headers:User-Agent: %d", rc); return rc; } if (IB_LIST_ELEMENTS(bs_list) == 0) { ib_log_debug_tx(tx, "request_header_finished_event: No user agent"); return IB_OK; } req_agent = (ib_field_t *)IB_LIST_NODE_DATA(IB_LIST_LAST(bs_list)); /* Found it: copy the data into a newly allocated string buffer */ rc = ib_field_value_type(req_agent, ib_ftype_bytestr_out(&bs), IB_FTYPE_BYTESTR); if (rc != IB_OK) { ib_log_error_tx(tx, "Request user agent is not a BYTESTR: %s", ib_status_to_string(rc)); return rc; } /* Finally, split it up & store the components */ rc = modua_agent_fields(ib, tx, bs); return rc; }
//! Iterator just past end of list. iterator end() const { if (IB_LIST_ELEMENTS(ib()) == 0) { return begin(); } else { return boost::next(iterator(IB_LIST_LAST(ib()))); } }
// Test pattern matching a field. TEST(TestIronBee, test_data_pcre) { ib_engine_t *ib; ib_data_config_t *dataconfig; ib_data_t *data; ib_field_t *list_field; ib_field_t *out_field; ib_list_t *list; ib_list_t *out_list; ib_field_t *field1; ib_field_t *field2; ib_field_t *field3; ib_num_t num1 = 1; ib_num_t num2 = 2; ib_num_t num3 = 3; ibtest_engine_create(&ib); ASSERT_EQ(IB_OK, ib_data_config_create(ib_engine_pool_main_get(ib), & dataconfig)); ASSERT_EQ(IB_OK, ib_data_create(dataconfig, ib_engine_pool_main_get(ib), &data)); ASSERT_TRUE(data); ASSERT_IB_OK( ib_field_create(&field1, ib_data_pool(data), "field1", 6, IB_FTYPE_NUM, &num1)); ASSERT_IB_OK( ib_field_create(&field2, ib_data_pool(data), "field2", 6, IB_FTYPE_NUM, &num2)); ASSERT_IB_OK( ib_field_create(&field3, ib_data_pool(data), "field3", 6, IB_FTYPE_NUM, &num3)); ASSERT_IB_OK(ib_data_add_list(data, "ARGV", &list_field)); ASSERT_IB_OK(ib_data_get(data, "ARGV", &out_field)); ASSERT_IB_OK(ib_field_value(list_field, &list)); ASSERT_IB_OK(ib_list_push(list, field1)); ASSERT_IB_OK(ib_list_push(list, field2)); ASSERT_IB_OK(ib_list_push(list, field3)); ASSERT_IB_OK(ib_data_get(data, "ARGV:/.*(1|3)/", &out_field)); ASSERT_IB_OK(ib_field_value(out_field, &out_list)); ASSERT_NE(list, out_list); /* Make sure it's a different list. */ ASSERT_EQ(2U, IB_LIST_ELEMENTS(out_list)); out_field = (ib_field_t *) IB_LIST_FIRST(out_list)->data; ASSERT_FALSE(memcmp(out_field->name, field1->name, field1->nlen)); out_field = (ib_field_t *) IB_LIST_LAST(out_list)->data; ASSERT_FALSE(memcmp(out_field->name, field3->name, field3->nlen)); ibtest_engine_destroy(ib); }
ib_status_t ib_stream_push_sdata(ib_stream_t *s, ib_sdata_t *sdata) { IB_FTRACE_INIT(); s->slen += sdata->dlen; if (IB_LIST_ELEMENTS(s) == 0) { IB_LIST_NODE_INSERT_INITIAL(s, sdata); IB_FTRACE_RET_STATUS(IB_OK); } IB_LIST_NODE_INSERT_LAST(s, sdata, ib_sdata_t); IB_FTRACE_RET_STATUS(IB_OK); }
const char *ib_field_format( const ib_field_t *field, bool quote, bool escape, const char **type_name, char *buf, size_t bufsize ) { ib_status_t rc; const char *tname = NULL; assert(buf != NULL); assert(bufsize > 0); *buf = '\0'; if (field == NULL) { tname = "NULL"; if (quote) { strncpy(buf, "\"\"", bufsize-1); *(buf+bufsize) = '\0'; } else { *buf = '\0'; } } else { switch (field->type) { case IB_FTYPE_NULSTR : { const char *s; tname = "NULSTR"; rc = ib_field_value(field, ib_ftype_nulstr_out(&s)); if (rc != IB_OK) { break; } if (escape) { ib_string_escape_json_buf(s, quote, buf, bufsize, NULL, NULL); } else if (quote) { snprintf(buf, bufsize, "\"%s\"", (s?s:"")); } else { strncpy(buf, s, bufsize-1); *(buf+bufsize-1) = '\0'; } break; } case IB_FTYPE_BYTESTR: { const ib_bytestr_t *bs; tname = "BYTESTR"; rc = ib_field_value(field, ib_ftype_bytestr_out(&bs)); if (rc != IB_OK) { break; } if (escape) { ib_string_escape_json_buf_ex(ib_bytestr_const_ptr(bs), ib_bytestr_length(bs), true, quote, buf, bufsize, NULL, NULL); } else if (quote) { snprintf(buf, bufsize, "\"%.*s\"", (int)ib_bytestr_length(bs), (const char *)ib_bytestr_const_ptr(bs)); } else { size_t len = ib_bytestr_length(bs); if (len > (bufsize - 1) ) { len = bufsize - 1; } strncpy(buf, (const char *)ib_bytestr_const_ptr(bs), len); *(buf+len) = '\0'; } break; } case IB_FTYPE_NUM : /**< Numeric value */ { ib_num_t n; tname = "NUM"; rc = ib_field_value(field, ib_ftype_num_out(&n)); if (rc != IB_OK) { break; } snprintf(buf, bufsize, "%"PRId64, n); break; } case IB_FTYPE_FLOAT : /**< Float numeric value */ { ib_float_t f; tname = "FLOAT"; rc = ib_field_value(field, ib_ftype_float_out(&f)); if (rc != IB_OK) { break; } snprintf(buf, bufsize, "%Lf", f); break; } case IB_FTYPE_LIST : /**< List */ { const ib_list_t *lst; size_t len; tname = "LIST"; rc = ib_field_value(field, ib_ftype_list_out(&lst)); if (rc != IB_OK) { break; } len = IB_LIST_ELEMENTS(lst); if (len == 0) { snprintf(buf, bufsize, "list[%zd]", len); } else { const ib_list_node_t *node; node = ib_list_last_const(lst); if (node == NULL) { snprintf(buf, bufsize, "list[%zd]", len); } else { ib_field_format((const ib_field_t *)node->data, quote, escape, &tname, buf, bufsize); } } break; } default: tname = buf; snprintf(buf, bufsize, "type = %d", field->type); break; } } /* Store the type name */ if (type_name != NULL) { *type_name = tname; } /* Return the buffer */ return buf; }
/** * Handle request_header events for user agent extraction. * * Extract the "request_headers" field (a list) from the transactions's * data provider instance, then loop through the list, looking for the * "User-Agent" field. If found, the value is parsed and used to update the * connection object fields. * * @param[in] ib IronBee object * @param[in,out] tx Transaction. * @param[in] event Event type * @param[in] data Callback data (module) * * @returns Status code */ static ib_status_t modua_user_agent(ib_engine_t *ib, ib_tx_t *tx, ib_state_event_type_t event, void *data) { assert(ib != NULL); assert(tx != NULL); assert(tx->var_store != NULL); assert(event == request_header_finished_event); assert(data != NULL); const ib_module_t *m = (const ib_module_t *)data; const ib_field_t *req_agent = NULL; ib_status_t rc = IB_OK; const ib_list_t *bs_list; const ib_bytestr_t *bs; const modua_config_t *cfg; rc = ib_context_module_config(ib_context_main(ib), m, &cfg); if (rc != IB_OK) { ib_log_error_tx(tx, "Can't fetch configuration: %s", ib_status_to_string(rc)); return rc; } /* Extract the User-Agent header field */ rc = ib_var_target_get_const( cfg->user_agent, &bs_list, tx->mp, tx->var_store ); if (rc == IB_ENOENT || ib_list_elements(bs_list) == 0) { ib_log_debug_tx(tx, "request_header_finished_event: No user agent"); return IB_OK; } if (rc != IB_OK) { ib_log_error_tx(tx, "Cannot retrieve request_headers:User-Agent: %d", rc); return rc; } if (IB_LIST_ELEMENTS(bs_list) == 0) { ib_log_debug_tx(tx, "request_header_finished_event: No user agent"); return IB_OK; } req_agent = (ib_field_t *)IB_LIST_NODE_DATA(IB_LIST_LAST(bs_list)); /* Found it: copy the data into a newly allocated string buffer */ rc = ib_field_value_type(req_agent, ib_ftype_bytestr_out(&bs), IB_FTYPE_BYTESTR); if (rc != IB_OK) { ib_log_error_tx(tx, "Request user agent is not a BYTESTR: %s", ib_status_to_string(rc)); return rc; } /* Finally, split it up & store the components */ rc = modua_agent_fields(ib, tx, bs); return rc; }