2 * ModSecurity for Apache 2.x, http://www.modsecurity.org/
3 * Copyright (c) 2004-2009 Breach Security, Inc. (http://www.breach.com/)
5 * This product is released under the terms of the General Public Licence,
6 * version 2 (GPLv2). Please refer to the file LICENSE (included with this
7 * distribution) which contains the complete text of the licence.
9 * There are special exceptions to the terms and conditions of the GPL
10 * as it is applied to this software. View the full text of the exception in
11 * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software
14 * If any of the files related to licensing are missing or if you have any
15 * other questions related to licensing please contact Breach Security, Inc.
16 * directly using the email address support@breach.com.
19 #include "msc_parsers.h"
25 int parse_cookies_v0(modsec_rec *msr, char *_cookie_header, apr_table_t *cookies) {
26 char *attr_name = NULL, *attr_value = NULL;
32 if (_cookie_header == NULL) {
33 msr_log(msr, 1, "Cookie parser: Received null for argument.");
37 cookie_header = strdup(_cookie_header);
38 if (cookie_header == NULL) return -1;
40 p = apr_strtok(cookie_header, ";", &saveptr);
45 /* ignore whitespace at the beginning of cookie name */
46 while(isspace(*p)) p++;
49 attr_value = strstr(p, "=");
50 if (attr_value != NULL) {
51 /* terminate cookie name */
53 /* move over to the beginning of the value */
57 /* we ignore cookies with empty names */
58 if ((attr_name != NULL)&&(strlen(attr_name) != 0)) {
59 if (attr_value != NULL) {
60 if (msr->txcfg->debuglog_level >= 5) {
61 msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"",
62 log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value));
65 apr_table_add(cookies, attr_name, attr_value);
67 if (msr->txcfg->debuglog_level >= 5) {
68 msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty",
69 log_escape(msr->mp, attr_name));
72 apr_table_add(cookies, attr_name, "");
78 p = apr_strtok(NULL, ";", &saveptr);
88 int parse_cookies_v1(modsec_rec *msr, char *_cookie_header, apr_table_t *cookies) {
89 char *attr_name = NULL, *attr_value = NULL, *p = NULL;
90 char *prev_attr_name = NULL;
91 char *cookie_header = NULL;
94 if (_cookie_header == NULL) return -1;
95 cookie_header = strdup(_cookie_header);
96 if (cookie_header == NULL) return -1;
105 /* remove space from the beginning */
106 while((isspace(*p))&&(*p != 0)) p++;
108 while((*p != 0)&&(*p != '=')&&(*p != ';')&&(*p != ',')) p++;
110 /* if we've reached the end of string */
111 if (*p == 0) goto add_cookie;
113 /* if there is no cookie value supplied */
114 if ((*p == ';')||(*p == ',')) {
115 *p++ = 0; /* terminate the name */
119 /* terminate the attribute name,
120 * writing over the = character
124 /* attribute value */
126 /* skip over the whitespace at the beginning */
127 while((isspace(*p))&&(*p != 0)) p++;
129 /* no value supplied */
130 if (*p == 0) goto add_cookie;
133 if (*++p == 0) goto add_cookie;
135 while((*p != 0)&&(*p != '"')) p++;
136 if (*p != 0) *p++ = 0;
138 /* Do nothing about this. */
142 while((*p != 0)&&(*p != ',')&&(*p != ';')) p++;
143 if (*p != 0) *p++ = 0;
145 /* remove the whitespace from the end of cookie value */
146 if (attr_value != NULL) {
147 char *t = attr_value;
155 while((i-- > 0)&&(isspace(*(--t)))) *t = 0;
161 /* remove the whitespace from the end of cookie name */
162 if (attr_name != NULL) {
171 while((i-- > 0)&&(isspace(*(--t)))) *t = 0;
174 /* add the cookie to the list now */
175 if ((attr_name != NULL)&&(strlen(attr_name) != 0)) {
177 /* handle special attribute names */
178 if (attr_name[0] == '$') {
179 if (prev_attr_name != NULL) {
180 /* cookie keyword, we change the name we use
181 * so they can have a unique name in the cookie table
183 attr_name = apr_psprintf(msr->mp, "$%s_%s", prev_attr_name, attr_name + 1);
187 if (attr_value != NULL) {
188 if (msr->txcfg->debuglog_level >= 5) {
189 msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"",
190 log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value));
193 apr_table_add(cookies, attr_name, attr_value);
195 if (msr->txcfg->debuglog_level >= 5) {
196 msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty",
197 log_escape(msr->mp, attr_name));
200 apr_table_add(cookies, attr_name, "");
205 /* only keep the cookie names for later */
206 if (attr_name[0] != '$') prev_attr_name = attr_name;
209 /* at this point the *p is either 0 (in which case we exit), or
210 * right after the current cookie ended - we need to look for
213 while( (*p != 0)&&( (*p == ',')||(*p == ';')||(isspace(*p)) ) ) p++;
222 int parse_arguments(modsec_rec *msr, const char *s, apr_size_t inputlength,
223 int argument_separator, const char *origin,
224 apr_table_t *arguments, int *invalid_count)
233 if (s == NULL) return -1;
234 if (inputlength == 0) return 1;
236 /* Check that adding one will not overflow */
237 if (inputlength + 1 <= 0) return -1;
239 buf = (char *)malloc(inputlength + 1);
240 if (buf == NULL) return -1;
242 arg = (msc_arg *)apr_pcalloc(msr->mp, sizeof(msc_arg));
243 arg->origin = origin;
249 while (i < inputlength) {
252 arg->name_origin_offset = i;
253 while ((s[i] != '=') && (s[i] != argument_separator) && (i < inputlength)) {
259 arg->name_origin_len = i - arg->name_origin_offset;
261 /* parameter value */
262 arg->value_origin_offset = i;
263 while ((s[i] != argument_separator) && (i < inputlength)) {
269 arg->value_origin_len = i - arg->value_origin_offset;
273 arg->name_len = urldecode_nonstrict_inplace_ex((unsigned char *)buf, arg->name_origin_len, invalid_count, &changed);
274 arg->name = apr_pstrmemdup(msr->mp, buf, arg->name_len);
276 if (s[i] == argument_separator) {
277 /* Empty parameter */
281 add_argument(msr, arguments, arg);
283 arg = (msc_arg *)apr_pcalloc(msr->mp, sizeof(msc_arg));
284 arg->origin = origin;
286 status = 0; /* unchanged */
294 arg->value_len = urldecode_nonstrict_inplace_ex((unsigned char *)value, arg->value_origin_len, invalid_count, &changed);
295 arg->value = apr_pstrmemdup(msr->mp, value, arg->value_len);
297 add_argument(msr, arguments, arg);
299 arg = (msc_arg *)apr_pcalloc(msr->mp, sizeof(msc_arg));
300 arg->origin = origin;
306 i++; /* skip over the separator */
309 /* the last parameter was empty */
314 add_argument(msr, arguments, arg);
325 void add_argument(modsec_rec *msr, apr_table_t *arguments, msc_arg *arg) {
326 if (msr->txcfg->debuglog_level >= 5) {
327 msr_log(msr, 5, "Adding request argument (%s): name \"%s\", value \"%s\"",
328 arg->origin, log_escape_ex(msr->mp, arg->name, arg->name_len),
329 log_escape_ex(msr->mp, arg->value, arg->value_len));
332 apr_table_addn(arguments, log_escape_nq_ex(msr->mp, arg->name, arg->name_len), (void *)arg);