summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'session.c')
-rw-r--r--session.c773
1 files changed, 33 insertions, 740 deletions
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