Beispiel #1
0
/**
 * @brief Execute the PCRE operator
 *
 * @param[in] tx Current transaction.
 * @param[in] instance_data Instance data needed for execution.
 * @param[in] field The field to operate on.
 * @param[in] capture If non-NULL, the collection to capture to.
 * @param[out] result The result of the operator 1=true 0=false.
 * @param[in] cbdata Callback data.
 *
 * @returns IB_OK most times. IB_EALLOC when a memory allocation error handles.
 */
static
ib_status_t pcre_operator_execute(
    ib_tx_t *tx,
    void *instance_data,
    const ib_field_t *field,
    ib_field_t *capture,
    ib_num_t *result,
    void *cbdata
)
{
    assert(instance_data != NULL);
    assert(tx            != 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;
    modpcre_operator_data_t *operator_data =
        (modpcre_operator_data_t *)instance_data;
    pcre_extra *edata = NULL;
#ifdef PCRE_JIT_STACK
    pcre_jit_stack *jit_stack = NULL;
#endif

    assert(operator_data->cpdata->is_dfa == false);

    if (ovector==NULL) {
        return 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);
            return 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);
            return ib_rc;
        }

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

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

    if (operator_data->cpdata->is_jit) {
#ifdef PCRE_JIT_STACK
        jit_stack = pcre_jit_stack_alloc(operator_data->cpdata->jit_stack_start,
                                         operator_data->cpdata->jit_stack_max);
        if (jit_stack == NULL) {
            ib_log_warn(ib,
                "Failed to allocate a jit stack for a jit-compiled rule.  "
                "Not using jit for this call."
            );
        }
        /* If the study data is NULL or size zero, don't use it. */
        else if (operator_data->cpdata->study_data_sz > 0) {
            edata = operator_data->cpdata->edata;
        }
        if (edata != NULL) {
            pcre_assign_jit_stack(edata, NULL, jit_stack);
        }
#else
        edata = NULL;
#endif
    }
    else if (operator_data->cpdata->study_data_sz > 0) {
        edata = operator_data->cpdata->edata;
    }
    else {
        edata = NULL;
    }

    matches = pcre_exec(operator_data->cpdata->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 (capture != NULL) {
            pcre_set_matches(tx, capture, ovector, matches, subject);
        }
        ib_rc = IB_OK;
        *result = 1;
    }
    else if (matches == PCRE_ERROR_NOMATCH) {
        ib_rc = IB_OK;
        *result = 0;
    }
    else {
        /* Some other error occurred. Set the status to false return the
         * error. */
        ib_rc = IB_EUNKNOWN;
        *result = 0;
    }

    free(ovector);
    return ib_rc;
}
Beispiel #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);
}
Beispiel #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[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);
}