Ejemplo n.º 1
0
TEST_F(TestIBUtilField, AliasBytestr)
{
    const char s1[] = "hello";
    const char s2[] = "bye";
    ib_field_t *f;
    const ib_bytestr_t *obs;
    ib_status_t rc;
    ib_bytestr_t *bs;
    uint8_t *copy;

    copy = (uint8_t *)ib_mm_strdup(MM(), "x");
    rc = ib_field_create_bytestr_alias(&f, MM(),
                                       IB_S2SL("foo"), copy, 0);
    ASSERT_EQ(IB_OK, rc);

    rc = ib_bytestr_dup_nulstr(&bs, MM(), s1);
    ASSERT_EQ(IB_OK, rc);
    rc = ib_field_setv(f, bs);
    ASSERT_EQ(IB_OK, rc);
    rc = ib_field_value(f, ib_ftype_bytestr_out(&obs));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(strlen(s1), ib_bytestr_length(obs));
    ASSERT_EQ(0, memcmp(s1,
                        ib_bytestr_const_ptr(obs), ib_bytestr_length(obs)) );

    rc = ib_bytestr_dup_nulstr(&bs, MM(), s2);
    ASSERT_EQ(IB_OK, rc);
    rc = ib_field_setv(f, bs);
    ASSERT_EQ(IB_OK, rc);
    rc = ib_field_value(f, ib_ftype_bytestr_out(&obs));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(strlen(s2), ib_bytestr_length(obs));
    ASSERT_EQ(0, memcmp(s2,
                        ib_bytestr_const_ptr(obs), ib_bytestr_length(obs)) );
}
Ejemplo n.º 2
0
static
ib_status_t core_vars_placeholder_bytestr(
    ib_var_store_t *store,
    const char     *name
)
{
    ib_status_t rc;
    ib_var_source_t *source;
    ib_field_t *f;

    rc = ib_var_source_acquire(
             &source,
             ib_var_store_pool(store),
             ib_var_store_config(store),
             name, strlen(name)
         );
    if (rc != IB_OK) {
        return rc;
    }

    rc = ib_field_create_bytestr_alias(
             &f,
             ib_var_store_pool(store),
             name, strlen(name),
             (uint8_t *)core_placeholder_value,
             sizeof(core_placeholder_value)
         );
    if (rc != IB_OK) {
        return rc;
    }

    rc = ib_var_source_set(
             source,
             store,
             f
         );
    return rc;
}
Ejemplo n.º 3
0
/**
 * String modification transformation core
 *
 * @param[in] mp Memory pool to use for allocations.
 * @param[in] str_fn NUL-terminated string transformation function
 * @param[in] ex_fn EX (string/length) transformation function
 * @param[in] fin Input field.
 * @param[out] fout Output field. This is NULL on error.
 *
 * @returns IB_OK if successful.
 */
