Example #1
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;
}
Example #2
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;
}
Example #3
0
/**
 * Length transformation
 *
 * @param[in] mp Memory pool to use for allocations.
 * @param[in] fin Input field.
 * @param[out] fout Output field. This is NULL on error.
 * @param[in] fndata Callback data
 *
 * @returns IB_OK if successful.
 */
static ib_status_t tfn_length(ib_mpool_t *mp,
                              const ib_field_t *fin,
                              const ib_field_t **fout,
                              void *fndata)
{
    assert(mp != NULL);
    assert(fin != NULL);
    assert(fout != NULL);

    ib_status_t rc = IB_OK;
    ib_field_t *fnew;

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

    /**
     * This works on C-style (NUL terminated) and byte strings.  Note
     * that data is assumed to be a NUL terminated string (because our
     * configuration parser can't produce anything else).
     **/
    if (fin->type == IB_FTYPE_NULSTR) {
        const char *fval;
        rc = ib_field_value(fin, ib_ftype_nulstr_out(&fval));
        if (rc != IB_OK) {
            return rc;
        }

        const ib_num_t len = strlen(fval);
        rc = ib_field_create(
            &fnew, mp,
            IB_FIELD_NAME("Length"),
            IB_FTYPE_NUM,
            ib_ftype_num_in(&len)
        );
    }
    else if (fin->type == IB_FTYPE_BYTESTR) {
        const ib_bytestr_t *value;
        rc = ib_field_value(fin, ib_ftype_bytestr_out(&value));
        if (rc != IB_OK) {
            return rc;
        }

        const ib_num_t len = ib_bytestr_length(value);
        rc = ib_field_create(
            &fnew, mp,
            IB_FIELD_NAME("Length"),
            IB_FTYPE_NUM,
            ib_ftype_num_in(&len)
        );
    }
    else if (fin->type == IB_FTYPE_LIST) {
        const ib_list_node_t  *node = NULL;
        const ib_list_t       *ilist;        /** Incoming list */

        /* Get the incoming list */
        // @todo Remove mutable once list is const correct.
        rc = ib_field_value(fin, ib_ftype_list_out(&ilist));
        if (rc != IB_OK) {
            return rc;
        }

        if (ilist == NULL) {
            return IB_EUNKNOWN;
        }

        /* Create the outgoing list field */
        rc = ib_field_create(
            &fnew, mp,
            IB_FIELD_NAME("Length"),
            IB_FTYPE_LIST, NULL
        );
        if (rc != IB_OK) {
            return rc;
        }

        /* Walk through the incoming fields */
        IB_LIST_LOOP_CONST(ilist, node) {
            const ib_field_t *ifield = (ib_field_t *)node->data;
            const ib_field_t *ofield = NULL;

            rc = tfn_length(mp, ifield, &ofield, NULL);
            if (rc != IB_OK) {
                return rc;
            }
            rc = ib_field_list_add_const(fnew, ofield);
            if (rc != IB_OK) {
                return rc;
            }
        }
    }
    else {
Example #4
0
const char *ib_field_format(
    const ib_field_t  *field,
    bool               quote,
    bool               escape,
    const char       **type_name,
    char              *buf,
    size_t             bufsize
)
{
    ib_status_t rc;
    const char *tname = NULL;

    assert(buf != NULL);
    assert(bufsize > 0);

    *buf = '\0';
    if (field == NULL) {
        tname = "NULL";
        if (quote) {
            strncpy(buf, "\"\"", bufsize-1);
            *(buf+bufsize) = '\0';
        }
        else {
            *buf = '\0';
        }
    }
    else {
        switch (field->type) {

        case IB_FTYPE_NULSTR :
        {
            const char *s;
            tname = "NULSTR";
            rc = ib_field_value(field, ib_ftype_nulstr_out(&s));
            if (rc != IB_OK) {
                break;
            }
            if (escape) {
                ib_string_escape_json_buf(s, quote, buf, bufsize, NULL, NULL);
            }
            else if (quote) {
                snprintf(buf, bufsize, "\"%s\"", (s?s:""));
            }
            else {
                strncpy(buf, s, bufsize-1);
                *(buf+bufsize-1) = '\0';
            }
            break;
        }

        case IB_FTYPE_BYTESTR:
        {
            const ib_bytestr_t *bs;

            tname = "BYTESTR";
            rc = ib_field_value(field, ib_ftype_bytestr_out(&bs));
            if (rc != IB_OK) {
                break;
            }

            if (escape) {
                ib_string_escape_json_buf_ex(ib_bytestr_const_ptr(bs),
                                             ib_bytestr_length(bs),
                                             true,
                                             quote,
                                             buf, bufsize, NULL,
                                             NULL);
            }
            else if (quote) {
                snprintf(buf, bufsize, "\"%.*s\"",
                         (int)ib_bytestr_length(bs),
                         (const char *)ib_bytestr_const_ptr(bs));
            }
            else {
                size_t len = ib_bytestr_length(bs);
                if (len > (bufsize - 1) ) {
                    len = bufsize - 1;
                }
                strncpy(buf, (const char *)ib_bytestr_const_ptr(bs), len);
                *(buf+len) = '\0';
            }
            break;
        }

        case IB_FTYPE_NUM :          /**< Numeric value */
        {
            ib_num_t n;
            tname = "NUM";
            rc = ib_field_value(field, ib_ftype_num_out(&n));
            if (rc != IB_OK) {
                break;
            }
            snprintf(buf, bufsize, "%"PRId64, n);
            break;
        }

        case IB_FTYPE_FLOAT :        /**< Float numeric value */
        {
            ib_float_t f;
            tname = "FLOAT";
            rc = ib_field_value(field, ib_ftype_float_out(&f));
            if (rc != IB_OK) {
                break;
            }
            snprintf(buf, bufsize, "%Lf", f);
            break;
        }

        case IB_FTYPE_LIST :         /**< List */
        {
            const ib_list_t *lst;
            size_t len;

            tname = "LIST";
            rc = ib_field_value(field, ib_ftype_list_out(&lst));
            if (rc != IB_OK) {
                break;
            }
            len = IB_LIST_ELEMENTS(lst);
            if (len == 0) {
                snprintf(buf, bufsize, "list[%zd]", len);
            }
            else {
                const ib_list_node_t *node;
                node = ib_list_last_const(lst);
                if (node == NULL) {
                    snprintf(buf, bufsize, "list[%zd]", len);
                }
                else {
                    ib_field_format((const ib_field_t *)node->data,
                                    quote, escape,
                                    &tname, buf, bufsize);
                }
            }
            break;
        }

        default:
            tname = buf;
            snprintf(buf, bufsize, "type = %d", field->type);
            break;
        }
    }

    /* Store the type name */
    if (type_name != NULL) {
        *type_name = tname;
    }

    /* Return the buffer */
    return buf;
}
Example #5
0
ib_status_t ib_tfn_execute(
    ib_mpool_t        *mp,
    const ib_tfn_t    *tfn,
    const ib_field_t  *fin,
    const ib_field_t **fout
)
{
    assert(mp   != NULL);
    assert(tfn  != NULL);
    assert(fin  != NULL);
    assert(fout != NULL);

    ib_status_t       rc;
    const ib_field_t *out = NULL;

    if (fin->type == IB_FTYPE_LIST && ! ib_tfn_handle_list(tfn)) {
        /* Unroll list */
        const ib_list_t *value_list;
        const ib_list_node_t *node;
        ib_list_t *out_list;
        ib_field_t *fnew;

        rc = ib_field_value(fin, ib_ftype_list_out(&value_list));
        if (rc != IB_OK) {
            return rc;
        }

        rc = ib_list_create(&out_list, mp);
        if (rc != IB_OK) {
            return rc;
        }

        IB_LIST_LOOP_CONST(value_list, node) {
            const ib_field_t *in;
            const ib_field_t *tfn_out;

            in = (const ib_field_t *)ib_list_node_data_const(node);
            assert(in != NULL);

            rc = ib_tfn_execute(mp, tfn, in, &tfn_out);
            if (rc != IB_OK) {
                return rc;
            }
            if (tfn_out == NULL) {
                return IB_EINVAL;
            }

            rc = ib_list_push(out_list, (void *)tfn_out);
            if (rc != IB_OK) {
                return rc;
            }
        }

        /* Finally, create the output field (list) and return it */
        rc = ib_field_create(&fnew, mp,
                             fin->name, fin->nlen,
                             IB_FTYPE_LIST, ib_ftype_list_in(out_list));
        if (rc != IB_OK) {
            return rc;
        }
        out = fnew;
    }
    else {
Example #6
0
void ib_field_util_log_debug(
    const char       *prefix,
    const ib_field_t *f
)
{
    assert(prefix != NULL);
    assert(f != NULL);

    ib_status_t rc;

    if (ib_util_get_log_level() < IB_LOG_DEBUG) {
        return;
    }

    if (ib_field_is_dynamic(f)) {
        ib_util_log_debug(
            "%s is dynamic: fn_get=%p cbdata_get=%p fn_set=%p cbdata_set=%p",

          prefix,
            f->val->fn_get, f->val->cbdata_get,
            f->val->fn_set, f->val->cbdata_set
        );
    }

    ib_util_log_debug("%s name=%.*s type=%d",
                      prefix, (int)f->nlen, f->name, f->type
    );

    if (ib_field_is_dynamic(f)) {
        return;
    }

    assert(f->val->pval);

    if (*(void **)(f->val->pval) == NULL) {
        ib_util_log_debug(
            "%s has no value.",
            prefix
        );
    }
    else {
        switch (f->type) {
        case IB_FTYPE_GENERIC:
        {
            void *v;
            rc = ib_field_value(f, ib_ftype_generic_out(&v));
            if (rc == IB_OK) {
                ib_util_log_debug("%s value=%p", prefix, v);
            }
            break;
        }
        case IB_FTYPE_NUM:
        {
            ib_num_t v;
            rc = ib_field_value(f, ib_ftype_num_out(&v));
            if (rc == IB_OK) {
                ib_util_log_debug("%s value=%"PRId64, prefix, v);
            }
            break;
        }
        case IB_FTYPE_FLOAT:
        {
            ib_float_t v;
            rc = ib_field_value(f, ib_ftype_float_out(&v));
            if (rc == IB_OK) {
                ib_util_log_debug("%s value=%Lf", prefix, v);
            }
            break;
        }
        case IB_FTYPE_NULSTR:
        {
            const char *v;
            rc = ib_field_value(f, ib_ftype_nulstr_out(&v));
            if (rc == IB_OK) {
                ib_util_log_debug("%s value=%s", prefix, v);
            }
            break;
        }
        case IB_FTYPE_BYTESTR:
        {
            const ib_bytestr_t *v;
            rc = ib_field_value(f, ib_ftype_bytestr_out(&v));
            if (rc == IB_OK) {
                ib_util_log_debug("%s value=%" IB_BYTESTR_FMT,
                                  prefix, IB_BYTESTR_FMT_PARAM(v));
            }
            break;
        }
        case IB_FTYPE_LIST:
        {
            const ib_list_t* v;
            rc = ib_field_value(f, ib_ftype_list_out(&v));
            if (rc == IB_OK) {
                ib_util_log_debug("%s &value=%p", prefix, v);
            }
            break;
        }
        case IB_FTYPE_SBUFFER:
        {
            const ib_stream_t* v;
            rc = ib_field_value(f, ib_ftype_sbuffer_out(&v));
            if (rc == IB_OK) {
                ib_util_log_debug("%s &value=%p", prefix, v);
            }
            break;
        }
        default:
            ib_util_log_debug("%s Unknown field type: %u",
                              prefix, f->type
            );
        }
    }
}
Example #7
0
/**
 * Join a field with strings before and after it
 *
 * @param[in] mp Memory pool
 * @param[in] f Field to join
 * @param[in] iptr Pointer to initial string
 * @param[in] ilen Length of @a iptr
 * @param[in] fptr Pointer to final string
 * @param[in] flen Length of @a fptr
 * @param[in] nul true if NUL byte should be tacked on, false if not
 * @param[out] out Pointer to output block
 * @param[out] olen Length of the output block
 *
 * @returns status code
 */
static ib_status_t join_parts(ib_mpool_t *mp,
                              const ib_field_t *f,
                              const char *iptr,
                              size_t ilen,
                              const char *fptr,
                              size_t flen,
                              bool nul,
                              char **out,
                              size_t *olen)
{
    IB_FTRACE_INIT();
    ib_status_t rc;
    char numbuf[NUM_BUF_LEN+1]; /* Buffer used to convert number to str */
    assert(NUM_BUF_LEN <= 256);

    switch(f->type) {
    case IB_FTYPE_NULSTR:
    {
        /* Field is a NUL-terminated string */
        const char *s;
        rc = ib_field_value(f, ib_ftype_nulstr_out(&s));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        size_t slen = strlen(s);
        rc = join3(mp,
                   iptr, ilen,
                   s, slen,
                   fptr, flen,
                   nul,
                   out, olen);
        break;
    }

    case IB_FTYPE_BYTESTR:
    {
        /* Field is a byte string */
        const ib_bytestr_t *bs;
        rc = ib_field_value(f, ib_ftype_bytestr_out(&bs));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        rc = join3(mp,
                   iptr, ilen,
                   (const char *)ib_bytestr_const_ptr(bs),
                   ib_bytestr_length(bs),
                   fptr, flen,
                   nul,
                   out, olen);
        break;
    }

    case IB_FTYPE_NUM:
    {
        /* Field is a number; convert it to a string */
        ib_num_t n;
        rc = ib_field_value(f, ib_ftype_num_out(&n));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        snprintf(numbuf, NUM_BUF_LEN, "%"PRId64, n);
        rc = join3(mp,
                   iptr, ilen,
                   numbuf, strlen(numbuf),
                   fptr, flen,
                   nul,
                   out, olen);
        break;
    }

    case IB_FTYPE_UNUM:
    {
        /* Field is an unsigned number; convert it to a string */
        ib_unum_t n;
        rc = ib_field_value(f, ib_ftype_unum_out(&n));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        snprintf(numbuf, NUM_BUF_LEN, "%"PRIu64, n);
        rc = join3(mp,
                   iptr, ilen,
                   numbuf, strlen(numbuf),
                   fptr, flen,
                   nul,
                   out, olen);
        break;
    }

    case IB_FTYPE_LIST:
    {
        /* Field is a list: use the first element in the list */
        const ib_list_t *list;
        const ib_list_node_t *node;
        const ib_field_t *element;

        rc = ib_field_value(f, ib_ftype_list_out(&list));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }

        node = ib_list_first_const(list);
        if (node == NULL) {
            rc = join2(mp, iptr, ilen, fptr, flen, nul, out, olen);
            break;
        }

        element = (const ib_field_t *)ib_list_node_data_const(node);
        rc = join_parts(mp, element, iptr, ilen, fptr, flen, nul, out, olen);
        break;
    }

    default:
        /* Something else: replace with "" */
        rc = join2(mp, iptr, ilen, fptr, flen, nul, out, olen);
        break;
    }

    IB_FTRACE_RET_STATUS(rc);
}
Example #8
0
/**
 * Length transformation
 *
 * @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_length(ib_engine_t *ib,
                              ib_mpool_t *mp,
                              void *fndata,
                              const ib_field_t *fin,
                              ib_field_t **fout,
                              ib_flags_t *pflags)
{
    IB_FTRACE_INIT();
    ib_status_t rc = IB_OK;

    assert(mp != NULL);
    assert(fin != NULL);
    assert(fout != NULL);
    assert(pflags != NULL);

    /**
     * This works on C-style (NUL terminated) and byte strings.  Note
     * that data is assumed to be a NUL terminated string (because our
     * configuration parser can't produce anything else).
     **/
    if (fin->type == IB_FTYPE_NULSTR) {
        const char *fval;
        rc = ib_field_value(fin, ib_ftype_nulstr_out(&fval));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }

        const ib_unum_t len = strlen(fval);
        rc = ib_field_create(
            fout, mp,
            IB_FIELD_NAME("Length"),
            IB_FTYPE_UNUM,
            ib_ftype_unum_in(&len)
        );
    }
    else if (fin->type == IB_FTYPE_BYTESTR) {
        const ib_bytestr_t *value;
        rc = ib_field_value(fin, ib_ftype_bytestr_out(&value));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }

        const ib_unum_t len = ib_bytestr_length(value);
        rc = ib_field_create(
            fout, mp,
            IB_FIELD_NAME("Length"),
            IB_FTYPE_UNUM,
            ib_ftype_unum_in(&len)
        );
    }
    else if (fin->type == IB_FTYPE_LIST) {
        const ib_list_node_t  *node = NULL;
        const ib_list_t       *ilist;        /** Incoming list */

        /* Get the incoming list */
        // @todo Remove mutable once list is const correct.
        rc = ib_field_value(fin, ib_ftype_list_out(&ilist));
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }

        if (ilist == NULL) {
            IB_FTRACE_RET_STATUS(IB_EUNKNOWN);
        }

        /* Create the outgoing list field */
        rc = ib_field_create(
            fout, mp,
            IB_FIELD_NAME("Length"),
            IB_FTYPE_LIST, NULL
        );
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }

        /* Walk through the incoming fields */
        IB_LIST_LOOP_CONST(ilist, node) {
            const ib_field_t *ifield = (ib_field_t *)node->data;
            ib_field_t *ofield = NULL;
            ib_flags_t flags = 0;

            rc = tfn_length(ib, mp, NULL, ifield, &ofield, &flags);
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
            rc = ib_field_list_add(*fout, ofield);
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else {
Example #9
0
/**
 * JSON YAJL encode: Encode a list
 *
 * @param[in,out] handle YAJL generator handle
 * @param[in] name Name of @a list (or NULL)
 * @param[in] nlen Length of @a name
 * @param[in] list IronBee list to encode
 *
 * @returns IronBee status code
 */
static ib_status_t encode_list(
    yajl_gen         handle,
    const char      *name,
    size_t           nlen,
    const ib_list_t *list)
{
    ib_status_t           rc = IB_OK;
    const ib_list_node_t *node;
    yajl_gen_status       status;
    int                   errors = 0;

    /* Encode the name */
    if ( (name != NULL) && (nlen != 0) ) {
        status = yajl_gen_string(handle, (const unsigned char *)name, nlen);
        if (status != yajl_gen_status_ok) {
            return IB_EUNKNOWN;
        }
    }

    /* Encode the map start */
    status = yajl_gen_map_open(handle);
    if (status != yajl_gen_status_ok) {
        return IB_EUNKNOWN;
    }

    IB_LIST_LOOP_CONST(list, node) {
        const ib_field_t *field = (const ib_field_t *)node->data;
        ib_status_t       tmprc;

        status = yajl_gen_string(handle,
                                 (const unsigned char *)field->name,
                                 field->nlen);
        if (status != yajl_gen_status_ok) {
            rc = IB_EUNKNOWN;
            ++errors;
            continue;
        }

        switch(field->type) {
        case IB_FTYPE_LIST:
        {
            const ib_list_t *list2;
            tmprc = ib_field_value(field, ib_ftype_list_out(&list2));
            if ( (tmprc != IB_OK) && (rc == IB_OK) ) {
                rc = tmprc;
                ++errors;
            }
            else {
                tmprc = encode_list(handle, NULL, 0, list2);
                if ( (tmprc != IB_OK) && (rc == IB_OK) ) {
                    rc = tmprc;
                    ++errors;
                }
            }
            break;
        }

        case IB_FTYPE_NUM:
        {
            ib_num_t num;
            tmprc = ib_field_value(field, ib_ftype_num_out(&num));
            if ( (tmprc != IB_OK) && (rc == IB_OK) ) {
                rc = tmprc;
                ++errors;
            }
            else {
                status = yajl_gen_integer(handle, num);
                if (status != yajl_gen_status_ok) {
                    if (rc != IB_OK) {
                        rc = IB_EUNKNOWN;
                    }
                    ++errors;
                }
            }
            break;
        }

        case IB_FTYPE_FLOAT:
        {
            ib_float_t fnum;
            tmprc = ib_field_value(field, ib_ftype_float_out(&fnum));
            if ( (tmprc != IB_OK) && (rc == IB_OK) ) {
                rc = tmprc;
                ++errors;
            }
            else {
                char buf[float_buf_size+1];
                snprintf(buf, float_buf_size, "%#.8Lg", fnum);
                status = yajl_gen_number(handle, buf, strlen(buf));
                if (status != yajl_gen_status_ok) {
                    if (rc != IB_OK) {
                        rc = IB_EUNKNOWN;
                    }
                    ++errors;
                }
            }
            break;
        }

        case IB_FTYPE_NULSTR:
        {
            const char *str;
            tmprc = ib_field_value(field, ib_ftype_nulstr_out(&str));
            if ( (tmprc != IB_OK) && (rc == IB_OK) ) {
                rc = tmprc;
                ++errors;
            }
            else {
                status = yajl_gen_string(handle,
                                         (unsigned char *)str,
                                         strlen(str));
                if (status != yajl_gen_status_ok) {
                    if (rc != IB_OK) {
                        rc = IB_EUNKNOWN;
                    }
                    ++errors;
                }
            }
            break;
        }

        case IB_FTYPE_BYTESTR:
        {
            const ib_bytestr_t *bs;
            tmprc = ib_field_value(field, ib_ftype_bytestr_out(&bs));
            if ( (tmprc != IB_OK) && (rc == IB_OK) ) {
                rc = tmprc;
                ++errors;
            }
            else {
                status = yajl_gen_string(handle,
                                         ib_bytestr_const_ptr(bs),
                                         ib_bytestr_length(bs));
                if (status != yajl_gen_status_ok) {
                    if (rc != IB_OK) {
                        rc = IB_EUNKNOWN;
                    }
                    ++errors;
                }
            }
            break;
        }

        default: /* Just ignore it */
            break;

        } /* switch(f->type) */
    }

    /* Encode the map end */
    status = yajl_gen_map_close(handle);
    if (status != yajl_gen_status_ok) {
        return IB_EUNKNOWN;
    }

    return IB_OK;
}
Example #10
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;
        }
    }