summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Esser2012-01-11 19:57:40 +0100
committerStefan Esser2012-01-11 19:57:40 +0100
commit70310b8f359e1276e3fa6ed326a8f91d9b02f0fc (patch)
tree47d25d6c801d7417e4e65a15778a42cf5204b1f6
parentba38594769bc6d4bf3dbb6ab8a666a165a77b8b4 (diff)
Fix git repository. Github had the wrong git repository commited. The last revisions were missing.
From here we can continue developing.
-rw-r--r--Changelog10
-rw-r--r--execute.c1
-rw-r--r--memory_limit.c20
-rw-r--r--php_suhosin.h2
-rw-r--r--session.c1282
5 files changed, 667 insertions, 648 deletions
diff --git a/Changelog b/Changelog
index 19e9036..aeecfe4 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,13 @@
12010-07-23 - 0.9.32.1
2
3 - Fixed missing header file resulting in compile errors
4
52010-07-23 - 0.9.32
6
7 - Added support for memory_limit > 2GB
8 - Fixed missing header file resulting in wrong php_combined_lcg() prototype being used
9 - Improved random number seed generation more by adding /dev/urandom juice
10
12010-03-28 - 0.9.31 112010-03-28 - 0.9.31
2 12
3 - Fix ZTS build of session.c 13 - Fix ZTS build of session.c
diff --git a/execute.c b/execute.c
index 95e9ccc..9a0cfbc 100644
--- a/execute.c
+++ b/execute.c
@@ -23,6 +23,7 @@
23#include "config.h" 23#include "config.h"
24#endif 24#endif
25 25
26#include <fcntl.h>
26#include "php.h" 27#include "php.h"
27#include "php_ini.h" 28#include "php_ini.h"
28#include "zend_hash.h" 29#include "zend_hash.h"
diff --git a/memory_limit.c b/memory_limit.c
index 84c0bf3..c135ab4 100644
--- a/memory_limit.c
+++ b/memory_limit.c
@@ -47,12 +47,20 @@ static PHP_INI_MH(suhosin_OnChangeMemoryLimit)
47 SUHOSIN_G(hard_memory_limit) = 0; 47 SUHOSIN_G(hard_memory_limit) = 0;
48 } 48 }
49 if (new_value) { 49 if (new_value) {
50 PG(memory_limit) = zend_atoi(new_value, new_value_length); 50 PG(memory_limit) = zend_atol(new_value, new_value_length);
51 if (PG(memory_limit) > hard_memory_limit || PG(memory_limit) < 0) { 51 if (hard_memory_limit > 0) {
52 suhosin_log(S_MISC, "script tried to increase memory_limit to %u bytes which is above the allowed value", PG(memory_limit)); 52 if (PG(memory_limit) > hard_memory_limit) {
53 if (!SUHOSIN_G(simulation)) { 53 suhosin_log(S_MISC, "script tried to increase memory_limit to %u bytes which is above the allowed value", PG(memory_limit));
54 PG(memory_limit) = hard_memory_limit; 54 if (!SUHOSIN_G(simulation)) {
55 return FAILURE; 55 PG(memory_limit) = hard_memory_limit;
56 return FAILURE;
57 }
58 } else if (PG(memory_limit) < 0) {
59 suhosin_log(S_MISC, "script tried to disable memory_limit by setting it to a negative value %d bytes which is not allowed", PG(memory_limit));
60 if (!SUHOSIN_G(simulation)) {
61 PG(memory_limit) = hard_memory_limit;
62 return FAILURE;
63 }
56 } 64 }
57 } 65 }
58 } else { 66 } else {
diff --git a/php_suhosin.h b/php_suhosin.h
index e256ca3..312bb08 100644
--- a/php_suhosin.h
+++ b/php_suhosin.h
@@ -22,7 +22,7 @@
22#ifndef PHP_SUHOSIN_H 22#ifndef PHP_SUHOSIN_H
23#define PHP_SUHOSIN_H 23#define PHP_SUHOSIN_H
24 24
25#define SUHOSIN_EXT_VERSION "0.9.31" 25#define SUHOSIN_EXT_VERSION "0.9.32.1"
26 26
27/*#define SUHOSIN_DEBUG*/ 27/*#define SUHOSIN_DEBUG*/
28#define SUHOSIN_LOG "/tmp/suhosin_log.txt" 28#define SUHOSIN_LOG "/tmp/suhosin_log.txt"
diff --git a/session.c b/session.c
index 2e5b092..0fe9d3b 100644
--- a/session.c
+++ b/session.c
@@ -1,19 +1,19 @@
1/* 1/*
2 +----------------------------------------------------------------------+ 2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 | 3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+ 4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project | 5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2010 SektionEins GmbH | 6 | Copyright (c) 2007-2010 SektionEins GmbH |
7 +----------------------------------------------------------------------+ 7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, | 8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is | 9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: | 10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt | 11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to | 12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to | 13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. | 14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+ 15 +----------------------------------------------------------------------+
16 | Author: Stefan Esser <sesser@sektioneins.de> | 16 | Author: Stefan Esser <sesser@sektioneins.de> |
17 +----------------------------------------------------------------------+ 17 +----------------------------------------------------------------------+
18*/ 18*/
19/* 19/*
@@ -49,188 +49,188 @@
49#define PS_CREATE_SID_ARGS void **mod_data, int *newlen TSRMLS_DC 49#define PS_CREATE_SID_ARGS void **mod_data, int *newlen TSRMLS_DC
50 50
51typedef struct ps_module_struct { 51typedef struct ps_module_struct {
52 const char *s_name; 52 const char *s_name;
53 int (*s_open)(PS_OPEN_ARGS); 53 int (*s_open)(PS_OPEN_ARGS);
54 int (*s_close)(PS_CLOSE_ARGS); 54 int (*s_close)(PS_CLOSE_ARGS);
55 int (*s_read)(PS_READ_ARGS); 55 int (*s_read)(PS_READ_ARGS);
56 int (*s_write)(PS_WRITE_ARGS); 56 int (*s_write)(PS_WRITE_ARGS);
57 int (*s_destroy)(PS_DESTROY_ARGS); 57 int (*s_destroy)(PS_DESTROY_ARGS);
58 int (*s_gc)(PS_GC_ARGS); 58 int (*s_gc)(PS_GC_ARGS);
59 char *(*s_create_sid)(PS_CREATE_SID_ARGS); 59 char *(*s_create_sid)(PS_CREATE_SID_ARGS);
60} ps_module; 60} ps_module;
61 61
62typedef enum { 62typedef enum {
63 php_session_disabled, 63 php_session_disabled,
64 php_session_none, 64 php_session_none,
65 php_session_active 65 php_session_active
66} php_session_status; 66} php_session_status;
67 67
68#define PS_SERIALIZER_ENCODE_ARGS char **newstr, int *newlen TSRMLS_DC 68#define PS_SERIALIZER_ENCODE_ARGS char **newstr, int *newlen TSRMLS_DC
69#define PS_SERIALIZER_DECODE_ARGS const char *val, int vallen TSRMLS_DC 69#define PS_SERIALIZER_DECODE_ARGS const char *val, int vallen TSRMLS_DC
70 70
71typedef struct ps_serializer_struct { 71typedef struct ps_serializer_struct {
72 const char *name; 72 const char *name;
73 int (*encode)(PS_SERIALIZER_ENCODE_ARGS); 73 int (*encode)(PS_SERIALIZER_ENCODE_ARGS);
74 int (*decode)(PS_SERIALIZER_DECODE_ARGS); 74 int (*decode)(PS_SERIALIZER_DECODE_ARGS);
75} ps_serializer; 75} ps_serializer;
76 76
77typedef struct _php_ps_globals_43_44 { 77typedef struct _php_ps_globals_43_44 {
78 char *save_path; 78 char *save_path;
79 char *session_name; 79 char *session_name;
80 char *id; 80 char *id;
81 char *extern_referer_chk; 81 char *extern_referer_chk;
82 char *entropy_file; 82 char *entropy_file;
83 char *cache_limiter; 83 char *cache_limiter;
84 long entropy_length; 84 long entropy_length;
85 long cookie_lifetime; 85 long cookie_lifetime;
86 char *cookie_path; 86 char *cookie_path;
87 char *cookie_domain; 87 char *cookie_domain;
88 zend_bool cookie_secure; 88 zend_bool cookie_secure;
89 ps_module *mod; 89 ps_module *mod;
90 void *mod_data; 90 void *mod_data;
91 php_session_status session_status; 91 php_session_status session_status;
92 long gc_probability; 92 long gc_probability;
93 long gc_divisor; 93 long gc_divisor;
94 long gc_maxlifetime; 94 long gc_maxlifetime;
95 int module_number; 95 int module_number;
96 long cache_expire; 96 long cache_expire;
97 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ 97 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */
98 zend_bool bug_compat_warn; /* Whether to warn about it */ 98 zend_bool bug_compat_warn; /* Whether to warn about it */
99 const struct ps_serializer_struct *serializer; 99 const struct ps_serializer_struct *serializer;
100 zval *http_session_vars; 100 zval *http_session_vars;
101 zend_bool auto_start; 101 zend_bool auto_start;
102 zend_bool use_cookies; 102 zend_bool use_cookies;
103 zend_bool use_only_cookies; 103 zend_bool use_only_cookies;
104 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ 104 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
105 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ 105 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
106 int send_cookie; 106 int send_cookie;
107 int define_sid; 107 int define_sid;
108} php_ps_globals_43_44; 108} php_ps_globals_43_44;
109 109
110typedef struct _php_ps_globals_50_51 { 110typedef struct _php_ps_globals_50_51 {
111 char *save_path; 111 char *save_path;
112 char *session_name; 112 char *session_name;
113 char *id; 113 char *id;
114 char *extern_referer_chk; 114 char *extern_referer_chk;
115 char *entropy_file; 115 char *entropy_file;
116 char *cache_limiter; 116 char *cache_limiter;
117 long entropy_length; 117 long entropy_length;
118 long cookie_lifetime; 118 long cookie_lifetime;
119 char *cookie_path; 119 char *cookie_path;
120 char *cookie_domain; 120 char *cookie_domain;
121 zend_bool cookie_secure; 121 zend_bool cookie_secure;
122 ps_module *mod; 122 ps_module *mod;
123 void *mod_data; 123 void *mod_data;
124 php_session_status session_status; 124 php_session_status session_status;
125 long gc_probability; 125 long gc_probability;
126 long gc_divisor; 126 long gc_divisor;
127 long gc_maxlifetime; 127 long gc_maxlifetime;
128 int module_number; 128 int module_number;
129 long cache_expire; 129 long cache_expire;
130 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ 130 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */
131 zend_bool bug_compat_warn; /* Whether to warn about it */ 131 zend_bool bug_compat_warn; /* Whether to warn about it */
132 const struct ps_serializer_struct *serializer; 132 const struct ps_serializer_struct *serializer;
133 zval *http_session_vars; 133 zval *http_session_vars;
134 zend_bool auto_start; 134 zend_bool auto_start;
135 zend_bool use_cookies; 135 zend_bool use_cookies;
136 zend_bool use_only_cookies; 136 zend_bool use_only_cookies;
137 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ 137 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
138 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ 138 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
139 139
140 long hash_func; 140 long hash_func;
141 long hash_bits_per_character; 141 long hash_bits_per_character;
142 int send_cookie; 142 int send_cookie;
143 int define_sid; 143 int define_sid;
144} php_ps_globals_50_51; 144} php_ps_globals_50_51;
145 145
146typedef struct _php_ps_globals_52 { 146typedef struct _php_ps_globals_52 {
147 char *save_path; 147 char *save_path;
148 char *session_name; 148 char *session_name;
149 char *id; 149 char *id;
150 char *extern_referer_chk; 150 char *extern_referer_chk;
151 char *entropy_file; 151 char *entropy_file;
152 char *cache_limiter; 152 char *cache_limiter;
153 long entropy_length; 153 long entropy_length;
154 long cookie_lifetime; 154 long cookie_lifetime;
155 char *cookie_path; 155 char *cookie_path;
156 char *cookie_domain; 156 char *cookie_domain;
157 zend_bool cookie_secure; 157 zend_bool cookie_secure;
158 zend_bool cookie_httponly; 158 zend_bool cookie_httponly;
159 ps_module *mod; 159 ps_module *mod;
160 void *mod_data; 160 void *mod_data;
161 php_session_status session_status; 161 php_session_status session_status;
162 long gc_probability; 162 long gc_probability;
163 long gc_divisor; 163 long gc_divisor;
164 long gc_maxlifetime; 164 long gc_maxlifetime;
165 int module_number; 165 int module_number;
166 long cache_expire; 166 long cache_expire;
167 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ 167 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */
168 zend_bool bug_compat_warn; /* Whether to warn about it */ 168 zend_bool bug_compat_warn; /* Whether to warn about it */
169 const struct ps_serializer_struct *serializer; 169 const struct ps_serializer_struct *serializer;
170 zval *http_session_vars; 170 zval *http_session_vars;
171 zend_bool auto_start; 171 zend_bool auto_start;
172 zend_bool use_cookies; 172 zend_bool use_cookies;
173 zend_bool use_only_cookies; 173 zend_bool use_only_cookies;
174 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ 174 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
175 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ 175 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
176 176
177 long hash_func; 177 long hash_func;
178 long hash_bits_per_character; 178 long hash_bits_per_character;
179 int send_cookie; 179 int send_cookie;
180 int define_sid; 180 int define_sid;
181 zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ 181 zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */
182} php_ps_globals_52; 182} php_ps_globals_52;
183 183
184typedef struct _php_ps_globals_53 { 184typedef struct _php_ps_globals_53 {
185 char *save_path; 185 char *save_path;
186 char *session_name; 186 char *session_name;
187 char *id; 187 char *id;
188 char *extern_referer_chk; 188 char *extern_referer_chk;
189 char *entropy_file; 189 char *entropy_file;
190 char *cache_limiter; 190 char *cache_limiter;
191 long entropy_length; 191 long entropy_length;
192 long cookie_lifetime; 192 long cookie_lifetime;
193 char *cookie_path; 193 char *cookie_path;
194 char *cookie_domain; 194 char *cookie_domain;
195 zend_bool cookie_secure; 195 zend_bool cookie_secure;
196 zend_bool cookie_httponly; 196 zend_bool cookie_httponly;
197 ps_module *mod; 197 ps_module *mod;
198 void *mod_data; 198 void *mod_data;
199 php_session_status session_status; 199 php_session_status session_status;
200 long gc_probability; 200 long gc_probability;
201 long gc_divisor; 201 long gc_divisor;
202 long gc_maxlifetime; 202 long gc_maxlifetime;
203 int module_number; 203 int module_number;
204 long cache_expire; 204 long cache_expire;
205 union { 205 union {
206 zval *names[6]; 206 zval *names[6];
207 struct { 207 struct {
208 zval *ps_open; 208 zval *ps_open;
209 zval *ps_close; 209 zval *ps_close;
210 zval *ps_read; 210 zval *ps_read;
211 zval *ps_write; 211 zval *ps_write;
212 zval *ps_destroy; 212 zval *ps_destroy;
213 zval *ps_gc; 213 zval *ps_gc;
214 } name; 214 } name;
215 } mod_user_names; 215 } mod_user_names;
216 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ 216 zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */
217 zend_bool bug_compat_warn; /* Whether to warn about it */ 217 zend_bool bug_compat_warn; /* Whether to warn about it */
218 const struct ps_serializer_struct *serializer; 218 const struct ps_serializer_struct *serializer;
219 zval *http_session_vars; 219 zval *http_session_vars;
220 zend_bool auto_start; 220 zend_bool auto_start;
221 zend_bool use_cookies; 221 zend_bool use_cookies;
222 zend_bool use_only_cookies; 222 zend_bool use_only_cookies;
223 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ 223 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
224 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ 224 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
225 225
226 long hash_func; 226 long hash_func;
227#if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) 227#if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
228 php_hash_ops *hash_ops; 228 php_hash_ops *hash_ops;
229#endif 229#endif
230 long hash_bits_per_character; 230 long hash_bits_per_character;
231 int send_cookie; 231 int send_cookie;
232 int define_sid; 232 int define_sid;
233 zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ 233 zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */
234} php_ps_globals_53; 234} php_ps_globals_53;
235 235
236#ifdef ZTS 236#ifdef ZTS
@@ -263,52 +263,52 @@ static php_ps_globals_43_44 *session_globals = NULL;
263 263
264ps_serializer *(*suhosin_find_ps_serializer)(char *name TSRMLS_DC) = NULL; 264ps_serializer *(*suhosin_find_ps_serializer)(char *name TSRMLS_DC) = NULL;
265 265
266#define PS_ENCODE_VARS \ 266#define PS_ENCODE_VARS \
267 char *key; \ 267 char *key; \
268 uint key_length; \ 268 uint key_length; \
269 ulong num_key; \ 269 ulong num_key; \
270 zval **struc; 270 zval **struc;
271 271
272#define PS_ENCODE_LOOP(code) do { \ 272#define PS_ENCODE_LOOP(code) do { \
273 HashTable *_ht = Z_ARRVAL_P(SESSION_G(http_session_vars)); \ 273 HashTable *_ht = Z_ARRVAL_P(SESSION_G(http_session_vars)); \
274 int key_type; \ 274 int key_type; \
275 \ 275 \
276 for (zend_hash_internal_pointer_reset(_ht); \ 276 for (zend_hash_internal_pointer_reset(_ht); \
277 (key_type = zend_hash_get_current_key_ex(_ht, &key, &key_length, &num_key, 0, NULL)) != HASH_KEY_NON_EXISTANT; \ 277 (key_type = zend_hash_get_current_key_ex(_ht, &key, &key_length, &num_key, 0, NULL)) != HASH_KEY_NON_EXISTANT; \
278 zend_hash_move_forward(_ht)) { \ 278 zend_hash_move_forward(_ht)) { \
279 if (key_type == HASH_KEY_IS_LONG) { \ 279 if (key_type == HASH_KEY_IS_LONG) { \
280 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric key %ld", num_key); \ 280 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric key %ld", num_key); \
281 continue; \ 281 continue; \
282 } \ 282 } \
283 key_length--; \ 283 key_length--; \
284 if (suhosin_get_session_var(key, key_length, &struc TSRMLS_CC) == SUCCESS) { \ 284 if (suhosin_get_session_var(key, key_length, &struc TSRMLS_CC) == SUCCESS) { \
285 code; \ 285 code; \
286 } \ 286 } \
287 } \ 287 } \
288 } while(0) 288 } while(0)
289 289
290static int suhosin_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) /* {{{ */ 290static int suhosin_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) /* {{{ */
291{ 291{
292 int ret = FAILURE; 292 int ret = FAILURE;
293 293
294 if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { 294 if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) {
295 ret = zend_hash_find(Z_ARRVAL_P(SESSION_G(http_session_vars)), name, namelen + 1, (void **) state_var); 295 ret = zend_hash_find(Z_ARRVAL_P(SESSION_G(http_session_vars)), name, namelen + 1, (void **) state_var);
296 296
297 /* If register_globals is enabled, and 297 /* If register_globals is enabled, and
298 * if there is an entry for the slot in $_SESSION, and 298 * if there is an entry for the slot in $_SESSION, and
299 * if that entry is still set to NULL, and 299 * if that entry is still set to NULL, and
300 * if the global var exists, then 300 * if the global var exists, then
301 * we prefer the same key in the global sym table. */ 301 * we prefer the same key in the global sym table. */
302 302
303 if (PG(register_globals) && ret == SUCCESS && Z_TYPE_PP(*state_var) == IS_NULL) { 303 if (PG(register_globals) && ret == SUCCESS && Z_TYPE_PP(*state_var) == IS_NULL) {
304 zval **tmp; 304 zval **tmp;
305 305
306 if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { 306 if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) {
307 *state_var = tmp; 307 *state_var = tmp;
308 } 308 }
309 } 309 }
310 } 310 }
311 return ret; 311 return ret;
312} 312}
313 313
314#define PS_DELIMITER '|' 314#define PS_DELIMITER '|'
@@ -316,148 +316,148 @@ static int suhosin_get_session_var(char *name, size_t namelen, zval ***state_var
316 316
317int suhosin_session_encode(char **newstr, int *newlen TSRMLS_DC) 317int suhosin_session_encode(char **newstr, int *newlen TSRMLS_DC)
318{ 318{
319 smart_str buf = {0}; 319 smart_str buf = {0};
320 php_serialize_data_t var_hash; 320 php_serialize_data_t var_hash;
321 PS_ENCODE_VARS; 321 PS_ENCODE_VARS;
322 322
323 PHP_VAR_SERIALIZE_INIT(var_hash); 323 PHP_VAR_SERIALIZE_INIT(var_hash);
324 324
325 PS_ENCODE_LOOP( 325 PS_ENCODE_LOOP(
326 smart_str_appendl(&buf, key, key_length); 326 smart_str_appendl(&buf, key, key_length);
327 if (key[0] == PS_UNDEF_MARKER || memchr(key, PS_DELIMITER, key_length)) { 327 if (key[0] == PS_UNDEF_MARKER || memchr(key, PS_DELIMITER, key_length)) {
328 PHP_VAR_SERIALIZE_DESTROY(var_hash); 328 PHP_VAR_SERIALIZE_DESTROY(var_hash);
329 smart_str_free(&buf); 329 smart_str_free(&buf);
330 return FAILURE; 330 return FAILURE;
331 } 331 }
332 smart_str_appendc(&buf, PS_DELIMITER); 332 smart_str_appendc(&buf, PS_DELIMITER);
333 333
334 php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); 334 php_var_serialize(&buf, struc, &var_hash TSRMLS_CC);
335 } else { 335 } else {
336 smart_str_appendc(&buf, PS_UNDEF_MARKER); 336 smart_str_appendc(&buf, PS_UNDEF_MARKER);
337 smart_str_appendl(&buf, key, key_length); 337 smart_str_appendl(&buf, key, key_length);
338 smart_str_appendc(&buf, PS_DELIMITER); 338 smart_str_appendc(&buf, PS_DELIMITER);
339 ); 339 );
340 340
341 if (newlen) { 341 if (newlen) {
342 *newlen = buf.len; 342 *newlen = buf.len;
343 } 343 }
344 smart_str_0(&buf); 344 smart_str_0(&buf);
345 *newstr = buf.c; 345 *newstr = buf.c;
346 346
347 PHP_VAR_SERIALIZE_DESTROY(var_hash); 347 PHP_VAR_SERIALIZE_DESTROY(var_hash);
348 return SUCCESS; 348 return SUCCESS;
349} 349}
350 350
351static void suhosin_send_cookie(TSRMLS_D) 351static void suhosin_send_cookie(TSRMLS_D)
352{ 352{
353 int * session_send_cookie = &SESSION_G(send_cookie); 353 int * session_send_cookie = &SESSION_G(send_cookie);
354 char * base; 354 char * base;
355 zend_ini_entry *ini_entry; 355 zend_ini_entry *ini_entry;
356 356
357 /* The following is requires to be 100% compatible to PHP 357 /* The following is requires to be 100% compatible to PHP
358 versions where the hash extension is not available by default */ 358 versions where the hash extension is not available by default */
359#if (PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3) 359#if (PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3)
360 if (zend_hash_find(EG(ini_directives), "session.hash_bits_per_character", sizeof("session.hash_bits_per_character"), (void **) &ini_entry) == SUCCESS) { 360 if (zend_hash_find(EG(ini_directives), "session.hash_bits_per_character", sizeof("session.hash_bits_per_character"), (void **) &ini_entry) == SUCCESS) {
361#ifndef ZTS 361#ifndef ZTS
362 base = (char *) ini_entry->mh_arg2; 362 base = (char *) ini_entry->mh_arg2;
363#else 363#else
364 base = (char *) ts_resource(*((int *) ini_entry->mh_arg2)); 364 base = (char *) ts_resource(*((int *) ini_entry->mh_arg2));
365#endif 365#endif
366 session_send_cookie = (int *) (base+(size_t) ini_entry->mh_arg1+sizeof(long)); 366 session_send_cookie = (int *) (base+(size_t) ini_entry->mh_arg1+sizeof(long));
367 } 367 }
368#endif 368#endif
369 *session_send_cookie = 1; 369 *session_send_cookie = 1;
370} 370}
371 371
372void suhosin_get_ipv4(char *buf TSRMLS_DC) 372void suhosin_get_ipv4(char *buf TSRMLS_DC)
373{ 373{
374 char *raddr = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); 374 char *raddr = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
375 int i; 375 int i;
376 376
377 377
378 if (raddr == NULL) { 378 if (raddr == NULL) {
379 memset(buf, 0, 4); 379 memset(buf, 0, 4);
380 return; 380 return;
381 } 381 }
382 382
383 for (i=0; i<4; i++) { 383 for (i=0; i<4; i++) {
384 if (raddr[0] == 0) { 384 if (raddr[0] == 0) {
385 buf[i] = 0; 385 buf[i] = 0;
386 } else { 386 } else {
387 buf[i] = strtol(raddr, &raddr, 10); 387 buf[i] = strtol(raddr, &raddr, 10);
388 if (raddr[0] == '.') { 388 if (raddr[0] == '.') {
389 raddr++; 389 raddr++;
390 } 390 }
391 } 391 }
392 } 392 }
393} 393}
394 394
395char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC) 395char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC)
396{ 396{
397 int padded_len, i, slen; 397 int padded_len, i, slen;
398 unsigned char *crypted, *tmp; 398 unsigned char *crypted, *tmp;
399 unsigned int check = 0x13579BDF; 399 unsigned int check = 0x13579BDF;
400 400
401 if (str == NULL) { 401 if (str == NULL) {
402 return NULL; 402 return NULL;
403 }
404 if (len == 0) {
405 return estrndup("", 0);
403 } 406 }
404 if (len == 0) {
405 return estrndup("", 0);
406 }
407 407
408 408
409 suhosin_aes_gkey(4,8,key TSRMLS_CC); 409 suhosin_aes_gkey(4,8,key TSRMLS_CC);
410 410
411 padded_len = ((len+15) & ~0xF); 411 padded_len = ((len+15) & ~0xF);
412 crypted = emalloc(16+padded_len+1); 412 crypted = emalloc(16+padded_len+1);
413 memset(crypted, 0xff, 16+padded_len+1); 413 memset(crypted, 0xff, 16+padded_len+1);
414 memcpy(crypted+16, str, len+1); 414 memcpy(crypted+16, str, len+1);
415 415
416 /* calculate check value */ 416 /* calculate check value */
417 for (i = 0; i<vlen; i++) { 417 for (i = 0; i<vlen; i++) {
418 check = (check << 3) | (check >> (32-3)); 418 check = (check << 3) | (check >> (32-3));
419 check += check << 1; 419 check += check << 1;
420 check ^= (unsigned char)var[i]; 420 check ^= (unsigned char)var[i];
421 } 421 }
422 for (i = 0; i<len; i++) { 422 for (i = 0; i<len; i++) {
423 check = (check << 3) | (check >> (32-3)); 423 check = (check << 3) | (check >> (32-3));
424 check += check << 1; 424 check += check << 1;
425 check ^= (unsigned char)str[i]; 425 check ^= (unsigned char)str[i];
426 } 426 }
427 427
428 /* store ip value */ 428 /* store ip value */
429 suhosin_get_ipv4(crypted+4 TSRMLS_CC); 429 suhosin_get_ipv4(crypted+4 TSRMLS_CC);
430 430
431 /* store check value */ 431 /* store check value */
432 crypted[8] = check & 0xff; 432 crypted[8] = check & 0xff;
433 crypted[9] = (check >> 8) & 0xff; 433 crypted[9] = (check >> 8) & 0xff;
434 crypted[10] = (check >> 16) & 0xff; 434 crypted[10] = (check >> 16) & 0xff;
435 crypted[11] = (check >> 24) & 0xff; 435 crypted[11] = (check >> 24) & 0xff;
436 436
437 /* store original length */ 437 /* store original length */
438 crypted[12] = len & 0xff; 438 crypted[12] = len & 0xff;
439 crypted[13] = (len >> 8) & 0xff; 439 crypted[13] = (len >> 8) & 0xff;
440 crypted[14] = (len >> 16) & 0xff; 440 crypted[14] = (len >> 16) & 0xff;
441 crypted[15] = (len >> 24) & 0xff; 441 crypted[15] = (len >> 24) & 0xff;
442 442
443 for (i=0, tmp=crypted; i<padded_len+16; i+=16, tmp+=16) { 443 for (i=0, tmp=crypted; i<padded_len+16; i+=16, tmp+=16) {
444 if (i > 0) { 444 if (i > 0) {
445 int j; 445 int j;
446 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16]; 446 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
447 } 447 }
448 suhosin_aes_encrypt((char *)tmp TSRMLS_CC); 448 suhosin_aes_encrypt((char *)tmp TSRMLS_CC);
449 } 449 }
450 450
451 tmp = php_base64_encode(crypted, padded_len+16, NULL); 451 tmp = php_base64_encode(crypted, padded_len+16, NULL);
452 efree(crypted); 452 efree(crypted);
453 slen=strlen((char *)tmp); 453 slen=strlen((char *)tmp);
454 for (i=0; i<slen; i++) { 454 for (i=0; i<slen; i++) {
455 switch (tmp[i]) { 455 switch (tmp[i]) {
456 case '/': tmp[i]='-'; break; 456 case '/': tmp[i]='-'; break;
457 case '=': tmp[i]='.'; break; 457 case '=': tmp[i]='.'; break;
458 case '+': tmp[i]='_'; break; 458 case '+': tmp[i]='_'; break;
459 } 459 }
460 } 460 }
461 return (char *)tmp; 461 return (char *)tmp;
462} 462}
463 463
@@ -465,162 +465,162 @@ char *suhosin_decrypt_string(char *str, int padded_len, char *var, int vlen, cha
465{ 465{
466 int len, i, o_len, invalid = 0; 466 int len, i, o_len, invalid = 0;
467 unsigned char *decrypted, *tmp; 467 unsigned char *decrypted, *tmp;
468 unsigned int check = 0x13579BDF; 468 unsigned int check = 0x13579BDF;
469 char buf[4]; 469 char buf[4];
470 470
471 if (str == NULL) { 471 if (str == NULL) {
472 return NULL; 472 return NULL;
473 }
474
475 if (padded_len == 0) {
476 if (orig_len) {
477 *orig_len = 0;
478 }
479 return estrndup("", 0);
473 } 480 }
474
475 if (padded_len == 0) {
476 if (orig_len) {
477 *orig_len = 0;
478 }
479 return estrndup("", 0);
480 }
481 suhosin_aes_gkey(4,8,key TSRMLS_CC); 481 suhosin_aes_gkey(4,8,key TSRMLS_CC);
482 482
483 for (i=0; i<padded_len; i++) { 483 for (i=0; i<padded_len; i++) {
484 switch (str[i]) { 484 switch (str[i]) {
485 case '-': str[i]='/'; break; 485 case '-': str[i]='/'; break;
486 case '.': str[i]='='; break; 486 case '.': str[i]='='; break;
487 case '_': str[i]='+'; break; 487 case '_': str[i]='+'; break;
488 } 488 }
489 } 489 }
490 490
491 decrypted = php_base64_decode((unsigned char *)str, padded_len, &len); 491 decrypted = php_base64_decode((unsigned char *)str, padded_len, &len);
492 if (decrypted == NULL || len < 2*16 || (len % 16) != 0) { 492 if (decrypted == NULL || len < 2*16 || (len % 16) != 0) {
493error_out: 493error_out:
494 if (decrypted != NULL) { 494 if (decrypted != NULL) {
495 efree(decrypted); 495 efree(decrypted);
496 } 496 }
497 if (orig_len) { 497 if (orig_len) {
498 *orig_len = 0; 498 *orig_len = 0;
499 }
500 return NULL;
501 }
502
503 for (i=len-16, tmp=decrypted+i; i>=0; i-=16, tmp-=16) {
504 suhosin_aes_decrypt((char *)tmp TSRMLS_CC);
505 if (i > 0) {
506 int j;
507 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
508 } 499 }
500 return NULL;
501 }
502
503 for (i=len-16, tmp=decrypted+i; i>=0; i-=16, tmp-=16) {
504 suhosin_aes_decrypt((char *)tmp TSRMLS_CC);
505 if (i > 0) {
506 int j;
507 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
508 }
509 }
510
511 /* retrieve orig_len */
512 o_len = decrypted[15];
513 o_len <<= 8;
514 o_len |= decrypted[14];
515 o_len <<= 8;
516 o_len |= decrypted[13];
517 o_len <<= 8;
518 o_len |= decrypted[12];
519
520 if (o_len < 0 || o_len > len-16) {
521 goto error_out;
509 } 522 }
510
511 /* retrieve orig_len */
512 o_len = decrypted[15];
513 o_len <<= 8;
514 o_len |= decrypted[14];
515 o_len <<= 8;
516 o_len |= decrypted[13];
517 o_len <<= 8;
518 o_len |= decrypted[12];
519
520 if (o_len < 0 || o_len > len-16) {
521 goto error_out;
522 }
523 523
524 /* calculate check value */ 524 /* calculate check value */
525 for (i = 0; i<vlen; i++) { 525 for (i = 0; i<vlen; i++) {
526 check = (check << 3) | (check >> (32-3)); 526 check = (check << 3) | (check >> (32-3));
527 check += check << 1; 527 check += check << 1;
528 check ^= (unsigned char)var[i]; 528 check ^= (unsigned char)var[i];
529 } 529 }
530 for (i = 0; i<o_len; i++) { 530 for (i = 0; i<o_len; i++) {
531 check = (check << 3) | (check >> (32-3)); 531 check = (check << 3) | (check >> (32-3));
532 check += check << 1; 532 check += check << 1;
533 check ^= decrypted[16+i]; 533 check ^= decrypted[16+i];
534 } 534 }
535 535
536 /* check value */ 536 /* check value */
537 invalid = (decrypted[8] != (check & 0xff)) || 537 invalid = (decrypted[8] != (check & 0xff)) ||
538 (decrypted[9] != ((check >> 8) & 0xff)) || 538 (decrypted[9] != ((check >> 8) & 0xff)) ||
539 (decrypted[10] != ((check >> 16) & 0xff)) || 539 (decrypted[10] != ((check >> 16) & 0xff)) ||
540 (decrypted[11] != ((check >> 24) & 0xff)); 540 (decrypted[11] != ((check >> 24) & 0xff));
541 541
542 /* check IP */ 542 /* check IP */
543 if (check_ra > 0) { 543 if (check_ra > 0) {
544 if (check_ra > 4) { 544 if (check_ra > 4) {
545 check_ra = 4; 545 check_ra = 4;
546 } 546 }
547 suhosin_get_ipv4(&buf TSRMLS_CC); 547 suhosin_get_ipv4(&buf TSRMLS_CC);
548 if (memcmp(buf, decrypted+4, check_ra) != 0) { 548 if (memcmp(buf, decrypted+4, check_ra) != 0) {
549 goto error_out; 549 goto error_out;
550 } 550 }
551 } 551 }
552 552
553 if (invalid) { 553 if (invalid) {
554 goto error_out; 554 goto error_out;
555 } 555 }
556 556
557 if (orig_len) { 557 if (orig_len) {
558 *orig_len = o_len; 558 *orig_len = o_len;
559 } 559 }
560 560
561 memmove(decrypted, decrypted+16, o_len); 561 memmove(decrypted, decrypted+16, o_len);
562 decrypted[o_len] = 0; 562 decrypted[o_len] = 0;
563 /* we do not realloc() here because 16 byte less 563 /* we do not realloc() here because 16 byte less
564 is simply not worth the overhead */ 564 is simply not worth the overhead */
565 return (char *)decrypted; 565 return (char *)decrypted;
566} 566}
567 567
568char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC) 568char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC)
569{ 569{
570 char *_ua = NULL; 570 char *_ua = NULL;
571 char *_dr = NULL; 571 char *_dr = NULL;
572 char *_ra = NULL; 572 char *_ra = NULL;
573 suhosin_SHA256_CTX ctx; 573 suhosin_SHA256_CTX ctx;
574 574
575 if (ua) { 575 if (ua) {
576 _ua = sapi_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC); 576 _ua = sapi_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC);
577 } 577 }
578 578
579 if (dr) { 579 if (dr) {
580 _dr = sapi_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); 580 _dr = sapi_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
581 } 581 }
582 582
583 if (raddr > 0) { 583 if (raddr > 0) {
584 _ra = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); 584 _ra = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
585 } 585 }
586 586
587 SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra); 587 SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra);
588 588
589 suhosin_SHA256Init(&ctx); 589 suhosin_SHA256Init(&ctx);
590 if (key == NULL) { 590 if (key == NULL) {
591 suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", sizeof("D3F4UL7")); 591 suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", sizeof("D3F4UL7"));
592 } else { 592 } else {
593 suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key)); 593 suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key));
594 } 594 }
595 if (_ua) { 595 if (_ua) {
596 suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua)); 596 suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua));
597 } 597 }
598 if (_dr) { 598 if (_dr) {
599 suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr)); 599 suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr));
600 } 600 }
601 if (_ra) { 601 if (_ra) {
602 if (raddr >= 4) { 602 if (raddr >= 4) {
603 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra)); 603 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra));
604 } else { 604 } else {
605 long dots = 0; 605 long dots = 0;
606 char *tmp = _ra; 606 char *tmp = _ra;
607 607
608 while (*tmp) { 608 while (*tmp) {
609 if (*tmp == '.') { 609 if (*tmp == '.') {
610 dots++; 610 dots++;
611 if (dots == raddr) { 611 if (dots == raddr) {
612 break; 612 break;
613 } 613 }
614 } 614 }
615 tmp++; 615 tmp++;
616 } 616 }
617 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra); 617 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra);
618 } 618 }
619 } 619 }
620 suhosin_SHA256Final((unsigned char *)cryptkey, &ctx); 620 suhosin_SHA256Final((unsigned char *)cryptkey, &ctx);
621 cryptkey[32] = 0; /* uhmm... not really a string */ 621 cryptkey[32] = 0; /* uhmm... not really a string */
622 622
623 return cryptkey; 623 return cryptkey;
624} 624}
625 625
626 626
@@ -629,270 +629,270 @@ static int (*old_SessionRINIT)(INIT_FUNC_ARGS) = NULL;
629 629
630static int suhosin_hook_s_read(void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC) 630static int suhosin_hook_s_read(void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC)
631{ 631{
632 int r; 632 int r;
633 633
634 int i;char *v,*KEY=(char *)key; 634 int i;char *v,*KEY=(char *)key;
635 635
636 /* protect session vars */ 636 /* protect session vars */
637/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { 637/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) {
638 SESSION_G(http_session_vars)->refcount++; 638 SESSION_G(http_session_vars)->refcount++;
639 }*/ 639 }*/
640 640
641 /* protect dumb session handlers */ 641 /* protect dumb session handlers */
642 if (key == NULL || !key[0] || *mod_data == NULL) { 642 if (key == NULL || !key[0] || *mod_data == NULL) {
643regenerate: 643regenerate:
644 SDEBUG("regenerating key is %s", key); 644 SDEBUG("regenerating key is %s", key);
645 KEY = SESSION_G(id) = SESSION_G(mod)->s_create_sid(&SESSION_G(mod_data), NULL TSRMLS_CC); 645 KEY = SESSION_G(id) = SESSION_G(mod)->s_create_sid(&SESSION_G(mod_data), NULL TSRMLS_CC);
646 suhosin_send_cookie(TSRMLS_C); 646 suhosin_send_cookie(TSRMLS_C);
647 } else if (strlen(key) > SUHOSIN_G(session_max_id_length)) { 647 } else if (strlen(key) > SUHOSIN_G(session_max_id_length)) {
648 suhosin_log(S_SESSION, "session id ('%s') exceeds maximum length - regenerating", KEY); 648 suhosin_log(S_SESSION, "session id ('%s') exceeds maximum length - regenerating", KEY);
649 if (!SUHOSIN_G(simulation)) { 649 if (!SUHOSIN_G(simulation)) {
650 goto regenerate; 650 goto regenerate;
651 } 651 }
652 } 652 }
653#if (PHP_MAJOR_VERSION < 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) 653#if (PHP_MAJOR_VERSION < 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2)
654 else if (strpbrk(KEY, "\r\n\t <>'\"\\")) { 654 else if (strpbrk(KEY, "\r\n\t <>'\"\\")) {
655 suhosin_log(S_SESSION, "session id ('%s') contains invalid chars - regenerating", KEY); 655 suhosin_log(S_SESSION, "session id ('%s') contains invalid chars - regenerating", KEY);
656 if (!SUHOSIN_G(simulation)) { 656 if (!SUHOSIN_G(simulation)) {
657 goto regenerate; 657 goto regenerate;
658 } 658 }
659 } 659 }
660#endif 660#endif
661 661
662 r = SUHOSIN_G(old_s_read)(mod_data, KEY, val, vallen TSRMLS_CC); 662 r = SUHOSIN_G(old_s_read)(mod_data, KEY, val, vallen TSRMLS_CC);
663 663
664 if (r == SUCCESS && SUHOSIN_G(session_encrypt) && *vallen > 0) { 664 if (r == SUCCESS && SUHOSIN_G(session_encrypt) && *vallen > 0) {
665 char cryptkey[33]; 665 char cryptkey[33];
666 666
667 SUHOSIN_G(do_not_scan) = 1; 667 SUHOSIN_G(do_not_scan) = 1;
668 suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); 668 suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC);
669 669
670 v = *val; 670 v = *val;
671 i = *vallen; 671 i = *vallen;
672 *val = suhosin_decrypt_string(v, i, "", 0, (char *)&cryptkey, vallen, SUHOSIN_G(session_checkraddr) TSRMLS_CC); 672 *val = suhosin_decrypt_string(v, i, "", 0, (char *)&cryptkey, vallen, SUHOSIN_G(session_checkraddr) TSRMLS_CC);
673 SUHOSIN_G(do_not_scan) = 0; 673 SUHOSIN_G(do_not_scan) = 0;
674 if (*val == NULL) { 674 if (*val == NULL) {
675 *val = estrndup("", 0); 675 *val = estrndup("", 0);
676 *vallen = 0; 676 *vallen = 0;
677 } 677 }
678 efree(v); 678 efree(v);
679 } 679 }
680 680
681 return r; 681 return r;
682} 682}
683 683
684static int suhosin_hook_s_write(void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC) 684static int suhosin_hook_s_write(void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC)
685{ 685{
686 int r; 686 int r;
687/* int nullify = 0;*/ 687/* int nullify = 0;*/
688 char *v = (char *)val; 688 char *v = (char *)val;
689 689
690 /* protect dumb session handlers */ 690 /* protect dumb session handlers */
691 if (key == NULL || !key[0] || val == NULL || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { 691 if (key == NULL || !key[0] || val == NULL || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) {
692 r = FAILURE; 692 r = FAILURE;
693 goto return_write; 693 goto return_write;
694 } 694 }
695 695
696 r = vallen; 696 r = vallen;
697 697
698 if (r > 0 && SUHOSIN_G(session_encrypt)) { 698 if (r > 0 && SUHOSIN_G(session_encrypt)) {
699 char cryptkey[33]; 699 char cryptkey[33];
700 700
701 SUHOSIN_G(do_not_scan) = 1; 701 SUHOSIN_G(do_not_scan) = 1;
702 702
703 suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); 703 suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC);
704 704
705 v = suhosin_encrypt_string(v, vallen, "", 0, (char *)&cryptkey TSRMLS_CC); 705 v = suhosin_encrypt_string(v, vallen, "", 0, (char *)&cryptkey TSRMLS_CC);
706 706
707 SUHOSIN_G(do_not_scan) = 0; 707 SUHOSIN_G(do_not_scan) = 0;
708 r = strlen(v); 708 r = strlen(v);
709 } 709 }
710 710
711 r = SUHOSIN_G(old_s_write)(mod_data, key, v, r TSRMLS_CC); 711 r = SUHOSIN_G(old_s_write)(mod_data, key, v, r TSRMLS_CC);
712 712
713return_write: 713return_write:
714 /* protect session vars */ 714 /* protect session vars */
715/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { 715/* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) {
716 if (SESSION_G(http_session_vars)->refcount==1) { 716 if (SESSION_G(http_session_vars)->refcount==1) {
717 nullify = 1; 717 nullify = 1;
718 } 718 }
719 zval_ptr_dtor(&SESSION_G(http_session_vars)); 719 zval_ptr_dtor(&SESSION_G(http_session_vars));
720 if (nullify) { 720 if (nullify) {
721 suhosin_log(S_SESSION, "possible session variables double free attack stopped"); 721 suhosin_log(S_SESSION, "possible session variables double free attack stopped");
722 SESSION_G(http_session_vars) = NULL; 722 SESSION_G(http_session_vars) = NULL;
723 } 723 }
724 }*/ 724 }*/
725 725
726 return r; 726 return r;
727} 727}
728 728
729static int suhosin_hook_s_destroy(void **mod_data, const char *key TSRMLS_DC) 729static int suhosin_hook_s_destroy(void **mod_data, const char *key TSRMLS_DC)
730{ 730{
731 int r; 731 int r;
732 732
733 /* protect dumb session handlers */ 733 /* protect dumb session handlers */
734 if (key == NULL || !key[0] || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { 734 if (key == NULL || !key[0] || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) {
735 return FAILURE; 735 return FAILURE;
736 } 736 }
737 737
738 r = SUHOSIN_G(old_s_destroy)(mod_data, key TSRMLS_CC); 738 r = SUHOSIN_G(old_s_destroy)(mod_data, key TSRMLS_CC);
739 739
740 return r; 740 return r;
741} 741}
742 742
743static void suhosin_hook_session_module(TSRMLS_D) 743static void suhosin_hook_session_module(TSRMLS_D)
744{ 744{
745 ps_module *old_mod = SESSION_G(mod), *mod; 745 ps_module *old_mod = SESSION_G(mod), *mod;
746 746
747 if (old_mod == NULL || SUHOSIN_G(s_module) == old_mod) { 747 if (old_mod == NULL || SUHOSIN_G(s_module) == old_mod) {
748 return; 748 return;
749 } 749 }
750 if (SUHOSIN_G(s_module) == NULL) { 750 if (SUHOSIN_G(s_module) == NULL) {
751 SUHOSIN_G(s_module) = mod = malloc(sizeof(ps_module)); 751 SUHOSIN_G(s_module) = mod = malloc(sizeof(ps_module));
752 if (mod == NULL) { 752 if (mod == NULL) {
753 return; 753 return;
754 } 754 }
755 } 755 }
756 mod = SUHOSIN_G(s_module); 756 mod = SUHOSIN_G(s_module);
757 memcpy(mod, old_mod, sizeof(ps_module)); 757 memcpy(mod, old_mod, sizeof(ps_module));
758 758
759 SUHOSIN_G(old_s_read) = mod->s_read; 759 SUHOSIN_G(old_s_read) = mod->s_read;
760 mod->s_read = suhosin_hook_s_read; 760 mod->s_read = suhosin_hook_s_read;
761 SUHOSIN_G(old_s_write) = mod->s_write; 761 SUHOSIN_G(old_s_write) = mod->s_write;
762 mod->s_write = suhosin_hook_s_write; 762 mod->s_write = suhosin_hook_s_write;
763 SUHOSIN_G(old_s_destroy) = mod->s_destroy; 763 SUHOSIN_G(old_s_destroy) = mod->s_destroy;
764 mod->s_destroy = suhosin_hook_s_destroy; 764 mod->s_destroy = suhosin_hook_s_destroy;
765 765
766 SESSION_G(mod) = mod; 766 SESSION_G(mod) = mod;
767} 767}
768 768
769static PHP_INI_MH(suhosin_OnUpdateSaveHandler) 769static PHP_INI_MH(suhosin_OnUpdateSaveHandler)
770{ 770{
771 int r; 771 int r;
772 772
773 r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); 773 r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
774 774
775 suhosin_hook_session_module(TSRMLS_C); 775 suhosin_hook_session_module(TSRMLS_C);
776 776
777 return r; 777 return r;
778} 778}
779 779
780 780
781static int suhosin_hook_session_RINIT(INIT_FUNC_ARGS) 781static int suhosin_hook_session_RINIT(INIT_FUNC_ARGS)
782{ 782{
783 if (SESSION_G(mod) == NULL) { 783 if (SESSION_G(mod) == NULL) {
784 char *value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); 784 char *value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0);
785 785
786 if (value) { 786 if (value) {
787 suhosin_OnUpdateSaveHandler(NULL, value, strlen(value), NULL, NULL, NULL, 0 TSRMLS_CC); 787 suhosin_OnUpdateSaveHandler(NULL, value, strlen(value), NULL, NULL, NULL, 0 TSRMLS_CC);
788 } 788 }
789 } 789 }
790 return old_SessionRINIT(INIT_FUNC_ARGS_PASSTHRU); 790 return old_SessionRINIT(INIT_FUNC_ARGS_PASSTHRU);
791} 791}
792 792
793void suhosin_hook_session(TSRMLS_D) 793void suhosin_hook_session(TSRMLS_D)
794{ 794{
795 ps_serializer *serializer; 795 ps_serializer *serializer;
796 zend_ini_entry *ini_entry; 796 zend_ini_entry *ini_entry;
797 zend_module_entry *module; 797 zend_module_entry *module;
798#ifdef ZTS 798#ifdef ZTS
799 ts_rsrc_id *ps_globals_id_ptr; 799 ts_rsrc_id *ps_globals_id_ptr;
800#endif 800#endif
801 801
802 if (zend_hash_find(&module_registry, "session", sizeof("session"), (void**)&module) == FAILURE) { 802 if (zend_hash_find(&module_registry, "session", sizeof("session"), (void**)&module) == FAILURE) {
803 return; 803 return;
804 } 804 }
805 /* retrieve globals from module entry struct if possible */ 805 /* retrieve globals from module entry struct if possible */
806#if PHP_VERSION_ID >= 50200 806#if PHP_VERSION_ID >= 50200
807#ifdef ZTS 807#ifdef ZTS
808 if (session_globals_id == 0) { 808 if (session_globals_id == 0) {
809 session_globals_id = *module->globals_id_ptr; 809 session_globals_id = *module->globals_id_ptr;
810 } 810 }
811#else 811#else
812 if (session_globals == NULL) { 812 if (session_globals == NULL) {
813 session_globals = module->globals_ptr; 813 session_globals = module->globals_ptr;
814 } 814 }
815#endif 815#endif
816#else 816#else
817 /* retrieve globals from symbols if PHP version is old */ 817 /* retrieve globals from symbols if PHP version is old */
818#ifdef ZTS 818#ifdef ZTS
819 if (session_globals_id == 0) { 819 if (session_globals_id == 0) {
820 ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "ps_globals_id"); 820 ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "ps_globals_id");
821 if (ps_globals_id_ptr == NULL) { 821 if (ps_globals_id_ptr == NULL) {
822 ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "_ps_globals_id"); 822 ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "_ps_globals_id");
823 } 823 }
824 if (ps_globals_id_ptr == NULL) { 824 if (ps_globals_id_ptr == NULL) {
825 return; 825 return;
826 } 826 }
827 827
828 session_globals_id = *ps_globals_id_ptr; 828 session_globals_id = *ps_globals_id_ptr;
829 } 829 }
830#else 830#else
831 if (session_globals == NULL) { 831 if (session_globals == NULL) {
832 session_globals = DL_FETCH_SYMBOL(module->handle, "ps_globals"); 832 session_globals = DL_FETCH_SYMBOL(module->handle, "ps_globals");
833 if (session_globals == NULL) { 833 if (session_globals == NULL) {
834 session_globals = DL_FETCH_SYMBOL(module->handle, "_ps_globals"); 834 session_globals = DL_FETCH_SYMBOL(module->handle, "_ps_globals");
835 } 835 }
836 if (session_globals == NULL) { 836 if (session_globals == NULL) {
837 return; 837 return;
838 } 838 }
839 } 839 }
840#endif 840#endif
841#endif 841#endif
842 if (old_OnUpdateSaveHandler != NULL) { 842 if (old_OnUpdateSaveHandler != NULL) {
843 return; 843 return;
844 } 844 }
845 845
846 /* hook request startup function of session module */ 846 /* hook request startup function of session module */
847 old_SessionRINIT = module->request_startup_func; 847 old_SessionRINIT = module->request_startup_func;
848 module->request_startup_func = suhosin_hook_session_RINIT; 848 module->request_startup_func = suhosin_hook_session_RINIT;
849 849
850 /* retrieve pointer to session.save_handler ini entry */ 850 /* retrieve pointer to session.save_handler ini entry */
851 if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { 851 if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) {
852 return; 852 return;
853 } 853 }
854 SUHOSIN_G(s_module) = NULL; 854 SUHOSIN_G(s_module) = NULL;
855 855
856 /* replace OnUpdateMemoryLimit handler */ 856 /* replace OnUpdateMemoryLimit handler */
857 old_OnUpdateSaveHandler = ini_entry->on_modify; 857 old_OnUpdateSaveHandler = ini_entry->on_modify;
858 ini_entry->on_modify = suhosin_OnUpdateSaveHandler; 858 ini_entry->on_modify = suhosin_OnUpdateSaveHandler;
859 859
860 suhosin_hook_session_module(TSRMLS_C); 860 suhosin_hook_session_module(TSRMLS_C);
861 861
862 /* Protect the PHP serializer from ! attacks */ 862 /* Protect the PHP serializer from ! attacks */
863# if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) 863# if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2)
864 serializer = SESSION_G(serializer); 864 serializer = SESSION_G(serializer);
865 if (serializer != NULL && strcmp(serializer->name, "php")==0) { 865 if (serializer != NULL && strcmp(serializer->name, "php")==0) {
866 serializer->encode = suhosin_session_encode; 866 serializer->encode = suhosin_session_encode;
867 } 867 }
868#endif 868#endif
869 869
870 /* increase session identifier entropy */ 870 /* increase session identifier entropy */
871 if (SESSION_G(entropy_length) == 0 || SESSION_G(entropy_file) == NULL) { 871 if (SESSION_G(entropy_length) == 0 || SESSION_G(entropy_file) == NULL) {
872 872
873 /* ensure that /dev/urandom exists */ 873 /* ensure that /dev/urandom exists */
874 int fd = VCWD_OPEN("/dev/urandom", O_RDONLY); 874 int fd = VCWD_OPEN("/dev/urandom", O_RDONLY);
875 if (fd >= 0) { 875 if (fd >= 0) {
876 close(fd); 876 close(fd);
877 SESSION_G(entropy_length) = 16; 877 SESSION_G(entropy_length) = 16;
878 SESSION_G(entropy_file) = pestrdup("/dev/urandom", 1); 878 SESSION_G(entropy_file) = pestrdup("/dev/urandom", 1);
879 }
880 } 879 }
880 }
881} 881}
882 882
883void suhosin_unhook_session(TSRMLS_D) 883void suhosin_unhook_session(TSRMLS_D)
884{ 884{
885 if (old_OnUpdateSaveHandler != NULL) { 885 if (old_OnUpdateSaveHandler != NULL) {
886 zend_ini_entry *ini_entry; 886 zend_ini_entry *ini_entry;
887 887
888 /* retrieve pointer to session.save_handler ini entry */ 888 /* retrieve pointer to session.save_handler ini entry */
889 if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { 889 if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) {
890 return; 890 return;
891 } 891 }
892 ini_entry->on_modify = old_OnUpdateSaveHandler; 892 ini_entry->on_modify = old_OnUpdateSaveHandler;
893 893
894 old_OnUpdateSaveHandler = NULL; 894 old_OnUpdateSaveHandler = NULL;
895 } 895 }
896 896
897} 897}
898 898