Esempio n. 1
0
/// @test Test util list library - IB_LIST_LOOP()
TEST_F(TestIBUtilList, test_list_loop)
{
    ib_list_t *list;
    ib_list_node_t *node;
    ib_status_t rc;
    int init[] = { 0, 1, 2, 3, 4 };
    int *val;
    int i;

    rc = ib_list_create(&list, MemPool());
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(list);
    ASSERT_EQ(0UL, ib_list_elements(list));

    for (i = 0; i < 5; i++) {
        rc = ib_list_push(list, &init[i]);
        ASSERT_EQ(IB_OK, rc);
    }
    ASSERT_EQ(5UL, ib_list_elements(list));

    i = 0;
    IB_LIST_LOOP(list, node) {
        val = (int *)ib_list_node_data(node);
        ASSERT_EQ(init[i], *val);
        i++;
    }
Esempio n. 2
0
TEST_F(XRulesTest, SetFlag) {
    ib_field_t       *field;
    ib_num_t          num;
    ib_var_target_t  *target;
    const ib_list_t  *list;

    std::string config =
        std::string(
            "LogLevel DEBUG\n"
            "LoadModule \"ibmod_persistence_framework.so\"\n"
            "LoadModule \"ibmod_init_collection.so\"\n"
            "LoadModule \"ibmod_xrules.so\"\n"
            "InitCollection GeoIP vars: country_code=US\n"
            "SensorId B9C1B52B-C24A-4309-B9F9-0EF4CD577A3E\n"
            "SensorName UnitTesting\n"
            "SensorHostname unit-testing.sensor.tld\n"
            /* Note that both rules should fire and result in a single entry. */
            "XRulePath /  EnableRequestParamInspection priority=1\n"
            "XRuleGeo US EnableRequestParamInspection priority=1\n"
            "<Site test-site>\n"
            "   SiteId AAAABBBB-1111-2222-3333-000000000000\n"
            "   Hostname somesite.com\n"
            "</Site>\n"
        );

    configureIronBeeByString(config.c_str());
    performTx();
    ASSERT_TRUE(ib_tx);
    ASSERT_TRUE(ib_tx->flags & IB_TX_FINSPECT_REQPARAMS);

    ASSERT_EQ(
        IB_OK,
        ib_var_target_acquire_from_string(
            &target,
            ib_tx->mp,
            ib_var_store_config(ib_tx->var_store),
            "FLAGS:inspectRequestParams",
            strlen("FLAGS:inspectRequestParams"),
            NULL,
            NULL)
    );
    ASSERT_EQ(
        IB_OK,
        ib_var_target_get_const(
            target,
            &list,
            ib_tx->mp,
            ib_tx->var_store)
    );
    ASSERT_EQ(1U, ib_list_elements(list));
    field = (ib_field_t *)ib_list_node_data_const(ib_list_first_const(list));
    ASSERT_EQ(IB_FTYPE_NUM, field->type);
    ASSERT_EQ(
        IB_OK,
        ib_field_value(field, ib_ftype_num_out(&num))
    );
    ASSERT_EQ(1, num);
}
Esempio n. 3
0
/// @test Test util list library - ib_htree_list() and ib_list_destroy()
TEST_F(TestIBUtilList, test_list_create_and_destroy)
{
    ib_list_t *list;
    ib_status_t rc;

    rc = ib_list_create(&list, MemPool());
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(list);
    ASSERT_EQ(0UL, ib_list_elements(list));
}
TEST_F(TestIBUtilLogformat, test_parse_custom3)
{
    ib_status_t rc;
    ib_logformat_t *lf = NULL;
    size_t len;
    static char linebuf[buflen + 1];
    static const char *formatted = \
                                   "Start" SITE_ID " \\ " SENSOR_ID " " HOST_NAME "  \t" LOG_FILE " %End";

    rc = ib_logformat_create(MM(), &lf);
    ASSERT_EQ(IB_OK, rc);

    rc = ib_logformat_parse(lf, "Start%s \\\\ %S %h\\n\\r\\t%f %%End");
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(9U, ib_list_elements(lf->items));

    rc = ib_logformat_format(lf, linebuf, buflen, &len, format_field, NULL);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_STREQ(formatted, linebuf);
}
/// @test Test util logformat library - ib_logformat_parse()
TEST_F(TestIBUtilLogformat, test_parse_custom1)
{
    ib_status_t rc;
    ib_logformat_t *lf = NULL;
    size_t len;
    static char linebuf[buflen + 1];
    static const char *formatted = \
                                   "MyFormat " SITE_ID " " SENSOR_ID " " HOST_NAME " " LOG_FILE " END";

    rc = ib_logformat_create(MM(), &lf);
    ASSERT_EQ(IB_OK, rc);

    rc = ib_logformat_parse(lf, "MyFormat %s %S %h %f END");
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(9U, ib_list_elements(lf->items));

    rc = ib_logformat_format(lf, linebuf, buflen, &len, format_field, NULL);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_STREQ(formatted, linebuf);
}
TEST_F(TestIBUtilLogformat, test_parse_default)
{
    ib_status_t rc;
    ib_logformat_t *lf = NULL;
    const ib_list_node_t *node;
    const ib_logformat_item_t *item;
    static char linebuf[buflen + 1];
    static const char *formatted = \
                                   TIME_STAMP " " HOST_NAME " " REMOTE_IP " " SENSOR_ID " " SITE_ID " " \
                                   TX_ID " " LOG_FILE;
    size_t len;

    rc = ib_logformat_create(MM(), &lf);
    ASSERT_EQ(IB_OK, rc);

    rc = ib_logformat_parse(lf, IB_LOGFORMAT_DEFAULT);
    ASSERT_EQ(IB_OK, rc);

    ASSERT_STREQ(IB_LOGFORMAT_DEFAULT, lf->format);

    ASSERT_EQ(13U, ib_list_elements(lf->items));

    node = ib_list_first_const(lf->items);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_format, item->itype);
    ASSERT_EQ('T', item->item.field.fchar);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_literal, item->itype);
    ASSERT_STREQ(" ", item->item.literal.buf.short_str);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_format, item->itype);
    ASSERT_EQ('h', item->item.field.fchar);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_literal, item->itype);
    ASSERT_STREQ(" ", item->item.literal.buf.short_str);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_format, item->itype);
    ASSERT_EQ('a', item->item.field.fchar);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_literal, item->itype);
    ASSERT_STREQ(" ", item->item.literal.buf.short_str);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_format, item->itype);
    ASSERT_EQ('S', item->item.field.fchar);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_literal, item->itype);
    ASSERT_STREQ(" ", item->item.literal.buf.short_str);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_format, item->itype);
    ASSERT_EQ('s', item->item.field.fchar);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_literal, item->itype);
    ASSERT_STREQ(" ", item->item.literal.buf.short_str);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_format, item->itype);
    ASSERT_EQ('t', item->item.field.fchar);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_literal, item->itype);
    ASSERT_STREQ(" ", item->item.literal.buf.short_str);

    node = ib_list_node_next_const(node);
    ASSERT_TRUE(node);
    item = (const ib_logformat_item_t *)node->data;
    ASSERT_EQ(item_type_format, item->itype);
    ASSERT_EQ('f', item->item.field.fchar);

    rc = ib_logformat_format(lf, linebuf, buflen, &len, format_field, NULL);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_STREQ(formatted, linebuf);

    /* Verify that truncation is handled correctly */
    rc = ib_logformat_format(lf, linebuf, trunclen, &len, format_field, NULL);
    ASSERT_EQ(IB_ETRUNC, rc);
    ASSERT_EQ(len, trunclen-1);
    char trunc_buf[trunclen];
    strncpy(trunc_buf, formatted, trunclen-1);
    trunc_buf[trunclen-1] = '\0';
    ASSERT_STREQ(trunc_buf, linebuf);
}
Esempio n. 7
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 (module)
 *
 * @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->var_store != NULL);
    assert(event == request_header_finished_event);

    const ib_module_t    *m = (const ib_module_t *)cbdata;
    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;
    const modua_config_t *cfg;

    rc = ib_context_module_config(ib_context_main(ib), m, &cfg);
    if (rc != IB_OK) {
        ib_log_error_tx(tx, "Can't fetch configuration: %s",
                        ib_status_to_string(rc));
        return rc;
    }

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

    /* Extract the X-Forwarded-For header field */
    rc = ib_var_target_get_const(
        cfg->forwarded_for,
        &list,
        tx->mp,
        tx->var_store
    );
    if (rc == IB_ENOENT || ib_list_elements(list) == 0) {
        ib_log_debug_tx(tx, "No X-Forwarded-For");
        return IB_OK;
    }
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
                        "Cannot retrieve request_headers:User-Agent: %d",
                        rc);
        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_field_create_bytestr_alias(
        &field,
        tx->mp,
        "", 0,
        (uint8_t *)buf, len
    );
    if (rc != IB_OK) {
        ib_log_error_tx(tx, "Failed to create field for remote_addr: %s",
                        ib_status_to_string(rc));
        return rc;
    }
    rc = ib_var_source_set(cfg->remote_addr, tx->var_store, field);
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
                        "Failed to set remote address var: %s",
                        ib_status_to_string(rc));
        return rc;
    }

    return IB_OK;
}
/**
 * Handle managed collection registration for vars "name=value" parameters
 *
 * @param[in] ib Engine
 * @param[in] module Collection manager's module object (unused)
 * @param[in] manager The collection manager object to register with (unused)
 * @param[in] mp Memory pool to use for allocations
 * @param[in] collection_name Name of the collection
 * @param[in] uri Full collection URI (unused)
 * @param[in] uri_scheme URI scheme (unused)
 * @param[in] uri_data Hierarchical/data part of the URI
 * @param[in] params List of parameter strings
 * @param[in] register_data Register callback data (unused)
 * @param[out] pmanager_inst_data Pointer to manager specific collection data
 *
 * @returns Status code:
 *   - IB_OK All OK
 *   - IB_Exxx Other error
 */
