Beispiel #1
0
// 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);
}
Beispiel #2
0
/**
 * 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;
}
Beispiel #3
0
TEST(TestIronBee, test_data_indexed)
{
    ib_engine_t *ib;
    ib_data_config_t *dataconfig;
    ib_data_t *data;
    ib_field_t *f;
    size_t i;
    size_t j;
    ib_num_t n;

    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_register_indexed_ex(dataconfig, "foo", 3, &i));
    ASSERT_EQ(IB_OK, ib_data_lookup_index(dataconfig, "foo", &j));
    ASSERT_EQ(i, j);
    ASSERT_EQ(IB_ENOENT, ib_data_lookup_index(dataconfig, "bar", NULL));
    ASSERT_EQ(IB_EINVAL, ib_data_register_indexed(dataconfig, "foo"));

    ASSERT_EQ(IB_OK, ib_data_create(dataconfig, ib_engine_pool_main_get(ib), &data));
    ASSERT_TRUE(data);

    ASSERT_EQ(IB_OK, ib_data_add_num(data, "foo", 5, NULL));
    ASSERT_EQ(IB_OK, ib_data_get_indexed(data, i, &f));
    ASSERT_EQ(IB_OK, ib_field_value(f, ib_ftype_num_out(&n)));
    ASSERT_EQ(5, n);
    ASSERT_EQ(IB_OK, ib_data_get(data, "foo", &f));
    ASSERT_EQ(IB_OK, ib_field_value(f, ib_ftype_num_out(&n)));
    ASSERT_EQ(5, n);
}
Beispiel #4
0
TEST_F(CoreActionTest, setVarMult) {
    ib_field_t *f;
    ib_num_t n;

    ASSERT_EQ(IB_OK, ib_data_get(ib_conn->tx->dpi, "c", &f));

    ASSERT_EQ(IB_FTYPE_NUM, f->type);

    ib_field_value(f, ib_ftype_num_out(&n));

    ASSERT_EQ(2, n);
}
Beispiel #5
0
/**
 * Do a larger integration test.
 */
TEST_F(CoreActionTest, integration) {
    ib_field_t *f;
    ib_num_t n;

    ASSERT_EQ(IB_OK, ib_data_get(ib_conn->tx->dpi, "r1", &f));
    ASSERT_EQ(IB_FTYPE_NUM, f->type);
    ib_field_value(f, ib_ftype_num_out(&n));
    ASSERT_EQ(1, n);

    ASSERT_EQ(IB_OK, ib_data_get(ib_conn->tx->dpi, "r2", &f));
    ASSERT_EQ(IB_FTYPE_NUM, f->type);
    ib_field_value(f, ib_ftype_num_out(&n));
    ASSERT_EQ(1, n);

    ASSERT_EQ(IB_OK, ib_data_get(ib_conn->tx->dpi, "r3", &f));
    ASSERT_EQ(IB_FTYPE_NUM, f->type);
    ib_field_value(f, ib_ftype_num_out(&n));
    ASSERT_EQ(1, n);

    ASSERT_EQ(IB_OK, ib_data_get(ib_conn->tx->dpi, "r4", &f));
    ASSERT_EQ(IB_FTYPE_NUM, f->type);
    ib_field_value(f, ib_ftype_num_out(&n));
    ASSERT_EQ(1, n);
}
Beispiel #6
0
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);
}
Beispiel #7
0
//! 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);
}
Beispiel #8
0
/**
 * Handle request_header events for remote IP extraction.
 *
 * Extract the "request_headers" field (a list) from the transactions's
 * data provider instance, then loop through the list, looking for the
 * "X-Forwarded-For"  field.  If found, the first value in the (comma
 * separated) list replaces the local ip address string in the connection
 * object.
 *
 * @param[in] ib IronBee object
 * @param[in,out] tx Transaction object
 * @param[in] event Event type
 * @param[in] cbdata Callback data (not used)
 *
 * @returns Status code
 */
