ib_status_t ib_parsed_headers_add( ib_parsed_headers_t *headers, const char *name, size_t name_len, const char *value, size_t value_len ) { ib_status_t rc; assert(headers != NULL); assert(name != NULL); assert(value != NULL); ib_parsed_header_t *ele; ele = ib_mm_alloc(headers->mm, sizeof(*ele)); if (ele == NULL) { return IB_EALLOC; } rc = ib_bytestr_dup_mem( &ele->name, headers->mm, (const uint8_t *)name, name_len ); if (rc != IB_OK) { return rc; } rc = ib_bytestr_dup_mem( &ele->value, headers->mm, (const uint8_t *)value, value_len ); if (rc != IB_OK) { return rc; } ele->next = NULL; /* List is empty. Add first element. */ if (headers->head == NULL) { headers->head = ele; headers->tail = ele; headers->size = 1; } /* Normal append to a list with values in it already. */ else { headers->tail->next = ele; headers->tail = ele; ++(headers->size); } return IB_OK; }
ib_status_t ib_parsed_name_value_pair_list_add( ib_parsed_name_value_pair_list_wrapper_t *headers, const char *name, size_t name_len, const char *value, size_t value_len) { IB_FTRACE_INIT(); ib_status_t rc; assert(headers != NULL); assert(headers->mpool != NULL); assert(name != NULL); assert(value != NULL); ib_parsed_name_value_pair_list_t *ele; ele = ib_mpool_alloc(headers->mpool, sizeof(*ele)); if (ele == NULL) { IB_FTRACE_RET_STATUS(IB_EALLOC); } rc = ib_bytestr_dup_mem(&ele->name, headers->mpool, (const uint8_t *)name, name_len); if (rc != IB_OK) { IB_FTRACE_RET_STATUS(rc); } rc = ib_bytestr_dup_mem(&ele->value, headers->mpool, (const uint8_t *)value, value_len); if (rc != IB_OK) { IB_FTRACE_RET_STATUS(rc); } ele->next = NULL; /* List is empty. Add first element. */ if (headers->head == NULL) { headers->head = ele; headers->tail = ele; headers->size = 1; } /* Normal append to a list with values in it already. */ else { headers->tail->next = ele; headers->tail = ele; ++(headers->size); } IB_FTRACE_RET_STATUS(IB_OK); }
/// @test Test util field library - ib_field_create() ib_field_create() TEST_F(TestIBUtilField, test_field_create) { ib_field_t *f; ib_status_t rc; const char *nulstrval = "TestValue"; ib_num_t numval = 5; ib_bytestr_t *bytestrval; const char *nulout; const char *nulcopy; nulcopy = ib_mm_strdup(MM(), nulstrval); ASSERT_STRNE(NULL, nulcopy); rc = ib_field_create(&f, MM(), IB_S2SL("test_nulstr"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in(nulcopy)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); ASSERT_EQ(11UL, f->nlen); ASSERT_EQ(0, memcmp("test_nulstr", f->name, 11)); rc = ib_field_value(f, ib_ftype_nulstr_out(&nulout)); ASSERT_EQ(IB_OK, rc); ASSERT_STREQ(nulstrval, nulout); rc = ib_field_create(&f, MM(), IB_S2SL("test_num"), IB_FTYPE_NUM, ib_ftype_num_in(&numval)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); ASSERT_EQ(8UL, f->nlen); ASSERT_EQ(0, memcmp("test_num", f->name, 8)); rc = ib_bytestr_dup_mem(&bytestrval, MM(), (uint8_t *)nulstrval, strlen(nulstrval)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); rc = ib_field_create(&f, MM(), IB_S2SL("test_bytestr"), IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bytestrval)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); ASSERT_EQ(12UL, f->nlen); ASSERT_EQ(0, memcmp("test_bytestr", f->name, 12)); rc = ib_field_create(&f, MM(), IB_S2SL("test_nulstr_ex"), IB_FTYPE_NULSTR, ib_ftype_nulstr_in(nulstrval)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); rc = ib_field_create(&f, MM(), IB_S2SL("test_num_ex"), IB_FTYPE_NUM, ib_ftype_num_in(&numval)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); rc = ib_field_create(&f, MM(), IB_S2SL("test_bytestr_ex"), IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bytestrval)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); }
/** * Set the matches from a multi-match dfa as a list in the CAPTURE * collection (all with "0" key). * * @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_dfa_set_match( 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); int i; /* We have a match! Now populate TX:0-9 in tx->data. */ ib_log_debug2_tx(tx, "DFA populating %d matches", matches); for (i = 0; i < matches; ++i) { size_t match_len; const char *match_start; const char *name; ib_bytestr_t *bs; ib_field_t *field; ib_status_t rc; /* 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(0); 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_add_item(capture, field); if (rc != IB_OK) { return rc; } } return IB_OK; }
/** * 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; }
ib_status_t ib_bytestr_dup_nulstr( ib_bytestr_t **pdst, ib_mm_t mm, const char *data ) { assert(pdst != NULL); assert(data != NULL); ib_status_t rc = ib_bytestr_dup_mem( pdst, mm, (uint8_t *)data, strlen(data) ); return rc; }
ib_status_t ib_bytestr_dup( ib_bytestr_t **pdst, ib_mm_t mm, const ib_bytestr_t *src ) { assert(pdst != NULL); ib_status_t rc; rc = ib_bytestr_dup_mem( pdst, mm, ib_bytestr_const_ptr(src), ib_bytestr_length(src) ); return rc; }
ib_status_t ib_bytestr_dup_nulstr( ib_bytestr_t **pdst, ib_mpool_t *pool, const char *data ) { IB_FTRACE_INIT(); assert(pdst != NULL); assert(pool != NULL); assert(data != NULL); ib_status_t rc = ib_bytestr_dup_mem( pdst, pool, (uint8_t *)data, strlen(data) ); IB_FTRACE_RET_STATUS(rc); }
ib_status_t ib_bytestr_dup( ib_bytestr_t **pdst, ib_mpool_t *pool, const ib_bytestr_t *src ) { IB_FTRACE_INIT(); assert(pdst != NULL); assert(pool != NULL); ib_status_t rc; rc = ib_bytestr_dup_mem( pdst, pool, ib_bytestr_const_ptr(src), ib_bytestr_length(src) ); IB_FTRACE_RET_STATUS(rc); }
/** * Set the matches into the given field name as .0, .1, .2 ... .9. * * @param[in] ib The IronBee engine to log to. * @param[in] tx The transaction to store the values into (tx->dpi). * @param[in] field_name The field to populate with Regex matches. * @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(ib_engine_t *ib, ib_tx_t *tx, const char* field_name, int *ovector, int matches, const char *subject) { IB_FTRACE_INIT(); /* IronBee status. */ ib_status_t rc; /* Iterator. */ int i; /* Length of field_name. */ const int field_name_sz = strlen(field_name); /* The length of the match. */ size_t match_len; /* The first character in the match. */ const char* match_start; /* +3 = '.', [digit], and \0. */ char *full_field_name = malloc(field_name_sz+3); /* Holder to build an optional debug message in. */ char *debug_msg; /* Holder for a copy of the field value when creating a new field. */ ib_bytestr_t *field_value; /* Field holder. */ ib_field_t *ib_field; /* Ensure the above allocations happened. */ if (full_field_name==NULL) { IB_FTRACE_RET_STATUS(IB_EALLOC); } rc = ensure_field_exists(ib, tx, field_name); if (rc != IB_OK) { ib_log_alert_tx(tx, "Could not ensure that field %s was a list.", field_name); free(full_field_name); IB_FTRACE_RET_STATUS(IB_EINVAL); } /* We have a match! Now populate TX.0-9 in tx->dpi. */ for (i=0; i<matches; i++) { /* Build the field name. Typically TX.0, TX.1 ... TX.9 */ sprintf(full_field_name, "%s.%d", field_name, i); /* Readability. Mark the start and length of the string. */ match_start = subject+ovector[i*2]; match_len = ovector[i*2+1] - ovector[i*2]; /* If debugging this, copy the string value out and print it to the * log. This could be dangerous as there could be non-character * values in the match. */ if (ib_log_get_level(ib) >= 7) { debug_msg = malloc(match_len+1); /* Notice: Don't provoke a crash if malloc fails. */ if (debug_msg != NULL) { memcpy(debug_msg, match_start, match_len); debug_msg[match_len] = '\0'; ib_log_debug2_tx(tx, "REGEX Setting %s=%s", full_field_name, debug_msg); free(debug_msg); } } ib_data_get(tx->dpi, full_field_name, &ib_field); if (ib_field == NULL) { ib_data_add_bytestr(tx->dpi, full_field_name, (uint8_t*)subject+ovector[i*2], match_len, NULL); } else { ib_bytestr_dup_mem(&field_value, tx->mp, (const uint8_t*)match_start, match_len); ib_field_setv_no_copy( ib_field, ib_ftype_bytestr_mutable_in(field_value) ); } } IB_FTRACE_RET_STATUS(IB_OK); }
ib_status_t ib_parsed_req_line_create( ib_parsed_req_line_t **line, ib_mm_t mm, const char *raw, size_t raw_len, const char *method, size_t method_len, const char *uri, size_t uri_len, const char *protocol, size_t protocol_len ) { ib_status_t rc = IB_OK; ib_parsed_req_line_t *line_tmp = ib_mm_alloc(mm, sizeof(*line_tmp)); if (line_tmp == NULL) { return IB_EALLOC; } /* Record the components if available. If the components are * not available, but the raw line is, then it will be possible * to parse the components out later on. Otherwise, if there * is no component and no raw line, then set default values. */ if (method != NULL) { rc = ib_bytestr_dup_mem( &line_tmp->method, mm, (const uint8_t *)method, method_len ); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem( &line_tmp->method, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } if (uri != NULL) { rc = ib_bytestr_dup_mem( &line_tmp->uri, mm, (const uint8_t *)uri, uri_len ); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem( &line_tmp->uri, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } if (protocol != NULL) { rc = ib_bytestr_dup_mem( &line_tmp->protocol, mm, (const uint8_t *)protocol, protocol_len ); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem( &line_tmp->protocol, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } /* If no raw line is available, then create one. */ if (raw == NULL) { if (method_len + uri_len + protocol_len == 0) { rc = ib_bytestr_dup_mem( &line_tmp->raw, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } else { size_t raw_line_len; assert(method != NULL); assert(uri != NULL); /* Create a correctly sized bytestr and manually copy * the data into it. */ raw_line_len = method_len + 1 + uri_len + (protocol == NULL ? 0 : 1 + protocol_len); rc = ib_bytestr_create(&line_tmp->raw, mm, raw_line_len); if (rc != IB_OK) { return rc; } ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)method, method_len ); ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)" ", 1 ); ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)uri, uri_len ); if (protocol != NULL) { ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)" ", 1 ); ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)protocol, protocol_len ); } } } else { rc = ib_bytestr_dup_mem( &line_tmp->raw, mm, (const uint8_t *)raw, raw_len ); if (rc != IB_OK) { return rc; } } /* Commit back successfully created line. */ *line = line_tmp; return IB_OK; }
/** * 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; }
/// @test Test util field library - ib_field_format() with bytestr TEST_F(TestIBUtilField, test_field_format_bytestr) { ib_field_t *f; ib_status_t rc; char fmtbuf[32]; const uint8_t in1[] = "a\0b"; const uint8_t in2[] = "\fabcd\0efghijk\t"; size_t size; ib_bytestr_t *bs; const char *tname; const char *buf; size = sizeof(in1) - 1; rc = ib_bytestr_dup_mem(&bs, MemPool(), in1, size); ASSERT_EQ(IB_OK, rc); rc = ib_field_create(&f, MemPool(), IB_FIELD_NAME("test_bytestr"), IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bs)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f != NULL); buf = ib_field_format(f, false, false, &tname, fmtbuf, sizeof(fmtbuf)); ASSERT_STREQ((const char *)in1, fmtbuf); ASSERT_STREQ("BYTESTR", tname); ASSERT_EQ(buf, fmtbuf); buf = ib_field_format(f, false, true, &tname, fmtbuf, sizeof(fmtbuf)); ASSERT_STREQ("a\\u0000b", fmtbuf); ASSERT_STREQ("BYTESTR", tname); ASSERT_EQ(buf, fmtbuf); buf = ib_field_format(f, true, true, &tname, fmtbuf, sizeof(fmtbuf)); ASSERT_STREQ("\"a\\u0000b\"", fmtbuf); ASSERT_STREQ("BYTESTR", tname); ASSERT_EQ(buf, fmtbuf); size = sizeof(in2) - 1; rc = ib_bytestr_dup_mem(&bs, MemPool(), in2, size); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f != NULL); rc = ib_field_create(&f, MemPool(), IB_FIELD_NAME("test_bytestr"), IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bs)); ASSERT_EQ(IB_OK, rc); ASSERT_TRUE(f); buf = ib_field_format(f, false, false, NULL, fmtbuf, sizeof(fmtbuf)); ASSERT_STREQ((const char *)in2, fmtbuf); ASSERT_EQ(buf, fmtbuf); buf = ib_field_format(f, true, false, NULL, fmtbuf, sizeof(fmtbuf)); ASSERT_STREQ("\"\fabcd\"", fmtbuf); ASSERT_EQ(buf, fmtbuf); buf = ib_field_format(f, false, true, NULL, fmtbuf, sizeof(fmtbuf)); ASSERT_STREQ("\\fabcd\\u0000efghijk\\t", fmtbuf); ASSERT_EQ(buf, fmtbuf); buf = ib_field_format(f, true, true, NULL, fmtbuf, sizeof(fmtbuf)); ASSERT_STREQ("\"\\fabcd\\u0000efghijk\\t\"", fmtbuf); ASSERT_EQ(buf, fmtbuf); }
static ib_status_t field_from_string_internal( ib_mpool_t *mp, const char *name, size_t nlen, const char *vstr, size_t vlen, bool vstr_is_nulstr, ib_field_t **pfield) { assert(mp != NULL); assert(name != NULL); assert(vstr != NULL); assert(pfield != NULL); ib_status_t conv; ib_status_t rc = IB_OK; ib_field_t *field; *pfield = NULL; /* Try to convert to an integer */ if (*pfield == NULL) { ib_num_t num_val; if (vstr_is_nulstr) { conv = ib_string_to_num(vstr, 0, &num_val); } else { conv = ib_string_to_num_ex(vstr, vlen, 0, &num_val); } if (conv == IB_OK) { rc = ib_field_create(&field, mp, name, nlen, IB_FTYPE_NUM, ib_ftype_num_in(&num_val)); *pfield = field; } } /* Try to convert to a float */ if (*pfield == NULL) { ib_float_t float_val; if (vstr_is_nulstr) { conv = ib_string_to_float(vstr, &float_val); } else { conv = ib_string_to_float_ex(vstr, vlen, &float_val); } if (conv == IB_OK) { rc = ib_field_create(&field, mp, name, nlen, IB_FTYPE_FLOAT, ib_ftype_float_in(&float_val)); *pfield = field; } } /* Finally, assume that it's a string */ if (*pfield == NULL) { if (vstr_is_nulstr) { rc = ib_field_create(&field, mp, name, nlen, IB_FTYPE_NULSTR, ib_ftype_nulstr_in(vstr)); } else { ib_bytestr_t *bs; rc = ib_bytestr_dup_mem(&bs, mp, (const uint8_t *)vstr, vlen); if (rc != IB_OK) { return rc; } rc = ib_field_create(&field, mp, name, nlen, IB_FTYPE_BYTESTR, ib_ftype_bytestr_in(bs)); } *pfield = field; } return rc; }
/** * 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; }
ib_status_t ib_parsed_resp_line_create( ib_parsed_resp_line_t **line, ib_mm_t mm, const char *raw, size_t raw_len, const char *protocol, size_t protocol_len, const char *status, size_t status_len, const char *msg, size_t msg_len ) { ib_status_t rc = IB_OK; ib_parsed_resp_line_t *line_tmp = ib_mm_alloc(mm, sizeof(*line_tmp)); if (line_tmp == NULL) { return IB_EALLOC; } if (protocol != NULL) { rc = ib_bytestr_dup_mem( &line_tmp->protocol, mm, (const uint8_t *)protocol, protocol_len ); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem( &line_tmp->protocol, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } if (status != NULL) { rc = ib_bytestr_dup_mem( &line_tmp->status, mm, (const uint8_t *)status, status_len ); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem( &line_tmp->status, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } if (msg != NULL) { rc = ib_bytestr_dup_mem( &line_tmp->msg, mm, (const uint8_t *)msg, msg_len ); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem( &line_tmp->msg, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } /* If no raw line is available, then create one. */ if (raw == NULL) { assert(protocol != NULL); assert(status != NULL); if (protocol_len + status_len + msg_len == 0) { rc = ib_bytestr_dup_mem( &line_tmp->raw, mm, (const uint8_t *)"", 0 ); if (rc != IB_OK) { return rc; } } else { /* Create a correctly sized bytestr and manually copy * the data into it. */ rc = ib_bytestr_create( &line_tmp->raw, mm, protocol_len + 1 + status_len + (msg == NULL ? 0 : 1 + msg_len) ); if (rc != IB_OK) { return rc; } ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)protocol, protocol_len ); ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)" ", 1 ); ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)status, status_len ); if (msg != NULL) { ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)" ", 1 ); ib_bytestr_append_mem( line_tmp->raw, (const uint8_t *)msg, msg_len ); } } } else { rc = ib_bytestr_dup_mem( &line_tmp->raw, mm, (const uint8_t *)raw, raw_len ); if (rc != IB_OK) { return rc; } } /* Commit back successfully created line. */ *line = line_tmp; return IB_OK; }
ib_status_t ib_parsed_resp_line_create(ib_tx_t *tx, ib_parsed_resp_line_t **line, const char *raw, size_t raw_len, const char *protocol, size_t protocol_len, const char *status, size_t status_len, const char *msg, size_t msg_len) { ib_status_t rc = IB_OK; assert(tx != NULL); assert(tx->ib != NULL); assert(tx->mp != NULL); ib_parsed_resp_line_t *line_tmp = ib_mpool_alloc(tx->mp, sizeof(*line_tmp)); if (line_tmp == NULL) { *line = NULL; return IB_EALLOC; } if (protocol != NULL) { rc = ib_bytestr_dup_mem(&line_tmp->protocol, tx->mp, (const uint8_t *)protocol, protocol_len); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->protocol, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } if (status != NULL) { rc = ib_bytestr_dup_mem(&line_tmp->status, tx->mp, (const uint8_t *)status, status_len); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->status, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } if (msg != NULL) { rc = ib_bytestr_dup_mem(&line_tmp->msg, tx->mp, (const uint8_t *)msg, msg_len); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->msg, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } /* If no raw line is available, then create one. */ if (raw == NULL) { assert(protocol != NULL); assert(status != NULL); if (protocol_len + status_len + msg_len == 0) { rc = ib_bytestr_dup_mem(&line_tmp->raw, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } else { /* Create a correctly sized bytestr and manually copy * the data into it. */ rc = ib_bytestr_create(&line_tmp->raw, tx->mp, protocol_len + 1 + status_len + (msg == NULL ? 0 : 1 + msg_len)); if (rc != IB_OK) { return rc; } ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)protocol, protocol_len); ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)" ", 1); ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)status, status_len); if (msg != NULL) { ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)" ", 1); ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)msg, msg_len); } } } else { rc = ib_bytestr_dup_mem(&line_tmp->raw, tx->mp, (const uint8_t *)raw, raw_len); if (rc != IB_OK) { return rc; } /* Now, if all components are missing, then parse them out * from the raw line. If only some are missing, then * do not assume anything is parsable. * * NOTE: This is a strict HTTP parser and assumes single * space (0x20) component separators. Better is to * have the server parse the components properly. */ if ((protocol == NULL) && (status == NULL) && (msg == NULL)) { uint8_t *raw_end = (uint8_t *)(raw + raw_len) - 1; uint8_t *ptr = (uint8_t *)raw; const uint8_t *parsed_field = ptr; ib_log_debug_tx(tx, "Parsing raw response line into components."); /* Parse the protocol. */ while (ptr <= raw_end) { if (*ptr == ' ') { break; } ++ptr; } rc = ib_bytestr_dup_mem(&line_tmp->protocol, tx->mp, parsed_field, (ptr - parsed_field)); if (rc != IB_OK) { return rc; } /* Parse the status. */ parsed_field = ++ptr; while (ptr <= raw_end) { if (*ptr == ' ') { break; } ++ptr; } rc = ib_bytestr_dup_mem(&line_tmp->status, tx->mp, parsed_field, (ptr - parsed_field)); if (rc != IB_OK) { return rc; } /* Parse the message. */ parsed_field = ++ptr; if (parsed_field <= raw_end) { rc = ib_bytestr_dup_mem(&line_tmp->msg, tx->mp, parsed_field, (raw_end - parsed_field) + 1); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->msg, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } } } /* Commit back successfully created line. */ *line = line_tmp; return IB_OK; }
/** * Set the matches into the given field name as .0, .1, .2 ... .9. * * @param[in] ib The IronBee engine to log to. * @param[in] tx The transaction to store the values into (tx->dpi). * @param[in] field_name The field to populate with Regex matches. * @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(ib_engine_t *ib, ib_tx_t *tx, int *ovector, int matches, const char *subject) { IB_FTRACE_INIT(); /* IronBee status. */ ib_status_t rc; /* Iterator. */ int i; rc = ib_data_capture_clear(tx); 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->dpi. */ 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]; /* If debugging this, copy the string value out and print it to the * log. This could be dangerous as there could be non-character * values in the match. */ ib_log_debug2_tx(tx, "REGEX Setting #%d=%.*s", i, (int)match_len, match_start); /* Create a byte-string representation */ rc = ib_bytestr_dup_mem(&bs, tx->mp, (const uint8_t*)match_start, match_len); if (rc != IB_OK) { IB_FTRACE_RET_STATUS(rc); } /* Create a field to hold the byte-string */ name = ib_data_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) { IB_FTRACE_RET_STATUS(rc); } /* Add it to the capture collection */ rc = ib_data_capture_set_item(tx, i, field); if (rc != IB_OK) { IB_FTRACE_RET_STATUS(rc); } } IB_FTRACE_RET_STATUS(IB_OK); }
ib_status_t ib_parsed_req_line_create(ib_tx_t *tx, ib_parsed_req_line_t **line, const char *raw, size_t raw_len, const char *method, size_t method_len, const char *uri, size_t uri_len, const char *protocol, size_t protocol_len) { ib_status_t rc = IB_OK; assert(tx != NULL); assert(tx->ib != NULL); assert(tx->mp != NULL); ib_parsed_req_line_t *line_tmp = ib_mpool_alloc(tx->mp, sizeof(*line_tmp)); if ( line_tmp == NULL ) { *line = NULL; return IB_EALLOC; } /* Record the components if available. If the components are * not available, but the raw line is, then it will be possible * to parse the components out later on. Otherwise, if there * is no component and no raw line, then set default values. */ if (method != NULL) { rc = ib_bytestr_dup_mem(&line_tmp->method, tx->mp, (const uint8_t *)method, method_len); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->method, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } if (uri != NULL) { rc = ib_bytestr_dup_mem(&line_tmp->uri, tx->mp, (const uint8_t *)uri, uri_len); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->uri, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } if (protocol != NULL) { rc = ib_bytestr_dup_mem(&line_tmp->protocol, tx->mp, (const uint8_t *)protocol, protocol_len); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->protocol, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } /* If no raw line is available, then create one. */ if (raw == NULL) { if (method_len + uri_len + protocol_len == 0) { ib_log_notice_tx(tx, "Unable to generate raw request line without line " "components - using zero length request line." ); rc = ib_bytestr_dup_mem(&line_tmp->raw, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } else { size_t raw_line_len; assert(method != NULL); assert(uri != NULL); /* Create a correctly sized bytestr and manually copy * the data into it. */ raw_line_len = method_len + 1 + uri_len + (protocol == NULL ? 0 : 1 + protocol_len); rc = ib_bytestr_create(&line_tmp->raw, tx->mp, raw_line_len); if (rc != IB_OK) { return rc; } ib_log_debug_tx(tx, "Generating raw request line from components " "(length %zd).", raw_line_len); ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)method, method_len); ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)" ", 1); ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)uri, uri_len); if (protocol != NULL) { ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)" ", 1); ib_bytestr_append_mem(line_tmp->raw, (const uint8_t *)protocol, protocol_len); } } } else { rc = ib_bytestr_dup_mem(&line_tmp->raw, tx->mp, (const uint8_t *)raw, raw_len); if (rc != IB_OK) { return rc; } /* Now, if all components are missing, then parse them out * from the raw line. If only some are missing, then * do not assume anything is parsable. * * NOTE: This is a strict HTTP parser and assumes single * space (0x20) component separators. Better is to * have the server parse the components properly. */ if ((method == NULL) && (uri == NULL) && (protocol == NULL)) { uint8_t *raw_end = (uint8_t *)(raw + raw_len) - 1; uint8_t *ptr = (uint8_t *)raw; const uint8_t *parsed_field = ptr; ib_log_debug_tx(tx, "Parsing raw request line into components."); /* Parse the method. */ while (ptr <= raw_end) { if (*ptr == ' ') { break; } ++ptr; } rc = ib_bytestr_dup_mem(&line_tmp->method, tx->mp, parsed_field, (ptr - parsed_field)); if (rc != IB_OK) { return rc; } /* Parse the uri. */ parsed_field = ++ptr; while (ptr <= raw_end) { if (*ptr == ' ') { break; } ++ptr; } rc = ib_bytestr_dup_mem(&line_tmp->uri, tx->mp, parsed_field, (ptr - parsed_field)); if (rc != IB_OK) { return rc; } /* Parse the protocol. */ parsed_field = ++ptr; if (parsed_field <= raw_end) { rc = ib_bytestr_dup_mem(&line_tmp->protocol, tx->mp, parsed_field, (raw_end - parsed_field) + 1); if (rc != IB_OK) { return rc; } } else { rc = ib_bytestr_dup_mem(&line_tmp->protocol, tx->mp, (const uint8_t *)"", 0); if (rc != IB_OK) { return rc; } } } } /* Commit back successfully created line. */ *line = line_tmp; return IB_OK; }