static ib_status_t core_managed_collection_vars_register_fn(
    const ib_engine_t             *ib,
    const ib_module_t             *module,
    const ib_collection_manager_t *manager,
    ib_mpool_t                    *mp,
    const char                    *collection_name,
    const char                    *uri,
    const char                    *uri_scheme,
    const char                    *uri_data,
    const ib_list_t               *params,
    void                          *register_data,
    void                         **pmanager_inst_data)
{
    assert(ib != NULL);
    assert(module != NULL);
    assert(mp != NULL);
    assert(collection_name != NULL);
    assert(params != NULL);
    assert(pmanager_inst_data != NULL);

    const ib_list_node_t *node;
    ib_list_t *vars_list;
    ib_list_t *field_list;
    ib_mpool_t *tmp = ib_engine_pool_temp_get(ib);
    ib_status_t rc;

    if (strlen(uri_data) != 0) {
        return IB_DECLINED;
    }
    if (ib_list_elements(params) < 1) {
        return IB_EINVAL;
    }

    /* Create a temporary list */
    rc = ib_list_create(&vars_list, tmp);
    if (rc != IB_OK) {
        return rc;
    }

    /* First pass; walk through all params, look for "a=b" type syntax */
    IB_LIST_LOOP_CONST(params, node) {
        static const int ovecsize = 9;
        int ovector[ovecsize];
        const char *param = (const char *)node->data;
        core_vars_t *vars;
        int pcre_rc;

        pcre_rc = pcre_exec(core_vars_manager.pattern, NULL,
                            param, strlen(param),
                            0, 0, ovector, ovecsize);
        if (pcre_rc < 0) {
            return IB_DECLINED;
        }

        vars = ib_mpool_alloc(tmp, sizeof(*vars));
        if (vars == NULL) {
            return IB_EALLOC;
        }
        vars->name  = ib_mpool_memdup_to_str(tmp,
                                             param + ovector[2],
                                             ovector[3] - ovector[2]);
        vars->value = ib_mpool_memdup_to_str(tmp,
                                             param + ovector[4],
                                             ovector[5] - ovector[4]);
        if ( (vars->name == NULL) || (vars->value == NULL) ) {
            return IB_EALLOC;
        }
        rc = ib_list_push(vars_list, vars);
        if (rc != IB_OK) {
            return rc;
        }
    }

    /* Build the list of fields */
    rc = ib_list_create(&field_list, mp);
    if (rc != IB_OK) {
        return rc;
    }

    /* Now walk though the list, creating a field for each one */
    IB_LIST_LOOP_CONST(vars_list, node) {
        const core_vars_t *vars = (const core_vars_t *)node->data;
        ib_field_t *field;
        ib_field_val_union_t fval;

        rc = ib_field_from_string(mp,
                                  IB_FIELD_NAME(vars->name), vars->value,
                                  &field, &fval);
        if (rc != IB_OK) {
            ib_log_error(ib, "Error creating field (\"%s\", \"%s\"): %s",
                         vars->name, vars->value,
                         ib_status_to_string(rc));
            return rc;
        }
        rc = ib_list_push(field_list, field);
        if (rc != IB_OK) {
            return rc;
        }

        if (field->type == IB_FTYPE_NUM) {
            ib_log_trace(ib, "Created numeric field \"%s\" %"PRId64" in \"%s\"",
                         vars->name, fval.num, collection_name);
        }

        else if (field->type == IB_FTYPE_FLOAT) {
            ib_log_trace(ib, "Created float field \"%s\" %f in \"%s\"",
                         vars->name, (double)fval.fnum, collection_name);
        }
        else {
            ib_log_trace(ib, "Created string field \"%s\" \"%s\" in \"%s\"",
                         vars->name, fval.nulstr, collection_name);
        }
    }

    /* Finally, store the list as the manager specific collection data */
    *pmanager_inst_data = field_list;

    return IB_OK;
}
Esempio n. 9
0
 //! Number of elements in list. O(1)
 size_type size() const
 {
     return ib_list_elements(ib());
 }
