Blame apache2/msc_parsers.c

Packit Service 384592
/*
Packit Service 384592
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
Packit Service 384592
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
Packit Service 384592
*
Packit Service 384592
* You may not use this file except in compliance with
Packit Service 384592
* the License.  You may obtain a copy of the License at
Packit Service 384592
*
Packit Service 384592
*     http://www.apache.org/licenses/LICENSE-2.0
Packit Service 384592
*
Packit Service 384592
* If any of the files related to licensing are missing or if you have any
Packit Service 384592
* other questions related to licensing please contact Trustwave Holdings, Inc.
Packit Service 384592
* directly using the email address security@modsecurity.org.
Packit Service 384592
*/
Packit Service 384592
Packit Service 384592
#include "msc_parsers.h"
Packit Service 384592
#include <ctype.h>
Packit Service 384592
Packit Service 384592
/**
Packit Service 384592
 *
Packit Service 384592
 */
Packit Service 384592
int parse_cookies_v0(modsec_rec *msr, char *_cookie_header,
Packit Service 384592
                     apr_table_t *cookies, const char *delim)
Packit Service 384592
{
Packit Service 384592
    char *attr_name = NULL, *attr_value = NULL;
Packit Service 384592
    char *cookie_header;
Packit Service 384592
    char *saveptr = NULL;
Packit Service 384592
    int cookie_count = 0;
Packit Service 384592
    char *p = NULL;
Packit Service 384592
Packit Service 384592
    if (_cookie_header == NULL) {
Packit Service 384592
        msr_log(msr, 1, "Cookie parser: Received null for argument.");
Packit Service 384592
        return -1;
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    cookie_header = strdup(_cookie_header);
Packit Service 384592
    if (cookie_header == NULL) return -1;
Packit Service 384592
Packit Service 384592
    if(msr->txcfg->cookiev0_separator == NULL) {
Packit Service 384592
        p = apr_strtok(cookie_header, delim, &saveptr);
Packit Service 384592
    } else {
Packit Service 384592
        p = apr_strtok(cookie_header, msr->txcfg->cookiev0_separator, &saveptr);
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    while(p != NULL) {
Packit Service 384592
        attr_name = NULL;
Packit Service 384592
        attr_value = NULL;
Packit Service 384592
Packit Service 384592
        /* ignore whitespace at the beginning of cookie name */
Packit Service 384592
        while(isspace(*p)) p++;
Packit Service 384592
        attr_name = p;
Packit Service 384592
Packit Service 384592
        attr_value = strstr(p, "=");
Packit Service 384592
        if (attr_value != NULL) {
Packit Service 384592
            /* terminate cookie name */
Packit Service 384592
            *attr_value = 0;
Packit Service 384592
            /* move over to the beginning of the value */
Packit Service 384592
            attr_value++;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        /* we ignore cookies with empty names */
Packit Service 384592
        if ((attr_name != NULL)&&(strlen(attr_name) != 0)) {
Packit Service 384592
            if (attr_value != NULL) {
Packit Service 384592
                if (msr->txcfg->debuglog_level >= 5) {
Packit Service 384592
                    msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"",
Packit Service 384592
                            log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value));
Packit Service 384592
                }
Packit Service 384592
Packit Service 384592
                apr_table_add(cookies, attr_name, attr_value);
Packit Service 384592
            } else {
Packit Service 384592
                if (msr->txcfg->debuglog_level >= 5) {
Packit Service 384592
                    msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty",
Packit Service 384592
                            log_escape(msr->mp, attr_name));
Packit Service 384592
                }
Packit Service 384592
Packit Service 384592
                apr_table_add(cookies, attr_name, "");
Packit Service 384592
            }
Packit Service 384592
Packit Service 384592
            cookie_count++;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        if(msr->txcfg->cookiev0_separator == NULL) {
Packit Service 384592
            p = apr_strtok(NULL, delim, &saveptr);
Packit Service 384592
        } else {
Packit Service 384592
            p = apr_strtok(NULL, msr->txcfg->cookiev0_separator, &saveptr);
Packit Service 384592
        }
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    free(cookie_header);
Packit Service 384592
    return cookie_count;
Packit Service 384592
}
Packit Service 384592
Packit Service 384592
/**
Packit Service 384592
 *
Packit Service 384592
 */
Packit Service 384592
int parse_cookies_v1(modsec_rec *msr, char *_cookie_header,
Packit Service 384592
        apr_table_t *cookies)
Packit Service 384592
{
Packit Service 384592
    char *attr_name = NULL, *attr_value = NULL, *p = NULL;
Packit Service 384592
    char *prev_attr_name = NULL;
Packit Service 384592
    char *cookie_header = NULL;
Packit Service 384592
    int cookie_count = 0;
Packit Service 384592
Packit Service 384592
    if (_cookie_header == NULL) return -1;
Packit Service 384592
    // XXX Should it not match _v0 parser?
Packit Service 384592
    //if (_cookie_header == NULL) {
Packit Service 384592
    //    msr_log(msr, 1, "Cookie parser: Received null for argument.");
Packit Service 384592
    //    return -1;
Packit Service 384592
    //}
Packit Service 384592
Packit Service 384592
    cookie_header = strdup(_cookie_header);
Packit Service 384592
    if (cookie_header == NULL) return -1;
Packit Service 384592
Packit Service 384592
    p = cookie_header;
Packit Service 384592
    while(*p != 0) {
Packit Service 384592
        attr_name = NULL;
Packit Service 384592
        attr_value = NULL;
Packit Service 384592
Packit Service 384592
        /* attribute name */
Packit Service 384592
Packit Service 384592
        /* remove space from the beginning */
Packit Service 384592
        while((isspace(*p))&&(*p != 0)) p++;
Packit Service 384592
        attr_name = p;
Packit Service 384592
        while((*p != 0)&&(*p != '=')&&(*p != ';')&&(*p != ',')) p++;
Packit Service 384592
Packit Service 384592
        /* if we've reached the end of string */
Packit Service 384592
        if (*p == 0) goto add_cookie;
Packit Service 384592
Packit Service 384592
        /* if there is no cookie value supplied */
Packit Service 384592
        if ((*p == ';')||(*p == ',')) {
Packit Service 384592
            *p++ = 0; /* terminate the name */
Packit Service 384592
            goto add_cookie;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        /* terminate the attribute name,
Packit Service 384592
         * writing over the = character
Packit Service 384592
         */
Packit Service 384592
        *p++ = 0;
Packit Service 384592
Packit Service 384592
        /* attribute value */
Packit Service 384592
Packit Service 384592
        /* skip over the whitespace at the beginning */
Packit Service 384592
        while((isspace(*p))&&(*p != 0)) p++;
Packit Service 384592
Packit Service 384592
        /* no value supplied */
Packit Service 384592
        if (*p == 0) goto add_cookie;
Packit Service 384592
Packit Service 384592
        if (*p == '"') {
Packit Service 384592
            if (*++p == 0) goto add_cookie;
Packit Service 384592
            attr_value = p;
Packit Service 384592
            while((*p != 0)&&(*p != '"')) p++;
Packit Service 384592
            if (*p != 0) *p++ = 0;
Packit Service 384592
            else {
Packit Service 384592
                /* Do nothing about this. */
Packit Service 384592
            }
Packit Service 384592
        } else {
Packit Service 384592
            attr_value = p;
Packit Service 384592
            while((*p != 0)&&(*p != ',')&&(*p != ';')) p++;
Packit Service 384592
            if (*p != 0) *p++ = 0;
Packit Service 384592
Packit Service 384592
            /* remove the whitespace from the end of cookie value */
Packit Service 384592
            if (attr_value != NULL) {
Packit Service 384592
                char *t = attr_value;
Packit Service 384592
                int i = 0;
Packit Service 384592
Packit Service 384592
                while(*t != 0) {
Packit Service 384592
                    t++;
Packit Service 384592
                    i++;
Packit Service 384592
                }
Packit Service 384592
Packit Service 384592
                while((i-- > 0)&&(isspace(*(--t)))) *t = 0;
Packit Service 384592
            }
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
add_cookie:
Packit Service 384592
Packit Service 384592
        /* remove the whitespace from the end of cookie name */
Packit Service 384592
        if (attr_name != NULL) {
Packit Service 384592
            char *t = attr_name;
Packit Service 384592
            int i = 0;
Packit Service 384592
Packit Service 384592
            while(*t != 0) {
Packit Service 384592
                t++;
Packit Service 384592
                i++;
Packit Service 384592
            }
Packit Service 384592
Packit Service 384592
            while((i-- > 0)&&(isspace(*(--t)))) *t = 0;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        /* add the cookie to the list now */
Packit Service 384592
        if ((attr_name != NULL)&&(strlen(attr_name) != 0)) {
Packit Service 384592
Packit Service 384592
            /* handle special attribute names */
Packit Service 384592
            if (attr_name[0] == '$') {
Packit Service 384592
                if (prev_attr_name != NULL) {
Packit Service 384592
                    /* cookie keyword, we change the name we use
Packit Service 384592
                     * so they can have a unique name in the cookie table
Packit Service 384592
                     */
Packit Service 384592
                    attr_name = apr_psprintf(msr->mp, "$%s_%s", prev_attr_name, attr_name + 1);
Packit Service 384592
                }
Packit Service 384592
            }
Packit Service 384592
Packit Service 384592
            if (attr_value != NULL) {
Packit Service 384592
                if (msr->txcfg->debuglog_level >= 5) {
Packit Service 384592
                    msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"",
Packit Service 384592
                            log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value));
Packit Service 384592
                }
Packit Service 384592
Packit Service 384592
                apr_table_add(cookies, attr_name, attr_value);
Packit Service 384592
            } else {
Packit Service 384592
                if (msr->txcfg->debuglog_level >= 5) {
Packit Service 384592
                    msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty",
Packit Service 384592
                            log_escape(msr->mp, attr_name));
Packit Service 384592
                }
Packit Service 384592
Packit Service 384592
                apr_table_add(cookies, attr_name, "");
Packit Service 384592
            }
Packit Service 384592
Packit Service 384592
            cookie_count++;
Packit Service 384592
Packit Service 384592
            /* only keep the cookie names for later */
Packit Service 384592
            if (attr_name[0] != '$') prev_attr_name = attr_name;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        /* at this point the *p is either 0 (in which case we exit), or
Packit Service 384592
         * right after the current cookie ended - we need to look for
Packit Service 384592
         * the next cookie
Packit Service 384592
         */
Packit Service 384592
        while( (*p != 0)&&( (*p == ',')||(*p == ';')||(isspace(*p)) ) ) p++;
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    free(cookie_header);
Packit Service 384592
    return cookie_count;
Packit Service 384592
}
Packit Service 384592
Packit Service 384592
/**
Packit Service 384592
 *
Packit Service 384592
 */
Packit Service 384592
int parse_arguments(modsec_rec *msr, const char *s, apr_size_t inputlength,
Packit Service 384592
        int argument_separator, const char *origin,
Packit Service 384592
        apr_table_t *arguments, int *invalid_count)
Packit Service 384592
{
Packit Service 384592
    msc_arg *arg;
Packit Service 384592
    apr_size_t i, j;
Packit Service 384592
    char *value = NULL;
Packit Service 384592
    char *buf;
Packit Service 384592
    int status;
Packit Service 384592
    int changed;
Packit Service 384592
Packit Service 384592
    if (s == NULL) return -1;
Packit Service 384592
    if (inputlength == 0) return 1;
Packit Service 384592
Packit Service 384592
    /* Check that adding one will not overflow */
Packit Service 384592
    if (inputlength + 1 <= 0) return -1;
Packit Service 384592
Packit Service 384592
    buf = (char *)malloc(inputlength + 1);
Packit Service 384592
    if (buf == NULL) return -1;
Packit Service 384592
Packit Service 384592
    arg = (msc_arg *)apr_pcalloc(msr->mp, sizeof(msc_arg));
Packit Service 384592
    arg->origin = origin;
Packit Service 384592
Packit Service 384592
    i = 0;
Packit Service 384592
    j = 0;
Packit Service 384592
    status = 0;
Packit Service 384592
    *invalid_count = 0;
Packit Service 384592
    while (i < inputlength) {
Packit Service 384592
        if (status == 0) {
Packit Service 384592
            /* parameter name */
Packit Service 384592
            arg->name_origin_offset = i;
Packit Service 384592
            while ((s[i] != '=') && (s[i] != argument_separator) && (i < inputlength)) {
Packit Service 384592
                buf[j] = s[i];
Packit Service 384592
                j++;
Packit Service 384592
                i++;
Packit Service 384592
            }
Packit Service 384592
            buf[j++] = '\0';
Packit Service 384592
            arg->name_origin_len = i - arg->name_origin_offset;
Packit Service 384592
        } else {
Packit Service 384592
            /* parameter value */
Packit Service 384592
            arg->value_origin_offset = i;
Packit Service 384592
            while ((s[i] != argument_separator) && (i < inputlength)) {
Packit Service 384592
                buf[j] = s[i];
Packit Service 384592
                j++;
Packit Service 384592
                i++;
Packit Service 384592
            }
Packit Service 384592
            buf[j++] = '\0';
Packit Service 384592
            arg->value_origin_len = i - arg->value_origin_offset;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        if (status == 0) {
Packit Service 384592
            arg->name_len = urldecode_nonstrict_inplace_ex((unsigned char *)buf, arg->name_origin_len, invalid_count, &changed);
Packit Service 384592
            arg->name = apr_pstrmemdup(msr->mp, buf, arg->name_len);
Packit Service 384592
Packit Service 384592
            if (s[i] == argument_separator) {
Packit Service 384592
                /* Empty parameter */
Packit Service 384592
                arg->value_len = 0;
Packit Service 384592
                arg->value = "";
Packit Service 384592
Packit Service 384592
                add_argument(msr, arguments, arg);
Packit Service 384592
Packit Service 384592
                arg = (msc_arg *)apr_pcalloc(msr->mp, sizeof(msc_arg));
Packit Service 384592
                arg->origin = origin;
Packit Service 384592
Packit Service 384592
                status = 0; /* unchanged */
Packit Service 384592
                j = 0;
Packit Service 384592
            } else {
Packit Service 384592
                status = 1;
Packit Service 384592
                value = &buf[j];
Packit Service 384592
            }
Packit Service 384592
        }
Packit Service 384592
        else {
Packit Service 384592
            arg->value_len = urldecode_nonstrict_inplace_ex((unsigned char *)value, arg->value_origin_len, invalid_count, &changed);
Packit Service 384592
            arg->value = apr_pstrmemdup(msr->mp, value, arg->value_len);
Packit Service 384592
Packit Service 384592
            add_argument(msr, arguments, arg);
Packit Service 384592
Packit Service 384592
            arg = (msc_arg *)apr_pcalloc(msr->mp, sizeof(msc_arg));
Packit Service 384592
            arg->origin = origin;
Packit Service 384592
Packit Service 384592
            status = 0;
Packit Service 384592
            j = 0;
Packit Service 384592
        }
Packit Service 384592
Packit Service 384592
        i++; /* skip over the separator */
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    /* the last parameter was empty */
Packit Service 384592
    if (status == 1) {
Packit Service 384592
        arg->value_len = 0;
Packit Service 384592
        arg->value = "";
Packit Service 384592
Packit Service 384592
        add_argument(msr, arguments, arg);
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    free(buf);
Packit Service 384592
Packit Service 384592
    return 1;
Packit Service 384592
}
Packit Service 384592
Packit Service 384592
/**
Packit Service 384592
 *
Packit Service 384592
 */
Packit Service 384592
void add_argument(modsec_rec *msr, apr_table_t *arguments, msc_arg *arg)
Packit Service 384592
{
Packit Service 384592
    if (msr->txcfg->debuglog_level >= 5) {
Packit Service 384592
        msr_log(msr, 5, "Adding request argument (%s): name \"%s\", value \"%s\"",
Packit Service 384592
                arg->origin, log_escape_ex(msr->mp, arg->name, arg->name_len),
Packit Service 384592
                log_escape_ex(msr->mp, arg->value, arg->value_len));
Packit Service 384592
    }
Packit Service 384592
Packit Service 384592
    apr_table_addn(arguments, log_escape_nq_ex(msr->mp, arg->name, arg->name_len), (void *)arg);
Packit Service 384592
}
Packit Service 384592