static int msre_op_gsbLookup_execute()

in apache2/re_operators.c [1638:1967]


static int msre_op_gsbLookup_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
    msc_regex_t *regex = (msc_regex_t *)rule->op_param_data;
    char *my_error_msg = NULL;
    int ovector[33];
    unsigned int offset = 0;
    gsb_db *gsb = msr->txcfg->gsb;
    const char *match = NULL;
    unsigned int match_length;
    unsigned int canon_length;
    int rv, i, ret, count_slash;
    unsigned int j = 0;
    unsigned int size = var->value_len;
    char *base = NULL, *domain = NULL, *savedptr = NULL;
    char *str = NULL, *canon = NULL, *dot = NULL;
    char *data = NULL, *ptr = NULL, *url = NULL;
    int capture, domain_len;
    int d_pos = -1;
    int s_pos = -1;

    if (error_msg == NULL) return -1;
    *error_msg = NULL;

    if(regex == NULL)    {
        *error_msg = "Internal Error: regex is null.";
        return 0;
    }

    if(gsb == NULL)    {
        msr_log(msr, 1, "GSB lookup failed without a database.  Set SecGsbLookupDB.");
        return 0;
    }

    data = apr_pcalloc(rule->ruleset->mp, var->value_len+1);

    if(data == NULL)    {
        *error_msg = "Internal Error: cannot allocate memory for data.";
        return -1;
    }

    capture = apr_table_get(rule->actionset->actions, "capture") ? 1 : 0;

    memcpy(data,var->value,var->value_len);

    while (offset < size && (rv = msc_regexec_ex(regex, data, size, offset, PCRE_NOTEMPTY, ovector, 30, &my_error_msg)) >= 0)
    {
        for(i = 0; i < rv; ++i)
        {
            match = apr_psprintf(rule->ruleset->mp, "%.*s", ovector[2*i+1] - ovector[2*i], data + ovector[2*i]);

            if (match == NULL)  {
                *error_msg = "Internal Error: cannot allocate memory for match.";
                return -1;
            }

            match = remove_escape(rule->ruleset->mp, match, strlen(match));

            match = gsb_replace_tpath(rule->ruleset->mp, match, strlen(match));

            match = gsb_reduce_char(rule->ruleset->mp, match);

            match_length = strlen(match);

            strtolower_inplace((unsigned char *)match);

            if((strstr(match,"http") == NULL) && (match_length > 0) && (strchr(match,'.')))    {

                /* full url */
                if (msr->txcfg->debuglog_level >= 4) {
                    msr_log(msr, 4, "GSB: Successfully extracted url: %s", match);
                }

                ret = verify_gsb(gsb, msr, match, match_length);

                if(ret > 0) {
                    set_match_to_tx(msr, capture, match, 0);
                    if (! *error_msg) {
                        *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                log_escape_nq(msr->mp, match));
                    }

                    str = apr_pstrdup(rule->ruleset->mp,match);

                    base = apr_strtok(str,"/",&savedptr);
                    if(base != NULL)
                        set_match_to_tx(msr, capture, base, 1);

                    return 1;
                }

                /* append / in the end of full url */
                if ((match[match_length -1] != '/') && (strchr(match,'?') == NULL))    {

                    canon = apr_psprintf(rule->ruleset->mp, "%s/", match);
                    if (canon != NULL)  {

                        canon_length = strlen(canon);
                        ret = verify_gsb(gsb, msr, canon, canon_length);

                        if(ret > 0) {
                            set_match_to_tx(msr, capture, match, 0);
                            if (! *error_msg) {
                                *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                        log_escape_nq(msr->mp, canon));
                            }

                            str = apr_pstrdup(rule->ruleset->mp,match);

                            base = apr_strtok(str,"/",&savedptr);
                            if(base != NULL)
                                set_match_to_tx(msr, capture, base, 1);

                            return 1;
                        }
                    }
                }

                /* Parsing full url */

                domain = apr_pstrdup(rule->ruleset->mp, match);

                domain_len = strlen(domain);

                if(*domain != '/')  {

                    if(domain[domain_len-1] == '.')
                        domain[domain_len-1] = '\0';
                    if(domain[domain_len-1] == '/' && domain[domain_len-2] == '.')    {
                        domain[domain_len-2] = '/';
                        domain[domain_len-1] = '\0';
                    }

                    dot = strchr(domain,'.');
                    if(dot != NULL) {
                        canon = apr_pstrdup(rule->ruleset->mp, domain);

                        ret = verify_gsb(gsb, msr, canon, strlen(canon));

                        if(ret > 0) {
                            set_match_to_tx(msr, capture, canon, 0);
                            if (! *error_msg) {
                                *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                        log_escape_nq(msr->mp, canon));
                            }

                            str = apr_pstrdup(rule->ruleset->mp,match);

                            base = apr_strtok(str,"/",&savedptr);
                            if(base != NULL)
                                set_match_to_tx(msr, capture, base, 1);

                            return 1;
                        }


                        base = apr_strtok(canon,"?",&savedptr);

                        if(base != NULL)   {
                            ret = verify_gsb(gsb, msr, base, strlen(base));

                            if(ret > 0) {
                                set_match_to_tx(msr, capture, base, 0);
                                if (! *error_msg) {
                                    *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                            log_escape_nq(msr->mp, base));
                                }

                                str = apr_pstrdup(rule->ruleset->mp,match);

                                base = apr_strtok(str,"/",&savedptr);
                                if(base != NULL)
                                    set_match_to_tx(msr, capture, base, 1);

                                return 1;
                            }

                        }

                        url = apr_palloc(rule->ruleset->mp, strlen(canon));
                        count_slash = 0;

                        while(*canon != '\0') {
                            switch (*canon)   {
                                case '/':
                                    ptr = apr_psprintf(rule->ruleset->mp,"%s/",url);
                                    ret = verify_gsb(gsb, msr, ptr, strlen(ptr));
                                    if(ret > 0) {
                                        set_match_to_tx(msr, capture, ptr, 0);
                                        if (! *error_msg) {
                                            *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                                    log_escape_nq(msr->mp, ptr));
                                        }

                                        str = apr_pstrdup(rule->ruleset->mp,match);

                                        base = apr_strtok(str,"/",&savedptr);
                                        if(base != NULL)
                                            set_match_to_tx(msr, capture, base, 1);
                                        return 1;
                                    }

                                    break;
                            }
                            url[count_slash] = *canon;
                            count_slash++;
                            canon++;
                        }
                    }
                }

                /* Do the same for subdomains */

                for(j=0; j<strlen(match); j++)    {
                    if(match[j] == '/')    {
                        s_pos = j;
                        break;
                    }
                }


                str = apr_pstrdup(rule->ruleset->mp, match);

                while (*str != '\0')   {

                    switch(*str) {
                        case '.':
                            domain++;
                            domain_len = strlen(domain);

                            d_pos = strchr(domain,'.') - domain;

                            if(s_pos >= 0 && d_pos >= 0 && d_pos > s_pos)
                                break;

                            if(*domain != '/')  {

                                if(domain[domain_len-1] == '.')
                                    domain[domain_len-1] = '\0';
                                if(domain[domain_len-1] == '/' && domain[domain_len-2] == '.')    {
                                    domain[domain_len-2] = '/';
                                    domain[domain_len-1] = '\0';
                                }

                                dot = strchr(domain,'.');
                                if(dot != NULL) {
                                    canon = apr_pstrdup(rule->ruleset->mp, domain);

                                    ret = verify_gsb(gsb, msr, canon, strlen(canon));

                                    if(ret > 0) {
                                        set_match_to_tx(msr, capture, canon, 0);
                                        if (! *error_msg) {
                                            *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                                    log_escape_nq(msr->mp, canon));
                                        }
                                        str = apr_pstrdup(rule->ruleset->mp,match);

                                        base = apr_strtok(str,"/",&savedptr);
                                        if(base != NULL)
                                            set_match_to_tx(msr, capture, base, 1);
                                        return 1;
                                    }


                                    base = apr_strtok(canon,"?",&savedptr);

                                    if(base != NULL)   {
                                        ret = verify_gsb(gsb, msr, base, strlen(base));

                                        if(ret > 0) {
                                            set_match_to_tx(msr, capture, base, 0);
                                            if (! *error_msg) {
                                                *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                                        log_escape_nq(msr->mp, base));
                                            }
                                            str = apr_pstrdup(rule->ruleset->mp,match);

                                            base = apr_strtok(str,"/",&savedptr);
                                            if(base != NULL)
                                                set_match_to_tx(msr, capture, base, 1);
                                            return 1;
                                        }

                                    }

                                    url = apr_palloc(rule->ruleset->mp, strlen(canon));
                                    count_slash = 0;

                                    while(*canon != '\0') {
                                        switch (*canon)   {
                                            case '/':
                                                ptr = apr_psprintf(rule->ruleset->mp,"%s/",url);
                                                ret = verify_gsb(gsb, msr, ptr, strlen(ptr));
                                                if(ret > 0) {
                                                    set_match_to_tx(msr, capture, ptr, 0);
                                                    if (! *error_msg) {
                                                        *error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
                                                                log_escape_nq(msr->mp, ptr));
                                                    }
                                                    str = apr_pstrdup(rule->ruleset->mp,match);

                                                    base = apr_strtok(str,"/",&savedptr);
                                                    if(base != NULL)
                                                        set_match_to_tx(msr, capture, base, 1);
                                                    return 1;
                                                }

                                                break;
                                        }
                                        url[count_slash] = *canon;
                                        count_slash++;
                                        canon++;
                                    }
                                }
                            }
                            break;
                    }

                    domain = str;
                    domain++;
                    str++;
                }

            }
        }

        offset = ovector[1];
    }

    return 0;
}