Esempio n. 10
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);
}
Esempio n. 11
0
    ASSERT_TRUE(list);
    ASSERT_EQ(0UL, ib_list_elements(list));

    for (i = 0; i < 5; i++) {
        rc = ib_list_push(list, &init[i]);
        ASSERT_EQ(IB_OK, rc);
    }
    ASSERT_EQ(5UL, ib_list_elements(list));

    i = 0;
    IB_LIST_LOOP(list, node) {
        val = (int *)ib_list_node_data(node);
        ASSERT_EQ(init[i], *val);
        i++;
    }
    ASSERT_EQ(5UL, ib_list_elements(list));
}

/// @test Test util list library - IB_LIST_LOOP_SAFE()
TEST_F(TestIBUtilList, test_list_loop_safe)
{
    ib_list_t *list;
    ib_list_node_t *node;
    ib_list_node_t *node_next;
    ib_status_t rc;
    int init[] = { 0, 1, 2, 3, 4 };
    int *val;
    int i;

    rc = ib_util_initialize();
    ASSERT_EQ(IB_OK, rc);
Esempio n. 12
0
/*
 * Function that return a list of all the datas with a prefix that start like
 * the provided prefix arg
 *
 * Example: insert data in 192.168.1.27, as well as 192.168.1.28,
 * as well as 192.168.10.0/24 and 10.0.0.0/8 and then search 192.168.0.0/16
 * it should return a list containing all the datas except the associated to
 * 10.0.0.0/8
 *
 * @param node the node to check
 * @param prefix the prefix we are searching
 * @param offset, the number of bits already compared +1 (cur possition)
 * @param rlist reference to the pointer that will be linked to the list, if any
 * @param mp pool where we should allocate the list
 *
 * @returns Status code
 */
ib_status_t ib_radix_match_all_data(ib_radix_t *radix,
                                     ib_radix_prefix_t *prefix,
                                     ib_list_t **rlist,
                                     ib_mpool_t *mp)
{
    IB_FTRACE_INIT(ib_radix_match_all_data);
    ib_status_t ret;

    if (rlist == NULL) {
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    if (radix->start == NULL) {
        IB_FTRACE_RET_STATUS(IB_ENOENT);
    }

    if (radix->start->data != NULL  &&
        prefix->prefixlen == 0)
    {
        if (*rlist == NULL) {
            ret = ib_list_create(rlist, mp);
            if (ret != IB_OK) {
                IB_FTRACE_RET_STATUS(ret);
            }
        }
        ret = ib_list_push(*rlist, radix->start->data);
        if (ret != IB_OK) {
            IB_FTRACE_RET_STATUS(ret);
        }
    }

    if (prefix->prefixlen == 0) {
            // Append data of both branches
            ret = ib_radix_match_all(radix->start->zero, prefix, 0,
                                        rlist, mp);
            if (ret != IB_OK && ret != IB_ENOENT) {
                IB_FTRACE_RET_STATUS(ret);
            }
            ret = ib_radix_match_all(radix->start->one, prefix, 0,
                                        rlist, mp);
            if (ret != IB_OK && ret != IB_ENOENT) {
                IB_FTRACE_RET_STATUS(ret);
            }
    }
    else {
        // Follow it's path until we reach the correct offset
        if (IB_GET_DIR(prefix->rawbits[0]) == 0) {
            ret = ib_radix_match_all(radix->start->zero, prefix, 0,
                                        rlist, mp);
        }
        else {
            ret = ib_radix_match_all(radix->start->one, prefix, 0,
                                        rlist, mp);
        }
    }

    if (ret == IB_ENOENT && *rlist != NULL &&
        ib_list_elements(*rlist) > 0) {
        IB_FTRACE_RET_STATUS(IB_OK);
    }

    IB_FTRACE_RET_STATUS(ret);
}
Esempio n. 13
0
ib_status_t ib_string_join(
    const char  *join_string,
    ib_list_t   *list,
    ib_mm_t      mm,
    const char **pout,
    size_t      *pout_len
)
{
    assert(join_string != NULL);
    assert(list != NULL);
    assert(pout != NULL);
    assert(pout_len != NULL);

    const ib_list_node_t *node;
    char                 *end;         /* Points to the \0 in out. */
    const char           *out;
    size_t                out_len = 1; /* Size to hold an empty string, '\0' */
    size_t               *str_len;     /* Array of lengths of char*s in list. */
    size_t                str_idx;     /* Index into str_len. */
    size_t                join_string_len;

    join_string_len = strlen(join_string);

    /* Handle the base-case and avoid asking for size 0 memory segments. */
    if (ib_list_elements(list) == 0) {
        *pout     = "";
        *pout_len = 0;
        return IB_OK;
    }

    /* First, build a place to cache string lengths. */
    str_len = ib_mm_alloc(mm, sizeof(*str_len) * ib_list_elements(list));
    if (str_len == NULL) {
        return IB_EALLOC;
    }

    /* Record each string length and sum those lengths into out_len.
     * Recall that out_len starts equal to 1 for the '\0'. */
    str_idx = 0;
    IB_LIST_LOOP_CONST(list, node) {
        const size_t len = strlen((const char *)ib_list_node_data_const(node));

        out_len += len;
        str_len[str_idx] = len;
        ++str_idx;
    }

    /* Increase out_len by the join string length * (n-1) elements. */
    out_len += (ib_list_elements(list) - 1)* join_string_len;

    /* Allocate the final string. */
    end = ib_mm_alloc(mm, out_len);
    if (end == NULL) {
        return IB_EALLOC;
    }

    /* Setup vars for joining the strings into out. */
    out     = end;
    str_idx = 0;
    node    = ib_list_first(list);

    /* Copy the first string. We know the list is > 0 elements long. */
    strcpy(end, (const char *)ib_list_node_data_const(node));
    end += str_len[str_idx];
    ++str_idx;
    /* Having copied the first string, now copy the join string, then the
     * the next string until the end of the list. */
    for (
        node = ib_list_node_next_const(node);
        node != NULL;
        node = ib_list_node_next_const(node)
    )
    {
        /* Copy the join string first. */
        strcpy(end, join_string);
        end += join_string_len;

        /* Copy the lagging string. */
        strcpy(end, (const char *)ib_list_node_data_const(node));
        end += str_len[str_idx];

        ++str_idx;
    }

    /* Commit work back to the caller. */
    *pout     = out;
    *pout_len = out_len-1;
    return IB_OK;
}
Esempio n. 14
0
ib_status_t ib_config_directive_process(ib_cfgparser_t *cp,
                                        const char *name,
                                        ib_list_t *args)
{
    IB_FTRACE_INIT(ib_config_directive_process);
    ib_engine_t *ib = cp->ib;
    ib_dirmap_init_t *rec;
    ib_list_node_t *node;
    size_t nargs = ib_list_elements(args);
    const char *p1;
    const char *p2;
    ib_flags_t flags;
    ib_flags_t fmask;
    ib_status_t rc;
    int i;

    rc = ib_hash_get(ib->dirmap, name, (void *)&rec);
    if (rc != IB_OK) {
        IB_FTRACE_RET_STATUS(rc);
    }

    switch (rec->type) {
        case IB_DIRTYPE_ONOFF:
            if (nargs != 1) {
                ib_log_error(ib, 1, "OnOff directive \"%s\" takes one parameter, not %d",
                             name, nargs);
                rc = IB_EINVAL;
                break;
            }
            ib_list_shift(args, &p1);
            if (   (strcasecmp("on", p1) == 0)
                || (strcasecmp("yes", p1) == 0)
                || (strcasecmp("true", p1) == 0))
            {
                rc = rec->cb.fn_onoff(cp, name, 1, rec->cbdata);
            }
            else {
                rc = rec->cb.fn_onoff(cp, name, 0, rec->cbdata);
            }
            break;
        case IB_DIRTYPE_PARAM1:
            if (nargs != 1) {
                ib_log_error(ib, 1, "Param1 directive \"%s\" takes one parameter, not %d",
                             name, nargs);
                rc = IB_EINVAL;
                break;
            }
            ib_list_shift(args, &p1);
            rc = rec->cb.fn_param1(cp, name, p1, rec->cbdata);
            break;
        case IB_DIRTYPE_PARAM2:
            if (nargs != 2) {
                ib_log_error(ib, 1, "Param2 directive \"%s\" takes two parameters, not %d",
                             name, nargs);
                rc = IB_EINVAL;
                break;
            }
            ib_list_shift(args, &p1);
            ib_list_shift(args, &p2);
            rc = rec->cb.fn_param2(cp, name, p1, p2, rec->cbdata);
            break;
        case IB_DIRTYPE_LIST:
            rc = rec->cb.fn_list(cp, name, args, rec->cbdata);
            break;
        case IB_DIRTYPE_OPFLAGS:
            i = 0;
            flags = 0;
            fmask = 0;

            IB_LIST_LOOP(args, node) {
                const char *opname = (const char *)ib_list_node_data(node);
                int oper = (*opname == '-') ? -1 : ((*opname == '+') ? 1 : 0);
                ib_num_t val;

                /* If the first option does not use an operator, then
                 * this is setting all flags so set all the mask bits.
                 */
                if ((i == 0) && (oper == 0)) {
                    fmask = ~0;
                }

                ib_log_debug(ib, 9, "Processing %s option: %s", name, opname);

                /* Remove the operator from the name if required.
                 * and determine the numeric value of the option
                 * by using the value map.
                 */
                if (oper != 0) {
                    opname++;
                }

                rc = cfgp_opval(opname, rec->valmap, &val);
                if (rc != IB_OK) {
                    ib_log_error(ib, 3, "Invalid %s option: %s", name, opname);
                    IB_FTRACE_RET_STATUS(rc);
                }

                /* Mark which bit(s) we are setting. */
                fmask |= val;

                /* Set/Unset the appropriate bits. */
                if (oper == -1) {
                    flags = flags & ~val;
                }
                else {
                    flags |= val;
                }

                i++;
            }

            rc = rec->cb.fn_opflags(cp, name, flags, fmask, rec->cbdata);
            break;
        case IB_DIRTYPE_SBLK1:
            if (nargs != 1) {
                ib_log_error(ib, 1, "SBlk1 directive \"%s\" takes one parameter, not %d",
                             name, nargs);
                rc = IB_EINVAL;
                break;
            }
            ib_list_shift(args, &p1);
            rc = rec->cb.fn_sblk1(cp, name, p1, rec->cbdata);
            break;
        default:
            rc = IB_EINVAL;
    }

    IB_FTRACE_RET_STATUS(rc);
}
Esempio n. 15
0
/*********************************
 * Helper Functions
 *********************************/
static
ib_status_t sqli_create_fingerprint_set_from_file(
    sqli_fingerprint_set_t **out_ps,
    const char         *path,
    ib_mm_t             mm
)
{
    assert(out_ps != NULL);
    assert(path   != NULL);

    ib_status_t         rc;
    FILE               *fp          = NULL;
    char               *buffer      = NULL;
    size_t              buffer_size = 0;
    ib_list_t          *items       = NULL;
    ib_list_node_t     *n           = NULL;
    ib_mpool_lite_t    *tmp         = NULL;
    ib_mm_t             tmp_mm;
    sqli_fingerprint_set_t *ps          = NULL;
    size_t              i           = 0;

    /* Temporary memory pool for this function only. */
    rc = ib_mpool_lite_create(&tmp);
    assert(rc == IB_OK);
    assert(tmp != NULL);
    tmp_mm = ib_mm_mpool_lite(tmp);

    fp = fopen(path, "r");
    if (fp == NULL) {
        goto fail;
    }

    rc = ib_list_create(&items, tmp_mm);
    assert(rc    == IB_OK);
    assert(items != NULL);

    for (;;) {
        char *buffer_copy;
        int   read = getline(&buffer, &buffer_size, fp);
        char *space = NULL;
        ib_num_t confidence = 0;
        sqli_fingerprint_entry_t *entry = ib_mm_alloc(tmp_mm, sizeof(*entry));

        if (read == -1) {
            if (! feof(fp)) {
                fclose(fp);
                goto fail;
            }
            else {
                break;
            }
        }
        while (buffer[read-1] == '\n' || buffer[read-1] == '\r') {
            buffer[read-1] = '\0';
            --read;
        }

        space = strstr(buffer, " ");
        if (space != NULL) {
            rc = ib_type_atoi(space + 1, 10, &confidence);
            if (rc != IB_OK || confidence > 100) {
                return IB_EINVAL;
            }
            *space = '\0';
        }

        buffer_copy = ib_mm_strdup(mm, buffer);
        assert(buffer_copy != NULL);

        entry->confidence = confidence;
        entry->fingerprint = buffer_copy;

        rc = ib_list_push(items, (void *)entry);
        assert(rc == IB_OK);
    }

    fclose(fp);

    ps = ib_mm_alloc(mm, sizeof(*ps));
    assert(ps != NULL);

    ps->num_fingerprints = ib_list_elements(items);
    ps->fingerprints =
        ib_mm_alloc(mm, ps->num_fingerprints * sizeof(*ps->fingerprints));
    assert(ps->fingerprints != NULL);

    i = 0;
    IB_LIST_LOOP(items, n) {
        const sqli_fingerprint_entry_t *entry =
            (const sqli_fingerprint_entry_t *)ib_list_node_data(n);
        ps->fingerprints[i] = *entry;
        ++i;
    }
    assert(i == ps->num_fingerprints);

    ib_mpool_lite_destroy(tmp);

    qsort(
        ps->fingerprints, ps->num_fingerprints,
        sizeof(*ps->fingerprints),
        &sqli_cmp
    );

    *out_ps = ps;

    return IB_OK;

fail:
    ib_mpool_lite_destroy(tmp);
    return IB_EINVAL;
}
Esempio n. 16
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");
        }
    }
