コード例 #1
0
ファイル: logger.c プロジェクト: nickleroy/ironbee
ib_status_t DLL_PUBLIC ib_logevent_create(ib_logevent_t **ple,
                                          ib_mpool_t *pool,
                                          const char *rule_id,
                                          ib_logevent_type_t type,
                                          ib_logevent_action_t rec_action,
                                          ib_logevent_action_t action,
                                          uint8_t confidence,
                                          uint8_t severity,
                                          const char *fmt,
                                          ...)
{
    IB_FTRACE_INIT();

    /*
     * Defined so that size_t to int cast is avoided
     * checking the result of vsnprintf below.
     * NOTE: This is assumed >3 bytes and should not
     *       be overly large as it is used as the size
     *       of a stack buffer.
     */
#define IB_LEVENT_MSG_BUF_SIZE 1024

    char buf[IB_LEVENT_MSG_BUF_SIZE];
    va_list ap;

    *ple = (ib_logevent_t *)ib_mpool_calloc(pool, 1, sizeof(**ple));
    if (*ple == NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    (*ple)->event_id = (uint32_t)ib_clock_get_time(); /* truncated */
    (*ple)->mp = pool;
    (*ple)->rule_id = ib_mpool_strdup(pool, rule_id);
    (*ple)->type = type;
    (*ple)->rec_action = rec_action;
    (*ple)->action = action;
    (*ple)->confidence = confidence;
    (*ple)->severity = severity;

    /*
     * Generate the message, replacing the last three characters
     * with "..." if truncation is required.
     */
    va_start(ap, fmt);
    if (vsnprintf(buf, IB_LEVENT_MSG_BUF_SIZE, fmt, ap) >= IB_LEVENT_MSG_BUF_SIZE) {
        memcpy(buf + (IB_LEVENT_MSG_BUF_SIZE - 3), "...", 3);
    }
    va_end(ap);

    /* Copy the formatted message. */
    (*ple)->msg = ib_mpool_strdup(pool, buf);

    IB_FTRACE_RET_STATUS(IB_OK);
}
コード例 #2
0
ファイル: transformation.c プロジェクト: niubl/ironbee
ib_status_t ib_tfn_create(
    const ib_tfn_t **ptfn,
    ib_mpool_t      *mp,
    const char      *name,
    bool             handle_list,
    ib_tfn_fn_t      fn_execute,
    void            *cbdata
)
{
    assert(ptfn       != NULL);
    assert(mp         != NULL);
    assert(name       != NULL);
    assert(fn_execute != NULL);

    ib_tfn_t *tfn;
    char *name_copy;

    name_copy = ib_mpool_strdup(mp, name);
    if (name_copy == NULL) {
        return IB_EALLOC;
    }

    tfn = (ib_tfn_t *)ib_mpool_alloc(mp, sizeof(*tfn));
    if (tfn == NULL) {
        return IB_EALLOC;
    }
    tfn->name        = name_copy;
    tfn->fn_execute  = fn_execute;
    tfn->handle_list = handle_list;
    tfn->cbdata      = cbdata;

    *ptfn = tfn;

    return IB_OK;
}
コード例 #3
0
ファイル: strlower.c プロジェクト: moon2l/ironbee
/* ASCII lowercase function (string version); See string.h */
ib_status_t ib_strlower(ib_strop_t op,
                        ib_mpool_t *mp,
                        char *str_in,
                        char **str_out,
                        ib_flags_t *result)
{
    IB_FTRACE_INIT();
    size_t len;
    ib_status_t rc = IB_OK;
    char *out = NULL;

    assert(mp != NULL);
    assert(str_in != NULL);
    assert(str_out != NULL);
    assert(result != NULL);

    len = strlen(str_in);
    switch(op) {
    case IB_STROP_INPLACE:
        out = str_in;
        rc = inplace(IB_STRFLAG_ALIAS, (uint8_t*)str_in, len, result);
        break;

    case IB_STROP_COPY:
        out = ib_mpool_strdup(mp, str_in);
        if (out == NULL) {
            IB_FTRACE_RET_STATUS(IB_EALLOC);
        }
        rc = inplace(IB_STRFLAG_NEWBUF, (uint8_t*)out, len, result);
        break;

    case IB_STROP_COW:
    {
#if ((__GNUC__==4) && (__GNUC_MINOR__<3))
        uint8_t *uint8ptr;
        rc = copy_on_write(mp,
                           (uint8_t *)str_in, len+1,
                           &uint8ptr, &len, result);
        out = (char *)uint8ptr;
#else
        rc = copy_on_write(mp,
                           (uint8_t *)str_in, len+1,
                           (uint8_t **)&out, &len, result);
#endif
        break;
    }

    default:
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    if (rc == IB_OK) {
        if (ib_flags_all(*result, IB_STRFLAG_MODIFIED)) {
            *(out+len) = '\0';
        }
        *str_out = out;
    }
    IB_FTRACE_RET_STATUS(rc);
}
コード例 #4
0
ファイル: action.c プロジェクト: niubl/ironbee
ib_status_t ib_action_inst_create_ex(
    ib_engine_t *ib,
    const char *name,
    const char *parameters,
    ib_action_inst_t **act_inst)
{
    assert(ib != NULL);
    assert(name != NULL);

    ib_hash_t *action_hash = ib->actions;
    ib_action_t *action;
    ib_status_t rc;
    ib_mpool_t *mpool = ib_engine_pool_main_get(ib);

    assert(mpool != NULL);

    rc = ib_hash_get(action_hash, &action, name);
    if (rc != IB_OK) {
        /* name is not registered */
        return rc;
    }

    *act_inst = (ib_action_inst_t *)ib_mpool_alloc(mpool,
                                                   sizeof(ib_action_inst_t));
    if (*act_inst == NULL) {
        return IB_EALLOC;
    }
    (*act_inst)->action = action;
    (*act_inst)->params = ib_mpool_strdup(mpool, parameters);
    (*act_inst)->fparam = NULL;

    if (action->fn_create != NULL) {
        rc = action->fn_create(
            ib,
            parameters,
            *act_inst,
            action->cbdata_create
        );
        if (rc != IB_OK) {
            return rc;
        }
    }
    else {
        rc = IB_OK;
    }

    if ((*act_inst)->fparam == NULL) {
        rc = ib_field_create(&((*act_inst)->fparam),
                             mpool,
                             IB_FIELD_NAME("param"),
                             IB_FTYPE_NULSTR,
                             ib_ftype_nulstr_in(parameters));
    }

    return rc;
}
コード例 #5
0
ファイル: logger.c プロジェクト: niq/ironbee
/// @todo Change this to _ex function with all fields and only use
///       the required fields here.
ib_status_t ib_logevent_create(ib_logevent_t **ple,
                               ib_mpool_t *pool,
                               const char *rule_id,
                               ib_logevent_type_t type,
                               ib_logevent_activity_t activity,
                               ib_logevent_pri_class_t pri_class,
                               ib_logevent_sec_class_t sec_class,
                               ib_logevent_sys_env_t sys_env,
                               ib_logevent_action_t rec_action,
                               ib_logevent_action_t action,
                               uint8_t confidence,
                               uint8_t severity,
                               const char *fmt,
                               ...)
{
    IB_FTRACE_INIT(ib_logevent_create);
    char buf[8192];
    struct timeval tv;
    va_list ap;

    *ple = (ib_logevent_t *)ib_mpool_calloc(pool, 1, sizeof(**ple));
    if (*ple == NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    /// @todo Need a true unique id generator
    gettimeofday(&tv, NULL);
    (*ple)->event_id = (tv.tv_sec << (32-8)) + tv.tv_usec;

    /// @todo Generate the remaining portions of the event

    (*ple)->mp = pool;
    (*ple)->rule_id = rule_id;
    (*ple)->type = type;
    (*ple)->activity = activity;
    (*ple)->pri_class = pri_class;
    (*ple)->sec_class = sec_class;
    (*ple)->sys_env = sys_env;
    (*ple)->rec_action = rec_action;
    (*ple)->action = action;
    (*ple)->confidence = confidence;
    (*ple)->severity = severity;

    va_start(ap, fmt);
    if (vsnprintf(buf, sizeof(buf), fmt, ap) >= (int)sizeof(buf)) {
        strcpy(buf, "<msg too long>");
    }
    va_end(ap);

    /* Copy the formatted message. */
    (*ple)->msg = ib_mpool_strdup(pool, buf);

    IB_FTRACE_RET_STATUS(IB_OK);
}
コード例 #6
0
ファイル: test_action.cpp プロジェクト: aburan28/ironbee
static ib_status_t create_fn(ib_engine_t *ib,
                             ib_context_t *ctx,
                             ib_mpool_t *mp,
                             const char *params,
                             ib_action_inst_t *inst,
                             void *cbdata)
{
    if (strcmp(params, "INVALID") == 0) {
        return IB_EINVAL;
    }
    inst->data = ib_mpool_strdup(mp, params);
    return IB_OK;
}
コード例 #7
0
TEST_F(TestIronBeeModuleRulesLua, operator_test)
{
    const ib_operator_t *op;
    void *instance_data;
    ib_num_t result;

    ib_field_t* field1;

    const char* op_name = "test_module_rules_lua.lua";
    const char* rule_name = "luarule001";

    char* str1 = (char *)ib_mpool_strdup(ib_engine->mp, "string 1");
    ASSERT_TRUE(str1);

    // Create field 1.
    ASSERT_EQ(IB_OK,
        ib_field_create(
            &field1,
            ib_engine->mp,
            IB_FIELD_NAME("field1"),
            IB_FTYPE_NULSTR,
            ib_ftype_nulstr_in(str1)
        )
    );

    /* Configure the operator. */
    configureIronBee();

    // Ensure that the operator exists.
    ASSERT_EQ(IB_OK,
        ib_operator_lookup(ib_engine, op_name, &op)
    );

    ASSERT_EQ(IB_OK, ib_operator_inst_create(op,
                                             ib_context_main(ib_engine),
                                             IB_OP_CAPABILITY_NON_STREAM,
                                             rule_name,
                                             &instance_data));
    performTx();

    // Attempt to match.
    ASSERT_EQ(IB_OK, ib_operator_inst_execute(op,
                                          instance_data,
                                          ib_tx,
                                          field1,
                                          NULL,
                                          &result));

    // This time we should succeed.
    ASSERT_TRUE(result);
}
コード例 #8
0
ib_status_t ib_flags_oplist_parse(
    const ib_strval_t *map,
    ib_mpool_t        *mp,
    const char        *str,
    const char        *sep,
    ib_list_t         *oplist)
{
    if ( (map == NULL) || (str == NULL) || (sep == NULL) || (oplist == NULL) ) {
        return IB_EINVAL;
    }

    char       *copy;
    const char *tmp;

    /* Make a copy of the string that we can use for strtok */
    copy = ib_mpool_strdup(mp, str);
    if (copy == NULL) {
        return IB_EALLOC;
    }

    /* Clear the list */
    ib_list_clear(oplist);

    /* Walk through the separated list, parser each operator, build the list */
    tmp = strtok(copy, sep);
    do {
        ib_status_t           rc;
        ib_flags_op_t         op;
        ib_flags_t            flags;
        ib_flags_operation_t *operation;

        rc = parse_single(map, tmp, &op, &flags);
        if (rc != IB_OK) {
            return rc;
        }
        operation = ib_mpool_alloc(mp, sizeof(*operation));
        if (operation == NULL) {
            return IB_EALLOC;
        }
        operation->op = op;
        operation->flags = flags;
        rc = ib_list_push(oplist, operation);
        if (rc != IB_OK) {
            return rc;
        }
    } while ( (tmp = strtok(NULL, sep)) != NULL);

    return IB_OK;
}
コード例 #9
0
ファイル: action.c プロジェクト: loveshell/ironbee
ib_status_t ib_action_register(
    ib_engine_t            *ib,
    const char             *name,
    ib_flags_t              flags,
    ib_action_create_fn_t   fn_create,
    void                   *cbdata_create,
    ib_action_destroy_fn_t  fn_destroy,
    void                   *cbdata_destroy,
    ib_action_execute_fn_t  fn_execute,
    void                   *cbdata_execute
)
{
    IB_FTRACE_INIT();
    ib_hash_t *action_hash = ib->actions;
    ib_mpool_t *pool = ib_engine_pool_main_get(ib);
    ib_status_t rc;
    char *name_copy;
    ib_action_t *act;

    rc = ib_hash_get(action_hash, &act, name);
    if (rc == IB_OK) {
        /* name already is registered */
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    name_copy = ib_mpool_strdup(pool, name);
    if (name_copy == NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    act = (ib_action_t *)ib_mpool_alloc(pool, sizeof(*act));
    if (act == NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }
    act->name           = name_copy;
    act->flags          = flags;
    act->fn_create      = fn_create;
    act->cbdata_create  = cbdata_create;
    act->fn_destroy     = fn_destroy;
    act->cbdata_destroy = cbdata_destroy;
    act->fn_execute     = fn_execute;
    act->cbdata_execute = cbdata_execute;

    rc = ib_hash_set(action_hash, name_copy, act);

    IB_FTRACE_RET_STATUS(rc);
}
コード例 #10
0
ファイル: action.c プロジェクト: niubl/ironbee
ib_status_t ib_action_register(
    ib_engine_t            *ib,
    const char             *name,
    ib_action_create_fn_t   fn_create,
    void                   *cbdata_create,
    ib_action_destroy_fn_t  fn_destroy,
    void                   *cbdata_destroy,
    ib_action_execute_fn_t  fn_execute,
    void                   *cbdata_execute
)
{
    ib_hash_t *action_hash = ib->actions;
    ib_mpool_t *pool = ib_engine_pool_main_get(ib);
    ib_status_t rc;
    char *name_copy;
    ib_action_t *act;

    rc = ib_hash_get(action_hash, &act, name);
    if (rc == IB_OK) {
        /* name already is registered */
        return IB_EINVAL;
    }

    name_copy = ib_mpool_strdup(pool, name);
    if (name_copy == NULL) {
        return IB_EALLOC;
    }

    act = (ib_action_t *)ib_mpool_alloc(pool, sizeof(*act));
    if (act == NULL) {
        return IB_EALLOC;
    }
    act->name           = name_copy;
    act->fn_create      = fn_create;
    act->cbdata_create  = cbdata_create;
    act->fn_destroy     = fn_destroy;
    act->cbdata_destroy = cbdata_destroy;
    act->fn_execute     = fn_execute;
    act->cbdata_execute = cbdata_execute;

    rc = ib_hash_set(action_hash, name_copy, act);

    return rc;
}
コード例 #11
0
ib_status_t ib_flags_strtok(
    const ib_strval_t *map,
    ib_mpool_t        *mp,
    const char        *str,
    const char        *sep,
    ib_flags_t        *pflags,
    ib_flags_t        *pmask)
{
    if ( (map == NULL) || (mp == NULL) || (str == NULL) || (sep == NULL) ||
         (pflags == NULL) || (pmask == NULL) )
    {
        return IB_EINVAL;
    }

    int         n = 0;
    ib_flags_t  flags = 0;
    ib_flags_t  mask = 0;
    char       *copy;
    const char *tmp;

    /* Make a copy of the string that we can use for strtok */
    copy = ib_mpool_strdup(mp, str);
    if (copy == NULL) {
        return IB_EALLOC;
    }

    /* Walk through the separated list */
    tmp = strtok(copy, sep);
    do {
        ib_status_t rc;
        rc = ib_flags_string(map, tmp, n++, &flags, &mask);
        if (rc != IB_OK) {
            return rc;
        }
    } while ( (tmp = strtok(NULL, sep)) != NULL);

    /* Done */
    *pflags = flags;
    *pmask = mask;
    return IB_OK;
}
コード例 #12
0
ファイル: test_operator.cpp プロジェクト: aburan28/ironbee
ib_status_t test_create_fn(ib_engine_t *ib,
                           ib_context_t *ctx,
                           const ib_rule_t *rule,
                           ib_mpool_t *pool,
                           const char *data,
                           ib_operator_inst_t *op_inst)
{
    char *str;

    if (strcmp(data, "INVALID") == 0) {
        return IB_EINVAL;
    }
    str = ib_mpool_strdup(pool, data);
    if (str == NULL) {
        return IB_EALLOC;
    }

    op_inst->data = str;

    return IB_OK;
}
コード例 #13
0
ib_status_t test_create_fn(
    ib_context_t  *ctx,
    const char    *parameters,
    void         **instance_data,
    void          *cbdata
)
{
    assert(ctx != NULL);
    char *str;
    ib_mpool_t *pool = ib_context_get_mpool(ctx);

    if (strcmp(parameters, "INVALID") == 0) {
        return IB_EINVAL;
    }
    str = ib_mpool_strdup(pool, parameters);
    if (str == NULL) {
        return IB_EALLOC;
    }

    *instance_data = str;

    return IB_OK;
}
コード例 #14
0
ib_status_t ib_tfn_register(ib_engine_t *ib,
                            const char *name,
                            ib_tfn_fn_t fn_execute,
                            ib_flags_t flags,
                            void *fndata)
{
    assert(ib != NULL);
    assert(name != NULL);
    assert(fn_execute != NULL);

    ib_hash_t *tfn_hash = ib->tfns;
    ib_status_t rc;
    ib_tfn_t *tfn;
    char *name_copy;

    name_copy = ib_mpool_strdup(ib->mp, name);
    if (name_copy == NULL) {
        return IB_EALLOC;
    }

    tfn = (ib_tfn_t *)ib_mpool_alloc(ib->mp, sizeof(*tfn));
    if (tfn == NULL) {
        return IB_EALLOC;
    }
    tfn->name = name_copy;
    tfn->fn_execute = fn_execute;
    tfn->tfn_flags = flags;
    tfn->fndata = fndata;

    rc = ib_hash_set(tfn_hash, name_copy, tfn);
    if (rc != IB_OK) {
        return rc;
    }

    return IB_OK;
}
コード例 #15
0
ファイル: pcre.c プロジェクト: BillTheBest/ironbee
/**
 * Internal compilation of the modpcre pattern.
 *
 * @param[in] ib IronBee engine for logging.
 * @param[in] pool The memory pool to allocate memory out of.
 * @param[out] pcre_cpatt Struct containing the compilation.
 * @param[in] patt The uncompiled pattern to match.
 * @param[out] errptr Pointer to an error message describing the failure.
 * @param[out] errorffset The location of the failure, if this fails.
 * @returns IronBee status. IB_EINVAL if the pattern is invalid,
 *          IB_EALLOC if memory allocation fails or IB_OK.
 */
static ib_status_t pcre_compile_internal(ib_engine_t *ib,
                                         ib_mpool_t *pool,
                                         modpcre_cpatt_t **pcre_cpatt,
                                         const char *patt,
                                         const char **errptr,
                                         int *erroffset)
{
    IB_FTRACE_INIT();

    /* Compiled pattern. */
    pcre *cpatt = NULL;

    /* Compiled pattern size. Used to copy cpatt. */
    size_t cpatt_sz;

    /* Extra data structure. This contains the study_data pointer. */
    pcre_extra *edata = NULL;

    /* Size of edata->study_data. */
    size_t study_data_sz;

    /* Is the compiled regex jit-compiled? This impacts how it is executed. */
    int is_jit;

    /* How cpatt is produced. */
    const int compile_flags = PCRE_DOTALL | PCRE_DOLLAR_ENDONLY;
#ifdef PCRE_HAVE_JIT
    /* Determine the success of a call. */
    int rc;

    /* Determines if the pcre compilation was successful with pcre_jit. */
    int pcre_jit_ret;

    /* How edata is produced if we are using JIT. */
    const int study_flags = PCRE_STUDY_JIT_COMPILE;
#else

    /* How edata is produced if we are not using JIT. */
    const int study_flags = 0;
#endif /* PCRE_HAVE_JIT */

    cpatt = pcre_compile(patt, compile_flags, errptr, erroffset, NULL);

    if (*errptr != NULL) {
        ib_util_log_error("PCRE compile error for \"%s\": %s at offset %d",
                          patt, *errptr, *erroffset);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    edata = pcre_study(cpatt, study_flags, errptr);

#ifdef PCRE_HAVE_JIT
    if(*errptr != NULL)  {
        pcre_free(cpatt);
        ib_util_log_error("PCRE-JIT study failed: %s", *errptr);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* The check to see if JIT compilation was a success changed in 8.20RC1
       now uses pcre_fullinfo see doc/pcrejit.3 */
    rc = pcre_fullinfo(cpatt, edata, PCRE_INFO_JIT, &pcre_jit_ret);
    if (rc != 0) {
        ib_log_error(ib, "PCRE-JIT failed to get pcre_fullinfo");
        is_jit = 0;
    }
    else if (pcre_jit_ret != 1) {
        ib_log_info(ib, "PCRE-JIT compiler does not support: %s", patt);
        ib_log_info(ib, "It will fallback to the normal PCRE");
        is_jit = 0;
    }
    else { /* Assume pcre_jit_ret == 1. */
        is_jit = 1;
    }
#else
    if(*errptr != NULL)  {
        pcre_free(cpatt);
        ib_log_info(ib, "PCRE study failed: %s", *errptr);
    }
    is_jit = 0;
#endif /*PCRE_HAVE_JIT*/

    /* Compute the size of the populated values of cpatt. */
    pcre_fullinfo(cpatt, edata, PCRE_INFO_SIZE, &cpatt_sz);

    if (edata != NULL) {
        pcre_fullinfo(cpatt, edata, PCRE_INFO_STUDYSIZE, &study_data_sz);
    }
    else {
        study_data_sz = 0;
    }

    /**
     * Below is only allocation and copy operations to pass the PCRE results
     * back to the output variable pcre_cpatt.
     */

    *pcre_cpatt = (modpcre_cpatt_t *)ib_mpool_alloc(pool, sizeof(**pcre_cpatt));
    if (*pcre_cpatt == NULL) {
        pcre_free(cpatt);
        pcre_free(edata);
        ib_log_error(ib,
                     "Failed to allocate pcre_cpatt of size: %zd",
                     sizeof(**pcre_cpatt));
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    (*pcre_cpatt)->is_jit = is_jit;
    (*pcre_cpatt)->cpatt_sz = cpatt_sz;
    (*pcre_cpatt)->study_data_sz = study_data_sz;

    /* Copy pattern. */
    (*pcre_cpatt)->patt  = ib_mpool_strdup(pool, patt);
    if ((*pcre_cpatt)->patt == NULL) {
        pcre_free(cpatt);
        pcre_free(edata);
        ib_log_error(ib, "Failed to duplicate pattern string: %s", patt);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    /* Copy compiled pattern. */
    (*pcre_cpatt)->cpatt = ib_mpool_memdup(pool, cpatt, cpatt_sz);
    pcre_free(cpatt);
    if ((*pcre_cpatt)->cpatt == NULL) {
        pcre_free(edata);
        ib_log_error(ib, "Failed to duplicate pattern of size: %zd", cpatt_sz);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    /* Copy extra data (study data). */
    if (edata != NULL) {

        /* Copy edata. */
        (*pcre_cpatt)->edata = ib_mpool_memdup(pool, edata, sizeof(*edata));

        if ((*pcre_cpatt)->edata == NULL) {
            pcre_free(edata);
            ib_log_error(ib, "Failed to duplicate edata.");
            IB_FTRACE_RET_STATUS(IB_EALLOC);
        }

        /* Copy edata->study_data. */
        (*pcre_cpatt)->edata->study_data = ib_mpool_memdup(pool,
                                                           edata->study_data,
                                                           study_data_sz);
        pcre_free(edata);
        if ((*pcre_cpatt)->edata->study_data == NULL) {
            ib_log_error(ib, "Failed to study data of size: %zd", study_data_sz);
            IB_FTRACE_RET_STATUS(IB_EALLOC);
        }
    }
    else {
        (*pcre_cpatt)->edata = NULL;
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}
コード例 #16
0
ファイル: pcre.c プロジェクト: BillTheBest/ironbee
/**
 * Internal compilation of the dfa pattern.
 *
 * The major difference in this compilation from that of a normal pcre pattern
 * is that it does not use PCRE_JIT because it is intended for use
 * on streaming data. Streaming data is delivered in chunks
 * and partial matches are found. Doing partial matches and resumes
 * disable JIT optimizations and some a few other normal optimizations.
 *
 * @param[in] pool The memory pool to allocate memory out of.
 * @param[out] pcre_cpatt Struct containing the compilation.
 * @param[in] patt The uncompiled pattern to match.
 * @param[out] errptr Pointer to an error message describing the failure.
 * @param[out] errorffset The location of the failure, if this fails.
 * @returns IronBee status. IB_EINVAL if the pattern is invalid,
 *          IB_EALLOC if memory allocation fails or IB_OK.
 */
static ib_status_t dfa_compile_internal(ib_mpool_t *pool,
                                        dfa_rule_data_t **dfa_cpatt,
                                        const char *patt,
                                        const char **errptr,
                                        int *erroffset)
{
    IB_FTRACE_INIT();

    /* Compiled pattern. */
    pcre *cpatt = NULL;

    /* Compiled pattern size. Used to copy cpatt. */
    size_t cpatt_sz;

    /* Extra data structure. This contains the study_data pointer. */
    pcre_extra *edata = NULL;

    /* Size of edata->study_data. */
    size_t study_data_sz;

    /* How cpatt is produced. */
    const int compile_flags = PCRE_DOTALL | PCRE_DOLLAR_ENDONLY;

    /* How edata is produced if we are not using JIT. */
    const int study_flags = 0;

    cpatt = pcre_compile(patt, compile_flags, errptr, erroffset, NULL);

    if (*errptr != NULL) {
        ib_util_log_error("PCRE compile error for \"%s\": %s at offset %d",
                          patt, *errptr, *erroffset);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    edata = pcre_study(cpatt, study_flags, errptr);

    if(*errptr != NULL)  {
        pcre_free(cpatt);
        ib_util_log_error("PCRE study failed: %s", *errptr);
    }

    /* Compute the size of the populated values of cpatt. */
    pcre_fullinfo(cpatt, edata, PCRE_INFO_SIZE, &cpatt_sz);

    if (edata != NULL) {
        pcre_fullinfo(cpatt, edata, PCRE_INFO_STUDYSIZE, &study_data_sz);
    }
    else {
        study_data_sz = 0;
    }

    /**
     * Below is only allocation and copy operations to pass the PCRE results
     * back to the output variable dfa_cpatt.
     */

    *dfa_cpatt = (dfa_rule_data_t *)ib_mpool_alloc(pool, sizeof(**dfa_cpatt));
    if (*dfa_cpatt == NULL) {
        pcre_free(cpatt);
        pcre_free(edata);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    (*dfa_cpatt)->cpatt_sz = cpatt_sz;
    (*dfa_cpatt)->study_data_sz = study_data_sz;

    /* Copy pattern. */
    (*dfa_cpatt)->patt  = ib_mpool_strdup(pool, patt);
    if ((*dfa_cpatt)->patt == NULL) {
        pcre_free(cpatt);
        pcre_free(edata);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    /* Copy compiled pattern. */
    (*dfa_cpatt)->cpatt = ib_mpool_memdup(pool, cpatt, cpatt_sz);
    pcre_free(cpatt);
    if ((*dfa_cpatt)->cpatt == NULL) {
        pcre_free(edata);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    /* Copy extra data (study data). */
    if (edata != NULL) {

        /* Copy edata. */
        (*dfa_cpatt)->edata = ib_mpool_memdup(pool, edata, sizeof(*edata));

        if ((*dfa_cpatt)->edata == NULL) {
            pcre_free(edata);
            IB_FTRACE_RET_STATUS(IB_EALLOC);
        }

        /* Copy edata->study_data. */
        (*dfa_cpatt)->edata->study_data = ib_mpool_memdup(pool,
                                                           edata->study_data,
                                                           study_data_sz);
        pcre_free(edata);
        if ((*dfa_cpatt)->edata->study_data == NULL) {
            IB_FTRACE_RET_STATUS(IB_EALLOC);
        }
    }
    else {
        (*dfa_cpatt)->edata = NULL;
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}
コード例 #17
0
/**
 * Parse the user agent header, splitting into component fields.
 *
 * Attempt to tokenize the user agent string passed in, storing the
 * result in the DPI associated with the transaction.
 *
 * @param[in] ib IronBee object
 * @param[in,out] tx Transaction object
 * @param[in] bs Byte string containing the agent string
 *
 * @returns Status code
 */
static ib_status_t modua_agent_fields(ib_engine_t *ib,
                                      ib_tx_t *tx,
                                      const ib_bytestr_t *bs)
{
    const modua_match_rule_t *rule = NULL;
    ib_field_t               *agent_list = NULL;
    char                     *product = NULL;
    char                     *platform = NULL;
    char                     *extra = NULL;
    char                     *agent;
    char                     *buf;
    size_t                    len;
    ib_status_t               rc;

    /* Get the length of the byte string */
    len = ib_bytestr_length(bs);

    /* Allocate memory for a copy of the string to split up below. */
    buf = (char *)ib_mpool_calloc(tx->mp, 1, len+1);
    if (buf == NULL) {
        ib_log_error_tx(tx,
                        "Failed to allocate %zd bytes for agent string",
                        len+1);
        return IB_EALLOC;
    }

    /* Copy the string out */
    memcpy(buf, ib_bytestr_const_ptr(bs), len);
    buf[len] = '\0';
    ib_log_debug_tx(tx, "Found user agent: '%s'", buf);

    /* Copy the agent string */
    agent = (char *)ib_mpool_strdup(tx->mp, buf);
    if (agent == NULL) {
        ib_log_error_tx(tx, "Failed to allocate copy of agent string");
        return IB_EALLOC;
    }

    /* Parse the user agent string */
    rc = modua_parse_uastring(buf, &product, &platform, &extra);
    if (rc != IB_OK) {
        ib_log_debug_tx(tx, "Failed to parse User Agent string '%s'", agent);
        return IB_OK;
    }

    /* Categorize the parsed string */
    rule = modua_match_cat_rules(product, platform, extra);
    if (rule == NULL) {
        ib_log_debug_tx(tx, "No rule matched" );
    }
    else {
        ib_log_debug_tx(tx, "Matched to rule #%d / category '%s'",
                        rule->rule_num, rule->category );
    }

    /* Build a new list. */
    rc = ib_data_add_list(tx->data, "UA", &agent_list);
    if (rc != IB_OK)
    {
        ib_log_alert_tx(tx, "Unable to add UserAgent list to DPI.");
        return rc;
    }

    /* Store Agent */
    rc = modua_store_field(ib, tx->mp, agent_list, "agent", agent);
    if (rc != IB_OK) {
        return rc;
    }

    /* Store product */
    rc = modua_store_field(ib, tx->mp, agent_list, "PRODUCT", product);
    if (rc != IB_OK) {
        return rc;
    }

    /* Store Platform */
    rc = modua_store_field(ib, tx->mp, agent_list, "OS", platform);
    if (rc != IB_OK) {
        return rc;
    }

    /* Store Extra */
    rc = modua_store_field(ib, tx->mp, agent_list, "extra", extra);
    if (rc != IB_OK) {
        return rc;
    }

    /* Store Extra */
    if (rule != NULL) {
        rc = modua_store_field(ib, tx->mp, agent_list,
                               "category", rule->category);
    }
    else {
        rc = modua_store_field(ib, tx->mp, agent_list, "category", NULL );
    }
    if (rc != IB_OK) {
        return rc;
    }

    /* Done */
    return IB_OK;
}
コード例 #18
0
ファイル: logformat.c プロジェクト: igalic/ironbee
ib_status_t ib_logformat_set(ib_logformat_t *lf, char *format) {
    IB_FTRACE_INIT(ib_logformat_set);
    ib_mpool_t *mp = lf->mp;
    char literal[IB_LOGFORMAT_MAXLINELEN + 1];
    int literal_tot = 0;
    uint8_t status = 0;
    int i = 0;
    int j = 0;
    int l = 0;

    memset(lf, 0, sizeof(ib_logformat_t) + 1);
    lf->mp = mp;

    literal[0] = '\0';

    /* Store the original format (right now its just for debugging purposses) */
    lf->orig_format = ib_mpool_strdup(lf->mp, format);
    if (lf->orig_format == NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    for (; lf->orig_format[i] != '\0' &&
         lf->field_cnt < IB_LOGFORMAT_MAXFIELDS &&
         j < IB_LOGFORMAT_MAXLINELEN; i++)
    {
        if (i == 0 && lf->orig_format[i] != '%') {
            lf->literal_starts = 1;
        }
        switch (status) {
            case IB_LOGFORMAT_ST_PR:
                /* Which field? */
                switch (lf->orig_format[i]) {
                    case IB_LOG_FIELD_REMOTE_ADDR:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_REMOTE_ADDR;
                        break;
                    case IB_LOG_FIELD_LOCAL_ADDR:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_LOCAL_ADDR;
                        break;
                    case IB_LOG_FIELD_HOSTNAME:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_HOSTNAME;
                        break;
                    case IB_LOG_FIELD_SITE_ID:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_SITE_ID;
                        break;
                    case IB_LOG_FIELD_SENSOR_ID:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_SENSOR_ID;
                        break;
                    case IB_LOG_FIELD_TRANSACTION_ID:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_TRANSACTION_ID;
                        break;
                    case IB_LOG_FIELD_TIMESTAMP:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_TIMESTAMP;
                        break;
                    case IB_LOG_FIELD_LOG_FILE:
                        lf->fields[lf->field_cnt++] = IB_LOG_FIELD_LOG_FILE;
                        break;
                    case '%':
                        if (i == 1) {
                            lf->literal_starts = 1;
                        }
                        /* just allow it */
                        literal[j++] = '%';
                        break;
                    default:
                        /* Not understood - ignore it */
                        break;
                }

                if (literal[0] != '\0') {
                    literal_tot += j;
                    if (literal_tot > IB_LOGFORMAT_MAXLINELEN) {
                        /* Too long */
                        IB_FTRACE_RET_STATUS(IB_EINVAL);
                    }

                    /* Add string end for later usage with *printf() functions*/
                    literal[j] = '\0';
                    lf->literals[l] = ib_mpool_strdup(lf->mp, literal);
                    if (lf->literals[l] == NULL) {
                        /* Uops.. */
                        IB_FTRACE_RET_STATUS(IB_EINVAL);
                    }
                    else {
                        lf->literals_len[l] = j;
                        ++l;
                    }
                    literal[0] = '\0';
                    j = 0;
                }
                status = IB_LOGFORMAT_ST_NONE;
                break;
            case IB_LOGFORMAT_ST_BS:
                /* Avoid '\b', '\n' */
                switch (lf->orig_format[i]) {
                    case 't':
                        literal[j++] = '\t';
                        break;
                    case 'n':
                    case 'b':
                        /* Just add a space */
                        /// @todo more to add?
                        literal[j++] = ' ';
                        break;
                    default:
                        /* Just use the character directly */
                        literal[j++] = lf->orig_format[i];
                }
                status = IB_LOGFORMAT_ST_NONE;
                break;
            case IB_LOGFORMAT_ST_NONE:
            default:
                switch (lf->orig_format[i]) {
                    /** @todo Do we need to check certain escape chars?
                     *  Will we allow for example '\n' in the log index file?
                     */
                    case '\\':
                        status = IB_LOGFORMAT_ST_BS;
                        break;
                    case '%':
                        status = IB_LOGFORMAT_ST_PR;
                        break;
                    default:
                        /* literal string */
                        literal[j++] = lf->orig_format[i];
                }
        }        
    }

    if (lf->orig_format[i] != '\0' || status == IB_LOGFORMAT_ST_PR) {
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }
    lf->fields[lf->field_cnt + 1] = '\0';
    /* Write the last parsed literal and the length */
    if (literal[0] != '\0') {
        literal_tot += j;
        if (literal_tot > IB_LOGFORMAT_MAXLINELEN) {
            /* Too long */
            IB_FTRACE_RET_STATUS(IB_EINVAL);
        }
        literal[j] = '\0';
        lf->literals_len[l] = j;
        lf->literals[l++] = ib_mpool_strdup(lf->mp, literal);
    }
    lf->literal_cnt = l;

    IB_FTRACE_RET_STATUS(IB_OK);
}
コード例 #19
0
ファイル: test_util_field.cpp プロジェクト: poona/ironbee
TEST_F(TestIBUtilField, AliasConvert)
{
    char       *str;
    ib_field_t *f1;
    ib_field_t *f2;
    ib_status_t rc;
    ib_num_t    num;
    ib_float_t  flt;

    /*
     * Convert numeric string to number
     */

    /* Copy a number into the string */
    str = ib_mpool_strdup(MemPool(), "1");
    ASSERT_TRUE(str != NULL);

    /* Create the aliased field */
    rc = ib_field_create_alias(&f1, MemPool(), "one", 3,
                               IB_FTYPE_NULSTR,
                               ib_ftype_nulstr_mutable_out(&str));
    ASSERT_EQ(IB_OK, rc);

    /* Attempt a numeric conversion. */
    rc = ib_field_convert(MemPool(), IB_FTYPE_NUM, f1, &f2);
    ASSERT_EQ(IB_OK, rc);

    /* Pull out param value for check. */
    rc = ib_field_value(f2, ib_ftype_num_out(&num));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_EQ(1, num);

    /*
     * Convert floating-point string to float
     */

    /* Copy a number into the string */
    str = ib_mpool_strdup(MemPool(), "1.1");
    ASSERT_TRUE(str != NULL);

    /* Create the aliased field */
    rc = ib_field_create_alias(&f1, MemPool(), "one", 3,
                               IB_FTYPE_NULSTR,
                               ib_ftype_nulstr_mutable_out(&str));
    ASSERT_EQ(IB_OK, rc);

    /* Attempt a numeric conversion. */
    rc = ib_field_convert(MemPool(), IB_FTYPE_FLOAT, f1, &f2);
    ASSERT_EQ(IB_OK, rc);

    /* Pull out param value for check. */
    rc = ib_field_value(f2, ib_ftype_float_out(&flt));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_FLOAT_EQ(1.1, flt);

    /*
     * Convert non-numeric string to number
     */

    /* Copy a number into the string */
    str = ib_mpool_strdup(MemPool(), "x1");
    ASSERT_TRUE(str != NULL);

    /* Create the aliased field */
    rc = ib_field_create_alias(&f1, MemPool(), "one", 3,
                               IB_FTYPE_NULSTR,
                               ib_ftype_nulstr_mutable_out(&str));
    ASSERT_EQ(IB_OK, rc);

    /* Attempt a numeric conversion. */
    rc = ib_field_convert(MemPool(), IB_FTYPE_NUM, f1, &f2);
    ASSERT_EQ(IB_EINVAL, rc);

    /*
     * Convert floating-point string to number
     */

    /* Copy a number into the string */
    str = ib_mpool_strdup(MemPool(), "1.1");
    ASSERT_TRUE(str != NULL);

    /* Create the aliased field */
    rc = ib_field_create_alias(&f1, MemPool(), "one", 3,
                               IB_FTYPE_NULSTR,
                               ib_ftype_nulstr_mutable_out(&str));
    ASSERT_EQ(IB_OK, rc);

    /* Attempt a numeric conversion. */
    rc = ib_field_convert(MemPool(), IB_FTYPE_NUM, f1, &f2);
    ASSERT_EQ(IB_EINVAL, rc);


    /*
     * Convert non-numeric string to float
     */

    /* Copy a number into the string */
    str = ib_mpool_strdup(MemPool(), "1.1");
    ASSERT_TRUE(str != NULL);

    /* Create the aliased field */
    rc = ib_field_create_alias(&f1, MemPool(), "one", 3,
                               IB_FTYPE_NULSTR,
                               ib_ftype_nulstr_mutable_out(&str));
    ASSERT_EQ(IB_OK, rc);

    /* Attempt a numeric conversion. */
    rc = ib_field_convert(MemPool(), IB_FTYPE_FLOAT, f1, &f2);
    ASSERT_EQ(IB_OK, rc);

    /* Pull out param value for check. */
    rc = ib_field_value(f2, ib_ftype_float_out(&flt));
    ASSERT_EQ(IB_OK, rc);
    ASSERT_FLOAT_EQ(1.1, flt);
}
コード例 #20
0
ファイル: field.c プロジェクト: aburan28/ironbee
ib_status_t ib_field_setv_ex(
    ib_field_t *f,
    void       *in_pval,
    const void *arg,
    size_t      alen
)
{
    ib_status_t rc;

    if (ib_field_is_dynamic(f)) {
        if (f->val->fn_set == NULL) {
            return IB_EINVAL;
        }
        return f->val->fn_set(f, arg, alen, in_pval, f->val->cbdata_set);
    }

    /* No dynamic setter */
    if (arg != NULL) {
        return IB_EINVAL;
    }

    /* What and how it is stored depends on the field type. */
    switch (f->type) {
    case IB_FTYPE_BYTESTR:
    {
        const ib_bytestr_t *bs = (const ib_bytestr_t *)in_pval;
        if (bs != NULL) {
            rc = ib_bytestr_dup((ib_bytestr_t **)f->val->pval, f->mp, bs);
            if (rc != IB_OK) {
                goto failed;
            }
        }
        break;
    }
    case IB_FTYPE_LIST:
    {
        /// @todo Fix const once lists are const aware/copying.
        ib_list_t *l = (ib_list_t *)in_pval;
        if (l != NULL) {
            /// @todo Should do shallow copy
            *(ib_list_t **)f->val->pval = l;
        }
        else {
            rc = ib_list_create((ib_list_t **)f->val->pval, f->mp);
            if (rc != IB_OK) {
                goto failed;
            }
        }
        break;
    }
    case IB_FTYPE_SBUFFER:
    {
        /// @todo Fix once stream is const aware/copying
        ib_stream_t *s = (ib_stream_t *)in_pval;
        if (s != NULL) {
            /// @todo Should do shallow copy
            *(ib_stream_t **)f->val->pval = s;
        }
        else {
            rc = ib_stream_create((ib_stream_t **)f->val->pval, f->mp);
            if (rc != IB_OK) {
                goto failed;
            }
        }
        break;
    }
    case IB_FTYPE_NULSTR:
    {
        const char *s = (const char *)in_pval;
        if (s != NULL) {
            *(char **)(f->val->pval) = ib_mpool_strdup(f->mp, s);
            if (*(void **)(f->val->pval) == NULL) {
                rc = IB_EALLOC;
                goto failed;
            }
        }
        break;
    }
    case IB_FTYPE_NUM:
    {
        ib_num_t n = (in_pval != NULL) ? *(ib_num_t *)in_pval : 0;
        *(ib_num_t *)(f->val->pval) = n;
        break;
    }
    case IB_FTYPE_FLOAT:
    {
        ib_float_t fl = (in_pval != NULL) ? *(ib_float_t *)in_pval : 0;
        *(ib_float_t *)(f->val->pval) = fl;
        break;
    }
    case IB_FTYPE_GENERIC:
    default:
    {
        void *p = in_pval;
        *(void **)(f->val->pval) = p;
        break;
    }
    }

    ib_field_util_log_debug("FIELD_SETV", f);

    return IB_OK;

failed:
    return rc;
}
コード例 #21
0
ファイル: pcre.c プロジェクト: niubl/ironbee
/**
 * Internal compilation of the modpcre pattern.
 *
 * @param[in] ib IronBee engine for logging.
 * @param[in] pool The memory pool to allocate memory out of.
 * @param[in] config Module configuration
 * @param[in] is_dfa Set to true for DFA
 * @param[out] pcpdata Pointer to new struct containing the compilation.
 * @param[in] patt The uncompiled pattern to match.
 * @param[out] errptr Pointer to an error message describing the failure.
 * @param[out] erroffset The location of the failure, if this fails.
 *
 * @returns IronBee status. IB_EINVAL if the pattern is invalid,
 *          IB_EALLOC if memory allocation fails or IB_OK.
 */
static ib_status_t pcre_compile_internal(ib_engine_t *ib,
                                         ib_mpool_t *pool,
                                         const modpcre_cfg_t *config,
                                         bool is_dfa,
                                         modpcre_cpat_data_t **pcpdata,
                                         const char *patt,
                                         const char **errptr,
                                         int *erroffset)
{
    assert(ib != NULL);
    assert(pool != NULL);
    assert(config != NULL);
    assert(pcpdata != NULL);
    assert(patt != NULL);

    /* Pattern data structure we'll create */
    modpcre_cpat_data_t *cpdata;

    /* Compiled pattern. */
    pcre *cpatt = NULL;

    /* Compiled pattern size. Used to copy cpatt. */
    size_t cpatt_sz;

    /* Extra data structure. This contains the study_data pointer. */
    pcre_extra *edata = NULL;

    /* Size of edata->study_data. */
    size_t study_data_sz;

    /* How cpatt is produced. */
    const int compile_flags = PCRE_DOTALL | PCRE_DOLLAR_ENDONLY;

    /* Are we using JIT? */
    bool use_jit = !is_dfa;

#ifdef PCRE_HAVE_JIT
    if (config->use_jit == 0) {
        use_jit = false;
    }

    /* Do we want to be using JIT? */
    const bool want_jit = use_jit;
#else
    use_jit = false;
#endif /* PCRE_HAVE_JIT */

    cpatt = pcre_compile(patt, compile_flags, errptr, erroffset, NULL);

    if (*errptr != NULL) {
        ib_log_error(ib, "PCRE compile error for \"%s\": %s at offset %d",
                     patt, *errptr, *erroffset);
        return IB_EINVAL;
    }

    if (config->study) {
        if (use_jit) {
#ifdef PCRE_HAVE_JIT
            edata = pcre_study(cpatt, PCRE_STUDY_JIT_COMPILE, errptr);
            if (*errptr != NULL)  {
                pcre_free(cpatt);
                use_jit = false;
                ib_log_warning(ib, "PCRE-JIT study failed: %s", *errptr);
            }
#endif
        }
        else {
            edata = pcre_study(cpatt, 0, errptr);
            if (*errptr != NULL)  {
                pcre_free(cpatt);
                ib_log_error(ib, "PCRE study failed: %s", *errptr);
            }
        }
    }
    else if (use_jit) {
        ib_log_warning(ib, "PCRE: Disabling JIT because study disabled");
        use_jit = false;
    }

#ifdef PCRE_HAVE_JIT
    /* The check to see if JIT compilation was a success changed in 8.20RC1
       now uses pcre_fullinfo see doc/pcrejit.3 */
    if (use_jit) {
        int rc;
        int pcre_jit_ret;

        rc = pcre_fullinfo(cpatt, edata, PCRE_INFO_JIT, &pcre_jit_ret);
        if (rc != 0) {
            ib_log_error(ib, "PCRE-JIT failed to get pcre_fullinfo");
            use_jit = false;
        }
        else if (pcre_jit_ret != 1) {
            ib_log_info(ib, "PCRE-JIT compiler does not support: %s", patt);
            use_jit = false;
        }
        else { /* Assume pcre_jit_ret == 1. */
            /* Do nothing */
        }
    }
    if (want_jit && !use_jit) {
        ib_log_info(ib, "Falling back to normal PCRE");
    }
#endif /*PCRE_HAVE_JIT*/

    /* Compute the size of the populated values of cpatt. */
    pcre_fullinfo(cpatt, edata, PCRE_INFO_SIZE, &cpatt_sz);
    if (edata != NULL) {
        pcre_fullinfo(cpatt, edata, PCRE_INFO_STUDYSIZE, &study_data_sz);
    }
    else {
        study_data_sz = 0;
    }

    /**
     * Below is only allocation and copy operations to pass the PCRE results
     * back to the output variable cpdata.
     */

    cpdata = (modpcre_cpat_data_t *)ib_mpool_calloc(pool, sizeof(*cpdata), 1);
    if (cpdata == NULL) {
        pcre_free(cpatt);
        pcre_free(edata);
        ib_log_error(ib,
                     "Failed to allocate cpdata of size: %zd",
                     sizeof(*cpdata));
        return IB_EALLOC;
    }

    cpdata->is_dfa = is_dfa;
    cpdata->is_jit = use_jit;
    cpdata->cpatt_sz = cpatt_sz;
    cpdata->study_data_sz = study_data_sz;

    /* Copy pattern. */
    cpdata->patt = ib_mpool_strdup(pool, patt);
    if (cpdata->patt == NULL) {
        pcre_free(cpatt);
        pcre_free(edata);
        ib_log_error(ib, "Failed to duplicate pattern string: %s", patt);
        return IB_EALLOC;
    }

    /* Copy compiled pattern. */
    cpdata->cpatt = ib_mpool_memdup(pool, cpatt, cpatt_sz);
    pcre_free(cpatt);
    if (cpdata->cpatt == NULL) {
        pcre_free(edata);
        ib_log_error(ib, "Failed to duplicate pattern of size: %zd", cpatt_sz);
        return IB_EALLOC;
    }
    ib_log_debug(ib, "PCRE copied cpatt @ %p -> %p (%zd bytes)",
                 (void *)cpatt, (void *)cpdata->cpatt, cpatt_sz);

    /* Copy extra data (study data). */
    if (edata != NULL) {

        /* Copy edata. */
        cpdata->edata = ib_mpool_memdup(pool, edata, sizeof(*edata));
        if (cpdata->edata == NULL) {
            pcre_free(edata);
            ib_log_error(ib, "Failed to duplicate edata.");
            return IB_EALLOC;
        }

        /* Copy edata->study_data. */
        if (edata->study_data != NULL) {
            cpdata->edata->study_data =
                ib_mpool_memdup(pool, edata->study_data, study_data_sz);

            if (cpdata->edata->study_data == NULL) {
                ib_log_error(ib, "Failed to study data of size: %zd",
                             study_data_sz);
                pcre_free(edata);
                return IB_EALLOC;
            }
        }
        pcre_free(edata);
    }
    else {
        cpdata->edata = ib_mpool_calloc(pool, 1, sizeof(*edata));
        if (cpdata->edata == NULL) {
            pcre_free(edata);
            ib_log_error(ib, "Failed to allocate edata.");
            return IB_EALLOC;
        }
    }

    /* Set the PCRE limits for non-DFA patterns */
    if (! is_dfa) {
        cpdata->edata->flags |=
            (PCRE_EXTRA_MATCH_LIMIT | PCRE_EXTRA_MATCH_LIMIT_RECURSION);
        cpdata->edata->match_limit =
            (unsigned long)config->match_limit;
        cpdata->edata->match_limit_recursion =
            (unsigned long)config->match_limit_recursion;
        cpdata->dfa_ws_size = 0;
    }
    else {
        cpdata->edata->match_limit = 0U;
        cpdata->edata->match_limit_recursion = 0U;
        cpdata->dfa_ws_size = (int)config->dfa_workspace_size;
    }

    /* Set stack limits for JIT */
    if (cpdata->is_jit) {
#ifdef PCRE_HAVE_JIT
        if (config->jit_stack_start == 0U) {
            cpdata->jit_stack_start =
                PCRE_JIT_STACK_START_MULT * config->match_limit_recursion;
        }
        else {
            cpdata->jit_stack_start = (int)config->jit_stack_start;
        }
        if (config->jit_stack_max == 0U) {
            cpdata->jit_stack_max =
                PCRE_JIT_STACK_MAX_MULT * config->match_limit_recursion;
        }
        else {
            cpdata->jit_stack_max = (int)config->jit_stack_max;
        }
#endif
    }
    else {
        cpdata->jit_stack_start = 0;
        cpdata->jit_stack_max = 0;
    }

    ib_log_trace(ib,
                 "Compiled pcre pattern \"%s\": "
                 "cpatt=%p edata=%p limit=%ld rlimit=%ld study=%p "
                 "dfa=%s dfa-ws-sz=%d "
                 "jit=%s jit-stack: start=%d max=%d",
                 patt,
                 (void *)cpdata->cpatt,
                 (void *)cpdata->edata,
                 cpdata->edata->match_limit,
                 cpdata->edata->match_limit_recursion,
                 cpdata->edata->study_data,
                 cpdata->is_dfa ? "yes" : "no",
                 cpdata->dfa_ws_size,
                 cpdata->is_jit ? "yes" : "no",
                 cpdata->jit_stack_start,
                 cpdata->jit_stack_max);
    *pcpdata = cpdata;

    return IB_OK;
}
コード例 #22
0
/**
 * 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;
}
コード例 #23
0
ファイル: poc_sig.c プロジェクト: niq/ironbee
/**
 * @internal
 * Handle a PocSig directive.
 *
 * @param cp Config parser
 * @param name Directive name
 * @param args List of directive arguments
 * @param cbdata Callback data (from directive registration)
 *
 * @returns Status code
 */
static ib_status_t pocsig_dir_signature(ib_cfgparser_t *cp,
                                        const char *name,
                                        ib_list_t *args,
                                        void *cbdata)
{
    IB_FTRACE_INIT(pocsig_dir_signature);
    ib_engine_t *ib = cp->ib;
    ib_context_t *ctx = cp->cur_ctx ? cp->cur_ctx : ib_context_main(ib);
    ib_list_t *list;
    const char *target;
    const char *op;
    const char *action;
    pocsig_cfg_t *cfg;
    pocsig_phase_t phase;
    pocsig_sig_t *sig;
    const char *errptr;
    int erroff;
    ib_status_t rc;

    /* Get the pocsig configuration for this context. */
    rc = ib_context_module_config(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);
    }

    /* Setup the PCRE matcher. */
    if (cfg->pcre == NULL) {
        rc = ib_matcher_create(ib, ib_engine_pool_config_get(ib),
                               "pcre", &cfg->pcre);
        if (rc != IB_OK) {
            ib_log_error(ib, 2, "Could not create a PCRE matcher: %d", rc);
            IB_FTRACE_RET_STATUS(rc);
        }
    }

    /* Determine phase and initialize the phase list if required. */
    if (strcasecmp("PocSigPreTx", name) == 0) {
        phase = POCSIG_PRE;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(cfg->phase + POCSIG_PRE,
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigReqHead", name) == 0) {
        phase = POCSIG_REQHEAD;
        if (cfg->phase[phase] == NULL) {
            ib_log_debug(ib, 4, "Creating list for phase=%d", phase);
            rc = ib_list_create(&list,
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
            ib_log_debug(ib, 4, "List for phase=%d list=%p", phase, list);
            cfg->phase[phase] = list;
        }
    }
    else if (strcasecmp("PocSigReq", name) == 0) {
        phase = POCSIG_REQ;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(&cfg->phase[phase],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigResHead", name) == 0) {
        phase = POCSIG_RESHEAD;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(&cfg->phase[phase],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigRes", name) == 0) {
        phase = POCSIG_RES;
        if (cfg->phase[POCSIG_RES] == NULL) {
            rc = ib_list_create(&cfg->phase[POCSIG_RES],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigPostTx", name) == 0) {
        phase = POCSIG_POST;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(&cfg->phase[phase],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else {
        ib_log_error(ib, 2, "Invalid signature: %s", name);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* Target */
    rc = ib_list_shift(args, &target);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "No PocSig target");
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* Operator */
    rc = ib_list_shift(args, &op);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "No PocSig operator");
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* Action */
    rc = ib_list_shift(args, &action);
    if (rc != IB_OK) {
        ib_log_debug(ib, 4, "No PocSig action");
        action = "";
    }

    /* Signature */
    sig = (pocsig_sig_t *)ib_mpool_alloc(ib_engine_pool_config_get(ib),
                                         sizeof(*sig));
    if (sig == NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    sig->target = ib_mpool_strdup(ib_engine_pool_config_get(ib), target);
    sig->patt = ib_mpool_strdup(ib_engine_pool_config_get(ib), op);
    sig->emsg = ib_mpool_strdup(ib_engine_pool_config_get(ib), action);

    /* Compile the PCRE patt. */
    if (cfg->pcre == NULL) {
        ib_log_error(ib, 2, "No PCRE matcher available (load the pcre module?)");
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }
    sig->cpatt = ib_matcher_compile(cfg->pcre, sig->patt, &errptr, &erroff);
    if (sig->cpatt == NULL) {
        ib_log_error(ib, 2, "Error at offset=%d of PCRE patt=\"%s\": %s",
                     erroff, sig->patt, errptr);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    ib_log_debug(ib, 4, "POCSIG: \"%s\" \"%s\" \"%s\" phase=%d ctx=%p",
                 target, op, action, phase, ctx);

    /* Add the signature to the phase list. */
    rc = ib_list_push(cfg->phase[phase], sig);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "Failed to add signature");
        IB_FTRACE_RET_STATUS(rc);
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}