static ib_status_t modua_remoteip(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 == request_header_finished_event);

    ib_field_t           *field = NULL;
    ib_status_t           rc = IB_OK;
    const ib_bytestr_t   *bs;
    const uint8_t        *data;
    size_t                len;
    char                 *buf;
    uint8_t              *comma;
    const ib_list_t      *list;
    const ib_list_node_t *node;
    const ib_field_t     *forwarded;
    uint8_t              *stripped;
    size_t                num;
    ib_flags_t            flags;

    ib_log_debug3_tx(tx, "Checking for alternate remote address");

    /* Extract the X-Forwarded-For from the provider instance */
    rc = ib_data_get(tx->data, "request_headers:X-Forwarded-For", &field);
    if ( (field == NULL) || (rc != IB_OK) ) {
        ib_log_debug_tx(tx, "No X-Forwarded-For field");
        return IB_OK;
    }

    /* Because we asked for a filtered item, what we get back is a list */
    rc = ib_field_value(field, ib_ftype_list_out(&list));
    if (rc != IB_OK) {
        ib_log_debug_tx(tx, "No request header collection");
        return rc;
    }

    num = ib_list_elements(list);
    if (num == 0) {
        ib_log_debug_tx(tx, "No X-Forwarded-For header found");
        return rc;
    }
    else if (num != 1) {
        ib_log_debug_tx(tx, "%zd X-Forwarded-For headers found: ignoring", num);
        return rc;
    }
    node = ib_list_last_const(list);
    if ( (node == NULL) || (node->data == NULL) ) {
        ib_log_notice_tx(tx, "Invalid X-Forwarded-For header found");
        return rc;
    }
    forwarded = (const ib_field_t *)node->data;

    /* Found it: copy the data into a newly allocated string buffer */
    rc = ib_field_value_type(forwarded,
                             ib_ftype_bytestr_out(&bs),
                             IB_FTYPE_BYTESTR);
    if (rc != IB_OK) {
        ib_log_notice_tx(tx, "Invalid X-Forwarded-For header value");
        return rc;
    }

    if (bs == NULL) {
        ib_log_notice_tx(tx, "X-Forwarded-For header not a bytestr");
        return IB_EINVAL;
    }
    len = ib_bytestr_length(bs);
    data = ib_bytestr_const_ptr(bs);

    /* Search for a comma in the buffer */
    comma = memchr(data, ',', len);
    if (comma != NULL) {
        len = comma - data;
    }

    /* Trim whitespace */
    stripped = (uint8_t *)data;
    rc = ib_strtrim_lr_ex(IB_STROP_INPLACE, tx->mp,
                          stripped, len,
                          &stripped, &len, &flags);
    if (rc != IB_OK) {
        return rc;
    }

    /* Verify that it looks like a valid IP v4/6 address */
    rc = ib_ip_validate_ex((const char *)stripped, len);
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
                        "X-Forwarded-For \"%.*s\" is not a valid IP address",
                        (int)len, stripped
                       );
        return IB_OK;
    }

    /* Allocate memory for copy of stripped string */
    buf = (char *)ib_mpool_alloc(tx->mp, len+1);
    if (buf == NULL) {
        ib_log_error_tx(tx,
                        "Failed to allocate %zd bytes for remote address",
                        len+1);
        return IB_EALLOC;
    }

    /* Copy the string out */
    memcpy(buf, stripped, len);
    buf[len] = '\0';

    ib_log_debug_tx(tx, "Remote address changed to \"%s\"", buf);

    /* This will lose the pointer to the original address
     * buffer, but it should be cleaned up with the rest
     * of the memory pool. */
    tx->er_ipstr = buf;

    /* Update the remote address field in the tx collection */
    rc = ib_data_add_bytestr(tx->data, "remote_addr", (uint8_t*)buf, len, NULL);
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
                        "Failed to create remote address TX field: %s",
                        ib_status_to_string(rc));
        return rc;
    }

    return IB_OK;
}
Beispiel #9
0
/// @test Test ironbee library - data provider
TEST(TestIronBee, test_data_dynf)
{
    ib_engine_t *ib;
    ib_data_config_t *dataconfig;
    ib_data_t *data;
    ib_field_t *dynf;
    ib_field_t *f;
    ib_field_t *f2;
    ib_status_t rc;
    ib_num_t n;
    ib_list_t* l;

    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);

    /* Create a field with no initial value. */
    ASSERT_EQ(
        IB_OK,
        ib_field_create_dynamic(
            &dynf,
            ib_engine_pool_main_get(ib),
            IB_FIELD_NAME("test_dynf"),
            IB_FTYPE_LIST,
            dyn_get, (void *)ib_engine_pool_main_get(ib),
            NULL, NULL
        )
    );
    ASSERT_TRUE(dynf);
    ASSERT_EQ(9UL, dynf->nlen);
    ASSERT_MEMEQ("test_dynf", dynf->name, 9);

    /* Add the field to the data store. */
    ASSERT_EQ(IB_OK, ib_data_add(data, dynf));

    /* Fetch the field from the data store */
    ASSERT_EQ(IB_OK, ib_data_get(data, "test_dynf", &f));
    ASSERT_TRUE(f);
    ASSERT_EQ(dynf, f);

    /* Fetch a dynamic field from the data store */
    ASSERT_EQ(IB_OK, ib_data_get(data, "test_dynf:dyn_subkey", &f));
    ASSERT_TRUE(f);
    ASSERT_EQ(9UL, f->nlen);

    /* Get the list value from the dynamic field. */
    rc = ib_field_mutable_value(f, ib_ftype_list_mutable_out(&l));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(1UL, ib_list_elements(l));

    /* Get the single value from the list. */
    f2 = (ib_field_t *)ib_list_node_data(ib_list_first(l));
    ASSERT_TRUE(f2);
    ASSERT_EQ(10UL, f2->nlen);
    rc = ib_field_value(f2, ib_ftype_num_out(&n));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(5, n);

    /* Fetch a another subkey */
    ASSERT_EQ(IB_OK, ib_data_get(data, "test_dynf:dyn_subkey2", &f));
    ASSERT_TRUE(f);
    ASSERT_EQ(9UL, f->nlen);

    /* Get the list value from the dynamic field. */
    rc = ib_field_mutable_value(f, ib_ftype_list_mutable_out(&l));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(1UL, ib_list_elements(l));

    /* Get the single value from the list. */
    f2 = (ib_field_t *)ib_list_node_data(ib_list_first(l));
    ASSERT_TRUE(f2);
    ASSERT_EQ(11UL, f2->nlen);
    rc = ib_field_value(f2, ib_ftype_num_out(&n));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(5, n);

    ibtest_engine_destroy(ib);
}
Beispiel #10
0
/**
 * @internal
 * Handle signature execution.
 *
 * @param ib Engine
 * @param tx Transaction
 * @param cbdata Phase passed as pointer value
 *
 * @return Status code
 */