Esempio n. 17
0
/*********************************
 * Helper Functions
 *********************************/
static
ib_status_t sqli_create_pattern_set_from_file(
    sqli_pattern_set_t **out_ps,
    const char         *path,
    ib_mpool_t         *mp
)
{
    assert(out_ps != NULL);
    assert(path   != NULL);
    assert(mp     != NULL);

    ib_status_t  rc;
    FILE               *fp          = NULL;
    char               *buffer      = NULL;
    size_t              buffer_size = 0;
    ib_list_t          *items       = NULL;
    ib_list_node_t     *n           = NULL;
    ib_mpool_t         *tmp         = NULL;
    sqli_pattern_set_t *ps          = NULL;
    size_t              i           = 0;

    /* Temporary memory pool for this function only. */
    rc = ib_mpool_create(&tmp, "sqli tmp", NULL);
    assert(rc == IB_OK);
    assert(tmp != NULL);

    fp = fopen(path, "r");
    if (fp == NULL) {
        goto fail;
    }

    rc = ib_list_create(&items, tmp);
    assert(rc    == IB_OK);
    assert(items != NULL);

    for (;;) {
        char *buffer_copy;
        int   read = getline(&buffer, &buffer_size, fp);

        if (read == -1) {
            if (! feof(fp)) {
                fclose(fp);
                goto fail;
            }
            else {
                break;
            }
        }

        buffer_copy = ib_mpool_memdup(mp, buffer, read);
        assert(buffer_copy != NULL);
        while (buffer_copy[read-1] == '\n' || buffer_copy[read-1] == '\r') {
            buffer_copy[read-1] = '\0';
            --read;
        }

        rc = ib_list_push(items, (void *)buffer_copy);
        assert(rc == IB_OK);
    }

    fclose(fp);

    ps = ib_mpool_alloc(mp, sizeof(*ps));
    assert(ps != NULL);

    ps->num_patterns = ib_list_elements(items);
    ps->patterns =
        ib_mpool_alloc(mp, ps->num_patterns * sizeof(*ps->patterns));
    assert(ps->patterns != NULL);

    i = 0;
    IB_LIST_LOOP(items, n) {
        ps->patterns[i] = ib_list_node_data(n);
        ++i;
    }
Esempio n. 18
0
/// @test Test util list library - ib_list_push() and ib_list_pop()
TEST_F(TestIBUtilList, test_list_push_and_pop)
{
    ib_list_t *list;
    ib_status_t rc;
    int v0 = 0;
    int v1 = 1;
    int v2 = 2;
    int v3 = 3;
    int v4 = 4;
    int *val;

    rc = ib_list_create(&list, MemPool());
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(list);
    ASSERT_EQ(0UL, ib_list_elements(list));

    /* Pop invalid. */
    rc = ib_list_pop(list,(void *)&val);
    ASSERT_EQ(IB_ENOENT, rc);
    ASSERT_FALSE(val);
    ASSERT_EQ(0UL, ib_list_elements(list));

    /* Simple pushes followed by pops. */
    rc = ib_list_push(list, &v0);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(1UL, ib_list_elements(list));
    rc = ib_list_push(list, &v1);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(2UL, ib_list_elements(list));
    rc = ib_list_push(list, &v2);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(3UL, ib_list_elements(list));
    rc = ib_list_push(list, &v3);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(4UL, ib_list_elements(list));
    rc = ib_list_push(list, &v4);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(5UL, ib_list_elements(list));
    ASSERT_EQ(v0, *(int *)(ib_list_node_data(ib_list_first(list))));
    ASSERT_EQ(v4, *(int *)(ib_list_node_data(ib_list_last(list))));
    rc = ib_list_pop(list, (void *)&val);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(val);
    ASSERT_EQ(v4, *val);
    ASSERT_EQ(4UL, ib_list_elements(list));
    rc = ib_list_pop(list, (void *)&val);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(val);
    ASSERT_EQ(v3, *val);
    ASSERT_EQ(3UL, ib_list_elements(list));
    rc = ib_list_pop(list, (void *)&val);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(val);
    ASSERT_EQ(v2, *val);
    ASSERT_EQ(2UL, ib_list_elements(list));
    rc = ib_list_pop(list, (void *)&val);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(val);
    ASSERT_EQ(v1, *val);
    ASSERT_EQ(1UL, ib_list_elements(list));
    rc = ib_list_pop(list, (void *)&val);
    ASSERT_EQ(IB_OK, rc);
    ASSERT_TRUE(val);
    ASSERT_EQ(v0, *val);
    ASSERT_EQ(0UL, ib_list_elements(list));
}
Esempio n. 19
0
/**
 * Constructs fail links of branches (the failure transition function)
 *
 * @param ac_tree the ac tree matcher
 *
 * @return ib_status_t status of the operation
 */
static ib_status_t ib_ac_link_fail_states(ib_ac_t *ac_tree)
{
    ib_status_t rc;

    ib_ac_state_t *child = NULL;
    ib_ac_state_t *state = NULL;
    ib_ac_state_t *goto_state = NULL;

    ib_list_t *iter_queue = NULL;

    if (ac_tree->flags & IB_AC_FLAG_PARSER_COMPILED) {
        return IB_OK;
    }

    ac_tree->root->pattern = 0;

    rc = ib_list_create(&iter_queue, ac_tree->mp);
    if (rc != IB_OK) {
        return rc;
    }

    ac_tree->root->fail = ac_tree->root;

    /* All first-level children will fail back to root state */
    for (child = ac_tree->root->child;
         child != NULL;
         child = child->sibling)
    {
        child->fail = ac_tree->root;
        rc = ib_list_enqueue(iter_queue, (void *) child);
        if (rc != IB_OK) {
            return rc;
        }
    }

    while (ib_list_elements(iter_queue) > 0) {
        rc = ib_list_dequeue(iter_queue, (void *) &state);
        if (rc != IB_OK) {
            return rc;
        }

        state->fail = ac_tree->root;

        if (state->parent != ac_tree->root) {
            goto_state = ib_ac_child_for_code(state->parent->fail,
                                             state->letter);
            if (goto_state != NULL) {
                state->fail = goto_state;
            }
        }

        for (child = state->child;
             child != NULL;
             child = child->sibling)
        {
            rc = ib_list_enqueue(iter_queue, (void *) child);
            if (rc != IB_OK) {
                return rc;
            }
        }
    }

    /* Link common outputs of subpatterns present in the branch*/
    ib_ac_link_outputs(ac_tree, ac_tree->root);

    /* Unlink invalid fail transitions. This guarantees that there will
     * be at least one letter with transition in each fail state*/
    ib_ac_unlink_unuseful(ac_tree, ac_tree->root);

    if (ac_tree->root->child != NULL) {
        ib_ac_build_bintree(ac_tree, ac_tree->root);
    }

    ac_tree->flags |= IB_AC_FLAG_PARSER_COMPILED;

    return IB_OK;
}
Esempio n. 20
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 (module)
 *
 * @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->var_store != NULL);
    assert(event == request_header_finished_event);
    assert(data != NULL);

    const ib_module_t *m = (const ib_module_t *)data;
    const ib_field_t  *req_agent = NULL;
    ib_status_t         rc = IB_OK;
    const ib_list_t *bs_list;
    const ib_bytestr_t *bs;
    const modua_config_t *cfg;

    rc = ib_context_module_config(ib_context_main(ib), m, &cfg);
    if (rc != IB_OK) {
        ib_log_error_tx(tx, "Can't fetch configuration: %s",
                        ib_status_to_string(rc));
        return rc;
    }

    /* Extract the User-Agent header field */
    rc = ib_var_target_get_const(
        cfg->user_agent,
        &bs_list,
        tx->mp,
        tx->var_store
    );
    if (rc == IB_ENOENT || ib_list_elements(bs_list) == 0) {
        ib_log_debug_tx(tx, "request_header_finished_event: No user agent");
        return IB_OK;
    }
    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;
}
Esempio n. 21
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;
}
/**
 * Handle managed collection: register for JSON file
 *
 * Examines the incoming parameters; if if it looks like a JSON file,
 * take it; otherwise do nothing (decline)
 *
 * @param[in] ib Engine
 * @param[in] module Collection manager's module object
 * @param[in] mp Memory pool to use for allocations
 * @param[in] collection_name Name of the collection
 * @param[in] uri Full collection URI
 * @param[in] uri_scheme URI scheme (unused)
 * @param[in] uri_data Hierarchical/data part of the URI (typically a path)
 * @param[in] params List of parameter strings
 * @param[in] register_data Selection callback data
 * @param[out] pmanager_inst_data Pointer to manager specific data
 *
 * @returns Status code:
 *   - IB_DECLINED Parameters not recognized
 *   - IB_OK All OK, parameters recognized
 *   - IB_Exxx Other error
 */
