From d4e9bb339360cb7d6ece5b1b60c08c8611bac19c Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Wed, 24 Feb 2016 23:33:34 +0100 Subject: executor improvements --- config.m4 | 2 +- execute.c | 700 ++++++++++-------------------------------------------- execute.h | 21 ++ execute_ih.c | 495 ++++++++++++++++++++++++++++++++++++++ execute_rnd.c | 385 ++++++++++++++++++++++++++++++ execute_rnd.inc.c | 385 ------------------------------ header.c | 4 +- log.c | 28 +-- php_suhosin7.h | 2 +- suhosin7.c | 2 +- 10 files changed, 1043 insertions(+), 981 deletions(-) create mode 100644 execute.h create mode 100644 execute_ih.c create mode 100644 execute_rnd.c delete mode 100644 execute_rnd.inc.c diff --git a/config.m4 b/config.m4 index 65b0c83..6b78024 100644 --- a/config.m4 +++ b/config.m4 @@ -5,7 +5,7 @@ PHP_ARG_ENABLE(suhosin7, whether to enable suhosin support, [ --enable-suhosin7 Enable suhosin support]) if test "$PHP_SUHOSIN7" != "no"; then - PHP_NEW_EXTENSION(suhosin7, suhosin7.c ifilter.c memory_limit.c aes.c treat_data.c log.c execute.c crypt.c cookiecrypt.c header.c, $ext_shared,, -DZEND_ENABLE_STATIC_ACHE=1) + PHP_NEW_EXTENSION(suhosin7, suhosin7.c ifilter.c memory_limit.c aes.c treat_data.c log.c execute.c execute_ih.c crypt.c cookiecrypt.c header.c, $ext_shared,, -DZEND_ENABLE_STATIC_ACHE=1) PHP_ADD_EXTENSION_DEP(suhosin7, hash) fi diff --git a/execute.c b/execute.c index 0e569e0..4a6e279 100644 --- a/execute.c +++ b/execute.c @@ -23,29 +23,30 @@ #include "config.h" #endif -#include +// #include #include "php.h" -#include "php_ini.h" -#include "zend_hash.h" +// #include "php_ini.h" +// #include "zend_hash.h" #include "zend_extensions.h" -#include "ext/standard/info.h" -#include "ext/standard/php_rand.h" -#include "ext/standard/php_lcg.h" +// #include "ext/standard/info.h" +// #include "ext/standard/php_rand.h" +// #include "ext/standard/php_lcg.h" #include "php_suhosin7.h" -#include "zend_compile.h" -#include "zend_llist.h" +// #include "zend_compile.h" +// #include "zend_llist.h" #include "SAPI.h" +#include "execute.h" -#include "sha256.h" +// #include "sha256.h" #ifdef PHP_WIN32 -# include "win32/fnmatch.h" +// # include "win32/fnmatch.h" # include "win32/winutil.h" # include "win32/time.h" #else -# ifdef HAVE_FNMATCH -# include -# endif +// # ifdef HAVE_FNMATCH +// # include +// # endif # include #endif @@ -86,7 +87,7 @@ conts: #define SUHOSIN_CODE_TYPE_UNKNOWN 0 #define SUHOSIN_CODE_TYPE_COMMANDLINE 1 #define SUHOSIN_CODE_TYPE_EVAL 2 -#define SUHOSIN_CODE_TYPE_REGEXP 3 +// #define SUHOSIN_CODE_TYPE_REGEXP 3 #define SUHOSIN_CODE_TYPE_ASSERT 4 #define SUHOSIN_CODE_TYPE_CFUNC 5 #define SUHOSIN_CODE_TYPE_SUHOSIN 6 @@ -98,7 +99,7 @@ conts: #define SUHOSIN_CODE_TYPE_BADFILE 12 #define SUHOSIN_CODE_TYPE_LONGNAME 13 #define SUHOSIN_CODE_TYPE_MANYDOTS 14 -#define SUHOSIN_CODE_TYPE_WRITABLE 15 +#define SUHOSIN_CODE_TYPE_WRITABLE 15 #define SUHOSIN_CODE_TYPE_MBREGEXP 16 static int suhosin_check_filename(char *s, int len) @@ -315,9 +316,9 @@ static int suhosin_detect_codetype(zend_op_array *op_array) return SUHOSIN_CODE_TYPE_EVAL; } - if (strstr(s, "regexp code") != NULL) { - return SUHOSIN_CODE_TYPE_REGEXP; - } + // if (strstr(s, "regexp code") != NULL) { + // return SUHOSIN_CODE_TYPE_REGEXP; + // } if (strstr(s, "mbregex replace") != NULL) { return SUHOSIN_CODE_TYPE_MBREGEXP; @@ -519,18 +520,23 @@ not_evaled_code: } break; - case SUHOSIN_CODE_TYPE_REGEXP: + // case SUHOSIN_CODE_TYPE_REGEXP: + // if (SUHOSIN7_G(executor_disable_emod)) { + // suhosin_log(S_EXECUTOR|S_GETCALLER, "use of preg_replace() with /e modifier is forbidden by configuration"); + // if (!SUHOSIN7_G(simulation)) { + // zend_error(E_ERROR, "SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration"); + // } + // } + // break; + + case SUHOSIN_CODE_TYPE_MBREGEXP: if (SUHOSIN7_G(executor_disable_emod)) { - suhosin_log(S_EXECUTOR|S_GETCALLER, "use of preg_replace() with /e modifier is forbidden by configuration"); + suhosin_log(S_EXECUTOR|S_GETCALLER, "use of /e modifier in replace function is forbidden by configuration"); if (!SUHOSIN7_G(simulation)) { - zend_error(E_ERROR, "SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration"); + zend_error(E_ERROR, "SUHOSIN - Use of /e modifier in replace function is forbidden by configuration"); } } break; - - case SUHOSIN_CODE_TYPE_MBREGEXP: - /* XXX TODO: Do we want to disallow this, too? */ - break; case SUHOSIN_CODE_TYPE_ASSERT: break; @@ -603,499 +609,16 @@ continue_execution: /* }}} */ -#define IH_HANDLER_PARAMS_REST int ht, zval *return_value -#define IH_HANDLER_PARAMS internal_function_handler *ih, IH_HANDLER_PARAMS_REST -#define IH_HANDLER_PARAM_PASSTHRU ih, ht, return_value - - -HashTable ihandler_table; -typedef struct _internal_function_handler { +// ---------------------------------------------------------------------------- - char *name; - int (*handler)(struct _internal_function_handler *ih, IH_HANDLER_PARAMS_REST); - void *arg1; - void *arg2; - void *arg3; +static HashTable ihandler_table; -} internal_function_handler; - -// int ih_preg_replace(IH_HANDLER_PARAMS) -// { -// zval **regex, -// **replace, -// **subject, -// **limit, **zcount; -// -// if (zend_parse_parameters(ZEND_NUM_ARGS(), "ZZZ|ZZ", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) { -// return(0); -// } -// -// if (Z_TYPE_PP(regex) == IS_ARRAY) { -// zval **regex_entry; -// -// zend_hash_internal_pointer_reset(Z_ARRVAL_PP(regex)); -// /* For each entry in the regex array, get the entry */ -// while (zend_hash_get_current_data(Z_ARRVAL_PP(regex), (void **)®ex_entry) == SUCCESS) { -// -// if (Z_TYPE_PP(regex_entry) == IS_STRING) { -// if (strlen(Z_STRVAL_PP(regex_entry)) != Z_STRLEN_PP(regex_entry)) { -// suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// } -// -// zend_hash_move_forward(Z_ARRVAL_PP(regex)); -// -// } -// -// } else if (Z_TYPE_PP(regex) == IS_STRING) { -// if (strlen(Z_STRVAL_PP(regex)) != Z_STRLEN_PP(regex)) { -// suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// } -// -// return (0); -// } -// int ih_symlink(IH_HANDLER_PARAMS) -// { -// if (SUHOSIN7_G(executor_allow_symlink)) { -// return (0); -// } -// -// if (PG(open_basedir) && PG(open_basedir)[0]) { -// suhosin_log(S_EXECUTOR, "symlink called during open_basedir"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// -// return (0); -// } -// int ih_mail(IH_HANDLER_PARAMS) -// { -// char *to=NULL, *message=NULL, *headers=NULL; -// char *subject=NULL, *extra_cmd=NULL; -// char *tmp; -// int to_len, message_len, headers_len; -// int subject_len, extra_cmd_len; -// -// if (SUHOSIN7_G(mailprotect) == 0) { -// return (0); -// } -// -// if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|ss", -// &to, &to_len, -// &subject, &subject_len, -// &message, &message_len, -// &headers, &headers_len, -// &extra_cmd, &extra_cmd_len -// ) == FAILURE) { -// RETVAL_FALSE; -// return (1); -// } -// -// if (headers_len > 0 && headers && -// (strstr(headers, "\n\n") || strstr(headers, "\n\r\n") /* double newline */ -// || *headers == '\n' || (headers[0] == '\r' && headers[1] == '\n') /* starts with newline */ -// )) { -// suhosin_log(S_MAIL, "mail() - double newline in headers, possible injection, mail dropped"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// -// /* check for spam attempts with buggy webforms */ -// if (to_len > 0 && to) { -// do { -// if ((tmp = strchr(to, '\n')) == NULL) -// tmp = strchr(to, '\r'); -// if (tmp == NULL) break; -// to = tmp + 1; -// if (!isspace(*to)) break; -// } while (1); -// if (tmp != NULL) { -// suhosin_log(S_MAIL, "mail() - newline in To header, possible injection, mail dropped"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// } -// -// if (subject_len > 0 && subject) { -// do { -// if ((tmp = strchr(subject, '\n')) == NULL) -// tmp = strchr(subject, '\r'); -// if (tmp == NULL) break; -// subject = tmp + 1; -// if (!isspace(*subject)) break; -// } while (1); -// if (tmp != NULL) { -// suhosin_log(S_MAIL, "mail() - newline in Subject header, possible injection, mail dropped"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// } -// -// if (SUHOSIN7_G(mailprotect) > 1) { -// /* search for to, cc or bcc headers */ -// if (headers_len > 0 && headers != NULL) { -// if (strncasecmp(headers, "to:", sizeof("to:") - 1) == 0 || suhosin_strcasestr(headers, "\nto:")) { -// suhosin_log(S_MAIL, "mail() - To: headers aren't allowed in the headers parameter."); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// -// if (strncasecmp(headers, "cc:", sizeof("cc:") - 1) == 0 || suhosin_strcasestr(headers, "\ncc:")) { -// suhosin_log(S_MAIL, "mail() - CC: headers aren't allowed in the headers parameter."); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// -// if (strncasecmp(headers, "bcc:", sizeof("bcc:") - 1) == 0 || suhosin_strcasestr(headers, "\nbcc:")) { -// suhosin_log(S_MAIL, "mail() - BCC: headers aren't allowed in the headers parameter."); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// } -// } -// -// return (0); -// } +static suhosin_internal_function_handler ihandlers[] = { + S7_IH_ENTRY0i(preg_replace) -// #define SQLSTATE_SQL 0 -// #define SQLSTATE_IDENTIFIER 1 -// #define SQLSTATE_STRING 2 -// #define SQLSTATE_COMMENT 3 -// #define SQLSTATE_MLCOMMENT 4 -// -// int ih_querycheck(IH_HANDLER_PARAMS) -// { -// void **p = zend_vm_stack_top() - 1; -// unsigned long arg_count; -// zval **arg; -// char *query, *s, *e; -// zval *backup; -// int len; -// char quote; -// int state = SQLSTATE_SQL; -// int cnt_union = 0, cnt_select = 0, cnt_comment = 0, cnt_opencomment = 0; -// int mysql_extension = 0; -// -// -// SDEBUG("function: %s", ih->name); -// arg_count = (unsigned long) *p; -// -// if (ht < (long) ih->arg1) { -// return (0); -// } -// -// if ((long) ih->arg2) { -// mysql_extension = 1; -// } -// -// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ -// -// backup = *arg; -// if (Z_TYPE_P(backup) != IS_STRING) { -// return (0); -// } -// len = Z_STRLEN_P(backup); -// query = Z_STRVAL_P(backup); -// SDEBUG("SQL |%s|", query); -// -// s = query; -// e = s+len; -// -// while (s < e) { -// switch (state) -// { -// case SQLSTATE_SQL: -// switch (s[0]) -// { -// case '`': -// state = SQLSTATE_IDENTIFIER; -// quote = '`'; -// break; -// case '\'': -// case '"': -// state = SQLSTATE_STRING; -// quote = *s; -// break; -// case '/': -// if (s[1]=='*') { -// if (mysql_extension == 1 && s[2] == '!') { -// s += 2; -// break; -// } -// s++; -// state = SQLSTATE_MLCOMMENT; -// cnt_comment++; -// } -// break; -// case '-': -// if (s[1]=='-') { -// s++; -// state = SQLSTATE_COMMENT; -// cnt_comment++; -// } -// break; -// case '#': -// state = SQLSTATE_COMMENT; -// cnt_comment++; -// break; -// case 'u': -// case 'U': -// if (strncasecmp("union", s, 5)==0) { -// s += 4; -// cnt_union++; -// } -// break; -// case 's': -// case 'S': -// if (strncasecmp("select", s, 6)==0) { -// s += 5; -// cnt_select++; -// } -// break; -// } -// break; -// case SQLSTATE_STRING: -// case SQLSTATE_IDENTIFIER: -// if (s[0] == quote) { -// if (s[1] == quote) { -// s++; -// } else { -// state = SQLSTATE_SQL; -// } -// } -// if (s[0] == '\\') { -// s++; -// } -// break; -// case SQLSTATE_COMMENT: -// while (s[0] && s[0] != '\n') { -// s++; -// } -// state = SQLSTATE_SQL; -// break; -// case SQLSTATE_MLCOMMENT: -// while (s[0] && (s[0] != '*' || s[1] != '/')) { -// s++; -// } -// if (s[0]) { -// state = SQLSTATE_SQL; -// } -// break; -// } -// s++; -// } -// if (state == SQLSTATE_MLCOMMENT) { -// cnt_opencomment = 1; -// } -// -// if (cnt_opencomment && SUHOSIN7_G(sql_opencomment)>0) { -// suhosin_log(S_SQL, "Open comment in SQL query: '%*s'", len, query); -// if (SUHOSIN7_G(sql_opencomment)>1) { -// suhosin_bailout(); -// } -// } -// -// if (cnt_comment && SUHOSIN7_G(sql_comment)>0) { -// suhosin_log(S_SQL, "Comment in SQL query: '%*s'", len, query); -// if (SUHOSIN7_G(sql_comment)>1) { -// suhosin_bailout(); -// } -// } -// -// if (cnt_union && SUHOSIN7_G(sql_union)>0) { -// suhosin_log(S_SQL, "UNION in SQL query: '%*s'", len, query); -// if (SUHOSIN7_G(sql_union)>1) { -// suhosin_bailout(); -// } -// } -// -// if (cnt_select>1 && SUHOSIN7_G(sql_mselect)>0) { -// suhosin_log(S_SQL, "Multiple SELECT in SQL query: '%*s'", len, query); -// if (SUHOSIN7_G(sql_mselect)>1) { -// suhosin_bailout(); -// } -// } -// -// return (0); -// } -// -// -// int ih_fixusername(IH_HANDLER_PARAMS) -// { -// void **p = zend_vm_stack_top() - 1; -// unsigned long arg_count; -// zval **arg; -// char *prefix, *postfix, *user, *user_match, *cp; -// zval *backup, *my_user; -// int prefix_len, postfix_len, len; -// -// SDEBUG("function (fixusername): %s", ih->name); -// -// prefix = SUHOSIN7_G(sql_user_prefix); -// postfix = SUHOSIN7_G(sql_user_postfix); -// user_match = SUHOSIN7_G(sql_user_match); -// -// arg_count = (unsigned long) *p; -// -// if (ht < (long) ih->arg1) { -// return (0); -// } -// -// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ -// -// backup = *arg; -// if (Z_TYPE_P(backup) != IS_STRING) { -// user = ""; -// len = 0; -// } else { -// len = Z_STRLEN_P(backup); -// user = Z_STRVAL_P(backup); -// } -// -// cp = user; -// while (cp < user+len) { -// if (*cp < 32) { -// suhosin_log(S_SQL, "SQL username contains invalid characters"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// break; -// } -// cp++; -// } -// -// if ((prefix != NULL && prefix[0]) || (postfix != NULL && postfix[0])) { -// if (prefix == NULL) { -// prefix = ""; -// } -// if (postfix == NULL) { -// postfix = ""; -// } -// prefix_len = strlen(prefix); -// postfix_len = strlen(postfix); -// -// MAKE_STD_ZVAL(my_user); -// my_user->type = IS_STRING; -// my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); -// -// /* XXX: memory_leak? */ -// *arg = my_user; -// -// len = Z_STRLEN_P(my_user); -// user = Z_STRVAL_P(my_user); -// } -// -// if (user_match && user_match[0]) { -// #ifdef HAVE_FNMATCH -// if (fnmatch(user_match, user, 0) != 0) { -// suhosin_log(S_SQL, "SQL username ('%s') does not match suhosin.sql.user_match ('%s')", user, user_match); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// } -// #else -// #warning no support for fnmatch() - setting suhosin.sql.user_match will always fail. -// suhosin_log(S_SQL, "suhosin.sql.user_match specified, but system does not support fnmatch()"); -// if (!SUHOSIN7_G(simulation)) { -// RETVAL_FALSE; -// return (1); -// } -// #endif -// } -// -// SDEBUG("function: %s - user: %s", ih->name, user); -// -// return (0); -// } -// -// -// static int ih_function_exists(IH_HANDLER_PARAMS) -// { -// zval **function_name; -// zend_function *func; -// char *lcname; -// zend_bool retval; -// int func_name_len; -// -// if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) { -// ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(1); -// } -// convert_to_string_ex(function_name); -// func_name_len = Z_STRLEN_PP(function_name); -// lcname = estrndup(Z_STRVAL_PP(function_name), func_name_len); -// zend_str_tolower(lcname, func_name_len); -// -// retval = (zend_hash_find(EG(function_table), lcname, func_name_len+1, (void **)&func) == SUCCESS); -// -// /* -// * A bit of a hack, but not a bad one: we see if the handler of the function -// * is actually one that displays "function is disabled" message. -// */ -// if (retval && func->type == ZEND_INTERNAL_FUNCTION && -// func->internal_function.handler == zif_display_disabled_function) { -// retval = 0; -// } -// -// /* Now check if function is forbidden by Suhosin */ -// if (SUHOSIN7_G(in_code_type) == SUHOSIN_EVAL) { -// if (SUHOSIN7_G(eval_whitelist) != NULL) { -// if (!zend_hash_exists(SUHOSIN7_G(eval_whitelist), lcname, func_name_len+1)) { -// retval = 0; -// } -// } else if (SUHOSIN7_G(eval_blacklist) != NULL) { -// if (zend_hash_exists(SUHOSIN7_G(eval_blacklist), lcname, func_name_len+1)) { -// retval = 0; -// } -// } -// } -// -// if (SUHOSIN7_G(func_whitelist) != NULL) { -// if (!zend_hash_exists(SUHOSIN7_G(func_whitelist), lcname, func_name_len+1)) { -// retval = 0; -// } -// } else if (SUHOSIN7_G(func_blacklist) != NULL) { -// if (zend_hash_exists(SUHOSIN7_G(func_blacklist), lcname, func_name_len+1)) { -// retval = 0; -// } -// } -// -// efree(lcname); -// -// RETVAL_BOOL(retval); -// return (1); -// } - -// #include "execute_rnd.inc.c" - -internal_function_handler ihandlers[] = { // { "preg_replace", ih_preg_replace, NULL, NULL, NULL }, // { "mail", ih_mail, NULL, NULL, NULL }, // { "symlink", ih_symlink, NULL, NULL, NULL }, @@ -1139,7 +662,7 @@ internal_function_handler ihandlers[] = { // { "mysql_db_query", ih_querycheck, (void *)2, (void *)1, NULL }, // { "mysql_unbuffered_query", ih_querycheck, (void *)1, (void *)1, NULL }, -#ifdef SUHOSIN_EXPERIMENTAL +#ifdef SUHOSIN7_EXPERIMENTAL /* MaxDB */ // { "maxdb::maxdb", ih_fixusername, (void *)2, NULL, NULL }, // { "maxdb_connect", ih_fixusername, (void *)2, NULL, NULL }, @@ -1198,8 +721,8 @@ internal_function_handler ihandlers[] = { { NULL, NULL, NULL, NULL, NULL } }; -#define FUNCTION_WARNING() zend_error(E_WARNING, "%s() has been disabled for security reasons", suhosin_get_active_function_name()); -#define FUNCTION_SIMULATE_WARNING() zend_error(E_WARNING, "SIMULATION - %s() has been disabled for security reasons", suhosin_get_active_function_name()); +#define FUNCTION_WARNING(fname) zend_error(E_WARNING, "%s() has been disabled for security reasons", (fname)); +#define FUNCTION_SIMULATE_WARNING(fname) zend_error(E_WARNING, "SIMULATION - %s() has been disabled for security reasons", (fname)); /* {{{ void suhosin_execute_internal * This function provides a hook for internal execution */ @@ -1208,10 +731,28 @@ internal_function_handler ihandlers[] = { ZEND_API static void suhosin_execute_internal(zend_execute_data *execute_data, zval *return_value) { + if (execute_data == NULL) { + // if (EG(current_execute_data) != NULL) { + // execute_data = EG(current_execute_data); + // } + suhosin_log(S_EXECUTOR|S_GETCALLER, "execution without data. something is wrong."); + suhosin_bailout(); + return; + } + + zend_function *func = execute_data->func; + if (func == NULL) { + suhosin_log(S_EXECUTOR|S_GETCALLER, "execution without function context. something is wrong."); + suhosin_bailout(); + } + + // zval *return_value; // zval **return_value_ptr; // zval *this_ptr; int ht = 0; + int retval = SUCCESS; + // if (fci) { // return_value = *fci->retval_ptr_ptr; @@ -1249,32 +790,35 @@ ZEND_API static void suhosin_execute_internal(zend_execute_data *execute_data, z // zend_str_tolower(lcname, function_name_strlen); // } - // TODO: check execute_data + ->func - - zend_string *function_name = execute_data->func->op_array.function_name; - - // TODO: check for function_name == NULL - - SDEBUG("function: %s", ZSTR_VAL(function_name)); + zend_string *function_name = func->common.function_name; + if (function_name == NULL) { + function_name = func->op_array.function_name; + } + if (function_name == NULL) { + // no function name -> skip whitelists/blacklists + goto execute_internal_continue; + } + + SDEBUG("function: [%s]/%zu", ZSTR_VAL(function_name), ZSTR_LEN(function_name)) ; if (SUHOSIN7_G(in_code_type) == SUHOSIN_EVAL) { if (SUHOSIN7_G(eval_whitelist) != NULL) { if (!zend_hash_exists(SUHOSIN7_G(eval_whitelist), function_name)) { - suhosin_log(S_EXECUTOR|S_GETCALLER, "function outside of eval whitelist called: %s()", ZSTR_VAL(function_name)); + suhosin_log(S_EXECUTOR|S_GETCALLER, "eval'd function not whitelisted: %s()", ZSTR_VAL(function_name)); if (!SUHOSIN7_G(simulation)) { goto execute_internal_bailout; } else { - FUNCTION_SIMULATE_WARNING() + FUNCTION_SIMULATE_WARNING(ZSTR_VAL(function_name)) } } } else if (SUHOSIN7_G(eval_blacklist) != NULL) { if (zend_hash_exists(SUHOSIN7_G(eval_blacklist), function_name)) { - suhosin_log(S_EXECUTOR|S_GETCALLER, "function within eval blacklist called: %s()", ZSTR_VAL(function_name)); + suhosin_log(S_EXECUTOR|S_GETCALLER, "eval'd function blacklisted: %s()", ZSTR_VAL(function_name)); if (!SUHOSIN7_G(simulation)) { goto execute_internal_bailout; } else { - FUNCTION_SIMULATE_WARNING() + FUNCTION_SIMULATE_WARNING(ZSTR_VAL(function_name)) } } } @@ -1282,49 +826,51 @@ ZEND_API static void suhosin_execute_internal(zend_execute_data *execute_data, z if (SUHOSIN7_G(func_whitelist) != NULL) { if (!zend_hash_exists(SUHOSIN7_G(func_whitelist), function_name)) { - suhosin_log(S_EXECUTOR|S_GETCALLER, "function outside of whitelist called: %s()", ZSTR_VAL(function_name)); + suhosin_log(S_EXECUTOR|S_GETCALLER, "function not whitelisted: %s()", ZSTR_VAL(function_name)); if (!SUHOSIN7_G(simulation)) { goto execute_internal_bailout; } else { - FUNCTION_SIMULATE_WARNING() + FUNCTION_SIMULATE_WARNING(ZSTR_VAL(function_name)) } } } else if (SUHOSIN7_G(func_blacklist) != NULL) { if (zend_hash_exists(SUHOSIN7_G(func_blacklist), function_name)) { - suhosin_log(S_EXECUTOR|S_GETCALLER, "function within blacklist called: %s()", ZSTR_VAL(function_name)); + suhosin_log(S_EXECUTOR|S_GETCALLER, "function blacklisted: %s()", ZSTR_VAL(function_name)); if (!SUHOSIN7_G(simulation)) { goto execute_internal_bailout; } else { - FUNCTION_SIMULATE_WARNING() + FUNCTION_SIMULATE_WARNING(ZSTR_VAL(function_name)) } } } - internal_function_handler *ih; - int retval = 0; + suhosin_internal_function_handler *ih; + // SDEBUG("before %d", zend_hash_exists(&ihandler_table, function_name)); if ((ih = zend_hash_find_ptr(&ihandler_table, function_name))) { - + // SDEBUG("AFTER"); void *handler = execute_data->func->internal_function.handler; if (handler != ZEND_FN(display_disabled_function)) { - retval = ih->handler(IH_HANDLER_PARAM_PASSTHRU); + retval = ih->handler(S7_IH_HANDLER_PARAM_PASSTHRU); } } + +execute_internal_continue: - if (retval == 0) { + if (retval == SUCCESS) { old_execute_internal(execute_data, return_value); } - // if (free_lcname == 1) { - // efree(lcname); - // } return; + execute_internal_bailout: - // if (free_lcname == 1) { - // efree(lcname); - // } - FUNCTION_WARNING() + + if (function_name != NULL) { + FUNCTION_WARNING(ZSTR_VAL(function_name)) + } else { + FUNCTION_WARNING(""); + } suhosin_bailout(); } /* }}} */ @@ -1332,20 +878,20 @@ execute_internal_bailout: /* {{{ int function_lookup(zend_extension *extension) */ -static int function_lookup(zend_extension *extension) -{ - // if (zo_set_oe_ex != NULL) { - // return ZEND_HASH_APPLY_STOP; - // } - - // if (extension->handle != NULL) { - // - // zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(extension->handle, "zend_optimizer_set_oe_ex"); - // - // } - - return 0; -} +// static int function_lookup(zend_extension *extension) +// { +// if (zo_set_oe_ex != NULL) { +// return ZEND_HASH_APPLY_STOP; +// } +// +// if (extension->handle != NULL) { +// +// zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(extension->handle, "zend_optimizer_set_oe_ex"); +// +// } +// +// return 0; +// } /* }}} */ @@ -1353,26 +899,24 @@ static int function_lookup(zend_extension *extension) */ void suhosin_hook_execute() { - internal_function_handler *ih; - old_execute_ex = zend_execute_ex; zend_execute_ex = suhosin_execute_ex; /* old_compile_file = zend_compile_file; zend_compile_file = suhosin_compile_file; */ -#if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED - if (zo_set_oe_ex == NULL) { - zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(NULL, "zend_optimizer_set_oe_ex"); - } - if (zo_set_oe_ex == NULL) { - zend_llist_apply(&zend_extensions, (llist_apply_func_t)function_lookup); - } - - if (zo_set_oe_ex != NULL) { - old_execute_ZO = zo_set_oe_ex(suhosin_execute_ZO); - } -#endif +// #if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED +// if (zo_set_oe_ex == NULL) { +// zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(NULL, "zend_optimizer_set_oe_ex"); +// } +// if (zo_set_oe_ex == NULL) { +// zend_llist_apply(&zend_extensions, (llist_apply_func_t)function_lookup); +// } +// +// if (zo_set_oe_ex != NULL) { +// old_execute_ZO = zo_set_oe_ex(suhosin_execute_ZO); +// } +// #endif old_execute_internal = zend_execute_internal; if (old_execute_internal == NULL) { @@ -1382,9 +926,11 @@ void suhosin_hook_execute() /* register internal function handlers */ zend_hash_init(&ihandler_table, 16, NULL, NULL, 1); - ih = &ihandlers[0]; + suhosin_internal_function_handler *ih = &ihandlers[0]; while (ih->name) { - zend_hash_str_add_ptr(&ihandler_table, ih->name, sizeof(ih->name)-1, ih); + // SDEBUG("adding [%s]/%zu", ih->name, strlen(ih->name)); + // zend_hash_str_add_ptr(&ihandler_table, ZEND_STRL(ih->name), ih); + zend_hash_str_add_ptr(&ihandler_table, ih->name, strlen(ih->name), ih); ih++; } @@ -1403,11 +949,11 @@ void suhosin_hook_execute() */ void suhosin_unhook_execute() { -#if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED - if (zo_set_oe_ex) { - zo_set_oe_ex(old_execute_ZO); - } -#endif +// #if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED +// if (zo_set_oe_ex) { +// zo_set_oe_ex(old_execute_ZO); +// } +// #endif zend_execute_ex = old_execute_ex; diff --git a/execute.h b/execute.h new file mode 100644 index 0000000..03d19d3 --- /dev/null +++ b/execute.h @@ -0,0 +1,21 @@ +#pragma once + +#define S7_IH_HANDLER_PARAMS_REST INTERNAL_FUNCTION_PARAMETERS +#define S7_IH_HANDLER_PARAMS suhosin_internal_function_handler *ih, S7_IH_HANDLER_PARAMS_REST +#define S7_IH_HANDLER_PARAM_PASSTHRU ih, INTERNAL_FUNCTION_PARAM_PASSTHRU + +#define S7_IH_FN(fname) suhosin_ih_ ## fname +#define S7_IH_FUNCTION(fname) int S7_IH_FN(fname)(S7_IH_HANDLER_PARAMS) +#define S7_IH_ENTRY(php_fname, fname, arg1, arg2, arg3) { php_fname, S7_IH_FN(fname), (void*)(arg1), (void*)(arg2), (void*)(arg3) }, +#define S7_IH_ENTRY0(php_fname, fname) S7_IH_ENTRY(php_fname, fname, NULL, NULL, NULL) +#define S7_IH_ENTRY0i(fname) S7_IH_ENTRY0(#fname, fname) + +typedef struct _suhosin_internal_function_handler { + char *name; + int (*handler)(struct _suhosin_internal_function_handler *ih, S7_IH_HANDLER_PARAMS_REST); + void *arg1; + void *arg2; + void *arg3; +} suhosin_internal_function_handler; + +S7_IH_FUNCTION(preg_replace); diff --git a/execute_ih.c b/execute_ih.c new file mode 100644 index 0000000..fa511b9 --- /dev/null +++ b/execute_ih.c @@ -0,0 +1,495 @@ +#include "php.h" +#include "php_suhosin7.h" +#include "execute.h" + +// #ifdef SUHOSIN7_PREG_REPLACE_NULL +// preg_replace \0 protection may be redundant, because PHP already checks for \0 +S7_IH_FUNCTION(preg_replace) +{ + zval *regex, *replace, *subject, *zcount = NULL; + zend_long limit = -1; + // int replace_count; + +#ifndef FAST_ZPP + /* Get function parameters and do error-checking. */ + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) { + return FAILURE; + } +#else + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_ZVAL(regex) + Z_PARAM_ZVAL(replace) + Z_PARAM_ZVAL(subject) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(limit) + Z_PARAM_ZVAL_EX(zcount, 0, 1) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); +#endif + + if (Z_TYPE_P(regex) != IS_ARRAY) { + convert_to_string_ex(regex); + // regex is string + + if (strlen(Z_STRVAL_P(regex)) != Z_STRLEN_P(regex)) { + suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); + if (!SUHOSIN7_G(simulation)) { + RETVAL_NULL(); + return FAILURE; + } + } + } else { + // regex is array + + /* For each entry in the regex array, get the entry */ + zval *regex_entry; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(regex), regex_entry) { + /* Make sure we're dealing with strings. */ + zend_string *regex_str = zval_get_string(regex_entry); + + if (strlen(ZSTR_VAL(regex_str)) != ZSTR_LEN(regex_str)) { + suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); + if (!SUHOSIN7_G(simulation)) { + RETVAL_NULL(); + zend_string_release(regex_str); + return FAILURE; + } + } + + zend_string_release(regex_str); + } ZEND_HASH_FOREACH_END(); + + } + + return SUCCESS; +} + +// #endif /* SUHOSIN7_PREG_REPLACE_NULL */ + + +// int ih_symlink(IH_HANDLER_PARAMS) +// { +// if (SUHOSIN7_G(executor_allow_symlink)) { +// return (0); +// } +// +// if (PG(open_basedir) && PG(open_basedir)[0]) { +// suhosin_log(S_EXECUTOR, "symlink called during open_basedir"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// return (0); +// } + +// int ih_mail(IH_HANDLER_PARAMS) +// { +// char *to=NULL, *message=NULL, *headers=NULL; +// char *subject=NULL, *extra_cmd=NULL; +// char *tmp; +// int to_len, message_len, headers_len; +// int subject_len, extra_cmd_len; +// +// if (SUHOSIN7_G(mailprotect) == 0) { +// return (0); +// } +// +// if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|ss", +// &to, &to_len, +// &subject, &subject_len, +// &message, &message_len, +// &headers, &headers_len, +// &extra_cmd, &extra_cmd_len +// ) == FAILURE) { +// RETVAL_FALSE; +// return (1); +// } +// +// if (headers_len > 0 && headers && +// (strstr(headers, "\n\n") || strstr(headers, "\n\r\n") /* double newline */ +// || *headers == '\n' || (headers[0] == '\r' && headers[1] == '\n') /* starts with newline */ +// )) { +// suhosin_log(S_MAIL, "mail() - double newline in headers, possible injection, mail dropped"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// /* check for spam attempts with buggy webforms */ +// if (to_len > 0 && to) { +// do { +// if ((tmp = strchr(to, '\n')) == NULL) +// tmp = strchr(to, '\r'); +// if (tmp == NULL) break; +// to = tmp + 1; +// if (!isspace(*to)) break; +// } while (1); +// if (tmp != NULL) { +// suhosin_log(S_MAIL, "mail() - newline in To header, possible injection, mail dropped"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// } +// +// if (subject_len > 0 && subject) { +// do { +// if ((tmp = strchr(subject, '\n')) == NULL) +// tmp = strchr(subject, '\r'); +// if (tmp == NULL) break; +// subject = tmp + 1; +// if (!isspace(*subject)) break; +// } while (1); +// if (tmp != NULL) { +// suhosin_log(S_MAIL, "mail() - newline in Subject header, possible injection, mail dropped"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// } +// +// if (SUHOSIN7_G(mailprotect) > 1) { +// /* search for to, cc or bcc headers */ +// if (headers_len > 0 && headers != NULL) { +// if (strncasecmp(headers, "to:", sizeof("to:") - 1) == 0 || suhosin_strcasestr(headers, "\nto:")) { +// suhosin_log(S_MAIL, "mail() - To: headers aren't allowed in the headers parameter."); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// if (strncasecmp(headers, "cc:", sizeof("cc:") - 1) == 0 || suhosin_strcasestr(headers, "\ncc:")) { +// suhosin_log(S_MAIL, "mail() - CC: headers aren't allowed in the headers parameter."); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// if (strncasecmp(headers, "bcc:", sizeof("bcc:") - 1) == 0 || suhosin_strcasestr(headers, "\nbcc:")) { +// suhosin_log(S_MAIL, "mail() - BCC: headers aren't allowed in the headers parameter."); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// } +// } +// +// return (0); +// } + +// #define SQLSTATE_SQL 0 +// #define SQLSTATE_IDENTIFIER 1 +// #define SQLSTATE_STRING 2 +// #define SQLSTATE_COMMENT 3 +// #define SQLSTATE_MLCOMMENT 4 +// +// int ih_querycheck(IH_HANDLER_PARAMS) +// { +// void **p = zend_vm_stack_top() - 1; +// unsigned long arg_count; +// zval **arg; +// char *query, *s, *e; +// zval *backup; +// int len; +// char quote; +// int state = SQLSTATE_SQL; +// int cnt_union = 0, cnt_select = 0, cnt_comment = 0, cnt_opencomment = 0; +// int mysql_extension = 0; +// +// +// SDEBUG("function: %s", ih->name); +// arg_count = (unsigned long) *p; +// +// if (ht < (long) ih->arg1) { +// return (0); +// } +// +// if ((long) ih->arg2) { +// mysql_extension = 1; +// } +// +// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ +// +// backup = *arg; +// if (Z_TYPE_P(backup) != IS_STRING) { +// return (0); +// } +// len = Z_STRLEN_P(backup); +// query = Z_STRVAL_P(backup); +// SDEBUG("SQL |%s|", query); +// +// s = query; +// e = s+len; +// +// while (s < e) { +// switch (state) +// { +// case SQLSTATE_SQL: +// switch (s[0]) +// { +// case '`': +// state = SQLSTATE_IDENTIFIER; +// quote = '`'; +// break; +// case '\'': +// case '"': +// state = SQLSTATE_STRING; +// quote = *s; +// break; +// case '/': +// if (s[1]=='*') { +// if (mysql_extension == 1 && s[2] == '!') { +// s += 2; +// break; +// } +// s++; +// state = SQLSTATE_MLCOMMENT; +// cnt_comment++; +// } +// break; +// case '-': +// if (s[1]=='-') { +// s++; +// state = SQLSTATE_COMMENT; +// cnt_comment++; +// } +// break; +// case '#': +// state = SQLSTATE_COMMENT; +// cnt_comment++; +// break; +// case 'u': +// case 'U': +// if (strncasecmp("union", s, 5)==0) { +// s += 4; +// cnt_union++; +// } +// break; +// case 's': +// case 'S': +// if (strncasecmp("select", s, 6)==0) { +// s += 5; +// cnt_select++; +// } +// break; +// } +// break; +// case SQLSTATE_STRING: +// case SQLSTATE_IDENTIFIER: +// if (s[0] == quote) { +// if (s[1] == quote) { +// s++; +// } else { +// state = SQLSTATE_SQL; +// } +// } +// if (s[0] == '\\') { +// s++; +// } +// break; +// case SQLSTATE_COMMENT: +// while (s[0] && s[0] != '\n') { +// s++; +// } +// state = SQLSTATE_SQL; +// break; +// case SQLSTATE_MLCOMMENT: +// while (s[0] && (s[0] != '*' || s[1] != '/')) { +// s++; +// } +// if (s[0]) { +// state = SQLSTATE_SQL; +// } +// break; +// } +// s++; +// } +// if (state == SQLSTATE_MLCOMMENT) { +// cnt_opencomment = 1; +// } +// +// if (cnt_opencomment && SUHOSIN7_G(sql_opencomment)>0) { +// suhosin_log(S_SQL, "Open comment in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_opencomment)>1) { +// suhosin_bailout(); +// } +// } +// +// if (cnt_comment && SUHOSIN7_G(sql_comment)>0) { +// suhosin_log(S_SQL, "Comment in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_comment)>1) { +// suhosin_bailout(); +// } +// } +// +// if (cnt_union && SUHOSIN7_G(sql_union)>0) { +// suhosin_log(S_SQL, "UNION in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_union)>1) { +// suhosin_bailout(); +// } +// } +// +// if (cnt_select>1 && SUHOSIN7_G(sql_mselect)>0) { +// suhosin_log(S_SQL, "Multiple SELECT in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_mselect)>1) { +// suhosin_bailout(); +// } +// } +// +// return (0); +// } +// +// +// int ih_fixusername(IH_HANDLER_PARAMS) +// { +// void **p = zend_vm_stack_top() - 1; +// unsigned long arg_count; +// zval **arg; +// char *prefix, *postfix, *user, *user_match, *cp; +// zval *backup, *my_user; +// int prefix_len, postfix_len, len; +// +// SDEBUG("function (fixusername): %s", ih->name); +// +// prefix = SUHOSIN7_G(sql_user_prefix); +// postfix = SUHOSIN7_G(sql_user_postfix); +// user_match = SUHOSIN7_G(sql_user_match); +// +// arg_count = (unsigned long) *p; +// +// if (ht < (long) ih->arg1) { +// return (0); +// } +// +// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ +// +// backup = *arg; +// if (Z_TYPE_P(backup) != IS_STRING) { +// user = ""; +// len = 0; +// } else { +// len = Z_STRLEN_P(backup); +// user = Z_STRVAL_P(backup); +// } +// +// cp = user; +// while (cp < user+len) { +// if (*cp < 32) { +// suhosin_log(S_SQL, "SQL username contains invalid characters"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// break; +// } +// cp++; +// } +// +// if ((prefix != NULL && prefix[0]) || (postfix != NULL && postfix[0])) { +// if (prefix == NULL) { +// prefix = ""; +// } +// if (postfix == NULL) { +// postfix = ""; +// } +// prefix_len = strlen(prefix); +// postfix_len = strlen(postfix); +// +// MAKE_STD_ZVAL(my_user); +// my_user->type = IS_STRING; +// my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); +// +// /* XXX: memory_leak? */ +// *arg = my_user; +// +// len = Z_STRLEN_P(my_user); +// user = Z_STRVAL_P(my_user); +// } +// +// if (user_match && user_match[0]) { +// #ifdef HAVE_FNMATCH +// if (fnmatch(user_match, user, 0) != 0) { +// suhosin_log(S_SQL, "SQL username ('%s') does not match suhosin.sql.user_match ('%s')", user, user_match); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// #else +// #warning no support for fnmatch() - setting suhosin.sql.user_match will always fail. +// suhosin_log(S_SQL, "suhosin.sql.user_match specified, but system does not support fnmatch()"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// #endif +// } +// +// SDEBUG("function: %s - user: %s", ih->name, user); +// +// return (0); +// } +// +// +// static int ih_function_exists(IH_HANDLER_PARAMS) +// { +// zval **function_name; +// zend_function *func; +// char *lcname; +// zend_bool retval; +// int func_name_len; +// +// if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) { +// ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(1); +// } +// convert_to_string_ex(function_name); +// func_name_len = Z_STRLEN_PP(function_name); +// lcname = estrndup(Z_STRVAL_PP(function_name), func_name_len); +// zend_str_tolower(lcname, func_name_len); +// +// retval = (zend_hash_find(EG(function_table), lcname, func_name_len+1, (void **)&func) == SUCCESS); +// +// /* +// * A bit of a hack, but not a bad one: we see if the handler of the function +// * is actually one that displays "function is disabled" message. +// */ +// if (retval && func->type == ZEND_INTERNAL_FUNCTION && +// func->internal_function.handler == zif_display_disabled_function) { +// retval = 0; +// } +// +// /* Now check if function is forbidden by Suhosin */ +// if (SUHOSIN7_G(in_code_type) == SUHOSIN_EVAL) { +// if (SUHOSIN7_G(eval_whitelist) != NULL) { +// if (!zend_hash_exists(SUHOSIN7_G(eval_whitelist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } else if (SUHOSIN7_G(eval_blacklist) != NULL) { +// if (zend_hash_exists(SUHOSIN7_G(eval_blacklist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } +// } +// +// if (SUHOSIN7_G(func_whitelist) != NULL) { +// if (!zend_hash_exists(SUHOSIN7_G(func_whitelist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } else if (SUHOSIN7_G(func_blacklist) != NULL) { +// if (zend_hash_exists(SUHOSIN7_G(func_blacklist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } +// +// efree(lcname); +// +// RETVAL_BOOL(retval); +// return (1); +// } diff --git a/execute_rnd.c b/execute_rnd.c new file mode 100644 index 0000000..9647b63 --- /dev/null +++ b/execute_rnd.c @@ -0,0 +1,385 @@ +/* MT RAND FUNCTIONS */ + +/* + The following php_mt_...() functions are based on a C++ class MTRand by + Richard J. Wagner. For more information see the web page at + http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html + + Mersenne Twister random number generator -- a C++ class MTRand + Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus + Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com + + The Mersenne Twister is an algorithm for generating random numbers. It + was designed with consideration of the flaws in various other generators. + The period, 2^19937-1, and the order of equidistribution, 623 dimensions, + are far greater. The generator is also fast; it avoids multiplication and + division, and it benefits from caches and pipelines. For more information + see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html + + Reference + M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally + Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on + Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + Copyright (C) 2000 - 2003, Richard J. Wagner + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + The original code included the following notice: + + When you use this, send an email to: matumoto@math.keio.ac.jp + with an appropriate reference to your work. + + It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu + when you write. +*/ + +#define N 624 /* length of state vector */ +#define M (397) /* a period parameter */ +#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */ +#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */ +#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ +#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ + +#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(v))) & 0x9908b0dfU)) + +/* {{{ php_mt_initialize + */ +static inline void suhosin_mt_initialize(php_uint32 seed, php_uint32 *state) +{ + /* Initialize generator state with seed + See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. + In previous versions, most significant bits (MSBs) of the seed affect + only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */ + + register php_uint32 *s = state; + register php_uint32 *r = state; + register int i = 1; + + *s++ = seed & 0xffffffffU; + for( ; i < N; ++i ) { + *s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU; + r++; + } +} +/* }}} */ + +static inline void suhosin_mt_init_by_array(php_uint32 *key, int keylen, php_uint32 *state) +{ + int i, j, k; + suhosin_mt_initialize(19650218U, state); + i = 1; j = 0; + k = (N > keylen ? N : keylen); + for (; k; k--) { + state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525U)) + key[j] + j; + i++; j = (j+1) % keylen; + if (i >= N) { state[0] = state[N-1]; i=1; } + } + for (k=N-1; k; k--) { + state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941U)) - i; + i++; + if (i >= N) { state[0] = state[N-1]; i=1; } + } + state[0] = 0x80000000U; +} +/* }}} */ + + +/* {{{ suhosin_mt_reload + */ +static inline void suhosin_mt_reload(php_uint32 *state, php_uint32 **next, int *left) +{ + /* Generate N new values in state + Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) */ + + register php_uint32 *p = state; + register int i; + + for (i = N - M; i--; ++p) + *p = twist(p[M], p[0], p[1]); + for (i = M; --i; ++p) + *p = twist(p[M-N], p[0], p[1]); + *p = twist(p[M-N], p[0], state[0]); + *left = N; + *next = state; +} +/* }}} */ + +/* {{{ suhosin_mt_srand + */ +static void suhosin_mt_srand(php_uint32 seed) +{ + /* Seed the generator with a simple uint32 */ + suhosin_mt_initialize(seed, SUHOSIN7_G(mt_state)); + suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left)); + + /* Seed only once */ + SUHOSIN7_G(mt_is_seeded) = 1; +} +/* }}} */ + +/* {{{ suhosin_mt_rand + */ +static php_uint32 suhosin_mt_rand() +{ + /* Pull a 32-bit integer from the generator state + Every other access function simply transforms the numbers extracted here */ + + register php_uint32 s1; + + if (SUHOSIN7_G(mt_left) == 0) { + suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left)); + } + --SUHOSIN7_G(mt_left); + + s1 = *SUHOSIN7_G(mt_next)++; + s1 ^= (s1 >> 11); + s1 ^= (s1 << 7) & 0x9d2c5680U; + s1 ^= (s1 << 15) & 0xefc60000U; + return ( s1 ^ (s1 >> 18) ); +} +/* }}} */ + +/* {{{ SUHOSIN7_Gen_entropy + */ +static void SUHOSIN7_Gen_entropy(php_uint32 *entropybuf) +{ + php_uint32 seedbuf[20]; + /* On a modern OS code, stack and heap base are randomized */ + unsigned long code_value = (unsigned long)SUHOSIN7_Gen_entropy; + unsigned long stack_value = (unsigned long)&code_value; + unsigned long heap_value = (unsigned long)SUHOSIN7_G(r_state); + suhosin_SHA256_CTX context; + int fd; + + code_value ^= code_value >> 32; + stack_value ^= stack_value >> 32; + heap_value ^= heap_value >> 32; + + seedbuf[0] = code_value; + seedbuf[1] = stack_value; + seedbuf[2] = heap_value; + seedbuf[3] = time(0); +#ifdef PHP_WIN32 + seedbuf[4] = GetCurrentProcessId(); +#else + seedbuf[4] = getpid(); +#endif + seedbuf[5] = (php_uint32) 0x7fffffff * php_combined_lcg(); + +#ifndef PHP_WIN32 + fd = VCWD_OPEN("/dev/urandom", O_RDONLY); + if (fd >= 0) { + /* ignore error case - if urandom doesn't give us any/enough random bytes */ + read(fd, &seedbuf[6], 8 * sizeof(php_uint32)); + close(fd); + } +#else + /* we have to live with the possibility that this call fails */ + php_win32_get_random_bytes((unsigned char*)&seedbuf[6], 8 * sizeof(php_uint32)); +#endif + + suhosin_SHA256Init(&context); + /* to our friends from Debian: yes this will add unitialized stack values to the entropy DO NOT REMOVE */ + suhosin_SHA256Update(&context, (void *) seedbuf, sizeof(seedbuf)); + if (SUHOSIN7_G(seedingkey) != NULL && *SUHOSIN7_G(seedingkey) != 0) { + suhosin_SHA256Update(&context, (unsigned char*)SUHOSIN7_G(seedingkey), strlen(SUHOSIN7_G(seedingkey))); + } + suhosin_SHA256Final((void *)entropybuf, &context); +} +/* }}} */ + + +/* {{{ suhosin_srand_auto + */ +static void suhosin_srand_auto() +{ + php_uint32 seed[8]; + SUHOSIN7_Gen_entropy(&seed[0]); + + suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(r_state)); + suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left)); + + /* Seed only once */ + SUHOSIN7_G(r_is_seeded) = 1; +} +/* }}} */ + +/* {{{ suhosin_mt_srand_auto + */ +static void suhosin_mt_srand_auto() +{ + php_uint32 seed[8]; + SUHOSIN7_Gen_entropy(&seed[0]); + + suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(mt_state)); + suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left)); + + /* Seed only once */ + SUHOSIN7_G(mt_is_seeded) = 1; +} +/* }}} */ + + +/* {{{ suhosin_srand + */ +static void suhosin_srand(php_uint32 seed) +{ + /* Seed the generator with a simple uint32 */ + suhosin_mt_initialize(seed+0x12345, SUHOSIN7_G(r_state)); + suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left)); + + /* Seed only once */ + SUHOSIN7_G(r_is_seeded) = 1; +} +/* }}} */ + +/* {{{ suhosin_mt_rand + */ +static php_uint32 suhosin_rand() +{ + /* Pull a 32-bit integer from the generator state + Every other access function simply transforms the numbers extracted here */ + + register php_uint32 s1; + + if (SUHOSIN7_G(r_left) == 0) { + suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left)); + } + --SUHOSIN7_G(r_left); + + s1 = *SUHOSIN7_G(r_next)++; + s1 ^= (s1 >> 11); + s1 ^= (s1 << 7) & 0x9d2c5680U; + s1 ^= (s1 << 15) & 0xefc60000U; + return ( s1 ^ (s1 >> 18) ); +} +/* }}} */ + +static int ih_srand(IH_HANDLER_PARAMS) +{ + int argc = ZEND_NUM_ARGS(); + long seed; + + if (SUHOSIN7_G(srand_ignore)) { + SUHOSIN7_G(r_is_seeded) = 0; + return 1; + } + + if (zend_parse_parameters(argc, "|l", &seed) == FAILURE) { + return 1; + } + + if (argc) { + suhosin_srand(seed); + } else { + suhosin_srand_auto(); + } + return (1); +} + +static int ih_mt_srand(IH_HANDLER_PARAMS) +{ + int argc = ZEND_NUM_ARGS(); + long seed; + + if (SUHOSIN7_G(mt_srand_ignore)) { + SUHOSIN7_G(mt_is_seeded) = 0; + return 1; + } + + if (zend_parse_parameters(argc, "|l", &seed) == FAILURE) { + return 1; + } + + if (argc) { + suhosin_mt_srand(seed); + } else { + suhosin_mt_srand_auto(); + } + return 1; +} + +static int ih_mt_rand(IH_HANDLER_PARAMS) +{ + int argc = ZEND_NUM_ARGS(); + long min; + long max; + long number; + + if (argc != 0 && zend_parse_parameters(argc, "ll", &min, &max) == FAILURE) { + return (1); + } + + if (!SUHOSIN7_G(mt_is_seeded)) { + suhosin_mt_srand_auto(); + } + + number = (long) (suhosin_mt_rand() >> 1); + if (argc == 2) { + RAND_RANGE(number, min, max, PHP_MT_RAND_MAX); + } + + RETVAL_LONG(number); + return (1); +} + +static int ih_rand(IH_HANDLER_PARAMS) +{ + int argc = ZEND_NUM_ARGS(); + long min; + long max; + long number; + + if (argc != 0 && zend_parse_parameters(argc, "ll", &min, &max) == FAILURE) { + return (1); + } + + if (!SUHOSIN7_G(r_is_seeded)) { + suhosin_srand_auto(); + } + + number = (long) (suhosin_rand() >> 1); + if (argc == 2) { + RAND_RANGE(number, min, max, PHP_MT_RAND_MAX); + } + + RETVAL_LONG(number); + return (1); +} + +static int ih_getrandmax(IH_HANDLER_PARAMS) +{ + if (zend_parse_parameters_none() == FAILURE) { + return(0); + } + RETVAL_LONG(PHP_MT_RAND_MAX); + return (1); +} diff --git a/execute_rnd.inc.c b/execute_rnd.inc.c deleted file mode 100644 index 9647b63..0000000 --- a/execute_rnd.inc.c +++ /dev/null @@ -1,385 +0,0 @@ -/* MT RAND FUNCTIONS */ - -/* - The following php_mt_...() functions are based on a C++ class MTRand by - Richard J. Wagner. For more information see the web page at - http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html - - Mersenne Twister random number generator -- a C++ class MTRand - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus - Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com - - The Mersenne Twister is an algorithm for generating random numbers. It - was designed with consideration of the flaws in various other generators. - The period, 2^19937-1, and the order of equidistribution, 623 dimensions, - are far greater. The generator is also fast; it avoids multiplication and - division, and it benefits from caches and pipelines. For more information - see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html - - Reference - M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally - Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on - Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - Copyright (C) 2000 - 2003, Richard J. Wagner - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - The original code included the following notice: - - When you use this, send an email to: matumoto@math.keio.ac.jp - with an appropriate reference to your work. - - It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu - when you write. -*/ - -#define N 624 /* length of state vector */ -#define M (397) /* a period parameter */ -#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */ -#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */ -#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ -#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ - -#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(v))) & 0x9908b0dfU)) - -/* {{{ php_mt_initialize - */ -static inline void suhosin_mt_initialize(php_uint32 seed, php_uint32 *state) -{ - /* Initialize generator state with seed - See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. - In previous versions, most significant bits (MSBs) of the seed affect - only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */ - - register php_uint32 *s = state; - register php_uint32 *r = state; - register int i = 1; - - *s++ = seed & 0xffffffffU; - for( ; i < N; ++i ) { - *s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU; - r++; - } -} -/* }}} */ - -static inline void suhosin_mt_init_by_array(php_uint32 *key, int keylen, php_uint32 *state) -{ - int i, j, k; - suhosin_mt_initialize(19650218U, state); - i = 1; j = 0; - k = (N > keylen ? N : keylen); - for (; k; k--) { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525U)) + key[j] + j; - i++; j = (j+1) % keylen; - if (i >= N) { state[0] = state[N-1]; i=1; } - } - for (k=N-1; k; k--) { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941U)) - i; - i++; - if (i >= N) { state[0] = state[N-1]; i=1; } - } - state[0] = 0x80000000U; -} -/* }}} */ - - -/* {{{ suhosin_mt_reload - */ -static inline void suhosin_mt_reload(php_uint32 *state, php_uint32 **next, int *left) -{ - /* Generate N new values in state - Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) */ - - register php_uint32 *p = state; - register int i; - - for (i = N - M; i--; ++p) - *p = twist(p[M], p[0], p[1]); - for (i = M; --i; ++p) - *p = twist(p[M-N], p[0], p[1]); - *p = twist(p[M-N], p[0], state[0]); - *left = N; - *next = state; -} -/* }}} */ - -/* {{{ suhosin_mt_srand - */ -static void suhosin_mt_srand(php_uint32 seed) -{ - /* Seed the generator with a simple uint32 */ - suhosin_mt_initialize(seed, SUHOSIN7_G(mt_state)); - suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left)); - - /* Seed only once */ - SUHOSIN7_G(mt_is_seeded) = 1; -} -/* }}} */ - -/* {{{ suhosin_mt_rand - */ -static php_uint32 suhosin_mt_rand() -{ - /* Pull a 32-bit integer from the generator state - Every other access function simply transforms the numbers extracted here */ - - register php_uint32 s1; - - if (SUHOSIN7_G(mt_left) == 0) { - suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left)); - } - --SUHOSIN7_G(mt_left); - - s1 = *SUHOSIN7_G(mt_next)++; - s1 ^= (s1 >> 11); - s1 ^= (s1 << 7) & 0x9d2c5680U; - s1 ^= (s1 << 15) & 0xefc60000U; - return ( s1 ^ (s1 >> 18) ); -} -/* }}} */ - -/* {{{ SUHOSIN7_Gen_entropy - */ -static void SUHOSIN7_Gen_entropy(php_uint32 *entropybuf) -{ - php_uint32 seedbuf[20]; - /* On a modern OS code, stack and heap base are randomized */ - unsigned long code_value = (unsigned long)SUHOSIN7_Gen_entropy; - unsigned long stack_value = (unsigned long)&code_value; - unsigned long heap_value = (unsigned long)SUHOSIN7_G(r_state); - suhosin_SHA256_CTX context; - int fd; - - code_value ^= code_value >> 32; - stack_value ^= stack_value >> 32; - heap_value ^= heap_value >> 32; - - seedbuf[0] = code_value; - seedbuf[1] = stack_value; - seedbuf[2] = heap_value; - seedbuf[3] = time(0); -#ifdef PHP_WIN32 - seedbuf[4] = GetCurrentProcessId(); -#else - seedbuf[4] = getpid(); -#endif - seedbuf[5] = (php_uint32) 0x7fffffff * php_combined_lcg(); - -#ifndef PHP_WIN32 - fd = VCWD_OPEN("/dev/urandom", O_RDONLY); - if (fd >= 0) { - /* ignore error case - if urandom doesn't give us any/enough random bytes */ - read(fd, &seedbuf[6], 8 * sizeof(php_uint32)); - close(fd); - } -#else - /* we have to live with the possibility that this call fails */ - php_win32_get_random_bytes((unsigned char*)&seedbuf[6], 8 * sizeof(php_uint32)); -#endif - - suhosin_SHA256Init(&context); - /* to our friends from Debian: yes this will add unitialized stack values to the entropy DO NOT REMOVE */ - suhosin_SHA256Update(&context, (void *) seedbuf, sizeof(seedbuf)); - if (SUHOSIN7_G(seedingkey) != NULL && *SUHOSIN7_G(seedingkey) != 0) { - suhosin_SHA256Update(&context, (unsigned char*)SUHOSIN7_G(seedingkey), strlen(SUHOSIN7_G(seedingkey))); - } - suhosin_SHA256Final((void *)entropybuf, &context); -} -/* }}} */ - - -/* {{{ suhosin_srand_auto - */ -static void suhosin_srand_auto() -{ - php_uint32 seed[8]; - SUHOSIN7_Gen_entropy(&seed[0]); - - suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(r_state)); - suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left)); - - /* Seed only once */ - SUHOSIN7_G(r_is_seeded) = 1; -} -/* }}} */ - -/* {{{ suhosin_mt_srand_auto - */ -static void suhosin_mt_srand_auto() -{ - php_uint32 seed[8]; - SUHOSIN7_Gen_entropy(&seed[0]); - - suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(mt_state)); - suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left)); - - /* Seed only once */ - SUHOSIN7_G(mt_is_seeded) = 1; -} -/* }}} */ - - -/* {{{ suhosin_srand - */ -static void suhosin_srand(php_uint32 seed) -{ - /* Seed the generator with a simple uint32 */ - suhosin_mt_initialize(seed+0x12345, SUHOSIN7_G(r_state)); - suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left)); - - /* Seed only once */ - SUHOSIN7_G(r_is_seeded) = 1; -} -/* }}} */ - -/* {{{ suhosin_mt_rand - */ -static php_uint32 suhosin_rand() -{ - /* Pull a 32-bit integer from the generator state - Every other access function simply transforms the numbers extracted here */ - - register php_uint32 s1; - - if (SUHOSIN7_G(r_left) == 0) { - suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left)); - } - --SUHOSIN7_G(r_left); - - s1 = *SUHOSIN7_G(r_next)++; - s1 ^= (s1 >> 11); - s1 ^= (s1 << 7) & 0x9d2c5680U; - s1 ^= (s1 << 15) & 0xefc60000U; - return ( s1 ^ (s1 >> 18) ); -} -/* }}} */ - -static int ih_srand(IH_HANDLER_PARAMS) -{ - int argc = ZEND_NUM_ARGS(); - long seed; - - if (SUHOSIN7_G(srand_ignore)) { - SUHOSIN7_G(r_is_seeded) = 0; - return 1; - } - - if (zend_parse_parameters(argc, "|l", &seed) == FAILURE) { - return 1; - } - - if (argc) { - suhosin_srand(seed); - } else { - suhosin_srand_auto(); - } - return (1); -} - -static int ih_mt_srand(IH_HANDLER_PARAMS) -{ - int argc = ZEND_NUM_ARGS(); - long seed; - - if (SUHOSIN7_G(mt_srand_ignore)) { - SUHOSIN7_G(mt_is_seeded) = 0; - return 1; - } - - if (zend_parse_parameters(argc, "|l", &seed) == FAILURE) { - return 1; - } - - if (argc) { - suhosin_mt_srand(seed); - } else { - suhosin_mt_srand_auto(); - } - return 1; -} - -static int ih_mt_rand(IH_HANDLER_PARAMS) -{ - int argc = ZEND_NUM_ARGS(); - long min; - long max; - long number; - - if (argc != 0 && zend_parse_parameters(argc, "ll", &min, &max) == FAILURE) { - return (1); - } - - if (!SUHOSIN7_G(mt_is_seeded)) { - suhosin_mt_srand_auto(); - } - - number = (long) (suhosin_mt_rand() >> 1); - if (argc == 2) { - RAND_RANGE(number, min, max, PHP_MT_RAND_MAX); - } - - RETVAL_LONG(number); - return (1); -} - -static int ih_rand(IH_HANDLER_PARAMS) -{ - int argc = ZEND_NUM_ARGS(); - long min; - long max; - long number; - - if (argc != 0 && zend_parse_parameters(argc, "ll", &min, &max) == FAILURE) { - return (1); - } - - if (!SUHOSIN7_G(r_is_seeded)) { - suhosin_srand_auto(); - } - - number = (long) (suhosin_rand() >> 1); - if (argc == 2) { - RAND_RANGE(number, min, max, PHP_MT_RAND_MAX); - } - - RETVAL_LONG(number); - return (1); -} - -static int ih_getrandmax(IH_HANDLER_PARAMS) -{ - if (zend_parse_parameters_none() == FAILURE) { - return(0); - } - RETVAL_LONG(PHP_MT_RAND_MAX); - return (1); -} diff --git a/header.c b/header.c index 65b2c26..a916746 100644 --- a/header.c +++ b/header.c @@ -75,7 +75,7 @@ static int suhosin_header_handler(sapi_header_struct *sapi_header, sapi_header_o int nlen, vlen, len, tlen; char cryptkey[33]; - suhosin_generate_key(SUHOSIN7_G(cookie_cryptkey), SUHOSIN7_G(cookie_cryptua), SUHOSIN7_G(cookie_cryptdocroot), SUHOSIN7_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC); + suhosin_generate_key(SUHOSIN7_G(cookie_cryptkey), SUHOSIN7_G(cookie_cryptua), SUHOSIN7_G(cookie_cryptdocroot), SUHOSIN7_G(cookie_cryptraddr), (char *)cryptkey); start = estrndup(sapi_header->header, sapi_header->header_len); rend = end = start + sapi_header->header_len; @@ -119,7 +119,7 @@ static int suhosin_header_handler(sapi_header_struct *sapi_header, sapi_header_o suhosin_skip_header_handling: /* If existing call the sapi header handler */ if (orig_header_handler) { - retval = orig_header_handler(sapi_header, op, sapi_headers TSRMLS_CC); + retval = orig_header_handler(sapi_header, op, sapi_headers); } return retval; diff --git a/log.c b/log.c index 5b14c61..67e37b4 100644 --- a/log.c +++ b/log.c @@ -158,22 +158,22 @@ SUHOSIN7_API void suhosin_log(int loglevel, char *fmt, ...) } if (zend_is_executing()) { - zend_execute_data *exdata = EG(current_execute_data); - if (exdata) { - if (getcaller && exdata->prev_execute_data && exdata->prev_execute_data->opline && exdata->prev_execute_data->func) { - lineno = exdata->prev_execute_data->opline->lineno; - fname = (char *)ZSTR_VAL(exdata->prev_execute_data->func->op_array.filename); - } else if (exdata->opline && exdata->func) { - lineno = exdata->opline->lineno; - fname = (char *)ZSTR_VAL(exdata->func->op_array.filename); - } else { - lineno = 0; - fname = "[unknown filename]"; - } - } else { + // zend_execute_data *exdata = EG(current_execute_data); + // if (exdata) { + // if (getcaller && exdata->prev_execute_data && exdata->prev_execute_data->opline && exdata->prev_execute_data->func) { + // lineno = exdata->prev_execute_data->opline->lineno; + // fname = (char *)ZSTR_VAL(exdata->prev_execute_data->func->op_array.filename); + // } else if (exdata->opline && exdata->func) { + // lineno = exdata->opline->lineno; + // fname = (char *)ZSTR_VAL(exdata->func->op_array.filename); + // } else { + // lineno = 0; + // fname = "[unknown filename]"; + // } + // } else { lineno = zend_get_executed_lineno(); fname = (char *)zend_get_executed_filename(); - } + // } ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno); } else { fname = suhosin_getenv("SCRIPT_FILENAME", 15); diff --git a/php_suhosin7.h b/php_suhosin7.h index eaf2f87..2b5f48e 100644 --- a/php_suhosin7.h +++ b/php_suhosin7.h @@ -68,7 +68,7 @@ extern zend_module_entry suhosin7_module_entry; // PHP_RSHUTDOWN_FUNCTION(suhosin); // PHP_MINFO_FUNCTION(suhosin); -#include "ext/standard/basic_functions.h" +// #include "ext/standard/basic_functions.h" static inline int suhosin_is_protected_varname(char *var, int var_len) { diff --git a/suhosin7.c b/suhosin7.c index 3b84767..5f36aa4 100644 --- a/suhosin7.c +++ b/suhosin7.c @@ -301,7 +301,7 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("suhosin.executor.func.whitelist", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateSuhosin_func_whitelist) PHP_INI_ENTRY("suhosin.executor.func.blacklist", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateSuhosin_func_blacklist) // STD_S7_INI_BOOLEAN("suhosin.executor.disable_eval", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateExecBool, executor_disable_eval) - // STD_S7_INI_BOOLEAN("suhosin.executor.disable_emodifier", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateExecBool, executor_disable_emod) + STD_S7_INI_BOOLEAN("suhosin.executor.disable_emodifier", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateExecBool, executor_disable_emod) // // STD_S7_INI_BOOLEAN("suhosin.executor.allow_symlink", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateExecBool, executor_allow_symlink) STD_S7_INI_ENTRY("suhosin.executor.max_depth", "750", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateExecLong, max_execution_depth) -- cgit v1.3