/** * Eudoxus first match callback function. Called when a match occurs. * * Always returns IA_EUDOXUS_CMD_STOP to stop matching (unless an * error occurs). If capture is enabled the matched text will be stored in the * capture variable. * * @param[in] engine Eudoxus engine. * @param[in] output Output defined by automata. * @param[in] output_length Length of output. * @param[in] input Current location in the input (first character * after the match). * @param[in,out] cbdata Pointer to the ee_callback_data_t instance we are * handling. This is needed for handling capture * of the match. * @return IA_EUDOXUS_CMD_ERROR on error, IA_EUDOXUS_CMD_STOP otherwise. */ static ia_eudoxus_command_t ee_first_match_callback(ia_eudoxus_t* engine, const char *output, size_t output_length, const uint8_t *input, void *cbdata) { assert(cbdata != NULL); assert(output != NULL); ib_status_t rc; uint32_t match_len; const ee_callback_data_t *ee_cbdata = cbdata; ib_tx_t *tx = ee_cbdata->tx; ib_field_t *capture = ee_cbdata->capture; ib_bytestr_t *bs; ib_field_t *field; const char *name; assert(tx != NULL); if (capture != NULL) { if (output_length != sizeof(uint32_t)) { return IA_EUDOXUS_CMD_ERROR; } match_len = *(uint32_t *)(output); rc = ib_capture_clear(capture); if (rc != IB_OK) { ib_log_error_tx(tx, "Error clearing captures: %s", ib_status_to_string(rc)); return IA_EUDOXUS_CMD_ERROR; } /* Create a byte-string representation */ rc = ib_bytestr_dup_mem(&bs, tx->mp, (input - match_len), match_len); if (rc != IB_OK) { return IA_EUDOXUS_CMD_ERROR; } name = ib_capture_name(0); rc = ib_field_create(&field, tx->mp, name, strlen(name), IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bs)); if (rc != IB_OK) { return IA_EUDOXUS_CMD_ERROR; } rc = ib_capture_set_item(capture, 0, tx->mp, field); if (rc != IB_OK) { return IA_EUDOXUS_CMD_ERROR; } } return IA_EUDOXUS_CMD_STOP; }
/** * Set the matches into the given field name as .0, .1, .2 ... .9. * * @param[in] tx Current transaction. * @param[in] capture Collection to capture to. * @param[in] ovector The vector of integer pairs of matches from PCRE. * @param[in] matches The number of matches. * @param[in] subject The matched-against string data. * * @returns IB_OK or IB_EALLOC. */ static ib_status_t pcre_set_matches( const ib_tx_t *tx, ib_field_t *capture, int *ovector, int matches, const char *subject ) { assert(tx != NULL); assert(tx->ib != NULL); assert(capture != NULL); assert(ovector != NULL); ib_status_t rc; int i; rc = ib_capture_clear(capture); if (rc != IB_OK) { ib_log_error_tx(tx, "Error clearing captures: %s", ib_status_to_string(rc)); } /* We have a match! Now populate TX:0-9 in tx->data. */ ib_log_debug2_tx(tx, "REGEX populating %d matches", matches); for (i = 0; i < matches; ++i) { /* The length of the match. */ size_t match_len; /* The first character in the match. */ const char *match_start; /* Field name */ const char *name; /* Holder for a copy of the field value when creating a new field. */ ib_bytestr_t *bs; /* Field holder. */ ib_field_t *field; /* Readability. Mark the start and length of the string. */ match_start = subject+ovector[i*2]; match_len = ovector[i*2+1] - ovector[i*2]; /* Create a byte-string representation */ rc = ib_bytestr_dup_mem(&bs, tx->mp, (const uint8_t*)match_start, match_len); if (rc != IB_OK) { return rc; } /* Create a field to hold the byte-string */ name = ib_capture_name(i); rc = ib_field_create(&field, tx->mp, name, strlen(name), IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bs)); if (rc != IB_OK) { return rc; } /* Add it to the capture collection */ rc = ib_capture_set_item(capture, i, tx->mp, field); if (rc != IB_OK) { return rc; } } return IB_OK; }
/** * @brief Execute the dfa operator * * @param[in] tx Current transaction. * @param[in] instance_data Instance data needed for execution. * @param[in] field The field to operate on. * @param[in] capture If non-NULL, the collection to capture to. * @param[out] result The result of the operator 1=true 0=false. * @param[in] cbdata Callback data. * * @returns IB_OK most times. IB_EALLOC when a memory allocation error handles. */ static ib_status_t dfa_operator_execute( ib_tx_t *tx, void *instance_data, const ib_field_t *field, ib_field_t *capture, ib_num_t *result, void *cbdata ) { assert(instance_data != NULL); assert(tx != NULL); int matches; ib_status_t ib_rc; const int ovecsize = 3 * MATCH_MAX; modpcre_operator_data_t *operator_data = (modpcre_operator_data_t *)instance_data; int *ovector; const char *subject; size_t subject_len; const ib_bytestr_t *bytestr; dfa_workspace_t *dfa_workspace; const char *id = operator_data->id; int options; /* dfa exec options. */ int start_offset; int match_count; const ib_module_t *m = (const ib_module_t *)cbdata; assert(m != NULL); assert(operator_data->cpdata->is_dfa == true); ovector = (int *)malloc(ovecsize*sizeof(*ovector)); if (ovector==NULL) { return IB_EALLOC; } if (field->type == IB_FTYPE_NULSTR) { ib_rc = ib_field_value(field, ib_ftype_nulstr_out(&subject)); if (ib_rc != IB_OK) { free(ovector); return ib_rc; } subject_len = strlen(subject); } else if (field->type == IB_FTYPE_BYTESTR) { ib_rc = ib_field_value(field, ib_ftype_bytestr_out(&bytestr)); if (ib_rc != IB_OK) { free(ovector); return ib_rc; } subject_len = ib_bytestr_length(bytestr); subject = (const char *) ib_bytestr_const_ptr(bytestr); } else { free(ovector); return IB_EINVAL; } /* Get the per-tx workspace data for this rule data id. */ ib_rc = get_dfa_tx_data(m, tx, id, &dfa_workspace); if (ib_rc == IB_ENOENT) { /* First time we are called, clear the captures. */ if (capture) { ib_rc = ib_capture_clear(capture); if (ib_rc != IB_OK) { ib_log_error_tx(tx, "Error clearing captures: %s", ib_status_to_string(ib_rc)); } } options = PCRE_PARTIAL_SOFT; ib_rc = alloc_dfa_tx_data(m, tx, operator_data->cpdata, id, &dfa_workspace); if (ib_rc != IB_OK) { free(ovector); return ib_rc; } } else if (ib_rc == IB_OK) { options = PCRE_PARTIAL_SOFT | PCRE_DFA_RESTART; } else { free(ovector); return ib_rc; } /* Perform the match. * If capturing is specified, then find all matches. */ start_offset = 0; match_count = 0; do { matches = pcre_dfa_exec(operator_data->cpdata->cpatt, operator_data->cpdata->edata, subject, subject_len, start_offset, /* Starting offset. */ options, ovector, ovecsize, dfa_workspace->workspace, dfa_workspace->wscount); if (matches > 0) { ++match_count; /* Use the longest match - the first in ovector - * to set the offset in the subject for the next * match. */ start_offset = ovector[1] + 1; if (capture) { pcre_dfa_set_match(tx, capture, ovector, 1, subject); } } } while (capture && (matches > 0)); if (match_count > 0) { ib_rc = IB_OK; *result = 1; } else if ((matches == 0) || (matches == PCRE_ERROR_NOMATCH)) { ib_rc = IB_OK; *result = 0; } else if (matches == PCRE_ERROR_PARTIAL) { ib_rc = IB_OK; *result = 0; } else { /* Some other error occurred. Set the status to false and * return the error. */ ib_rc = IB_EUNKNOWN; *result = 0; } free(ovector); return ib_rc; }
// 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; }