summaryrefslogtreecommitdiff
path: root/ifilter.c
diff options
context:
space:
mode:
authorStefan Esser2010-02-21 11:44:54 +0100
committerStefan Esser2010-02-21 11:44:54 +0100
commit36dbfacbe64697d959f524e537b15b73c090d898 (patch)
treef1c7ce1409b0e7765fc72d550546967fcf0f9717 /ifilter.c
Inital commit
Diffstat (limited to 'ifilter.c')
-rw-r--r--ifilter.c732
1 files changed, 732 insertions, 0 deletions
diff --git a/ifilter.c b/ifilter.c
new file mode 100644
index 0000000..f90173b
--- /dev/null
+++ b/ifilter.c
@@ -0,0 +1,732 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007 SektionEins GmbH |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Author: Stefan Esser <sesser@sektioneins.de> |
17 +----------------------------------------------------------------------+
18*/
19/*
20 $Id: ifilter.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "php.h"
28#include "php_ini.h"
29#include "ext/standard/info.h"
30#include "php_suhosin.h"
31#include "php_variables.h"
32
33
34static void (*orig_register_server_variables)(zval *track_vars_array TSRMLS_DC) = NULL;
35
36#ifdef ZEND_ENGINE_2
37#define HASH_HTTP_GET_VARS 0x2095733f
38#define HASH_HTTP_POST_VARS 0xbfee1265
39#define HASH_HTTP_COOKIE_VARS 0xaaca9d99
40#define HASH_HTTP_ENV_VARS 0x1fe186a8
41#define HASH_HTTP_SERVER_VARS 0xc987afd6
42#define HASH_HTTP_SESSION_VARS 0x7aba0d43
43#define HASH_HTTP_POST_FILES 0x98eb1ddc
44#define HASH_HTTP_RAW_POST_DATA 0xdd633fec
45#else
46#define HASH_HTTP_GET_VARS 0x8d8645bd
47#define HASH_HTTP_POST_VARS 0x7c699bf3
48#define HASH_HTTP_COOKIE_VARS 0x93ad0d6f
49#define HASH_HTTP_ENV_VARS 0x84da3016
50#define HASH_HTTP_SERVER_VARS 0x6dbf964e
51#define HASH_HTTP_SESSION_VARS 0x322906f5
52#define HASH_HTTP_POST_FILES 0xe4e4ce70
53#define HASH_HTTP_RAW_POST_DATA 0xe6137a0e
54#endif
55
56
57/* {{{ normalize_varname
58 */
59void normalize_varname(char *varname)
60{
61 char *s=varname, *index=NULL, *indexend=NULL, *p;
62
63 /* overjump leading space */
64 while (*s == ' ') {
65 s++;
66 }
67
68 /* and remove it */
69 if (s != varname) {
70 memmove(varname, s, strlen(s)+1);
71 }
72
73 for (p=varname; *p && *p != '['; p++) {
74 switch(*p) {
75 case ' ':
76 case '.':
77 *p='_';
78 break;
79 }
80 }
81
82 /* find index */
83 index = strchr(varname, '[');
84 if (index) {
85 index++;
86 s=index;
87 } else {
88 return;
89 }
90
91 /* done? */
92 while (index) {
93
94 while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
95 index++;
96 }
97 indexend = strchr(index, ']');
98 indexend = indexend ? indexend + 1 : index + strlen(index);
99
100 if (s != index) {
101 memmove(s, index, strlen(index)+1);
102 s += indexend-index;
103 } else {
104 s = indexend;
105 }
106
107 if (*s == '[') {
108 s++;
109 index = s;
110 } else {
111 index = NULL;
112 }
113 }
114 *s++='\0';
115}
116/* }}} */
117
118static unsigned char suhosin_hexchars[] = "0123456789ABCDEF";
119
120static const char suhosin_is_dangerous_char[256] = {
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
127 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
137};
138
139/* {{{ suhosin_server_encode
140 */
141static void suhosin_server_strip(HashTable *arr, char *key, int klen)
142{
143 zval **tzval;
144 unsigned char *s, *t;
145
146 if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS &&
147 Z_TYPE_PP(tzval) == IS_STRING) {
148
149 s = t = Z_STRVAL_PP(tzval);
150 for (; *t; t++) {
151 if (suhosin_is_dangerous_char[*t]) {
152 *t = '?';
153 }
154 }
155 Z_STRLEN_PP(tzval) = t-s;
156 }
157}
158/* }}} */
159
160/* {{{ suhosin_server_encode
161 */
162static void suhosin_server_encode(HashTable *arr, char *key, int klen)
163{
164 zval **tzval;
165 unsigned char *temp = NULL, *t, *newv, *n;
166 int extra = 0;
167
168 if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS &&
169 Z_TYPE_PP(tzval) == IS_STRING) {
170
171 temp = Z_STRVAL_PP(tzval);
172
173 t = temp;
174 for (t = temp; *t; t++) {
175 if (suhosin_is_dangerous_char[*t]) {
176 extra += 2;
177 }
178 }
179
180 /* no extra bytes required */
181 if (extra == 0) {
182 return;
183 }
184
185 n = newv = emalloc(t - temp + 1 + extra);
186 t = temp;
187 for (t = temp; *t; t++, n++) {
188 if (suhosin_is_dangerous_char[*t]) {
189 *n++ = '%';
190 *n++ = suhosin_hexchars[*t >> 4];
191 *n = suhosin_hexchars[*t & 15];
192 } else {
193 *n = *t;
194 }
195 }
196 *n = 0;
197
198 Z_STRVAL_PP(tzval) = newv;
199 Z_STRLEN_PP(tzval) = n-newv;
200 }
201}
202/* }}} */
203
204/* {{{ suhosin_register_server_variables
205 */
206void suhosin_register_server_variables(zval *track_vars_array TSRMLS_DC)
207{
208 HashTable *svars;
209 int retval, failure=0;
210
211 orig_register_server_variables(track_vars_array TSRMLS_CC);
212
213 svars = Z_ARRVAL_P(track_vars_array);
214
215 if (!SUHOSIN_G(simulation)) {
216 retval = zend_hash_del_key_or_index(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"), HASH_HTTP_GET_VARS, HASH_DEL_INDEX);
217 if (retval == SUCCESS) failure = 1;
218 retval = zend_hash_del_key_or_index(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), HASH_HTTP_POST_VARS, HASH_DEL_INDEX);
219 if (retval == SUCCESS) failure = 1;
220 retval = zend_hash_del_key_or_index(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"), HASH_HTTP_COOKIE_VARS, HASH_DEL_INDEX);
221 if (retval == SUCCESS) failure = 1;
222 retval = zend_hash_del_key_or_index(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"), HASH_HTTP_ENV_VARS, HASH_DEL_INDEX);
223 if (retval == SUCCESS) failure = 1;
224 retval = zend_hash_del_key_or_index(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), HASH_HTTP_SERVER_VARS, HASH_DEL_INDEX);
225 if (retval == SUCCESS) failure = 1;
226 retval = zend_hash_del_key_or_index(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), HASH_HTTP_SESSION_VARS, HASH_DEL_INDEX);
227 if (retval == SUCCESS) failure = 1;
228 retval = zend_hash_del_key_or_index(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"), HASH_HTTP_POST_FILES, HASH_DEL_INDEX);
229 if (retval == SUCCESS) failure = 1;
230 retval = zend_hash_del_key_or_index(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), HASH_HTTP_RAW_POST_DATA, HASH_DEL_INDEX);
231 if (retval == SUCCESS) failure = 1;
232 } else {
233 retval = zend_hash_exists(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"));
234 retval+= zend_hash_exists(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"));
235 retval+= zend_hash_exists(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"));
236 retval+= zend_hash_exists(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"));
237 retval+= zend_hash_exists(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"));
238 retval+= zend_hash_exists(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"));
239 retval+= zend_hash_exists(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"));
240 retval+= zend_hash_exists(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
241 if (retval > 0) failure = 1;
242 }
243
244 if (failure) {
245 suhosin_log(S_VARS, "Attacker tried to overwrite a superglobal through a HTTP header");
246 }
247
248 if (SUHOSIN_G(raw_cookie)) {
249 zval *z;
250 MAKE_STD_ZVAL(z);
251 ZVAL_STRING(z, SUHOSIN_G(raw_cookie), 1);
252 zend_hash_add(svars, "RAW_HTTP_COOKIE", sizeof("RAW_HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL);
253 }
254 if (SUHOSIN_G(decrypted_cookie)) {
255 zval *z;
256 MAKE_STD_ZVAL(z);
257 ZVAL_STRING(z, SUHOSIN_G(decrypted_cookie), 0);
258 zend_hash_update(svars, "HTTP_COOKIE", sizeof("HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL);
259 SUHOSIN_G(decrypted_cookie) = NULL;
260 }
261
262 if (SUHOSIN_G(server_encode)) {
263 /* suhosin_server_encode(svars, "argv", sizeof("argv")); */
264 suhosin_server_encode(svars, "REQUEST_URI", sizeof("REQUEST_URI"));
265 suhosin_server_encode(svars, "QUERY_STRING", sizeof("QUERY_STRING"));
266 }
267 if (SUHOSIN_G(server_strip)) {
268 suhosin_server_strip(svars, "PHP_SELF", sizeof("PHP_SELF"));
269 suhosin_server_strip(svars, "PATH_INFO", sizeof("PATH_INFO"));
270 suhosin_server_strip(svars, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"));
271 }
272}
273/* }}} */
274
275
276#ifdef ZEND_ENGINE_2
277 /* Old Input filter */
278 unsigned int (*old_input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) = NULL;
279
280/* {{{ suhosin_input_filter_wrapper
281 */
282unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
283{
284 zend_bool already_scanned = SUHOSIN_G(already_scanned);
285 SUHOSIN_G(already_scanned) = 0;
286
287 if (SUHOSIN_G(do_not_scan)) {
288 if (new_val_len) {
289 *new_val_len = val_len;
290 }
291 return 1;
292 }
293
294 if (!already_scanned) {
295 if (suhosin_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC)==0) {
296 SUHOSIN_G(abort_request)=1;
297 return 0;
298 }
299 if (new_val_len) {
300 val_len = *new_val_len;
301 }
302 }
303 if (old_input_filter) {
304 return old_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC);
305 } else {
306 return 1;
307 }
308}
309#endif
310
311/* {{{ suhosin_input_filter
312 */
313unsigned int suhosin_input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
314{
315 char *index, *prev_index = NULL;
316 unsigned int var_len, total_len, depth = 0;
317
318 /* Mark that we were called */
319 SUHOSIN_G(already_scanned) = 1;
320
321 if (new_val_len) {
322 *new_val_len = 0;
323 }
324
325 /* Drop this variable if the limit was reached */
326 switch (arg) {
327 case PARSE_GET:
328 if (SUHOSIN_G(no_more_get_variables)) {
329 return 0;
330 }
331 break;
332 case PARSE_POST:
333 if (SUHOSIN_G(no_more_post_variables)) {
334 return 0;
335 }
336 break;
337 case PARSE_COOKIE:
338 if (SUHOSIN_G(no_more_cookie_variables)) {
339 return 0;
340 }
341 break;
342 default: /* we do not want to protect parse_str() and friends */
343 if (new_val_len) {
344 *new_val_len = val_len;
345 }
346 return 1;
347 }
348
349 /* Drop this variable if the limit is now reached */
350 switch (arg) {
351 case PARSE_GET:
352 if (SUHOSIN_G(max_get_vars) && SUHOSIN_G(max_get_vars) <= SUHOSIN_G(cur_get_vars)) {
353 suhosin_log(S_VARS, "configured GET variable limit exceeded - dropped variable '%s'", var);
354 if (!SUHOSIN_G(simulation)) {
355 SUHOSIN_G(no_more_get_variables) = 1;
356 return 0;
357 }
358 }
359 break;
360 case PARSE_COOKIE:
361 if (SUHOSIN_G(max_cookie_vars) && SUHOSIN_G(max_cookie_vars) <= SUHOSIN_G(cur_cookie_vars)) {
362 suhosin_log(S_VARS, "configured COOKIE variable limit exceeded - dropped variable '%s'", var);
363 if (!SUHOSIN_G(simulation)) {
364 SUHOSIN_G(no_more_cookie_variables) = 1;
365 return 0;
366 }
367 }
368 break;
369 case PARSE_POST:
370 if (SUHOSIN_G(max_post_vars) && SUHOSIN_G(max_post_vars) <= SUHOSIN_G(cur_post_vars)) {
371 suhosin_log(S_VARS, "configured POST variable limit exceeded - dropped variable '%s'", var);
372 if (!SUHOSIN_G(simulation)) {
373 SUHOSIN_G(no_more_post_variables) = 1;
374 return 0;
375 }
376 }
377 break;
378 }
379
380 /* Drop this variable if it begins with whitespace which is disallowed */
381 if (*var == ' ') {
382 if (SUHOSIN_G(disallow_ws)) {
383 suhosin_log(S_VARS, "request variable name begins with disallowed whitespace - dropped variable '%s'", var);
384 if (!SUHOSIN_G(simulation)) {
385 return 0;
386 }
387 }
388 switch (arg) {
389 case PARSE_GET:
390 if (SUHOSIN_G(disallow_get_ws)) {
391 suhosin_log(S_VARS, "GET variable name begins with disallowed whitespace - dropped variable '%s'", var);
392 if (!SUHOSIN_G(simulation)) {
393 return 0;
394 }
395 }
396 break;
397 case PARSE_POST:
398 if (SUHOSIN_G(disallow_post_ws)) {
399 suhosin_log(S_VARS, "POST variable name begins with disallowed whitespace - dropped variable '%s'", var);
400 if (!SUHOSIN_G(simulation)) {
401 return 0;
402 }
403 }
404 break;
405 case PARSE_COOKIE:
406 if (SUHOSIN_G(disallow_cookie_ws)) {
407 suhosin_log(S_VARS, "COOKIE variable name begins with disallowed whitespace - dropped variable '%s'", var);
408 if (!SUHOSIN_G(simulation)) {
409 return 0;
410 }
411 }
412 break;
413 }
414 }
415
416 /* Drop this variable if it exceeds the value length limit */
417 if (SUHOSIN_G(max_value_length) && SUHOSIN_G(max_value_length) < val_len) {
418 suhosin_log(S_VARS, "configured request variable value length limit exceeded - dropped variable '%s'", var);
419 if (!SUHOSIN_G(simulation)) {
420 return 0;
421 }
422 }
423 switch (arg) {
424 case PARSE_GET:
425 if (SUHOSIN_G(max_get_value_length) && SUHOSIN_G(max_get_value_length) < val_len) {
426 suhosin_log(S_VARS, "configured GET variable value length limit exceeded - dropped variable '%s'", var);
427 if (!SUHOSIN_G(simulation)) {
428 return 0;
429 }
430 }
431 break;
432 case PARSE_COOKIE:
433 if (SUHOSIN_G(max_cookie_value_length) && SUHOSIN_G(max_cookie_value_length) < val_len) {
434 suhosin_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped variable '%s'", var);
435 if (!SUHOSIN_G(simulation)) {
436 return 0;
437 }
438 }
439 break;
440 case PARSE_POST:
441 if (SUHOSIN_G(max_post_value_length) && SUHOSIN_G(max_post_value_length) < val_len) {
442 suhosin_log(S_VARS, "configured POST variable value length limit exceeded - dropped variable '%s'", var);
443 if (!SUHOSIN_G(simulation)) {
444 return 0;
445 }
446 }
447 break;
448 }
449
450 /* Normalize the variable name */
451 normalize_varname(var);
452
453 /* Find length of variable name */
454 index = strchr(var, '[');
455 total_len = strlen(var);
456 var_len = index ? index-var : total_len;
457
458 /* Drop this variable if it exceeds the varname/total length limit */
459 if (SUHOSIN_G(max_varname_length) && SUHOSIN_G(max_varname_length) < var_len) {
460 suhosin_log(S_VARS, "configured request variable name length limit exceeded - dropped variable '%s'", var);
461 if (!SUHOSIN_G(simulation)) {
462 return 0;
463 }
464 }
465 if (SUHOSIN_G(max_totalname_length) && SUHOSIN_G(max_totalname_length) < total_len) {
466 suhosin_log(S_VARS, "configured request variable total name length limit exceeded - dropped variable '%s'", var);
467 if (!SUHOSIN_G(simulation)) {
468 return 0;
469 }
470 }
471 switch (arg) {
472 case PARSE_GET:
473 if (SUHOSIN_G(max_get_name_length) && SUHOSIN_G(max_get_name_length) < var_len) {
474 suhosin_log(S_VARS, "configured GET variable name length limit exceeded - dropped variable '%s'", var);
475 if (!SUHOSIN_G(simulation)) {
476 return 0;
477 }
478 }
479 if (SUHOSIN_G(max_get_totalname_length) && SUHOSIN_G(max_get_totalname_length) < var_len) {
480 suhosin_log(S_VARS, "configured GET variable total name length limit exceeded - dropped variable '%s'", var);
481 if (!SUHOSIN_G(simulation)) {
482 return 0;
483 }
484 }
485 break;
486 case PARSE_COOKIE:
487 if (SUHOSIN_G(max_cookie_name_length) && SUHOSIN_G(max_cookie_name_length) < var_len) {
488 suhosin_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped variable '%s'", var);
489 if (!SUHOSIN_G(simulation)) {
490 return 0;
491 }
492 }
493 if (SUHOSIN_G(max_cookie_totalname_length) && SUHOSIN_G(max_cookie_totalname_length) < var_len) {
494 suhosin_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped variable '%s'", var);
495 if (!SUHOSIN_G(simulation)) {
496 return 0;
497 }
498 }
499 break;
500 case PARSE_POST:
501 if (SUHOSIN_G(max_post_name_length) && SUHOSIN_G(max_post_name_length) < var_len) {
502 suhosin_log(S_VARS, "configured POST variable name length limit exceeded - dropped variable '%s'", var);
503 if (!SUHOSIN_G(simulation)) {
504 return 0;
505 }
506 }
507 if (SUHOSIN_G(max_post_totalname_length) && SUHOSIN_G(max_post_totalname_length) < var_len) {
508 suhosin_log(S_VARS, "configured POST variable total name length limit exceeded - dropped variable '%s'", var);
509 if (!SUHOSIN_G(simulation)) {
510 return 0;
511 }
512 }
513 break;
514 }
515
516 /* Find out array depth */
517 while (index) {
518 unsigned int index_length;
519
520 depth++;
521 index = strchr(index+1, '[');
522
523 if (prev_index) {
524 index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
525
526 if (SUHOSIN_G(max_array_index_length) && SUHOSIN_G(max_array_index_length) < index_length) {
527 suhosin_log(S_VARS, "configured request variable array index length limit exceeded - dropped variable '%s'", var);
528 if (!SUHOSIN_G(simulation)) {
529 return 0;
530 }
531 }
532 switch (arg) {
533 case PARSE_GET:
534 if (SUHOSIN_G(max_get_array_index_length) && SUHOSIN_G(max_get_array_index_length) < index_length) {
535 suhosin_log(S_VARS, "configured GET variable array index length limit exceeded - dropped variable '%s'", var);
536 if (!SUHOSIN_G(simulation)) {
537 return 0;
538 }
539 }
540 break;
541 case PARSE_COOKIE:
542 if (SUHOSIN_G(max_cookie_array_index_length) && SUHOSIN_G(max_cookie_array_index_length) < index_length) {
543 suhosin_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped variable '%s'", var);
544 if (!SUHOSIN_G(simulation)) {
545 return 0;
546 }
547 }
548 break;
549 case PARSE_POST:
550 if (SUHOSIN_G(max_post_array_index_length) && SUHOSIN_G(max_post_array_index_length) < index_length) {
551 suhosin_log(S_VARS, "configured POST variable array index length limit exceeded - dropped variable '%s'", var);
552 if (!SUHOSIN_G(simulation)) {
553 return 0;
554 }
555 }
556 break;
557 }
558 prev_index = index;
559 }
560
561 }
562
563 /* Drop this variable if it exceeds the array depth limit */
564 if (SUHOSIN_G(max_array_depth) && SUHOSIN_G(max_array_depth) < depth) {
565 suhosin_log(S_VARS, "configured request variable array depth limit exceeded - dropped variable '%s'", var);
566 if (!SUHOSIN_G(simulation)) {
567 return 0;
568 }
569 }
570 switch (arg) {
571 case PARSE_GET:
572 if (SUHOSIN_G(max_get_array_depth) && SUHOSIN_G(max_get_array_depth) < depth) {
573 suhosin_log(S_VARS, "configured GET variable array depth limit exceeded - dropped variable '%s'", var);
574 if (!SUHOSIN_G(simulation)) {
575 return 0;
576 }
577 }
578 break;
579 case PARSE_COOKIE:
580 if (SUHOSIN_G(max_cookie_array_depth) && SUHOSIN_G(max_cookie_array_depth) < depth) {
581 suhosin_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped variable '%s'", var);
582 if (!SUHOSIN_G(simulation)) {
583 return 0;
584 }
585 }
586 break;
587 case PARSE_POST:
588 if (SUHOSIN_G(max_post_array_depth) && SUHOSIN_G(max_post_array_depth) < depth) {
589 suhosin_log(S_VARS, "configured POST variable array depth limit exceeded - dropped variable '%s'", var);
590 if (!SUHOSIN_G(simulation)) {
591 return 0;
592 }
593 }
594 break;
595 }
596
597 /* Check if variable value is truncated by a \0 */
598
599 if (val && *val && val_len != strlen(*val)) {
600
601 if (SUHOSIN_G(disallow_nul)) {
602 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within request variables - dropped variable '%s'", var);
603 if (!SUHOSIN_G(simulation)) {
604 return 0;
605 }
606 }
607 switch (arg) {
608 case PARSE_GET:
609 if (SUHOSIN_G(disallow_get_nul)) {
610 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within GET variables - dropped variable '%s'", var);
611 if (!SUHOSIN_G(simulation)) {
612 return 0;
613 }
614 }
615 break;
616 case PARSE_COOKIE:
617 if (SUHOSIN_G(disallow_cookie_nul)) {
618 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within COOKIE variables - dropped variable '%s'", var);
619 if (!SUHOSIN_G(simulation)) {
620 return 0;
621 }
622 }
623 break;
624 case PARSE_POST:
625 if (SUHOSIN_G(disallow_post_nul)) {
626 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within POST variables - dropped variable '%s'", var);
627 if (!SUHOSIN_G(simulation)) {
628 return 0;
629 }
630 }
631 break;
632 }
633 }
634
635 /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
636 /* This is to protect several silly scripts that do globalizing themself */
637
638 switch (var_len) {
639 case 18:
640 if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
641 break;
642 case 17:
643 if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
644 break;
645 case 16:
646 if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
647 if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
648 break;
649 case 15:
650 if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
651 break;
652 case 14:
653 if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
654 break;
655 case 13:
656 if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
657 if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
658 break;
659 case 8:
660 if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
661 if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
662 break;
663 case 7:
664 if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
665 if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
666 if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
667 break;
668 case 6:
669 if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
670 break;
671 case 5:
672 if (memcmp(var, "_POST", 5)==0) goto protected_varname;
673 break;
674 case 4:
675 if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
676 if (memcmp(var, "_GET", 4)==0) goto protected_varname;
677 break;
678 }
679
680 /* Okay let PHP register this variable */
681 SUHOSIN_G(cur_request_variables)++;
682 switch (arg) {
683 case PARSE_GET:
684 SUHOSIN_G(cur_get_vars)++;
685 break;
686 case PARSE_COOKIE:
687 SUHOSIN_G(cur_cookie_vars)++;
688 break;
689 case PARSE_POST:
690 SUHOSIN_G(cur_post_vars)++;
691 break;
692 }
693
694 if (new_val_len) {
695 *new_val_len = val_len;
696 }
697
698 return 1;
699protected_varname:
700 suhosin_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
701 if (!SUHOSIN_G(simulation)) {
702 return 0;
703 } else {
704 return 1;
705 }
706}
707/* }}} */
708
709
710
711/* {{{ suhosin_hook_register_server_variables
712 */
713void suhosin_hook_register_server_variables()
714{
715 if (sapi_module.register_server_variables) {
716 orig_register_server_variables = sapi_module.register_server_variables;
717 sapi_module.register_server_variables = suhosin_register_server_variables;
718 }
719}
720/* }}} */
721
722
723/*
724 * Local variables:
725 * tab-width: 4
726 * c-basic-offset: 4
727 * End:
728 * vim600: noet sw=4 ts=4 fdm=marker
729 * vim<600: noet sw=4 ts=4
730 */
731
732