From 36dbfacbe64697d959f524e537b15b73c090d898 Mon Sep 17 00:00:00 2001 From: Stefan Esser Date: Sun, 21 Feb 2010 11:44:54 +0100 Subject: Inital commit --- header.c | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 header.c (limited to 'header.c') diff --git a/header.c b/header.c new file mode 100644 index 0000000..9750232 --- /dev/null +++ b/header.c @@ -0,0 +1,353 @@ +/* + +----------------------------------------------------------------------+ + | Suhosin Version 1 | + +----------------------------------------------------------------------+ + | Copyright (c) 2006-2007 The Hardened-PHP Project | + | Copyright (c) 2007 SektionEins GmbH | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Stefan Esser | + +----------------------------------------------------------------------+ +*/ +/* + $Id: header.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "ext/standard/url.h" +#include "php_suhosin.h" +#include "SAPI.h" +#include "php_variables.h" + +static int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) = NULL; + +char *suhosin_encrypt_single_cookie(char *name, int name_len, char *value, int value_len, char *key TSRMLS_DC) +{ + char buffer[4096]; + char buffer2[4096]; + char *buf = buffer, *buf2 = buffer2, *d, *d_url; + int l; + + if (name_len > sizeof(buffer)-2) { + buf = estrndup(name, name_len); + } else { + memcpy(buf, name, name_len); + buf[name_len] = 0; + } + + name_len = php_url_decode(buf, name_len); + normalize_varname(buf); + name_len = strlen(buf); + + if (SUHOSIN_G(cookie_plainlist)) { + if (zend_hash_exists(SUHOSIN_G(cookie_plainlist), buf, name_len+1)) { +encrypt_return_plain: + if (buf != buffer) { + efree(buf); + } + return estrndup(value, value_len); + } + } else if (SUHOSIN_G(cookie_cryptlist)) { + if (!zend_hash_exists(SUHOSIN_G(cookie_cryptlist), buf, name_len+1)) { + goto encrypt_return_plain; + } + } + + if (strlen(value) <= sizeof(buffer2)-2) { + memcpy(buf2, value, value_len); + buf2[value_len] = 0; + } else { + buf2 = estrndup(value, value_len); + } + + value_len = php_url_decode(buf2, value_len); + + d = suhosin_encrypt_string(buf2, value_len, buf, name_len, key TSRMLS_CC); + d_url = php_url_encode(d, strlen(d), &l); + efree(d); + if (buf != buffer) { + efree(buf); + } + if (buf2 != buffer2) { + efree(buf2); + } + return d_url; +} + +char *suhosin_decrypt_single_cookie(char *name, int name_len, char *value, int value_len, char *key, char **where TSRMLS_DC) +{ + char buffer[4096]; + char buffer2[4096]; + int o_name_len = name_len; + char *buf = buffer, *buf2 = buffer2, *d, *d_url; + int l; + + if (name_len > sizeof(buffer)-2) { + buf = estrndup(name, name_len); + } else { + memcpy(buf, name, name_len); + buf[name_len] = 0; + } + + name_len = php_url_decode(buf, name_len); + normalize_varname(buf); + name_len = strlen(buf); + + if (SUHOSIN_G(cookie_plainlist)) { + if (zend_hash_exists(SUHOSIN_G(cookie_plainlist), buf, name_len+1)) { +decrypt_return_plain: + if (buf != buffer) { + efree(buf); + } + memcpy(*where, name, o_name_len); + *where += o_name_len; + **where = '='; *where +=1; + memcpy(*where, value, value_len); + *where += value_len; + return *where; + } + } else if (SUHOSIN_G(cookie_cryptlist)) { + if (!zend_hash_exists(SUHOSIN_G(cookie_cryptlist), buf, name_len+1)) { + goto decrypt_return_plain; + } + } + + + if (strlen(value) <= sizeof(buffer2)-2) { + memcpy(buf2, value, value_len); + buf2[value_len] = 0; + } else { + buf2 = estrndup(value, value_len); + } + + value_len = php_url_decode(buf2, value_len); + + d = suhosin_decrypt_string(buf2, value_len, buf, name_len, key, &l, SUHOSIN_G(cookie_checkraddr) TSRMLS_CC); + if (d == NULL) { + goto skip_cookie; + } + d_url = php_url_encode(d, l, &l); + efree(d); + memcpy(*where, name, o_name_len); + *where += o_name_len; + **where = '=';*where += 1; + memcpy(*where, d_url, l); + *where += l; + efree(d_url); +skip_cookie: + if (buf != buffer) { + efree(buf); + } + if (buf2 != buffer2) { + efree(buf2); + } + return *where; +} + +/* {{{ suhosin_cookie_decryptor + */ +char *suhosin_cookie_decryptor(TSRMLS_D) +{ + char *raw_cookie = SG(request_info).cookie_data; + char *decrypted, *ret, *var, *val, *tmp; + int j; + char cryptkey[33]; + + /* + if (...deactivated...) { + return estrdup(raw_cookie); + } + */ + + suhosin_generate_key(SUHOSIN_G(cookie_cryptkey), SUHOSIN_G(cookie_cryptua), SUHOSIN_G(cookie_cryptdocroot), SUHOSIN_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC); + + ret = decrypted = emalloc(strlen(raw_cookie)*4+1); + raw_cookie = estrdup(raw_cookie); + SUHOSIN_G(raw_cookie) = estrdup(raw_cookie); + + + j = 0; tmp = raw_cookie; + while (*tmp) { + char *d_url;int varlen; + while (*tmp == '\t' || *tmp == ' ') tmp++; + var = tmp; + while (*tmp && *tmp != ';' && *tmp != '=') tmp++; + + varlen = tmp-var; + /*memcpy(decrypted, var, varlen); + decrypted += varlen;*/ + if (*tmp == 0) break; + + if (*tmp++ == ';') { + *decrypted++ = ';'; + continue; + } + + /**decrypted++ = '=';*/ + + val = tmp; + while (*tmp && *tmp != ';') tmp++; + + d_url = suhosin_decrypt_single_cookie(var, varlen, val, tmp-val, (char *)&cryptkey, &decrypted TSRMLS_CC); + if (*tmp == ';') { + *decrypted++ = ';'; + } + + if (*tmp == 0) break; + tmp++; + } + *decrypted++ = 0; + ret = erealloc(ret, decrypted-ret); + + SUHOSIN_G(decrypted_cookie) = ret; + efree(raw_cookie); + + return ret; +} +/* }}} */ + +/* {{{ suhosin_header_handler + */ +int suhosin_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) +{ + int retval = SAPI_HEADER_ADD, i; + char *tmp; + + if (!SUHOSIN_G(allow_multiheader) && sapi_header && sapi_header->header) { + + tmp = sapi_header->header; + + for (i=0; iheader_len; i++, tmp++) { + if (tmp[0] == 0) { + char *fname = get_active_function_name(TSRMLS_C); + + if (!fname) { + fname = "unknown"; + } + + suhosin_log(S_MISC, "%s() - wanted to send a HTTP header with an ASCII NUL in it", fname); + if (!SUHOSIN_G(simulation)) { + sapi_header->header_len = i; + } + } else if ((tmp[0] == '\r' && (tmp[1] != '\n' || i == 0)) || + (tmp[0] == '\n' && (i == sapi_header->header_len-1 || i == 0 || (tmp[1] != ' ' && tmp[1] != '\t')))) { + char *fname = get_active_function_name(TSRMLS_C); + + if (!fname) { + fname = "unknown"; + } + + suhosin_log(S_MISC, "%s() - wanted to send multiple HTTP headers at once", fname); + if (!SUHOSIN_G(simulation)) { + sapi_header->header_len = i; + tmp[0] = 0; + } + } + } + } + + /* Handle a potential cookie */ + + if (SUHOSIN_G(cookie_encrypt) && (strncasecmp("Set-Cookie:", sapi_header->header, sizeof("Set-Cookie:")-1) == 0)) { + + char *start, *end, *rend, *tmp; + char *name, *value; + int nlen, vlen, len, tlen; + char cryptkey[33]; + + suhosin_generate_key(SUHOSIN_G(cookie_cryptkey), SUHOSIN_G(cookie_cryptua), SUHOSIN_G(cookie_cryptdocroot), SUHOSIN_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC); + start = estrndup(sapi_header->header, sapi_header->header_len); + rend = end = start + sapi_header->header_len; + + tmp = memchr(start, ';', end-start); + if (tmp != NULL) { + end = tmp; + } + + tmp = start + sizeof("Set-Cookie:") - 1; + while (tmp < end && tmp[0]==' ') { + tmp++; + } + name = tmp; + nlen = end-name; + tmp = memchr(name, '=', nlen); + if (tmp == NULL) { + value = end; + } else { + value = tmp+1; + nlen = tmp-name; + } + vlen = end-value; + + value = suhosin_encrypt_single_cookie(name, nlen, value, vlen, (char *)&cryptkey TSRMLS_CC); + vlen = strlen(value); + + len = sizeof("Set-Cookie: ")-1 + nlen + 1 + vlen + rend-end; + tmp = emalloc(len + 1); + tlen = sprintf(tmp, "Set-Cookie: %.*s=%s", nlen,name, value); + memcpy(tmp + tlen, end, rend-end); + tmp[len] = 0; + + efree(sapi_header->header); + efree(value); + efree(start); + + sapi_header->header = tmp; + sapi_header->header_len = len; + } + + + /* If existing call the sapi header handler */ + if (orig_header_handler) { + retval = orig_header_handler(sapi_header, sapi_headers TSRMLS_CC); + } + + return retval; +} +/* }}} */ + + +/* {{{ suhosin_hook_header_handler + */ +void suhosin_hook_header_handler() +{ + if (orig_header_handler == NULL) { + orig_header_handler = sapi_module.header_handler; + sapi_module.header_handler = suhosin_header_handler; + } +} +/* }}} */ + +/* {{{ suhosin_unhook_header_handler + */ +void suhosin_unhook_header_handler() +{ + sapi_module.header_handler = orig_header_handler; + orig_header_handler = NULL; +} +/* }}} */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + + -- cgit v1.3