summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Fuhrmannek2016-02-19 11:30:08 +0100
committerBen Fuhrmannek2016-02-19 11:33:55 +0100
commit123907cdea68a7f8a58437ffe5cafd02e4d60aaf (patch)
tree6c801e046cfc48e8970a0ed7d50b029da50288aa
parent477b70127027407a7957690f24d5f857ca311de9 (diff)
basic executor support - ported from suhosin 0.9.39
-rw-r--r--execute.c1436
-rw-r--r--execute_rnd.inc.c385
2 files changed, 1821 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 */
diff --git a/execute_rnd.inc.c b/execute_rnd.inc.c
new file mode 100644
index 0000000..c09c467
--- /dev/null
+++ b/execute_rnd.inc.c
@@ -0,0 +1,385 @@
1/* MT RAND FUNCTIONS */
2
3/*
4 The following php_mt_...() functions are based on a C++ class MTRand by
5 Richard J. Wagner. For more information see the web page at
6 http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
7
8 Mersenne Twister random number generator -- a C++ class MTRand
9 Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
10 Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
11
12 The Mersenne Twister is an algorithm for generating random numbers. It
13 was designed with consideration of the flaws in various other generators.
14 The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
15 are far greater. The generator is also fast; it avoids multiplication and
16 division, and it benefits from caches and pipelines. For more information
17 see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
18
19 Reference
20 M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
21 Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
22 Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
23
24 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
25 Copyright (C) 2000 - 2003, Richard J. Wagner
26 All rights reserved.
27
28 Redistribution and use in source and binary forms, with or without
29 modification, are permitted provided that the following conditions
30 are met:
31
32 1. Redistributions of source code must retain the above copyright
33 notice, this list of conditions and the following disclaimer.
34
35 2. Redistributions in binary form must reproduce the above copyright
36 notice, this list of conditions and the following disclaimer in the
37 documentation and/or other materials provided with the distribution.
38
39 3. The names of its contributors may not be used to endorse or promote
40 products derived from this software without specific prior written
41 permission.
42
43 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
47 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
48 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
51 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
52 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54
55 The original code included the following notice:
56
57 When you use this, send an email to: matumoto@math.keio.ac.jp
58 with an appropriate reference to your work.
59
60 It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
61 when you write.
62*/
63
64#define N 624 /* length of state vector */
65#define M (397) /* a period parameter */
66#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */
67#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */
68#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */
69#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
70
71#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(v))) & 0x9908b0dfU))
72
73/* {{{ php_mt_initialize
74 */
75static inline void suhosin_mt_initialize(php_uint32 seed, php_uint32 *state)
76{
77 /* Initialize generator state with seed
78 See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
79 In previous versions, most significant bits (MSBs) of the seed affect
80 only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */
81
82 register php_uint32 *s = state;
83 register php_uint32 *r = state;
84 register int i = 1;
85
86 *s++ = seed & 0xffffffffU;
87 for( ; i < N; ++i ) {
88 *s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU;
89 r++;
90 }
91}
92/* }}} */
93
94static inline void suhosin_mt_init_by_array(php_uint32 *key, int keylen, php_uint32 *state)
95{
96 int i, j, k;
97 suhosin_mt_initialize(19650218U, state);
98 i = 1; j = 0;
99 k = (N > keylen ? N : keylen);
100 for (; k; k--) {
101 state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525U)) + key[j] + j;
102 i++; j = (j+1) % keylen;
103 if (i >= N) { state[0] = state[N-1]; i=1; }
104 }
105 for (k=N-1; k; k--) {
106 state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941U)) - i;
107 i++;
108 if (i >= N) { state[0] = state[N-1]; i=1; }
109 }
110 state[0] = 0x80000000U;
111}
112/* }}} */
113
114
115/* {{{ suhosin_mt_reload
116 */
117static inline void suhosin_mt_reload(php_uint32 *state, php_uint32 **next, int *left)
118{
119 /* Generate N new values in state
120 Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) */
121
122 register php_uint32 *p = state;
123 register int i;
124
125 for (i = N - M; i--; ++p)
126 *p = twist(p[M], p[0], p[1]);
127 for (i = M; --i; ++p)
128 *p = twist(p[M-N], p[0], p[1]);
129 *p = twist(p[M-N], p[0], state[0]);
130 *left = N;
131 *next = state;
132}
133/* }}} */
134
135/* {{{ suhosin_mt_srand
136 */
137static void suhosin_mt_srand(php_uint32 seed TSRMLS_DC)
138{
139 /* Seed the generator with a simple uint32 */
140 suhosin_mt_initialize(seed, SUHOSIN7_G(mt_state));
141 suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left));
142
143 /* Seed only once */
144 SUHOSIN7_G(mt_is_seeded) = 1;
145}
146/* }}} */
147
148/* {{{ suhosin_mt_rand
149 */
150static php_uint32 suhosin_mt_rand(TSRMLS_D)
151{
152 /* Pull a 32-bit integer from the generator state
153 Every other access function simply transforms the numbers extracted here */
154
155 register php_uint32 s1;
156
157 if (SUHOSIN7_G(mt_left) == 0) {
158 suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left));
159 }
160 --SUHOSIN7_G(mt_left);
161
162 s1 = *SUHOSIN7_G(mt_next)++;
163 s1 ^= (s1 >> 11);
164 s1 ^= (s1 << 7) & 0x9d2c5680U;
165 s1 ^= (s1 << 15) & 0xefc60000U;
166 return ( s1 ^ (s1 >> 18) );
167}
168/* }}} */
169
170/* {{{ SUHOSIN7_Gen_entropy
171 */
172static void SUHOSIN7_Gen_entropy(php_uint32 *entropybuf TSRMLS_DC)
173{
174 php_uint32 seedbuf[20];
175 /* On a modern OS code, stack and heap base are randomized */
176 unsigned long code_value = (unsigned long)SUHOSIN7_Gen_entropy;
177 unsigned long stack_value = (unsigned long)&code_value;
178 unsigned long heap_value = (unsigned long)SUHOSIN7_G(r_state);
179 suhosin_SHA256_CTX context;
180 int fd;
181
182 code_value ^= code_value >> 32;
183 stack_value ^= stack_value >> 32;
184 heap_value ^= heap_value >> 32;
185
186 seedbuf[0] = code_value;
187 seedbuf[1] = stack_value;
188 seedbuf[2] = heap_value;
189 seedbuf[3] = time(0);
190#ifdef PHP_WIN32
191 seedbuf[4] = GetCurrentProcessId();
192#else
193 seedbuf[4] = getpid();
194#endif
195 seedbuf[5] = (php_uint32) 0x7fffffff * php_combined_lcg(TSRMLS_C);
196
197#ifndef PHP_WIN32
198 fd = VCWD_OPEN("/dev/urandom", O_RDONLY);
199 if (fd >= 0) {
200 /* ignore error case - if urandom doesn't give us any/enough random bytes */
201 read(fd, &seedbuf[6], 8 * sizeof(php_uint32));
202 close(fd);
203 }
204#else
205 /* we have to live with the possibility that this call fails */
206 php_win32_get_random_bytes((unsigned char*)&seedbuf[6], 8 * sizeof(php_uint32));
207#endif
208
209 suhosin_SHA256Init(&context);
210 /* to our friends from Debian: yes this will add unitialized stack values to the entropy DO NOT REMOVE */
211 suhosin_SHA256Update(&context, (void *) seedbuf, sizeof(seedbuf));
212 if (SUHOSIN7_G(seedingkey) != NULL && *SUHOSIN7_G(seedingkey) != 0) {
213 suhosin_SHA256Update(&context, (unsigned char*)SUHOSIN7_G(seedingkey), strlen(SUHOSIN7_G(seedingkey)));
214 }
215 suhosin_SHA256Final((void *)entropybuf, &context);
216}
217/* }}} */
218
219
220/* {{{ suhosin_srand_auto
221 */
222static void suhosin_srand_auto(TSRMLS_D)
223{
224 php_uint32 seed[8];
225 SUHOSIN7_Gen_entropy(&seed[0] TSRMLS_CC);
226
227 suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(r_state));
228 suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left));
229
230 /* Seed only once */
231 SUHOSIN7_G(r_is_seeded) = 1;
232}
233/* }}} */
234
235/* {{{ suhosin_mt_srand_auto
236 */
237static void suhosin_mt_srand_auto(TSRMLS_D)
238{
239 php_uint32 seed[8];
240 SUHOSIN7_Gen_entropy(&seed[0] TSRMLS_CC);
241
242 suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(mt_state));
243 suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left));
244
245 /* Seed only once */
246 SUHOSIN7_G(mt_is_seeded) = 1;
247}
248/* }}} */
249
250
251/* {{{ suhosin_srand
252 */
253static void suhosin_srand(php_uint32 seed TSRMLS_DC)
254{
255 /* Seed the generator with a simple uint32 */
256 suhosin_mt_initialize(seed+0x12345, SUHOSIN7_G(r_state));
257 suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left));
258
259 /* Seed only once */
260 SUHOSIN7_G(r_is_seeded) = 1;
261}
262/* }}} */
263
264/* {{{ suhosin_mt_rand
265 */
266static php_uint32 suhosin_rand(TSRMLS_D)
267{
268 /* Pull a 32-bit integer from the generator state
269 Every other access function simply transforms the numbers extracted here */
270
271 register php_uint32 s1;
272
273 if (SUHOSIN7_G(r_left) == 0) {
274 suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left));
275 }
276 --SUHOSIN7_G(r_left);
277
278 s1 = *SUHOSIN7_G(r_next)++;
279 s1 ^= (s1 >> 11);
280 s1 ^= (s1 << 7) & 0x9d2c5680U;
281 s1 ^= (s1 << 15) & 0xefc60000U;
282 return ( s1 ^ (s1 >> 18) );
283}
284/* }}} */
285
286static int ih_srand(IH_HANDLER_PARAMS)
287{
288 int argc = ZEND_NUM_ARGS();
289 long seed;
290
291 if (SUHOSIN7_G(srand_ignore)) {
292 SUHOSIN7_G(r_is_seeded) = 0;
293 return 1;
294 }
295
296 if (zend_parse_parameters(argc TSRMLS_CC, "|l", &seed) == FAILURE) {
297 return 1;
298 }
299
300 if (argc) {
301 suhosin_srand(seed TSRMLS_CC);
302 } else {
303 suhosin_srand_auto(TSRMLS_C);
304 }
305 return (1);
306}
307
308static int ih_mt_srand(IH_HANDLER_PARAMS)
309{
310 int argc = ZEND_NUM_ARGS();
311 long seed;
312
313 if (SUHOSIN7_G(mt_srand_ignore)) {
314 SUHOSIN7_G(mt_is_seeded) = 0;
315 return 1;
316 }
317
318 if (zend_parse_parameters(argc TSRMLS_CC, "|l", &seed) == FAILURE) {
319 return 1;
320 }
321
322 if (argc) {
323 suhosin_mt_srand(seed TSRMLS_CC);
324 } else {
325 suhosin_mt_srand_auto(TSRMLS_C);
326 }
327 return 1;
328}
329
330static int ih_mt_rand(IH_HANDLER_PARAMS)
331{
332 int argc = ZEND_NUM_ARGS();
333 long min;
334 long max;
335 long number;
336
337 if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) {
338 return (1);
339 }
340
341 if (!SUHOSIN7_G(mt_is_seeded)) {
342 suhosin_mt_srand_auto(TSRMLS_C);
343 }
344
345 number = (long) (suhosin_mt_rand(TSRMLS_C) >> 1);
346 if (argc == 2) {
347 RAND_RANGE(number, min, max, PHP_MT_RAND_MAX);
348 }
349
350 RETVAL_LONG(number);
351 return (1);
352}
353
354static int ih_rand(IH_HANDLER_PARAMS)
355{
356 int argc = ZEND_NUM_ARGS();
357 long min;
358 long max;
359 long number;
360
361 if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) {
362 return (1);
363 }
364
365 if (!SUHOSIN7_G(r_is_seeded)) {
366 suhosin_srand_auto(TSRMLS_C);
367 }
368
369 number = (long) (suhosin_rand(TSRMLS_C) >> 1);
370 if (argc == 2) {
371 RAND_RANGE(number, min, max, PHP_MT_RAND_MAX);
372 }
373
374 RETVAL_LONG(number);
375 return (1);
376}
377
378static int ih_getrandmax(IH_HANDLER_PARAMS)
379{
380 if (zend_parse_parameters_none() == FAILURE) {
381 return(0);
382 }
383 RETVAL_LONG(PHP_MT_RAND_MAX);
384 return (1);
385}