/** * Store a field in the agent list * * Creates a new field and adds it to the agent list field list. * * @param[in] ib IronBee object * @param[in,out] mp Memory pool to allocate from * @param[in] agent_list Field to add the field to * @param[in] name Field name * @param[in] value Field value * * @returns Status code */ static ib_status_t modua_store_field(ib_engine_t *ib, ib_mpool_t *mp, ib_field_t *agent_list, const char *name, const char *value) { IB_FTRACE_INIT(); ib_field_t *tmp_field = NULL; ib_status_t rc = IB_OK; /* No value? Do nothing */ if (value == NULL) { ib_log_debug3(ib, "No %s field in user agent", name); IB_FTRACE_RET_STATUS(IB_OK); } /* Create the field */ rc = ib_field_create( &tmp_field, mp, IB_FIELD_NAME(name), IB_FTYPE_NULSTR, ib_ftype_nulstr_in(value) ); if (rc != IB_OK) { ib_log_alert(ib, "Error creating user agent %s field: %s", name, ib_status_to_string(rc)); IB_FTRACE_RET_STATUS(rc); } /* Add the field to the list */ rc = ib_field_list_add(agent_list, tmp_field); if (rc != IB_OK) { ib_log_alert(ib, "Error adding user agent %s field: %s", name, ib_status_to_string(rc)); IB_FTRACE_RET_STATUS(rc); } ib_log_debug3(ib, "Stored user agent %s '%s'", name, value); IB_FTRACE_RET_STATUS(IB_OK); }
/** * Lookup the IP address in the GeoIP database * * @param[in] ib IronBee engine * @param[in] tx Transaction * @param[in] event Event * @param[in] data callback data (Module configuration) */ static ib_status_t geoip_lookup( ib_engine_t *ib, ib_tx_t *tx, ib_state_event_type_t event, void *data ) { assert(ib != NULL); assert(event == handle_context_tx_event); assert(data != NULL); const char *ip = tx->er_ipstr; const module_data_t *mod_data = (const module_data_t *)data; 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_var_source_initialize( mod_data->geoip_source, &geoip_lst, tx->var_store, IB_FTYPE_LIST ); /* NOTICE: Called before GeoIP_record_by_addr allocates a * GeoIPRecord. */ if (rc != IB_OK) { ib_log_alert_tx(tx, "Unable to add GEOIP var."); return IB_EINVAL; } if (mod_data->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(mod_data->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(mod_data->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; }
/** * Length transformation * * @param[in] ib IronBee engine * @param[in] mp Memory pool to use for allocations. * @param[in] fndata Function specific data. * @param[in] fin Input field. * @param[out] fout Output field. * @param[out] pflags Transformation flags. * * @returns IB_OK if successful. */ static ib_status_t tfn_length(ib_engine_t *ib, ib_mpool_t *mp, void *fndata, const ib_field_t *fin, ib_field_t **fout, ib_flags_t *pflags) { ib_status_t rc = IB_OK; assert(mp != NULL); assert(fin != NULL); assert(fout != NULL); assert(pflags != NULL); /** * This works on C-style (NUL terminated) and byte strings. Note * that data is assumed to be a NUL terminated string (because our * configuration parser can't produce anything else). **/ if (fin->type == IB_FTYPE_NULSTR) { const char *fval; rc = ib_field_value(fin, ib_ftype_nulstr_out(&fval)); if (rc != IB_OK) { return rc; } const ib_num_t len = strlen(fval); rc = ib_field_create( fout, mp, IB_FIELD_NAME("Length"), IB_FTYPE_NUM, ib_ftype_num_in(&len) ); } else if (fin->type == IB_FTYPE_BYTESTR) { const ib_bytestr_t *value; rc = ib_field_value(fin, ib_ftype_bytestr_out(&value)); if (rc != IB_OK) { return rc; } const ib_num_t len = ib_bytestr_length(value); rc = ib_field_create( fout, mp, IB_FIELD_NAME("Length"), IB_FTYPE_NUM, ib_ftype_num_in(&len) ); } else if (fin->type == IB_FTYPE_LIST) { const ib_list_node_t *node = NULL; const ib_list_t *ilist; /** Incoming list */ /* Get the incoming list */ // @todo Remove mutable once list is const correct. rc = ib_field_value(fin, ib_ftype_list_out(&ilist)); if (rc != IB_OK) { return rc; } if (ilist == NULL) { return IB_EUNKNOWN; } /* Create the outgoing list field */ rc = ib_field_create( fout, mp, IB_FIELD_NAME("Length"), IB_FTYPE_LIST, NULL ); if (rc != IB_OK) { return rc; } /* Walk through the incoming fields */ IB_LIST_LOOP_CONST(ilist, node) { const ib_field_t *ifield = (ib_field_t *)node->data; ib_field_t *ofield = NULL; ib_flags_t flags = 0; rc = tfn_length(ib, mp, NULL, ifield, &ofield, &flags); if (rc != IB_OK) { return rc; } rc = ib_field_list_add(*fout, ofield); if (rc != IB_OK) { return rc; } } } else {
/* * Callback used to generate request header fields. */ static ib_status_t core_gen_request_header_fields(ib_engine_t *ib, ib_tx_t *tx, ib_state_event_type_t event, void *cbdata) { ib_field_t *f; ib_status_t rc; assert(ib != NULL); assert(tx != NULL); assert(event == request_header_finished_event); /** * Alias connection remote and server addresses */ rc = ib_data_get(tx->conn->data, "server_addr", &f); if (rc != IB_OK) { return rc; } rc = ib_data_add(tx->data, f); if (rc != IB_OK) { return rc; } rc = ib_data_get(tx->conn->data, "server_port", &f); if (rc != IB_OK) { return rc; } rc = ib_data_add(tx->data, f); if (rc != IB_OK) { return rc; } rc = ib_data_get(tx->conn->data, "remote_addr", &f); if (rc != IB_OK) { return rc; } rc = ib_data_add(tx->data, f); if (rc != IB_OK) { return rc; } rc = ib_data_get(tx->conn->data, "remote_port", &f); if (rc != IB_OK) { return rc; } rc = ib_data_add(tx->data, f); if (rc != IB_OK) { return rc; } core_gen_tx_numeric_field(tx, "conn_tx_count", tx->conn->tx_count); if (tx->request_line != NULL) { core_gen_tx_bytestr_alias_field(tx, "request_line", tx->request_line->raw); core_gen_tx_bytestr_alias_field(tx, "request_method", tx->request_line->method); core_gen_tx_bytestr_alias_field(tx, "request_uri_raw", tx->request_line->uri); core_gen_tx_bytestr_alias_field(tx, "request_protocol", tx->request_line->protocol); } /* Populate the ARGS collection. */ rc = ib_data_get(tx->data, "ARGS", &f); if (rc == IB_OK) { ib_field_t *param_list; /* Add request URI parameters to ARGS collection. */ rc = ib_data_get(tx->data, "request_uri_params", ¶m_list); if (rc == IB_OK) { ib_list_t *field_list; ib_list_node_t *node = NULL; rc = ib_field_mutable_value( param_list, ib_ftype_list_mutable_out(&field_list) ); if (rc != IB_OK) { return rc; } IB_LIST_LOOP(field_list, node) { ib_field_t *param = (ib_field_t *)ib_list_node_data(node); /* Add the field to the ARGS collection. */ rc = ib_field_list_add(f, param); if (rc != IB_OK) { ib_log_notice_tx(tx, "Failed to add parameter to " "ARGS collection: %s", ib_status_to_string(rc)); } }
static ib_status_t sqli_op_execute( ib_tx_t *tx, const ib_field_t *field, ib_field_t *capture, ib_num_t *result, void *instance_data, void *cbdata ) { assert(tx != NULL); assert(field != NULL); assert(result != NULL); const sqli_fingerprint_set_t *ps = (const sqli_fingerprint_set_t *)instance_data; sfilter sf; ib_bytestr_t *bs; ib_status_t rc; sqli_callback_data_t callback_data; *result = 0; /* Currently only bytestring types are supported. * Other types will just get passed through. */ if (field->type != IB_FTYPE_BYTESTR) { return IB_OK; } rc = ib_field_value(field, ib_ftype_bytestr_mutable_out(&bs)); if (rc != IB_OK) { return rc; } /* Run through libinjection. */ libinjection_sqli_init( &sf, (const char *)ib_bytestr_const_ptr(bs), ib_bytestr_length(bs), FLAG_NONE ); callback_data.confidence = 0; callback_data.fingerprint_set = NULL; if (ps != NULL) { callback_data.fingerprint_set = ps; libinjection_sqli_callback(&sf, sqli_lookup_word, (void *)&callback_data); } if (libinjection_is_sqli(&sf)) { ib_log_debug_tx(tx, "Matched SQLi fingerprint: %s", sf.fingerprint); *result = 1; } if (*result == 1 && capture != NULL) { { ib_field_t *fingerprint_field; size_t fingerprint_length = strlen(sf.fingerprint); const uint8_t *fingerprint; fingerprint = ib_mm_memdup( tx->mm, sf.fingerprint, fingerprint_length ); if (fingerprint == NULL) { return IB_EALLOC; } rc = ib_field_create_bytestr_alias( &fingerprint_field, tx->mm, IB_S2SL("fingerprint"), fingerprint, fingerprint_length ); if (rc != IB_OK) { return rc; } rc = ib_field_list_add(capture, fingerprint_field); if (rc != IB_OK) { return rc; } } { ib_field_t *confidence_field; rc = ib_field_create( &confidence_field, tx->mm, IB_S2SL("confidence"), IB_FTYPE_NUM, ib_ftype_num_in(&callback_data.confidence) ); if (rc != IB_OK) { return rc; } rc = ib_field_list_add(capture, confidence_field); if (rc != IB_OK) { return rc; } } } return IB_OK; }
/* * Callback used to generate request header fields. */ static ib_status_t core_gen_request_header_fields(ib_engine_t *ib, ib_tx_t *tx, ib_state_event_type_t event, void *cbdata) { ib_field_t *f; ib_status_t rc; ib_conn_t *conn = tx->conn; assert(ib != NULL); assert(tx != NULL); assert(event == handle_request_header_event); core_gen_tx_bytestr_alias2(tx, "server_addr", conn->local_ipstr, strlen(conn->local_ipstr)); core_gen_tx_numeric(tx, "server_port", conn->local_port); core_gen_tx_bytestr_alias2(tx, "remote_addr", conn->remote_ipstr, strlen(conn->remote_ipstr)); core_gen_tx_numeric(tx, "remote_port", conn->remote_port); core_gen_tx_numeric(tx, "conn_tx_count", tx->conn->tx_count); if (tx->request_line != NULL) { core_gen_tx_bytestr_alias(tx, "request_line", tx->request_line->raw); core_gen_tx_bytestr_alias(tx, "request_method", tx->request_line->method); core_gen_tx_bytestr_alias(tx, "request_uri_raw", tx->request_line->uri); core_gen_tx_bytestr_alias(tx, "request_protocol", tx->request_line->protocol); } /* Populate the ARGS collection. */ rc = core_slow_get(&f, tx, "ARGS"); if (rc == IB_OK) { ib_field_t *param_list; rc = core_slow_get(¶m_list, tx, "request_uri_params"); if (rc == IB_OK) { ib_list_t *field_list; ib_list_node_t *node = NULL; rc = ib_field_mutable_value( param_list, ib_ftype_list_mutable_out(&field_list) ); if (rc != IB_OK) { return rc; } IB_LIST_LOOP(field_list, node) { ib_field_t *param = (ib_field_t *)ib_list_node_data(node); /* Add the field to the ARGS collection. */ rc = ib_field_list_add(f, param); if (rc != IB_OK) { ib_log_notice_tx(tx, "Failed to add parameter to " "ARGS collection: %s", ib_status_to_string(rc)); } }