static ib_status_t pocsig_handle_sigs(ib_engine_t *ib,
                                      ib_tx_t *tx,
                                      void *cbdata)
{
    IB_FTRACE_INIT(pocsig_handle_post);
    pocsig_cfg_t *cfg;
    pocsig_phase_t phase = (pocsig_phase_t)(uintptr_t)cbdata;
    ib_list_t *sigs;
    ib_list_node_t *node;
    int dbglvl;
    ib_status_t rc;

    /* Get the pocsig configuration for this context. */
    rc = ib_context_module_config(tx->ctx, IB_MODULE_STRUCT_PTR, (void *)&cfg);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "Failed to fetch %s config: %d",
                     MODULE_NAME_STR, rc);
    }

    /* If tracing is enabled, lower the log level. */
    dbglvl = cfg->trace ? 4 : 9;

    /* Get the list of sigs for this phase. */
    sigs = cfg->phase[phase];
    if (sigs == NULL) {
        ib_log_debug(ib, dbglvl, "No signatures for phase=%d ctx=%p",
                     phase, tx->ctx);
        IB_FTRACE_RET_STATUS(IB_OK);
    }

    ib_log_debug(ib, dbglvl, "Executing %d signatures for phase=%d ctx=%p",
                 ib_list_elements(sigs), phase, tx->ctx);

    /* Run all the sigs for this phase. */
    IB_LIST_LOOP(sigs, node) {
        pocsig_sig_t *s = (pocsig_sig_t *)ib_list_node_data(node);
        ib_field_t *f;

        /* Fetch the field. */
        rc = ib_data_get(tx->dpi, s->target, &f);
        if (rc != IB_OK) {
            ib_log_error(ib, 4, "PocSig: No field named \"%s\"", s->target);
            continue;
        }

        /* Perform the match. */
        ib_log_debug(ib, dbglvl, "PocSig: Matching \"%s\" against field \"%s\"",
                     s->patt, s->target);
        rc = ib_matcher_match_field(cfg->pcre, s->cpatt, 0, f, NULL);
        if (rc == IB_OK) {
            ib_logevent_t *e;

            ib_log_debug(ib, dbglvl, "PocSig MATCH: %s at %s", s->patt, s->target);

            /* Create the event. */
            rc = ib_logevent_create(
                &e,
                tx->mp,
                "-",
                IB_LEVENT_TYPE_ALERT,
                IB_LEVENT_ACT_UNKNOWN,
                IB_LEVENT_PCLASS_UNKNOWN,
                IB_LEVENT_SCLASS_UNKNOWN,
                90,
                80,
                IB_LEVENT_SYS_UNKNOWN,
                IB_LEVENT_ACTION_IGNORE,
                IB_LEVENT_ACTION_IGNORE,
                s->emsg
            );
            if (rc != IB_OK) {
                ib_log_error(ib, 3, "PocSig: Error generating event: %d", rc);
                continue;
            }

            /* Log the event. */
            ib_clog_event(tx->ctx, e);
        }
        else {
            ib_log_debug(ib, dbglvl, "PocSig NOMATCH");
        }
    }