static ib_status_t core_managed_collection_jsonfile_register_fn(
    const ib_engine_t              *ib,
    const ib_module_t              *module,
    const ib_collection_manager_t  *manager,
    ib_mpool_t                     *mp,
    const char                     *collection_name,
    const char                     *uri,
    const char                     *uri_scheme,
    const char                     *uri_data,
    const ib_list_t                *params,
    void                           *register_data,
    void                          **pmanager_inst_data)
{
    assert(ib != NULL);
    assert(module != NULL);
    assert(mp != NULL);
    assert(collection_name != NULL);
    assert(params != NULL);
    assert(pmanager_inst_data != NULL);

    const ib_list_node_t *node;
    const char *path;
    const char *param;
    const char *path_start = uri_data;
    bool persist = false;
    core_json_file_t *json_file;

    /* Get the first element in the list */
    if (ib_list_elements(params) > 1) {
        return IB_EINVAL;
    }

    /* Look at the first param (if it exists) */
    node = ib_list_first_const(params);
    if (node != NULL) {
        param = (const char *)node->data;
        if (strcasecmp(param, "persist") == 0) {
            persist = true;
        }
        else {
            ib_log_warning(ib, "JSON file: \"%s\"; unknown parameter \"%s\"",
                           uri, param);
            return IB_EINVAL;
        }
    }

    /* Try to stat the file */
    if (!persist) {
        struct stat sbuf;
        if (stat(path_start, &sbuf) < 0) {
            ib_log_warning(ib,
                           "JSON file: Declining \"%s\"; "
                           "stat(\"%s\") failed: %s",
                           uri, path_start, strerror(errno));
            return IB_DECLINED;
        }
        if (! S_ISREG(sbuf.st_mode)) {
            ib_log_warning(ib,
                           "JSON file: Declining \"%s\"; \"%s\" is not a file",
                           uri, path_start);
            return IB_DECLINED;
        }
    }

    /* Happy now, copy the file name, be done */
    path = ib_mpool_strdup(mp, path_start);
    if (path == NULL) {
        return IB_EALLOC;
    }
    json_file = ib_mpool_alloc(mp, sizeof(*json_file));
    if (json_file == NULL) {
        return IB_EALLOC;
    }
    json_file->path    = path;
    json_file->persist = persist;

    /* Store the file object as the manager specific collection data */
    *pmanager_inst_data = json_file;

    return IB_OK;
}