static ib_status_t tfn_strmod(ib_mpool_t *mp,
                              ib_strmod_fn_t str_fn,
                              ib_strmod_ex_fn_t ex_fn,
                              const ib_field_t *fin,
                              const ib_field_t **fout)
{
    ib_status_t rc;
    ib_flags_t result;
    ib_field_t *fnew;

    assert(mp != NULL);
    assert(str_fn != NULL);
    assert(ex_fn != NULL);
    assert(fin != NULL);
    assert(fout != NULL);

    /* Initialize the output field pointer */
    *fout = NULL;

    switch(fin->type) {
    case IB_FTYPE_NULSTR :
    {
        const char *in;
        char *out;
        rc = ib_field_value(fin, ib_ftype_nulstr_out(&in));
        if (rc != IB_OK) {
            return rc;
        }
        if (in == NULL) {
            return IB_EINVAL;
        }
        rc = str_fn(IB_STROP_COW, mp, (char *)in, &out, &result);
        if (rc != IB_OK) {
            return rc;
        }
        rc = ib_field_create(&fnew, mp,
                             fin->name, fin->nlen,
                             IB_FTYPE_NULSTR,
                             ib_ftype_nulstr_in(out));
        if (rc != IB_OK) {
            return rc;
        }
        *fout = fnew;
        break;
    }

    case IB_FTYPE_BYTESTR:
    {
        const ib_bytestr_t *bs;
        const uint8_t *din;
        uint8_t *dout;
        size_t dlen;
        rc = ib_field_value(fin, ib_ftype_bytestr_out(&bs));
        if (rc != IB_OK) {
            return rc;
        }
        if (bs == NULL) {
            return IB_EINVAL;
        }
        din = ib_bytestr_const_ptr(bs);
        if (din == NULL) {
            return IB_EINVAL;
        }
        dlen = ib_bytestr_length(bs);
        rc = ex_fn(IB_STROP_COW, mp,
                   (uint8_t *)din, dlen,
                   &dout, &dlen,
                   &result);
        if (rc != IB_OK) {
            return rc;
        }
        rc = ib_field_create_bytestr_alias(&fnew, mp,
                                           fin->name, fin->nlen,
                                           dout, dlen);
        if (rc != IB_OK) {
            return rc;
        }
        *fout = fnew;
        break;
    }

    default:
        return IB_EINVAL;
    } /* switch(fin->type) */

    return IB_OK;
}
Ejemplo n.º 4
0
static ib_status_t foo2bar(ib_engine_t *ib,
                           ib_mpool_t *mp,
                           void *fndata,
                           const ib_field_t *fin,
                           const ib_field_t **fout,
                           ib_flags_t *pflags)
{
    ib_status_t rc = IB_OK;
    ib_field_t *fnew;

    if (fin->type == IB_FTYPE_BYTESTR) {
        const ib_bytestr_t *ibs;
        rc = ib_field_value(fin, ib_ftype_bytestr_out(&ibs));
        if (rc != IB_OK) {
            return rc;
        }

        const uint8_t *data_in;
        size_t dlen_in;
        uint8_t *data_out;

        assert (ibs != NULL);

        data_in = ib_bytestr_const_ptr(ibs);
        dlen_in = ib_bytestr_length(ibs);

        if ( (data_in != NULL) &&
             (dlen_in == 3) &&
             (strncmp("foo", (char *)data_in, 3) == 0) )
        {
            data_out = (uint8_t *)ib_mpool_alloc(mp, dlen_in);
            if (data_out == NULL) {
                return IB_EINVAL;
            }
            *pflags = (IB_TFN_FMODIFIED);
            *(data_out+0) = 'b';
            *(data_out+1) = 'a';
            *(data_out+2) = 'r';
        }
        else {
            data_out = (uint8_t *)data_in;
        }
        rc = ib_field_create_bytestr_alias(&fnew, mp,
                                           fin->name, fin->nlen,
                                           data_out, dlen_in);
        if (rc == IB_OK) {
            *fout = fnew;
        }
    }
    else if (fin->type == IB_FTYPE_NULSTR) {
        const char *in;
        char *out;

        rc = ib_field_value(fin, ib_ftype_nulstr_out(&in));
        if (rc != IB_OK) {
            return rc;
        }
        if ( (in != NULL) && (strncmp(in, "foo", 3) == 0) ) {
            out = (char *)ib_mpool_alloc(mp, strlen(in) + 1);
            if (out == NULL) {
                return IB_EINVAL;
            }

            *pflags = (IB_TFN_FMODIFIED);
            *(out+0) = 'b';
            *(out+1) = 'a';
            *(out+2) = 'r';
            *(out+3) = '\0';
        }
        else {
            out = (char *)in;
        }
        rc = ib_field_create(&fnew, mp, fin->name, fin->nlen,
                             IB_FTYPE_NULSTR, ib_ftype_nulstr_in(out));
        if (rc == IB_OK) {
            *fout = fnew;
        }
    }
    else {
        return IB_EINVAL;
    }

    return rc;
}
Ejemplo n.º 5
0
/**
 * String modification transformation core
 *
 * @param[in] ib IronBee engine
 * @param[in] mp Memory pool to use for allocations.
 * @param[in] fndata Function specific data.
 * @param[in] fin Input field.
 * @param[out] fout Output field.
 * @param[out] pflags Transformation flags.
 *
 * @returns IB_OK if successful.
 */
