示例#1
0
文件: log.c 项目: liamslynch/ironbee
void DLL_PUBLIC ib_log_vex_ex(
    const ib_engine_t *ib,
    ib_log_level_t     level,
    const char        *file,
    int                line,
    const char        *fmt,
    va_list            ap
)
{
    /* Check the log level, return if we're not interested. */
    ib_log_level_t logger_level = ib_log_get_level(ib);
    if (level > logger_level) {
        return;
    }

    if (ib->logger_fn != NULL) {
        ib->logger_fn(ib, level, file, line, fmt, ap, ib->logger_cbdata);
    }
    else {
        default_logger(stderr, level, ib, file, line, fmt, ap);
    }
}
示例#2
0
/**
 * @brief Execute the rule.
 *
 * @param[in] ib Ironbee engine
 * @param[in] tx The transaction.
 * @param[in,out] User data. A @c pcre_rule_data_t.
 * @param[in] flags Operator instance flags
 * @param[in] field The field content.
 * @param[out] result The result.
 * @returns IB_OK most times. IB_EALLOC when a memory allocation error handles.
 */
static ib_status_t pcre_operator_execute(ib_engine_t *ib,
                                         ib_tx_t *tx,
                                         const ib_rule_t *rule,
                                         void *data,
                                         ib_flags_t flags,
                                         ib_field_t *field,
                                         ib_num_t *result)
{
    IB_FTRACE_INIT();

    assert(ib!=NULL);
    assert(tx!=NULL);
    assert(tx->dpi!=NULL);
    assert(data!=NULL);

    int matches;
    ib_status_t ib_rc;
    const int ovecsize = 3 * MATCH_MAX;
    int *ovector = (int *)malloc(ovecsize*sizeof(*ovector));
    const char* subject = NULL;
    size_t subject_len = 0;
    const ib_bytestr_t* bytestr;
    pcre_rule_data_t *rule_data = (pcre_rule_data_t *)data;
    pcre_extra *edata = NULL;
#ifdef PCRE_JIT_STACK
    pcre_jit_stack *jit_stack = pcre_jit_stack_alloc(PCRE_JIT_MIN_STACK_SZ,
                                                     PCRE_JIT_MAX_STACK_SZ);
#endif

    if (ovector==NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    if (field->type == IB_FTYPE_NULSTR) {
        ib_rc = ib_field_value(field, ib_ftype_nulstr_out(&subject));
        if (ib_rc != IB_OK) {
            free(ovector);
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        if (subject != NULL) {
            subject_len = strlen(subject);
        }
    }
    else if (field->type == IB_FTYPE_BYTESTR) {
        ib_rc = ib_field_value(field, ib_ftype_bytestr_out(&bytestr));
        if (ib_rc != IB_OK) {
            free(ovector);
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        if (bytestr != NULL) {
            subject_len = ib_bytestr_length(bytestr);
            subject = (const char *) ib_bytestr_const_ptr(bytestr);
        }
    }
    else {
        free(ovector);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    if (subject == NULL) {
        subject     = "";
    }

    /* Debug block. Escapes a string and prints it to the log.
     * Memory is freed. */
    if (ib_log_get_level(ib) >= 9) {

        /* Worst case, we can have a string that is 4x larger.
         * Consider if a string of 0xF7 is passed.  That single character
         * will expand to a string of 4 printed characters +1 for the \0
         * character. */
        char *debug_str = ib_util_hex_escape(subject, subject_len);

        if ( debug_str != NULL ) {
            ib_log_debug3_tx(tx, "Matching against: %s", debug_str);
            free( debug_str );
        }
    }

#ifdef PCRE_JIT_STACK
    /* Log if we expected jit, but did not get it. */
    if (rule_data->is_jit && jit_stack == NULL) {
        ib_log_debug(ib,
                     "Failed to allocate a jit stack for a jit-compiled rule. "
                     "Not using jit for this call.");
        edata = NULL;
    }

    /* If the study data is NULL or size zero, don't use it. */
    else if (rule_data->edata == NULL || rule_data->study_data_sz <= 0) {
        edata = NULL;
    }

    /* Only if we get here do we use the study data (edata) in the rule_data. */
    else {
        edata = rule_data->edata;
        pcre_assign_jit_stack(rule_data->edata, NULL, jit_stack);
    }

#endif

    matches = pcre_exec(rule_data->cpatt,
                        edata,
                        subject,
                        subject_len,
                        0, /* Starting offset. */
                        0, /* Options. */
                        ovector,
                        ovecsize);

#ifdef PCRE_JIT_STACK
    if (jit_stack != NULL) {
        pcre_jit_stack_free(jit_stack);
    }
#endif

    if (matches > 0) {
        if (ib_flags_all(rule->flags, IB_RULE_FLAG_CAPTURE) == true) {
            pcre_set_matches(ib, tx, ovector, matches, subject);
        }
        ib_rc = IB_OK;
        *result = 1;
    }
    else if (matches == PCRE_ERROR_NOMATCH) {

        if (ib_log_get_level(ib) >= 7) {
            char* tmp_c = malloc(subject_len+1);
            memcpy(tmp_c, subject, subject_len);
            tmp_c[subject_len] = '\0';
            /* No match. Return false to the caller (*result = 0). */
            ib_log_debug2_tx(tx, "No match for [%s] using pattern [%s].",
                        tmp_c,
                        rule_data->patt);
            free(tmp_c);
        }


        ib_rc = IB_OK;
        *result = 0;
    }
    else {
        /* Some other error occurred. Set the status to false and
        report the error. */
        ib_rc = IB_EUNKNOWN;
        *result = 0;
    }

    free(ovector);
    IB_FTRACE_RET_STATUS(ib_rc);
}
示例#3
0
/**
 * @brief Execute the rule.
 *
 * @param[in] ib Ironbee engine
 * @param[in] tx The transaction.
 * @param[in,out] User data. A @c pcre_rule_data_t.
 * @param[in] flags Operator instance flags
 * @param[in] field The field content.
 * @param[out] result The result.
 * @returns IB_OK most times. IB_EALLOC when a memory allocation error handles.
 */
static ib_status_t dfa_operator_execute(ib_engine_t *ib,
                                        ib_tx_t *tx,
                                        const ib_rule_t *rule,
                                        void *data,
                                        ib_flags_t flags,
                                        ib_field_t *field,
                                        ib_num_t *result)
{
    IB_FTRACE_INIT();
    assert(tx);
    assert(data);


    int matches;
    ib_status_t ib_rc;
    const int ovecsize = 3 * MATCH_MAX;
    dfa_rule_data_t *rule_data;
    int *ovector;
    const char* subject;
    size_t subject_len;
    const ib_bytestr_t* bytestr;
    dfa_workspace_t *dfa_workspace;
    int options; /* dfa exec options. */

    ovector = (int *)malloc(ovecsize*sizeof(*ovector));
    if (ovector==NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    /* Pull out the rule data. */
    rule_data = (dfa_rule_data_t *)data;


    if (field->type == IB_FTYPE_NULSTR) {
        ib_rc = ib_field_value(field, ib_ftype_nulstr_out(&subject));
        if (ib_rc != IB_OK) {
            free(ovector);
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        subject_len = strlen(subject);
    }
    else if (field->type == IB_FTYPE_BYTESTR) {
        ib_rc = ib_field_value(field, ib_ftype_bytestr_out(&bytestr));
        if (ib_rc != IB_OK) {
            free(ovector);
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        subject_len = ib_bytestr_length(bytestr);
        subject = (const char *) ib_bytestr_const_ptr(bytestr);
    }
    else {
        free(ovector);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* Debug block. Escapes a string and prints it to the log.
     * Memory is freed. */
    if (ib_log_get_level(ib) >= 9) {

        /* Worst case, we can have a string that is 4x larger.
         * Consider if a string of 0xF7 is passed.  That single character
         * will expand to a string of 4 printed characters +1 for the \0
         * character. */
        char *debug_str = ib_util_hex_escape(subject, subject_len);

        if ( debug_str != NULL ) {
            ib_log_debug3_tx(tx, "Matching against: %s", debug_str);
            free( debug_str );
        }
    }

    /* Get the per-tx workspace data for this rule data id. */
    ib_rc = get_dfa_tx_data(tx, rule_data->id, &dfa_workspace);
    if (ib_rc == IB_ENOENT) {
        options = PCRE_PARTIAL_SOFT;

        ib_rc = alloc_dfa_tx_data(tx, rule_data->id, &dfa_workspace);
        if (ib_rc != IB_OK) {
            free(ovector);
            ib_log_error_tx(tx, "Unexpected error creating tx storage "
                                "for dfa operator %s",
                                rule_data->id);
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        ib_log_debug_tx(tx,
                       "Created DFA workspace at %p for id %s.",
                        dfa_workspace,
                        rule_data->id);
    }
    else if (ib_rc == IB_OK) {
        options = PCRE_PARTIAL_SOFT | PCRE_DFA_RESTART;
        ib_log_debug_tx(tx,
                        "Reusing existing DFA workspace %p for id %s.",
                        dfa_workspace,
                        rule_data->id);
    }
    else {
        free(ovector);
        ib_log_error_tx(tx,
                        "Unexpected error fetching dfa data "
                        "for dfa operator %s",
                        rule_data->id);
        IB_FTRACE_RET_STATUS(ib_rc);
    }

    /* Actually do the DFA match. */
    matches = pcre_dfa_exec(rule_data->cpatt,
                            rule_data->edata,
                            subject,
                            subject_len,
                            0, /* Starting offset. */
                            options,
                            ovector,
                            ovecsize,
                            dfa_workspace->workspace,
                            dfa_workspace->wscount);

    if (matches >= 0) {
        ib_rc = IB_OK;
        *result = 1;
    }
    else if (matches == PCRE_ERROR_PARTIAL) {
        ib_log_debug2_tx(tx, "Partial match found, but not a full match.");
        ib_rc = IB_OK;
        *result = 0;
    }
    else if (matches == PCRE_ERROR_NOMATCH) {

        if (ib_log_get_level(ib) >= 7) {
            char* tmp_c = malloc(subject_len+1);
            memcpy(tmp_c, subject, subject_len);
            tmp_c[subject_len] = '\0';
            /* No match. Return false to the caller (*result = 0). */
            ib_log_debug2_tx(tx, "No match for [%s] using pattern [%s].",
                        tmp_c,
                        rule_data->patt);
            free(tmp_c);
        }

        ib_rc = IB_OK;
        *result = 0;
    }
    else {
        /* Some other error occurred. Set the status to false and
        report the error. */
        ib_rc = IB_EUNKNOWN;
        *result = 0;
    }

    free(ovector);
    IB_FTRACE_RET_STATUS(ib_rc);
}
示例#4
0
文件: pcre.c 项目: nickleroy/ironbee
/**
 * @brief Execute the rule.
 *
 * @param[in] ib Ironbee engine
 * @param[in] tx The transaction.
 * @param[in,out] User data. A @c pcre_rule_data_t.
 * @param[in] flags Operator instance flags
 * @param[in] field The field content.
 * @param[in] result The result.
 * @returns IB_OK most times. IB_EALLOC when a memory allocation error handles.
 */
static ib_status_t pcre_operator_execute(ib_engine_t *ib,
                                         ib_tx_t *tx,
                                         void *data,
                                         ib_flags_t flags,
                                         ib_field_t *field,
                                         ib_num_t *result)
{
    IB_FTRACE_INIT();

    assert(ib!=NULL);
    assert(tx!=NULL);
    assert(tx->dpi!=NULL);
    assert(data!=NULL);

    int matches;
    ib_status_t ib_rc;
    const int ovecsize = 3 * MATCH_MAX;
    int *ovector = (int *)malloc(ovecsize*sizeof(*ovector));
    const char* subject;
    size_t subject_len;
    const ib_bytestr_t* bytestr;
    pcre_rule_data_t *rule_data = (pcre_rule_data_t *)data;
    pcre *regex;
    pcre_extra *regex_extra = NULL;
#ifdef PCRE_JIT_STACK
    pcre_jit_stack *jit_stack = pcre_jit_stack_alloc(PCRE_JIT_MIN_STACK_SZ,
                                                     PCRE_JIT_MAX_STACK_SZ);
#endif

    if (ovector==NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    if (field->type == IB_FTYPE_NULSTR) {
        ib_rc = ib_field_value(field, ib_ftype_nulstr_out(&subject));
        if (ib_rc != IB_OK) {
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        subject_len = strlen(subject);
    }
    else if (field->type == IB_FTYPE_BYTESTR) {
        ib_rc = ib_field_value(field, ib_ftype_bytestr_out(&bytestr));
        if (ib_rc != IB_OK) {
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        subject_len = ib_bytestr_length(bytestr);
        subject = (const char *) ib_bytestr_const_ptr(bytestr);
    }
    else {
        free(ovector);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    /* Debug block. Escapes a string and prints it to the log.
     * Memory is freed. */
    if (ib_log_get_level(ib) >= 9) {

        /* Worst case, we can have a string that is 4x larger.
         * Consider if a string of 0xF7 is passed.  That single character
         * will expand to a string of 4 printed characters +1 for the \0
         * character. */
        char *debug_str = ib_util_hex_escape(subject, subject_len);

        if ( debug_str != NULL ) {
            ib_log_debug3_tx(tx, "Matching against: %s", debug_str);
            free( debug_str );
        }
    }

    /* Alloc space to copy regex. */
    regex = (pcre *)malloc(rule_data->cpatt_sz);

    if (regex == NULL ) {
        free(ovector);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    memcpy(regex, rule_data->cpatt, rule_data->cpatt_sz);

    if (rule_data->study_data_sz == 0 ) {
        regex_extra = NULL;
    }
    else {
        regex_extra = (pcre_extra *) malloc(sizeof(*regex_extra));

        if (regex_extra == NULL ) {
            free(ovector);
            free(regex);
            IB_FTRACE_RET_STATUS(IB_EALLOC);
        }
        *regex_extra = *rule_data->edata;

        if ( rule_data->study_data_sz == 0 ) {
            regex_extra->study_data = NULL;
        }
        else {
            regex_extra->study_data = malloc(rule_data->study_data_sz);

            if (regex_extra->study_data == NULL ) {
                free(ovector);
                if (regex_extra != NULL) {
                    free(regex_extra);
                }
                free(regex);
                IB_FTRACE_RET_STATUS(IB_EALLOC);
            }

            memcpy(regex_extra->study_data,
                   rule_data->edata->study_data,
                   rule_data->study_data_sz);
        }

        /* Put some modest limits on our regex. */
        regex_extra->match_limit = 1000;
        regex_extra->match_limit_recursion = 1000;
        regex_extra->flags = regex_extra->flags |
                            PCRE_EXTRA_MATCH_LIMIT |
                            PCRE_EXTRA_MATCH_LIMIT_RECURSION;
    }

#ifdef PCRE_JIT_STACK
    if (jit_stack == NULL) {
        if ( regex_extra != NULL ) {
            if ( regex_extra->study_data != NULL ) {
                free(regex_extra->study_data);
            }

            free(regex_extra);
        }
        free(ovector);
        free(regex);
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    pcre_assign_jit_stack(regex_extra, NULL, jit_stack);
#endif

    matches = pcre_exec(regex,
                        regex_extra,
                        subject,
                        subject_len,
                        0, /* Starting offset. */
                        0, /* Options. */
                        ovector,
                        ovecsize);

#ifdef PCRE_JIT_STACK
    pcre_jit_stack_free(jit_stack);
#endif

    if (matches > 0) {
        pcre_set_matches(ib, tx, "TX", ovector, matches, subject);
        ib_rc = IB_OK;
        *result = 1;
    }
    else if (matches == PCRE_ERROR_NOMATCH) {

        if (ib_log_get_level(ib) >= 7) {
            char* tmp_c = malloc(subject_len+1);
            memcpy(tmp_c, subject, subject_len);
            tmp_c[subject_len] = '\0';
            /* No match. Return false to the caller (*result = 0). */
            ib_log_debug2_tx(tx, "No match for [%s] using pattern [%s].",
                        tmp_c,
                        rule_data->patt);
            free(tmp_c);
        }


        ib_rc = IB_OK;
        *result = 0;
    }
    else {
        /* Some other error occurred. Set the status to false and
        report the error. */
        ib_rc = IB_EUNKNOWN;
        *result = 0;
    }

    if ( regex_extra != NULL ) {
        if ( regex_extra->study_data != NULL ) {
            free(regex_extra->study_data);
        }

        free(regex_extra);
    }
    free(ovector);
    free(regex);
    IB_FTRACE_RET_STATUS(ib_rc);
}
示例#5
0
文件: pcre.c 项目: nickleroy/ironbee
/**
 * Set the matches into the given field name as .0, .1, .2 ... .9.
 *
 * @param[in] ib The IronBee engine to log to.
 * @param[in] tx The transaction to store the values into (tx->dpi).
 * @param[in] field_name The field to populate with Regex matches.
 * @param[in] ovector The vector of integer pairs of matches from PCRE.
 * @param[in] matches The number of matches.
 * @param[in] subject The matched-against string data.
 *
 * @returns IB_OK or IB_EALLOC.
 */
static ib_status_t pcre_set_matches(ib_engine_t *ib,
                                    ib_tx_t *tx,
                                    const char* field_name,
                                    int *ovector,
                                    int matches,
                                    const char *subject)
{
    IB_FTRACE_INIT();

    /* IronBee status. */
    ib_status_t rc;

    /* Iterator. */
    int i;

    /* Length of field_name. */
    const int field_name_sz = strlen(field_name);

    /* The length of the match. */
    size_t match_len;

    /* The first character in the match. */
    const char* match_start;

    /* +3 = '.', [digit], and \0. */
    char *full_field_name = malloc(field_name_sz+3);

    /* Holder to build an optional debug message in. */
    char *debug_msg;

    /* Holder for a copy of the field value when creating a new field. */
    ib_bytestr_t *field_value;

    /* Field holder. */
    ib_field_t *ib_field;

    /* Ensure the above allocations happened. */
    if (full_field_name==NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    rc = ensure_field_exists(ib, tx, field_name);
    if (rc != IB_OK) {
        ib_log_alert_tx(tx, "Could not ensure that field %s was a list.",
            field_name);
        free(full_field_name);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* We have a match! Now populate TX.0-9 in tx->dpi. */
    for (i=0; i<matches; i++)
    {
        /* Build the field name. Typically TX.0, TX.1 ... TX.9 */
        sprintf(full_field_name, "%s.%d", field_name, i);

        /* Readability. Mark the start and length of the string. */
        match_start = subject+ovector[i*2];
        match_len = ovector[i*2+1] - ovector[i*2];

        /* If debugging this, copy the string value out and print it to the
         * log. This could be dangerous as there could be non-character
         * values in the match. */
        if (ib_log_get_level(ib) >= 7) {
            debug_msg = malloc(match_len+1);

            /* Notice: Don't provoke a crash if malloc fails. */
            if (debug_msg != NULL) {
                memcpy(debug_msg, match_start, match_len);
                debug_msg[match_len] = '\0';

                ib_log_debug2_tx(tx, "REGEX Setting %s=%s",
                            full_field_name,
                            debug_msg);

                free(debug_msg);
            }
        }

        ib_data_get(tx->dpi, full_field_name, &ib_field);

        if (ib_field == NULL) {
            ib_data_add_bytestr(tx->dpi,
                                full_field_name,
                                (uint8_t*)subject+ovector[i*2],
                                match_len,
                                NULL);
        }
        else {
            ib_bytestr_dup_mem(&field_value,
                               tx->mp,
                               (const uint8_t*)match_start,
                               match_len);
            ib_field_setv_no_copy(
                ib_field,
                ib_ftype_bytestr_mutable_in(field_value)
            );
        }
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}