|
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 |
|