summaryrefslogtreecommitdiff
path: root/execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'execute.c')
-rw-r--r--execute.c1436
1 files changed, 1436 insertions, 0 deletions
diff --git a/execute.c b/execute.c
new file mode 100644
index 0000000..1a7388b
--- /dev/null
+++ b/execute.c
@@ -0,0 +1,1436 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2015 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: execute.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */
21// #if 0
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <fcntl.h>
27#include "php.h"
28#include "php_ini.h"
29#include "zend_hash.h"
30#include "zend_extensions.h"
31#include "ext/standard/info.h"
32#include "ext/standard/php_rand.h"
33#include "ext/standard/php_lcg.h"
34#include "php_suhosin7.h"
35#include "zend_compile.h"
36#include "zend_llist.h"
37#include "SAPI.h"
38
39#include "sha256.h"
40
41#ifdef PHP_WIN32
42# include "win32/fnmatch.h"
43# include "win32/winutil.h"
44# include "win32/time.h"
45#else
46# ifdef HAVE_FNMATCH
47# include <fnmatch.h>
48# endif
49# include <sys/time.h>
50#endif
51
52ZEND_API static void (*old_execute_ex)(zend_execute_data *execute_data);
53ZEND_API static void suhosin_execute_ex(zend_execute_data *execute_data);
54ZEND_API static void (*old_execute_internal)(zend_execute_data *execute_data, zval *return_value);
55ZEND_API static void suhosin_execute_internal(zend_execute_data *execute_data, zval *return_value);
56ZEND_API static void (*old_execute)(zend_op_array *op_array, zval *return_value);
57ZEND_API static void suhosin_execute(zend_op_array *op_array, zval *return_value);
58// static void (*old_execute_ZO)(zend_op_array *op_array, long dummy TSRMLS_DC);
59// static void suhosin_execute_ZO(zend_op_array *op_array, long dummy TSRMLS_DC);
60// static void *(*zo_set_oe_ex)(void *ptr) = NULL;
61
62
63// extern zend_extension suhosin_zend_extension_entry;
64
65/* {{{ suhosin_strcasestr */
66static char *suhosin_strcasestr(char *haystack, char *needle)
67{
68 unsigned char *t, *h, *n;
69 h = (unsigned char *) haystack;
70conts:
71 while (*h) {
72 n = (unsigned char *) needle;
73 if (toupper(*h++) == toupper(*n++)) {
74 for (t=h; *n; t++, n++) {
75 if (toupper(*t) != toupper(*n)) goto conts;
76 }
77 return ((char*)h-1);
78 }
79 }
80
81 return (NULL);
82}
83/* }}} */
84
85
86#define SUHOSIN_CODE_TYPE_UNKNOWN 0
87#define SUHOSIN_CODE_TYPE_COMMANDLINE 1
88#define SUHOSIN_CODE_TYPE_EVAL 2
89#define SUHOSIN_CODE_TYPE_REGEXP 3
90#define SUHOSIN_CODE_TYPE_ASSERT 4
91#define SUHOSIN_CODE_TYPE_CFUNC 5
92#define SUHOSIN_CODE_TYPE_SUHOSIN 6
93#define SUHOSIN_CODE_TYPE_UPLOADED 7
94#define SUHOSIN_CODE_TYPE_0FILE 8
95#define SUHOSIN_CODE_TYPE_BLACKURL 9
96#define SUHOSIN_CODE_TYPE_BADURL 10
97#define SUHOSIN_CODE_TYPE_GOODFILE 11
98#define SUHOSIN_CODE_TYPE_BADFILE 12
99#define SUHOSIN_CODE_TYPE_LONGNAME 13
100#define SUHOSIN_CODE_TYPE_MANYDOTS 14
101#define SUHOSIN_CODE_TYPE_WRITABLE 15
102#define SUHOSIN_CODE_TYPE_MBREGEXP 16
103
104static int suhosin_check_filename(char *s, int len)
105{
106 char fname[MAXPATHLEN+1];
107 char *t, *h, *h2, *index, *e;
108 int tlen, i, count=0;
109 uint indexlen;
110 ulong numindex;
111 zend_bool isOk;
112
113 /* check if filename is too long */
114 if (len > MAXPATHLEN) {
115 return SUHOSIN_CODE_TYPE_LONGNAME;
116 }
117 memcpy(fname, s, len);
118 fname[len] = 0;
119 s = (char *)&fname;
120 e = s + len;
121
122 /* check if ASCIIZ attack */
123 if (len != strlen(s)) {
124 return SUHOSIN_CODE_TYPE_0FILE;
125 }
126
127 /* disallow uploaded files */
128 if (SG(rfc1867_uploaded_files)) {
129 if (zend_hash_str_exists(SG(rfc1867_uploaded_files), (char *) s, e-s+1)) { // <--- TODO: range check
130 return SUHOSIN_CODE_TYPE_UPLOADED;
131 }
132 }
133
134 /* count number of directory traversals */
135 for (i=0; i < len-3; i++) {
136 if (s[i] == '.' && s[i+1] == '.' && (s[i+2] == '/' || s[i+2] == '\\')) {
137 count++;
138 i+=2;
139 }
140 }
141 if (SUHOSIN7_G(executor_include_max_traversal) && SUHOSIN7_G(executor_include_max_traversal)<=count) {
142 return SUHOSIN_CODE_TYPE_MANYDOTS;
143 }
144
145 SDEBUG("xxx %p %p",SUHOSIN7_G(include_whitelist),SUHOSIN7_G(include_blacklist));
146 /* no black or whitelist then disallow all */
147 if (SUHOSIN7_G(include_whitelist)==NULL && SUHOSIN7_G(include_blacklist)==NULL) {
148 /* disallow all URLs */
149 if (strstr(s, "://") != NULL || suhosin_strcasestr(s, "data:") != NULL) {
150 return SUHOSIN_CODE_TYPE_BADURL;
151 }
152 } else
153 /* whitelist is stronger than blacklist */
154 // if (SUHOSIN7_G(include_whitelist)) {
155 //
156 // do {
157 // isOk = 0;
158 //
159 // h = strstr(s, "://");
160 // h2 = suhosin_strcasestr(s, "data:");
161 // h2 = h2 == NULL ? NULL : h2 + 4;
162 // t = h = (h == NULL) ? h2 : ( (h2 == NULL) ? h : ( (h < h2) ? h : h2 ) );
163 // if (h == NULL) break;
164 //
165 // while (t > s && (isalnum(t[-1]) || t[-1]=='_' || t[-1]=='.')) {
166 // t--;
167 // }
168 //
169 // tlen = e-t;
170 //
171 // zend_hash_internal_pointer_reset(SUHOSIN7_G(include_whitelist));
172 // do {
173 // int r = zend_hash_get_current_key_ex(SUHOSIN7_G(include_whitelist), &index, &indexlen, &numindex, 0, NULL);
174 //
175 // if (r==HASH_KEY_NON_EXISTANT) {
176 // break;
177 // }
178 // if (r==HASH_KEY_IS_STRING) {
179 // if (h-t <= indexlen-1 && tlen>=indexlen-1) {
180 // if (strncasecmp(t, index, indexlen-1)==0) {
181 // isOk = 1;
182 // break;
183 // }
184 // }
185 // }
186 //
187 // zend_hash_move_forward(SUHOSIN7_G(include_whitelist));
188 // } while (1);
189 //
190 // /* not found in whitelist */
191 // if (!isOk) {
192 // return SUHOSIN_CODE_TYPE_BADURL;
193 // }
194 //
195 // s = h + 1;
196 // } while (1);
197 // } else {
198 //
199 // do {
200 // int tlen;
201 //
202 // h = strstr(s, "://");
203 // h2 = suhosin_strcasestr(s, "data:");
204 // h2 = h2 == NULL ? NULL : h2 + 4;
205 // t = h = (h == NULL) ? h2 : ( (h2 == NULL) ? h : ( (h < h2) ? h : h2 ) );
206 // if (h == NULL) break;
207 //
208 // while (t > s && (isalnum(t[-1]) || t[-1]=='_' || t[-1]=='.')) {
209 // t--;
210 // }
211 //
212 // tlen = e-t;
213 //
214 // zend_hash_internal_pointer_reset(SUHOSIN7_G(include_blacklist));
215 // do {
216 // int r = zend_hash_get_current_key_ex(SUHOSIN7_G(include_blacklist), &index, &indexlen, &numindex, 0, NULL);
217 //
218 // if (r==HASH_KEY_NON_EXISTANT) {
219 // break;
220 // }
221 // if (r==HASH_KEY_IS_STRING) {
222 // if (h-t <= indexlen-1 && tlen>=indexlen-1) {
223 // if (strncasecmp(t, index, indexlen-1)==0) {
224 // return SUHOSIN_CODE_TYPE_BLACKURL;
225 // }
226 // }
227 // }
228 //
229 // zend_hash_move_forward(SUHOSIN7_G(include_blacklist));
230 // } while (1);
231 //
232 // s = h + 1;
233 // } while (1);
234 // }
235
236 /* disallow writable files */
237 if (!SUHOSIN7_G(executor_include_allow_writable_files)) {
238 /* protection against *REMOTE* attacks, potential
239 race condition of access() is irrelevant */
240 if (access(s, W_OK) == 0) {
241 return SUHOSIN_CODE_TYPE_WRITABLE;
242 }
243 }
244
245 return SUHOSIN_CODE_TYPE_GOODFILE;
246}
247
248
249// ZEND_API static int (*old_zend_stream_open)(const char *filename, zend_file_handle *handle);
250//
251// static int suhosin_zend_stream_open(const char *filename, zend_file_handle *fh TSRMLS_DC)
252// {
253// zend_execute_data *exd;
254// exd=EG(current_execute_data);
255// if (EG(in_execution) && (exd!=NULL) && (exd->opline != NULL) && (exd->opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
256// int filetype = suhosin_check_filename((char *)filename, strlen(filename));
257//
258// switch (filetype) {
259// case SUHOSIN_CODE_TYPE_LONGNAME:
260// suhosin_log(S_INCLUDE, "Include filename ('%s') is too long", filename);
261// suhosin_bailout(TSRMLS_C);
262// break;
263//
264// case SUHOSIN_CODE_TYPE_UPLOADED:
265// suhosin_log(S_INCLUDE, "Include filename is an uploaded file");
266// suhosin_bailout(TSRMLS_C);
267// break;
268//
269// case SUHOSIN_CODE_TYPE_0FILE:
270// suhosin_log(S_INCLUDE, "Include filename contains an ASCIIZ character");
271// suhosin_bailout(TSRMLS_C);
272// break;
273//
274// case SUHOSIN_CODE_TYPE_WRITABLE:
275// suhosin_log(S_INCLUDE, "Include filename ('%s') is writable by PHP process", filename);
276// suhosin_bailout(TSRMLS_C);
277// break;
278//
279// case SUHOSIN_CODE_TYPE_BLACKURL:
280// suhosin_log(S_INCLUDE, "Include filename ('%s') is a URL that is forbidden by the blacklist", filename);
281// suhosin_bailout(TSRMLS_C);
282// break;
283//
284// case SUHOSIN_CODE_TYPE_BADURL:
285// suhosin_log(S_INCLUDE, "Include filename ('%s') is a URL that is not allowed", filename);
286// suhosin_bailout(TSRMLS_C);
287// break;
288//
289// case SUHOSIN_CODE_TYPE_MANYDOTS:
290// suhosin_log(S_INCLUDE, "Include filename ('%s') contains too many '../'", filename);
291// suhosin_bailout(TSRMLS_C);
292// break;
293// }
294// }
295// return old_zend_stream_open(filename, fh TSRMLS_CC);
296// }
297
298
299static int suhosin_detect_codetype(zend_op_array *op_array TSRMLS_DC)
300{
301 if (op_array->filename == NULL) {
302 return SUHOSIN_CODE_TYPE_UNKNOWN;
303 }
304
305 char *s = (char *)ZSTR_VAL(op_array->filename);
306
307 /* eval, assert, create_function, preg_replace */
308 if (op_array->type == ZEND_EVAL_CODE) {
309
310 if (s == NULL) {
311 return SUHOSIN_CODE_TYPE_UNKNOWN;
312 }
313
314 if (strstr(s, "eval()'d code") != NULL) {
315 return SUHOSIN_CODE_TYPE_EVAL;
316 }
317
318 if (strstr(s, "regexp code") != NULL) {
319 return SUHOSIN_CODE_TYPE_REGEXP;
320 }
321
322 if (strstr(s, "mbregex replace") != NULL) {
323 return SUHOSIN_CODE_TYPE_MBREGEXP;
324 }
325
326 if (strstr(s, "assert code") != NULL) {
327 return SUHOSIN_CODE_TYPE_ASSERT;
328 }
329
330 if (strstr(s, "runtime-created function") != NULL) {
331 return SUHOSIN_CODE_TYPE_CFUNC;
332 }
333
334 if (strstr(s, "Command line code") != NULL) {
335 return SUHOSIN_CODE_TYPE_COMMANDLINE;
336 }
337
338 if (strstr(s, "Command line begin code") != NULL) {
339 return SUHOSIN_CODE_TYPE_COMMANDLINE;
340 }
341
342 if (strstr(s, "Command line run code") != NULL) {
343 return SUHOSIN_CODE_TYPE_COMMANDLINE;
344 }
345
346 if (strstr(s, "Command line end code") != NULL) {
347 return SUHOSIN_CODE_TYPE_COMMANDLINE;
348 }
349
350 if (strstr(s, "suhosin internal code") != NULL) {
351 return SUHOSIN_CODE_TYPE_SUHOSIN;
352 }
353
354 } else {
355
356 return suhosin_check_filename(s, strlen(s) TSRMLS_CC);
357
358 }
359
360 return SUHOSIN_CODE_TYPE_UNKNOWN;
361}
362
363/* {{{ void suhosin_execute_ex(zend_op_array *op_array)
364 * This function provides a hook for execution */
365ZEND_API static void suhosin_execute_ex(zend_execute_data *execute_data)
366{
367 // TODO: check execute_data + execute_data->func
368
369 zend_op_array *new_op_array;
370 int op_array_type;//, len;
371 // char *fn;
372 zval cs;
373 zend_ulong orig_code_type;
374 unsigned long *suhosin_flags = NULL;
375
376 /* log variable dropping statistics */
377 if (SUHOSIN7_G(abort_request)) {
378
379 SUHOSIN7_G(abort_request) = 0; /* we only want this to happen the first time */
380
381 if (SUHOSIN7_G(att_request_variables)-SUHOSIN7_G(cur_request_variables) > 0) {
382 suhosin_log(S_VARS, "dropped %u request variables - (%u in GET, %u in POST, %u in COOKIE)",
383 SUHOSIN7_G(att_request_variables)-SUHOSIN7_G(cur_request_variables),
384 SUHOSIN7_G(att_get_vars)-SUHOSIN7_G(cur_get_vars),
385 SUHOSIN7_G(att_post_vars)-SUHOSIN7_G(cur_post_vars),
386 SUHOSIN7_G(att_cookie_vars)-SUHOSIN7_G(cur_cookie_vars));
387 }
388
389 // if (!SUHOSIN7_G(simulation) && SUHOSIN7_G(filter_action)) {
390 //
391 // char *action = SUHOSIN7_G(filter_action);
392 // long code = -1;
393 //
394 // while (*action == ' ' || *action == '\t') action++;
395 //
396 // if (*action >= '0' && *action <= '9') {
397 // char *end = action;
398 // while (*end && *end != ',' && *end != ';') end++;
399 // code = zend_atoi(action, end-action);
400 // action = end;
401 // }
402 //
403 // while (*action == ' ' || *action == '\t' || *action == ',' || *action == ';') action++;
404 //
405 // if (*action) {
406 //
407 // if (strncasecmp("http://", action, sizeof("http://")-1)==0
408 // || strncasecmp("https://", action, sizeof("https://")-1)==0) {
409 // sapi_header_line ctr = {0};
410 //
411 // if (code == -1) {
412 // code = 302;
413 // }
414 //
415 // ctr.line_len = spprintf(&ctr.line, 0, "Location: %s", action);
416 // ctr.response_code = code;
417 // sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
418 // efree(ctr.line);
419 // } else {
420 // zend_file_handle file_handle;
421 // zend_op_array *new_op_array;
422 // zval *result = NULL;
423 //
424 // if (code == -1) {
425 // code = 200;
426 // }
427 //
428 // if (zend_stream_open(action, &file_handle TSRMLS_CC) == SUCCESS) {
429 // if (!file_handle.opened_path) {
430 // file_handle.opened_path = estrndup(action, strlen(action));
431 // }
432 // new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
433 // zend_destroy_file_handle(&file_handle TSRMLS_CC);
434 // if (new_op_array) {
435 // EG(return_value_ptr_ptr) = &result;
436 // EG(active_op_array) = new_op_array;
437 // zend_execute(new_op_array TSRMLS_CC);
438 // destroy_op_array(new_op_array TSRMLS_CC);
439 // efree(new_op_array);
440 //
441 // if (!EG(exception))
442 // {
443 // if (EG(return_value_ptr_ptr)) {
444 // zval_ptr_dtor(EG(return_value_ptr_ptr));
445 // EG(return_value_ptr_ptr) = NULL;
446 // }
447 // }
448 // } else {
449 // code = 500;
450 // }
451 // } else {
452 // code = 500;
453 // }
454 // }
455 // }
456 //
457 // sapi_header_op(SAPI_HEADER_SET_STATUS, (void *)code TSRMLS_CC);
458 // zend_bailout();
459 // }
460 }
461
462 // SDEBUG("%s %s", op_array->filename, op_array->function_name);
463
464 SUHOSIN7_G(execution_depth)++;
465
466 if (SUHOSIN7_G(max_execution_depth) && SUHOSIN7_G(execution_depth) > SUHOSIN7_G(max_execution_depth)) {
467 suhosin_log(S_EXECUTOR|S_GETCALLER, "maximum execution depth reached - script terminated");
468 suhosin_bailout(TSRMLS_C);
469 }
470
471 // fn = (char *)execute_data->func->op_array.filename;
472 // len = strlen(fn);
473
474 orig_code_type = SUHOSIN7_G(in_code_type);
475 if (execute_data->func->op_array.type == ZEND_EVAL_CODE) {
476 SUHOSIN7_G(in_code_type) = SUHOSIN_EVAL;
477 } else {
478 // if (suhosin_zend_extension_entry.resource_number != -1) {
479 // suhosin_flags = (unsigned long *) &execute_data->func->op_array.reserved[suhosin_zend_extension_entry.resource_number];
480 // SDEBUG("suhosin flags: %08lx", *suhosin_flags);
481 //
482 // if (*suhosin_flags & SUHOSIN_FLAG_CREATED_BY_EVAL) {
483 // SUHOSIN7_G(in_code_type) = SUHOSIN_EVAL;
484 // }
485 // if (*suhosin_flags & SUHOSIN_FLAG_NOT_EVALED_CODE) {
486 // goto not_evaled_code;
487 // }
488 // }
489
490 if (zend_string_equals_literal(execute_data->func->op_array.filename, "eval()'d code")) {
491 SUHOSIN7_G(in_code_type) = SUHOSIN_EVAL;
492 } // else {
493 // if (suhosin_flags) {
494 // *suhosin_flags |= SUHOSIN_FLAG_NOT_EVALED_CODE;
495 // }
496 // }
497 }
498not_evaled_code:
499 SDEBUG("code type %llu", SUHOSIN7_G(in_code_type));
500 if (execute_data->func->op_array.function_name) {
501 goto continue_execution;
502 }
503
504/* if (SUHOSIN7_G(deactivate)) {
505 goto continue_execution;
506 }
507*/
508
509 op_array_type = suhosin_detect_codetype(&execute_data->func->op_array);
510
511 switch (op_array_type) {
512 case SUHOSIN_CODE_TYPE_EVAL:
513 if (SUHOSIN7_G(executor_disable_eval)) {
514 suhosin_log(S_EXECUTOR|S_GETCALLER, "use of eval is forbidden by configuration");
515 if (!SUHOSIN7_G(simulation)) {
516 zend_error(E_ERROR, "SUHOSIN - Use of eval is forbidden by configuration");
517 }
518 }
519 break;
520
521 case SUHOSIN_CODE_TYPE_REGEXP:
522 if (SUHOSIN7_G(executor_disable_emod)) {
523 suhosin_log(S_EXECUTOR|S_GETCALLER, "use of preg_replace() with /e modifier is forbidden by configuration");
524 if (!SUHOSIN7_G(simulation)) {
525 zend_error(E_ERROR, "SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration");
526 }
527 }
528 break;
529
530 case SUHOSIN_CODE_TYPE_MBREGEXP:
531 /* XXX TODO: Do we want to disallow this, too? */
532 break;
533
534 case SUHOSIN_CODE_TYPE_ASSERT:
535 break;
536
537 case SUHOSIN_CODE_TYPE_CFUNC:
538 break;
539
540 case SUHOSIN_CODE_TYPE_LONGNAME:
541 suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is too long", ZSTR_VAL(execute_data->func->op_array.filename));
542 suhosin_bailout(TSRMLS_C);
543 break;
544
545 case SUHOSIN_CODE_TYPE_MANYDOTS:
546 suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') contains too many '../'", ZSTR_VAL(execute_data->func->op_array.filename));
547 suhosin_bailout(TSRMLS_C);
548 break;
549
550 case SUHOSIN_CODE_TYPE_UPLOADED:
551 suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename is an uploaded file");
552 suhosin_bailout(TSRMLS_C);
553 break;
554
555 case SUHOSIN_CODE_TYPE_0FILE:
556 suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename contains an ASCIIZ character");
557 suhosin_bailout(TSRMLS_C);
558 break;
559
560 case SUHOSIN_CODE_TYPE_WRITABLE:
561 suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is writable by PHP process", ZSTR_VAL(execute_data->func->op_array.filename));
562 suhosin_bailout(TSRMLS_C);
563 break;
564
565 case SUHOSIN_CODE_TYPE_BLACKURL:
566 suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is a URL that is forbidden by the blacklist", ZSTR_VAL(execute_data->func->op_array.filename));
567 suhosin_bailout(TSRMLS_C);
568 break;
569
570 case SUHOSIN_CODE_TYPE_BADURL:
571 suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is a URL that is not allowed", ZSTR_VAL(execute_data->func->op_array.filename));
572 suhosin_bailout(TSRMLS_C);
573 break;
574
575 case SUHOSIN_CODE_TYPE_BADFILE:
576// cs.type = IS_STRING;
577// #define DIE_WITH_MSG "die('disallowed_file'.chr(10).chr(10));"
578// cs.value.str.val = estrndup(DIE_WITH_MSG, sizeof(DIE_WITH_MSG)-1);
579// cs.value.str.len = sizeof(DIE_WITH_MSG)-1;
580// new_op_array = compile_string(&cs, "suhosin internal code" TSRMLS_CC);
581// if (new_op_array) {
582// op_array = new_op_array;
583// goto continue_execution;
584// }
585 suhosin_bailout(TSRMLS_C);
586 break;
587
588 case SUHOSIN_CODE_TYPE_COMMANDLINE:
589 case SUHOSIN_CODE_TYPE_SUHOSIN:
590 case SUHOSIN_CODE_TYPE_UNKNOWN:
591 case SUHOSIN_CODE_TYPE_GOODFILE:
592 goto continue_execution;
593 }
594
595continue_execution:
596 old_execute_ex (execute_data);
597
598 /* nothing to do */
599 SUHOSIN7_G(in_code_type) = orig_code_type;
600 SUHOSIN7_G(execution_depth)--;
601}
602/* }}} */
603
604
605#define IH_HANDLER_PARAMS_REST int ht, zval *return_value
606#define IH_HANDLER_PARAMS internal_function_handler *ih, IH_HANDLER_PARAMS_REST
607#define IH_HANDLER_PARAM_PASSTHRU ih, ht, return_value
608
609
610HashTable ihandler_table;
611
612typedef struct _internal_function_handler {
613
614 char *name;
615 int (*handler)(struct _internal_function_handler *ih, IH_HANDLER_PARAMS_REST);
616 void *arg1;
617 void *arg2;
618 void *arg3;
619
620} internal_function_handler;
621
622// int ih_preg_replace(IH_HANDLER_PARAMS)
623// {
624// zval **regex,
625// **replace,
626// **subject,
627// **limit, **zcount;
628//
629// if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|ZZ", &regex, &replace, &subject, &limit, &zcount) == FAILURE) {
630// return(0);
631// }
632//
633// if (Z_TYPE_PP(regex) == IS_ARRAY) {
634// zval **regex_entry;
635//
636// zend_hash_internal_pointer_reset(Z_ARRVAL_PP(regex));
637// /* For each entry in the regex array, get the entry */
638// while (zend_hash_get_current_data(Z_ARRVAL_PP(regex), (void **)&regex_entry) == SUCCESS) {
639//
640// if (Z_TYPE_PP(regex_entry) == IS_STRING) {
641// if (strlen(Z_STRVAL_PP(regex_entry)) != Z_STRLEN_PP(regex_entry)) {
642// suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected");
643// if (!SUHOSIN7_G(simulation)) {
644// RETVAL_FALSE;
645// return (1);
646// }
647// }
648// }
649//
650// zend_hash_move_forward(Z_ARRVAL_PP(regex));
651//
652// }
653//
654// } else if (Z_TYPE_PP(regex) == IS_STRING) {
655// if (strlen(Z_STRVAL_PP(regex)) != Z_STRLEN_PP(regex)) {
656// suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected");
657// if (!SUHOSIN7_G(simulation)) {
658// RETVAL_FALSE;
659// return (1);
660// }
661// }
662// }
663//
664// return (0);
665// }
666
667// int ih_symlink(IH_HANDLER_PARAMS)
668// {
669// if (SUHOSIN7_G(executor_allow_symlink)) {
670// return (0);
671// }
672//
673// if (PG(open_basedir) && PG(open_basedir)[0]) {
674// suhosin_log(S_EXECUTOR, "symlink called during open_basedir");
675// if (!SUHOSIN7_G(simulation)) {
676// RETVAL_FALSE;
677// return (1);
678// }
679// }
680//
681// return (0);
682// }
683
684// int ih_mail(IH_HANDLER_PARAMS)
685// {
686// char *to=NULL, *message=NULL, *headers=NULL;
687// char *subject=NULL, *extra_cmd=NULL;
688// char *tmp;
689// int to_len, message_len, headers_len;
690// int subject_len, extra_cmd_len;
691//
692// if (SUHOSIN7_G(mailprotect) == 0) {
693// return (0);
694// }
695//
696// if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss",
697// &to, &to_len,
698// &subject, &subject_len,
699// &message, &message_len,
700// &headers, &headers_len,
701// &extra_cmd, &extra_cmd_len
702// ) == FAILURE) {
703// RETVAL_FALSE;
704// return (1);
705// }
706//
707// if (headers_len > 0 && headers &&
708// (strstr(headers, "\n\n") || strstr(headers, "\n\r\n") /* double newline */
709// || *headers == '\n' || (headers[0] == '\r' && headers[1] == '\n') /* starts with newline */
710// )) {
711// suhosin_log(S_MAIL, "mail() - double newline in headers, possible injection, mail dropped");
712// if (!SUHOSIN7_G(simulation)) {
713// RETVAL_FALSE;
714// return (1);
715// }
716// }
717//
718// /* check for spam attempts with buggy webforms */
719// if (to_len > 0 && to) {
720// do {
721// if ((tmp = strchr(to, '\n')) == NULL)
722// tmp = strchr(to, '\r');
723// if (tmp == NULL) break;
724// to = tmp + 1;
725// if (!isspace(*to)) break;
726// } while (1);
727// if (tmp != NULL) {
728// suhosin_log(S_MAIL, "mail() - newline in To header, possible injection, mail dropped");
729// if (!SUHOSIN7_G(simulation)) {
730// RETVAL_FALSE;
731// return (1);
732// }
733// }
734// }
735//
736// if (subject_len > 0 && subject) {
737// do {
738// if ((tmp = strchr(subject, '\n')) == NULL)
739// tmp = strchr(subject, '\r');
740// if (tmp == NULL) break;
741// subject = tmp + 1;
742// if (!isspace(*subject)) break;
743// } while (1);
744// if (tmp != NULL) {
745// suhosin_log(S_MAIL, "mail() - newline in Subject header, possible injection, mail dropped");
746// if (!SUHOSIN7_G(simulation)) {
747// RETVAL_FALSE;
748// return (1);
749// }
750// }
751// }
752//
753// if (SUHOSIN7_G(mailprotect) > 1) {
754// /* search for to, cc or bcc headers */
755// if (headers_len > 0 && headers != NULL) {
756// if (strncasecmp(headers, "to:", sizeof("to:") - 1) == 0 || suhosin_strcasestr(headers, "\nto:")) {
757// suhosin_log(S_MAIL, "mail() - To: headers aren't allowed in the headers parameter.");
758// if (!SUHOSIN7_G(simulation)) {
759// RETVAL_FALSE;
760// return (1);
761// }
762// }
763//
764// if (strncasecmp(headers, "cc:", sizeof("cc:") - 1) == 0 || suhosin_strcasestr(headers, "\ncc:")) {
765// suhosin_log(S_MAIL, "mail() - CC: headers aren't allowed in the headers parameter.");
766// if (!SUHOSIN7_G(simulation)) {
767// RETVAL_FALSE;
768// return (1);
769// }
770// }
771//
772// if (strncasecmp(headers, "bcc:", sizeof("bcc:") - 1) == 0 || suhosin_strcasestr(headers, "\nbcc:")) {
773// suhosin_log(S_MAIL, "mail() - BCC: headers aren't allowed in the headers parameter.");
774// if (!SUHOSIN7_G(simulation)) {
775// RETVAL_FALSE;
776// return (1);
777// }
778// }
779// }
780// }
781//
782// return (0);
783// }
784
785// #define SQLSTATE_SQL 0
786// #define SQLSTATE_IDENTIFIER 1
787// #define SQLSTATE_STRING 2
788// #define SQLSTATE_COMMENT 3
789// #define SQLSTATE_MLCOMMENT 4
790//
791// int ih_querycheck(IH_HANDLER_PARAMS)
792// {
793// void **p = zend_vm_stack_top(TSRMLS_C) - 1;
794// unsigned long arg_count;
795// zval **arg;
796// char *query, *s, *e;
797// zval *backup;
798// int len;
799// char quote;
800// int state = SQLSTATE_SQL;
801// int cnt_union = 0, cnt_select = 0, cnt_comment = 0, cnt_opencomment = 0;
802// int mysql_extension = 0;
803//
804//
805// SDEBUG("function: %s", ih->name);
806// arg_count = (unsigned long) *p;
807//
808// if (ht < (long) ih->arg1) {
809// return (0);
810// }
811//
812// if ((long) ih->arg2) {
813// mysql_extension = 1;
814// }
815//
816// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */
817//
818// backup = *arg;
819// if (Z_TYPE_P(backup) != IS_STRING) {
820// return (0);
821// }
822// len = Z_STRLEN_P(backup);
823// query = Z_STRVAL_P(backup);
824// SDEBUG("SQL |%s|", query);
825//
826// s = query;
827// e = s+len;
828//
829// while (s < e) {
830// switch (state)
831// {
832// case SQLSTATE_SQL:
833// switch (s[0])
834// {
835// case '`':
836// state = SQLSTATE_IDENTIFIER;
837// quote = '`';
838// break;
839// case '\'':
840// case '"':
841// state = SQLSTATE_STRING;
842// quote = *s;
843// break;
844// case '/':
845// if (s[1]=='*') {
846// if (mysql_extension == 1 && s[2] == '!') {
847// s += 2;
848// break;
849// }
850// s++;
851// state = SQLSTATE_MLCOMMENT;
852// cnt_comment++;
853// }
854// break;
855// case '-':
856// if (s[1]=='-') {
857// s++;
858// state = SQLSTATE_COMMENT;
859// cnt_comment++;
860// }
861// break;
862// case '#':
863// state = SQLSTATE_COMMENT;
864// cnt_comment++;
865// break;
866// case 'u':
867// case 'U':
868// if (strncasecmp("union", s, 5)==0) {
869// s += 4;
870// cnt_union++;
871// }
872// break;
873// case 's':
874// case 'S':
875// if (strncasecmp("select", s, 6)==0) {
876// s += 5;
877// cnt_select++;
878// }
879// break;
880// }
881// break;
882// case SQLSTATE_STRING:
883// case SQLSTATE_IDENTIFIER:
884// if (s[0] == quote) {
885// if (s[1] == quote) {
886// s++;
887// } else {
888// state = SQLSTATE_SQL;
889// }
890// }
891// if (s[0] == '\\') {
892// s++;
893// }
894// break;
895// case SQLSTATE_COMMENT:
896// while (s[0] && s[0] != '\n') {
897// s++;
898// }
899// state = SQLSTATE_SQL;
900// break;
901// case SQLSTATE_MLCOMMENT:
902// while (s[0] && (s[0] != '*' || s[1] != '/')) {
903// s++;
904// }
905// if (s[0]) {
906// state = SQLSTATE_SQL;
907// }
908// break;
909// }
910// s++;
911// }
912// if (state == SQLSTATE_MLCOMMENT) {
913// cnt_opencomment = 1;
914// }
915//
916// if (cnt_opencomment && SUHOSIN7_G(sql_opencomment)>0) {
917// suhosin_log(S_SQL, "Open comment in SQL query: '%*s'", len, query);
918// if (SUHOSIN7_G(sql_opencomment)>1) {
919// suhosin_bailout(TSRMLS_C);
920// }
921// }
922//
923// if (cnt_comment && SUHOSIN7_G(sql_comment)>0) {
924// suhosin_log(S_SQL, "Comment in SQL query: '%*s'", len, query);
925// if (SUHOSIN7_G(sql_comment)>1) {
926// suhosin_bailout(TSRMLS_C);
927// }
928// }
929//
930// if (cnt_union && SUHOSIN7_G(sql_union)>0) {
931// suhosin_log(S_SQL, "UNION in SQL query: '%*s'", len, query);
932// if (SUHOSIN7_G(sql_union)>1) {
933// suhosin_bailout(TSRMLS_C);
934// }
935// }
936//
937// if (cnt_select>1 && SUHOSIN7_G(sql_mselect)>0) {
938// suhosin_log(S_SQL, "Multiple SELECT in SQL query: '%*s'", len, query);
939// if (SUHOSIN7_G(sql_mselect)>1) {
940// suhosin_bailout(TSRMLS_C);
941// }
942// }
943//
944// return (0);
945// }
946//
947//
948// int ih_fixusername(IH_HANDLER_PARAMS)
949// {
950// void **p = zend_vm_stack_top(TSRMLS_C) - 1;
951// unsigned long arg_count;
952// zval **arg;
953// char *prefix, *postfix, *user, *user_match, *cp;
954// zval *backup, *my_user;
955// int prefix_len, postfix_len, len;
956//
957// SDEBUG("function (fixusername): %s", ih->name);
958//
959// prefix = SUHOSIN7_G(sql_user_prefix);
960// postfix = SUHOSIN7_G(sql_user_postfix);
961// user_match = SUHOSIN7_G(sql_user_match);
962//
963// arg_count = (unsigned long) *p;
964//
965// if (ht < (long) ih->arg1) {
966// return (0);
967// }
968//
969// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */
970//
971// backup = *arg;
972// if (Z_TYPE_P(backup) != IS_STRING) {
973// user = "";
974// len = 0;
975// } else {
976// len = Z_STRLEN_P(backup);
977// user = Z_STRVAL_P(backup);
978// }
979//
980// cp = user;
981// while (cp < user+len) {
982// if (*cp < 32) {
983// suhosin_log(S_SQL, "SQL username contains invalid characters");
984// if (!SUHOSIN7_G(simulation)) {
985// RETVAL_FALSE;
986// return (1);
987// }
988// break;
989// }
990// cp++;
991// }
992//
993// if ((prefix != NULL && prefix[0]) || (postfix != NULL && postfix[0])) {
994// if (prefix == NULL) {
995// prefix = "";
996// }
997// if (postfix == NULL) {
998// postfix = "";
999// }
1000// prefix_len = strlen(prefix);
1001// postfix_len = strlen(postfix);
1002//
1003// MAKE_STD_ZVAL(my_user);
1004// my_user->type = IS_STRING;
1005// my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix);
1006//
1007// /* XXX: memory_leak? */
1008// *arg = my_user;
1009//
1010// len = Z_STRLEN_P(my_user);
1011// user = Z_STRVAL_P(my_user);
1012// }
1013//
1014// if (user_match && user_match[0]) {
1015// #ifdef HAVE_FNMATCH
1016// if (fnmatch(user_match, user, 0) != 0) {
1017// suhosin_log(S_SQL, "SQL username ('%s') does not match suhosin.sql.user_match ('%s')", user, user_match);
1018// if (!SUHOSIN7_G(simulation)) {
1019// RETVAL_FALSE;
1020// return (1);
1021// }
1022// }
1023// #else
1024// #warning no support for fnmatch() - setting suhosin.sql.user_match will always fail.
1025// suhosin_log(S_SQL, "suhosin.sql.user_match specified, but system does not support fnmatch()");
1026// if (!SUHOSIN7_G(simulation)) {
1027// RETVAL_FALSE;
1028// return (1);
1029// }
1030// #endif
1031// }
1032//
1033// SDEBUG("function: %s - user: %s", ih->name, user);
1034//
1035// return (0);
1036// }
1037//
1038//
1039// static int ih_function_exists(IH_HANDLER_PARAMS)
1040// {
1041// zval **function_name;
1042// zend_function *func;
1043// char *lcname;
1044// zend_bool retval;
1045// int func_name_len;
1046//
1047// if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) {
1048// ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(1);
1049// }
1050// convert_to_string_ex(function_name);
1051// func_name_len = Z_STRLEN_PP(function_name);
1052// lcname = estrndup(Z_STRVAL_PP(function_name), func_name_len);
1053// zend_str_tolower(lcname, func_name_len);
1054//
1055// retval = (zend_hash_find(EG(function_table), lcname, func_name_len+1, (void **)&func) == SUCCESS);
1056//
1057// /*
1058// * A bit of a hack, but not a bad one: we see if the handler of the function
1059// * is actually one that displays "function is disabled" message.
1060// */
1061// if (retval && func->type == ZEND_INTERNAL_FUNCTION &&
1062// func->internal_function.handler == zif_display_disabled_function) {
1063// retval = 0;
1064// }
1065//
1066// /* Now check if function is forbidden by Suhosin */
1067// if (SUHOSIN7_G(in_code_type) == SUHOSIN_EVAL) {
1068// if (SUHOSIN7_G(eval_whitelist) != NULL) {
1069// if (!zend_hash_exists(SUHOSIN7_G(eval_whitelist), lcname, func_name_len+1)) {
1070// retval = 0;
1071// }
1072// } else if (SUHOSIN7_G(eval_blacklist) != NULL) {
1073// if (zend_hash_exists(SUHOSIN7_G(eval_blacklist), lcname, func_name_len+1)) {
1074// retval = 0;
1075// }
1076// }
1077// }
1078//
1079// if (SUHOSIN7_G(func_whitelist) != NULL) {
1080// if (!zend_hash_exists(SUHOSIN7_G(func_whitelist), lcname, func_name_len+1)) {
1081// retval = 0;
1082// }
1083// } else if (SUHOSIN7_G(func_blacklist) != NULL) {
1084// if (zend_hash_exists(SUHOSIN7_G(func_blacklist), lcname, func_name_len+1)) {
1085// retval = 0;
1086// }
1087// }
1088//
1089// efree(lcname);
1090//
1091// RETVAL_BOOL(retval);
1092// return (1);
1093// }
1094
1095// #include "execute_rnd.inc.c"
1096
1097internal_function_handler ihandlers[] = {
1098 // { "preg_replace", ih_preg_replace, NULL, NULL, NULL },
1099 // { "mail", ih_mail, NULL, NULL, NULL },
1100 // { "symlink", ih_symlink, NULL, NULL, NULL },
1101
1102 // { "srand", ih_srand, NULL, NULL, NULL },
1103 // { "mt_srand", ih_mt_srand, NULL, NULL, NULL },
1104 // { "rand", ih_rand, NULL, NULL, NULL },
1105 // { "mt_rand", ih_mt_rand, NULL, NULL, NULL },
1106 // { "getrandmax", ih_getrandmax, NULL, NULL, NULL },
1107 // { "mt_getrandmax", ih_getrandmax, NULL, NULL, NULL },
1108
1109 // { "function_exists", ih_function_exists, NULL, NULL, NULL },
1110
1111 /* Mysqli */
1112 // { "mysqli::mysqli", ih_fixusername, (void *)2, NULL, NULL },
1113 // { "mysqli_connect", ih_fixusername, (void *)2, NULL, NULL },
1114 // { "mysqli::real_connect", ih_fixusername, (void *)2, NULL, NULL },
1115 // { "mysqli_real_connect", ih_fixusername, (void *)3, NULL, NULL },
1116 // { "mysqli_change_user", ih_fixusername, (void *)2, NULL, NULL },
1117 // { "mysqli::change_user", ih_fixusername, (void *)1, NULL, NULL },
1118
1119 // { "mysqli::query", ih_querycheck, (void *)1, (void *)1, NULL },
1120 // { "mysqli_query", ih_querycheck, (void *)2, (void *)1, NULL },
1121 // { "mysqli::multi_query", ih_querycheck, (void *)1, (void *)1, NULL },
1122 // { "mysqli_multi_query", ih_querycheck, (void *)2, (void *)1, NULL },
1123 // { "mysqli::prepare", ih_querycheck, (void *)1, (void *)1, NULL },
1124 // { "mysqli_prepare", ih_querycheck, (void *)2, (void *)1, NULL },
1125 // { "mysqli::real_query", ih_querycheck, (void *)1, (void *)1, NULL },
1126 // { "mysqli_real_query", ih_querycheck, (void *)2, (void *)1, NULL },
1127 // { "mysqli::send_query", ih_querycheck, (void *)1, (void *)1, NULL },
1128 // { "mysqli_send_query", ih_querycheck, (void *)2, (void *)1, NULL },
1129 // // removed in PHP 5.3
1130 // { "mysqli_master_query", ih_querycheck, (void *)2, (void *)1, NULL },
1131 // { "mysqli_slave_query", ih_querycheck, (void *)2, (void *)1, NULL },
1132 // ----
1133
1134 /* Mysql API - deprecated in PHP 5.5 */
1135 // { "mysql_connect", ih_fixusername, (void *)2, NULL, NULL },
1136 // { "mysql_pconnect", ih_fixusername, (void *)2, NULL, NULL },
1137 // { "mysql_query", ih_querycheck, (void *)1, (void *)1, NULL },
1138 // { "mysql_db_query", ih_querycheck, (void *)2, (void *)1, NULL },
1139 // { "mysql_unbuffered_query", ih_querycheck, (void *)1, (void *)1, NULL },
1140
1141#ifdef SUHOSIN_EXPERIMENTAL
1142 /* MaxDB */
1143 // { "maxdb::maxdb", ih_fixusername, (void *)2, NULL, NULL },
1144 // { "maxdb_connect", ih_fixusername, (void *)2, NULL, NULL },
1145 // { "maxdb::real_connect", ih_fixusername, (void *)2, NULL, NULL },
1146 // { "maxdb_real_connect", ih_fixusername, (void *)3, NULL, NULL },
1147 // { "maxdb::change_user", ih_fixusername, (void *)1, NULL, NULL },
1148 // { "maxdb_change_user", ih_fixusername, (void *)2, NULL, NULL },
1149 //
1150 // { "maxdb_master_query", ih_querycheck, (void *)2, NULL, NULL },
1151 // { "maxdb::multi_query", ih_querycheck, (void *)1, NULL, NULL },
1152 // { "maxdb_multi_query", ih_querycheck, (void *)2, NULL, NULL },
1153 // { "maxdb::query", ih_querycheck, (void *)1, NULL, NULL },
1154 // { "maxdb_query", ih_querycheck, (void *)2, NULL, NULL },
1155 // { "maxdb::real_query", ih_querycheck, (void *)1, NULL, NULL },
1156 // { "maxdb_real_query", ih_querycheck, (void *)2, NULL, NULL },
1157 // { "maxdb::send_query", ih_querycheck, (void *)1, NULL, NULL },
1158 // { "maxdb_send_query", ih_querycheck, (void *)2, NULL, NULL },
1159 // { "maxdb::prepare", ih_querycheck, (void *)1, NULL, NULL },
1160 // { "maxdb_prepare", ih_querycheck, (void *)2, NULL, NULL },
1161
1162 /* PDO */
1163 /* note: mysql conditional comments not supported here */
1164 // { "pdo::__construct", ih_fixusername, (void *)2, NULL, NULL }, /* note: username may come from dsn (param 1) */
1165 // { "pdo::query", ih_querycheck, (void *)1, NULL, NULL },
1166 // { "pdo::prepare", ih_querycheck, (void *)1, NULL, NULL },
1167 // { "pdo::exec", ih_querycheck, (void *)1, NULL, NULL },
1168
1169 /* Oracle OCI8 */
1170 // { "ocilogon", ih_fixusername, (void *)1, NULL, NULL },
1171 // { "ociplogon", ih_fixusername, (void *)1, NULL, NULL },
1172 // { "ocinlogon", ih_fixusername, (void *)1, NULL, NULL },
1173 // { "oci_connect", ih_fixusername, (void *)1, NULL, NULL },
1174 // { "oci_pconnect", ih_fixusername, (void *)1, NULL, NULL },
1175 // { "oci_new_connect", ih_fixusername, (void *)1, NULL, NULL },
1176
1177 /* FrontBase */
1178 // { "fbsql_connect", ih_fixusername, (void *)2, NULL, NULL },
1179 // { "fbsql_pconnect", ih_fixusername, (void *)2, NULL, NULL },
1180 // { "fbsql_change_user", ih_fixusername, (void *)1, NULL, NULL },
1181 // { "fbsql_username", ih_fixusername, (void *)2, NULL, NULL },
1182
1183 /* Informix */
1184 // { "ifx_connect", ih_fixusername, (void *)2, NULL, NULL },
1185 // { "ifx_pconnect", ih_fixusername, (void *)2, NULL, NULL },
1186 //
1187 /* Firebird/InterBase */
1188 // { "ibase_connect", ih_fixusername, (void *)2, NULL, NULL },
1189 // { "ibase_pconnect", ih_fixusername, (void *)2, NULL, NULL },
1190 // { "ibase_service_attach", ih_fixusername, (void *)2, NULL, NULL },
1191
1192 /* Microsoft SQL Server */
1193 // { "mssql_connect", ih_fixusername, (void *)2, NULL, NULL },
1194 // { "mssql_pconnect", ih_fixusername, (void *)2, NULL, NULL },
1195#endif
1196
1197 { NULL, NULL, NULL, NULL, NULL }
1198};
1199
1200#define FUNCTION_WARNING() zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
1201#define FUNCTION_SIMULATE_WARNING() zend_error(E_WARNING, "SIMULATION - %s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
1202
1203/* {{{ void suhosin_execute_internal
1204 * This function provides a hook for internal execution */
1205
1206#define EX_T(offset) (*EX_TMP_VAR(execute_data_ptr, offset))
1207
1208ZEND_API static void suhosin_execute_internal(zend_execute_data *execute_data, zval *return_value)
1209{
1210 // zval *return_value;
1211 // zval **return_value_ptr;
1212 // zval *this_ptr;
1213 int ht = 0;
1214
1215 // if (fci) {
1216 // return_value = *fci->retval_ptr_ptr;
1217 // return_value_ptr = fci->retval_ptr_ptr;
1218 // this_ptr = fci->object_ptr;
1219 // ht = fci->param_count;
1220 // } else {
1221 // temp_variable *ret = &EX_T(execute_data_ptr->opline->result.var);
1222 // zend_function *fbc = execute_data_ptr->function_state.function;
1223 // return_value = ret->var.ptr;
1224 // return_value_ptr = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL;
1225 // this_ptr = execute_data_ptr->object;
1226 // ht = execute_data->opline->extended_value;
1227 // }
1228
1229 // char *lcname;
1230 // int function_name_strlen, free_lcname = 0;
1231 // zend_class_entry *ce = NULL;
1232 // internal_function_handler *ih;
1233 //
1234 // ce = ((zend_internal_function *) execute_data_ptr->function_state.function)->scope;
1235 // lcname = (char *)((zend_internal_function *) execute_data_ptr->function_state.function)->function_name;
1236 // function_name_strlen = strlen(lcname);
1237
1238 /* handle methodcalls correctly */
1239 // if (ce != NULL) {
1240 // char *tmp = (char *) emalloc(function_name_strlen + 2 + ce->name_length + 1);
1241 // memcpy(tmp, ce->name, ce->name_length);
1242 // memcpy(tmp+ce->name_length, "::", 2);
1243 // memcpy(tmp+ce->name_length+2, lcname, function_name_strlen);
1244 // lcname = tmp;
1245 // free_lcname = 1;
1246 // function_name_strlen += ce->name_length + 2;
1247 // lcname[function_name_strlen] = 0;
1248 // zend_str_tolower(lcname, function_name_strlen);
1249 // }
1250
1251 // TODO: check execute_data + ->func
1252
1253 zend_string *function_name = execute_data->func->op_array.function_name;
1254
1255 // TODO: check for function_name == NULL
1256
1257 SDEBUG("function: %s", ZSTR_VAL(function_name));
1258
1259 if (SUHOSIN7_G(in_code_type) == SUHOSIN_EVAL) {
1260
1261 if (SUHOSIN7_G(eval_whitelist) != NULL) {
1262 if (!zend_hash_exists(SUHOSIN7_G(eval_whitelist), function_name)) {
1263 suhosin_log(S_EXECUTOR|S_GETCALLER, "function outside of eval whitelist called: %s()", ZSTR_VAL(function_name));
1264 if (!SUHOSIN7_G(simulation)) {
1265 goto execute_internal_bailout;
1266 } else {
1267 FUNCTION_SIMULATE_WARNING()
1268 }
1269 }
1270 } else if (SUHOSIN7_G(eval_blacklist) != NULL) {
1271 if (zend_hash_exists(SUHOSIN7_G(eval_blacklist), function_name)) {
1272 suhosin_log(S_EXECUTOR|S_GETCALLER, "function within eval blacklist called: %s()", ZSTR_VAL(function_name));
1273 if (!SUHOSIN7_G(simulation)) {
1274 goto execute_internal_bailout;
1275 } else {
1276 FUNCTION_SIMULATE_WARNING()
1277 }
1278 }
1279 }
1280 }
1281
1282 if (SUHOSIN7_G(func_whitelist) != NULL) {
1283 if (!zend_hash_exists(SUHOSIN7_G(func_whitelist), function_name)) {
1284 suhosin_log(S_EXECUTOR|S_GETCALLER, "function outside of whitelist called: %s()", ZSTR_VAL(function_name));
1285 if (!SUHOSIN7_G(simulation)) {
1286 goto execute_internal_bailout;
1287 } else {
1288 FUNCTION_SIMULATE_WARNING()
1289 }
1290 }
1291 } else if (SUHOSIN7_G(func_blacklist) != NULL) {
1292 if (zend_hash_exists(SUHOSIN7_G(func_blacklist), function_name)) {
1293 suhosin_log(S_EXECUTOR|S_GETCALLER, "function within blacklist called: %s()", ZSTR_VAL(function_name));
1294 if (!SUHOSIN7_G(simulation)) {
1295 goto execute_internal_bailout;
1296 } else {
1297 FUNCTION_SIMULATE_WARNING()
1298 }
1299 }
1300 }
1301
1302 internal_function_handler *ih;
1303 int retval = 0;
1304 if ((ih = zend_hash_find_ptr(&ihandler_table, function_name))) {
1305
1306 void *handler = execute_data->func->internal_function.handler;
1307
1308 if (handler != ZEND_FN(display_disabled_function)) {
1309 retval = ih->handler(IH_HANDLER_PARAM_PASSTHRU);
1310 }
1311
1312 }
1313
1314 if (retval == 0) {
1315 old_execute_internal(execute_data, return_value);
1316 }
1317
1318 // if (free_lcname == 1) {
1319 // efree(lcname);
1320 // }
1321 return;
1322execute_internal_bailout:
1323 // if (free_lcname == 1) {
1324 // efree(lcname);
1325 // }
1326 FUNCTION_WARNING()
1327 suhosin_bailout(TSRMLS_C);
1328}
1329/* }}} */
1330
1331
1332/* {{{ int function_lookup(zend_extension *extension)
1333 */
1334static int function_lookup(zend_extension *extension)
1335{
1336 // if (zo_set_oe_ex != NULL) {
1337 // return ZEND_HASH_APPLY_STOP;
1338 // }
1339
1340 // if (extension->handle != NULL) {
1341 //
1342 // zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(extension->handle, "zend_optimizer_set_oe_ex");
1343 //
1344 // }
1345
1346 return 0;
1347}
1348/* }}} */
1349
1350
1351/* {{{ void suhosin_hook_execute()
1352 */
1353void suhosin_hook_execute()
1354{
1355 internal_function_handler *ih;
1356
1357 old_execute_ex = zend_execute_ex;
1358 zend_execute_ex = suhosin_execute_ex;
1359
1360/* old_compile_file = zend_compile_file;
1361 zend_compile_file = suhosin_compile_file; */
1362
1363#if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED
1364 if (zo_set_oe_ex == NULL) {
1365 zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(NULL, "zend_optimizer_set_oe_ex");
1366 }
1367 if (zo_set_oe_ex == NULL) {
1368 zend_llist_apply(&zend_extensions, (llist_apply_func_t)function_lookup TSRMLS_CC);
1369 }
1370
1371 if (zo_set_oe_ex != NULL) {
1372 old_execute_ZO = zo_set_oe_ex(suhosin_execute_ZO);
1373 }
1374#endif
1375
1376 old_execute_internal = zend_execute_internal;
1377 if (old_execute_internal == NULL) {
1378 old_execute_internal = execute_internal;
1379 }
1380 zend_execute_internal = suhosin_execute_internal;
1381
1382 /* register internal function handlers */
1383 zend_hash_init(&ihandler_table, 16, NULL, NULL, 1);
1384 ih = &ihandlers[0];
1385 while (ih->name) {
1386 zend_hash_str_add_ptr(&ihandler_table, ih->name, sizeof(ih->name)-1, ih);
1387 ih++;
1388 }
1389
1390
1391 /* Add additional protection layer, that SHOULD
1392 catch ZEND_INCLUDE_OR_EVAL *before* the engine tries
1393 to execute */
1394 // old_zend_stream_open = zend_stream_open_function;
1395 // zend_stream_open_function = suhosin_zend_stream_open;
1396
1397}
1398/* }}} */
1399
1400
1401/* {{{ void suhosin_unhook_execute()
1402 */
1403void suhosin_unhook_execute()
1404{
1405#if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED
1406 if (zo_set_oe_ex) {
1407 zo_set_oe_ex(old_execute_ZO);
1408 }
1409#endif
1410
1411 zend_execute_ex = old_execute_ex;
1412
1413/* zend_compile_file = old_compile_file; */
1414
1415 if (old_execute_internal == execute_internal) {
1416 old_execute_internal = NULL;
1417 }
1418 zend_execute_internal = old_execute_internal;
1419 zend_hash_clean(&ihandler_table);
1420
1421 /* remove zend_open protection */
1422 // zend_stream_open_function = old_zend_stream_open;
1423
1424}
1425/* }}} */
1426
1427// #endif // 0
1428
1429/*
1430 * Local variables:
1431 * tab-width: 4
1432 * c-basic-offset: 4
1433 * End:
1434 * vim600: noet sw=4 ts=4 fdm=marker
1435 * vim<600: noet sw=4 ts=4
1436 */