Beispiel #11
0
/*
 * 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", &param_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));
                }
            }
Beispiel #12
0
/**
 * 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;
}
Beispiel #13
0
// 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;
}
Beispiel #14
0
/**
 * 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);
}
Beispiel #15
0
/**
 * Feed a collection of byte strings from an @ref ib_data_t to automata.
 *
 * @param[in] ib          IronBee engine; used for logging.
 * @param[in] eudoxus     Eudoxus engine; used for ia_eudoxus_error().
 * @param[in] state       Current Eudoxus execution state; updated.
 * @param[in] data        Data source.
 * @param[in] collection  Collection to feed.
 * @return
 * - IB_OK on success.
 * - IB_EINVAL on IronAutomata failure; will emit log message.
 * - IB_EOTHER on IronBee failure; will emit log message.
 */
static
ib_status_t fast_feed_data_collection(
    const ib_engine_t             *ib,
    const ia_eudoxus_t            *eudoxus,
    ia_eudoxus_state_t            *state,
    const ib_data_t               *data,
    const fast_collection_spec_t  *collection
)
{
    assert(ib         != NULL);
    assert(eudoxus    != NULL);
    assert(state      != NULL);
    assert(data       != NULL);
    assert(collection != NULL);

    ib_field_t           *field;
    const ib_list_t      *subfields;
    const ib_list_node_t *node;
    const ib_field_t     *subfield;
    const ib_bytestr_t   *bs;
    ib_status_t           rc;

    rc = ib_data_get(data, collection->name, &field);
    if (rc == IB_ENOENT) {
        ib_log_error(
            ib,
            "fast: No such data %s",
            collection->name
        );
        return IB_EOTHER;
    }
    else if (rc != IB_OK) {
        ib_log_error(
            ib,
            "fast: Error fetching data %s: %s",
            collection->name,
            ib_status_to_string(rc)
        );
        return IB_EOTHER;
    }

    rc = ib_field_value_type(
        field,
        ib_ftype_list_out(&subfields),
        IB_FTYPE_LIST
    );
    if (rc != IB_OK) {
        ib_log_error(
            ib,
            "fast: Error loading data field %s: %s",
            collection->name,
            ib_status_to_string(rc)
        );
        return IB_EOTHER;
    }

    IB_LIST_LOOP_CONST(subfields, node) {
        subfield = (const ib_field_t *)ib_list_node_data_const(node);
        assert(subfield != NULL);

        rc = ib_field_value_type(
            subfield,
            ib_ftype_bytestr_out(&bs),
            IB_FTYPE_BYTESTR
        );
        if (rc != IB_OK) {
            ib_log_error(
                ib,
                "fast: Error loading data subfield %s of %s: %s",
                subfield->name,
                collection->name,
                ib_status_to_string(rc)
            );
            return IB_EOTHER;
        }

        rc = fast_feed(
            ib,
            eudoxus,
            state,
            (const uint8_t *)subfield->name,
            subfield->nlen
        );
        if (rc != IB_OK) {
            return rc;
        }

        rc = fast_feed(
            ib,
            eudoxus,
            state,
            (const uint8_t *)collection->separator,
            strlen(collection->separator)
        );
        if (rc != IB_OK) {
            return rc;
        }

        if (ib_bytestr_const_ptr(bs) != NULL && ib_bytestr_size(bs) > 0) {
            rc = fast_feed(
                ib,
                eudoxus,
                state,
                ib_bytestr_const_ptr(bs),
                ib_bytestr_size(bs)
            );
            if (rc != IB_OK) {
                return rc;
            }
        }

        rc = fast_feed(
            ib,
            eudoxus,
            state,
            (const uint8_t *)c_data_separator,
            strlen(c_data_separator)
        );
        if (rc != IB_OK) {
            return rc;
        }
    }
Beispiel #16
0
/**
 * Feed a byte string from an @ref ib_data_t to the automata.
 *
 * @param[in] ib                    IronBee engine; used for logging.
 * @param[in] eudoxus               Eudoxus engine; used for
 *                                  ia_eudoxus_error().
 * @param[in] state                 Current Eudoxus execution state; updated.
 * @param[in] data                  Data source.
 * @param[in] bytestring_field_name Name of data field to feed.
 * @return
 * - IB_OK on success.
 * - IB_EINVAL on IronAutomata failure; will emit log message.
 * - IB_EOTHER on IronBee failure; will emit log message.
 */
static
ib_status_t fast_feed_data_bytestring(
    const ib_engine_t  *ib,
    const ia_eudoxus_t *eudoxus,
    ia_eudoxus_state_t *state,
    const ib_data_t    *data,
    const char         *bytestring_field_name
)
{
    assert(ib                    != NULL);
    assert(eudoxus               != NULL);
    assert(state                 != NULL);
    assert(data                  != NULL);
    assert(bytestring_field_name != NULL);

    ib_field_t         *field;
    const ib_bytestr_t *bs;
    ib_status_t         rc;

    rc = ib_data_get(data, bytestring_field_name, &field);
    if (rc == IB_ENOENT) {
        ib_log_error(
            ib,
            "fast: No such data %s",
            bytestring_field_name
        );
        return IB_EOTHER;
    }
    else if (rc != IB_OK) {
        ib_log_error(
            ib,
            "fast: Error fetching data %s: %s",
            bytestring_field_name,
            ib_status_to_string(rc)
        );
        return IB_EOTHER;
    }

    rc = ib_field_value_type(
        field,
        ib_ftype_bytestr_out(&bs),
        IB_FTYPE_BYTESTR
    );
    if (rc != IB_OK) {
        ib_log_error(
            ib,
            "fast: Error loading data field %s: %s",
            bytestring_field_name,
            ib_status_to_string(rc)
        );
        return IB_EOTHER;
    }

    if (ib_bytestr_const_ptr(bs) == NULL || ib_bytestr_size(bs) == 0) {
        return IB_OK;
    }
    return fast_feed(
        ib,
        eudoxus,
        state,
        ib_bytestr_const_ptr(bs), ib_bytestr_size(bs)
    );
}