static ib_status_t tfn_strmod(ib_engine_t *ib,
                              ib_mpool_t *mp,
                              ib_strmod_fn_t str_fn,
                              ib_strmod_ex_fn_t ex_fn,
                              const ib_field_t *fin,
                              ib_field_t **fout,
                              ib_flags_t *pflags)
{
    IB_FTRACE_INIT();
    ib_status_t rc;
    ib_flags_t result;

    assert(ib != NULL);
    assert(mp != NULL);
    assert(str_fn != NULL);
    assert(ex_fn != NULL);
    assert(fin != NULL);
    assert(fout != NULL);
    assert(pflags != NULL);

    /* Initialize the output field pointer */
    *fout = NULL;

    switch(fin->type) {
    case IB_FTYPE_NULSTR :
    {
        const char *in;
        char *out;
        rc = ib_field_value(fin, ib_ftype_nulstr_out(&in));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        if (in == NULL) {
            IB_FTRACE_RET_STATUS(IB_EINVAL);
        }
        rc = str_fn(IB_STROP_COW, mp, (char *)in, &out, &result);
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        rc = ib_field_create(fout, mp,
                             fin->name, fin->nlen,
                             IB_FTYPE_NULSTR,
                             ib_ftype_nulstr_in(out));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        break;
    }

    case IB_FTYPE_BYTESTR:
    {
        const ib_bytestr_t *bs;
        const uint8_t *din;
        uint8_t *dout;
        size_t dlen;
        rc = ib_field_value(fin, ib_ftype_bytestr_out(&bs));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        if (bs == NULL) {
            IB_FTRACE_RET_STATUS(IB_EINVAL);
        }
        din = ib_bytestr_const_ptr(bs);
        if (din == NULL) {
            IB_FTRACE_RET_STATUS(IB_EINVAL);
        }
        dlen = ib_bytestr_length(bs);
        rc = ex_fn(IB_STROP_COW, mp,
                   (uint8_t *)din, dlen,
                   &dout, &dlen,
                   &result);
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        rc = ib_field_create_bytestr_alias(fout, mp,
                                           fin->name, fin->nlen,
                                           dout, dlen);
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        break;
    }
    default:
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    } /* switch(fin->type) */

    /* Check the flags */
    if (ib_flags_all(result, IB_STRFLAG_MODIFIED) == true) {
        *pflags = IB_TFN_FMODIFIED;
    }
    else {
        *pflags = IB_TFN_NONE;
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
static
ib_status_t sqli_op_execute(
    ib_tx_t *tx,
    const ib_field_t *field,
    ib_field_t *capture,
    ib_num_t *result,
    void *instance_data,
    void *cbdata
)
{
    assert(tx     != NULL);
    assert(field  != NULL);
    assert(result != NULL);

    const sqli_fingerprint_set_t *ps = (const sqli_fingerprint_set_t *)instance_data;
    sfilter                   sf;
    ib_bytestr_t             *bs;
    ib_status_t               rc;
    sqli_callback_data_t      callback_data;

    *result = 0;

    /* Currently only bytestring types are supported.
     * Other types will just get passed through. */
    if (field->type != IB_FTYPE_BYTESTR) {
        return IB_OK;
    }

    rc = ib_field_value(field, ib_ftype_bytestr_mutable_out(&bs));
    if (rc != IB_OK) {
        return rc;
    }

    /* Run through libinjection. */
    libinjection_sqli_init(
        &sf,
        (const char *)ib_bytestr_const_ptr(bs),
        ib_bytestr_length(bs),
        FLAG_NONE
    );
    callback_data.confidence = 0;
    callback_data.fingerprint_set = NULL;
    if (ps != NULL) {
        callback_data.fingerprint_set = ps;
        libinjection_sqli_callback(&sf, sqli_lookup_word, (void *)&callback_data);
    }
    if (libinjection_is_sqli(&sf)) {
        ib_log_debug_tx(tx, "Matched SQLi fingerprint: %s", sf.fingerprint);
        *result = 1;
    }
    if (*result == 1 && capture != NULL) {
        {
            ib_field_t *fingerprint_field;
            size_t fingerprint_length = strlen(sf.fingerprint);
            const uint8_t *fingerprint;

            fingerprint = ib_mm_memdup(
                tx->mm,
                sf.fingerprint, fingerprint_length
            );
            if (fingerprint == NULL) {
                return IB_EALLOC;
            }

            rc = ib_field_create_bytestr_alias(
                &fingerprint_field,
                tx->mm,
                IB_S2SL("fingerprint"),
                fingerprint, fingerprint_length
            );
            if (rc != IB_OK) {
                return rc;
            }

            rc = ib_field_list_add(capture, fingerprint_field);
            if (rc != IB_OK) {
                return rc;
            }
        }

        {
            ib_field_t *confidence_field;

            rc = ib_field_create(
                &confidence_field,
                tx->mm,
                IB_S2SL("confidence"),
                IB_FTYPE_NUM,
                ib_ftype_num_in(&callback_data.confidence)
            );
            if (rc != IB_OK) {
                return rc;
            }

            rc = ib_field_list_add(capture, confidence_field);
            if (rc != IB_OK) {
                return rc;
            }
        }
    }

    return IB_OK;
}