summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog2
-rw-r--r--config.m42
-rw-r--r--config.w322
-rw-r--r--crypt.c283
-rw-r--r--session.c773
-rw-r--r--suhosin.c8
-rw-r--r--tests/session/session_recursive_crash2.phpt61
7 files changed, 387 insertions, 744 deletions
diff --git a/Changelog b/Changelog
index 449714d..947d2a8 100644
--- a/Changelog
+++ b/Changelog
@@ -17,6 +17,8 @@
17 - Added new array index filter (character whitelist/blacklist) 17 - Added new array index filter (character whitelist/blacklist)
18 - Added option to suppress date/time for suhosin file logging (suhosin.log.file.time=0) 18 - Added option to suppress date/time for suhosin file logging (suhosin.log.file.time=0)
19 - Added simple script to create binary Debian package 19 - Added simple script to create binary Debian package
20 - Fixed additional recursion problems with session handler
21 - Suhosin now depends on php_session.h instead of version-specific struct code
20 22
212014-06-10 - 0.9.36 232014-06-10 - 0.9.36
22 24
diff --git a/config.m4 b/config.m4
index 01edafd..d71514d 100644
--- a/config.m4
+++ b/config.m4
@@ -5,7 +5,7 @@ PHP_ARG_ENABLE(suhosin, whether to enable suhosin support,
5[ --enable-suhosin Enable suhosin support]) 5[ --enable-suhosin Enable suhosin support])
6 6
7if test "$PHP_SUHOSIN" != "no"; then 7if test "$PHP_SUHOSIN" != "no"; then
8 PHP_NEW_EXTENSION(suhosin, suhosin.c sha256.c memory_limit.c treat_data.c ifilter.c post_handler.c ufilter.c rfc1867.c rfc1867_new.c log.c header.c execute.c ex_imp.c session.c aes.c compat_snprintf.c, $ext_shared) 8 PHP_NEW_EXTENSION(suhosin, suhosin.c sha256.c memory_limit.c treat_data.c ifilter.c post_handler.c ufilter.c rfc1867.c rfc1867_new.c log.c header.c execute.c ex_imp.c session.c aes.c compat_snprintf.c crypt.c, $ext_shared)
9fi 9fi
10 10
11PHP_ARG_ENABLE(suhosin-experimental, whether to enable experimental suhosin features, 11PHP_ARG_ENABLE(suhosin-experimental, whether to enable experimental suhosin features,
diff --git a/config.w32 b/config.w32
index 9fc8d41..5fa25bc 100644
--- a/config.w32
+++ b/config.w32
@@ -4,5 +4,5 @@
4ARG_ENABLE("suhosin", "whether to enable suhosin support", "yes"); 4ARG_ENABLE("suhosin", "whether to enable suhosin support", "yes");
5 5
6if (PHP_SUHOSIN == "yes") { 6if (PHP_SUHOSIN == "yes") {
7 EXTENSION("suhosin", "suhosin.c sha256.c memory_limit.c treat_data.c ifilter.c post_handler.c ufilter.c rfc1867.c log.c header.c execute.c ex_imp.c session.c aes.c"); 7 EXTENSION("suhosin", "suhosin.c sha256.c memory_limit.c treat_data.c ifilter.c post_handler.c ufilter.c rfc1867.c rfc1867_new.c log.c header.c execute.c ex_imp.c session.c aes.c crypt.c");
8} 8}
diff --git a/crypt.c b/crypt.c
new file mode 100644
index 0000000..6df306d
--- /dev/null
+++ b/crypt.c
@@ -0,0 +1,283 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2014 SektionEins GmbH |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Authors: Stefan Esser <sesser@sektioneins.de> |
17 | Ben Fuhrmannek <ben.fuhrmannek@sektioneins.de> |
18 +----------------------------------------------------------------------+
19*/
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include "php.h"
26#include "TSRM.h"
27#include "php_suhosin.h"
28#include "ext/standard/base64.h"
29#include "sha256.h"
30
31static void suhosin_get_ipv4(char *buf TSRMLS_DC)
32{
33 char *raddr = suhosin_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
34 int i;
35
36
37 if (raddr == NULL) {
38 memset(buf, 0, 4);
39 return;
40 }
41
42 for (i=0; i<4; i++) {
43 if (raddr[0] == 0) {
44 buf[i] = 0;
45 } else {
46 buf[i] = strtol(raddr, &raddr, 10);
47 if (raddr[0] == '.') {
48 raddr++;
49 }
50 }
51 }
52}
53
54char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC)
55{
56 int padded_len, i, slen;
57 unsigned char *crypted, *tmp;
58 unsigned int check = 0x13579BDF;
59
60 if (str == NULL) {
61 return NULL;
62 }
63 if (len == 0) {
64 return estrndup("", 0);
65 }
66
67
68 suhosin_aes_gkey(4,8,key TSRMLS_CC);
69
70 padded_len = ((len+15) & ~0xF);
71 crypted = emalloc(16+padded_len+1);
72 memset(crypted, 0xff, 16+padded_len+1);
73 memcpy(crypted+16, str, len+1);
74
75 /* calculate check value */
76 for (i = 0; i<vlen; i++) {
77 check = (check << 3) | (check >> (32-3));
78 check += check << 1;
79 check ^= (unsigned char)var[i];
80 }
81 for (i = 0; i<len; i++) {
82 check = (check << 3) | (check >> (32-3));
83 check += check << 1;
84 check ^= (unsigned char)str[i];
85 }
86
87 /* store ip value */
88 suhosin_get_ipv4((char *)crypted+4 TSRMLS_CC);
89
90 /* store check value */
91 crypted[8] = check & 0xff;
92 crypted[9] = (check >> 8) & 0xff;
93 crypted[10] = (check >> 16) & 0xff;
94 crypted[11] = (check >> 24) & 0xff;
95
96 /* store original length */
97 crypted[12] = len & 0xff;
98 crypted[13] = (len >> 8) & 0xff;
99 crypted[14] = (len >> 16) & 0xff;
100 crypted[15] = (len >> 24) & 0xff;
101
102 for (i=0, tmp=crypted; i<padded_len+16; i+=16, tmp+=16) {
103 if (i > 0) {
104 int j;
105 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
106 }
107 suhosin_aes_encrypt((char *)tmp TSRMLS_CC);
108 }
109
110 tmp = php_base64_encode(crypted, padded_len+16, NULL);
111 efree(crypted);
112 slen=strlen((char *)tmp);
113 for (i=0; i<slen; i++) {
114 switch (tmp[i]) {
115 case '/': tmp[i]='-'; break;
116 case '=': tmp[i]='.'; break;
117 case '+': tmp[i]='_'; break;
118 }
119 }
120 return (char *)tmp;
121}
122
123char *suhosin_decrypt_string(char *str, int padded_len, char *var, int vlen, char *key, int *orig_len, int check_ra TSRMLS_DC)
124{
125 int len, i, o_len, invalid = 0;
126 unsigned char *decrypted, *tmp;
127 unsigned int check = 0x13579BDF;
128 char buf[4];
129
130 if (str == NULL) {
131 return NULL;
132 }
133
134 if (padded_len == 0) {
135 if (orig_len) {
136 *orig_len = 0;
137 }
138 return estrndup("", 0);
139 }
140 suhosin_aes_gkey(4,8,key TSRMLS_CC);
141
142 for (i=0; i<padded_len; i++) {
143 switch (str[i]) {
144 case '-': str[i]='/'; break;
145 case '.': str[i]='='; break;
146 case '_': str[i]='+'; break;
147 }
148 }
149
150 decrypted = php_base64_decode((unsigned char *)str, padded_len, &len);
151 if (decrypted == NULL || len < 2*16 || (len % 16) != 0) {
152error_out:
153 if (decrypted != NULL) {
154 efree(decrypted);
155 }
156 if (orig_len) {
157 *orig_len = 0;
158 }
159 return NULL;
160 }
161
162 for (i=len-16, tmp=decrypted+i; i>=0; i-=16, tmp-=16) {
163 suhosin_aes_decrypt((char *)tmp TSRMLS_CC);
164 if (i > 0) {
165 int j;
166 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
167 }
168 }
169
170 /* retrieve orig_len */
171 o_len = decrypted[15];
172 o_len <<= 8;
173 o_len |= decrypted[14];
174 o_len <<= 8;
175 o_len |= decrypted[13];
176 o_len <<= 8;
177 o_len |= decrypted[12];
178
179 if (o_len < 0 || o_len > len-16) {
180 goto error_out;
181 }
182
183 /* calculate check value */
184 for (i = 0; i<vlen; i++) {
185 check = (check << 3) | (check >> (32-3));
186 check += check << 1;
187 check ^= (unsigned char)var[i];
188 }
189 for (i = 0; i<o_len; i++) {
190 check = (check << 3) | (check >> (32-3));
191 check += check << 1;
192 check ^= decrypted[16+i];
193 }
194
195 /* check value */
196 invalid = (decrypted[8] != (check & 0xff)) ||
197 (decrypted[9] != ((check >> 8) & 0xff)) ||
198 (decrypted[10] != ((check >> 16) & 0xff)) ||
199 (decrypted[11] != ((check >> 24) & 0xff));
200
201 /* check IP */
202 if (check_ra > 0) {
203 if (check_ra > 4) {
204 check_ra = 4;
205 }
206 suhosin_get_ipv4(&buf[0] TSRMLS_CC);
207 if (memcmp(buf, decrypted+4, check_ra) != 0) {
208 goto error_out;
209 }
210 }
211
212 if (invalid) {
213 goto error_out;
214 }
215
216 if (orig_len) {
217 *orig_len = o_len;
218 }
219
220 memmove(decrypted, decrypted+16, o_len);
221 decrypted[o_len] = 0;
222 /* we do not realloc() here because 16 byte less
223 is simply not worth the overhead */
224 return (char *)decrypted;
225}
226
227char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC)
228{
229 char *_ua = NULL;
230 char *_dr = NULL;
231 char *_ra = NULL;
232 suhosin_SHA256_CTX ctx;
233
234 if (ua) {
235 _ua = suhosin_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC);
236 }
237
238 if (dr) {
239 _dr = suhosin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
240 }
241
242 if (raddr > 0) {
243 _ra = suhosin_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
244 }
245
246 SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra);
247
248 suhosin_SHA256Init(&ctx);
249 if (key == NULL || *key == 0) {
250 suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", strlen("D3F4UL7"));
251 } else {
252 suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key));
253 }
254 if (_ua) {
255 suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua));
256 }
257 if (_dr) {
258 suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr));
259 }
260 if (_ra) {
261 if (raddr >= 4) {
262 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra));
263 } else {
264 long dots = 0;
265 char *tmp = _ra;
266
267 while (*tmp) {
268 if (*tmp == '.') {
269 dots++;
270 if (dots == raddr) {
271 break;
272 }
273 }
274 tmp++;
275 }
276 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra);
277 }
278 }
279 suhosin_SHA256Final((unsigned char *)cryptkey, &ctx);
280 cryptkey[32] = 0; /* uhmm... not really a string */
281
282 return cryptkey;
283}
diff --git a/session.c b/session.c
index a3261c9..548786f 100644
--- a/session.c
+++ b/session.c
@@ -1,19 +1,20 @@
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-2014 SektionEins GmbH | 6 | Copyright (c) 2007-2014 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 | Authors: Stefan Esser <sesser@sektioneins.de> |
17 | Ben Fuhrmannek <ben.fuhrmannek@sektioneins.de> |
17 +----------------------------------------------------------------------+ 18 +----------------------------------------------------------------------+
18*/ 19*/
19/* 20/*
@@ -29,10 +30,8 @@
29#include "SAPI.h" 30#include "SAPI.h"
30#include "php_ini.h" 31#include "php_ini.h"
31#include "php_suhosin.h" 32#include "php_suhosin.h"
32#include "ext/standard/base64.h"
33#include "ext/standard/php_smart_str.h" 33#include "ext/standard/php_smart_str.h"
34#include "ext/standard/php_var.h" 34#include "ext/standard/php_var.h"
35#include "sha256.h"
36 35
37#include <fcntl.h> 36#include <fcntl.h>
38 37
@@ -40,481 +39,19 @@
40# include "ext/hash/php_hash.h" 39# include "ext/hash/php_hash.h"
41#endif 40#endif
42 41
43#define PS_OPEN_ARGS void **mod_data, const char *save_path, const char *session_name TSRMLS_DC 42#ifdef HAVE_PHP_SESSION
44#define PS_CLOSE_ARGS void **mod_data TSRMLS_DC 43#include "ext/session/php_session.h"
45#define PS_READ_ARGS void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC
46#define PS_WRITE_ARGS void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC
47#define PS_DESTROY_ARGS void **mod_data, const char *key TSRMLS_DC
48#define PS_GC_ARGS void **mod_data, int maxlifetime, int *nrdels TSRMLS_DC
49#define PS_CREATE_SID_ARGS void **mod_data, int *newlen TSRMLS_DC
50
51typedef struct ps_module_struct {
52 const char *s_name;
53 int (*s_open)(PS_OPEN_ARGS);
54 int (*s_close)(PS_CLOSE_ARGS);
55 int (*s_read)(PS_READ_ARGS);
56 int (*s_write)(PS_WRITE_ARGS);
57 int (*s_destroy)(PS_DESTROY_ARGS);
58 int (*s_gc)(PS_GC_ARGS);
59 char *(*s_create_sid)(PS_CREATE_SID_ARGS);
60} ps_module;
61
62typedef enum {
63 php_session_disabled,
64 php_session_none,
65 php_session_active
66} php_session_status;
67
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
70
71typedef struct ps_serializer_struct {
72 const char *name;
73 int (*encode)(PS_SERIALIZER_ENCODE_ARGS);
74 int (*decode)(PS_SERIALIZER_DECODE_ARGS);
75} ps_serializer;
76
77typedef struct _php_ps_globals_43_44 {
78 char *save_path;
79 char *session_name;
80 char *id;
81 char *extern_referer_chk;
82 char *entropy_file;
83 char *cache_limiter;
84 long entropy_length;
85 long cookie_lifetime;
86 char *cookie_path;
87 char *cookie_domain;
88 zend_bool cookie_secure;
89 ps_module *mod;
90 void *mod_data;
91 php_session_status session_status;
92 long gc_probability;
93 long gc_divisor;
94 long gc_maxlifetime;
95 int module_number;
96 long cache_expire;
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 */
99 const struct ps_serializer_struct *serializer;
100 zval *http_session_vars;
101 zend_bool auto_start;
102 zend_bool use_cookies;
103 zend_bool use_only_cookies;
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 */
106 int send_cookie;
107 int define_sid;
108} php_ps_globals_43_44;
109
110typedef struct _php_ps_globals_50_51 {
111 char *save_path;
112 char *session_name;
113 char *id;
114 char *extern_referer_chk;
115 char *entropy_file;
116 char *cache_limiter;
117 long entropy_length;
118 long cookie_lifetime;
119 char *cookie_path;
120 char *cookie_domain;
121 zend_bool cookie_secure;
122 ps_module *mod;
123 void *mod_data;
124 php_session_status session_status;
125 long gc_probability;
126 long gc_divisor;
127 long gc_maxlifetime;
128 int module_number;
129 long cache_expire;
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 */
132 const struct ps_serializer_struct *serializer;
133 zval *http_session_vars;
134 zend_bool auto_start;
135 zend_bool use_cookies;
136 zend_bool use_only_cookies;
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 */
139
140 long hash_func;
141 long hash_bits_per_character;
142 int send_cookie;
143 int define_sid;
144} php_ps_globals_50_51;
145
146typedef struct _php_ps_globals_52 {
147 char *save_path;
148 char *session_name;
149 char *id;
150 char *extern_referer_chk;
151 char *entropy_file;
152 char *cache_limiter;
153 long entropy_length;
154 long cookie_lifetime;
155 char *cookie_path;
156 char *cookie_domain;
157 zend_bool cookie_secure;
158 zend_bool cookie_httponly;
159 ps_module *mod;
160 void *mod_data;
161 php_session_status session_status;
162 long gc_probability;
163 long gc_divisor;
164 long gc_maxlifetime;
165 int module_number;
166 long cache_expire;
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 */
169 const struct ps_serializer_struct *serializer;
170 zval *http_session_vars;
171 zend_bool auto_start;
172 zend_bool use_cookies;
173 zend_bool use_only_cookies;
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 */
176
177 long hash_func;
178 long hash_bits_per_character;
179 int send_cookie;
180 int define_sid;
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;
183
184typedef struct _php_ps_globals_53 {
185 char *save_path;
186 char *session_name;
187 char *id;
188 char *extern_referer_chk;
189 char *entropy_file;
190 char *cache_limiter;
191 long entropy_length;
192 long cookie_lifetime;
193 char *cookie_path;
194 char *cookie_domain;
195 zend_bool cookie_secure;
196 zend_bool cookie_httponly;
197 ps_module *mod;
198 void *mod_data;
199 php_session_status session_status;
200 long gc_probability;
201 long gc_divisor;
202 long gc_maxlifetime;
203 int module_number;
204 long cache_expire;
205 union {
206 zval *names[6];
207 struct {
208 zval *ps_open;
209 zval *ps_close;
210 zval *ps_read;
211 zval *ps_write;
212 zval *ps_destroy;
213 zval *ps_gc;
214 } name;
215 } mod_user_names;
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 */
218 const struct ps_serializer_struct *serializer;
219 zval *http_session_vars;
220 zend_bool auto_start;
221 zend_bool use_cookies;
222 zend_bool use_only_cookies;
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 */
225
226 long hash_func;
227#if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
228 php_hash_ops *hash_ops;
229#endif
230 long hash_bits_per_character;
231 int send_cookie;
232 int define_sid;
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;
235
236#if PHP_VERSION_ID >= 50400
237typedef struct _php_session_rfc1867_progress_54_55_56 {
238
239 size_t sname_len;
240 zval sid;
241 smart_str key;
242
243 long update_step;
244 long next_update;
245 double next_update_time;
246 zend_bool cancel_upload;
247 zend_bool apply_trans_sid;
248 size_t content_length;
249
250 zval *data; /* the array exported to session data */
251 zval *post_bytes_processed; /* data["bytes_processed"] */
252 zval *files; /* data["files"] array */
253 zval *current_file; /* array of currently uploading file */
254 zval *current_file_bytes_processed;
255} php_session_rfc1867_progress_54_55_56;
256
257typedef struct _php_ps_globals_54 {
258 char *save_path;
259 char *session_name;
260 char *id;
261 char *extern_referer_chk;
262 char *entropy_file;
263 char *cache_limiter;
264 long entropy_length;
265 long cookie_lifetime;
266 char *cookie_path;
267 char *cookie_domain;
268 zend_bool cookie_secure;
269 zend_bool cookie_httponly;
270 ps_module *mod;
271 ps_module *default_mod;
272 void *mod_data;
273 php_session_status session_status;
274 long gc_probability;
275 long gc_divisor;
276 long gc_maxlifetime;
277 int module_number;
278 long cache_expire;
279 union {
280 zval *names[6];
281 struct {
282 zval *ps_open;
283 zval *ps_close;
284 zval *ps_read;
285 zval *ps_write;
286 zval *ps_destroy;
287 zval *ps_gc;
288 } name;
289 } mod_user_names;
290 int mod_user_implemented;
291 int mod_user_is_open;
292 const struct ps_serializer_struct *serializer;
293 zval *http_session_vars;
294 zend_bool auto_start;
295 zend_bool use_cookies;
296 zend_bool use_only_cookies;
297 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
298 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
299
300 long hash_func;
301#if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
302 php_hash_ops *hash_ops;
303#endif
304 long hash_bits_per_character;
305 int send_cookie;
306 int define_sid;
307 zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */
308
309 php_session_rfc1867_progress_54_55_56 *rfc1867_progress;
310 zend_bool rfc1867_enabled; /* session.upload_progress.enabled */
311 zend_bool rfc1867_cleanup; /* session.upload_progress.cleanup */
312 smart_str rfc1867_prefix; /* session.upload_progress.prefix */
313 smart_str rfc1867_name; /* session.upload_progress.name */
314 long rfc1867_freq; /* session.upload_progress.freq */
315 double rfc1867_min_freq; /* session.upload_progress.min_freq */
316} php_ps_globals_54;
317#endif
318
319#if PHP_VERSION_ID >= 50500
320typedef struct _php_ps_globals_55 {
321 char *save_path;
322 char *session_name;
323 char *id;
324 char *extern_referer_chk;
325 char *entropy_file;
326 char *cache_limiter;
327 long entropy_length;
328 long cookie_lifetime;
329 char *cookie_path;
330 char *cookie_domain;
331 zend_bool cookie_secure;
332 zend_bool cookie_httponly;
333 ps_module *mod;
334 ps_module *default_mod;
335 void *mod_data;
336 php_session_status session_status;
337 long gc_probability;
338 long gc_divisor;
339 long gc_maxlifetime;
340 int module_number;
341 long cache_expire;
342 union {
343 zval *names[7];
344 struct {
345 zval *ps_open;
346 zval *ps_close;
347 zval *ps_read;
348 zval *ps_write;
349 zval *ps_destroy;
350 zval *ps_gc;
351 zval *ps_create_sid;
352 } name;
353 } mod_user_names;
354 int mod_user_implemented;
355 int mod_user_is_open;
356 const struct ps_serializer_struct *serializer;
357 zval *http_session_vars;
358 zend_bool auto_start;
359 zend_bool use_cookies;
360 zend_bool use_only_cookies;
361 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
362 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
363
364 long hash_func;
365#if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
366 php_hash_ops *hash_ops;
367#endif
368 long hash_bits_per_character;
369 int send_cookie;
370 int define_sid;
371 zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */
372
373 php_session_rfc1867_progress_54_55_56 *rfc1867_progress;
374 zend_bool rfc1867_enabled; /* session.upload_progress.enabled */
375 zend_bool rfc1867_cleanup; /* session.upload_progress.cleanup */
376 smart_str rfc1867_prefix; /* session.upload_progress.prefix */
377 smart_str rfc1867_name; /* session.upload_progress.name */
378 long rfc1867_freq; /* session.upload_progress.freq */
379 double rfc1867_min_freq; /* session.upload_progress.min_freq */
380
381 zend_bool use_strict_mode; /* whether or not PHP accepts unknown session ids */
382} php_ps_globals_55;
383
384typedef struct _php_ps_globals_56 {
385 char *save_path;
386 char *session_name;
387 char *id;
388 char *extern_referer_chk;
389 char *entropy_file;
390 char *cache_limiter;
391 long entropy_length;
392 long cookie_lifetime;
393 char *cookie_path;
394 char *cookie_domain;
395 zend_bool cookie_secure;
396 zend_bool cookie_httponly;
397 ps_module *mod;
398 ps_module *default_mod;
399 void *mod_data;
400 php_session_status session_status;
401 long gc_probability;
402 long gc_divisor;
403 long gc_maxlifetime;
404 int module_number;
405 long cache_expire;
406 union {
407 zval *names[7];
408 struct {
409 zval *ps_open;
410 zval *ps_close;
411 zval *ps_read;
412 zval *ps_write;
413 zval *ps_destroy;
414 zval *ps_gc;
415 zval *ps_create_sid;
416 } name;
417 } mod_user_names;
418 int mod_user_implemented;
419 int mod_user_is_open;
420 const struct ps_serializer_struct *serializer;
421 zval *http_session_vars;
422 zend_bool auto_start;
423 zend_bool use_cookies;
424 zend_bool use_only_cookies;
425 zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
426 zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
427
428 long hash_func;
429#if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
430 php_hash_ops *hash_ops;
431#endif
432 long hash_bits_per_character;
433 int send_cookie;
434 int define_sid;
435 zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */
436
437 php_session_rfc1867_progress_54_55_56 *rfc1867_progress;
438 zend_bool rfc1867_enabled; /* session.upload_progress.enabled */
439 zend_bool rfc1867_cleanup; /* session.upload_progress.cleanup */
440 smart_str rfc1867_prefix; /* session.upload_progress.prefix */
441 smart_str rfc1867_name; /* session.upload_progress.name */
442 long rfc1867_freq; /* session.upload_progress.freq */
443 double rfc1867_min_freq; /* session.upload_progress.min_freq */
444
445 zend_bool use_strict_mode; /* whether or not PHP accepts unknown session ids */
446 unsigned char session_data_hash[16]; /* binary MD5 hash length */
447} php_ps_globals_56;
448#endif
449 44
450#ifdef ZTS 45#ifdef ZTS
451static ts_rsrc_id session_globals_id = 0; 46static ts_rsrc_id session_globals_id = 0;
452# if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 6) 47#define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals *, v)
453# define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_56 *, v)
454# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 5)
455# define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_55 *, v)
456# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4)
457# define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_54 *, v)
458# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3)
459# define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_53 *, v)
460# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2)
461# define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_52 *, v)
462# elif (PHP_MAJOR_VERSION == 5)
463# define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_50_51 *, v)
464# elif (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION >= 3)
465# define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_43_44 *, v)
466# else
467 UNSUPPORTED PHP VERSION
468# endif
469#else 48#else
470# if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 6) 49static php_ps_globals *session_globals = NULL;
471static php_ps_globals_56 *session_globals = NULL;
472# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 5)
473static php_ps_globals_55 *session_globals = NULL;
474# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4)
475static php_ps_globals_54 *session_globals = NULL;
476# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3)
477static php_ps_globals_53 *session_globals = NULL;
478# elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2)
479static php_ps_globals_52 *session_globals = NULL;
480# elif (PHP_MAJOR_VERSION == 5)
481static php_ps_globals_50_51 *session_globals = NULL;
482# elif (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION >= 3)
483static php_ps_globals_43_44 *session_globals = NULL;
484# else
485 UNSUPPORTED PHP VERSION
486# endif
487#define SESSION_G(v) (session_globals->v) 50#define SESSION_G(v) (session_globals->v)
488#endif 51#endif
489 52
490static ps_module *ps_mod_user = NULL;
491
492ps_serializer *(*suhosin_find_ps_serializer)(char *name TSRMLS_DC) = NULL; 53ps_serializer *(*suhosin_find_ps_serializer)(char *name TSRMLS_DC) = NULL;
493 54
494#define PS_ENCODE_VARS \
495 char *key; \
496 uint key_length; \
497 ulong num_key; \
498 zval **struc;
499
500#define PS_ENCODE_LOOP(code) do { \
501 HashTable *_ht = Z_ARRVAL_P(SESSION_G(http_session_vars)); \
502 int key_type; \
503 \
504 for (zend_hash_internal_pointer_reset(_ht); \
505 (key_type = zend_hash_get_current_key_ex(_ht, &key, &key_length, &num_key, 0, NULL)) != HASH_KEY_NON_EXISTANT; \
506 zend_hash_move_forward(_ht)) { \
507 if (key_type == HASH_KEY_IS_LONG) { \
508 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric key %ld", num_key); \
509 continue; \
510 } \
511 key_length--; \
512 if (suhosin_get_session_var(key, key_length, &struc TSRMLS_CC) == SUCCESS) { \
513 code; \
514 } \
515 } \
516 } while(0)
517
518static int suhosin_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) /* {{{ */ 55static int suhosin_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) /* {{{ */
519{ 56{
520 int ret = FAILURE; 57 int ret = FAILURE;
@@ -599,259 +136,6 @@ static void suhosin_send_cookie(TSRMLS_D)
599 *session_send_cookie = 1; 136 *session_send_cookie = 1;
600} 137}
601 138
602void suhosin_get_ipv4(char *buf TSRMLS_DC)
603{
604 char *raddr = suhosin_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
605 int i;
606
607
608 if (raddr == NULL) {
609 memset(buf, 0, 4);
610 return;
611 }
612
613 for (i=0; i<4; i++) {
614 if (raddr[0] == 0) {
615 buf[i] = 0;
616 } else {
617 buf[i] = strtol(raddr, &raddr, 10);
618 if (raddr[0] == '.') {
619 raddr++;
620 }
621 }
622 }
623}
624
625char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC)
626{
627 int padded_len, i, slen;
628 unsigned char *crypted, *tmp;
629 unsigned int check = 0x13579BDF;
630
631 if (str == NULL) {
632 return NULL;
633 }
634 if (len == 0) {
635 return estrndup("", 0);
636 }
637
638
639 suhosin_aes_gkey(4,8,key TSRMLS_CC);
640
641 padded_len = ((len+15) & ~0xF);
642 crypted = emalloc(16+padded_len+1);
643 memset(crypted, 0xff, 16+padded_len+1);
644 memcpy(crypted+16, str, len+1);
645
646 /* calculate check value */
647 for (i = 0; i<vlen; i++) {
648 check = (check << 3) | (check >> (32-3));
649 check += check << 1;
650 check ^= (unsigned char)var[i];
651 }
652 for (i = 0; i<len; i++) {
653 check = (check << 3) | (check >> (32-3));
654 check += check << 1;
655 check ^= (unsigned char)str[i];
656 }
657
658 /* store ip value */
659 suhosin_get_ipv4((char *)crypted+4 TSRMLS_CC);
660
661 /* store check value */
662 crypted[8] = check & 0xff;
663 crypted[9] = (check >> 8) & 0xff;
664 crypted[10] = (check >> 16) & 0xff;
665 crypted[11] = (check >> 24) & 0xff;
666
667 /* store original length */
668 crypted[12] = len & 0xff;
669 crypted[13] = (len >> 8) & 0xff;
670 crypted[14] = (len >> 16) & 0xff;
671 crypted[15] = (len >> 24) & 0xff;
672
673 for (i=0, tmp=crypted; i<padded_len+16; i+=16, tmp+=16) {
674 if (i > 0) {
675 int j;
676 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
677 }
678 suhosin_aes_encrypt((char *)tmp TSRMLS_CC);
679 }
680
681 tmp = php_base64_encode(crypted, padded_len+16, NULL);
682 efree(crypted);
683 slen=strlen((char *)tmp);
684 for (i=0; i<slen; i++) {
685 switch (tmp[i]) {
686 case '/': tmp[i]='-'; break;
687 case '=': tmp[i]='.'; break;
688 case '+': tmp[i]='_'; break;
689 }
690 }
691 return (char *)tmp;
692}
693
694char *suhosin_decrypt_string(char *str, int padded_len, char *var, int vlen, char *key, int *orig_len, int check_ra TSRMLS_DC)
695{
696 int len, i, o_len, invalid = 0;
697 unsigned char *decrypted, *tmp;
698 unsigned int check = 0x13579BDF;
699 char buf[4];
700
701 if (str == NULL) {
702 return NULL;
703 }
704
705 if (padded_len == 0) {
706 if (orig_len) {
707 *orig_len = 0;
708 }
709 return estrndup("", 0);
710 }
711 suhosin_aes_gkey(4,8,key TSRMLS_CC);
712
713 for (i=0; i<padded_len; i++) {
714 switch (str[i]) {
715 case '-': str[i]='/'; break;
716 case '.': str[i]='='; break;
717 case '_': str[i]='+'; break;
718 }
719 }
720
721 decrypted = php_base64_decode((unsigned char *)str, padded_len, &len);
722 if (decrypted == NULL || len < 2*16 || (len % 16) != 0) {
723error_out:
724 if (decrypted != NULL) {
725 efree(decrypted);
726 }
727 if (orig_len) {
728 *orig_len = 0;
729 }
730 return NULL;
731 }
732
733 for (i=len-16, tmp=decrypted+i; i>=0; i-=16, tmp-=16) {
734 suhosin_aes_decrypt((char *)tmp TSRMLS_CC);
735 if (i > 0) {
736 int j;
737 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
738 }
739 }
740
741 /* retrieve orig_len */
742 o_len = decrypted[15];
743 o_len <<= 8;
744 o_len |= decrypted[14];
745 o_len <<= 8;
746 o_len |= decrypted[13];
747 o_len <<= 8;
748 o_len |= decrypted[12];
749
750 if (o_len < 0 || o_len > len-16) {
751 goto error_out;
752 }
753
754 /* calculate check value */
755 for (i = 0; i<vlen; i++) {
756 check = (check << 3) | (check >> (32-3));
757 check += check << 1;
758 check ^= (unsigned char)var[i];
759 }
760 for (i = 0; i<o_len; i++) {
761 check = (check << 3) | (check >> (32-3));
762 check += check << 1;
763 check ^= decrypted[16+i];
764 }
765
766 /* check value */
767 invalid = (decrypted[8] != (check & 0xff)) ||
768 (decrypted[9] != ((check >> 8) & 0xff)) ||
769 (decrypted[10] != ((check >> 16) & 0xff)) ||
770 (decrypted[11] != ((check >> 24) & 0xff));
771
772 /* check IP */
773 if (check_ra > 0) {
774 if (check_ra > 4) {
775 check_ra = 4;
776 }
777 suhosin_get_ipv4(&buf[0] TSRMLS_CC);
778 if (memcmp(buf, decrypted+4, check_ra) != 0) {
779 goto error_out;
780 }
781 }
782
783 if (invalid) {
784 goto error_out;
785 }
786
787 if (orig_len) {
788 *orig_len = o_len;
789 }
790
791 memmove(decrypted, decrypted+16, o_len);
792 decrypted[o_len] = 0;
793 /* we do not realloc() here because 16 byte less
794 is simply not worth the overhead */
795 return (char *)decrypted;
796}
797
798char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC)
799{
800 char *_ua = NULL;
801 char *_dr = NULL;
802 char *_ra = NULL;
803 suhosin_SHA256_CTX ctx;
804
805 if (ua) {
806 _ua = suhosin_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC);
807 }
808
809 if (dr) {
810 _dr = suhosin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
811 }
812
813 if (raddr > 0) {
814 _ra = suhosin_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
815 }
816
817 SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra);
818
819 suhosin_SHA256Init(&ctx);
820 if (key == NULL || *key == 0) {
821 suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", strlen("D3F4UL7"));
822 } else {
823 suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key));
824 }
825 if (_ua) {
826 suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua));
827 }
828 if (_dr) {
829 suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr));
830 }
831 if (_ra) {
832 if (raddr >= 4) {
833 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra));
834 } else {
835 long dots = 0;
836 char *tmp = _ra;
837
838 while (*tmp) {
839 if (*tmp == '.') {
840 dots++;
841 if (dots == raddr) {
842 break;
843 }
844 }
845 tmp++;
846 }
847 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra);
848 }
849 }
850 suhosin_SHA256Final((unsigned char *)cryptkey, &ctx);
851 cryptkey[32] = 0; /* uhmm... not really a string */
852
853 return cryptkey;
854}
855 139
856 140
857static int (*old_OnUpdateSaveHandler)(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC) = NULL; 141static int (*old_OnUpdateSaveHandler)(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC) = NULL;
@@ -1018,14 +302,14 @@ static void suhosin_hook_session_module(TSRMLS_D)
1018static PHP_INI_MH(suhosin_OnUpdateSaveHandler) 302static PHP_INI_MH(suhosin_OnUpdateSaveHandler)
1019{ 303{
1020 int r; 304 int r;
1021 char *tmp;
1022 305
1023 if ((ps_mod_user) && (SUHOSIN_G(s_original_mod) == ps_mod_user) && (strcmp(new_value, "user") == 0)) { 306 if (stage == PHP_INI_STAGE_RUNTIME && SESSION_G(session_status) == php_session_none && SUHOSIN_G(s_original_mod)
307 && strcmp(new_value, "user") == 0 && strcmp(((ps_module*)SUHOSIN_G(s_original_mod))->s_name, "user") == 0) {
1024 return SUCCESS; 308 return SUCCESS;
1025 } 309 }
1026 310
1027 SESSION_G(mod) = SUHOSIN_G(s_original_mod); 311 SESSION_G(mod) = SUHOSIN_G(s_original_mod);
1028 312
1029 r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); 313 r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
1030 314
1031 suhosin_hook_session_module(TSRMLS_C); 315 suhosin_hook_session_module(TSRMLS_C);
@@ -1095,12 +379,6 @@ void suhosin_hook_session(TSRMLS_D)
1095 } 379 }
1096#endif 380#endif
1097#endif 381#endif
1098 if (ps_mod_user == NULL) {
1099 ps_mod_user = DL_FETCH_SYMBOL(module->handle, "ps_mod_user");
1100 if (ps_mod_user == NULL) {
1101 ps_mod_user = DL_FETCH_SYMBOL(module->handle, "_ps_mod_user");
1102 }
1103 }
1104 382
1105 if (old_OnUpdateSaveHandler != NULL) { 383 if (old_OnUpdateSaveHandler != NULL) {
1106 return; 384 return;
@@ -1159,6 +437,21 @@ void suhosin_unhook_session(TSRMLS_D)
1159 437
1160} 438}
1161 439
440#else /* HAVE_PHP_SESSION */
441
442#warning BUILDING SUHOSIN WITHOUT SESSION SUPPORT
443
444void suhosin_hook_session(TSRMLS_D)
445{
446}
447
448void suhosin_unhook_session(TSRMLS_D)
449{
450}
451
452#endif /* HAVE_PHP_SESSION */
453
454
1162/* 455/*
1163 * Local variables: 456 * Local variables:
1164 * tab-width: 4 457 * tab-width: 4
diff --git a/suhosin.c b/suhosin.c
index c19a2b8..6d437d0 100644
--- a/suhosin.c
+++ b/suhosin.c
@@ -871,7 +871,8 @@ PHP_INI_BEGIN()
871 STD_PHP_INI_ENTRY("suhosin.sql.opencomment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_opencomment, zend_suhosin_globals, suhosin_globals) 871 STD_PHP_INI_ENTRY("suhosin.sql.opencomment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_opencomment, zend_suhosin_globals, suhosin_globals)
872 STD_PHP_INI_ENTRY("suhosin.sql.multiselect", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_mselect, zend_suhosin_globals, suhosin_globals) 872 STD_PHP_INI_ENTRY("suhosin.sql.multiselect", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_mselect, zend_suhosin_globals, suhosin_globals)
873 STD_PHP_INI_ENTRY("suhosin.sql.union", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_union, zend_suhosin_globals, suhosin_globals) 873 STD_PHP_INI_ENTRY("suhosin.sql.union", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_union, zend_suhosin_globals, suhosin_globals)
874 874
875#ifdef HAVE_PHP_SESSION
875 STD_ZEND_INI_BOOLEAN("suhosin.session.encrypt", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_encrypt, zend_suhosin_globals, suhosin_globals) 876 STD_ZEND_INI_BOOLEAN("suhosin.session.encrypt", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_encrypt, zend_suhosin_globals, suhosin_globals)
876 STD_PHP_INI_ENTRY("suhosin.session.cryptkey", "", PHP_INI_ALL, OnUpdateString, session_cryptkey, zend_suhosin_globals, suhosin_globals) 877 STD_PHP_INI_ENTRY("suhosin.session.cryptkey", "", PHP_INI_ALL, OnUpdateString, session_cryptkey, zend_suhosin_globals, suhosin_globals)
877 STD_ZEND_INI_BOOLEAN("suhosin.session.cryptua", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_cryptua, zend_suhosin_globals, suhosin_globals) 878 STD_ZEND_INI_BOOLEAN("suhosin.session.cryptua", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_cryptua, zend_suhosin_globals, suhosin_globals)
@@ -879,7 +880,10 @@ PHP_INI_BEGIN()
879 STD_PHP_INI_ENTRY("suhosin.session.cryptraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_cryptraddr, zend_suhosin_globals, suhosin_globals) 880 STD_PHP_INI_ENTRY("suhosin.session.cryptraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_cryptraddr, zend_suhosin_globals, suhosin_globals)
880 STD_PHP_INI_ENTRY("suhosin.session.checkraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_checkraddr, zend_suhosin_globals, suhosin_globals) 881 STD_PHP_INI_ENTRY("suhosin.session.checkraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_checkraddr, zend_suhosin_globals, suhosin_globals)
881 STD_PHP_INI_ENTRY("suhosin.session.max_id_length", "128", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_max_id_length, zend_suhosin_globals, suhosin_globals) 882 STD_PHP_INI_ENTRY("suhosin.session.max_id_length", "128", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_max_id_length, zend_suhosin_globals, suhosin_globals)
882 883#else /* HAVE_PHP_SESSION */
884#warning BUILDING SUHOSIN WITHOUT SESSION SUPPORT
885#endif /* HAVE_PHP_SESSION */
886
883 887
884 STD_ZEND_INI_BOOLEAN("suhosin.cookie.encrypt", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, cookie_encrypt, zend_suhosin_globals, suhosin_globals) 888 STD_ZEND_INI_BOOLEAN("suhosin.cookie.encrypt", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, cookie_encrypt, zend_suhosin_globals, suhosin_globals)
885 STD_PHP_INI_ENTRY("suhosin.cookie.cryptkey", "", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, cookie_cryptkey, zend_suhosin_globals, suhosin_globals) 889 STD_PHP_INI_ENTRY("suhosin.cookie.cryptkey", "", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, cookie_cryptkey, zend_suhosin_globals, suhosin_globals)
diff --git a/tests/session/session_recursive_crash2.phpt b/tests/session/session_recursive_crash2.phpt
new file mode 100644
index 0000000..e99d924
--- /dev/null
+++ b/tests/session/session_recursive_crash2.phpt
@@ -0,0 +1,61 @@
1--TEST--
2session user handler recursive crash - issue #60
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--ENV--
6return <<<END
7HTTP_USER_AGENT=test
8END;
9--INI--
10suhosin.session.encrypt=On
11suhosin.session.cryptkey=D3F4UL7
12suhosin.session.cryptua=On
13suhosin.session.cryptdocroot=Off
14suhosin.session.cryptraddr=0
15suhosin.session.checkraddr=0
16--FILE--
17<?php
18$foo = "";
19
20class MySessionHandlerA implements SessionHandlerInterface
21{
22 public function close() {}
23 public function destroy($session_id) {}
24 public function gc($maxlifetime) {}
25 public function open($save_path, $name) { global $foo; $foo .= "A\n"; }
26 public function read($session_id ) {}
27 public function write($session_id, $session_data) {}
28}
29
30session_set_save_handler(new MySessionHandlerA(), true);
31session_start();
32session_destroy();
33
34//
35
36class MySessionHandlerB extends MySessionHandlerA
37{
38 public function open($save_path, $name) { global $foo; $foo .= "B\n"; }
39}
40
41session_set_save_handler(new MySessionHandlerB(), true);
42session_start();
43session_destroy();
44
45//
46
47class MySessionHandlerC extends MySessionHandlerA
48{
49 public function open($save_path, $name) { global $foo; $foo .= "C\n"; }
50}
51
52session_set_save_handler(new MySessionHandlerC(), true);
53session_start();
54session_destroy();
55
56
57echo $foo;
58--EXPECTF--
59A
60B
61C