summaryrefslogtreecommitdiff
path: root/header.c
diff options
context:
space:
mode:
Diffstat (limited to 'header.c')
-rw-r--r--header.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/header.c b/header.c
new file mode 100644
index 0000000..9750232
--- /dev/null
+++ b/header.c
@@ -0,0 +1,353 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007 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 | Author: Stefan Esser <sesser@sektioneins.de> |
17 +----------------------------------------------------------------------+
18*/
19/*
20 $Id: header.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "php.h"
28#include "php_ini.h"
29#include "ext/standard/info.h"
30#include "ext/standard/url.h"
31#include "php_suhosin.h"
32#include "SAPI.h"
33#include "php_variables.h"
34
35static int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) = NULL;
36
37char *suhosin_encrypt_single_cookie(char *name, int name_len, char *value, int value_len, char *key TSRMLS_DC)
38{
39 char buffer[4096];
40 char buffer2[4096];
41 char *buf = buffer, *buf2 = buffer2, *d, *d_url;
42 int l;
43
44 if (name_len > sizeof(buffer)-2) {
45 buf = estrndup(name, name_len);
46 } else {
47 memcpy(buf, name, name_len);
48 buf[name_len] = 0;
49 }
50
51 name_len = php_url_decode(buf, name_len);
52 normalize_varname(buf);
53 name_len = strlen(buf);
54
55 if (SUHOSIN_G(cookie_plainlist)) {
56 if (zend_hash_exists(SUHOSIN_G(cookie_plainlist), buf, name_len+1)) {
57encrypt_return_plain:
58 if (buf != buffer) {
59 efree(buf);
60 }
61 return estrndup(value, value_len);
62 }
63 } else if (SUHOSIN_G(cookie_cryptlist)) {
64 if (!zend_hash_exists(SUHOSIN_G(cookie_cryptlist), buf, name_len+1)) {
65 goto encrypt_return_plain;
66 }
67 }
68
69 if (strlen(value) <= sizeof(buffer2)-2) {
70 memcpy(buf2, value, value_len);
71 buf2[value_len] = 0;
72 } else {
73 buf2 = estrndup(value, value_len);
74 }
75
76 value_len = php_url_decode(buf2, value_len);
77
78 d = suhosin_encrypt_string(buf2, value_len, buf, name_len, key TSRMLS_CC);
79 d_url = php_url_encode(d, strlen(d), &l);
80 efree(d);
81 if (buf != buffer) {
82 efree(buf);
83 }
84 if (buf2 != buffer2) {
85 efree(buf2);
86 }
87 return d_url;
88}
89
90char *suhosin_decrypt_single_cookie(char *name, int name_len, char *value, int value_len, char *key, char **where TSRMLS_DC)
91{
92 char buffer[4096];
93 char buffer2[4096];
94 int o_name_len = name_len;
95 char *buf = buffer, *buf2 = buffer2, *d, *d_url;
96 int l;
97
98 if (name_len > sizeof(buffer)-2) {
99 buf = estrndup(name, name_len);
100 } else {
101 memcpy(buf, name, name_len);
102 buf[name_len] = 0;
103 }
104
105 name_len = php_url_decode(buf, name_len);
106 normalize_varname(buf);
107 name_len = strlen(buf);
108
109 if (SUHOSIN_G(cookie_plainlist)) {
110 if (zend_hash_exists(SUHOSIN_G(cookie_plainlist), buf, name_len+1)) {
111decrypt_return_plain:
112 if (buf != buffer) {
113 efree(buf);
114 }
115 memcpy(*where, name, o_name_len);
116 *where += o_name_len;
117 **where = '='; *where +=1;
118 memcpy(*where, value, value_len);
119 *where += value_len;
120 return *where;
121 }
122 } else if (SUHOSIN_G(cookie_cryptlist)) {
123 if (!zend_hash_exists(SUHOSIN_G(cookie_cryptlist), buf, name_len+1)) {
124 goto decrypt_return_plain;
125 }
126 }
127
128
129 if (strlen(value) <= sizeof(buffer2)-2) {
130 memcpy(buf2, value, value_len);
131 buf2[value_len] = 0;
132 } else {
133 buf2 = estrndup(value, value_len);
134 }
135
136 value_len = php_url_decode(buf2, value_len);
137
138 d = suhosin_decrypt_string(buf2, value_len, buf, name_len, key, &l, SUHOSIN_G(cookie_checkraddr) TSRMLS_CC);
139 if (d == NULL) {
140 goto skip_cookie;
141 }
142 d_url = php_url_encode(d, l, &l);
143 efree(d);
144 memcpy(*where, name, o_name_len);
145 *where += o_name_len;
146 **where = '=';*where += 1;
147 memcpy(*where, d_url, l);
148 *where += l;
149 efree(d_url);
150skip_cookie:
151 if (buf != buffer) {
152 efree(buf);
153 }
154 if (buf2 != buffer2) {
155 efree(buf2);
156 }
157 return *where;
158}
159
160/* {{{ suhosin_cookie_decryptor
161 */
162char *suhosin_cookie_decryptor(TSRMLS_D)
163{
164 char *raw_cookie = SG(request_info).cookie_data;
165 char *decrypted, *ret, *var, *val, *tmp;
166 int j;
167 char cryptkey[33];
168
169 /*
170 if (...deactivated...) {
171 return estrdup(raw_cookie);
172 }
173 */
174
175 suhosin_generate_key(SUHOSIN_G(cookie_cryptkey), SUHOSIN_G(cookie_cryptua), SUHOSIN_G(cookie_cryptdocroot), SUHOSIN_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC);
176
177 ret = decrypted = emalloc(strlen(raw_cookie)*4+1);
178 raw_cookie = estrdup(raw_cookie);
179 SUHOSIN_G(raw_cookie) = estrdup(raw_cookie);
180
181
182 j = 0; tmp = raw_cookie;
183 while (*tmp) {
184 char *d_url;int varlen;
185 while (*tmp == '\t' || *tmp == ' ') tmp++;
186 var = tmp;
187 while (*tmp && *tmp != ';' && *tmp != '=') tmp++;
188
189 varlen = tmp-var;
190 /*memcpy(decrypted, var, varlen);
191 decrypted += varlen;*/
192 if (*tmp == 0) break;
193
194 if (*tmp++ == ';') {
195 *decrypted++ = ';';
196 continue;
197 }
198
199 /**decrypted++ = '=';*/
200
201 val = tmp;
202 while (*tmp && *tmp != ';') tmp++;
203
204 d_url = suhosin_decrypt_single_cookie(var, varlen, val, tmp-val, (char *)&cryptkey, &decrypted TSRMLS_CC);
205 if (*tmp == ';') {
206 *decrypted++ = ';';
207 }
208
209 if (*tmp == 0) break;
210 tmp++;
211 }
212 *decrypted++ = 0;
213 ret = erealloc(ret, decrypted-ret);
214
215 SUHOSIN_G(decrypted_cookie) = ret;
216 efree(raw_cookie);
217
218 return ret;
219}
220/* }}} */
221
222/* {{{ suhosin_header_handler
223 */
224int suhosin_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
225{
226 int retval = SAPI_HEADER_ADD, i;
227 char *tmp;
228
229 if (!SUHOSIN_G(allow_multiheader) && sapi_header && sapi_header->header) {
230
231 tmp = sapi_header->header;
232
233 for (i=0; i<sapi_header->header_len; i++, tmp++) {
234 if (tmp[0] == 0) {
235 char *fname = get_active_function_name(TSRMLS_C);
236
237 if (!fname) {
238 fname = "unknown";
239 }
240
241 suhosin_log(S_MISC, "%s() - wanted to send a HTTP header with an ASCII NUL in it", fname);
242 if (!SUHOSIN_G(simulation)) {
243 sapi_header->header_len = i;
244 }
245 } else if ((tmp[0] == '\r' && (tmp[1] != '\n' || i == 0)) ||
246 (tmp[0] == '\n' && (i == sapi_header->header_len-1 || i == 0 || (tmp[1] != ' ' && tmp[1] != '\t')))) {
247 char *fname = get_active_function_name(TSRMLS_C);
248
249 if (!fname) {
250 fname = "unknown";
251 }
252
253 suhosin_log(S_MISC, "%s() - wanted to send multiple HTTP headers at once", fname);
254 if (!SUHOSIN_G(simulation)) {
255 sapi_header->header_len = i;
256 tmp[0] = 0;
257 }
258 }
259 }
260 }
261
262 /* Handle a potential cookie */
263
264 if (SUHOSIN_G(cookie_encrypt) && (strncasecmp("Set-Cookie:", sapi_header->header, sizeof("Set-Cookie:")-1) == 0)) {
265
266 char *start, *end, *rend, *tmp;
267 char *name, *value;
268 int nlen, vlen, len, tlen;
269 char cryptkey[33];
270
271 suhosin_generate_key(SUHOSIN_G(cookie_cryptkey), SUHOSIN_G(cookie_cryptua), SUHOSIN_G(cookie_cryptdocroot), SUHOSIN_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC);
272 start = estrndup(sapi_header->header, sapi_header->header_len);
273 rend = end = start + sapi_header->header_len;
274
275 tmp = memchr(start, ';', end-start);
276 if (tmp != NULL) {
277 end = tmp;
278 }
279
280 tmp = start + sizeof("Set-Cookie:") - 1;
281 while (tmp < end && tmp[0]==' ') {
282 tmp++;
283 }
284 name = tmp;
285 nlen = end-name;
286 tmp = memchr(name, '=', nlen);
287 if (tmp == NULL) {
288 value = end;
289 } else {
290 value = tmp+1;
291 nlen = tmp-name;
292 }
293 vlen = end-value;
294
295 value = suhosin_encrypt_single_cookie(name, nlen, value, vlen, (char *)&cryptkey TSRMLS_CC);
296 vlen = strlen(value);
297
298 len = sizeof("Set-Cookie: ")-1 + nlen + 1 + vlen + rend-end;
299 tmp = emalloc(len + 1);
300 tlen = sprintf(tmp, "Set-Cookie: %.*s=%s", nlen,name, value);
301 memcpy(tmp + tlen, end, rend-end);
302 tmp[len] = 0;
303
304 efree(sapi_header->header);
305 efree(value);
306 efree(start);
307
308 sapi_header->header = tmp;
309 sapi_header->header_len = len;
310 }
311
312
313 /* If existing call the sapi header handler */
314 if (orig_header_handler) {
315 retval = orig_header_handler(sapi_header, sapi_headers TSRMLS_CC);
316 }
317
318 return retval;
319}
320/* }}} */
321
322
323/* {{{ suhosin_hook_header_handler
324 */
325void suhosin_hook_header_handler()
326{
327 if (orig_header_handler == NULL) {
328 orig_header_handler = sapi_module.header_handler;
329 sapi_module.header_handler = suhosin_header_handler;
330 }
331}
332/* }}} */
333
334/* {{{ suhosin_unhook_header_handler
335 */
336void suhosin_unhook_header_handler()
337{
338 sapi_module.header_handler = orig_header_handler;
339 orig_header_handler = NULL;
340}
341/* }}} */
342
343
344/*
345 * Local variables:
346 * tab-width: 4
347 * c-basic-offset: 4
348 * End:
349 * vim600: noet sw=4 ts=4 fdm=marker
350 * vim<600: noet sw=4 ts=4
351 */
352
353