From 70310b8f359e1276e3fa6ed326a8f91d9b02f0fc Mon Sep 17 00:00:00 2001 From: Stefan Esser Date: Wed, 11 Jan 2012 19:57:40 +0100 Subject: Fix git repository. Github had the wrong git repository commited. The last revisions were missing. From here we can continue developing. --- session.c | 1334 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 667 insertions(+), 667 deletions(-) (limited to 'session.c') diff --git a/session.c b/session.c index 2e5b092..0fe9d3b 100644 --- a/session.c +++ b/session.c @@ -1,19 +1,19 @@ /* +----------------------------------------------------------------------+ - | Suhosin Version 1 | + | Suhosin Version 1 | +----------------------------------------------------------------------+ - | Copyright (c) 2006-2007 The Hardened-PHP Project | - | Copyright (c) 2007-2010 SektionEins GmbH | + | Copyright (c) 2006-2007 The Hardened-PHP Project | + | Copyright (c) 2007-2010 SektionEins GmbH | +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Stefan Esser | + | Author: Stefan Esser | +----------------------------------------------------------------------+ */ /* @@ -49,188 +49,188 @@ #define PS_CREATE_SID_ARGS void **mod_data, int *newlen TSRMLS_DC typedef struct ps_module_struct { - const char *s_name; - int (*s_open)(PS_OPEN_ARGS); - int (*s_close)(PS_CLOSE_ARGS); - int (*s_read)(PS_READ_ARGS); - int (*s_write)(PS_WRITE_ARGS); - int (*s_destroy)(PS_DESTROY_ARGS); - int (*s_gc)(PS_GC_ARGS); - char *(*s_create_sid)(PS_CREATE_SID_ARGS); + const char *s_name; + int (*s_open)(PS_OPEN_ARGS); + int (*s_close)(PS_CLOSE_ARGS); + int (*s_read)(PS_READ_ARGS); + int (*s_write)(PS_WRITE_ARGS); + int (*s_destroy)(PS_DESTROY_ARGS); + int (*s_gc)(PS_GC_ARGS); + char *(*s_create_sid)(PS_CREATE_SID_ARGS); } ps_module; typedef enum { - php_session_disabled, - php_session_none, - php_session_active + php_session_disabled, + php_session_none, + php_session_active } php_session_status; #define PS_SERIALIZER_ENCODE_ARGS char **newstr, int *newlen TSRMLS_DC #define PS_SERIALIZER_DECODE_ARGS const char *val, int vallen TSRMLS_DC typedef struct ps_serializer_struct { - const char *name; - int (*encode)(PS_SERIALIZER_ENCODE_ARGS); - int (*decode)(PS_SERIALIZER_DECODE_ARGS); + const char *name; + int (*encode)(PS_SERIALIZER_ENCODE_ARGS); + int (*decode)(PS_SERIALIZER_DECODE_ARGS); } ps_serializer; typedef struct _php_ps_globals_43_44 { - char *save_path; - char *session_name; - char *id; - char *extern_referer_chk; - char *entropy_file; - char *cache_limiter; - long entropy_length; - long cookie_lifetime; - char *cookie_path; - char *cookie_domain; - zend_bool cookie_secure; - ps_module *mod; - void *mod_data; - php_session_status session_status; - long gc_probability; - long gc_divisor; - long gc_maxlifetime; - int module_number; - long cache_expire; - zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ - zend_bool bug_compat_warn; /* Whether to warn about it */ - const struct ps_serializer_struct *serializer; - zval *http_session_vars; - zend_bool auto_start; - zend_bool use_cookies; - zend_bool use_only_cookies; - zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ - zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ - int send_cookie; - int define_sid; + char *save_path; + char *session_name; + char *id; + char *extern_referer_chk; + char *entropy_file; + char *cache_limiter; + long entropy_length; + long cookie_lifetime; + char *cookie_path; + char *cookie_domain; + zend_bool cookie_secure; + ps_module *mod; + void *mod_data; + php_session_status session_status; + long gc_probability; + long gc_divisor; + long gc_maxlifetime; + int module_number; + long cache_expire; + zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ + zend_bool bug_compat_warn; /* Whether to warn about it */ + const struct ps_serializer_struct *serializer; + zval *http_session_vars; + zend_bool auto_start; + zend_bool use_cookies; + zend_bool use_only_cookies; + zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ + zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ + int send_cookie; + int define_sid; } php_ps_globals_43_44; typedef struct _php_ps_globals_50_51 { - char *save_path; - char *session_name; - char *id; - char *extern_referer_chk; - char *entropy_file; - char *cache_limiter; - long entropy_length; - long cookie_lifetime; - char *cookie_path; - char *cookie_domain; - zend_bool cookie_secure; - ps_module *mod; - void *mod_data; - php_session_status session_status; - long gc_probability; - long gc_divisor; - long gc_maxlifetime; - int module_number; - long cache_expire; - zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ - zend_bool bug_compat_warn; /* Whether to warn about it */ - const struct ps_serializer_struct *serializer; - zval *http_session_vars; - zend_bool auto_start; - zend_bool use_cookies; - zend_bool use_only_cookies; - zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ - zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ - - long hash_func; - long hash_bits_per_character; - int send_cookie; - int define_sid; + char *save_path; + char *session_name; + char *id; + char *extern_referer_chk; + char *entropy_file; + char *cache_limiter; + long entropy_length; + long cookie_lifetime; + char *cookie_path; + char *cookie_domain; + zend_bool cookie_secure; + ps_module *mod; + void *mod_data; + php_session_status session_status; + long gc_probability; + long gc_divisor; + long gc_maxlifetime; + int module_number; + long cache_expire; + zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ + zend_bool bug_compat_warn; /* Whether to warn about it */ + const struct ps_serializer_struct *serializer; + zval *http_session_vars; + zend_bool auto_start; + zend_bool use_cookies; + zend_bool use_only_cookies; + zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ + zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ + + long hash_func; + long hash_bits_per_character; + int send_cookie; + int define_sid; } php_ps_globals_50_51; typedef struct _php_ps_globals_52 { - char *save_path; - char *session_name; - char *id; - char *extern_referer_chk; - char *entropy_file; - char *cache_limiter; - long entropy_length; - long cookie_lifetime; - char *cookie_path; - char *cookie_domain; - zend_bool cookie_secure; - zend_bool cookie_httponly; - ps_module *mod; - void *mod_data; - php_session_status session_status; - long gc_probability; - long gc_divisor; - long gc_maxlifetime; - int module_number; - long cache_expire; - zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ - zend_bool bug_compat_warn; /* Whether to warn about it */ - const struct ps_serializer_struct *serializer; - zval *http_session_vars; - zend_bool auto_start; - zend_bool use_cookies; - zend_bool use_only_cookies; - zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ - zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ - - long hash_func; - long hash_bits_per_character; - int send_cookie; - int define_sid; - zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ + char *save_path; + char *session_name; + char *id; + char *extern_referer_chk; + char *entropy_file; + char *cache_limiter; + long entropy_length; + long cookie_lifetime; + char *cookie_path; + char *cookie_domain; + zend_bool cookie_secure; + zend_bool cookie_httponly; + ps_module *mod; + void *mod_data; + php_session_status session_status; + long gc_probability; + long gc_divisor; + long gc_maxlifetime; + int module_number; + long cache_expire; + zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ + zend_bool bug_compat_warn; /* Whether to warn about it */ + const struct ps_serializer_struct *serializer; + zval *http_session_vars; + zend_bool auto_start; + zend_bool use_cookies; + zend_bool use_only_cookies; + zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ + zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ + + long hash_func; + long hash_bits_per_character; + int send_cookie; + int define_sid; + zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ } php_ps_globals_52; typedef struct _php_ps_globals_53 { - char *save_path; - char *session_name; - char *id; - char *extern_referer_chk; - char *entropy_file; - char *cache_limiter; - long entropy_length; - long cookie_lifetime; - char *cookie_path; - char *cookie_domain; - zend_bool cookie_secure; - zend_bool cookie_httponly; - ps_module *mod; - void *mod_data; - php_session_status session_status; - long gc_probability; - long gc_divisor; - long gc_maxlifetime; - int module_number; - long cache_expire; - union { - zval *names[6]; - struct { - zval *ps_open; - zval *ps_close; - zval *ps_read; - zval *ps_write; - zval *ps_destroy; - zval *ps_gc; - } name; - } mod_user_names; - zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ - zend_bool bug_compat_warn; /* Whether to warn about it */ - const struct ps_serializer_struct *serializer; - zval *http_session_vars; - zend_bool auto_start; - zend_bool use_cookies; - zend_bool use_only_cookies; - zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ - zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ - - long hash_func; + char *save_path; + char *session_name; + char *id; + char *extern_referer_chk; + char *entropy_file; + char *cache_limiter; + long entropy_length; + long cookie_lifetime; + char *cookie_path; + char *cookie_domain; + zend_bool cookie_secure; + zend_bool cookie_httponly; + ps_module *mod; + void *mod_data; + php_session_status session_status; + long gc_probability; + long gc_divisor; + long gc_maxlifetime; + int module_number; + long cache_expire; + union { + zval *names[6]; + struct { + zval *ps_open; + zval *ps_close; + zval *ps_read; + zval *ps_write; + zval *ps_destroy; + zval *ps_gc; + } name; + } mod_user_names; + zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ + zend_bool bug_compat_warn; /* Whether to warn about it */ + const struct ps_serializer_struct *serializer; + zval *http_session_vars; + zend_bool auto_start; + zend_bool use_cookies; + zend_bool use_only_cookies; + zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ + zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ + + long hash_func; #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) - php_hash_ops *hash_ops; + php_hash_ops *hash_ops; #endif - long hash_bits_per_character; - int send_cookie; - int define_sid; - zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ + long hash_bits_per_character; + int send_cookie; + int define_sid; + zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ } php_ps_globals_53; #ifdef ZTS @@ -263,52 +263,52 @@ static php_ps_globals_43_44 *session_globals = NULL; ps_serializer *(*suhosin_find_ps_serializer)(char *name TSRMLS_DC) = NULL; -#define PS_ENCODE_VARS \ - char *key; \ - uint key_length; \ - ulong num_key; \ - zval **struc; - -#define PS_ENCODE_LOOP(code) do { \ - HashTable *_ht = Z_ARRVAL_P(SESSION_G(http_session_vars)); \ - int key_type; \ - \ - for (zend_hash_internal_pointer_reset(_ht); \ - (key_type = zend_hash_get_current_key_ex(_ht, &key, &key_length, &num_key, 0, NULL)) != HASH_KEY_NON_EXISTANT; \ - zend_hash_move_forward(_ht)) { \ - if (key_type == HASH_KEY_IS_LONG) { \ - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric key %ld", num_key); \ - continue; \ - } \ - key_length--; \ - if (suhosin_get_session_var(key, key_length, &struc TSRMLS_CC) == SUCCESS) { \ - code; \ - } \ - } \ - } while(0) +#define PS_ENCODE_VARS \ + char *key; \ + uint key_length; \ + ulong num_key; \ + zval **struc; + +#define PS_ENCODE_LOOP(code) do { \ + HashTable *_ht = Z_ARRVAL_P(SESSION_G(http_session_vars)); \ + int key_type; \ + \ + for (zend_hash_internal_pointer_reset(_ht); \ + (key_type = zend_hash_get_current_key_ex(_ht, &key, &key_length, &num_key, 0, NULL)) != HASH_KEY_NON_EXISTANT; \ + zend_hash_move_forward(_ht)) { \ + if (key_type == HASH_KEY_IS_LONG) { \ + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric key %ld", num_key); \ + continue; \ + } \ + key_length--; \ + if (suhosin_get_session_var(key, key_length, &struc TSRMLS_CC) == SUCCESS) { \ + code; \ + } \ + } \ + } while(0) static int suhosin_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) /* {{{ */ { - int ret = FAILURE; - - if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { - ret = zend_hash_find(Z_ARRVAL_P(SESSION_G(http_session_vars)), name, namelen + 1, (void **) state_var); - - /* If register_globals is enabled, and - * if there is an entry for the slot in $_SESSION, and - * if that entry is still set to NULL, and - * if the global var exists, then - * we prefer the same key in the global sym table. */ - - if (PG(register_globals) && ret == SUCCESS && Z_TYPE_PP(*state_var) == IS_NULL) { - zval **tmp; - - if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { - *state_var = tmp; - } - } - } - return ret; + int ret = FAILURE; + + if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { + ret = zend_hash_find(Z_ARRVAL_P(SESSION_G(http_session_vars)), name, namelen + 1, (void **) state_var); + + /* If register_globals is enabled, and + * if there is an entry for the slot in $_SESSION, and + * if that entry is still set to NULL, and + * if the global var exists, then + * we prefer the same key in the global sym table. */ + + if (PG(register_globals) && ret == SUCCESS && Z_TYPE_PP(*state_var) == IS_NULL) { + zval **tmp; + + if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { + *state_var = tmp; + } + } + } + return ret; } #define PS_DELIMITER '|' @@ -316,148 +316,148 @@ static int suhosin_get_session_var(char *name, size_t namelen, zval ***state_var int suhosin_session_encode(char **newstr, int *newlen TSRMLS_DC) { - smart_str buf = {0}; - php_serialize_data_t var_hash; - PS_ENCODE_VARS; - - PHP_VAR_SERIALIZE_INIT(var_hash); - - PS_ENCODE_LOOP( - smart_str_appendl(&buf, key, key_length); - if (key[0] == PS_UNDEF_MARKER || memchr(key, PS_DELIMITER, key_length)) { - PHP_VAR_SERIALIZE_DESTROY(var_hash); - smart_str_free(&buf); - return FAILURE; - } - smart_str_appendc(&buf, PS_DELIMITER); - - php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); - } else { - smart_str_appendc(&buf, PS_UNDEF_MARKER); - smart_str_appendl(&buf, key, key_length); - smart_str_appendc(&buf, PS_DELIMITER); - ); - - if (newlen) { - *newlen = buf.len; - } - smart_str_0(&buf); - *newstr = buf.c; - - PHP_VAR_SERIALIZE_DESTROY(var_hash); - return SUCCESS; + smart_str buf = {0}; + php_serialize_data_t var_hash; + PS_ENCODE_VARS; + + PHP_VAR_SERIALIZE_INIT(var_hash); + + PS_ENCODE_LOOP( + smart_str_appendl(&buf, key, key_length); + if (key[0] == PS_UNDEF_MARKER || memchr(key, PS_DELIMITER, key_length)) { + PHP_VAR_SERIALIZE_DESTROY(var_hash); + smart_str_free(&buf); + return FAILURE; + } + smart_str_appendc(&buf, PS_DELIMITER); + + php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); + } else { + smart_str_appendc(&buf, PS_UNDEF_MARKER); + smart_str_appendl(&buf, key, key_length); + smart_str_appendc(&buf, PS_DELIMITER); + ); + + if (newlen) { + *newlen = buf.len; + } + smart_str_0(&buf); + *newstr = buf.c; + + PHP_VAR_SERIALIZE_DESTROY(var_hash); + return SUCCESS; } static void suhosin_send_cookie(TSRMLS_D) { - int * session_send_cookie = &SESSION_G(send_cookie); - char * base; - zend_ini_entry *ini_entry; - - /* The following is requires to be 100% compatible to PHP - versions where the hash extension is not available by default */ + int * session_send_cookie = &SESSION_G(send_cookie); + char * base; + zend_ini_entry *ini_entry; + + /* The following is requires to be 100% compatible to PHP + versions where the hash extension is not available by default */ #if (PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3) - if (zend_hash_find(EG(ini_directives), "session.hash_bits_per_character", sizeof("session.hash_bits_per_character"), (void **) &ini_entry) == SUCCESS) { + if (zend_hash_find(EG(ini_directives), "session.hash_bits_per_character", sizeof("session.hash_bits_per_character"), (void **) &ini_entry) == SUCCESS) { #ifndef ZTS - base = (char *) ini_entry->mh_arg2; + base = (char *) ini_entry->mh_arg2; #else - base = (char *) ts_resource(*((int *) ini_entry->mh_arg2)); + base = (char *) ts_resource(*((int *) ini_entry->mh_arg2)); #endif - session_send_cookie = (int *) (base+(size_t) ini_entry->mh_arg1+sizeof(long)); - } + session_send_cookie = (int *) (base+(size_t) ini_entry->mh_arg1+sizeof(long)); + } #endif - *session_send_cookie = 1; + *session_send_cookie = 1; } void suhosin_get_ipv4(char *buf TSRMLS_DC) { - char *raddr = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); - int i; - - - if (raddr == NULL) { - memset(buf, 0, 4); - return; - } - - for (i=0; i<4; i++) { - if (raddr[0] == 0) { - buf[i] = 0; - } else { - buf[i] = strtol(raddr, &raddr, 10); - if (raddr[0] == '.') { - raddr++; - } - } - } + char *raddr = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); + int i; + + + if (raddr == NULL) { + memset(buf, 0, 4); + return; + } + + for (i=0; i<4; i++) { + if (raddr[0] == 0) { + buf[i] = 0; + } else { + buf[i] = strtol(raddr, &raddr, 10); + if (raddr[0] == '.') { + raddr++; + } + } + } } char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC) { int padded_len, i, slen; unsigned char *crypted, *tmp; - unsigned int check = 0x13579BDF; - + unsigned int check = 0x13579BDF; + if (str == NULL) { - return NULL; + return NULL; + } + if (len == 0) { + return estrndup("", 0); } - if (len == 0) { - return estrndup("", 0); - } suhosin_aes_gkey(4,8,key TSRMLS_CC); padded_len = ((len+15) & ~0xF); crypted = emalloc(16+padded_len+1); - memset(crypted, 0xff, 16+padded_len+1); + memset(crypted, 0xff, 16+padded_len+1); memcpy(crypted+16, str, len+1); - /* calculate check value */ - for (i = 0; i> (32-3)); - check += check << 1; - check ^= (unsigned char)var[i]; - } - for (i = 0; i> (32-3)); - check += check << 1; - check ^= (unsigned char)str[i]; - } - - /* store ip value */ - suhosin_get_ipv4(crypted+4 TSRMLS_CC); - - /* store check value */ - crypted[8] = check & 0xff; - crypted[9] = (check >> 8) & 0xff; - crypted[10] = (check >> 16) & 0xff; - crypted[11] = (check >> 24) & 0xff; - - /* store original length */ - crypted[12] = len & 0xff; - crypted[13] = (len >> 8) & 0xff; - crypted[14] = (len >> 16) & 0xff; - crypted[15] = (len >> 24) & 0xff; - + /* calculate check value */ + for (i = 0; i> (32-3)); + check += check << 1; + check ^= (unsigned char)var[i]; + } + for (i = 0; i> (32-3)); + check += check << 1; + check ^= (unsigned char)str[i]; + } + + /* store ip value */ + suhosin_get_ipv4(crypted+4 TSRMLS_CC); + + /* store check value */ + crypted[8] = check & 0xff; + crypted[9] = (check >> 8) & 0xff; + crypted[10] = (check >> 16) & 0xff; + crypted[11] = (check >> 24) & 0xff; + + /* store original length */ + crypted[12] = len & 0xff; + crypted[13] = (len >> 8) & 0xff; + crypted[14] = (len >> 16) & 0xff; + crypted[15] = (len >> 24) & 0xff; + for (i=0, tmp=crypted; i 0) { - int j; + int j; for (j=0; j<16; j++) tmp[j] ^= tmp[j-16]; } suhosin_aes_encrypt((char *)tmp TSRMLS_CC); } - + tmp = php_base64_encode(crypted, padded_len+16, NULL); efree(crypted); slen=strlen((char *)tmp); - for (i=0; i=0; i-=16, tmp-=16) { - suhosin_aes_decrypt((char *)tmp TSRMLS_CC); - if (i > 0) { - int j; - for (j=0; j<16; j++) tmp[j] ^= tmp[j-16]; + suhosin_aes_decrypt((char *)tmp TSRMLS_CC); + if (i > 0) { + int j; + for (j=0; j<16; j++) tmp[j] ^= tmp[j-16]; + } + } + + /* retrieve orig_len */ + o_len = decrypted[15]; + o_len <<= 8; + o_len |= decrypted[14]; + o_len <<= 8; + o_len |= decrypted[13]; + o_len <<= 8; + o_len |= decrypted[12]; + + if (o_len < 0 || o_len > len-16) { + goto error_out; + } + + /* calculate check value */ + for (i = 0; i> (32-3)); + check += check << 1; + check ^= (unsigned char)var[i]; + } + for (i = 0; i> (32-3)); + check += check << 1; + check ^= decrypted[16+i]; + } + + /* check value */ + invalid = (decrypted[8] != (check & 0xff)) || + (decrypted[9] != ((check >> 8) & 0xff)) || + (decrypted[10] != ((check >> 16) & 0xff)) || + (decrypted[11] != ((check >> 24) & 0xff)); + + /* check IP */ + if (check_ra > 0) { + if (check_ra > 4) { + check_ra = 4; } + suhosin_get_ipv4(&buf TSRMLS_CC); + if (memcmp(buf, decrypted+4, check_ra) != 0) { + goto error_out; + } + } + + if (invalid) { + goto error_out; + } + + if (orig_len) { + *orig_len = o_len; } - - /* retrieve orig_len */ - o_len = decrypted[15]; - o_len <<= 8; - o_len |= decrypted[14]; - o_len <<= 8; - o_len |= decrypted[13]; - o_len <<= 8; - o_len |= decrypted[12]; - - if (o_len < 0 || o_len > len-16) { - goto error_out; - } - - /* calculate check value */ - for (i = 0; i> (32-3)); - check += check << 1; - check ^= (unsigned char)var[i]; - } - for (i = 0; i> (32-3)); - check += check << 1; - check ^= decrypted[16+i]; - } - - /* check value */ - invalid = (decrypted[8] != (check & 0xff)) || - (decrypted[9] != ((check >> 8) & 0xff)) || - (decrypted[10] != ((check >> 16) & 0xff)) || - (decrypted[11] != ((check >> 24) & 0xff)); - - /* check IP */ - if (check_ra > 0) { - if (check_ra > 4) { - check_ra = 4; - } - suhosin_get_ipv4(&buf TSRMLS_CC); - if (memcmp(buf, decrypted+4, check_ra) != 0) { - goto error_out; - } - } - - if (invalid) { - goto error_out; - } - - if (orig_len) { - *orig_len = o_len; - } - - memmove(decrypted, decrypted+16, o_len); - decrypted[o_len] = 0; - /* we do not realloc() here because 16 byte less - is simply not worth the overhead */ - return (char *)decrypted; + + memmove(decrypted, decrypted+16, o_len); + decrypted[o_len] = 0; + /* we do not realloc() here because 16 byte less + is simply not worth the overhead */ + return (char *)decrypted; } char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC) { - char *_ua = NULL; - char *_dr = NULL; - char *_ra = NULL; - suhosin_SHA256_CTX ctx; - - if (ua) { - _ua = sapi_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC); - } - - if (dr) { - _dr = sapi_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); - } - - if (raddr > 0) { - _ra = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); - } - - SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra); - - suhosin_SHA256Init(&ctx); - if (key == NULL) { - suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", sizeof("D3F4UL7")); - } else { - suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key)); - } - if (_ua) { - suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua)); - } - if (_dr) { - suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr)); - } - if (_ra) { - if (raddr >= 4) { - suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra)); - } else { - long dots = 0; - char *tmp = _ra; - - while (*tmp) { - if (*tmp == '.') { - dots++; - if (dots == raddr) { - break; - } - } - tmp++; - } - suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra); - } - } - suhosin_SHA256Final((unsigned char *)cryptkey, &ctx); - cryptkey[32] = 0; /* uhmm... not really a string */ - - return cryptkey; + char *_ua = NULL; + char *_dr = NULL; + char *_ra = NULL; + suhosin_SHA256_CTX ctx; + + if (ua) { + _ua = sapi_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC); + } + + if (dr) { + _dr = sapi_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); + } + + if (raddr > 0) { + _ra = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); + } + + SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra); + + suhosin_SHA256Init(&ctx); + if (key == NULL) { + suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", sizeof("D3F4UL7")); + } else { + suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key)); + } + if (_ua) { + suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua)); + } + if (_dr) { + suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr)); + } + if (_ra) { + if (raddr >= 4) { + suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra)); + } else { + long dots = 0; + char *tmp = _ra; + + while (*tmp) { + if (*tmp == '.') { + dots++; + if (dots == raddr) { + break; + } + } + tmp++; + } + suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra); + } + } + suhosin_SHA256Final((unsigned char *)cryptkey, &ctx); + cryptkey[32] = 0; /* uhmm... not really a string */ + + return cryptkey; } @@ -629,270 +629,270 @@ static int (*old_SessionRINIT)(INIT_FUNC_ARGS) = NULL; static int suhosin_hook_s_read(void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC) { - int r; - - int i;char *v,*KEY=(char *)key; - - /* protect session vars */ -/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { - SESSION_G(http_session_vars)->refcount++; - }*/ - - /* protect dumb session handlers */ - if (key == NULL || !key[0] || *mod_data == NULL) { + int r; + + int i;char *v,*KEY=(char *)key; + + /* protect session vars */ +/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { + SESSION_G(http_session_vars)->refcount++; + }*/ + + /* protect dumb session handlers */ + if (key == NULL || !key[0] || *mod_data == NULL) { regenerate: - SDEBUG("regenerating key is %s", key); - KEY = SESSION_G(id) = SESSION_G(mod)->s_create_sid(&SESSION_G(mod_data), NULL TSRMLS_CC); - suhosin_send_cookie(TSRMLS_C); - } else if (strlen(key) > SUHOSIN_G(session_max_id_length)) { - suhosin_log(S_SESSION, "session id ('%s') exceeds maximum length - regenerating", KEY); - if (!SUHOSIN_G(simulation)) { - goto regenerate; - } - } + SDEBUG("regenerating key is %s", key); + KEY = SESSION_G(id) = SESSION_G(mod)->s_create_sid(&SESSION_G(mod_data), NULL TSRMLS_CC); + suhosin_send_cookie(TSRMLS_C); + } else if (strlen(key) > SUHOSIN_G(session_max_id_length)) { + suhosin_log(S_SESSION, "session id ('%s') exceeds maximum length - regenerating", KEY); + if (!SUHOSIN_G(simulation)) { + goto regenerate; + } + } #if (PHP_MAJOR_VERSION < 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) - else if (strpbrk(KEY, "\r\n\t <>'\"\\")) { - suhosin_log(S_SESSION, "session id ('%s') contains invalid chars - regenerating", KEY); - if (!SUHOSIN_G(simulation)) { - goto regenerate; - } - } + else if (strpbrk(KEY, "\r\n\t <>'\"\\")) { + suhosin_log(S_SESSION, "session id ('%s') contains invalid chars - regenerating", KEY); + if (!SUHOSIN_G(simulation)) { + goto regenerate; + } + } #endif - r = SUHOSIN_G(old_s_read)(mod_data, KEY, val, vallen TSRMLS_CC); - - if (r == SUCCESS && SUHOSIN_G(session_encrypt) && *vallen > 0) { - char cryptkey[33]; - - SUHOSIN_G(do_not_scan) = 1; - suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); - - v = *val; - i = *vallen; - *val = suhosin_decrypt_string(v, i, "", 0, (char *)&cryptkey, vallen, SUHOSIN_G(session_checkraddr) TSRMLS_CC); - SUHOSIN_G(do_not_scan) = 0; - if (*val == NULL) { - *val = estrndup("", 0); - *vallen = 0; - } - efree(v); - } - - return r; + r = SUHOSIN_G(old_s_read)(mod_data, KEY, val, vallen TSRMLS_CC); + + if (r == SUCCESS && SUHOSIN_G(session_encrypt) && *vallen > 0) { + char cryptkey[33]; + + SUHOSIN_G(do_not_scan) = 1; + suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); + + v = *val; + i = *vallen; + *val = suhosin_decrypt_string(v, i, "", 0, (char *)&cryptkey, vallen, SUHOSIN_G(session_checkraddr) TSRMLS_CC); + SUHOSIN_G(do_not_scan) = 0; + if (*val == NULL) { + *val = estrndup("", 0); + *vallen = 0; + } + efree(v); + } + + return r; } static int suhosin_hook_s_write(void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC) { - int r; -/* int nullify = 0;*/ - char *v = (char *)val; - - /* protect dumb session handlers */ - if (key == NULL || !key[0] || val == NULL || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { - r = FAILURE; - goto return_write; - } - - r = vallen; - - if (r > 0 && SUHOSIN_G(session_encrypt)) { - char cryptkey[33]; - - SUHOSIN_G(do_not_scan) = 1; - - suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); - - v = suhosin_encrypt_string(v, vallen, "", 0, (char *)&cryptkey TSRMLS_CC); - - SUHOSIN_G(do_not_scan) = 0; - r = strlen(v); - } - - r = SUHOSIN_G(old_s_write)(mod_data, key, v, r TSRMLS_CC); - + int r; +/* int nullify = 0;*/ + char *v = (char *)val; + + /* protect dumb session handlers */ + if (key == NULL || !key[0] || val == NULL || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { + r = FAILURE; + goto return_write; + } + + r = vallen; + + if (r > 0 && SUHOSIN_G(session_encrypt)) { + char cryptkey[33]; + + SUHOSIN_G(do_not_scan) = 1; + + suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); + + v = suhosin_encrypt_string(v, vallen, "", 0, (char *)&cryptkey TSRMLS_CC); + + SUHOSIN_G(do_not_scan) = 0; + r = strlen(v); + } + + r = SUHOSIN_G(old_s_write)(mod_data, key, v, r TSRMLS_CC); + return_write: - /* protect session vars */ -/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { - if (SESSION_G(http_session_vars)->refcount==1) { - nullify = 1; - } - zval_ptr_dtor(&SESSION_G(http_session_vars)); - if (nullify) { - suhosin_log(S_SESSION, "possible session variables double free attack stopped"); - SESSION_G(http_session_vars) = NULL; - } - }*/ - - return r; + /* protect session vars */ +/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { + if (SESSION_G(http_session_vars)->refcount==1) { + nullify = 1; + } + zval_ptr_dtor(&SESSION_G(http_session_vars)); + if (nullify) { + suhosin_log(S_SESSION, "possible session variables double free attack stopped"); + SESSION_G(http_session_vars) = NULL; + } + }*/ + + return r; } static int suhosin_hook_s_destroy(void **mod_data, const char *key TSRMLS_DC) { - int r; - - /* protect dumb session handlers */ - if (key == NULL || !key[0] || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { - return FAILURE; - } - - r = SUHOSIN_G(old_s_destroy)(mod_data, key TSRMLS_CC); - - return r; + int r; + + /* protect dumb session handlers */ + if (key == NULL || !key[0] || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { + return FAILURE; + } + + r = SUHOSIN_G(old_s_destroy)(mod_data, key TSRMLS_CC); + + return r; } static void suhosin_hook_session_module(TSRMLS_D) { - ps_module *old_mod = SESSION_G(mod), *mod; - - if (old_mod == NULL || SUHOSIN_G(s_module) == old_mod) { - return; - } - if (SUHOSIN_G(s_module) == NULL) { - SUHOSIN_G(s_module) = mod = malloc(sizeof(ps_module)); - if (mod == NULL) { - return; - } - } - mod = SUHOSIN_G(s_module); - memcpy(mod, old_mod, sizeof(ps_module)); - - SUHOSIN_G(old_s_read) = mod->s_read; - mod->s_read = suhosin_hook_s_read; - SUHOSIN_G(old_s_write) = mod->s_write; - mod->s_write = suhosin_hook_s_write; - SUHOSIN_G(old_s_destroy) = mod->s_destroy; - mod->s_destroy = suhosin_hook_s_destroy; - - SESSION_G(mod) = mod; + ps_module *old_mod = SESSION_G(mod), *mod; + + if (old_mod == NULL || SUHOSIN_G(s_module) == old_mod) { + return; + } + if (SUHOSIN_G(s_module) == NULL) { + SUHOSIN_G(s_module) = mod = malloc(sizeof(ps_module)); + if (mod == NULL) { + return; + } + } + mod = SUHOSIN_G(s_module); + memcpy(mod, old_mod, sizeof(ps_module)); + + SUHOSIN_G(old_s_read) = mod->s_read; + mod->s_read = suhosin_hook_s_read; + SUHOSIN_G(old_s_write) = mod->s_write; + mod->s_write = suhosin_hook_s_write; + SUHOSIN_G(old_s_destroy) = mod->s_destroy; + mod->s_destroy = suhosin_hook_s_destroy; + + SESSION_G(mod) = mod; } static PHP_INI_MH(suhosin_OnUpdateSaveHandler) { - int r; + int r; - r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); - - suhosin_hook_session_module(TSRMLS_C); - - return r; + r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + + suhosin_hook_session_module(TSRMLS_C); + + return r; } static int suhosin_hook_session_RINIT(INIT_FUNC_ARGS) { - if (SESSION_G(mod) == NULL) { - char *value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); - - if (value) { - suhosin_OnUpdateSaveHandler(NULL, value, strlen(value), NULL, NULL, NULL, 0 TSRMLS_CC); - } - } - return old_SessionRINIT(INIT_FUNC_ARGS_PASSTHRU); + if (SESSION_G(mod) == NULL) { + char *value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); + + if (value) { + suhosin_OnUpdateSaveHandler(NULL, value, strlen(value), NULL, NULL, NULL, 0 TSRMLS_CC); + } + } + return old_SessionRINIT(INIT_FUNC_ARGS_PASSTHRU); } void suhosin_hook_session(TSRMLS_D) { - ps_serializer *serializer; - zend_ini_entry *ini_entry; - zend_module_entry *module; + ps_serializer *serializer; + zend_ini_entry *ini_entry; + zend_module_entry *module; #ifdef ZTS - ts_rsrc_id *ps_globals_id_ptr; + ts_rsrc_id *ps_globals_id_ptr; #endif - - if (zend_hash_find(&module_registry, "session", sizeof("session"), (void**)&module) == FAILURE) { - return; - } + + if (zend_hash_find(&module_registry, "session", sizeof("session"), (void**)&module) == FAILURE) { + return; + } /* retrieve globals from module entry struct if possible */ #if PHP_VERSION_ID >= 50200 #ifdef ZTS if (session_globals_id == 0) { - session_globals_id = *module->globals_id_ptr; + session_globals_id = *module->globals_id_ptr; } #else if (session_globals == NULL) { - session_globals = module->globals_ptr; + session_globals = module->globals_ptr; } #endif #else - /* retrieve globals from symbols if PHP version is old */ + /* retrieve globals from symbols if PHP version is old */ #ifdef ZTS - if (session_globals_id == 0) { - ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "ps_globals_id"); - if (ps_globals_id_ptr == NULL) { - ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "_ps_globals_id"); - } - if (ps_globals_id_ptr == NULL) { - return; - } - - session_globals_id = *ps_globals_id_ptr; - } + if (session_globals_id == 0) { + ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "ps_globals_id"); + if (ps_globals_id_ptr == NULL) { + ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "_ps_globals_id"); + } + if (ps_globals_id_ptr == NULL) { + return; + } + + session_globals_id = *ps_globals_id_ptr; + } #else - if (session_globals == NULL) { - session_globals = DL_FETCH_SYMBOL(module->handle, "ps_globals"); - if (session_globals == NULL) { - session_globals = DL_FETCH_SYMBOL(module->handle, "_ps_globals"); - } - if (session_globals == NULL) { - return; - } - } + if (session_globals == NULL) { + session_globals = DL_FETCH_SYMBOL(module->handle, "ps_globals"); + if (session_globals == NULL) { + session_globals = DL_FETCH_SYMBOL(module->handle, "_ps_globals"); + } + if (session_globals == NULL) { + return; + } + } #endif #endif - if (old_OnUpdateSaveHandler != NULL) { - return; - } - - /* hook request startup function of session module */ - old_SessionRINIT = module->request_startup_func; - module->request_startup_func = suhosin_hook_session_RINIT; - - /* retrieve pointer to session.save_handler ini entry */ - if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { - return; - } - SUHOSIN_G(s_module) = NULL; - - /* replace OnUpdateMemoryLimit handler */ - old_OnUpdateSaveHandler = ini_entry->on_modify; - ini_entry->on_modify = suhosin_OnUpdateSaveHandler; - - suhosin_hook_session_module(TSRMLS_C); - - /* Protect the PHP serializer from ! attacks */ + if (old_OnUpdateSaveHandler != NULL) { + return; + } + + /* hook request startup function of session module */ + old_SessionRINIT = module->request_startup_func; + module->request_startup_func = suhosin_hook_session_RINIT; + + /* retrieve pointer to session.save_handler ini entry */ + if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { + return; + } + SUHOSIN_G(s_module) = NULL; + + /* replace OnUpdateMemoryLimit handler */ + old_OnUpdateSaveHandler = ini_entry->on_modify; + ini_entry->on_modify = suhosin_OnUpdateSaveHandler; + + suhosin_hook_session_module(TSRMLS_C); + + /* Protect the PHP serializer from ! attacks */ # if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) - serializer = SESSION_G(serializer); - if (serializer != NULL && strcmp(serializer->name, "php")==0) { - serializer->encode = suhosin_session_encode; - } + serializer = SESSION_G(serializer); + if (serializer != NULL && strcmp(serializer->name, "php")==0) { + serializer->encode = suhosin_session_encode; + } #endif - /* increase session identifier entropy */ - if (SESSION_G(entropy_length) == 0 || SESSION_G(entropy_file) == NULL) { - - /* ensure that /dev/urandom exists */ - int fd = VCWD_OPEN("/dev/urandom", O_RDONLY); - if (fd >= 0) { - close(fd); - SESSION_G(entropy_length) = 16; - SESSION_G(entropy_file) = pestrdup("/dev/urandom", 1); - } + /* increase session identifier entropy */ + if (SESSION_G(entropy_length) == 0 || SESSION_G(entropy_file) == NULL) { + + /* ensure that /dev/urandom exists */ + int fd = VCWD_OPEN("/dev/urandom", O_RDONLY); + if (fd >= 0) { + close(fd); + SESSION_G(entropy_length) = 16; + SESSION_G(entropy_file) = pestrdup("/dev/urandom", 1); } + } } void suhosin_unhook_session(TSRMLS_D) { - if (old_OnUpdateSaveHandler != NULL) { - zend_ini_entry *ini_entry; - - /* retrieve pointer to session.save_handler ini entry */ - if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { - return; - } - ini_entry->on_modify = old_OnUpdateSaveHandler; - - old_OnUpdateSaveHandler = NULL; - } + if (old_OnUpdateSaveHandler != NULL) { + zend_ini_entry *ini_entry; + + /* retrieve pointer to session.save_handler ini entry */ + if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { + return; + } + ini_entry->on_modify = old_OnUpdateSaveHandler; + + old_OnUpdateSaveHandler = NULL; + } } -- cgit v1.3