// 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); }
TEST(TestIronBee, test_data_name) { ib_engine_t *ib = NULL; ib_data_t *data = NULL; ib_field_t *list_field = NULL; ib_field_t *out_field = NULL; ibtest_engine_create(&ib); ASSERT_EQ(IB_OK, ib_data_create(ib_engine_pool_main_get(ib), &data)); ASSERT_TRUE(data); ASSERT_IB_OK(ib_data_add_list(data, "ARGV", &list_field)); ASSERT_IB_OK(ib_data_get(data, "ARGV", &out_field)); ASSERT_TRUE(out_field); out_field = NULL; ASSERT_IB_OK(ib_data_get_ex(data, "ARGV:/.*(1|3)/", 4, &out_field)); ASSERT_TRUE(out_field); ibtest_engine_destroy(ib); }
//! Ensure that the given field name exists in tx->dpi. static ib_status_t ensure_field_exists(ib_engine_t *ib, ib_tx_t *tx, const char *field_name) { IB_FTRACE_INIT(); ib_status_t rc; assert(ib!=NULL); assert(tx!=NULL); assert(tx->dpi!=NULL); assert(field_name!=NULL); ib_field_t *ib_field; rc = ib_data_get(tx->dpi, field_name, &ib_field); if (rc == IB_ENOENT) { ib_data_add_list(tx->dpi, field_name, NULL); } IB_FTRACE_RET_STATUS(IB_OK); }
/** * Parse the user agent header, splitting into component fields. * * Attempt to tokenize the user agent string passed in, storing the * result in the DPI associated with the transaction. * * @param[in] ib IronBee object * @param[in,out] tx Transaction object * @param[in] bs Byte string containing the agent string * * @returns Status code */ static ib_status_t modua_agent_fields(ib_engine_t *ib, ib_tx_t *tx, const ib_bytestr_t *bs) { const modua_match_rule_t *rule = NULL; ib_field_t *agent_list = NULL; char *product = NULL; char *platform = NULL; char *extra = NULL; char *agent; char *buf; size_t len; ib_status_t rc; /* Get the length of the byte string */ len = ib_bytestr_length(bs); /* Allocate memory for a copy of the string to split up below. */ buf = (char *)ib_mpool_calloc(tx->mp, 1, len+1); if (buf == NULL) { ib_log_error_tx(tx, "Failed to allocate %zd bytes for agent string", len+1); return IB_EALLOC; } /* Copy the string out */ memcpy(buf, ib_bytestr_const_ptr(bs), len); buf[len] = '\0'; ib_log_debug_tx(tx, "Found user agent: '%s'", buf); /* Copy the agent string */ agent = (char *)ib_mpool_strdup(tx->mp, buf); if (agent == NULL) { ib_log_error_tx(tx, "Failed to allocate copy of agent string"); return IB_EALLOC; } /* Parse the user agent string */ rc = modua_parse_uastring(buf, &product, &platform, &extra); if (rc != IB_OK) { ib_log_debug_tx(tx, "Failed to parse User Agent string '%s'", agent); return IB_OK; } /* Categorize the parsed string */ rule = modua_match_cat_rules(product, platform, extra); if (rule == NULL) { ib_log_debug_tx(tx, "No rule matched" ); } else { ib_log_debug_tx(tx, "Matched to rule #%d / category '%s'", rule->rule_num, rule->category ); } /* Build a new list. */ rc = ib_data_add_list(tx->data, "UA", &agent_list); if (rc != IB_OK) { ib_log_alert_tx(tx, "Unable to add UserAgent list to DPI."); return rc; } /* Store Agent */ rc = modua_store_field(ib, tx->mp, agent_list, "agent", agent); if (rc != IB_OK) { return rc; } /* Store product */ rc = modua_store_field(ib, tx->mp, agent_list, "PRODUCT", product); if (rc != IB_OK) { return rc; } /* Store Platform */ rc = modua_store_field(ib, tx->mp, agent_list, "OS", platform); if (rc != IB_OK) { return rc; } /* Store Extra */ rc = modua_store_field(ib, tx->mp, agent_list, "extra", extra); if (rc != IB_OK) { return rc; } /* Store Extra */ if (rule != NULL) { rc = modua_store_field(ib, tx->mp, agent_list, "category", rule->category); } else { rc = modua_store_field(ib, tx->mp, agent_list, "category", NULL ); } if (rc != IB_OK) { return rc; } /* Done */ return IB_OK; }
/** * Create an alias list collection. * * @param ib Engine. * @param tx Transaction. * @param name Collection name * @param header Header list to alias * * @returns Status code */ static ib_status_t create_header_alias_list( ib_engine_t *ib, ib_tx_t *tx, const char *name, ib_parsed_header_wrapper_t *header) { ib_field_t *f; ib_list_t *header_list; ib_status_t rc; ib_parsed_name_value_pair_list_t *nvpair; assert(ib != NULL); assert(tx != NULL); assert(name != NULL); assert(header != NULL); /* Create the list */ rc = ib_data_get(tx->data, name, &f); if (rc == IB_ENOENT) { rc = ib_data_add_list(tx->data, name, &f); if (rc != IB_OK) { return rc; } } else if (rc != IB_OK) { return rc; } rc = ib_field_mutable_value(f, ib_ftype_list_mutable_out(&header_list)); if (rc != IB_OK) { return rc; } /* Loop through the list & alias everything */ for(nvpair = header->head; nvpair != NULL; nvpair = nvpair->next) { assert(nvpair); assert(nvpair->value); ib_bytestr_t *bs = NULL; if (ib_bytestr_ptr(nvpair->value) != NULL) { rc = ib_bytestr_alias_mem( &bs, tx->mp, ib_bytestr_ptr(nvpair->value), ib_bytestr_length(nvpair->value) ); } else { rc = ib_bytestr_dup_mem(&bs, tx->mp, (const uint8_t *)"", 0); } if (rc != IB_OK) { ib_log_error_tx( tx, "Error creating bytestring of '%.*s' for %s: %s", (int)ib_bytestr_length(nvpair->name), (const char *)ib_bytestr_ptr(nvpair->name), name, ib_status_to_string(rc) ); return rc; } /* Create a byte string field */ rc = ib_field_create( &f, tx->mp, (const char *)ib_bytestr_const_ptr(nvpair->name), ib_bytestr_length(nvpair->name), IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bs) ); if (rc != IB_OK) { ib_log_error_tx(tx, "Error creating field of '%.*s' for %s: %s", (int)ib_bytestr_length(nvpair->name), (const char *)ib_bytestr_ptr(nvpair->name), name, ib_status_to_string(rc)); return rc; } /* Add the field to the list */ rc = ib_list_push(header_list, f); if (rc != IB_OK) { ib_log_error_tx(tx, "Error adding alias of '%.*s' to %s list: %s", (int)ib_bytestr_length(nvpair->name), (const char *)ib_bytestr_ptr(nvpair->name), name, ib_status_to_string(rc)); return rc; } } return IB_OK; }
// FIXME: This needs to go away and be replaced with dynamic fields static ib_status_t core_gen_placeholder_fields(ib_engine_t *ib, ib_tx_t *tx, ib_state_event_type_t event, void *cbdata) { assert(ib != NULL); assert(tx != NULL); assert(tx->data != NULL); assert(event == tx_started_event); ib_status_t rc; ib_field_t *tmp; /* Core Request Fields */ rc = core_field_placeholder_bytestr(tx->data, "request_line"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_method"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_protocol"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_raw"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_scheme"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_username"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_password"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_host"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_host"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_port"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_path"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_path_raw"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_query"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_uri_fragment"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_content_type"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "request_filename"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "auth_type"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "auth_username"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "auth_password"); if (rc != IB_OK) { return rc; } /* Core Request Collections */ rc = ib_data_add_list(tx->data, "request_headers", NULL); if (rc != IB_OK) { return rc; } rc = ib_data_add_list(tx->data, "request_cookies", NULL); if (rc != IB_OK) { return rc; } rc = ib_data_add_list(tx->data, "request_uri_params", NULL); if (rc != IB_OK) { return rc; } rc = ib_data_add_list(tx->data, "request_body_params", NULL); if (rc != IB_OK) { return rc; } /* ARGS collection */ rc = ib_data_get(tx->data, "ARGS", &tmp); if (rc == IB_ENOENT) { rc = ib_data_add_list(tx->data, "ARGS", NULL); if (rc != IB_OK) { return rc; } } else if (rc != IB_OK) { return rc; } /* Flags collection */ rc = ib_data_get(tx->data, "FLAGS", &tmp); if (rc == IB_ENOENT) { rc = ib_data_add_list(tx->data, "FLAGS", NULL); if (rc != IB_OK) { return rc; } } else if (rc != IB_OK) { return rc; } /* Initialize CAPTURE */ { ib_field_t *capture; rc = ib_capture_acquire(tx, NULL, &capture); if (rc != IB_OK) { return rc; } assert(capture != NULL); rc = ib_capture_clear(capture); if (rc != IB_OK) { return rc; } } /* Core Response Fields */ rc = core_field_placeholder_bytestr(tx->data, "response_line"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "response_protocol"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "response_status"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "response_message"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "response_content_type"); if (rc != IB_OK) { return rc; } /* Core Response Collections */ rc = ib_data_add_list(tx->data, "response_headers", NULL); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "FIELD_NAME"); if (rc != IB_OK) { return rc; } rc = core_field_placeholder_bytestr(tx->data, "FIELD_NAME_FULL"); if (rc != IB_OK) { return rc; } rc = ib_data_add_list(tx->data, "response_cookies", NULL); return rc; }
static ib_status_t geoip_lookup( ib_engine_t *ib, ib_tx_t *tx, ib_state_event_type_t event, void *data ) { const char *ip = tx->er_ipstr; if (ip == NULL) { ib_log_alert_tx(tx, "Trying to lookup NULL IP in GEOIP"); return IB_EINVAL; } #ifdef GEOIP_HAVE_VERSION /** * Some configurations exist as single characters and must be converted to * a string. This is simply a place to assemble that string before * it is passed into ip_data_add_nulstr. * This is only needed if we have support confidence items. WAM */ char one_char_str[2] = { '\0', '\0' }; #endif /* GEOIP_HAVE_VERSION */ ib_status_t rc; /* Declare and initialize the GeoIP property list. * Regardless of if we find a record or not, we want to create the list * artifact so that later modules know we ran and did [not] find a * record. */ ib_field_t *geoip_lst = NULL; ib_field_t *tmp_field = NULL; /* Id of geo ip record to read. */ int geoip_id; ib_log_debug_tx(tx, "GeoIP Lookup '%s'", ip); /* Build a new list. */ rc = ib_data_add_list(tx->data, "GEOIP", &geoip_lst); /* NOTICE: Called before GeoIP_record_by_addr allocates a * GeoIPRecord. */ if (rc != IB_OK) { ib_log_alert_tx(tx, "Unable to add GEOIP list to DPI."); return IB_EINVAL; } if (geoip_db == NULL) { ib_log_alert_tx(tx, "GeoIP database was never opened. Perhaps the " "configuration file needs a GeoIPDatabaseFile " "\"/usr/share/geoip/GeoLite.dat\" line?"); return IB_EINVAL; } geoip_id = GeoIP_id_by_addr(geoip_db, ip); if (geoip_id > 0) { const char *tmp_str; ib_log_debug_tx(tx, "GeoIP record found."); /* Add integers. */ tmp_field = NULL; tmp_str = GeoIP_code_by_id(geoip_id); if (tmp_str) { ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("country_code"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in(tmp_str)); ib_field_list_add(geoip_lst, tmp_field); } tmp_str = GeoIP_code3_by_id(geoip_id); if (tmp_str) { ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("country_code3"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in(tmp_str)); ib_field_list_add(geoip_lst, tmp_field); } tmp_str = GeoIP_country_name_by_id(geoip_db, geoip_id); if (tmp_str) { ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("country_name"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in(tmp_str)); ib_field_list_add(geoip_lst, tmp_field); } tmp_str = GeoIP_continent_by_id(geoip_id); if (tmp_str) { ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("continent_code"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in(tmp_str)); ib_field_list_add(geoip_lst, tmp_field); } } else { ib_log_debug_tx(tx, "No GeoIP record found."); ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("country_code"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in("O1")); ib_field_list_add(geoip_lst, tmp_field); ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("country_code3"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in("O01")); ib_field_list_add(geoip_lst, tmp_field); ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("country_name"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in("Other Country")); ib_field_list_add(geoip_lst, tmp_field); ib_field_create(&tmp_field, tx->mp, IB_FIELD_NAME("continent_code"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in("O1")); ib_field_list_add(geoip_lst, tmp_field); } return IB_OK; }