From 7ce0f98b0be3ad15a664e506dff461cf6d633a69 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Sun, 13 Oct 2019 12:35:52 +0200 Subject: Add more patches --- 0.2.7/hardened-php-4.3.10-0.2.7.patch | 5918 +++++++++++++++++++++++++++++++++ 0.2.7/hardened-php-4.3.11-0.2.7.patch | 3417 +++++++++++++++++++ 0.2.7/hardened-php-5.0.4-0.2.7.patch | 3100 +++++++++++++++++ 3 files changed, 12435 insertions(+) create mode 100644 0.2.7/hardened-php-4.3.10-0.2.7.patch create mode 100644 0.2.7/hardened-php-4.3.11-0.2.7.patch create mode 100644 0.2.7/hardened-php-5.0.4-0.2.7.patch (limited to '0.2.7') diff --git a/0.2.7/hardened-php-4.3.10-0.2.7.patch b/0.2.7/hardened-php-4.3.10-0.2.7.patch new file mode 100644 index 0000000..cb5c546 --- /dev/null +++ b/0.2.7/hardened-php-4.3.10-0.2.7.patch @@ -0,0 +1,5918 @@ +diff -Nur php-4.3.10/README.input_filter hardened-php-4.3.10-0.2.7/README.input_filter +--- php-4.3.10/README.input_filter 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/README.input_filter 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,193 @@ ++Input Filter Support ported from PHP 5 ++-------------------------------------- ++ ++XSS (Cross Site Scripting) hacks are becoming more and more prevalent, ++and can be quite difficult to prevent. Whenever you accept user data ++and somehow display this data back to users, you are likely vulnerable ++to XSS hacks. ++ ++The Input Filter support in PHP 5 is aimed at providing the framework ++through which a company-wide or site-wide security policy can be ++enforced. It is implemented as a SAPI hook and is called from the ++treat_data and post handler functions. To implement your own security ++policy you will need to write a standard PHP extension. ++ ++A simple implementation might look like the following. This stores the ++original raw user data and adds a my_get_raw() function while the normal ++$_POST, $_GET and $_COOKIE arrays are only populated with stripped ++data. In this simple example all I am doing is calling strip_tags() on ++the data. If register_globals is turned on, the default globals that ++are created will be stripped ($foo) while a $RAW_foo is created with the ++original user input. ++ ++ZEND_BEGIN_MODULE_GLOBALS(my_input_filter) ++ zval *post_array; ++ zval *get_array; ++ zval *cookie_array; ++ZEND_END_MODULE_GLOBALS(my_input_filter) ++ ++#ifdef ZTS ++#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v) ++#else ++#define IF_G(v) (my_input_filter_globals.v) ++#endif ++ ++ZEND_DECLARE_MODULE_GLOBALS(my_input_filter) ++ ++function_entry my_input_filter_functions[] = { ++ PHP_FE(my_get_raw, NULL) ++ {NULL, NULL, NULL} ++}; ++ ++zend_module_entry my_input_filter_module_entry = { ++ STANDARD_MODULE_HEADER, ++ "my_input_filter", ++ my_input_filter_functions, ++ PHP_MINIT(my_input_filter), ++ PHP_MSHUTDOWN(my_input_filter), ++ NULL, ++ PHP_RSHUTDOWN(my_input_filter), ++ PHP_MINFO(my_input_filter), ++ "0.1", ++ STANDARD_MODULE_PROPERTIES ++}; ++ ++PHP_MINIT_FUNCTION(my_input_filter) ++{ ++ ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL); ++ ++ REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT); ++ REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT); ++ REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT); ++ ++ sapi_register_input_filter(my_sapi_input_filter); ++ return SUCCESS; ++} ++ ++PHP_RSHUTDOWN_FUNCTION(my_input_filter) ++{ ++ if(IF_G(get_array)) { ++ zval_ptr_dtor(&IF_G(get_array)); ++ IF_G(get_array) = NULL; ++ } ++ if(IF_G(post_array)) { ++ zval_ptr_dtor(&IF_G(post_array)); ++ IF_G(post_array) = NULL; ++ } ++ if(IF_G(cookie_array)) { ++ zval_ptr_dtor(&IF_G(cookie_array)); ++ IF_G(cookie_array) = NULL; ++ } ++ return SUCCESS; ++} ++ ++PHP_MINFO_FUNCTION(my_input_filter) ++{ ++ php_info_print_table_start(); ++ php_info_print_table_row( 2, "My Input Filter Support", "enabled" ); ++ php_info_print_table_row( 2, "Revision", "$Revision: 1.1 $"); ++ php_info_print_table_end(); ++} ++ ++/* The filter handler. If you return 1 from it, then PHP also registers the ++ * (modified) variable. Returning 0 prevents PHP from registering the variable; ++ * you can use this if your filter already registers the variable under a ++ * different name, or if you just don't want the variable registered at all. */ ++SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter) ++{ ++ zval new_var; ++ zval *array_ptr = NULL; ++ char *raw_var; ++ int var_len; ++ ++ assert(*val != NULL); ++ ++ switch(arg) { ++ case PARSE_GET: ++ if(!IF_G(get_array)) { ++ ALLOC_ZVAL(array_ptr); ++ array_init(array_ptr); ++ INIT_PZVAL(array_ptr); ++ } ++ IF_G(get_array) = array_ptr; ++ break; ++ case PARSE_POST: ++ if(!IF_G(post_array)) { ++ ALLOC_ZVAL(array_ptr); ++ array_init(array_ptr); ++ INIT_PZVAL(array_ptr); ++ } ++ IF_G(post_array) = array_ptr; ++ break; ++ case PARSE_COOKIE: ++ if(!IF_G(cookie_array)) { ++ ALLOC_ZVAL(array_ptr); ++ array_init(array_ptr); ++ INIT_PZVAL(array_ptr); ++ } ++ IF_G(cookie_array) = array_ptr; ++ break; ++ } ++ Z_STRLEN(new_var) = val_len; ++ Z_STRVAL(new_var) = estrndup(*val, val_len); ++ Z_TYPE(new_var) = IS_STRING; ++ ++ var_len = strlen(var); ++ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */ ++ strcpy(raw_var, "RAW_"); ++ strlcat(raw_var,var,var_len+5); ++ ++ php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC); ++ ++ php_strip_tags(*val, val_len, NULL, NULL, 0); ++ ++ *new_val_len = strlen(*val); ++ return 1; ++} ++ ++PHP_FUNCTION(my_get_raw) ++{ ++ long arg; ++ char *var; ++ int var_len; ++ zval **tmp; ++ zval *array_ptr = NULL; ++ HashTable *hash_ptr; ++ char *raw_var; ++ ++ if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) { ++ return; ++ } ++ ++ switch(arg) { ++ case PARSE_GET: ++ array_ptr = IF_G(get_array); ++ break; ++ case PARSE_POST: ++ array_ptr = IF_G(post_array); ++ break; ++ case PARSE_COOKIE: ++ array_ptr = IF_G(post_array); ++ break; ++ } ++ ++ if(!array_ptr) RETURN_FALSE; ++ ++ /* ++ * I'm changing the variable name here because when running with register_globals on, ++ * the variable will end up in the global symbol table ++ */ ++ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */ ++ strcpy(raw_var, "RAW_"); ++ strlcat(raw_var,var,var_len+5); ++ hash_ptr = HASH_OF(array_ptr); ++ ++ if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) { ++ *return_value = **tmp; ++ zval_copy_ctor(return_value); ++ } else { ++ RETVAL_FALSE; ++ } ++ efree(raw_var); ++} ++ +diff -Nur php-4.3.10/TSRM/TSRM.h hardened-php-4.3.10-0.2.7/TSRM/TSRM.h +--- php-4.3.10/TSRM/TSRM.h 2002-10-05 13:26:17.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/TSRM/TSRM.h 2005-04-07 01:51:16.000000000 +0200 +@@ -33,6 +33,13 @@ + # define TSRM_API + #endif + ++#if HARDENED_PHP ++# if HAVE_REALPATH ++# undef realpath ++# define realpath php_realpath ++# endif ++#endif ++ + /* Only compile multi-threading functions if we're in ZTS mode */ + #ifdef ZTS + +@@ -90,6 +97,7 @@ + + #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts + ++ + #ifdef __cplusplus + extern "C" { + #endif +diff -Nur php-4.3.10/TSRM/tsrm_virtual_cwd.c hardened-php-4.3.10-0.2.7/TSRM/tsrm_virtual_cwd.c +--- php-4.3.10/TSRM/tsrm_virtual_cwd.c 2004-12-02 02:04:46.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/TSRM/tsrm_virtual_cwd.c 2005-04-07 01:51:16.000000000 +0200 +@@ -17,7 +17,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: tsrm_virtual_cwd.c,v 1.41.2.8 2004/12/02 01:04:46 sesser Exp $ */ ++/* $Id: tsrm_virtual_cwd.c,v 1.41.2.4 2003/07/28 18:35:34 iliaa Exp $ */ + + #include + #include +@@ -192,6 +192,165 @@ + return p; + } + ++#if HARDENED_PHP ++CWD_API char *php_realpath(const char *path, char *resolved) ++{ ++ struct stat sb; ++ char *p, *q, *s; ++ size_t left_len, resolved_len; ++ unsigned symlinks; ++ int serrno, slen; ++ int is_dir = 1; ++ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; ++ ++ serrno = errno; ++ symlinks = 0; ++ if (path[0] == '/') { ++ resolved[0] = '/'; ++ resolved[1] = '\0'; ++ if (path[1] == '\0') ++ return (resolved); ++ resolved_len = 1; ++ left_len = strlcpy(left, path + 1, sizeof(left)); ++ } else { ++ if (getcwd(resolved, PATH_MAX) == NULL) { ++ strlcpy(resolved, ".", PATH_MAX); ++ return (NULL); ++ } ++ resolved_len = strlen(resolved); ++ left_len = strlcpy(left, path, sizeof(left)); ++ } ++ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ ++ /* ++ * Iterate over path components in `left'. ++ */ ++ while (left_len != 0) { ++ /* ++ * Extract the next path component and adjust `left' ++ * and its length. ++ */ ++ p = strchr(left, '/'); ++ s = p ? p : left + left_len; ++ if (s - left >= sizeof(next_token)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ memcpy(next_token, left, s - left); ++ next_token[s - left] = '\0'; ++ left_len -= s - left; ++ if (p != NULL) ++ memmove(left, s + 1, left_len + 1); ++ if (resolved[resolved_len - 1] != '/') { ++ if (resolved_len + 1 >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ resolved[resolved_len++] = '/'; ++ resolved[resolved_len] = '\0'; ++ } ++ if (next_token[0] == '\0') ++ continue; ++ else if (strcmp(next_token, ".") == 0) ++ continue; ++ else if (strcmp(next_token, "..") == 0) { ++ /* ++ * Strip the last path component except when we have ++ * single "/" ++ */ ++ if (!is_dir) { ++ errno = ENOENT; ++ return (NULL); ++ } ++ if (resolved_len > 1) { ++ resolved[resolved_len - 1] = '\0'; ++ q = strrchr(resolved, '/'); ++ *q = '\0'; ++ resolved_len = q - resolved; ++ } ++ continue; ++ } ++ ++ /* ++ * Append the next path component and lstat() it. If ++ * lstat() fails we still can return successfully if ++ * there are no more path components left. ++ */ ++ resolved_len = strlcat(resolved, next_token, PATH_MAX); ++ if (resolved_len >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ if (lstat(resolved, &sb) != 0) { ++ if (errno == ENOENT && p == NULL) { ++ errno = serrno; ++ return (resolved); ++ } ++ return (NULL); ++ } ++ if (S_ISLNK(sb.st_mode)) { ++ if (symlinks++ > MAXSYMLINKS) { ++ errno = ELOOP; ++ return (NULL); ++ } ++ slen = readlink(resolved, symlink, sizeof(symlink) - 1); ++ if (slen < 0) ++ return (NULL); ++ symlink[slen] = '\0'; ++ if (symlink[0] == '/') { ++ resolved[1] = 0; ++ resolved_len = 1; ++ } else if (resolved_len > 1) { ++ /* Strip the last path component. */ ++ resolved[resolved_len - 1] = '\0'; ++ q = strrchr(resolved, '/'); ++ *q = '\0'; ++ resolved_len = q - resolved; ++ } ++ ++ /* ++ * If there are any path components left, then ++ * append them to symlink. The result is placed ++ * in `left'. ++ */ ++ if (p != NULL) { ++ if (symlink[slen - 1] != '/') { ++ if (slen + 1 >= sizeof(symlink)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ symlink[slen] = '/'; ++ symlink[slen + 1] = 0; ++ } ++ left_len = strlcat(symlink, left, sizeof(left)); ++ if (left_len >= sizeof(left)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ } ++ left_len = strlcpy(left, symlink, sizeof(left)); ++ } else { ++ if (S_ISDIR(sb.st_mode)) { ++ is_dir = 1; ++ } else { ++ is_dir = 0; ++ } ++ } ++ } ++ ++ /* ++ * Remove trailing slash except when the resolved pathname ++ * is a single "/". ++ */ ++ if (resolved_len > 1 && resolved[resolved_len - 1] == '/') ++ resolved[resolved_len - 1] = '\0'; ++ return (resolved); ++} ++#endif ++ + CWD_API void virtual_cwd_startup(void) + { + char cwd[MAXPATHLEN]; +@@ -314,8 +473,7 @@ + path = resolved_path; + path_length = strlen(path); + } else { +- /* disable for now +- return 1; */ ++ return 1; + } + } + } else { /* Concat current directory with relative path and then run realpath() on it */ +@@ -341,9 +499,8 @@ + path = resolved_path; + path_length = strlen(path); + } else { +- /* disable for now + free(tmp); +- return 1; */ ++ return 1; + } + } + free(tmp); +@@ -852,7 +1009,7 @@ + dir_length = CWDG(cwd).cwd_length; + dir = CWDG(cwd).cwd; + +- ptr = command_line = (char *) malloc(command_length + sizeof("cd '' ; ") + dir_length +1+1); ++ ptr = command_line = (char *) malloc(command_length + sizeof("cd '' ; ") + dir_length +extra+1+1); + if (!command_line) { + return NULL; + } +diff -Nur php-4.3.10/TSRM/tsrm_virtual_cwd.h hardened-php-4.3.10-0.2.7/TSRM/tsrm_virtual_cwd.h +--- php-4.3.10/TSRM/tsrm_virtual_cwd.h 2003-09-20 04:08:12.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/TSRM/tsrm_virtual_cwd.h 2005-04-07 01:51:16.000000000 +0200 +@@ -128,6 +128,22 @@ + + typedef int (*verify_path_func)(const cwd_state *); + ++#ifndef HAVE_STRLCPY ++CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz); ++#undef strlcpy ++#define strlcpy php_strlcpy ++#endif ++ ++#ifndef HAVE_STRLCAT ++CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz); ++#undef strlcat ++#define strlcat php_strlcat ++#endif ++ ++ ++#if HARDENED_PHP ++CWD_API char *php_realpath(const char *path, char *resolved); ++#endif + CWD_API void virtual_cwd_startup(void); + CWD_API void virtual_cwd_shutdown(void); + CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC); +diff -Nur php-4.3.10/Zend/zend.c hardened-php-4.3.10-0.2.7/Zend/zend.c +--- php-4.3.10/Zend/zend.c 2004-12-06 16:35:03.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend.c 2005-04-07 01:51:16.000000000 +0200 +@@ -53,6 +53,12 @@ + ZEND_API void (*zend_unblock_interruptions)(void); + ZEND_API void (*zend_ticks_function)(int ticks); + ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); ++#if HARDENED_PHP ++ZEND_API void (*zend_security_log)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ZEND_API int (*zend_is_valid_include)(zval *z); ++#endif + + void (*zend_on_timeout)(int seconds TSRMLS_DC); + +@@ -424,6 +430,14 @@ + extern zend_scanner_globals language_scanner_globals; + #endif + ++ /* Set up Hardened-PHP utility functions first */ ++#if HARDENED_PHP ++ zend_security_log = utility_functions->security_log_function; ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ zend_is_valid_include = utility_functions->is_valid_include; ++#endif ++ + #ifdef ZTS + ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor); + #else +diff -Nur php-4.3.10/Zend/zend.h hardened-php-4.3.10-0.2.7/Zend/zend.h +--- php-4.3.10/Zend/zend.h 2004-07-28 21:06:48.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/Zend/zend.h 2005-04-07 01:51:16.000000000 +0200 +@@ -261,9 +261,9 @@ + struct _zval_struct { + /* Variable information */ + zvalue_value value; /* value */ ++ zend_uint refcount; + zend_uchar type; /* active type */ + zend_uchar is_ref; +- zend_ushort refcount; + }; + + +@@ -324,6 +324,12 @@ + void (*ticks_function)(int ticks); + void (*on_timeout)(int seconds TSRMLS_DC); + zend_bool (*open_function)(const char *filename, struct _zend_file_handle *); ++#if HARDENED_PHP ++ void (*security_log_function)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ int (*is_valid_include)(zval *z); ++#endif + } zend_utility_functions; + + +@@ -455,7 +461,16 @@ + extern ZEND_API void (*zend_ticks_function)(int ticks); + extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0); + extern void (*zend_on_timeout)(int seconds TSRMLS_DC); ++#if HARDENED_PHP ++extern ZEND_API void (*zend_security_log)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++extern ZEND_API int (*zend_is_valid_include)(zval *z); ++#endif + ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++ZEND_API unsigned int zend_canary(void); ++#endif + + ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 2, 3); + +@@ -574,6 +589,10 @@ + #define EMPTY_SWITCH_DEFAULT_CASE() + #endif + ++#if HARDENED_PHP ++#include "hardened_globals.h" ++#endif ++ + #endif /* ZEND_H */ + + /* +diff -Nur php-4.3.10/Zend/zend_alloc.c hardened-php-4.3.10-0.2.7/Zend/zend_alloc.c +--- php-4.3.10/Zend/zend_alloc.c 2004-08-27 18:51:25.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_alloc.c 2005-04-07 01:51:16.000000000 +0200 +@@ -56,6 +56,11 @@ + # define END_MAGIC_SIZE 0 + #endif + ++#if HARDENED_PHP_MM_PROTECT ++# define CANARY_SIZE sizeof(unsigned int) ++#else ++# define CANARY_SIZE 0 ++#endif + + # if MEMORY_LIMIT + # if ZEND_DEBUG +@@ -95,9 +100,17 @@ + if (p==AG(head)) { \ + AG(head) = p->pNext; \ + } else { \ ++ if (p != p->pLast->pNext) { \ ++ zend_security_log("linked list corrupt on efree() - heap corruption detected"); \ ++ exit(1); \ ++ } \ + p->pLast->pNext = p->pNext; \ + } \ + if (p->pNext) { \ ++ if (p != p->pNext->pLast) { \ ++ zend_security_log("linked list corrupt on efree() - heap corruption detected"); \ ++ exit(1); \ ++ } \ + p->pNext->pLast = p->pLast; \ + } + +@@ -129,6 +142,12 @@ + DECLARE_CACHE_VARS(); + TSRMLS_FETCH(); + ++#if HARDENED_PHP_MM_PROTECT ++ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) { ++ zend_security_log("emalloc() - requested size would result in integer overflow"); ++ exit(1); ++ } ++#endif + CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size); + + if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] > 0)) { +@@ -146,6 +165,10 @@ + AG(cache_stats)[CACHE_INDEX][1]++; + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif ++#if HARDENED_PHP_MM_PROTECT ++ p->canary = HG(canary_1); ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + p->cached = 0; + p->size = size; + return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING); +@@ -161,7 +184,7 @@ + AG(allocated_memory_peak) = AG(allocated_memory); + } + #endif +- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE); ++ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE); + } + + HANDLE_BLOCK_INTERRUPTIONS(); +@@ -191,7 +214,10 @@ + # endif + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif +- ++#if HARDENED_PHP_MM_PROTECT ++ p->canary = HG(canary_1); ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING); + } +@@ -218,17 +244,33 @@ + return emalloc_rel(lval + offset); + } + } +- ++ ++#if HARDENED_PHP ++ zend_security_log("Possible integer overflow catched by safe_emalloc()"); ++#endif + zend_error(E_ERROR, "Possible integer overflow in memory allocation (%ld * %ld + %ld)", nmemb, size, offset); + return 0; + } + + ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int *canary_2; ++#endif + zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING); + DECLARE_CACHE_VARS(); + TSRMLS_FETCH(); + ++#if HARDENED_PHP_MM_PROTECT ++ canary_2 = (unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE); ++ if (p->canary != HG(canary_1) || *canary_2 != HG(canary_2)) { ++ zend_security_log("canary mismatch on efree() - heap overflow or double efree detected"); ++ exit(1); ++ } ++ /* to catch double efree()s */ ++ *canary_2 = p->canary = 0; ++#endif ++ + #if defined(ZTS) && TSRM_DEBUG + if (p->thread_id != tsrm_thread_id()) { + tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) on thread %x freed at %s:(%d) on thread %x, ignoring", +@@ -273,6 +315,9 @@ + size_t _size = nmemb * size; + + if (nmemb && (_size/nmemb!=size)) { ++#if HARDENED_PHP ++ zend_security_log("Possible integer overflow catched by ecalloc()"); ++#endif + fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size); + #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID + kill(getpid(), SIGSEGV); +@@ -292,6 +337,9 @@ + + ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary_2; ++#endif + zend_mem_header *p; + zend_mem_header *orig; + DECLARE_CACHE_VARS(); +@@ -303,6 +351,14 @@ + + p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING); + ++#if HARDENED_PHP_MM_PROTECT ++ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE); ++ if (p->canary != HG(canary_1) || canary_2 != HG(canary_2)) { ++ zend_security_log("canary mismatch on erealloc() - heap overflow detected"); ++ exit(1); ++ } ++#endif ++ + #if defined(ZTS) && TSRM_DEBUG + if (p->thread_id != tsrm_thread_id()) { + void *new_p; +@@ -326,7 +382,7 @@ + } + #endif + REMOVE_POINTER_FROM_LIST(p); +- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE); ++ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE); + if (!p) { + if (!allow_failure) { + fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size); +@@ -348,6 +404,9 @@ + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif + ++#if HARDENED_PHP_MM_PROTECT ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + p->size = size; + + HANDLE_UNBLOCK_INTERRUPTIONS(); +@@ -423,6 +482,10 @@ + { + AG(head) = NULL; + ++#if HARDENED_PHP_MM_PROTECT ++ HG(canary_1) = zend_canary(); ++ HG(canary_2) = zend_canary(); ++#endif + #if MEMORY_LIMIT + AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */ + AG(allocated_memory) = 0; +diff -Nur php-4.3.10/Zend/zend_alloc.h hardened-php-4.3.10-0.2.7/Zend/zend_alloc.h +--- php-4.3.10/Zend/zend_alloc.h 2004-08-11 08:10:46.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_alloc.h 2005-04-07 01:51:16.000000000 +0200 +@@ -32,6 +32,9 @@ + #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL + + typedef struct _zend_mem_header { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary; ++#endif + #if ZEND_DEBUG + long magic; + char *filename; +diff -Nur php-4.3.10/Zend/zend_builtin_functions.c hardened-php-4.3.10-0.2.7/Zend/zend_builtin_functions.c +--- php-4.3.10/Zend/zend_builtin_functions.c 2004-04-01 21:05:01.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_builtin_functions.c 2005-04-07 01:51:16.000000000 +0200 +@@ -49,6 +49,9 @@ + static ZEND_FUNCTION(crash); + #endif + #endif ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++static ZEND_FUNCTION(heap_overflow); ++#endif + static ZEND_FUNCTION(get_included_files); + static ZEND_FUNCTION(is_subclass_of); + static ZEND_FUNCTION(is_a); +@@ -101,6 +104,9 @@ + ZEND_FE(crash, NULL) + #endif + #endif ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++ ZEND_FE(heap_overflow, NULL) ++#endif + ZEND_FE(get_included_files, NULL) + ZEND_FALIAS(get_required_files, get_included_files, NULL) + ZEND_FE(is_subclass_of, NULL) +@@ -805,6 +811,19 @@ + + #endif /* ZEND_DEBUG */ + ++ ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++ZEND_FUNCTION(heap_overflow) ++{ ++ char *nowhere = emalloc(10); ++ ++ memcpy(nowhere, "something1234567890", sizeof("something1234567890")); ++ ++ efree(nowhere); ++} ++#endif ++ ++ + /* {{{ proto array get_included_files(void) + Returns an array with the file names that were include_once()'d */ + ZEND_FUNCTION(get_included_files) +diff -Nur php-4.3.10/Zend/zend_canary.c hardened-php-4.3.10-0.2.7/Zend/zend_canary.c +--- php-4.3.10/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_canary.c 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,58 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */ ++ ++#include "zend.h" ++ ++#include ++#include ++ ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT ++ ++/* will be replaced later with more compatible method */ ++ZEND_API unsigned int zend_canary() ++{ ++ time_t t; ++ unsigned int canary; ++ int fd; ++ ++ fd = open("/dev/urandom", 0); ++ if (fd != -1) { ++ int r = read(fd, &canary, sizeof(canary)); ++ close(fd); ++ if (r == sizeof(canary)) { ++ return (canary); ++ } ++ } ++ /* not good but we never want to do this */ ++ time(&t); ++ canary = *(unsigned int *)&t + getpid() << 16; ++ return (canary); ++} ++#endif ++ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nur php-4.3.10/Zend/zend_execute.c hardened-php-4.3.10-0.2.7/Zend/zend_execute.c +--- php-4.3.10/Zend/zend_execute.c 2004-11-03 12:23:59.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_execute.c 2005-04-07 01:51:16.000000000 +0200 +@@ -2149,7 +2149,12 @@ + int dummy = 1; + zend_file_handle file_handle = {0}; + ++#if HARDENED_PHP_INC_PROTECT ++ if (zend_is_valid_include(inc_filename) ++ && zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS ++#else + if (zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS ++#endif + && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { + + file_handle.filename = inc_filename->value.str.val; +@@ -2178,6 +2183,11 @@ + break; + case ZEND_INCLUDE: + case ZEND_REQUIRE: ++#if HARDENED_PHP_INC_PROTECT ++ if (!zend_is_valid_include(inc_filename)) { ++ break; ++ } ++#endif + new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC); + break; + case ZEND_EVAL: { +diff -Nur php-4.3.10/Zend/zend_extensions.h hardened-php-4.3.10-0.2.7/Zend/zend_extensions.h +--- php-4.3.10/Zend/zend_extensions.h 2002-12-31 17:23:02.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_extensions.h 2005-04-07 01:51:16.000000000 +0200 +@@ -23,7 +23,9 @@ + + #include "zend_compile.h" + +-#define ZEND_EXTENSION_API_NO 20021010 ++/* Create own API version number for Hardened-PHP */ ++ ++#define ZEND_EXTENSION_API_NO 1020041222 + + typedef struct _zend_extension_version_info { + int zend_extension_api_no; +diff -Nur php-4.3.10/Zend/zend_hash.c hardened-php-4.3.10-0.2.7/Zend/zend_hash.c +--- php-4.3.10/Zend/zend_hash.c 2004-07-12 23:26:46.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_hash.c 2005-04-07 01:51:16.000000000 +0200 +@@ -26,6 +26,17 @@ + # include + #endif + ++#if HARDENED_PHP_HASH_PROTECT ++ unsigned int zend_hash_canary = 0x1234567; ++ zend_bool zend_hash_canary_inited = 0; ++#endif ++ ++#define CHECK_HASH_CANARY(hash) \ ++ if (zend_hash_canary != (hash)->canary) { \ ++ zend_security_log("Zend HashTable canary was overwritten"); \ ++ exit(1); \ ++ } ++ + #define HANDLE_NUMERIC(key, length, func) { \ + register char *tmp=key; \ + \ +@@ -175,6 +186,9 @@ + { + uint i = 3; + Bucket **tmp; ++#if HARDENED_PHP_HASH_PROTECT ++ TSRMLS_FETCH(); ++#endif + + SET_INCONSISTENT(HT_OK); + +@@ -184,6 +198,13 @@ + + ht->nTableSize = 1 << i; + ht->nTableMask = ht->nTableSize - 1; ++#if HARDENED_PHP_HASH_PROTECT ++ if (zend_hash_canary_inited==0) { ++ zend_hash_canary = zend_canary(); ++ zend_hash_canary_inited = 1; ++ } ++ ht->canary = zend_hash_canary; ++#endif + ht->pDestructor = pDestructor; + ht->pListHead = NULL; + ht->pListTail = NULL; +@@ -259,6 +280,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -327,6 +351,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -402,6 +429,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -450,7 +480,7 @@ + IS_CONSISTENT(ht); + + if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */ +- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent); ++ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent); + if (t) { + HANDLE_BLOCK_INTERRUPTIONS(); + ht->arBuckets = t; +@@ -460,6 +490,7 @@ + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } ++ zend_error(E_ERROR, "zend_hash_do_resize - out of memory"); + return FAILURE; + } + return SUCCESS; +@@ -524,6 +555,9 @@ + ht->pInternalPointer = p->pListNext; + } + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { +@@ -553,6 +587,9 @@ + q = p; + p = p->pListNext; + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { +@@ -579,6 +616,9 @@ + q = p; + p = p->pListNext; + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { +@@ -608,6 +648,9 @@ + HANDLE_BLOCK_INTERRUPTIONS(); + + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { +diff -Nur php-4.3.10/Zend/zend_hash.h hardened-php-4.3.10-0.2.7/Zend/zend_hash.h +--- php-4.3.10/Zend/zend_hash.h 2002-12-31 17:23:03.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_hash.h 2005-04-07 01:51:16.000000000 +0200 +@@ -54,6 +54,9 @@ + } Bucket; + + typedef struct _hashtable { ++#if HARDENED_PHP_HASH_PROTECT ++ unsigned int canary; ++#endif + uint nTableSize; + uint nTableMask; + uint nNumOfElements; +diff -Nur php-4.3.10/Zend/zend_llist.c hardened-php-4.3.10-0.2.7/Zend/zend_llist.c +--- php-4.3.10/Zend/zend_llist.c 2002-12-31 17:23:04.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_llist.c 2005-04-07 01:51:16.000000000 +0200 +@@ -21,9 +21,34 @@ + #include "zend.h" + #include "zend_llist.h" + #include "zend_qsort.h" ++#include "zend_globals.h" ++ ++#define CHECK_LIST_CANARY(list) \ ++ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \ ++ zend_security_log("linked list canary was overwritten"); \ ++ exit(1); \ ++ } ++ ++#define CHECK_LISTELEMENT_CANARY(elem) \ ++ if (HG(canary_3) != (elem)->canary) { \ ++ zend_security_log("linked list element canary was overwritten"); \ ++ exit(1); \ ++ } ++ + + ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent) + { ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ ++ if (!HG(ll_canary_inited)) { ++ HG(canary_3) = zend_canary(); ++ HG(canary_4) = zend_canary(); ++ HG(ll_canary_inited) = 1; ++ } ++ l->canary_h = HG(canary_3); ++ l->canary_t = HG(canary_4); ++#endif + l->head = NULL; + l->tail = NULL; + l->count = 0; +@@ -37,6 +62,11 @@ + { + zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent); + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++ tmp->canary = HG(canary_3); ++#endif + tmp->prev = l->tail; + tmp->next = NULL; + if (l->tail) { +@@ -55,6 +85,11 @@ + { + zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent); + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++ tmp->canary = HG(canary_3); ++#endif + tmp->next = l->head; + tmp->prev = NULL; + if (l->head) { +@@ -91,10 +126,20 @@ + zend_llist_element *current=l->head; + zend_llist_element *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + while (current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(current) ++#endif + next = current->next; + if (compare(current->data, element)) { + DEL_LLIST_ELEMENT(current, l); ++#if HARDENED_PHP_LL_PROTECT ++ current->canary = 0; ++#endif + break; + } + current = next; +@@ -106,7 +151,14 @@ + { + zend_llist_element *current=l->head, *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + while (current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(current) ++#endif + next = current->next; + if (l->dtor) { + l->dtor(current->data); +@@ -131,7 +183,14 @@ + zend_llist_element *old_tail; + void *data; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if ((old_tail = l->tail)) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(old_tail) ++#endif + if (l->tail->prev) { + l->tail->prev->next = NULL; + } +@@ -157,9 +216,16 @@ + { + zend_llist_element *ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(src) ++#endif + zend_llist_init(dst, src->size, src->dtor, src->persistent); + ptr = src->head; + while (ptr) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(ptr) ++#endif + zend_llist_add_element(dst, ptr->data); + ptr = ptr->next; + } +@@ -170,11 +236,21 @@ + { + zend_llist_element *element, *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + element=l->head; + while (element) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + next = element->next; + if (func(element->data)) { + DEL_LLIST_ELEMENT(element, l); ++#if HARDENED_PHP_LL_PROTECT ++ element->canary = 0; ++#endif + } + element = next; + } +@@ -185,7 +261,13 @@ + { + zend_llist_element *element; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data TSRMLS_CC); + } + } +@@ -197,6 +279,9 @@ + zend_llist_element **elements; + zend_llist_element *element, **ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + if (l->count <= 0) { + return; + } +@@ -206,6 +291,9 @@ + ptr = &elements[0]; + + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + *ptr++ = element; + } + +@@ -228,7 +316,13 @@ + { + zend_llist_element *element; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data, arg TSRMLS_CC); + } + } +@@ -239,8 +333,14 @@ + zend_llist_element *element; + va_list args; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + va_start(args, num_args); + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data, num_args, args TSRMLS_CC); + } + va_end(args); +@@ -249,6 +349,10 @@ + + ZEND_API int zend_llist_count(zend_llist *l) + { ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + return l->count; + } + +@@ -256,8 +360,15 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + *current = l->head; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } else { + return NULL; +@@ -269,8 +380,15 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + *current = l->tail; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } else { + return NULL; +@@ -282,9 +400,19 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + *current = (*current)->next; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } + } +@@ -296,9 +424,19 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + *current = (*current)->prev; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } + } +diff -Nur php-4.3.10/Zend/zend_llist.h hardened-php-4.3.10-0.2.7/Zend/zend_llist.h +--- php-4.3.10/Zend/zend_llist.h 2002-12-31 17:23:04.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_llist.h 2005-04-07 01:51:16.000000000 +0200 +@@ -24,6 +24,9 @@ + #include + + typedef struct _zend_llist_element { ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary; ++#endif + struct _zend_llist_element *next; + struct _zend_llist_element *prev; + char data[1]; /* Needs to always be last in the struct */ +@@ -36,6 +39,9 @@ + typedef void (*llist_apply_func_t)(void * TSRMLS_DC); + + typedef struct _zend_llist { ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_h; /* head */ ++#endif + zend_llist_element *head; + zend_llist_element *tail; + size_t size; +@@ -43,6 +49,9 @@ + llist_dtor_func_t dtor; + unsigned char persistent; + zend_llist_element *traverse_ptr; ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_t; /* tail */ ++#endif + } zend_llist; + + typedef zend_llist_element* zend_llist_position; +diff -Nur php-4.3.10/Zend/zend_modules.h hardened-php-4.3.10-0.2.7/Zend/zend_modules.h +--- php-4.3.10/Zend/zend_modules.h 2002-12-31 17:23:04.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/Zend/zend_modules.h 2005-04-07 01:51:16.000000000 +0200 +@@ -34,7 +34,7 @@ + ZEND_API extern unsigned char second_arg_force_ref[]; + ZEND_API extern unsigned char third_arg_force_ref[]; + +-#define ZEND_MODULE_API_NO 20020429 ++#define ZEND_MODULE_API_NO 1020041222 + #ifdef ZTS + #define USING_ZTS 1 + #else +diff -Nur php-4.3.10/acinclude.m4 hardened-php-4.3.10-0.2.7/acinclude.m4 +--- php-4.3.10/acinclude.m4 2004-12-11 12:17:21.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/acinclude.m4 2005-04-07 01:51:16.000000000 +0200 +@@ -1153,6 +1153,36 @@ + fi + ]) + ++dnl ++dnl Check for broken realpath() ++dnl ++dnl realpath("/etc/hosts/../passwd",XXX) should not return ++dnl "/etc/passwd" ++dnl ++AC_DEFUN([PHP_AC_BROKEN_REALPATH],[ ++ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[ ++ AC_TRY_RUN([ ++main() { ++ char buf[4096+1]; ++ buf[0] = 0; ++ realpath("/etc/hosts/../passwd", buf); ++ exit(strcmp(buf, "/etc/passwd")==0); ++} ++ ],[ ++ ac_cv_broken_realpath=no ++ ],[ ++ ac_cv_broken_realpath=yes ++ ],[ ++ ac_cv_broken_realpath=no ++ ]) ++ ]) ++ if test "$ac_cv_broken_realpath" = "yes"; then ++ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken]) ++ else ++ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken]) ++ fi ++]) ++ + dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx) + dnl + dnl Basically sets up the link-stage for building module-name +diff -Nur php-4.3.10/configure hardened-php-4.3.10-0.2.7/configure +--- php-4.3.10/configure 2004-12-14 18:55:18.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/configure 2005-04-07 01:51:16.000000000 +0200 +@@ -389,6 +389,16 @@ + ac_default_prefix=/usr/local + # Any additions from configure.in: + ac_help="$ac_help ++ --disable-hardened-php-mm-protect Disable the Memory Manager protection." ++ac_help="$ac_help ++ --disable-hardened-php-ll-protect Disable the Linked List protection." ++ac_help="$ac_help ++ --disable-hardened-php-inc-protect Disable include/require protection." ++ac_help="$ac_help ++ --disable-hardened-php-fmt-protect Disable format string protection." ++ac_help="$ac_help ++ --disable-hardened-php-hash-protect Disable Zend HashTable DTOR protection." ++ac_help="$ac_help + + SAPI modules: + " +@@ -831,6 +841,8 @@ + ac_help="$ac_help + --disable-tokenizer Disable tokenizer support" + ac_help="$ac_help ++ --disable-varfilter Disable Hardened-PHP's variable filter" ++ac_help="$ac_help + --enable-wddx Enable WDDX support." + ac_help="$ac_help + --disable-xml Disable XML support using bundled expat lib" +@@ -2643,6 +2655,157 @@ + + + ++# Check whether --enable-hardened-php-mm-protect or --disable-hardened-php-mm-protect was given. ++if test "${enable_hardened_php_mm_protect+set}" = set; then ++ enableval="$enable_hardened_php_mm_protect" ++ ++ DO_HARDENED_PHP_MM_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_MM_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-ll-protect or --disable-hardened-php-ll-protect was given. ++if test "${enable_hardened_php_ll_protect+set}" = set; then ++ enableval="$enable_hardened_php_ll_protect" ++ ++ DO_HARDENED_PHP_LL_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_LL_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-inc-protect or --disable-hardened-php-inc-protect was given. ++if test "${enable_hardened_php_inc_protect+set}" = set; then ++ enableval="$enable_hardened_php_inc_protect" ++ ++ DO_HARDENED_PHP_INC_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_INC_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-fmt-protect or --disable-hardened-php-fmt-protect was given. ++if test "${enable_hardened_php_fmt_protect+set}" = set; then ++ enableval="$enable_hardened_php_fmt_protect" ++ ++ DO_HARDENED_PHP_FMT_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_FMT_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-hash-protect or --disable-hardened-php-hash-protect was given. ++if test "${enable_hardened_php_hash_protect+set}" = set; then ++ enableval="$enable_hardened_php_hash_protect" ++ ++ DO_HARDENED_PHP_HASH_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_HASH_PROTECT=yes ++ ++fi ++ ++ ++echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6 ++echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_MM_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6 ++echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_LL_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6 ++echo "configure:2733: checking whether to protect include/require statements" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_INC_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6 ++echo "configure:2737: checking whether to protect PHP Format String functions" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_FMT_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6 ++echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_HASH_PROTECT" 1>&6 ++ ++ ++cat >> confdefs.h <<\EOF ++#define HARDENED_PHP 1 ++EOF ++ ++ ++ ++if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_MM_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_MM_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_LL_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_LL_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_INC_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_INC_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_FMT_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_FMT_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_HASH_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_HASH_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_HASH_PROTECT 0 ++EOF ++ ++fi + + + +@@ -14890,6 +15053,62 @@ + fi + + ++ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6 ++echo "configure:14928: checking whether realpath is broken" >&5 ++if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ ++ if test "$cross_compiling" = yes; then ++ ++ ac_cv_broken_realpath=no ++ ++else ++ cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null ++then ++ ++ ac_cv_broken_realpath=no ++ ++else ++ echo "configure: failed program was:" >&5 ++ cat conftest.$ac_ext >&5 ++ rm -fr conftest* ++ ++ ac_cv_broken_realpath=yes ++ ++fi ++rm -fr conftest* ++fi ++ ++ ++fi ++ ++echo "$ac_t""$ac_cv_broken_realpath" 1>&6 ++ if test "$ac_cv_broken_realpath" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define PHP_BROKEN_REALPATH 1 ++EOF ++ ++ else ++ cat >> confdefs.h <<\EOF ++#define PHP_BROKEN_REALPATH 0 ++EOF ++ ++ fi ++ ++ + echo $ac_n "checking for declared timezone""... $ac_c" 1>&6 + echo "configure:14895: checking for declared timezone" >&5 + if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then +@@ -82014,6 +82233,265 @@ + fi + + ++echo $ac_n "checking whether to enable Hardened-PHP's variable filter""... $ac_c" 1>&6 ++echo "configure:82041: checking whether to enable Hardened-PHP's variable filter" >&5 ++# Check whether --enable-varfilter or --disable-varfilter was given. ++if test "${enable_varfilter+set}" = set; then ++ enableval="$enable_varfilter" ++ PHP_VARFILTER=$enableval ++else ++ ++ PHP_VARFILTER=yes ++ ++ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then ++ PHP_VARFILTER=$PHP_ENABLE_ALL ++ fi ++ ++fi ++ ++ ++ ++ext_output="yes, shared" ++ext_shared=yes ++case $PHP_VARFILTER in ++shared,*) ++ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'` ++ ;; ++shared) ++ PHP_VARFILTER=yes ++ ;; ++no) ++ ext_output=no ++ ext_shared=no ++ ;; ++*) ++ ext_output=yes ++ ext_shared=no ++ ;; ++esac ++ ++ ++ ++echo "$ac_t""$ext_output" 1>&6 ++ ++ ++ ++ ++if test "$PHP_VARFILTER" != "no"; then ++ cat >> confdefs.h <<\EOF ++#define HAVE_VARFILTER 1 ++EOF ++ ++ ++ ext_builddir=ext/varfilter ++ ext_srcdir=$abs_srcdir/ext/varfilter ++ ++ ac_extra= ++ ++ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then ++ ++ ++ ++ case ext/varfilter in ++ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;; ++ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;; ++ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;; ++ esac ++ ++ ++ ++ b_c_pre=$php_c_pre ++ b_cxx_pre=$php_cxx_pre ++ b_c_meta=$php_c_meta ++ b_cxx_meta=$php_cxx_meta ++ b_c_post=$php_c_post ++ b_cxx_post=$php_cxx_post ++ b_lo=$php_lo ++ ++ ++ old_IFS=$IFS ++ for ac_src in varfilter.c; do ++ ++ IFS=. ++ set $ac_src ++ ac_obj=$1 ++ IFS=$old_IFS ++ ++ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo" ++ ++ case $ac_src in ++ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; ++ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;; ++ esac ++ ++ cat >>Makefile.objects<>Makefile.objects<>Makefile.objects<> confdefs.h <>Makefile.objects<>Makefile.objects<&6 +@@ -94503,7 +94981,7 @@ + php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ + strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \ + streams.c network.c php_open_temporary_file.c php_logos.c \ +- output.c memory_streams.c user_streams.c; do ++ output.c memory_streams.c user_streams.c hardened_php.c; do + + IFS=. + set $ac_src +@@ -94676,7 +95154,7 @@ + zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \ + zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ + zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ +- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c; do ++ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c; do + + IFS=. + set $ac_src +diff -Nur php-4.3.10/configure.in hardened-php-4.3.10-0.2.7/configure.in +--- php-4.3.10/configure.in 2004-12-14 17:07:49.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/configure.in 2005-04-07 01:51:16.000000000 +0200 +@@ -205,7 +205,7 @@ + sinclude(Zend/acinclude.m4) + sinclude(Zend/Zend.m4) + sinclude(TSRM/tsrm.m4) +- ++sinclude(main/hardened_php.m4) + + + divert(2) +@@ -573,6 +573,7 @@ + AC_FUNC_ALLOCA + dnl PHP_AC_BROKEN_SPRINTF + dnl PHP_AC_BROKEN_SNPRINTF ++PHP_AC_BROKEN_REALPATH + PHP_DECLARED_TIMEZONE + PHP_TIME_R_TYPE + PHP_READDIR_R_TYPE +@@ -1201,7 +1202,7 @@ + php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ + strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \ + streams.c network.c php_open_temporary_file.c php_logos.c \ +- output.c memory_streams.c user_streams.c) ++ output.c memory_streams.c user_streams.c hardened_php.c) + PHP_ADD_SOURCES(/main, internal_functions.c,, sapi) + PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli) + +@@ -1214,7 +1215,7 @@ + zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \ + zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ + zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ +- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c) ++ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c ) + + if test -r "$abs_srcdir/Zend/zend_objects.c"; then + PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c) +diff -Nur php-4.3.10/ext/curl/curl.c hardened-php-4.3.10-0.2.7/ext/curl/curl.c +--- php-4.3.10/ext/curl/curl.c 2004-11-01 05:56:10.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/curl/curl.c 2005-04-07 01:51:16.000000000 +0200 +@@ -16,7 +16,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: curl.c,v 1.124.2.27 2004/11/01 04:56:10 iliaa Exp $ */ ++/* $Id: curl.c,v 1.124.2.29 2005/03/14 09:03:09 sniper Exp $ */ + + #ifdef HAVE_CONFIG_H + #include "config.h" +@@ -50,6 +50,7 @@ + #include "ext/standard/php_smart_str.h" + #include "ext/standard/info.h" + #include "ext/standard/file.h" ++#include "ext/standard/url.h" + #include "php_curl.h" + + static int le_curl; +@@ -64,6 +65,26 @@ + #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s), (char *) v, 1); + #define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s), (zval *) v); + ++#define PHP_CURL_CHECK_OPEN_BASEDIR(str, len) \ ++ if (PG(open_basedir) && *PG(open_basedir) && \ ++ strncasecmp(str, "file://", sizeof("file://") - 1) == 0) \ ++ { \ ++ php_url *tmp_url; \ ++ \ ++ if (!(tmp_url = php_url_parse_ex(str, len))) { \ ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid url '%s'", str); \ ++ RETURN_FALSE; \ ++ } \ ++ \ ++ if (php_check_open_basedir(tmp_url->path TSRMLS_CC) || \ ++ (PG(safe_mode) && !php_checkuid(tmp_url->path, "rb+", CHECKUID_CHECK_MODE_PARAM)) \ ++ ) { \ ++ php_url_free(tmp_url); \ ++ RETURN_FALSE; \ ++ } \ ++ php_url_free(tmp_url); \ ++ } ++ + /* {{{ curl_functions[] + */ + function_entry curl_functions[] = { +@@ -682,6 +703,11 @@ + WRONG_PARAM_COUNT; + } + ++ if (argc > 0) { ++ convert_to_string_ex(url); ++ PHP_CURL_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(url), Z_STRLEN_PP(url)); ++ } ++ + alloc_curl_handle(&ch); + + ch->cp = curl_easy_init(); +@@ -712,7 +738,6 @@ + + if (argc > 0) { + char *urlcopy; +- convert_to_string_ex(url); + + urlcopy = estrndup(Z_STRVAL_PP(url), Z_STRLEN_PP(url)); + curl_easy_setopt(ch->cp, CURLOPT_URL, urlcopy); +@@ -724,7 +749,7 @@ + } + /* }}} */ + +-/* {{{ proto bool curl_setopt(resource ch, string option, mixed value) ++/* {{{ proto bool curl_setopt(resource ch, int option, mixed value) + Set an option for a CURL transfer */ + PHP_FUNCTION(curl_setopt) + { +@@ -819,8 +844,12 @@ + char *copystr = NULL; + + convert_to_string_ex(zvalue); +- copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); + ++ if (option == CURLOPT_URL) { ++ PHP_CURL_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); ++ } ++ ++ copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); + error = curl_easy_setopt(ch->cp, option, copystr); + zend_llist_add_element(&ch->to_free.str, ©str); + +@@ -955,16 +984,16 @@ + if (*postval == '@') { + error = curl_formadd(&first, &last, + CURLFORM_COPYNAME, string_key, +- CURLFORM_NAMELENGTH, string_key_len - 1, ++ CURLFORM_NAMELENGTH, (long)string_key_len - 1, + CURLFORM_FILE, ++postval, + CURLFORM_END); + } + else { + error = curl_formadd(&first, &last, + CURLFORM_COPYNAME, string_key, +- CURLFORM_NAMELENGTH, string_key_len - 1, ++ CURLFORM_NAMELENGTH, (long)string_key_len - 1, + CURLFORM_COPYCONTENTS, postval, +- CURLFORM_CONTENTSLENGTH, Z_STRLEN_PP(current), ++ CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current), + CURLFORM_END); + } + } +diff -Nur php-4.3.10/ext/exif/exif.c hardened-php-4.3.10-0.2.7/ext/exif/exif.c +--- php-4.3.10/ext/exif/exif.c 2004-11-10 02:44:58.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/exif/exif.c 2005-04-07 01:51:16.000000000 +0200 +@@ -17,7 +17,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: exif.c,v 1.118.2.29 2004/11/10 01:44:58 iliaa Exp $ */ ++/* $Id: exif.c,v 1.118.2.37 2005/03/22 22:07:03 edink Exp $ */ + + /* ToDos + * +@@ -58,7 +58,7 @@ + #include "ext/standard/php_image.h" + #include "ext/standard/info.h" + +-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) ++#if defined(PHP_WIN32) || (HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)) + #define EXIF_USE_MBSTRING 1 + #else + #define EXIF_USE_MBSTRING 0 +@@ -68,6 +68,12 @@ + #include "ext/mbstring/mbstring.h" + #endif + ++/* needed for ssize_t definition */ ++#include ++#if defined(PHP_WIN32) && !defined(ssize_t) ++typedef SSIZE_T ssize_t; ++#endif ++ + typedef unsigned char uchar; + + #ifndef safe_emalloc +@@ -85,6 +91,8 @@ + + #define EFREE_IF(ptr) if (ptr) efree(ptr) + ++#define MAX_IFD_NESTING_LEVEL 100 ++ + static unsigned char exif_thumbnail_force_ref[] = {2, BYREF_NONE, BYREF_FORCE_REST}; + + /* {{{ exif_functions[] +@@ -99,7 +107,7 @@ + }; + /* }}} */ + +-#define EXIF_VERSION "1.4 $Id: exif.c,v 1.118.2.29 2004/11/10 01:44:58 iliaa Exp $" ++#define EXIF_VERSION "1.4 $Id: exif.c,v 1.118.2.37 2005/03/22 22:07:03 edink Exp $" + + /* {{{ PHP_MINFO_FUNCTION + */ +@@ -1430,6 +1438,7 @@ + /* for parsing */ + int read_thumbnail; + int read_all; ++ int ifd_nesting_level; + /* internal */ + file_section_list file; + } image_info_type; +@@ -2689,6 +2698,13 @@ + size_t byte_count, offset_val, fpos, fgot; + xp_field_type *tmp_xp; + ++ /* Protect against corrupt headers */ ++ if (ImageInfo->ifd_nesting_level > MAX_IFD_NESTING_LEVEL) { ++ exif_error_docref("exif_read_data#error_ifd" TSRMLS_CC, ImageInfo, E_WARNING, "corrupt EXIF header: maximum directory nesting level reached"); ++ return FALSE; ++ } ++ ImageInfo->ifd_nesting_level++; ++ + tag = php_ifd_get16u(dir_entry, ImageInfo->motorola_intel); + format = php_ifd_get16u(dir_entry+2, ImageInfo->motorola_intel); + components = php_ifd_get32u(dir_entry+4, ImageInfo->motorola_intel); +@@ -2702,6 +2718,11 @@ + + byte_count = components * php_tiff_bytes_per_format[format]; + ++ if ((ssize_t)byte_count < 0) { ++ exif_error_docref("exif_read_data#error_ifd" TSRMLS_CC, ImageInfo, E_WARNING, "Process tag(x%04X=%s): Illegal byte_count(%ld)", tag, exif_get_tagname(tag, tagname, -12, tag_table TSRMLS_CC), byte_count); ++ return FALSE; ++ } ++ + if (byte_count > 4) { + offset_val = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); + /* If its bigger than 4 bytes, the dir entry contains an offset. */ +@@ -3372,7 +3393,7 @@ + return FALSE; + } + php_stream_read(ImageInfo->infile, (char*)(ImageInfo->file.list[sn].data+2), dir_size-2); +- /*exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Dump: %s", exif_char_dump(ImageInfo->file.list[sn].data, dir_size, 0));*/ ++ /*exif_error_docref(NULL TSRMLS_CC, ImageInfo, E_NOTICE, "Dump: %s", exif_char_dump(ImageInfo->file.list[sn].data, dir_size, 0));*/ + next_offset = php_ifd_get32u(ImageInfo->file.list[sn].data + dir_size - 4, ImageInfo->motorola_intel); + #ifdef EXIF_DEBUG + exif_error_docref(NULL TSRMLS_CC, ImageInfo, E_NOTICE, "read from TIFF done, next offset x%04X", next_offset); +@@ -3713,6 +3734,8 @@ + } + } + ++ ImageInfo->ifd_nesting_level = 0; ++ + /* Scan the JPEG headers. */ + ret = exif_scan_FILE_header(ImageInfo TSRMLS_CC); + +diff -Nur php-4.3.10/ext/fbsql/php_fbsql.c hardened-php-4.3.10-0.2.7/ext/fbsql/php_fbsql.c +--- php-4.3.10/ext/fbsql/php_fbsql.c 2004-08-24 20:00:05.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/ext/fbsql/php_fbsql.c 2005-04-07 01:51:16.000000000 +0200 +@@ -16,7 +16,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: php_fbsql.c,v 1.86.2.9 2004/08/24 18:00:05 fmk Exp $ */ ++/* $Id: php_fbsql.c,v 1.86.2.14 2005/02/09 19:33:32 fmk Exp $ */ + + /* TODO: + * +@@ -459,11 +459,11 @@ + + if (FB_SQL_G(allowPersistent)) + { +- sprintf(buf, "%ld", FB_SQL_G(persistentCount)); ++ snprintf(buf, sizeof(buf), "%ld", FB_SQL_G(persistentCount)); + php_info_print_table_row(2, "Active Persistent Links", buf); + } + +- sprintf(buf, "%ld", FB_SQL_G(linkCount)); ++ snprintf(buf, sizeof(buf), "%ld", FB_SQL_G(linkCount)); + php_info_print_table_row(2, "Active Links", buf); + + /* +@@ -507,7 +507,9 @@ + if (userName == NULL) userName = FB_SQL_G(userName); + if (userPassword == NULL) userPassword = FB_SQL_G(userPassword); + +- sprintf(name, "fbsql_%s_%s_%s", hostName, userName, userPassword); ++ if (snprintf(name, sizeof(name), "fbsql_%s_%s_%s", hostName, userName, userPassword) < 0) { ++ RETURN_FALSE; ++ } + + if (!FB_SQL_G(allowPersistent)) { + persistent=0; +@@ -818,9 +820,21 @@ + WRONG_PARAM_COUNT; + break; + } ++ ++ if (Z_LVAL_PP(Locking) < 0 || Z_LVAL_PP(Locking) > 2) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid locking type."); ++ RETURN_FALSE; ++ } ++ if (Z_LVAL_PP(Isolation) < 0 || Z_LVAL_PP(Isolation) > 4) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid isolation type."); ++ RETURN_FALSE; ++ } ++ + ZEND_FETCH_RESOURCE2(phpLink, PHPFBLink *, fbsql_link_index, -1, "FrontBase-Link", le_link, le_plink); + +- sprintf(strSQL, "SET TRANSACTION LOCKING %s, ISOLATION %s;", strLocking[Z_LVAL_PP(Locking)], strIsolation[Z_LVAL_PP(Isolation)]); ++ if (snprintf(strSQL, sizeof(strSQL) , "SET TRANSACTION LOCKING %s, ISOLATION %s;", strLocking[Z_LVAL_PP(Locking)], strIsolation[Z_LVAL_PP(Isolation)]) < 0) { ++ RETURN_FALSE; ++ } + + md = fbcdcExecuteDirectSQL(phpLink->connection, strSQL); + fbcmdRelease(md); +@@ -1417,7 +1431,9 @@ + convert_to_string_ex(password); + userPassword = Z_STRVAL_PP(password); + +- sprintf(buffer, "SET AUTHORIZATION %s;", userName); ++ if (snprintf(buffer, sizeof(buffer), "SET AUTHORIZATION %s;", userName) < 0) { ++ RETURN_FALSE; ++ } + + phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU, buffer, phpLink); + if (Z_LVAL_P(return_value)) +@@ -1791,11 +1807,28 @@ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No message"); + } + link->errorText = strdup(emg); +- link->errorNo = fbcemdErrorCodeAtIndex(emd, 0);; ++ link->errorNo = fbcemdErrorCodeAtIndex(emd, 0); + free(emg); + fbcemdRelease(emd); + result = 0; + } ++ else if (fbcmdWarningsFound(md)) ++ { ++ FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md); ++ char* emg = fbcemdAllErrorMessages(emd); ++ if (FB_SQL_G(generateWarnings)) ++ { ++ if (emg) ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Warning in statement: '%s' %s", sql, emg); ++ else ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No message"); ++ } ++ link->errorText = strdup(emg); ++ link->errorNo = fbcemdErrorCodeAtIndex(emd, 0); ++ free(emg); ++ fbcemdRelease(emd); ++ result = 1; ++ } + return result; + } + /* }}} */ +@@ -1824,9 +1857,12 @@ + md = meta; + + tp = fbcmdStatementType(md); +- +- if ((tp[0] == 'C') || (tp[0] == 'R')) +- { ++ if (tp == NULL) { ++ fbcmdRelease(meta); ++ ZVAL_BOOL(return_value, 1) ++ } ++ else if ((tp[0] == 'C') || (tp[0] == 'R')) ++ { + if (sR == 1 && md) fbcmdRelease(md); + ZVAL_BOOL(return_value, 1) + } +@@ -2084,7 +2120,9 @@ + RETURN_FALSE; + } + +- sprintf(sql, "SELECT * FROM %s WHERE 1=0;", tableName); ++ if (snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE 1=0;", tableName) < 0) { ++ RETURN_FALSE; ++ } + + phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU, sql, phpLink); + } +@@ -2268,7 +2306,7 @@ + { + int v = *((int*)data); + char b[128]; +- sprintf(b, "%d", v); ++ snprintf(b, sizeof(b), "%d", v); + phpfbestrdup(b, length, value); + } + break; +@@ -2277,7 +2315,7 @@ + { + short int v = *((FBTinyInteger*)data); + char b[128]; +- sprintf(b, "%d", v); ++ snprintf(b, sizeof(b), "%d", v); + phpfbestrdup(b, length, value); + } + break; +@@ -2288,9 +2326,9 @@ + FBLongInteger v = *((FBLongInteger*)data); + char b[128]; + #ifdef PHP_WIN32 +- sprintf(b, "%I64i", v); ++ snprintf(b, sizeof(b), "%I64i", v); + #else +- sprintf(b, "%ll", v); ++ snprintf(b, sizeof(b), "%ll", v); + #endif + phpfbestrdup(b, length, value); + } +@@ -2300,7 +2338,7 @@ + { + short v = *((short*)data); + char b[128]; +- sprintf(b, "%d", v); ++ snprintf(b, sizeof(b), "%d", v); + phpfbestrdup(b, length, value); + } + break; +@@ -2313,7 +2351,7 @@ + { + double v = *((double*)data); + char b[128]; +- sprintf(b, "%f", v); ++ snprintf(b, sizeof(b), "%f", v); + phpfbestrdup(b, length, value); + } + break; +@@ -2346,7 +2384,7 @@ + *length = l*2+3+1; + if (value) + { +- char* r = emalloc(l*2+3+1); ++ char* r = safe_emalloc(l, 2, 4); + r[0] = 'X'; + r[1] = '\''; + for (i = 0; i < nBits / 8; i++) +@@ -2368,7 +2406,7 @@ + *length = l*2+3+1; + if (value) + { +- char* r = emalloc(l*2+3+1); ++ char* r = safe_emalloc(l, 2, 4); + r[0] = 'B'; + r[1] = '\''; + for (i = 0; i < nBits; i++) +@@ -2400,7 +2438,7 @@ + { + char b[128]; + int v = *((unsigned int*)data); +- sprintf(b, "%d", v); ++ snprintf(b, sizeof(b), "%d", v); + phpfbestrdup(b, length, value); + } + break; +@@ -2409,7 +2447,7 @@ + { + char b[128]; + double seconds = *((double*)data); +- sprintf(b, "%f", seconds); ++ snprintf(b, sizeof(b), "%f", seconds); + phpfbestrdup(b, length, value); + } + break; +diff -Nur php-4.3.10/ext/mbstring/mbstring.c hardened-php-4.3.10-0.2.7/ext/mbstring/mbstring.c +--- php-4.3.10/ext/mbstring/mbstring.c 2004-06-24 00:07:01.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/ext/mbstring/mbstring.c 2005-04-07 01:51:16.000000000 +0200 +@@ -1467,12 +1467,13 @@ + + /* {{{ static void php_mbstr_encoding_handler() */ + static void +-php_mbstr_encoding_handler(zval *arg, char *res, char *separator TSRMLS_DC) ++php_mbstr_encoding_handler(zval *arg, int parse_type, char *res, char *separator TSRMLS_DC) + { + char *var, *val, *s1, *s2; + char *strtok_buf = NULL, **val_list; + zval *array_ptr = (zval *) arg; + int n, num, val_len, *len_list, elistsz; ++ unsigned int new_val_len; + enum mbfl_no_encoding from_encoding, to_encoding, *elist; + mbfl_string string, resvar, resval; + mbfl_encoding_detector *identd = NULL; +@@ -1593,8 +1594,14 @@ + val_len = len_list[n]; + } + n++; +- /* add variable to symbol table */ +- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC); ++ /* we need val to be emalloc()ed */ ++ val = estrndup(val, val_len); ++ if (sapi_module.input_filter(parse_type, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ /* add variable to symbol table */ ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); ++ + if (convd != NULL){ + mbfl_string_clear(&resvar); + mbfl_string_clear(&resval); +@@ -1620,7 +1627,7 @@ + { + MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid; + +- php_mbstr_encoding_handler(arg, SG(request_info).post_data, "&" TSRMLS_CC); ++ php_mbstr_encoding_handler(arg, PARSE_POST, SG(request_info).post_data, "&" TSRMLS_CC); + + if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid) { + MBSTRG(http_input_identify_post) = MBSTRG(http_input_identify); +@@ -1720,7 +1727,7 @@ + break; + } + +- php_mbstr_encoding_handler(array_ptr, res, separator TSRMLS_CC); ++ php_mbstr_encoding_handler(array_ptr, arg, res, separator TSRMLS_CC); + + if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid) { + switch(arg){ +diff -Nur php-4.3.10/ext/session/session.c hardened-php-4.3.10-0.2.7/ext/session/session.c +--- php-4.3.10/ext/session/session.c 2004-12-09 18:16:57.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/session/session.c 2005-04-07 01:54:27.000000000 +0200 +@@ -408,7 +408,7 @@ + p += namelen + 1; + + if (has_value) { +- MAKE_STD_ZVAL(current); ++ ALLOC_INIT_ZVAL(current); + if (php_var_unserialize(¤t, (const unsigned char **)&p, endptr, &var_hash TSRMLS_CC)) { + php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + } +@@ -488,7 +488,7 @@ + q++; + + if (has_value) { +- MAKE_STD_ZVAL(current); ++ ALLOC_INIT_ZVAL(current); + if (php_var_unserialize(¤t, (const unsigned char **)&q, endptr, &var_hash TSRMLS_CC)) { + php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + } +diff -Nur php-4.3.10/ext/standard/array.c hardened-php-4.3.10-0.2.7/ext/standard/array.c +--- php-4.3.10/ext/standard/array.c 2004-12-02 17:36:41.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/standard/array.c 2005-04-07 01:51:16.000000000 +0200 +@@ -1153,6 +1153,31 @@ + } + } + } ++ ++ if (var_name[0] == 'H') { ++ if ((strcmp(var_name, "HTTP_GET_VARS")==0)|| ++ (strcmp(var_name, "HTTP_POST_VARS")==0)|| ++ (strcmp(var_name, "HTTP_POST_FILES")==0)|| ++ (strcmp(var_name, "HTTP_ENV_VARS")==0)|| ++ (strcmp(var_name, "HTTP_SERVER_VARS")==0)|| ++ (strcmp(var_name, "HTTP_SESSION_VARS")==0)|| ++ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)) { ++ return 0; ++ } ++ } else if (var_name[0] == '_') { ++ if ((strcmp(var_name, "_COOKIE")==0)|| ++ (strcmp(var_name, "_ENV")==0)|| ++ (strcmp(var_name, "_FILES")==0)|| ++ (strcmp(var_name, "_GET")==0)|| ++ (strcmp(var_name, "_POST")==0)|| ++ (strcmp(var_name, "_REQUEST")==0)|| ++ (strcmp(var_name, "_SESSION")==0)|| ++ (strcmp(var_name, "_SERVER")==0)) { ++ return 0; ++ } ++ } else if (strcmp(var_name, "GLOBALS")==0) { ++ return 0; ++ } + + return 1; + } +diff -Nur php-4.3.10/ext/standard/basic_functions.c hardened-php-4.3.10-0.2.7/ext/standard/basic_functions.c +--- php-4.3.10/ext/standard/basic_functions.c 2004-11-16 00:26:40.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/standard/basic_functions.c 2005-04-07 01:51:16.000000000 +0200 +@@ -687,7 +687,7 @@ + PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL) + + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) +- PHP_FE(realpath, NULL) ++ PHP_STATIC_FE("realpath", zif_real_path, NULL) + #endif + + #ifdef HAVE_FNMATCH +@@ -3008,6 +3008,34 @@ + memcpy(new_key, prefix, prefix_len); + memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength); + ++ if (new_key[0] == 'H') { ++ if ((strcmp(new_key, "HTTP_GET_VARS")==0)|| ++ (strcmp(new_key, "HTTP_POST_VARS")==0)|| ++ (strcmp(new_key, "HTTP_POST_FILES")==0)|| ++ (strcmp(new_key, "HTTP_ENV_VARS")==0)|| ++ (strcmp(new_key, "HTTP_SERVER_VARS")==0)|| ++ (strcmp(new_key, "HTTP_SESSION_VARS")==0)|| ++ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)) { ++ efree(new_key); ++ return 0; ++ } ++ } else if (new_key[0] == '_') { ++ if ((strcmp(new_key, "_COOKIE")==0)|| ++ (strcmp(new_key, "_ENV")==0)|| ++ (strcmp(new_key, "_FILES")==0)|| ++ (strcmp(new_key, "_GET")==0)|| ++ (strcmp(new_key, "_POST")==0)|| ++ (strcmp(new_key, "_REQUEST")==0)|| ++ (strcmp(new_key, "_SESSION")==0)|| ++ (strcmp(new_key, "_SERVER")==0)) { ++ efree(new_key); ++ return 0; ++ } ++ } else if (strcmp(new_key, "GLOBALS")==0) { ++ efree(new_key); ++ return 0; ++ } ++ + zend_hash_del(&EG(symbol_table), new_key, new_key_len); + ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0); + +diff -Nur php-4.3.10/ext/standard/file.c hardened-php-4.3.10-0.2.7/ext/standard/file.c +--- php-4.3.10/ext/standard/file.c 2004-12-08 22:15:02.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/standard/file.c 2005-04-07 01:51:16.000000000 +0200 +@@ -2472,7 +2472,7 @@ + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) + /* {{{ proto string realpath(string path) + Return the resolved path */ +-PHP_FUNCTION(realpath) ++PHP_FUNCTION(real_path) + { + zval **path; + char resolved_path_buff[MAXPATHLEN]; +diff -Nur php-4.3.10/ext/standard/file.h hardened-php-4.3.10-0.2.7/ext/standard/file.h +--- php-4.3.10/ext/standard/file.h 2004-06-21 21:33:47.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/ext/standard/file.h 2005-04-07 01:51:16.000000000 +0200 +@@ -64,7 +64,7 @@ + PHP_FUNCTION(fd_set); + PHP_FUNCTION(fd_isset); + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) +-PHP_FUNCTION(realpath); ++PHP_FUNCTION(real_path); + #endif + #ifdef HAVE_FNMATCH + PHP_FUNCTION(fnmatch); +diff -Nur php-4.3.10/ext/standard/image.c hardened-php-4.3.10-0.2.7/ext/standard/image.c +--- php-4.3.10/ext/standard/image.c 2004-10-04 22:44:07.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/ext/standard/image.c 2005-04-07 01:51:16.000000000 +0200 +@@ -17,7 +17,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: image.c,v 1.72.2.15 2004/10/04 20:44:07 iliaa Exp $ */ ++/* $Id: image.c,v 1.72.2.18 2005/03/06 17:05:41 iliaa Exp $ */ + + #include "php.h" + #include +@@ -363,7 +363,7 @@ + /* just return 0 if we hit the end-of-file */ + if((php_stream_read(stream, a, sizeof(a))) <= 0) return 0; + +- return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]); ++ return (((unsigned short)a[0]) << 8) + ((unsigned short)a[1]); + } + /* }}} */ + +@@ -374,7 +374,7 @@ + int a=0, marker; + + /* get marker byte, swallowing possible padding */ +- if ( last_marker==M_COM && comment_correction) { ++ if (last_marker==M_COM && comment_correction) { + /* some software does not count the length bytes of COM section */ + /* one company doing so is very much envolved in JPEG... so we accept too */ + /* by the way: some of those companies changed their code now... */ +@@ -383,7 +383,7 @@ + last_marker = 0; + comment_correction = 0; + } +- if ( ff_read) { ++ if (ff_read) { + a = 1; /* already read 0xff in filetype detection */ + } + do { +@@ -391,9 +391,9 @@ + { + return M_EOI;/* we hit EOF */ + } +- if ( last_marker==M_COM && comment_correction>0) ++ if (last_marker==M_COM && comment_correction>0) + { +- if ( marker != 0xFF) ++ if (marker != 0xFF) + { + marker = 0xff; + comment_correction--; +@@ -401,14 +401,14 @@ + last_marker = M_PSEUDO; /* stop skipping non 0xff for M_COM */ + } + } +- if ( ++a > 10) ++ if (++a > 10) + { + /* who knows the maxim amount of 0xff? though 7 */ + /* but found other implementations */ + return M_EOI; + } +- } while ( marker == 0xff); +- if ( a < 2) ++ } while (marker == 0xff); ++ if (a < 2) + { + return M_EOI; /* at least one 0xff is needed before marker code */ + } +@@ -422,35 +422,39 @@ + + /* {{{ php_skip_variable + * skip over a variable-length block; assumes proper length marker */ +-static void php_skip_variable(php_stream * stream TSRMLS_DC) ++static int php_skip_variable(php_stream * stream TSRMLS_DC) + { + off_t length = ((unsigned int)php_read2(stream TSRMLS_CC)); + +- length = length-2; +- if (length) +- { +- php_stream_seek(stream, (long)length, SEEK_CUR); ++ if (length < 2) { ++ return 0; + } ++ length = length - 2; ++ php_stream_seek(stream, (long)length, SEEK_CUR); ++ return 1; + } + /* }}} */ + + /* {{{ php_read_APP + */ +-static void php_read_APP(php_stream * stream, unsigned int marker, zval *info TSRMLS_DC) ++static int php_read_APP(php_stream * stream, unsigned int marker, zval *info TSRMLS_DC) + { + unsigned short length; + unsigned char *buffer; +- unsigned char markername[ 16 ]; ++ unsigned char markername[16]; + zval *tmp; + + length = php_read2(stream TSRMLS_CC); ++ if (length < 2) { ++ return 0; ++ } + length -= 2; /* length includes itself */ + + buffer = emalloc(length); + + if (php_stream_read(stream, buffer, (long) length) <= 0) { + efree(buffer); +- return; ++ return 0; + } + + sprintf(markername, "APP%d", marker - M_APP0); +@@ -461,6 +465,7 @@ + } + + efree(buffer); ++ return 1; + } + /* }}} */ + +@@ -497,12 +502,16 @@ + result->height = php_read2(stream TSRMLS_CC); + result->width = php_read2(stream TSRMLS_CC); + result->channels = php_stream_getc(stream); +- if (!info || length<8) /* if we don't want an extanded info -> return */ ++ if (!info || length < 8) { /* if we don't want an extanded info -> return */ + return result; +- if (php_stream_seek(stream, length-8, SEEK_CUR)) /* file error after info */ ++ } ++ if (php_stream_seek(stream, length - 8, SEEK_CUR)) { /* file error after info */ + return result; ++ } + } else { +- php_skip_variable(stream TSRMLS_CC); ++ if (!php_skip_variable(stream TSRMLS_CC)) { ++ return result; ++ } + } + break; + +@@ -523,9 +532,13 @@ + case M_APP14: + case M_APP15: + if (info) { +- php_read_APP(stream, marker, info TSRMLS_CC); /* read all the app markes... */ ++ if (!php_read_APP(stream, marker, info TSRMLS_CC)) { /* read all the app markes... */ ++ return result; ++ } + } else { +- php_skip_variable(stream TSRMLS_CC); ++ if (!php_skip_variable(stream TSRMLS_CC)) { ++ return result; ++ } + } + break; + +@@ -534,7 +547,9 @@ + return result; /* we're about to hit image data, or are at EOF. stop processing. */ + + default: +- php_skip_variable(stream TSRMLS_CC); /* anything else isn't interesting */ ++ if (!php_skip_variable(stream TSRMLS_CC)) { /* anything else isn't interesting */ ++ return result; ++ } + break; + } + } +@@ -613,17 +628,28 @@ + + dummy_short = php_read2(stream TSRMLS_CC); /* Lsiz */ + dummy_short = php_read2(stream TSRMLS_CC); /* Rsiz */ +- result->height = php_read4(stream TSRMLS_CC); /* Xsiz */ + result->width = php_read4(stream TSRMLS_CC); /* Ysiz */ ++ result->height = php_read4(stream TSRMLS_CC); /* Xsiz */ + ++#if MBO_0 + dummy_int = php_read4(stream TSRMLS_CC); /* XOsiz */ + dummy_int = php_read4(stream TSRMLS_CC); /* YOsiz */ + dummy_int = php_read4(stream TSRMLS_CC); /* XTsiz */ + dummy_int = php_read4(stream TSRMLS_CC); /* YTsiz */ + dummy_int = php_read4(stream TSRMLS_CC); /* XTOsiz */ + dummy_int = php_read4(stream TSRMLS_CC); /* YTOsiz */ ++#else ++ if (php_stream_seek(stream, 24, SEEK_CUR)) { ++ efree(result); ++ return NULL; ++ } ++#endif + + result->channels = php_read2(stream TSRMLS_CC); /* Csiz */ ++ if (result->channels < 0 || result->channels > 256) { ++ efree(result); ++ return NULL; ++ } + + /* Collect bit depth info */ + highest_bit_depth = bit_depth = 0; +@@ -685,8 +711,15 @@ + break; + } + ++ /* Stop if this was the last box */ ++ if ((int)box_length <= 0) { ++ break; ++ } ++ + /* Skip over LBox (Which includes both TBox and LBox itself */ +- php_stream_seek(stream, box_length - 8, SEEK_CUR); ++ if (php_stream_seek(stream, box_length - 8, SEEK_CUR)) { ++ break; ++ } + } + + if (result == NULL) { +@@ -849,43 +882,49 @@ + */ + static struct gfxinfo *php_handle_iff(php_stream * stream TSRMLS_DC) + { +- struct gfxinfo *result = NULL; ++ struct gfxinfo * result; + unsigned char a[10]; + int chunkId; + int size; ++ short width, height, bits; + +- if (php_stream_read(stream, a, 8) != 8) ++ if (php_stream_read(stream, a, 8) != 8) { + return NULL; +- if (strncmp(a+4, "ILBM", 4) && strncmp(a+4, "PBM ", 4)) ++ } ++ if (strncmp(a+4, "ILBM", 4) && strncmp(a+4, "PBM ", 4)) { + return NULL; +- +- result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); ++ } + + /* loop chunks to find BMHD chunk */ + do { + if (php_stream_read(stream, a, 8) != 8) { +- efree(result); + return NULL; + } + chunkId = php_ifd_get32s(a+0, 1); + size = php_ifd_get32s(a+4, 1); ++ if (size < 0) { ++ return NULL; ++ } + if ((size & 1) == 1) { + size++; + } + if (chunkId == 0x424d4844) { /* BMHD chunk */ +- if (php_stream_read(stream, a, 9) != 9) { +- efree(result); ++ if (size < 9 || php_stream_read(stream, a, 9) != 9) { + return NULL; + } +- result->width = php_ifd_get16s(a+0, 1); +- result->height = php_ifd_get16s(a+2, 1); +- result->bits = a[8] & 0xff; ++ width = php_ifd_get16s(a+0, 1); ++ height = php_ifd_get16s(a+2, 1); ++ bits = a[8] & 0xff; ++ if (width > 0 && height > 0 && bits > 0 && bits < 33) { ++ result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); ++ result->width = width; ++ result->height = height; ++ result->bits = bits; + result->channels = 0; +- if (result->width > 0 && result->height > 0 && result->bits > 0 && result->bits < 33) + return result; ++ } + } else { + if (php_stream_seek(stream, size, SEEK_CUR)) { +- efree(result); + return NULL; + } + } +@@ -1230,11 +1269,14 @@ + case IMAGE_FILETYPE_SWF: + result = php_handle_swf(stream TSRMLS_CC); + break; +-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) + case IMAGE_FILETYPE_SWC: ++#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) + result = php_handle_swc(stream TSRMLS_CC); +- break; ++#else ++ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The image is a compressed SWF file, but you do not have a static version of the zlib extension enabled."); ++ + #endif ++ break; + case IMAGE_FILETYPE_PSD: + result = php_handle_psd(stream TSRMLS_CC); + break; +diff -Nur php-4.3.10/ext/standard/info.c hardened-php-4.3.10-0.2.7/ext/standard/info.c +--- php-4.3.10/ext/standard/info.c 2004-06-09 17:10:19.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/ext/standard/info.c 2005-04-07 01:51:16.000000000 +0200 +@@ -397,7 +397,7 @@ + + if (flag & PHP_INFO_GENERAL) { + char *zend_version = get_zend_version(); +- char temp_api[9]; ++ char temp_api[11]; + + php_uname = php_get_uname('a'); + +@@ -417,11 +417,22 @@ + } + } + ++#if HARDENED_PHP ++ if (!sapi_module.phpinfo_as_text) { ++ php_printf("

Hardened-PHP Version %s/%s

\n", PHP_VERSION, HARDENED_PHP_VERSION); ++ } else { ++ char temp_ver[40]; ++ ++ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENED_PHP_VERSION); ++ php_info_print_table_row(2, "Hardened-PHP Version", temp_ver); ++ } ++#else + if (!sapi_module.phpinfo_as_text) { + php_printf("

PHP Version %s

\n", PHP_VERSION); + } else { + php_info_print_table_row(2, "PHP Version", PHP_VERSION); + } ++#endif + php_info_print_box_end(); + php_info_print_table_start(); + php_info_print_table_row(2, "System", php_uname ); +diff -Nur php-4.3.10/ext/standard/pack.c hardened-php-4.3.10-0.2.7/ext/standard/pack.c +--- php-4.3.10/ext/standard/pack.c 2004-11-28 13:44:56.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/standard/pack.c 2005-04-07 01:51:16.000000000 +0200 +@@ -15,7 +15,7 @@ + | Author: Chris Schneider | + +----------------------------------------------------------------------+ + */ +-/* $Id: pack.c,v 1.40.2.6 2004/11/28 12:44:56 sesser Exp $ */ ++/* $Id: pack.c,v 1.40.2.7 2005/01/25 22:52:19 iliaa Exp $ */ + + #include "php.h" + +@@ -833,7 +833,9 @@ + + inputpos += size; + if (inputpos < 0) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type); ++ if (size != -1) { /* only print warning if not working with * */ ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type); ++ } + inputpos = 0; + } + } else if (arg < 0) { +diff -Nur php-4.3.10/ext/standard/php_var.h hardened-php-4.3.10-0.2.7/ext/standard/php_var.h +--- php-4.3.10/ext/standard/php_var.h 2004-09-24 23:57:18.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/ext/standard/php_var.h 2005-04-07 01:51:16.000000000 +0200 +@@ -16,7 +16,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: php_var.h,v 1.21.4.4 2004/09/24 21:57:18 helly Exp $ */ ++/* $Id: php_var.h,v 1.21.4.5 2005/01/15 18:44:29 sesser Exp $ */ + + #ifndef PHP_VAR_H + #define PHP_VAR_H +@@ -41,6 +41,7 @@ + + struct php_unserialize_data { + void *first; ++ void *first_dtor; + }; + + typedef struct php_unserialize_data php_unserialize_data_t; +@@ -54,7 +55,8 @@ + zend_hash_destroy(&(var_hash)) + + #define PHP_VAR_UNSERIALIZE_INIT(var_hash) \ +- (var_hash).first = 0 ++ (var_hash).first = 0; \ ++ (var_hash).first_dtor = 0 + #define PHP_VAR_UNSERIALIZE_DESTROY(var_hash) \ + var_destroy(&(var_hash)) + +diff -Nur php-4.3.10/ext/standard/var_unserializer.c hardened-php-4.3.10-0.2.7/ext/standard/var_unserializer.c +--- php-4.3.10/ext/standard/var_unserializer.c 2004-12-14 18:55:22.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/standard/var_unserializer.c 2005-04-07 01:51:16.000000000 +0200 +@@ -1,4 +1,4 @@ +-/* Generated by re2c 0.5 on Thu Nov 18 17:11:01 2004 */ ++/* Generated by re2c 0.9.4 on Thu Mar 10 02:59:20 2005 */ + /* + +----------------------------------------------------------------------+ + | PHP Version 4 | +@@ -17,7 +17,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: var_unserializer.c,v 1.18.4.14 2004/12/03 16:09:19 sesser Exp $ */ ++/* $Id: var_unserializer.c,v 1.18.4.23 2005/03/10 02:01:40 helly Exp $ */ + + #include "php.h" + #include "ext/standard/php_var.h" +@@ -28,7 +28,7 @@ + + typedef struct { + zval *data[VAR_ENTRIES_MAX]; +- int used_slots; ++ long used_slots; + void *next; + } var_entries; + +@@ -55,9 +55,33 @@ + var_hash->data[var_hash->used_slots++] = *rval; + } + ++static inline void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) ++{ ++ var_entries *var_hash = var_hashx->first_dtor, *prev = NULL; ++ ++ while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { ++ prev = var_hash; ++ var_hash = var_hash->next; ++ } ++ ++ if (!var_hash) { ++ var_hash = emalloc(sizeof(var_entries)); ++ var_hash->used_slots = 0; ++ var_hash->next = 0; ++ ++ if (!var_hashx->first_dtor) ++ var_hashx->first_dtor = var_hash; ++ else ++ prev->next = var_hash; ++ } ++ ++ (*rval)->refcount++; ++ var_hash->data[var_hash->used_slots++] = *rval; ++} ++ + PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval) + { +- int i; ++ long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) { +@@ -71,7 +95,7 @@ + } + } + +-static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) ++static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store) + { + var_entries *var_hash = var_hashx->first; + +@@ -92,6 +116,7 @@ + PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) + { + void *next; ++ long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) { +@@ -99,6 +124,17 @@ + efree(var_hash); + var_hash = next; + } ++ ++ var_hash = var_hashx->first_dtor; ++ ++ while (var_hash) { ++ for (i = 0; i < var_hash->used_slots; i++) { ++ zval_ptr_dtor(&var_hash->data[i]); ++ } ++ next = var_hash->next; ++ efree(var_hash); ++ var_hash = next; ++ } + } + + /* }}} */ +@@ -114,10 +150,10 @@ + + + +-static inline int parse_iv2(const unsigned char *p, const unsigned char **q) ++static inline long parse_iv2(const unsigned char *p, const unsigned char **q) + { + char cursor; +- int result = 0; ++ long result = 0; + int neg = 0; + + switch (*p) { +@@ -142,7 +178,7 @@ + return result; + } + +-static inline int parse_iv(const unsigned char *p) ++static inline long parse_iv(const unsigned char *p) + { + return parse_iv2(p, NULL); + } +@@ -172,10 +208,10 @@ + #define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC + #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC + +-static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements) ++static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements) + { + while (elements-- > 0) { +- zval *key, *data, *old_data; ++ zval *key, *data, **old_data; + + ALLOC_INIT_ZVAL(key); + +@@ -203,14 +239,14 @@ + + switch (Z_TYPE_P(key)) { + case IS_LONG: +- if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)) { +- var_replace(var_hash, old_data, rval); ++ if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); + } + zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL); + break; + case IS_STRING: +- if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)) { +- var_replace(var_hash, old_data, rval); ++ if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); + } + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL); + break; +@@ -241,7 +277,7 @@ + + static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) + { +- int elements; ++ long elements; + + elements = parse_iv2((*p) + 2, p); + +@@ -251,7 +287,7 @@ + return elements; + } + +-static inline int object_common2(UNSERIALIZE_PARAMETER, int elements) ++static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) + { + zval *retval_ptr = NULL; + zval fname; +@@ -300,6 +336,7 @@ + + + ++ + { + YYCTYPE yych; + unsigned int yyaccept; +@@ -378,7 +415,8 @@ + goto yy16; + } else { + if(yych <= '}') goto yy14; +- if(yych <= '\277') goto yy16; ++ if(yych <= 0xBF) goto yy16; ++ goto yy2; + } + } + } +@@ -389,8 +427,9 @@ + yy3: yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ':') goto yy87; ++ goto yy4; + yy4: +- { return 0; } ++{ return 0; } + yy5: yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ':') goto yy81; +@@ -426,9 +465,10 @@ + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ':') goto yy17; + goto yy4; +-yy14: yych = *++YYCURSOR; ++yy14: ++YYCURSOR; ++ goto yy15; + yy15: +- { ++{ + /* this is the case where we have less data than planned */ + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); + return 0; /* not sure if it should be 0 or 1 here? */ +@@ -438,21 +478,26 @@ + yy17: yych = *++YYCURSOR; + if(yybm[0+yych] & 128) goto yy19; + if(yych != '+') goto yy2; ++ goto yy18; + yy18: yych = *++YYCURSOR; + if(yybm[0+yych] & 128) goto yy19; + goto yy2; + yy19: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy20; + yy20: if(yybm[0+yych] & 128) goto yy19; + if(yych != ':') goto yy2; ++ goto yy21; + yy21: yych = *++YYCURSOR; + if(yych != '"') goto yy2; +-yy22: yych = *++YYCURSOR; ++ goto yy22; ++yy22: ++YYCURSOR; ++ goto yy23; + yy23: +- { +- size_t len, len2, maxlen; +- int elements; ++{ ++ size_t len, len2, len3, maxlen; ++ long elements; + char *class_name; + zend_class_entry *ce; + int incomplete_class = 0; +@@ -486,6 +531,14 @@ + class_name = str_tolower_copy((char *)emalloc(len+1), class_name, len); + class_name[len] = '\0'; + ++ len3 = strspn(class_name, "0123456789_abcdefghijklmnopqrstuvwxyz"); ++ if (len3 != len) ++ { ++ *p = YYCURSOR + len3 - len; ++ efree(class_name); ++ return 0; ++ } ++ + if (zend_hash_find(CG(class_table), class_name, len + 1, (void **) &ce) != SUCCESS) { + if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { + incomplete_class = 1; +@@ -533,6 +586,7 @@ + yy24: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy25; + } else { + if(yych <= '-') goto yy25; + if(yych <= '/') goto yy2; +@@ -542,17 +596,22 @@ + yy25: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy26; + yy26: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy27; + yy27: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy26; + if(yych >= ';') goto yy2; ++ goto yy28; + yy28: yych = *++YYCURSOR; + if(yych != '"') goto yy2; +-yy29: yych = *++YYCURSOR; ++ goto yy29; ++yy29: ++YYCURSOR; ++ goto yy30; + yy30: +- { ++{ + + INIT_PZVAL(*rval); + +@@ -567,21 +626,34 @@ + yy32: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy33; + yy33: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy34; + yy34: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy33; + if(yych >= ';') goto yy2; ++ goto yy35; + yy35: yych = *++YYCURSOR; + if(yych != '{') goto yy2; +-yy36: yych = *++YYCURSOR; ++ goto yy36; ++yy36: ++YYCURSOR; ++ goto yy37; + yy37: +- { +- int elements = parse_iv(start + 2); +- ++{ ++ long elements = parse_iv(start + 2); ++ /* use iv() not uiv() in order to check data range */ + *p = YYCURSOR; + ++ if (elements < 0) { ++ return 0; ++ } ++ ++ if (elements < 0) { ++ return 0; ++ } ++ + INIT_PZVAL(*rval); + Z_TYPE_PP(rval) = IS_ARRAY; + ALLOC_HASHTABLE(Z_ARRVAL_PP(rval)); +@@ -602,17 +674,22 @@ + yy39: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy40; + yy40: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy41; + yy41: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy40; + if(yych >= ';') goto yy2; ++ goto yy42; + yy42: yych = *++YYCURSOR; + if(yych != '"') goto yy2; +-yy43: yych = *++YYCURSOR; ++ goto yy43; ++yy43: ++YYCURSOR; ++ goto yy44; + yy44: +- { ++{ + size_t len, maxlen; + char *str; + +@@ -656,6 +733,7 @@ + goto yy48; + } else { + if(yych != 'N') goto yy2; ++ goto yy46; + } + } + yy46: yych = *++YYCURSOR; +@@ -668,6 +746,7 @@ + } else { + if(yych <= '9') goto yy50; + if(yych != 'I') goto yy2; ++ goto yy48; + } + yy48: yych = *++YYCURSOR; + if(yych == 'N') goto yy64; +@@ -676,9 +755,11 @@ + if(yych == '.') goto yy52; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy50; + yy50: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy51; + yy51: if(yych <= ':'){ + if(yych <= '.'){ + if(yych <= '-') goto yy2; +@@ -701,13 +782,16 @@ + yy52: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy53; + yy53: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy54; + yy54: if(yych <= ';'){ + if(yych <= '/') goto yy2; + if(yych <= '9') goto yy53; + if(yych <= ':') goto yy2; ++ goto yy55; + } else { + if(yych <= 'E'){ + if(yych <= 'D') goto yy2; +@@ -717,17 +801,19 @@ + goto yy2; + } + } +-yy55: yych = *++YYCURSOR; ++yy55: ++YYCURSOR; ++ goto yy56; + yy56: +- { ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); +- ZVAL_DOUBLE(*rval, atof(start + 2)); ++ ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); + return 1; + } + yy57: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy58; + } else { + if(yych <= '-') goto yy58; + if(yych <= '/') goto yy2; +@@ -742,10 +828,12 @@ + if(yych <= '-') goto yy61; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy59; + } + yy59: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy60; + yy60: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy59; + if(yych == ';') goto yy55; +@@ -757,6 +845,7 @@ + yy62: ++YYCURSOR; + if((YYLIMIT - YYCURSOR) < 4) YYFILL(4); + yych = *YYCURSOR; ++ goto yy63; + yy63: if(yych <= ';'){ + if(yych <= '/') goto yy2; + if(yych <= '9') goto yy62; +@@ -773,16 +862,17 @@ + } + yy64: yych = *++YYCURSOR; + if(yych != 'F') goto yy2; ++ goto yy65; + yy65: yych = *++YYCURSOR; + if(yych != ';') goto yy2; +-yy66: yych = *++YYCURSOR; ++ goto yy66; ++yy66: ++YYCURSOR; ++ goto yy67; + yy67: +- { ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); +-#if defined(HAVE_ATOF_ACCEPTS_NAN) && defined(HAVE_ATOF_ACCEPTS_INF) +- ZVAL_DOUBLE(*rval, atof(start + 2)); +-#else ++ + if (!strncmp(start + 2, "NAN", 3)) { + ZVAL_DOUBLE(*rval, php_get_nan()); + } else if (!strncmp(start + 2, "INF", 3)) { +@@ -790,7 +880,7 @@ + } else if (!strncmp(start + 2, "-INF", 4)) { + ZVAL_DOUBLE(*rval, -php_get_inf()); + } +-#endif ++ + return 1; + } + yy68: yych = *++YYCURSOR; +@@ -799,6 +889,7 @@ + yy69: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy70; + } else { + if(yych <= '-') goto yy70; + if(yych <= '/') goto yy2; +@@ -808,15 +899,19 @@ + yy70: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy71; + yy71: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy72; + yy72: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy71; + if(yych != ';') goto yy2; +-yy73: yych = *++YYCURSOR; ++ goto yy73; ++yy73: ++YYCURSOR; ++ goto yy74; + yy74: +- { ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); + ZVAL_LONG(*rval, parse_iv(start + 2)); +@@ -825,19 +920,23 @@ + yy75: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= '2') goto yy2; ++ goto yy76; + yy76: yych = *++YYCURSOR; + if(yych != ';') goto yy2; +-yy77: yych = *++YYCURSOR; ++ goto yy77; ++yy77: ++YYCURSOR; ++ goto yy78; + yy78: +- { ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); + ZVAL_BOOL(*rval, parse_iv(start + 2)); + return 1; + } +-yy79: yych = *++YYCURSOR; ++yy79: ++YYCURSOR; ++ goto yy80; + yy80: +- { ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); + ZVAL_NULL(*rval); +@@ -846,6 +945,7 @@ + yy81: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy82; + } else { + if(yych <= '-') goto yy82; + if(yych <= '/') goto yy2; +@@ -855,16 +955,20 @@ + yy82: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy83; + yy83: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy84; + yy84: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy83; + if(yych != ';') goto yy2; +-yy85: yych = *++YYCURSOR; ++ goto yy85; ++yy85: ++YYCURSOR; ++ goto yy86; + yy86: +- { +- int id; ++{ ++ long id; + + *p = YYCURSOR; + if (!var_hash) return 0; +@@ -873,7 +977,7 @@ + if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) { + return 0; + } +- ++ + if (*rval == *rval_ref) return 0; + + if (*rval != NULL) { +@@ -888,6 +992,7 @@ + yy87: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy88; + } else { + if(yych <= '-') goto yy88; + if(yych <= '/') goto yy2; +@@ -897,16 +1002,20 @@ + yy88: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy89; + yy89: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy90; + yy90: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy89; + if(yych != ';') goto yy2; +-yy91: yych = *++YYCURSOR; ++ goto yy91; ++yy91: ++YYCURSOR; ++ goto yy92; + yy92: +- { +- int id; ++{ ++ long id; + + *p = YYCURSOR; + if (!var_hash) return 0; +diff -Nur php-4.3.10/ext/standard/var_unserializer.c.orig hardened-php-4.3.10-0.2.7/ext/standard/var_unserializer.c.orig +--- php-4.3.10/ext/standard/var_unserializer.c.orig 2004-12-14 18:55:22.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/standard/var_unserializer.c.orig 2005-04-07 01:51:16.000000000 +0200 +@@ -1,5 +1,5 @@ +-/* Generated by re2c 0.5 on Thu Nov 18 17:11:01 2004 */ +-#line 1 "/home/rei/php4/ext/standard/var_unserializer.re" ++/* Generated by re2c 0.9.4 on Thu Mar 10 02:59:20 2005 */ ++#line 1 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" + /* + +----------------------------------------------------------------------+ + | PHP Version 4 | +@@ -18,7 +18,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: var_unserializer.c,v 1.18.4.14 2004/12/03 16:09:19 sesser Exp $ */ ++/* $Id: var_unserializer.c,v 1.18.4.23 2005/03/10 02:01:40 helly Exp $ */ + + #include "php.h" + #include "ext/standard/php_var.h" +@@ -29,7 +29,7 @@ + + typedef struct { + zval *data[VAR_ENTRIES_MAX]; +- int used_slots; ++ long used_slots; + void *next; + } var_entries; + +@@ -56,9 +56,33 @@ + var_hash->data[var_hash->used_slots++] = *rval; + } + ++static inline void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) ++{ ++ var_entries *var_hash = var_hashx->first_dtor, *prev = NULL; ++ ++ while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { ++ prev = var_hash; ++ var_hash = var_hash->next; ++ } ++ ++ if (!var_hash) { ++ var_hash = emalloc(sizeof(var_entries)); ++ var_hash->used_slots = 0; ++ var_hash->next = 0; ++ ++ if (!var_hashx->first_dtor) ++ var_hashx->first_dtor = var_hash; ++ else ++ prev->next = var_hash; ++ } ++ ++ (*rval)->refcount++; ++ var_hash->data[var_hash->used_slots++] = *rval; ++} ++ + PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval) + { +- int i; ++ long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) { +@@ -72,7 +96,7 @@ + } + } + +-static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) ++static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store) + { + var_entries *var_hash = var_hashx->first; + +@@ -93,6 +117,7 @@ + PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) + { + void *next; ++ long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) { +@@ -100,6 +125,17 @@ + efree(var_hash); + var_hash = next; + } ++ ++ var_hash = var_hashx->first_dtor; ++ ++ while (var_hash) { ++ for (i = 0; i < var_hash->used_slots; i++) { ++ zval_ptr_dtor(&var_hash->data[i]); ++ } ++ next = var_hash->next; ++ efree(var_hash); ++ var_hash = next; ++ } + } + + /* }}} */ +@@ -111,15 +147,15 @@ + #define YYMARKER marker + + +-#line 118 ++#line 154 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" + + + + +-static inline int parse_iv2(const unsigned char *p, const unsigned char **q) ++static inline long parse_iv2(const unsigned char *p, const unsigned char **q) + { + char cursor; +- int result = 0; ++ long result = 0; + int neg = 0; + + switch (*p) { +@@ -144,7 +180,7 @@ + return result; + } + +-static inline int parse_iv(const unsigned char *p) ++static inline long parse_iv(const unsigned char *p) + { + return parse_iv2(p, NULL); + } +@@ -174,10 +210,10 @@ + #define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC + #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC + +-static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements) ++static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements) + { + while (elements-- > 0) { +- zval *key, *data, *old_data; ++ zval *key, *data, **old_data; + + ALLOC_INIT_ZVAL(key); + +@@ -205,14 +241,14 @@ + + switch (Z_TYPE_P(key)) { + case IS_LONG: +- if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)) { +- var_replace(var_hash, old_data, rval); ++ if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); + } + zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL); + break; + case IS_STRING: +- if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)) { +- var_replace(var_hash, old_data, rval); ++ if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); + } + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL); + break; +@@ -243,7 +279,7 @@ + + static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) + { +- int elements; ++ long elements; + + elements = parse_iv2((*p) + 2, p); + +@@ -253,7 +289,7 @@ + return elements; + } + +-static inline int object_common2(UNSERIALIZE_PARAMETER, int elements) ++static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) + { + zval *retval_ptr = NULL; + zval fname; +@@ -302,6 +338,8 @@ + + + ++ ++#line 7 "" + { + YYCTYPE yych; + unsigned int yyaccept; +@@ -380,7 +418,8 @@ + goto yy16; + } else { + if(yych <= '}') goto yy14; +- if(yych <= '\277') goto yy16; ++ if(yych <= 0xBF) goto yy16; ++ goto yy2; + } + } + } +@@ -391,9 +430,11 @@ + yy3: yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ':') goto yy87; ++ goto yy4; + yy4: +-#line 532 +- { return 0; } ++#line 590 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ return 0; } ++#line 102 "" + yy5: yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ':') goto yy81; +@@ -429,35 +470,42 @@ + yych = *(YYMARKER = ++YYCURSOR); + if(yych == ':') goto yy17; + goto yy4; +-yy14: yych = *++YYCURSOR; ++yy14: ++YYCURSOR; ++ goto yy15; + yy15: +-#line 526 +- { ++#line 584 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + /* this is the case where we have less data than planned */ + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); + return 0; /* not sure if it should be 0 or 1 here? */ + } ++#line 147 "" + yy16: yych = *++YYCURSOR; + goto yy4; + yy17: yych = *++YYCURSOR; + if(yybm[0+yych] & 128) goto yy19; + if(yych != '+') goto yy2; ++ goto yy18; + yy18: yych = *++YYCURSOR; + if(yybm[0+yych] & 128) goto yy19; + goto yy2; + yy19: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy20; + yy20: if(yybm[0+yych] & 128) goto yy19; + if(yych != ':') goto yy2; ++ goto yy21; + yy21: yych = *++YYCURSOR; + if(yych != '"') goto yy2; +-yy22: yych = *++YYCURSOR; ++ goto yy22; ++yy22: ++YYCURSOR; ++ goto yy23; + yy23: +-#line 445 +- { +- size_t len, len2, maxlen; +- int elements; ++#line 495 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ ++ size_t len, len2, len3, maxlen; ++ long elements; + char *class_name; + zend_class_entry *ce; + int incomplete_class = 0; +@@ -491,6 +539,14 @@ + class_name = str_tolower_copy((char *)emalloc(len+1), class_name, len); + class_name[len] = '\0'; + ++ len3 = strspn(class_name, "0123456789_abcdefghijklmnopqrstuvwxyz"); ++ if (len3 != len) ++ { ++ *p = YYCURSOR + len3 - len; ++ efree(class_name); ++ return 0; ++ } ++ + if (zend_hash_find(CG(class_table), class_name, len + 1, (void **) &ce) != SUCCESS) { + if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { + incomplete_class = 1; +@@ -535,9 +591,11 @@ + + return object_common2(UNSERIALIZE_PASSTHRU, elements); + } ++#line 260 "" + yy24: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy25; + } else { + if(yych <= '-') goto yy25; + if(yych <= '/') goto yy2; +@@ -547,24 +605,30 @@ + yy25: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy26; + yy26: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy27; + yy27: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy26; + if(yych >= ';') goto yy2; ++ goto yy28; + yy28: yych = *++YYCURSOR; + if(yych != '"') goto yy2; +-yy29: yych = *++YYCURSOR; ++ goto yy29; ++yy29: ++YYCURSOR; ++ goto yy30; + yy30: +-#line 437 +- { ++#line 487 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + + INIT_PZVAL(*rval); + + return object_common2(UNSERIALIZE_PASSTHRU, + object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); + } ++#line 298 "" + yy31: yych = *++YYCURSOR; + if(yych == '+') goto yy32; + if(yych <= '/') goto yy2; +@@ -573,22 +637,35 @@ + yy32: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy33; + yy33: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy34; + yy34: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy33; + if(yych >= ';') goto yy2; ++ goto yy35; + yy35: yych = *++YYCURSOR; + if(yych != '{') goto yy2; +-yy36: yych = *++YYCURSOR; ++ goto yy36; ++yy36: ++YYCURSOR; ++ goto yy37; + yy37: +-#line 419 +- { +- int elements = parse_iv(start + 2); +- ++#line 461 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ ++ long elements = parse_iv(start + 2); ++ /* use iv() not uiv() in order to check data range */ + *p = YYCURSOR; + ++ if (elements < 0) { ++ return 0; ++ } ++ ++ if (elements < 0) { ++ return 0; ++ } ++ + INIT_PZVAL(*rval); + Z_TYPE_PP(rval) = IS_ARRAY; + ALLOC_HASHTABLE(Z_ARRVAL_PP(rval)); +@@ -601,6 +678,7 @@ + + return finish_nested_data(UNSERIALIZE_PASSTHRU); + } ++#line 349 "" + yy38: yych = *++YYCURSOR; + if(yych == '+') goto yy39; + if(yych <= '/') goto yy2; +@@ -609,18 +687,23 @@ + yy39: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy40; + yy40: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy41; + yy41: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy40; + if(yych >= ';') goto yy2; ++ goto yy42; + yy42: yych = *++YYCURSOR; + if(yych != '"') goto yy2; +-yy43: yych = *++YYCURSOR; ++ goto yy43; ++yy43: ++YYCURSOR; ++ goto yy44; + yy44: +-#line 391 +- { ++#line 433 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + size_t len, maxlen; + char *str; + +@@ -647,6 +730,7 @@ + ZVAL_STRINGL(*rval, str, len, 1); + return 1; + } ++#line 402 "" + yy45: yych = *++YYCURSOR; + if(yych <= '/'){ + if(yych <= ','){ +@@ -664,6 +748,7 @@ + goto yy48; + } else { + if(yych != 'N') goto yy2; ++ goto yy46; + } + } + yy46: yych = *++YYCURSOR; +@@ -676,6 +761,7 @@ + } else { + if(yych <= '9') goto yy50; + if(yych != 'I') goto yy2; ++ goto yy48; + } + yy48: yych = *++YYCURSOR; + if(yych == 'N') goto yy64; +@@ -684,9 +770,11 @@ + if(yych == '.') goto yy52; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy50; + yy50: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy51; + yy51: if(yych <= ':'){ + if(yych <= '.'){ + if(yych <= '-') goto yy2; +@@ -709,13 +797,16 @@ + yy52: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy53; + yy53: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy54; + yy54: if(yych <= ';'){ + if(yych <= '/') goto yy2; + if(yych <= '9') goto yy53; + if(yych <= ':') goto yy2; ++ goto yy55; + } else { + if(yych <= 'E'){ + if(yych <= 'D') goto yy2; +@@ -725,18 +816,21 @@ + goto yy2; + } + } +-yy55: yych = *++YYCURSOR; ++yy55: ++YYCURSOR; ++ goto yy56; + yy56: +-#line 384 +- { ++#line 426 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); +- ZVAL_DOUBLE(*rval, atof(start + 2)); ++ ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); + return 1; + } ++#line 500 "" + yy57: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy58; + } else { + if(yych <= '-') goto yy58; + if(yych <= '/') goto yy2; +@@ -751,10 +845,12 @@ + if(yych <= '-') goto yy61; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy59; + } + yy59: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy60; + yy60: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy59; + if(yych == ';') goto yy55; +@@ -766,6 +862,7 @@ + yy62: ++YYCURSOR; + if((YYLIMIT - YYCURSOR) < 4) YYFILL(4); + yych = *YYCURSOR; ++ goto yy63; + yy63: if(yych <= ';'){ + if(yych <= '/') goto yy2; + if(yych <= '9') goto yy62; +@@ -782,17 +879,18 @@ + } + yy64: yych = *++YYCURSOR; + if(yych != 'F') goto yy2; ++ goto yy65; + yy65: yych = *++YYCURSOR; + if(yych != ';') goto yy2; +-yy66: yych = *++YYCURSOR; ++ goto yy66; ++yy66: ++YYCURSOR; ++ goto yy67; + yy67: +-#line 367 +- { ++#line 411 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); +-#if defined(HAVE_ATOF_ACCEPTS_NAN) && defined(HAVE_ATOF_ACCEPTS_INF) +- ZVAL_DOUBLE(*rval, atof(start + 2)); +-#else ++ + if (!strncmp(start + 2, "NAN", 3)) { + ZVAL_DOUBLE(*rval, php_get_nan()); + } else if (!strncmp(start + 2, "INF", 3)) { +@@ -800,15 +898,17 @@ + } else if (!strncmp(start + 2, "-INF", 4)) { + ZVAL_DOUBLE(*rval, -php_get_inf()); + } +-#endif ++ + return 1; + } ++#line 577 "" + yy68: yych = *++YYCURSOR; + if(yych == 'N') goto yy65; + goto yy2; + yy69: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy70; + } else { + if(yych <= '-') goto yy70; + if(yych <= '/') goto yy2; +@@ -818,47 +918,59 @@ + yy70: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy71; + yy71: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy72; + yy72: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy71; + if(yych != ';') goto yy2; +-yy73: yych = *++YYCURSOR; ++ goto yy73; ++yy73: ++YYCURSOR; ++ goto yy74; + yy74: +-#line 360 +- { ++#line 404 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); + ZVAL_LONG(*rval, parse_iv(start + 2)); + return 1; + } ++#line 614 "" + yy75: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= '2') goto yy2; ++ goto yy76; + yy76: yych = *++YYCURSOR; + if(yych != ';') goto yy2; +-yy77: yych = *++YYCURSOR; ++ goto yy77; ++yy77: ++YYCURSOR; ++ goto yy78; + yy78: +-#line 353 +- { ++#line 397 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); + ZVAL_BOOL(*rval, parse_iv(start + 2)); + return 1; + } +-yy79: yych = *++YYCURSOR; ++#line 632 "" ++yy79: ++YYCURSOR; ++ goto yy80; + yy80: +-#line 346 +- { ++#line 390 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ + *p = YYCURSOR; + INIT_PZVAL(*rval); + ZVAL_NULL(*rval); + return 1; + } ++#line 643 "" + yy81: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy82; + } else { + if(yych <= '-') goto yy82; + if(yych <= '/') goto yy2; +@@ -868,17 +980,21 @@ + yy82: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy83; + yy83: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy84; + yy84: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy83; + if(yych != ';') goto yy2; +-yy85: yych = *++YYCURSOR; ++ goto yy85; ++yy85: ++YYCURSOR; ++ goto yy86; + yy86: +-#line 325 +- { +- int id; ++#line 367 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ ++ long id; + + *p = YYCURSOR; + if (!var_hash) return 0; +@@ -887,7 +1003,7 @@ + if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) { + return 0; + } +- ++ + if (*rval == *rval_ref) return 0; + + if (*rval != NULL) { +@@ -899,9 +1015,11 @@ + + return 1; + } ++#line 693 "" + yy87: yych = *++YYCURSOR; + if(yych <= ','){ + if(yych != '+') goto yy2; ++ goto yy88; + } else { + if(yych <= '-') goto yy88; + if(yych <= '/') goto yy2; +@@ -911,17 +1029,21 @@ + yy88: yych = *++YYCURSOR; + if(yych <= '/') goto yy2; + if(yych >= ':') goto yy2; ++ goto yy89; + yy89: ++YYCURSOR; + if(YYLIMIT == YYCURSOR) YYFILL(1); + yych = *YYCURSOR; ++ goto yy90; + yy90: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy89; + if(yych != ';') goto yy2; +-yy91: yych = *++YYCURSOR; ++ goto yy91; ++yy91: ++YYCURSOR; ++ goto yy92; + yy92: +-#line 304 +- { +- int id; ++#line 346 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" ++{ ++ long id; + + *p = YYCURSOR; + if (!var_hash) return 0; +@@ -940,8 +1062,9 @@ + + return 1; + } ++#line 741 "" + } +-#line 534 ++#line 592 "/usr/src/PHP_4_3_0/ext/standard/var_unserializer.re" + + + return 0; +diff -Nur php-4.3.10/ext/standard/var_unserializer.re hardened-php-4.3.10-0.2.7/ext/standard/var_unserializer.re +--- php-4.3.10/ext/standard/var_unserializer.re 2004-12-03 17:09:19.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/standard/var_unserializer.re 2005-04-07 01:51:16.000000000 +0200 +@@ -16,7 +16,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: var_unserializer.re,v 1.11.4.8 2004/12/03 16:09:19 sesser Exp $ */ ++/* $Id: var_unserializer.re,v 1.11.4.16 2005/03/10 02:00:17 helly Exp $ */ + + #include "php.h" + #include "ext/standard/php_var.h" +@@ -27,7 +27,7 @@ + + typedef struct { + zval *data[VAR_ENTRIES_MAX]; +- int used_slots; ++ long used_slots; + void *next; + } var_entries; + +@@ -54,9 +54,33 @@ + var_hash->data[var_hash->used_slots++] = *rval; + } + ++static inline void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) ++{ ++ var_entries *var_hash = var_hashx->first_dtor, *prev = NULL; ++ ++ while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { ++ prev = var_hash; ++ var_hash = var_hash->next; ++ } ++ ++ if (!var_hash) { ++ var_hash = emalloc(sizeof(var_entries)); ++ var_hash->used_slots = 0; ++ var_hash->next = 0; ++ ++ if (!var_hashx->first_dtor) ++ var_hashx->first_dtor = var_hash; ++ else ++ prev->next = var_hash; ++ } ++ ++ (*rval)->refcount++; ++ var_hash->data[var_hash->used_slots++] = *rval; ++} ++ + PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval) + { +- int i; ++ long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) { +@@ -70,7 +94,7 @@ + } + } + +-static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) ++static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store) + { + var_entries *var_hash = var_hashx->first; + +@@ -91,6 +115,7 @@ + PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) + { + void *next; ++ long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) { +@@ -98,6 +123,17 @@ + efree(var_hash); + var_hash = next; + } ++ ++ var_hash = var_hashx->first_dtor; ++ ++ while (var_hash) { ++ for (i = 0; i < var_hash->used_slots; i++) { ++ zval_ptr_dtor(&var_hash->data[i]); ++ } ++ next = var_hash->next; ++ efree(var_hash); ++ var_hash = next; ++ } + } + + /* }}} */ +@@ -119,10 +155,10 @@ + + + +-static inline int parse_iv2(const unsigned char *p, const unsigned char **q) ++static inline long parse_iv2(const unsigned char *p, const unsigned char **q) + { + char cursor; +- int result = 0; ++ long result = 0; + int neg = 0; + + switch (*p) { +@@ -147,7 +183,7 @@ + return result; + } + +-static inline int parse_iv(const unsigned char *p) ++static inline long parse_iv(const unsigned char *p) + { + return parse_iv2(p, NULL); + } +@@ -177,10 +213,10 @@ + #define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC + #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC + +-static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements) ++static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements) + { + while (elements-- > 0) { +- zval *key, *data, *old_data; ++ zval *key, *data, **old_data; + + ALLOC_INIT_ZVAL(key); + +@@ -208,14 +244,14 @@ + + switch (Z_TYPE_P(key)) { + case IS_LONG: +- if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)) { +- var_replace(var_hash, old_data, rval); ++ if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); + } + zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL); + break; + case IS_STRING: +- if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)) { +- var_replace(var_hash, old_data, rval); ++ if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); + } + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL); + break; +@@ -246,7 +282,7 @@ + + static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) + { +- int elements; ++ long elements; + + elements = parse_iv2((*p) + 2, p); + +@@ -256,7 +292,7 @@ + return elements; + } + +-static inline int object_common2(UNSERIALIZE_PARAMETER, int elements) ++static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) + { + zval *retval_ptr = NULL; + zval fname; +@@ -308,7 +344,7 @@ + /*!re2c + + "R:" iv ";" { +- int id; ++ long id; + + *p = YYCURSOR; + if (!var_hash) return 0; +@@ -329,7 +365,7 @@ + } + + "r:" iv ";" { +- int id; ++ long id; + + *p = YYCURSOR; + if (!var_hash) return 0; +@@ -375,9 +411,7 @@ + "d:" ("NAN" | "-"? "INF") ";" { + *p = YYCURSOR; + INIT_PZVAL(*rval); +-#if defined(HAVE_ATOF_ACCEPTS_NAN) && defined(HAVE_ATOF_ACCEPTS_INF) +- ZVAL_DOUBLE(*rval, atof(start + 2)); +-#else ++ + if (!strncmp(start + 2, "NAN", 3)) { + ZVAL_DOUBLE(*rval, php_get_nan()); + } else if (!strncmp(start + 2, "INF", 3)) { +@@ -385,14 +419,14 @@ + } else if (!strncmp(start + 2, "-INF", 4)) { + ZVAL_DOUBLE(*rval, -php_get_inf()); + } +-#endif ++ + return 1; + } + + "d:" (iv | nv | nvexp) ";" { + *p = YYCURSOR; + INIT_PZVAL(*rval); +- ZVAL_DOUBLE(*rval, atof(start + 2)); ++ ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); + return 1; + } + +@@ -425,10 +459,18 @@ + } + + "a:" uiv ":" "{" { +- int elements = parse_iv(start + 2); +- ++ long elements = parse_iv(start + 2); ++ /* use iv() not uiv() in order to check data range */ + *p = YYCURSOR; + ++ if (elements < 0) { ++ return 0; ++ } ++ ++ if (elements < 0) { ++ return 0; ++ } ++ + INIT_PZVAL(*rval); + Z_TYPE_PP(rval) = IS_ARRAY; + ALLOC_HASHTABLE(Z_ARRVAL_PP(rval)); +@@ -451,8 +493,8 @@ + } + + "O:" uiv ":" ["] { +- size_t len, len2, maxlen; +- int elements; ++ size_t len, len2, len3, maxlen; ++ long elements; + char *class_name; + zend_class_entry *ce; + int incomplete_class = 0; +@@ -486,6 +528,14 @@ + class_name = str_tolower_copy((char *)emalloc(len+1), class_name, len); + class_name[len] = '\0'; + ++ len3 = strspn(class_name, "0123456789_abcdefghijklmnopqrstuvwxyz"); ++ if (len3 != len) ++ { ++ *p = YYCURSOR + len3 - len; ++ efree(class_name); ++ return 0; ++ } ++ + if (zend_hash_find(CG(class_table), class_name, len + 1, (void **) &ce) != SUCCESS) { + if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { + incomplete_class = 1; +diff -Nur php-4.3.10/ext/swf/swf.c hardened-php-4.3.10-0.2.7/ext/swf/swf.c +--- php-4.3.10/ext/swf/swf.c 2003-09-12 06:53:39.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/ext/swf/swf.c 2005-04-07 01:51:16.000000000 +0200 +@@ -16,7 +16,7 @@ + +----------------------------------------------------------------------+ + */ + +-/* $Id: swf.c,v 1.46.2.2 2003/09/12 04:53:39 iliaa Exp $ */ ++/* $Id: swf.c,v 1.46.2.4 2004/12/23 18:29:36 iliaa Exp $ */ + + + #ifdef HAVE_CONFIG_H +@@ -239,12 +239,17 @@ + } + na = tmpna; + #endif ++ if (php_check_open_basedir(na TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(na, "wb+", CHECKUID_CHECK_MODE_PARAM))) { ++ goto err; ++ } ++ + if (!SWFG(use_file)) + SWFG(tmpfile_name) = na; + + swf_openfile(na,(float)Z_DVAL_PP(sizeX), (float)Z_DVAL_PP(sizeY), + (float)Z_DVAL_PP(frameRate), (float)Z_DVAL_PP(r), + (float)Z_DVAL_PP(g), (float)Z_DVAL_PP(b)); ++err: + #ifdef VIRTUAL_DIR + free(na); + #endif +@@ -606,8 +611,13 @@ + convert_to_double_ex(width); + + if (Z_TYPE_PP(coordinates) != IS_ARRAY) { +- return; + php_error(E_WARNING, "Wrong datatype of second argument to swf_definepoly"); ++ RETURN_FALSE; ++ } ++ ++ if (Z_LVAL_PP(NumPoints) > 256) { ++ php_error(E_WARNING, "The npoints value cannot be larger then 256."); ++ RETURN_FALSE; + } + + npoints = Z_LVAL_PP(NumPoints); +diff -Nur php-4.3.10/ext/varfilter/CREDITS hardened-php-4.3.10-0.2.7/ext/varfilter/CREDITS +--- php-4.3.10/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/varfilter/CREDITS 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,2 @@ ++varfilter ++Stefan Esser +\ No newline at end of file +diff -Nur php-4.3.10/ext/varfilter/config.m4 hardened-php-4.3.10-0.2.7/ext/varfilter/config.m4 +--- php-4.3.10/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/varfilter/config.m4 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,11 @@ ++dnl ++dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++dnl ++ ++PHP_ARG_ENABLE(varfilter, whether to enable Hardened-PHP's variable filter, ++[ --disable-varfilter Disable Hardened-PHP's variable filter], yes) ++ ++if test "$PHP_VARFILTER" != "no"; then ++ AC_DEFINE(HAVE_VARFILTER, 1, [ ]) ++ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared) ++fi +diff -Nur php-4.3.10/ext/varfilter/php_varfilter.h hardened-php-4.3.10-0.2.7/ext/varfilter/php_varfilter.h +--- php-4.3.10/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/varfilter/php_varfilter.h 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,72 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 4 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2003 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++*/ ++ ++#ifndef PHP_VARFILTER_H ++#define PHP_VARFILTER_H ++ ++extern zend_module_entry varfilter_module_entry; ++#define phpext_varfilter_ptr &varfilter_module_entry ++ ++#ifdef PHP_WIN32 ++#define PHP_VARFILTER_API __declspec(dllexport) ++#else ++#define PHP_VARFILTER_API ++#endif ++ ++#ifdef ZTS ++#include "TSRM.h" ++#endif ++ ++#include "SAPI.h" ++ ++PHP_MINIT_FUNCTION(varfilter); ++PHP_MSHUTDOWN_FUNCTION(varfilter); ++PHP_RINIT_FUNCTION(varfilter); ++PHP_RSHUTDOWN_FUNCTION(varfilter); ++PHP_MINFO_FUNCTION(varfilter); ++ ++ ++ZEND_BEGIN_MODULE_GLOBALS(varfilter) ++ long max_request_variables; ++ long cur_request_variables; ++ long max_varname_length; ++ long max_value_length; ++ long max_array_depth; ++ZEND_END_MODULE_GLOBALS(varfilter) ++ ++ ++#ifdef ZTS ++#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v) ++#else ++#define VARFILTER_G(v) (varfilter_globals.v) ++#endif ++ ++SAPI_INPUT_FILTER_FUNC(varfilter_input_filter); ++ ++#endif /* PHP_VARFILTER_H */ ++ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * indent-tabs-mode: t ++ * End: ++ */ +diff -Nur php-4.3.10/ext/varfilter/varfilter.c hardened-php-4.3.10-0.2.7/ext/varfilter/varfilter.c +--- php-4.3.10/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/ext/varfilter/varfilter.c 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,196 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 4 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2003 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: | ++ +----------------------------------------------------------------------+ ++ ++ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++*/ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "php.h" ++#include "php_ini.h" ++#include "ext/standard/info.h" ++#include "php_varfilter.h" ++#include "hardened_php.h" ++ ++ZEND_DECLARE_MODULE_GLOBALS(varfilter) ++ ++/* True global resources - no need for thread safety here */ ++static int le_varfilter; ++ ++/* {{{ varfilter_module_entry ++ */ ++zend_module_entry varfilter_module_entry = { ++#if ZEND_MODULE_API_NO >= 20010901 ++ STANDARD_MODULE_HEADER, ++#endif ++ "varfilter", ++ NULL, ++ PHP_MINIT(varfilter), ++ PHP_MSHUTDOWN(varfilter), ++ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */ ++ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */ ++ PHP_MINFO(varfilter), ++#if ZEND_MODULE_API_NO >= 20010901 ++ "0.2.0", /* Replace with version number for your extension */ ++#endif ++ STANDARD_MODULE_PROPERTIES ++}; ++/* }}} */ ++ ++#ifdef COMPILE_DL_VARFILTER ++ZEND_GET_MODULE(varfilter) ++#endif ++ ++/* {{{ PHP_INI ++ */ ++PHP_INI_BEGIN() ++ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_SYSTEM, OnUpdateInt, max_request_variables, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_SYSTEM, OnUpdateInt, max_varname_length, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_value_length", "10000", PHP_INI_SYSTEM, OnUpdateInt, max_value_length, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_SYSTEM, OnUpdateInt, max_array_depth, zend_varfilter_globals, varfilter_globals) ++PHP_INI_END() ++/* }}} */ ++ ++/* {{{ php_varfilter_init_globals ++ */ ++static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals) ++{ ++ varfilter_globals->max_request_variables = 200; ++ varfilter_globals->cur_request_variables = 0; ++ varfilter_globals->max_varname_length = 64; ++ varfilter_globals->max_value_length = 10000; ++ varfilter_globals->max_array_depth = 100; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINIT_FUNCTION ++ */ ++PHP_MINIT_FUNCTION(varfilter) ++{ ++ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL); ++ REGISTER_INI_ENTRIES(); ++ ++ sapi_register_input_filter(varfilter_input_filter); ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MSHUTDOWN_FUNCTION ++ */ ++PHP_MSHUTDOWN_FUNCTION(varfilter) ++{ ++ UNREGISTER_INI_ENTRIES(); ++ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* Remove if there's nothing to do at request start */ ++/* {{{ PHP_RINIT_FUNCTION ++ */ ++PHP_RINIT_FUNCTION(varfilter) ++{ ++ VARFILTER_G(cur_request_variables) = 0; ++ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* Remove if there's nothing to do at request end */ ++/* {{{ PHP_RSHUTDOWN_FUNCTION ++ */ ++PHP_RSHUTDOWN_FUNCTION(varfilter) ++{ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINFO_FUNCTION ++ */ ++PHP_MINFO_FUNCTION(varfilter) ++{ ++ php_info_print_table_start(); ++ php_info_print_table_header(2, "Hardened-PHP's variable filter support", "enabled"); ++ php_info_print_table_end(); ++ ++ DISPLAY_INI_ENTRIES(); ++} ++/* }}} */ ++ ++/* {{{ SAPI_INPUT_FILTER_FUNC ++ */ ++SAPI_INPUT_FILTER_FUNC(varfilter_input_filter) ++{ ++ char *index; ++ unsigned int var_len, depth = 0; ++ ++ /* Drop this variable if the limit is reached */ ++ if (VARFILTER_G(max_request_variables) == VARFILTER_G(cur_request_variables)) { ++ php_security_log("tried to register too many variables"); ++ return 0; ++ } ++ ++ /* Drop this variable if it exceeds the value length limit */ ++ if (VARFILTER_G(max_value_length) < val_len) { ++ php_security_log("tried to register a variable with a too long value"); ++ return 0; ++ } ++ ++ /* Find length of variable name */ ++ index = strchr(var, '['); ++ var_len = index ? index-var : strlen(var); ++ ++ /* Drop this variable if it exceeds the varname length limit */ ++ if (VARFILTER_G(max_varname_length) < var_len) { ++ php_security_log("tried to register a variable with a too long variable name"); ++ return 0; ++ } ++ ++ /* Find out array depth */ ++ while (index) { ++ depth++; ++ index = strchr(index+1, '['); ++ } ++ ++ /* Drop this variable if it exceeds the array depth limit */ ++ if (VARFILTER_G(max_array_depth) < depth) { ++ php_security_log("tried to register a too deep array variable"); ++ return 0; ++ } ++ ++ /* Okay let PHP register this variable */ ++ VARFILTER_G(cur_request_variables)++; ++ ++ if (new_val_len) { ++ *new_val_len = val_len; ++ } ++ ++ return 1; ++} ++/* }}} */ ++ ++ ++/* ++ * 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 ++ */ +diff -Nur php-4.3.10/main/SAPI.c hardened-php-4.3.10-0.2.7/main/SAPI.c +--- php-4.3.10/main/SAPI.c 2004-08-19 22:35:36.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/main/SAPI.c 2005-04-07 01:51:16.000000000 +0200 +@@ -823,6 +823,12 @@ + return SUCCESS; + } + ++SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)) ++{ ++ sapi_module.input_filter = input_filter; ++ return SUCCESS; ++} ++ + + SAPI_API int sapi_flush(TSRMLS_D) + { +diff -Nur php-4.3.10/main/SAPI.h hardened-php-4.3.10-0.2.7/main/SAPI.h +--- php-4.3.10/main/SAPI.h 2003-04-09 22:27:55.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/main/SAPI.h 2005-04-07 01:51:16.000000000 +0200 +@@ -101,9 +101,14 @@ + char *current_user; + int current_user_length; + +- /* this is necessary for CLI module */ +- int argc; +- char **argv; ++ /* this is necessary for CLI module */ ++ int argc; ++ char **argv; ++ ++#if HARDENED_PHP ++ /* this is necessary for IP logging */ ++ char ip_address[64]; ++#endif + } sapi_request_info; + + +@@ -177,6 +182,7 @@ + SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry); + SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D)); + SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC)); ++SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)); + + SAPI_API int sapi_flush(TSRMLS_D); + SAPI_API struct stat *sapi_get_stat(TSRMLS_D); +@@ -238,8 +244,11 @@ + int (*get_target_uid)(uid_t * TSRMLS_DC); + int (*get_target_gid)(gid_t * TSRMLS_DC); + ++ unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC); ++ + void (*ini_defaults)(HashTable *configuration_hash); + int phpinfo_as_text; ++ + }; + + +@@ -262,16 +271,23 @@ + + #define SAPI_DEFAULT_MIMETYPE "text/html" + #define SAPI_DEFAULT_CHARSET "" ++ ++#if HARDENED_PHP ++#define SAPI_PHP_VERSION_HEADER "X-Powered-By: Hardened-PHP/" PHP_VERSION ++#else + #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION ++#endif + + #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D) + #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC) + + #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC) ++#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) + + SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data); + SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader); + SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data); ++SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter); + + #define STANDARD_SAPI_MODULE_PROPERTIES + +diff -Nur php-4.3.10/main/fopen_wrappers.c hardened-php-4.3.10-0.2.7/main/fopen_wrappers.c +--- php-4.3.10/main/fopen_wrappers.c 2004-03-16 01:32:09.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/fopen_wrappers.c 2005-04-07 01:51:16.000000000 +0200 +@@ -16,7 +16,7 @@ + | Jim Winstead | + +----------------------------------------------------------------------+ + */ +-/* $Id: fopen_wrappers.c,v 1.153.2.9 2004/03/16 00:32:09 iliaa Exp $ */ ++/* $Id: fopen_wrappers.c,v 1.153.2.10 2005/02/02 23:44:07 iliaa Exp $ */ + + /* {{{ includes + */ +@@ -106,24 +106,11 @@ + char resolved_name[MAXPATHLEN]; + char resolved_basedir[MAXPATHLEN]; + char local_open_basedir[MAXPATHLEN]; +- int local_open_basedir_pos; + int resolved_basedir_len; + int resolved_name_len; + + /* Special case basedir==".": Use script-directory */ +- if ((strcmp(basedir, ".") == 0) && +- SG(request_info).path_translated && +- *SG(request_info).path_translated +- ) { +- strlcpy(local_open_basedir, SG(request_info).path_translated, sizeof(local_open_basedir)); +- local_open_basedir_pos = strlen(local_open_basedir) - 1; +- +- /* Strip filename */ +- while (!IS_SLASH(local_open_basedir[local_open_basedir_pos]) +- && (local_open_basedir_pos >= 0)) { +- local_open_basedir[local_open_basedir_pos--] = 0; +- } +- } else { ++ if (strcmp(basedir, ".") || !VCWD_GETCWD(local_open_basedir, MAXPATHLEN)) { + /* Else use the unmodified path */ + strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir)); + } +@@ -179,6 +166,21 @@ + char *pathbuf; + char *ptr; + char *end; ++ char path_copy[MAXPATHLEN]; ++ int path_len; ++ ++ /* Special case path ends with a trailing slash */ ++ path_len = strlen(path); ++ if (path_len >= MAXPATHLEN) { ++ errno = EPERM; /* we deny permission to open it */ ++ return -1; ++ } ++ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) { ++ memcpy(path_copy, path, path_len+1); ++ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--; ++ path_copy[path_len] = '\0'; ++ path = (const char *)&path_copy; ++ } + + pathbuf = estrdup(PG(open_basedir)); + +diff -Nur php-4.3.10/main/hardened_globals.h hardened-php-4.3.10-0.2.7/main/hardened_globals.h +--- php-4.3.10/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/hardened_globals.h 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,54 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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 | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef HARDENED_GLOBALS_H ++#define HARDENED_GLOBALS_H ++ ++typedef struct _hardened_globals hardened_globals_struct; ++ ++#ifdef ZTS ++# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v) ++extern int hardened_globals_id; ++#else ++# define HG(v) (hardened_globals.v) ++extern struct _hardened_globals hardened_globals; ++#endif ++ ++ ++struct _hardened_globals { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary_1; ++ unsigned int canary_2; ++#endif ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_3; ++ unsigned int canary_4; ++ unsigned int ll_canary_inited; ++#endif ++ unsigned int dummy; ++}; ++ ++ ++#endif /* HARDENED_GLOBALS_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nur php-4.3.10/main/hardened_php.c hardened-php-4.3.10-0.2.7/main/hardened_php.c +--- php-4.3.10/main/hardened_php.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/hardened_php.c 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,205 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: hardened_php.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */ ++ ++#include "php.h" ++ ++#include ++#include ++ ++#if HAVE_UNISTD_H ++#include ++#endif ++#include "SAPI.h" ++#include "php_globals.h" ++ ++#if HARDENED_PHP ++ ++#ifdef HAVE_SYS_SOCKET_H ++#include ++#endif ++ ++#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE) ++#undef AF_UNIX ++#endif ++ ++#if defined(AF_UNIX) ++#include ++#endif ++ ++#define SYSLOG_PATH "/dev/log" ++ ++#include "snprintf.h" ++ ++#ifdef ZTS ++#include "hardened_globals.h" ++int hardened_globals_id; ++#else ++struct _hardened_globals hardened_globals; ++#endif ++ ++static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC) ++{ ++ memset(hardened_globals, 0, sizeof(*hardened_globals)); ++} ++ ++PHPAPI void hardened_startup() ++{ ++#ifdef ZTS ++ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL); ++#else ++ hardened_globals_ctor(&hardened_globals TSRMLS_CC); ++#endif ++} ++ ++PHPAPI void php_security_log(char *str) ++{ ++#if defined(AF_UNIX) ++ int s, r; ++ struct sockaddr_un saun; ++ char buf[1024]; ++ char *ip_address; ++ char *fname; ++ TSRMLS_FETCH(); ++ ++ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC); ++ if (ip_address == NULL) { ++ ip_address = "REMOTE_ADDR not set"; ++ } ++ ++ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC); ++ ++ ap_php_snprintf(buf, 1024, "php security-alert: %s (attacker '%s', file '%s')\n", str, ip_address, fname); ++ ++ s = socket(AF_UNIX, SOCK_DGRAM, 0); ++ if (s == -1) { ++ return; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ s = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (s == -1) { ++ return; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ return; ++ } ++ } ++ send(s, buf, strlen(buf), 0); ++ ++ close(s); ++#endif ++} ++#endif ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++ ++/* will be replaced later with more compatible method */ ++PHPAPI unsigned int php_canary() ++{ ++ time_t t; ++ unsigned int canary; ++ int fd; ++ ++ fd = open("/dev/urandom", 0); ++ if (fd != -1) { ++ int r = read(fd, &canary, sizeof(canary)); ++ close(fd); ++ if (r == sizeof(canary)) { ++ return (canary); ++ } ++ } ++ /* not good but we never want to do this */ ++ time(&t); ++ canary = *(unsigned int *)&t + getpid() << 16; ++ return (canary); ++} ++#endif ++ ++#if HARDENED_PHP_INC_PROTECT ++ ++PHPAPI int php_is_valid_include(zval *z) ++{ ++ char *filename; ++ int len; ++ TSRMLS_FETCH(); ++ ++ /* must be of type string */ ++ if (z->type != IS_STRING || z->value.str.val == NULL) { ++ return (0); ++ } ++ ++ /* short cut */ ++ filename = z->value.str.val; ++ len = z->value.str.len; ++ ++ /* 1. must be shorter than MAXPATHLEN */ ++ if (len > MAXPATHLEN) { ++ php_security_log("Include filename longer than MAXPATHLEN chars"); ++ return (0); ++ } ++ ++ /* 2. must not be cutted */ ++ if (len != strlen(filename)) { ++ php_security_log("Include filename has a \\0 cut"); ++ return (0); ++ } ++ ++ /* 3. must not be a URL */ ++ if (strstr(filename, "://")) { ++ php_security_log("Include filename is an URL"); ++ return (0); ++ } ++ ++ /* 4. must not be an uploaded file */ ++ if (SG(rfc1867_uploaded_files)) { ++ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) { ++ php_security_log("Include filename is an uploaded file"); ++ return (0); ++ } ++ } ++ ++ /* passed all tests */ ++ return (1); ++} ++ ++#endif ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nur php-4.3.10/main/hardened_php.h hardened-php-4.3.10-0.2.7/main/hardened_php.h +--- php-4.3.10/main/hardened_php.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/hardened_php.h 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,45 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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 | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef HARDENED_PHP_H ++#define HARDENED_PHP_H ++ ++#include "zend.h" ++ ++#if HARDENED_PHP ++PHPAPI void php_security_log(char *str); ++PHPAPI void hardened_startup(); ++#define HARDENED_PHP_VERSION "0.2.7" ++#endif ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++PHPAPI unsigned int php_canary(); ++#endif ++ ++#if HARDENED_PHP_INC_PROTECT ++PHPAPI int php_is_valid_include(zval *z); ++#endif ++ ++#endif /* HARDENED_PHP_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nur php-4.3.10/main/hardened_php.m4 hardened-php-4.3.10-0.2.7/main/hardened_php.m4 +--- php-4.3.10/main/hardened_php.m4 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/hardened_php.m4 2005-04-07 01:51:16.000000000 +0200 +@@ -0,0 +1,95 @@ ++dnl ++dnl $Id: hardened_php.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $ ++dnl ++dnl This file contains Hardened-PHP specific autoconf functions. ++dnl ++ ++AC_ARG_ENABLE(hardened-php-mm-protect, ++[ --disable-hardened-php-mm-protect Disable the Memory Manager protection.],[ ++ DO_HARDENED_PHP_MM_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_MM_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-ll-protect, ++[ --disable-hardened-php-ll-protect Disable the Linked List protection.],[ ++ DO_HARDENED_PHP_LL_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_LL_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-inc-protect, ++[ --disable-hardened-php-inc-protect Disable include/require protection.],[ ++ DO_HARDENED_PHP_INC_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_INC_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-fmt-protect, ++[ --disable-hardened-php-fmt-protect Disable format string protection.],[ ++ DO_HARDENED_PHP_FMT_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_FMT_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-hash-protect, ++[ --disable-hardened-php-hash-protect Disable HashTable destructor protection.],[ ++ DO_HARDENED_PHP_HASH_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_HASH_PROTECT=yes ++]) ++ ++AC_MSG_CHECKING(whether to protect the Zend Memory Manager) ++AC_MSG_RESULT($DO_HARDENED_PHP_MM_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect the Zend Linked Lists) ++AC_MSG_RESULT($DO_HARDENED_PHP_LL_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect include/require statements) ++AC_MSG_RESULT($DO_HARDENED_PHP_INC_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect PHP Format String functions) ++AC_MSG_RESULT($DO_HARDENED_PHP_FMT_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables) ++AC_MSG_RESULT($DO_HARDENED_PHP_HASH_PROTECT) ++ ++ ++AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ ++ ++if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 1, [Memory Manager Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 0, [Memory Manager Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 1, [Linked List Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 0, [Linked List Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 1, [Include/Require Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 0, [Include/Require Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 1, [Fmt String Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 0, [Fmt String Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_HASH_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_HASH_PROTECT, 1, [HashTable DTOR Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_HASH_PROTECT, 0, [HashTable DTOR Protection]) ++fi ++ +diff -Nur php-4.3.10/main/main.c hardened-php-4.3.10-0.2.7/main/main.c +--- php-4.3.10/main/main.c 2004-10-01 16:27:13.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/main/main.c 2005-04-07 01:51:16.000000000 +0200 +@@ -100,6 +100,10 @@ + PHPAPI int core_globals_id; + #endif + ++#if HARDENED_PHP ++#include "hardened_globals.h" ++#endif ++ + #define ERROR_BUF_LEN 1024 + + typedef struct { +@@ -150,10 +154,33 @@ + */ + static PHP_INI_MH(OnChangeMemoryLimit) + { ++#if HARDENED_PHP ++ long orig_memory_limit; ++ ++ if (entry->modified) { ++ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length); ++ } else { ++ orig_memory_limit = 1<<30; ++ } ++ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) { ++ orig_memory_limit = 1<<30; ++ } ++#endif + if (new_value) { + PG(memory_limit) = zend_atoi(new_value, new_value_length); ++#if HARDENED_PHP ++ if (PG(memory_limit) > orig_memory_limit) { ++ PG(memory_limit) = orig_memory_limit; ++ php_security_log("script tried to increase memory_limit above allowed value"); ++ return FAILURE; ++ } ++#endif + } else { ++#if HARDENED_PHP ++ PG(memory_limit) = orig_memory_limit; ++#else + PG(memory_limit) = 1<<30; /* effectively, no limit */ ++#endif + } + return zend_set_memory_limit(PG(memory_limit)); + } +@@ -1091,6 +1118,10 @@ + tsrm_ls = ts_resource(0); + #endif + ++#if HARDENED_PHP ++ hardened_startup(); ++#endif ++ + sapi_initialize_empty_request(TSRMLS_C); + sapi_activate(TSRMLS_C); + +@@ -1103,6 +1134,12 @@ + php_output_startup(); + php_output_activate(TSRMLS_C); + ++#if HARDENED_PHP_INC_PROTECT ++ zuf.is_valid_include = php_is_valid_include; ++#endif ++#if HARDENED_PHP ++ zuf.security_log_function = php_security_log; ++#endif + zuf.error_function = php_error_cb; + zuf.printf_function = php_printf; + zuf.write_function = php_body_write_wrapper; +@@ -1204,6 +1241,10 @@ + REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS); ++#if HARDENED_PHP ++ REGISTER_MAIN_LONG_CONSTANT("HARDENED_PHP", 1, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_STRINGL_CONSTANT("HARDENED_PHP_VERSION", HARDENED_PHP_VERSION, sizeof(HARDENED_PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS); ++#endif + REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS); + php_output_register_constants(TSRMLS_C); + php_rfc1867_register_constants(TSRMLS_C); +@@ -1339,6 +1380,7 @@ + ulong num_key; + HashPosition pos; + int key_type; ++ int globals_check = (PG(register_globals) && (dest == (&EG(symbol_table)))); + + zend_hash_internal_pointer_reset_ex(src, &pos); + while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) { +@@ -1349,7 +1391,12 @@ + || Z_TYPE_PP(dest_entry) != IS_ARRAY) { + (*src_entry)->refcount++; + if (key_type == HASH_KEY_IS_STRING) { +- zend_hash_update(dest, string_key, strlen(string_key)+1, src_entry, sizeof(zval *), NULL); ++ /* if register_globals is on and working with main symbol table, prevent overwriting of GLOBALS */ ++ if (!globals_check || string_key_len != sizeof("GLOBALS") || memcmp(string_key, "GLOBALS", sizeof("GLOBALS") - 1)) { ++ zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL); ++ } else { ++ (*src_entry)->refcount--; ++ } + } else { + zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL); + } +diff -Nur php-4.3.10/main/php.h hardened-php-4.3.10-0.2.7/main/php.h +--- php-4.3.10/main/php.h 2004-11-28 13:44:56.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/php.h 2005-04-07 01:51:16.000000000 +0200 +@@ -35,11 +35,19 @@ + #include "zend_qsort.h" + #include "php_compat.h" + ++ + #include "zend_API.h" + + #undef sprintf + #define sprintf php_sprintf + ++#if HARDENED_PHP ++#if HAVE_REALPATH ++#undef realpath ++#define realpath php_realpath ++#endif ++#endif ++ + /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */ + #undef PHP_DEBUG + #define PHP_DEBUG ZEND_DEBUG +@@ -436,6 +444,10 @@ + #endif + #endif /* !XtOffsetOf */ + ++#if HARDENED_PHP ++#include "hardened_php.h" ++#endif ++ + #endif + + /* +diff -Nur php-4.3.10/main/php_config.h.in hardened-php-4.3.10-0.2.7/main/php_config.h.in +--- php-4.3.10/main/php_config.h.in 2004-12-14 18:55:22.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/php_config.h.in 2005-04-07 01:51:16.000000000 +0200 +@@ -834,6 +834,39 @@ + /* Enabling BIND8 compatibility for Panther */ + #undef BIND_8_COMPAT + ++/* Hardened-PHP */ ++#undef HARDENED_PHP ++ ++/* Memory Manager Protection */ ++#undef HARDENED_PHP_MM_PROTECT ++ ++/* Memory Manager Protection */ ++#undef HARDENED_PHP_MM_PROTECT ++ ++/* Linked List Protection */ ++#undef HARDENED_PHP_LL_PROTECT ++ ++/* Linked List Protection */ ++#undef HARDENED_PHP_LL_PROTECT ++ ++/* Include/Require Protection */ ++#undef HARDENED_PHP_INC_PROTECT ++ ++/* Include/Require Protection */ ++#undef HARDENED_PHP_INC_PROTECT ++ ++/* Fmt String Protection */ ++#undef HARDENED_PHP_FMT_PROTECT ++ ++/* Fmt String Protection */ ++#undef HARDENED_PHP_FMT_PROTECT ++ ++/* HashTable DTOR Protection */ ++#undef HARDENED_PHP_HASH_PROTECT ++ ++/* HashTable DTOR Protection */ ++#undef HARDENED_PHP_HASH_PROTECT ++ + /* Whether you have AOLserver */ + #undef HAVE_AOLSERVER + +@@ -1117,6 +1150,12 @@ + /* Define if you have the getaddrinfo function */ + #undef HAVE_GETADDRINFO + ++/* Whether realpath is broken */ ++#undef PHP_BROKEN_REALPATH ++ ++/* Whether realpath is broken */ ++#undef PHP_BROKEN_REALPATH ++ + /* Whether system headers declare timezone */ + #undef HAVE_DECLARED_TIMEZONE + +diff -Nur php-4.3.10/main/php_content_types.c hardened-php-4.3.10-0.2.7/main/php_content_types.c +--- php-4.3.10/main/php_content_types.c 2002-12-31 17:26:14.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/php_content_types.c 2005-04-07 01:51:16.000000000 +0200 +@@ -77,6 +77,7 @@ + sapi_register_post_entries(php_post_entries); + sapi_register_default_post_reader(php_default_post_reader); + sapi_register_treat_data(php_default_treat_data); ++ sapi_register_input_filter(php_default_input_filter); + return SUCCESS; + } + /* }}} */ +diff -Nur php-4.3.10/main/php_variables.c hardened-php-4.3.10-0.2.7/main/php_variables.c +--- php-4.3.10/main/php_variables.c 2004-10-18 17:08:46.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/main/php_variables.c 2005-04-07 01:51:16.000000000 +0200 +@@ -211,17 +211,28 @@ + while (var) { + val = strchr(var, '='); + if (val) { /* have a value */ +- int val_len; ++ unsigned int val_len, new_val_len; + + *val++ = '\0'; + php_url_decode(var, strlen(var)); + val_len = php_url_decode(val, strlen(val)); +- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC); ++ val = estrndup(val, val_len); ++ if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); + } + var = php_strtok_r(NULL, "&", &strtok_buf); + } + } + ++SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter) ++{ ++ /* TODO: check .ini setting here and apply user-defined input filter */ ++ *new_val_len = val_len; ++ return 1; ++} ++ + SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data) + { + char *res = NULL, *var, *val, *separator=NULL; +@@ -299,15 +310,26 @@ + while (var) { + val = strchr(var, '='); + if (val) { /* have a value */ +- int val_len; ++ unsigned int val_len, new_val_len; + + *val++ = '\0'; + php_url_decode(var, strlen(var)); + val_len = php_url_decode(val, strlen(val)); +- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC); ++ val = estrndup(val, val_len); ++ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); + } else { ++ unsigned int val_len, new_val_len; ++ + php_url_decode(var, strlen(var)); +- php_register_variable_safe(var, "", 0, array_ptr TSRMLS_CC); ++ val_len = 0; ++ val = estrndup("", 0); ++ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); + } + var = php_strtok_r(NULL, separator, &strtok_buf); + } +diff -Nur php-4.3.10/main/rfc1867.c hardened-php-4.3.10-0.2.7/main/rfc1867.c +--- php-4.3.10/main/rfc1867.c 2004-11-20 21:16:44.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/rfc1867.c 2005-04-07 01:51:16.000000000 +0200 +@@ -891,21 +891,24 @@ + if (!filename && param) { + + char *value = multipart_buffer_read_body(mbuff TSRMLS_CC); ++ unsigned int new_val_len; /* Dummy variable */ + + if (!value) { + value = estrdup(""); + } + ++ if (sapi_module.input_filter(PARSE_POST, param, &value, strlen(value), &new_val_len TSRMLS_CC)) { + #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) +- if (php_mb_encoding_translation(TSRMLS_C)) { +- php_mb_gpc_stack_variable(param, value, &val_list, &len_list, +- &num_vars, &num_vars_max TSRMLS_CC); +- } else { +- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); +- } ++ if (php_mb_encoding_translation(TSRMLS_C)) { ++ php_mb_gpc_stack_variable(param, value, &val_list, &len_list, ++ &num_vars, &num_vars_max TSRMLS_CC); ++ } else { ++ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); ++ } + #else +- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); ++ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); + #endif ++ } + if (!strcasecmp(param, "MAX_FILE_SIZE")) { + max_file_size = atol(value); + } +diff -Nur php-4.3.10/main/snprintf.c hardened-php-4.3.10-0.2.7/main/snprintf.c +--- php-4.3.10/main/snprintf.c 2004-11-16 00:27:26.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/main/snprintf.c 2005-04-07 01:51:16.000000000 +0200 +@@ -850,7 +850,11 @@ + + + case 'n': ++#if HARDENED_PHP_FMT_PROTECT ++ php_security_log("'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = cc; ++#endif + break; + + /* +diff -Nur php-4.3.10/main/spprintf.c hardened-php-4.3.10-0.2.7/main/spprintf.c +--- php-4.3.10/main/spprintf.c 2003-09-29 03:09:36.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/main/spprintf.c 2005-04-07 01:51:16.000000000 +0200 +@@ -531,7 +531,11 @@ + + + case 'n': ++#if HARDENED_PHP_FMT_PROTECT ++ php_security_log("'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = cc; ++#endif + break; + + /* +diff -Nur php-4.3.10/php.ini-dist hardened-php-4.3.10-0.2.7/php.ini-dist +--- php-4.3.10/php.ini-dist 2004-08-18 07:05:23.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/php.ini-dist 2005-04-07 01:51:16.000000000 +0200 +@@ -1113,6 +1113,23 @@ + ;exif.decode_jis_motorola = JIS + ;exif.decode_jis_intel = JIS + ++[varfilter] ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++; Hardened-PHP's variable filter ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++ ++; Maximum number of input variables per request ++varfilter.max_request_variables = 200 ++ ++; Maximum characters in input variable names ++varfilter.max_varname_length = 64 ++ ++; Maximum length of input variable values ++varfilter.max_value_length = 10000 ++ ++; Maximum depth of input variable arrays ++varfilter.max_array_depth = 100 ++ + ; Local Variables: + ; tab-width: 4 + ; End: +diff -Nur php-4.3.10/php.ini-recommended hardened-php-4.3.10-0.2.7/php.ini-recommended +--- php-4.3.10/php.ini-recommended 2004-08-18 07:05:23.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/php.ini-recommended 2005-04-07 01:51:16.000000000 +0200 +@@ -1111,6 +1111,23 @@ + ;exif.decode_jis_motorola = JIS + ;exif.decode_jis_intel = JIS + ++[varfilter] ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++; Hardened-PHP's variable filter ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++ ++; Maximum number of input variables per request ++varfilter.max_request_variables = 200 ++ ++; Maximum characters in input variable names ++varfilter.max_varname_length = 64 ++ ++; Maximum length of input variable values ++varfilter.max_value_length = 10000 ++ ++; Maximum depth of input variable arrays ++varfilter.max_array_depth = 100 ++ + ; Local Variables: + ; tab-width: 4 + ; End: +diff -Nur php-4.3.10/sapi/apache/mod_php4.c hardened-php-4.3.10-0.2.7/sapi/apache/mod_php4.c +--- php-4.3.10/sapi/apache/mod_php4.c 2004-07-21 18:25:28.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/sapi/apache/mod_php4.c 2005-04-07 01:51:16.000000000 +0200 +@@ -446,7 +446,7 @@ + sapi_apache_get_fd, + sapi_apache_force_http_10, + sapi_apache_get_target_uid, +- sapi_apache_get_target_gid ++ sapi_apache_get_target_gid, + }; + /* }}} */ + +@@ -892,7 +892,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component("Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component("PHP/" PHP_VERSION); ++#endif + } + } + #endif +diff -Nur php-4.3.10/sapi/apache2filter/sapi_apache2.c hardened-php-4.3.10-0.2.7/sapi/apache2filter/sapi_apache2.c +--- php-4.3.10/sapi/apache2filter/sapi_apache2.c 2004-06-18 02:37:02.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/sapi/apache2filter/sapi_apache2.c 2005-04-07 01:51:16.000000000 +0200 +@@ -560,7 +560,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nur php-4.3.10/sapi/apache2handler/sapi_apache2.c hardened-php-4.3.10-0.2.7/sapi/apache2handler/sapi_apache2.c +--- php-4.3.10/sapi/apache2handler/sapi_apache2.c 2004-12-06 19:55:16.000000000 +0100 ++++ hardened-php-4.3.10-0.2.7/sapi/apache2handler/sapi_apache2.c 2005-04-07 01:51:16.000000000 +0200 +@@ -337,7 +337,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nur php-4.3.10/sapi/cgi/cgi_main.c hardened-php-4.3.10-0.2.7/sapi/cgi/cgi_main.c +--- php-4.3.10/sapi/cgi/cgi_main.c 2004-07-15 00:38:18.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/sapi/cgi/cgi_main.c 2005-04-07 01:51:16.000000000 +0200 +@@ -1426,11 +1426,19 @@ + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + } ++#if HARDENED_PHP ++#if ZEND_DEBUG ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + php_end_ob_buffers(1 TSRMLS_CC); + exit(1); + break; +diff -Nur php-4.3.10/sapi/cli/php_cli.c hardened-php-4.3.10-0.2.7/sapi/cli/php_cli.c +--- php-4.3.10/sapi/cli/php_cli.c 2004-07-15 00:38:18.000000000 +0200 ++++ hardened-php-4.3.10-0.2.7/sapi/cli/php_cli.c 2005-04-07 01:51:16.000000000 +0200 +@@ -646,11 +646,19 @@ + if (php_request_startup(TSRMLS_C)==FAILURE) { + goto err; + } ++#if HARDENED_PHP ++#if ZEND_DEBUG ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + php_end_ob_buffers(1 TSRMLS_CC); + exit_status=1; + goto out; diff --git a/0.2.7/hardened-php-4.3.11-0.2.7.patch b/0.2.7/hardened-php-4.3.11-0.2.7.patch new file mode 100644 index 0000000..d91abe4 --- /dev/null +++ b/0.2.7/hardened-php-4.3.11-0.2.7.patch @@ -0,0 +1,3417 @@ +diff -Nur php-4.3.11/README.input_filter hardened-php-4.3.11-0.2.7/README.input_filter +--- php-4.3.11/README.input_filter 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/README.input_filter 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,193 @@ ++Input Filter Support ported from PHP 5 ++-------------------------------------- ++ ++XSS (Cross Site Scripting) hacks are becoming more and more prevalent, ++and can be quite difficult to prevent. Whenever you accept user data ++and somehow display this data back to users, you are likely vulnerable ++to XSS hacks. ++ ++The Input Filter support in PHP 5 is aimed at providing the framework ++through which a company-wide or site-wide security policy can be ++enforced. It is implemented as a SAPI hook and is called from the ++treat_data and post handler functions. To implement your own security ++policy you will need to write a standard PHP extension. ++ ++A simple implementation might look like the following. This stores the ++original raw user data and adds a my_get_raw() function while the normal ++$_POST, $_GET and $_COOKIE arrays are only populated with stripped ++data. In this simple example all I am doing is calling strip_tags() on ++the data. If register_globals is turned on, the default globals that ++are created will be stripped ($foo) while a $RAW_foo is created with the ++original user input. ++ ++ZEND_BEGIN_MODULE_GLOBALS(my_input_filter) ++ zval *post_array; ++ zval *get_array; ++ zval *cookie_array; ++ZEND_END_MODULE_GLOBALS(my_input_filter) ++ ++#ifdef ZTS ++#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v) ++#else ++#define IF_G(v) (my_input_filter_globals.v) ++#endif ++ ++ZEND_DECLARE_MODULE_GLOBALS(my_input_filter) ++ ++function_entry my_input_filter_functions[] = { ++ PHP_FE(my_get_raw, NULL) ++ {NULL, NULL, NULL} ++}; ++ ++zend_module_entry my_input_filter_module_entry = { ++ STANDARD_MODULE_HEADER, ++ "my_input_filter", ++ my_input_filter_functions, ++ PHP_MINIT(my_input_filter), ++ PHP_MSHUTDOWN(my_input_filter), ++ NULL, ++ PHP_RSHUTDOWN(my_input_filter), ++ PHP_MINFO(my_input_filter), ++ "0.1", ++ STANDARD_MODULE_PROPERTIES ++}; ++ ++PHP_MINIT_FUNCTION(my_input_filter) ++{ ++ ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL); ++ ++ REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT); ++ REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT); ++ REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT); ++ ++ sapi_register_input_filter(my_sapi_input_filter); ++ return SUCCESS; ++} ++ ++PHP_RSHUTDOWN_FUNCTION(my_input_filter) ++{ ++ if(IF_G(get_array)) { ++ zval_ptr_dtor(&IF_G(get_array)); ++ IF_G(get_array) = NULL; ++ } ++ if(IF_G(post_array)) { ++ zval_ptr_dtor(&IF_G(post_array)); ++ IF_G(post_array) = NULL; ++ } ++ if(IF_G(cookie_array)) { ++ zval_ptr_dtor(&IF_G(cookie_array)); ++ IF_G(cookie_array) = NULL; ++ } ++ return SUCCESS; ++} ++ ++PHP_MINFO_FUNCTION(my_input_filter) ++{ ++ php_info_print_table_start(); ++ php_info_print_table_row( 2, "My Input Filter Support", "enabled" ); ++ php_info_print_table_row( 2, "Revision", "$Revision: 1.1 $"); ++ php_info_print_table_end(); ++} ++ ++/* The filter handler. If you return 1 from it, then PHP also registers the ++ * (modified) variable. Returning 0 prevents PHP from registering the variable; ++ * you can use this if your filter already registers the variable under a ++ * different name, or if you just don't want the variable registered at all. */ ++SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter) ++{ ++ zval new_var; ++ zval *array_ptr = NULL; ++ char *raw_var; ++ int var_len; ++ ++ assert(*val != NULL); ++ ++ switch(arg) { ++ case PARSE_GET: ++ if(!IF_G(get_array)) { ++ ALLOC_ZVAL(array_ptr); ++ array_init(array_ptr); ++ INIT_PZVAL(array_ptr); ++ } ++ IF_G(get_array) = array_ptr; ++ break; ++ case PARSE_POST: ++ if(!IF_G(post_array)) { ++ ALLOC_ZVAL(array_ptr); ++ array_init(array_ptr); ++ INIT_PZVAL(array_ptr); ++ } ++ IF_G(post_array) = array_ptr; ++ break; ++ case PARSE_COOKIE: ++ if(!IF_G(cookie_array)) { ++ ALLOC_ZVAL(array_ptr); ++ array_init(array_ptr); ++ INIT_PZVAL(array_ptr); ++ } ++ IF_G(cookie_array) = array_ptr; ++ break; ++ } ++ Z_STRLEN(new_var) = val_len; ++ Z_STRVAL(new_var) = estrndup(*val, val_len); ++ Z_TYPE(new_var) = IS_STRING; ++ ++ var_len = strlen(var); ++ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */ ++ strcpy(raw_var, "RAW_"); ++ strlcat(raw_var,var,var_len+5); ++ ++ php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC); ++ ++ php_strip_tags(*val, val_len, NULL, NULL, 0); ++ ++ *new_val_len = strlen(*val); ++ return 1; ++} ++ ++PHP_FUNCTION(my_get_raw) ++{ ++ long arg; ++ char *var; ++ int var_len; ++ zval **tmp; ++ zval *array_ptr = NULL; ++ HashTable *hash_ptr; ++ char *raw_var; ++ ++ if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) { ++ return; ++ } ++ ++ switch(arg) { ++ case PARSE_GET: ++ array_ptr = IF_G(get_array); ++ break; ++ case PARSE_POST: ++ array_ptr = IF_G(post_array); ++ break; ++ case PARSE_COOKIE: ++ array_ptr = IF_G(post_array); ++ break; ++ } ++ ++ if(!array_ptr) RETURN_FALSE; ++ ++ /* ++ * I'm changing the variable name here because when running with register_globals on, ++ * the variable will end up in the global symbol table ++ */ ++ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */ ++ strcpy(raw_var, "RAW_"); ++ strlcat(raw_var,var,var_len+5); ++ hash_ptr = HASH_OF(array_ptr); ++ ++ if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) { ++ *return_value = **tmp; ++ zval_copy_ctor(return_value); ++ } else { ++ RETVAL_FALSE; ++ } ++ efree(raw_var); ++} ++ +diff -Nur php-4.3.11/TSRM/TSRM.h hardened-php-4.3.11-0.2.7/TSRM/TSRM.h +--- php-4.3.11/TSRM/TSRM.h 2005-02-11 04:34:04.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/TSRM/TSRM.h 2005-04-07 02:08:26.000000000 +0200 +@@ -33,6 +33,13 @@ + # define TSRM_API + #endif + ++#if HARDENED_PHP ++# if HAVE_REALPATH ++# undef realpath ++# define realpath php_realpath ++# endif ++#endif ++ + /* Only compile multi-threading functions if we're in ZTS mode */ + #ifdef ZTS + +@@ -90,6 +97,7 @@ + + #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts + ++ + #ifdef __cplusplus + extern "C" { + #endif +diff -Nur php-4.3.11/TSRM/tsrm_virtual_cwd.c hardened-php-4.3.11-0.2.7/TSRM/tsrm_virtual_cwd.c +--- php-4.3.11/TSRM/tsrm_virtual_cwd.c 2005-02-11 04:34:04.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/TSRM/tsrm_virtual_cwd.c 2005-04-07 02:08:26.000000000 +0200 +@@ -192,6 +192,165 @@ + return p; + } + ++#if HARDENED_PHP ++CWD_API char *php_realpath(const char *path, char *resolved) ++{ ++ struct stat sb; ++ char *p, *q, *s; ++ size_t left_len, resolved_len; ++ unsigned symlinks; ++ int serrno, slen; ++ int is_dir = 1; ++ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; ++ ++ serrno = errno; ++ symlinks = 0; ++ if (path[0] == '/') { ++ resolved[0] = '/'; ++ resolved[1] = '\0'; ++ if (path[1] == '\0') ++ return (resolved); ++ resolved_len = 1; ++ left_len = strlcpy(left, path + 1, sizeof(left)); ++ } else { ++ if (getcwd(resolved, PATH_MAX) == NULL) { ++ strlcpy(resolved, ".", PATH_MAX); ++ return (NULL); ++ } ++ resolved_len = strlen(resolved); ++ left_len = strlcpy(left, path, sizeof(left)); ++ } ++ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ ++ /* ++ * Iterate over path components in `left'. ++ */ ++ while (left_len != 0) { ++ /* ++ * Extract the next path component and adjust `left' ++ * and its length. ++ */ ++ p = strchr(left, '/'); ++ s = p ? p : left + left_len; ++ if (s - left >= sizeof(next_token)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ memcpy(next_token, left, s - left); ++ next_token[s - left] = '\0'; ++ left_len -= s - left; ++ if (p != NULL) ++ memmove(left, s + 1, left_len + 1); ++ if (resolved[resolved_len - 1] != '/') { ++ if (resolved_len + 1 >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ resolved[resolved_len++] = '/'; ++ resolved[resolved_len] = '\0'; ++ } ++ if (next_token[0] == '\0') ++ continue; ++ else if (strcmp(next_token, ".") == 0) ++ continue; ++ else if (strcmp(next_token, "..") == 0) { ++ /* ++ * Strip the last path component except when we have ++ * single "/" ++ */ ++ if (!is_dir) { ++ errno = ENOENT; ++ return (NULL); ++ } ++ if (resolved_len > 1) { ++ resolved[resolved_len - 1] = '\0'; ++ q = strrchr(resolved, '/'); ++ *q = '\0'; ++ resolved_len = q - resolved; ++ } ++ continue; ++ } ++ ++ /* ++ * Append the next path component and lstat() it. If ++ * lstat() fails we still can return successfully if ++ * there are no more path components left. ++ */ ++ resolved_len = strlcat(resolved, next_token, PATH_MAX); ++ if (resolved_len >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ if (lstat(resolved, &sb) != 0) { ++ if (errno == ENOENT && p == NULL) { ++ errno = serrno; ++ return (resolved); ++ } ++ return (NULL); ++ } ++ if (S_ISLNK(sb.st_mode)) { ++ if (symlinks++ > MAXSYMLINKS) { ++ errno = ELOOP; ++ return (NULL); ++ } ++ slen = readlink(resolved, symlink, sizeof(symlink) - 1); ++ if (slen < 0) ++ return (NULL); ++ symlink[slen] = '\0'; ++ if (symlink[0] == '/') { ++ resolved[1] = 0; ++ resolved_len = 1; ++ } else if (resolved_len > 1) { ++ /* Strip the last path component. */ ++ resolved[resolved_len - 1] = '\0'; ++ q = strrchr(resolved, '/'); ++ *q = '\0'; ++ resolved_len = q - resolved; ++ } ++ ++ /* ++ * If there are any path components left, then ++ * append them to symlink. The result is placed ++ * in `left'. ++ */ ++ if (p != NULL) { ++ if (symlink[slen - 1] != '/') { ++ if (slen + 1 >= sizeof(symlink)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ symlink[slen] = '/'; ++ symlink[slen + 1] = 0; ++ } ++ left_len = strlcat(symlink, left, sizeof(left)); ++ if (left_len >= sizeof(left)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ } ++ left_len = strlcpy(left, symlink, sizeof(left)); ++ } else { ++ if (S_ISDIR(sb.st_mode)) { ++ is_dir = 1; ++ } else { ++ is_dir = 0; ++ } ++ } ++ } ++ ++ /* ++ * Remove trailing slash except when the resolved pathname ++ * is a single "/". ++ */ ++ if (resolved_len > 1 && resolved[resolved_len - 1] == '/') ++ resolved[resolved_len - 1] = '\0'; ++ return (resolved); ++} ++#endif ++ + CWD_API void virtual_cwd_startup(void) + { + char cwd[MAXPATHLEN]; +@@ -314,8 +473,7 @@ + path = resolved_path; + path_length = strlen(path); + } else { +- /* disable for now +- return 1; */ ++ return 1; + } + } + } else { /* Concat current directory with relative path and then run realpath() on it */ +@@ -341,9 +499,8 @@ + path = resolved_path; + path_length = strlen(path); + } else { +- /* disable for now + free(tmp); +- return 1; */ ++ return 1; + } + } + free(tmp); +diff -Nur php-4.3.11/TSRM/tsrm_virtual_cwd.h hardened-php-4.3.11-0.2.7/TSRM/tsrm_virtual_cwd.h +--- php-4.3.11/TSRM/tsrm_virtual_cwd.h 2005-02-11 04:34:04.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/TSRM/tsrm_virtual_cwd.h 2005-04-07 02:08:26.000000000 +0200 +@@ -128,6 +128,22 @@ + + typedef int (*verify_path_func)(const cwd_state *); + ++#ifndef HAVE_STRLCPY ++CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz); ++#undef strlcpy ++#define strlcpy php_strlcpy ++#endif ++ ++#ifndef HAVE_STRLCAT ++CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz); ++#undef strlcat ++#define strlcat php_strlcat ++#endif ++ ++ ++#if HARDENED_PHP ++CWD_API char *php_realpath(const char *path, char *resolved); ++#endif + CWD_API void virtual_cwd_startup(void); + CWD_API void virtual_cwd_shutdown(void); + CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC); +diff -Nur php-4.3.11/Zend/zend.c hardened-php-4.3.11-0.2.7/Zend/zend.c +--- php-4.3.11/Zend/zend.c 2005-01-22 21:36:34.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend.c 2005-04-07 02:08:26.000000000 +0200 +@@ -53,6 +53,12 @@ + ZEND_API void (*zend_unblock_interruptions)(void); + ZEND_API void (*zend_ticks_function)(int ticks); + ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); ++#if HARDENED_PHP ++ZEND_API void (*zend_security_log)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ZEND_API int (*zend_is_valid_include)(zval *z); ++#endif + + void (*zend_on_timeout)(int seconds TSRMLS_DC); + +@@ -420,6 +426,14 @@ + extern zend_scanner_globals language_scanner_globals; + #endif + ++ /* Set up Hardened-PHP utility functions first */ ++#if HARDENED_PHP ++ zend_security_log = utility_functions->security_log_function; ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ zend_is_valid_include = utility_functions->is_valid_include; ++#endif ++ + #ifdef ZTS + ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor); + #else +diff -Nur php-4.3.11/Zend/zend.h hardened-php-4.3.11-0.2.7/Zend/zend.h +--- php-4.3.11/Zend/zend.h 2005-01-25 14:08:41.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend.h 2005-04-07 02:08:26.000000000 +0200 +@@ -275,9 +275,9 @@ + struct _zval_struct { + /* Variable information */ + zvalue_value value; /* value */ ++ zend_uint refcount; + zend_uchar type; /* active type */ + zend_uchar is_ref; +- zend_ushort refcount; + }; + + +@@ -338,6 +338,12 @@ + void (*ticks_function)(int ticks); + void (*on_timeout)(int seconds TSRMLS_DC); + zend_bool (*open_function)(const char *filename, struct _zend_file_handle *); ++#if HARDENED_PHP ++ void (*security_log_function)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ int (*is_valid_include)(zval *z); ++#endif + } zend_utility_functions; + + +@@ -469,7 +475,16 @@ + extern ZEND_API void (*zend_ticks_function)(int ticks); + extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0); + extern void (*zend_on_timeout)(int seconds TSRMLS_DC); ++#if HARDENED_PHP ++extern ZEND_API void (*zend_security_log)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++extern ZEND_API int (*zend_is_valid_include)(zval *z); ++#endif + ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++ZEND_API unsigned int zend_canary(void); ++#endif + + ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 2, 3); + +@@ -576,6 +591,10 @@ + + #define ZEND_MAX_RESERVED_RESOURCES 4 + ++#if HARDENED_PHP ++#include "hardened_globals.h" ++#endif ++ + #endif /* ZEND_H */ + + /* +diff -Nur php-4.3.11/Zend/zend_alloc.c hardened-php-4.3.11-0.2.7/Zend/zend_alloc.c +--- php-4.3.11/Zend/zend_alloc.c 2004-08-27 18:51:25.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_alloc.c 2005-04-07 02:11:04.000000000 +0200 +@@ -56,6 +56,11 @@ + # define END_MAGIC_SIZE 0 + #endif + ++#if HARDENED_PHP_MM_PROTECT ++# define CANARY_SIZE sizeof(unsigned int) ++#else ++# define CANARY_SIZE 0 ++#endif + + # if MEMORY_LIMIT + # if ZEND_DEBUG +@@ -95,9 +100,17 @@ + if (p==AG(head)) { \ + AG(head) = p->pNext; \ + } else { \ ++ if (p != p->pLast->pNext) { \ ++ zend_security_log("linked list corrupt on efree() - heap corruption detected"); \ ++ exit(1); \ ++ } \ + p->pLast->pNext = p->pNext; \ + } \ + if (p->pNext) { \ ++ if (p != p->pNext->pLast) { \ ++ zend_security_log("linked list corrupt on efree() - heap corruption detected"); \ ++ exit(1); \ ++ } \ + p->pNext->pLast = p->pLast; \ + } + +@@ -129,6 +142,12 @@ + DECLARE_CACHE_VARS(); + TSRMLS_FETCH(); + ++#if HARDENED_PHP_MM_PROTECT ++ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) { ++ zend_security_log("emalloc() - requested size would result in integer overflow"); ++ exit(1); ++ } ++#endif + CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size); + + if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] > 0)) { +@@ -146,6 +165,10 @@ + AG(cache_stats)[CACHE_INDEX][1]++; + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif ++#if HARDENED_PHP_MM_PROTECT ++ p->canary = HG(canary_1); ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + p->cached = 0; + p->size = size; + return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING); +@@ -161,7 +184,7 @@ + AG(allocated_memory_peak) = AG(allocated_memory); + } + #endif +- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE); ++ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE); + } + + HANDLE_BLOCK_INTERRUPTIONS(); +@@ -191,7 +214,10 @@ + # endif + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif +- ++#if HARDENED_PHP_MM_PROTECT ++ p->canary = HG(canary_1); ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING); + } +@@ -218,17 +244,33 @@ + return emalloc_rel(lval + offset); + } + } +- ++ ++#if HARDENED_PHP ++ zend_security_log("Possible integer overflow catched by safe_emalloc()"); ++#endif + zend_error(E_ERROR, "Possible integer overflow in memory allocation (%ld * %ld + %ld)", nmemb, size, offset); + return 0; + } + + ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int *canary_2; ++#endif + zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING); + DECLARE_CACHE_VARS(); + TSRMLS_FETCH(); + ++#if HARDENED_PHP_MM_PROTECT ++ canary_2 = (unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE); ++ if (p->canary != HG(canary_1) || *canary_2 != HG(canary_2)) { ++ zend_security_log("canary mismatch on efree() - heap overflow or double efree detected"); ++ exit(1); ++ } ++ /* to catch double efree()s */ ++ *canary_2 = p->canary = 0; ++#endif ++ + #if defined(ZTS) && TSRM_DEBUG + if (p->thread_id != tsrm_thread_id()) { + tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) on thread %x freed at %s:(%d) on thread %x, ignoring", +@@ -273,6 +315,9 @@ + size_t _size = nmemb * size; + + if (nmemb && (_size/nmemb!=size)) { ++#if HARDENED_PHP ++ zend_security_log("Possible integer overflow catched by ecalloc()"); ++#endif + fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size); + #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID + kill(getpid(), SIGSEGV); +@@ -292,6 +337,9 @@ + + ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary_2; ++#endif + zend_mem_header *p; + zend_mem_header *orig; + DECLARE_CACHE_VARS(); +@@ -303,6 +351,14 @@ + + p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING); + ++#if HARDENED_PHP_MM_PROTECT ++ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE); ++ if (p->canary != HG(canary_1) || canary_2 != HG(canary_2)) { ++ zend_security_log("canary mismatch on erealloc() - heap overflow detected"); ++ exit(1); ++ } ++#endif ++ + #if defined(ZTS) && TSRM_DEBUG + if (p->thread_id != tsrm_thread_id()) { + void *new_p; +@@ -326,7 +382,7 @@ + } + #endif + REMOVE_POINTER_FROM_LIST(p); +- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE); ++ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE); + if (!p) { + if (!allow_failure) { + fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size); +@@ -348,6 +404,9 @@ + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif + ++#if HARDENED_PHP_MM_PROTECT ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + p->size = size; + + HANDLE_UNBLOCK_INTERRUPTIONS(); +@@ -423,6 +482,10 @@ + { + AG(head) = NULL; + ++#if HARDENED_PHP_MM_PROTECT ++ HG(canary_1) = zend_canary(); ++ HG(canary_2) = zend_canary(); ++#endif + #if MEMORY_LIMIT + AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */ + AG(allocated_memory) = 0; +diff -Nur php-4.3.11/Zend/zend_alloc.h hardened-php-4.3.11-0.2.7/Zend/zend_alloc.h +--- php-4.3.11/Zend/zend_alloc.h 2004-08-11 08:10:46.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_alloc.h 2005-04-07 02:08:26.000000000 +0200 +@@ -32,6 +32,9 @@ + #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL + + typedef struct _zend_mem_header { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary; ++#endif + #if ZEND_DEBUG + long magic; + char *filename; +diff -Nur php-4.3.11/Zend/zend_builtin_functions.c hardened-php-4.3.11-0.2.7/Zend/zend_builtin_functions.c +--- php-4.3.11/Zend/zend_builtin_functions.c 2004-12-27 20:28:35.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_builtin_functions.c 2005-04-07 02:08:26.000000000 +0200 +@@ -49,6 +49,9 @@ + static ZEND_FUNCTION(crash); + #endif + #endif ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++static ZEND_FUNCTION(heap_overflow); ++#endif + static ZEND_FUNCTION(get_included_files); + static ZEND_FUNCTION(is_subclass_of); + static ZEND_FUNCTION(is_a); +@@ -101,6 +104,9 @@ + ZEND_FE(crash, NULL) + #endif + #endif ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++ ZEND_FE(heap_overflow, NULL) ++#endif + ZEND_FE(get_included_files, NULL) + ZEND_FALIAS(get_required_files, get_included_files, NULL) + ZEND_FE(is_subclass_of, NULL) +@@ -805,6 +811,19 @@ + + #endif /* ZEND_DEBUG */ + ++ ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++ZEND_FUNCTION(heap_overflow) ++{ ++ char *nowhere = emalloc(10); ++ ++ memcpy(nowhere, "something1234567890", sizeof("something1234567890")); ++ ++ efree(nowhere); ++} ++#endif ++ ++ + /* {{{ proto array get_included_files(void) + Returns an array with the file names that were include_once()'d */ + ZEND_FUNCTION(get_included_files) +diff -Nur php-4.3.11/Zend/zend_canary.c hardened-php-4.3.11-0.2.7/Zend/zend_canary.c +--- php-4.3.11/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_canary.c 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,58 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */ ++ ++#include "zend.h" ++ ++#include ++#include ++ ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT ++ ++/* will be replaced later with more compatible method */ ++ZEND_API unsigned int zend_canary() ++{ ++ time_t t; ++ unsigned int canary; ++ int fd; ++ ++ fd = open("/dev/urandom", 0); ++ if (fd != -1) { ++ int r = read(fd, &canary, sizeof(canary)); ++ close(fd); ++ if (r == sizeof(canary)) { ++ return (canary); ++ } ++ } ++ /* not good but we never want to do this */ ++ time(&t); ++ canary = *(unsigned int *)&t + getpid() << 16; ++ return (canary); ++} ++#endif ++ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nur php-4.3.11/Zend/zend_execute.c hardened-php-4.3.11-0.2.7/Zend/zend_execute.c +--- php-4.3.11/Zend/zend_execute.c 2005-02-21 13:38:54.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_execute.c 2005-04-07 02:08:26.000000000 +0200 +@@ -2161,7 +2161,12 @@ + int dummy = 1; + zend_file_handle file_handle = {0}; + ++#if HARDENED_PHP_INC_PROTECT ++ if (zend_is_valid_include(inc_filename) ++ && zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS ++#else + if (zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS ++#endif + && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { + + file_handle.filename = inc_filename->value.str.val; +@@ -2190,6 +2195,11 @@ + break; + case ZEND_INCLUDE: + case ZEND_REQUIRE: ++#if HARDENED_PHP_INC_PROTECT ++ if (!zend_is_valid_include(inc_filename)) { ++ break; ++ } ++#endif + new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC); + break; + case ZEND_EVAL: { +diff -Nur php-4.3.11/Zend/zend_extensions.h hardened-php-4.3.11-0.2.7/Zend/zend_extensions.h +--- php-4.3.11/Zend/zend_extensions.h 2002-12-31 17:23:02.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_extensions.h 2005-04-07 02:08:26.000000000 +0200 +@@ -23,7 +23,9 @@ + + #include "zend_compile.h" + +-#define ZEND_EXTENSION_API_NO 20021010 ++/* Create own API version number for Hardened-PHP */ ++ ++#define ZEND_EXTENSION_API_NO 1020041222 + + typedef struct _zend_extension_version_info { + int zend_extension_api_no; +diff -Nur php-4.3.11/Zend/zend_hash.c hardened-php-4.3.11-0.2.7/Zend/zend_hash.c +--- php-4.3.11/Zend/zend_hash.c 2004-07-12 23:26:46.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_hash.c 2005-04-07 02:09:31.000000000 +0200 +@@ -26,6 +26,17 @@ + # include + #endif + ++#if HARDENED_PHP_HASH_PROTECT ++ unsigned int zend_hash_canary = 0x1234567; ++ zend_bool zend_hash_canary_inited = 0; ++#endif ++ ++#define CHECK_HASH_CANARY(hash) \ ++ if (zend_hash_canary != (hash)->canary) { \ ++ zend_security_log("Zend HashTable canary was overwritten"); \ ++ exit(1); \ ++ } ++ + #define HANDLE_NUMERIC(key, length, func) { \ + register char *tmp=key; \ + \ +@@ -175,6 +186,9 @@ + { + uint i = 3; + Bucket **tmp; ++#if HARDENED_PHP_HASH_PROTECT ++ TSRMLS_FETCH(); ++#endif + + SET_INCONSISTENT(HT_OK); + +@@ -184,6 +198,13 @@ + + ht->nTableSize = 1 << i; + ht->nTableMask = ht->nTableSize - 1; ++#if HARDENED_PHP_HASH_PROTECT ++ if (zend_hash_canary_inited==0) { ++ zend_hash_canary = zend_canary(); ++ zend_hash_canary_inited = 1; ++ } ++ ht->canary = zend_hash_canary; ++#endif + ht->pDestructor = pDestructor; + ht->pListHead = NULL; + ht->pListTail = NULL; +@@ -259,6 +280,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -327,6 +351,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -402,6 +429,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -450,7 +480,7 @@ + IS_CONSISTENT(ht); + + if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */ +- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent); ++ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent); + if (t) { + HANDLE_BLOCK_INTERRUPTIONS(); + ht->arBuckets = t; +@@ -460,6 +490,7 @@ + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } ++ zend_error(E_ERROR, "zend_hash_do_resize - out of memory"); + return FAILURE; + } + return SUCCESS; +@@ -524,6 +555,9 @@ + ht->pInternalPointer = p->pListNext; + } + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { +@@ -553,6 +587,9 @@ + q = p; + p = p->pListNext; + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { +@@ -579,6 +616,9 @@ + q = p; + p = p->pListNext; + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { +@@ -608,6 +648,9 @@ + HANDLE_BLOCK_INTERRUPTIONS(); + + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { +diff -Nur php-4.3.11/Zend/zend_hash.h hardened-php-4.3.11-0.2.7/Zend/zend_hash.h +--- php-4.3.11/Zend/zend_hash.h 2002-12-31 17:23:03.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_hash.h 2005-04-07 02:08:26.000000000 +0200 +@@ -54,6 +54,9 @@ + } Bucket; + + typedef struct _hashtable { ++#if HARDENED_PHP_HASH_PROTECT ++ unsigned int canary; ++#endif + uint nTableSize; + uint nTableMask; + uint nNumOfElements; +diff -Nur php-4.3.11/Zend/zend_llist.c hardened-php-4.3.11-0.2.7/Zend/zend_llist.c +--- php-4.3.11/Zend/zend_llist.c 2002-12-31 17:23:04.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_llist.c 2005-04-07 02:08:26.000000000 +0200 +@@ -21,9 +21,34 @@ + #include "zend.h" + #include "zend_llist.h" + #include "zend_qsort.h" ++#include "zend_globals.h" ++ ++#define CHECK_LIST_CANARY(list) \ ++ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \ ++ zend_security_log("linked list canary was overwritten"); \ ++ exit(1); \ ++ } ++ ++#define CHECK_LISTELEMENT_CANARY(elem) \ ++ if (HG(canary_3) != (elem)->canary) { \ ++ zend_security_log("linked list element canary was overwritten"); \ ++ exit(1); \ ++ } ++ + + ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent) + { ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ ++ if (!HG(ll_canary_inited)) { ++ HG(canary_3) = zend_canary(); ++ HG(canary_4) = zend_canary(); ++ HG(ll_canary_inited) = 1; ++ } ++ l->canary_h = HG(canary_3); ++ l->canary_t = HG(canary_4); ++#endif + l->head = NULL; + l->tail = NULL; + l->count = 0; +@@ -37,6 +62,11 @@ + { + zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent); + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++ tmp->canary = HG(canary_3); ++#endif + tmp->prev = l->tail; + tmp->next = NULL; + if (l->tail) { +@@ -55,6 +85,11 @@ + { + zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent); + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++ tmp->canary = HG(canary_3); ++#endif + tmp->next = l->head; + tmp->prev = NULL; + if (l->head) { +@@ -91,10 +126,20 @@ + zend_llist_element *current=l->head; + zend_llist_element *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + while (current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(current) ++#endif + next = current->next; + if (compare(current->data, element)) { + DEL_LLIST_ELEMENT(current, l); ++#if HARDENED_PHP_LL_PROTECT ++ current->canary = 0; ++#endif + break; + } + current = next; +@@ -106,7 +151,14 @@ + { + zend_llist_element *current=l->head, *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + while (current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(current) ++#endif + next = current->next; + if (l->dtor) { + l->dtor(current->data); +@@ -131,7 +183,14 @@ + zend_llist_element *old_tail; + void *data; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if ((old_tail = l->tail)) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(old_tail) ++#endif + if (l->tail->prev) { + l->tail->prev->next = NULL; + } +@@ -157,9 +216,16 @@ + { + zend_llist_element *ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(src) ++#endif + zend_llist_init(dst, src->size, src->dtor, src->persistent); + ptr = src->head; + while (ptr) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(ptr) ++#endif + zend_llist_add_element(dst, ptr->data); + ptr = ptr->next; + } +@@ -170,11 +236,21 @@ + { + zend_llist_element *element, *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + element=l->head; + while (element) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + next = element->next; + if (func(element->data)) { + DEL_LLIST_ELEMENT(element, l); ++#if HARDENED_PHP_LL_PROTECT ++ element->canary = 0; ++#endif + } + element = next; + } +@@ -185,7 +261,13 @@ + { + zend_llist_element *element; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data TSRMLS_CC); + } + } +@@ -197,6 +279,9 @@ + zend_llist_element **elements; + zend_llist_element *element, **ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + if (l->count <= 0) { + return; + } +@@ -206,6 +291,9 @@ + ptr = &elements[0]; + + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + *ptr++ = element; + } + +@@ -228,7 +316,13 @@ + { + zend_llist_element *element; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data, arg TSRMLS_CC); + } + } +@@ -239,8 +333,14 @@ + zend_llist_element *element; + va_list args; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + va_start(args, num_args); + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data, num_args, args TSRMLS_CC); + } + va_end(args); +@@ -249,6 +349,10 @@ + + ZEND_API int zend_llist_count(zend_llist *l) + { ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + return l->count; + } + +@@ -256,8 +360,15 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + *current = l->head; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } else { + return NULL; +@@ -269,8 +380,15 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + *current = l->tail; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } else { + return NULL; +@@ -282,9 +400,19 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + *current = (*current)->next; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } + } +@@ -296,9 +424,19 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + *current = (*current)->prev; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } + } +diff -Nur php-4.3.11/Zend/zend_llist.h hardened-php-4.3.11-0.2.7/Zend/zend_llist.h +--- php-4.3.11/Zend/zend_llist.h 2002-12-31 17:23:04.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_llist.h 2005-04-07 02:08:26.000000000 +0200 +@@ -24,6 +24,9 @@ + #include + + typedef struct _zend_llist_element { ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary; ++#endif + struct _zend_llist_element *next; + struct _zend_llist_element *prev; + char data[1]; /* Needs to always be last in the struct */ +@@ -36,6 +39,9 @@ + typedef void (*llist_apply_func_t)(void * TSRMLS_DC); + + typedef struct _zend_llist { ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_h; /* head */ ++#endif + zend_llist_element *head; + zend_llist_element *tail; + size_t size; +@@ -43,6 +49,9 @@ + llist_dtor_func_t dtor; + unsigned char persistent; + zend_llist_element *traverse_ptr; ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_t; /* tail */ ++#endif + } zend_llist; + + typedef zend_llist_element* zend_llist_position; +diff -Nur php-4.3.11/Zend/zend_modules.h hardened-php-4.3.11-0.2.7/Zend/zend_modules.h +--- php-4.3.11/Zend/zend_modules.h 2002-12-31 17:23:04.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/Zend/zend_modules.h 2005-04-07 02:08:26.000000000 +0200 +@@ -34,7 +34,7 @@ + ZEND_API extern unsigned char second_arg_force_ref[]; + ZEND_API extern unsigned char third_arg_force_ref[]; + +-#define ZEND_MODULE_API_NO 20020429 ++#define ZEND_MODULE_API_NO 1020041222 + #ifdef ZTS + #define USING_ZTS 1 + #else +diff -Nur php-4.3.11/acinclude.m4 hardened-php-4.3.11-0.2.7/acinclude.m4 +--- php-4.3.11/acinclude.m4 2005-01-25 14:03:06.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/acinclude.m4 2005-04-07 02:08:26.000000000 +0200 +@@ -1173,6 +1173,36 @@ + fi + ]) + ++dnl ++dnl Check for broken realpath() ++dnl ++dnl realpath("/etc/hosts/../passwd",XXX) should not return ++dnl "/etc/passwd" ++dnl ++AC_DEFUN([PHP_AC_BROKEN_REALPATH],[ ++ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[ ++ AC_TRY_RUN([ ++main() { ++ char buf[4096+1]; ++ buf[0] = 0; ++ realpath("/etc/hosts/../passwd", buf); ++ exit(strcmp(buf, "/etc/passwd")==0); ++} ++ ],[ ++ ac_cv_broken_realpath=no ++ ],[ ++ ac_cv_broken_realpath=yes ++ ],[ ++ ac_cv_broken_realpath=no ++ ]) ++ ]) ++ if test "$ac_cv_broken_realpath" = "yes"; then ++ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken]) ++ else ++ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken]) ++ fi ++]) ++ + dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx) + dnl + dnl Basically sets up the link-stage for building module-name +diff -Nur php-4.3.11/configure hardened-php-4.3.11-0.2.7/configure +--- php-4.3.11/configure 2005-03-30 16:35:34.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/configure 2005-04-07 02:08:26.000000000 +0200 +@@ -394,6 +394,16 @@ + ac_default_prefix=/usr/local + # Any additions from configure.in: + ac_help="$ac_help ++ --disable-hardened-php-mm-protect Disable the Memory Manager protection." ++ac_help="$ac_help ++ --disable-hardened-php-ll-protect Disable the Linked List protection." ++ac_help="$ac_help ++ --disable-hardened-php-inc-protect Disable include/require protection." ++ac_help="$ac_help ++ --disable-hardened-php-fmt-protect Disable format string protection." ++ac_help="$ac_help ++ --disable-hardened-php-hash-protect Disable Zend HashTable DTOR protection." ++ac_help="$ac_help + + SAPI modules: + " +@@ -846,6 +856,8 @@ + ac_help="$ac_help + --disable-tokenizer Disable tokenizer support" + ac_help="$ac_help ++ --disable-varfilter Disable Hardened-PHP's variable filter" ++ac_help="$ac_help + --enable-wddx Enable WDDX support." + ac_help="$ac_help + --disable-xml Disable XML support using bundled expat lib" +@@ -2669,6 +2681,157 @@ + + + ++# Check whether --enable-hardened-php-mm-protect or --disable-hardened-php-mm-protect was given. ++if test "${enable_hardened_php_mm_protect+set}" = set; then ++ enableval="$enable_hardened_php_mm_protect" ++ ++ DO_HARDENED_PHP_MM_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_MM_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-ll-protect or --disable-hardened-php-ll-protect was given. ++if test "${enable_hardened_php_ll_protect+set}" = set; then ++ enableval="$enable_hardened_php_ll_protect" ++ ++ DO_HARDENED_PHP_LL_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_LL_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-inc-protect or --disable-hardened-php-inc-protect was given. ++if test "${enable_hardened_php_inc_protect+set}" = set; then ++ enableval="$enable_hardened_php_inc_protect" ++ ++ DO_HARDENED_PHP_INC_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_INC_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-fmt-protect or --disable-hardened-php-fmt-protect was given. ++if test "${enable_hardened_php_fmt_protect+set}" = set; then ++ enableval="$enable_hardened_php_fmt_protect" ++ ++ DO_HARDENED_PHP_FMT_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_FMT_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-hash-protect or --disable-hardened-php-hash-protect was given. ++if test "${enable_hardened_php_hash_protect+set}" = set; then ++ enableval="$enable_hardened_php_hash_protect" ++ ++ DO_HARDENED_PHP_HASH_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_HASH_PROTECT=yes ++ ++fi ++ ++ ++echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6 ++echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_MM_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6 ++echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_LL_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6 ++echo "configure:2733: checking whether to protect include/require statements" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_INC_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6 ++echo "configure:2737: checking whether to protect PHP Format String functions" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_FMT_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6 ++echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_HASH_PROTECT" 1>&6 ++ ++ ++cat >> confdefs.h <<\EOF ++#define HARDENED_PHP 1 ++EOF ++ ++ ++ ++if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_MM_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_MM_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_LL_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_LL_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_INC_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_INC_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_FMT_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_FMT_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_HASH_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_HASH_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_HASH_PROTECT 0 ++EOF ++ ++fi + + + +@@ -15486,6 +15649,62 @@ + fi + + ++ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6 ++echo "configure:14928: checking whether realpath is broken" >&5 ++if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ ++ if test "$cross_compiling" = yes; then ++ ++ ac_cv_broken_realpath=no ++ ++else ++ cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null ++then ++ ++ ac_cv_broken_realpath=no ++ ++else ++ echo "configure: failed program was:" >&5 ++ cat conftest.$ac_ext >&5 ++ rm -fr conftest* ++ ++ ac_cv_broken_realpath=yes ++ ++fi ++rm -fr conftest* ++fi ++ ++ ++fi ++ ++echo "$ac_t""$ac_cv_broken_realpath" 1>&6 ++ if test "$ac_cv_broken_realpath" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define PHP_BROKEN_REALPATH 1 ++EOF ++ ++ else ++ cat >> confdefs.h <<\EOF ++#define PHP_BROKEN_REALPATH 0 ++EOF ++ ++ fi ++ ++ + echo $ac_n "checking for declared timezone""... $ac_c" 1>&6 + echo "configure:15491: checking for declared timezone" >&5 + if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then +@@ -85975,6 +86194,265 @@ + fi + + ++echo $ac_n "checking whether to enable Hardened-PHP's variable filter""... $ac_c" 1>&6 ++echo "configure:82041: checking whether to enable Hardened-PHP's variable filter" >&5 ++# Check whether --enable-varfilter or --disable-varfilter was given. ++if test "${enable_varfilter+set}" = set; then ++ enableval="$enable_varfilter" ++ PHP_VARFILTER=$enableval ++else ++ ++ PHP_VARFILTER=yes ++ ++ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then ++ PHP_VARFILTER=$PHP_ENABLE_ALL ++ fi ++ ++fi ++ ++ ++ ++ext_output="yes, shared" ++ext_shared=yes ++case $PHP_VARFILTER in ++shared,*) ++ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'` ++ ;; ++shared) ++ PHP_VARFILTER=yes ++ ;; ++no) ++ ext_output=no ++ ext_shared=no ++ ;; ++*) ++ ext_output=yes ++ ext_shared=no ++ ;; ++esac ++ ++ ++ ++echo "$ac_t""$ext_output" 1>&6 ++ ++ ++ ++ ++if test "$PHP_VARFILTER" != "no"; then ++ cat >> confdefs.h <<\EOF ++#define HAVE_VARFILTER 1 ++EOF ++ ++ ++ ext_builddir=ext/varfilter ++ ext_srcdir=$abs_srcdir/ext/varfilter ++ ++ ac_extra= ++ ++ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then ++ ++ ++ ++ case ext/varfilter in ++ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;; ++ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;; ++ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;; ++ esac ++ ++ ++ ++ b_c_pre=$php_c_pre ++ b_cxx_pre=$php_cxx_pre ++ b_c_meta=$php_c_meta ++ b_cxx_meta=$php_cxx_meta ++ b_c_post=$php_c_post ++ b_cxx_post=$php_cxx_post ++ b_lo=$php_lo ++ ++ ++ old_IFS=$IFS ++ for ac_src in varfilter.c; do ++ ++ IFS=. ++ set $ac_src ++ ac_obj=$1 ++ IFS=$old_IFS ++ ++ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo" ++ ++ case $ac_src in ++ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; ++ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;; ++ esac ++ ++ cat >>Makefile.objects<>Makefile.objects<>Makefile.objects<> confdefs.h <>Makefile.objects<>Makefile.objects<&6 +@@ -98629,7 +99107,7 @@ + php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ + strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \ + streams.c network.c php_open_temporary_file.c php_logos.c \ +- output.c memory_streams.c user_streams.c; do ++ output.c memory_streams.c user_streams.c hardened_php.c; do + + IFS=. + set $ac_src +@@ -98802,7 +99280,7 @@ + zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \ + zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ + zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ +- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c; do ++ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c; do + + IFS=. + set $ac_src +diff -Nur php-4.3.11/configure.in hardened-php-4.3.11-0.2.7/configure.in +--- php-4.3.11/configure.in 2005-03-30 16:18:36.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/configure.in 2005-04-07 02:08:26.000000000 +0200 +@@ -227,7 +227,7 @@ + sinclude(Zend/acinclude.m4) + sinclude(Zend/Zend.m4) + sinclude(TSRM/tsrm.m4) +- ++sinclude(main/hardened_php.m4) + + + divert(2) +@@ -595,6 +595,7 @@ + AC_FUNC_ALLOCA + dnl PHP_AC_BROKEN_SPRINTF + dnl PHP_AC_BROKEN_SNPRINTF ++PHP_AC_BROKEN_REALPATH + PHP_DECLARED_TIMEZONE + PHP_TIME_R_TYPE + PHP_READDIR_R_TYPE +@@ -1224,7 +1225,7 @@ + php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ + strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \ + streams.c network.c php_open_temporary_file.c php_logos.c \ +- output.c memory_streams.c user_streams.c) ++ output.c memory_streams.c user_streams.c hardened_php.c) + PHP_ADD_SOURCES(/main, internal_functions.c,, sapi) + PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli) + +@@ -1237,7 +1238,7 @@ + zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \ + zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ + zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ +- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c) ++ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c ) + + if test -r "$abs_srcdir/Zend/zend_objects.c"; then + PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c) +diff -Nur php-4.3.11/ext/mbstring/mbstring.c hardened-php-4.3.11-0.2.7/ext/mbstring/mbstring.c +--- php-4.3.11/ext/mbstring/mbstring.c 2005-02-21 09:03:47.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/ext/mbstring/mbstring.c 2005-04-07 02:08:26.000000000 +0200 +@@ -1487,6 +1487,7 @@ + char *strtok_buf = NULL, **val_list; + zval *array_ptr = (zval *) arg; + int n, num, val_len, *len_list; ++ unsigned int new_val_len; + enum mbfl_no_encoding from_encoding; + mbfl_string string, resvar, resval; + mbfl_encoding_detector *identd = NULL; +@@ -1609,8 +1610,14 @@ + val_len = len_list[n]; + } + n++; +- /* add variable to symbol table */ +- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC); ++ /* we need val to be emalloc()ed */ ++ val = estrndup(val, val_len); ++ if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ /* add variable to symbol table */ ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); ++ + if (convd != NULL){ + mbfl_string_clear(&resvar); + mbfl_string_clear(&resval); +diff -Nur php-4.3.11/ext/standard/array.c hardened-php-4.3.11-0.2.7/ext/standard/array.c +--- php-4.3.11/ext/standard/array.c 2004-12-23 17:40:03.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/ext/standard/array.c 2005-04-07 02:08:26.000000000 +0200 +@@ -1153,6 +1153,31 @@ + } + } + } ++ ++ if (var_name[0] == 'H') { ++ if ((strcmp(var_name, "HTTP_GET_VARS")==0)|| ++ (strcmp(var_name, "HTTP_POST_VARS")==0)|| ++ (strcmp(var_name, "HTTP_POST_FILES")==0)|| ++ (strcmp(var_name, "HTTP_ENV_VARS")==0)|| ++ (strcmp(var_name, "HTTP_SERVER_VARS")==0)|| ++ (strcmp(var_name, "HTTP_SESSION_VARS")==0)|| ++ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)) { ++ return 0; ++ } ++ } else if (var_name[0] == '_') { ++ if ((strcmp(var_name, "_COOKIE")==0)|| ++ (strcmp(var_name, "_ENV")==0)|| ++ (strcmp(var_name, "_FILES")==0)|| ++ (strcmp(var_name, "_GET")==0)|| ++ (strcmp(var_name, "_POST")==0)|| ++ (strcmp(var_name, "_REQUEST")==0)|| ++ (strcmp(var_name, "_SESSION")==0)|| ++ (strcmp(var_name, "_SERVER")==0)) { ++ return 0; ++ } ++ } else if (strcmp(var_name, "GLOBALS")==0) { ++ return 0; ++ } + + return 1; + } +diff -Nur php-4.3.11/ext/standard/basic_functions.c hardened-php-4.3.11-0.2.7/ext/standard/basic_functions.c +--- php-4.3.11/ext/standard/basic_functions.c 2005-01-18 12:01:20.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/ext/standard/basic_functions.c 2005-04-07 02:08:26.000000000 +0200 +@@ -687,7 +687,7 @@ + PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL) + + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) +- PHP_FE(realpath, NULL) ++ PHP_STATIC_FE("realpath", zif_real_path, NULL) + #endif + + #ifdef HAVE_FNMATCH +@@ -3020,6 +3020,34 @@ + memcpy(new_key, prefix, prefix_len); + memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength); + ++ if (new_key[0] == 'H') { ++ if ((strcmp(new_key, "HTTP_GET_VARS")==0)|| ++ (strcmp(new_key, "HTTP_POST_VARS")==0)|| ++ (strcmp(new_key, "HTTP_POST_FILES")==0)|| ++ (strcmp(new_key, "HTTP_ENV_VARS")==0)|| ++ (strcmp(new_key, "HTTP_SERVER_VARS")==0)|| ++ (strcmp(new_key, "HTTP_SESSION_VARS")==0)|| ++ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)) { ++ efree(new_key); ++ return 0; ++ } ++ } else if (new_key[0] == '_') { ++ if ((strcmp(new_key, "_COOKIE")==0)|| ++ (strcmp(new_key, "_ENV")==0)|| ++ (strcmp(new_key, "_FILES")==0)|| ++ (strcmp(new_key, "_GET")==0)|| ++ (strcmp(new_key, "_POST")==0)|| ++ (strcmp(new_key, "_REQUEST")==0)|| ++ (strcmp(new_key, "_SESSION")==0)|| ++ (strcmp(new_key, "_SERVER")==0)) { ++ efree(new_key); ++ return 0; ++ } ++ } else if (strcmp(new_key, "GLOBALS")==0) { ++ efree(new_key); ++ return 0; ++ } ++ + zend_hash_del(&EG(symbol_table), new_key, new_key_len); + ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0); + +diff -Nur php-4.3.11/ext/standard/file.c hardened-php-4.3.11-0.2.7/ext/standard/file.c +--- php-4.3.11/ext/standard/file.c 2005-03-27 17:53:59.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/ext/standard/file.c 2005-04-07 02:08:26.000000000 +0200 +@@ -2469,7 +2469,7 @@ + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) + /* {{{ proto string realpath(string path) + Return the resolved path */ +-PHP_FUNCTION(realpath) ++PHP_FUNCTION(real_path) + { + zval **path; + char resolved_path_buff[MAXPATHLEN]; +diff -Nur php-4.3.11/ext/standard/file.h hardened-php-4.3.11-0.2.7/ext/standard/file.h +--- php-4.3.11/ext/standard/file.h 2004-06-21 21:33:47.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/ext/standard/file.h 2005-04-07 02:08:26.000000000 +0200 +@@ -64,7 +64,7 @@ + PHP_FUNCTION(fd_set); + PHP_FUNCTION(fd_isset); + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) +-PHP_FUNCTION(realpath); ++PHP_FUNCTION(real_path); + #endif + #ifdef HAVE_FNMATCH + PHP_FUNCTION(fnmatch); +diff -Nur php-4.3.11/ext/standard/info.c hardened-php-4.3.11-0.2.7/ext/standard/info.c +--- php-4.3.11/ext/standard/info.c 2004-06-09 17:10:19.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/ext/standard/info.c 2005-04-07 02:08:26.000000000 +0200 +@@ -397,7 +397,7 @@ + + if (flag & PHP_INFO_GENERAL) { + char *zend_version = get_zend_version(); +- char temp_api[9]; ++ char temp_api[11]; + + php_uname = php_get_uname('a'); + +@@ -417,11 +417,22 @@ + } + } + ++#if HARDENED_PHP ++ if (!sapi_module.phpinfo_as_text) { ++ php_printf("

Hardened-PHP Version %s/%s

\n", PHP_VERSION, HARDENED_PHP_VERSION); ++ } else { ++ char temp_ver[40]; ++ ++ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENED_PHP_VERSION); ++ php_info_print_table_row(2, "Hardened-PHP Version", temp_ver); ++ } ++#else + if (!sapi_module.phpinfo_as_text) { + php_printf("

PHP Version %s

\n", PHP_VERSION); + } else { + php_info_print_table_row(2, "PHP Version", PHP_VERSION); + } ++#endif + php_info_print_box_end(); + php_info_print_table_start(); + php_info_print_table_row(2, "System", php_uname ); +diff -Nur php-4.3.11/ext/varfilter/CREDITS hardened-php-4.3.11-0.2.7/ext/varfilter/CREDITS +--- php-4.3.11/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/ext/varfilter/CREDITS 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,2 @@ ++varfilter ++Stefan Esser +\ No newline at end of file +diff -Nur php-4.3.11/ext/varfilter/config.m4 hardened-php-4.3.11-0.2.7/ext/varfilter/config.m4 +--- php-4.3.11/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/ext/varfilter/config.m4 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,11 @@ ++dnl ++dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++dnl ++ ++PHP_ARG_ENABLE(varfilter, whether to enable Hardened-PHP's variable filter, ++[ --disable-varfilter Disable Hardened-PHP's variable filter], yes) ++ ++if test "$PHP_VARFILTER" != "no"; then ++ AC_DEFINE(HAVE_VARFILTER, 1, [ ]) ++ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared) ++fi +diff -Nur php-4.3.11/ext/varfilter/php_varfilter.h hardened-php-4.3.11-0.2.7/ext/varfilter/php_varfilter.h +--- php-4.3.11/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/ext/varfilter/php_varfilter.h 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,72 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 4 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2003 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++*/ ++ ++#ifndef PHP_VARFILTER_H ++#define PHP_VARFILTER_H ++ ++extern zend_module_entry varfilter_module_entry; ++#define phpext_varfilter_ptr &varfilter_module_entry ++ ++#ifdef PHP_WIN32 ++#define PHP_VARFILTER_API __declspec(dllexport) ++#else ++#define PHP_VARFILTER_API ++#endif ++ ++#ifdef ZTS ++#include "TSRM.h" ++#endif ++ ++#include "SAPI.h" ++ ++PHP_MINIT_FUNCTION(varfilter); ++PHP_MSHUTDOWN_FUNCTION(varfilter); ++PHP_RINIT_FUNCTION(varfilter); ++PHP_RSHUTDOWN_FUNCTION(varfilter); ++PHP_MINFO_FUNCTION(varfilter); ++ ++ ++ZEND_BEGIN_MODULE_GLOBALS(varfilter) ++ long max_request_variables; ++ long cur_request_variables; ++ long max_varname_length; ++ long max_value_length; ++ long max_array_depth; ++ZEND_END_MODULE_GLOBALS(varfilter) ++ ++ ++#ifdef ZTS ++#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v) ++#else ++#define VARFILTER_G(v) (varfilter_globals.v) ++#endif ++ ++SAPI_INPUT_FILTER_FUNC(varfilter_input_filter); ++ ++#endif /* PHP_VARFILTER_H */ ++ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * indent-tabs-mode: t ++ * End: ++ */ +diff -Nur php-4.3.11/ext/varfilter/varfilter.c hardened-php-4.3.11-0.2.7/ext/varfilter/varfilter.c +--- php-4.3.11/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/ext/varfilter/varfilter.c 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,196 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 4 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2003 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: | ++ +----------------------------------------------------------------------+ ++ ++ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++*/ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "php.h" ++#include "php_ini.h" ++#include "ext/standard/info.h" ++#include "php_varfilter.h" ++#include "hardened_php.h" ++ ++ZEND_DECLARE_MODULE_GLOBALS(varfilter) ++ ++/* True global resources - no need for thread safety here */ ++static int le_varfilter; ++ ++/* {{{ varfilter_module_entry ++ */ ++zend_module_entry varfilter_module_entry = { ++#if ZEND_MODULE_API_NO >= 20010901 ++ STANDARD_MODULE_HEADER, ++#endif ++ "varfilter", ++ NULL, ++ PHP_MINIT(varfilter), ++ PHP_MSHUTDOWN(varfilter), ++ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */ ++ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */ ++ PHP_MINFO(varfilter), ++#if ZEND_MODULE_API_NO >= 20010901 ++ "0.2.0", /* Replace with version number for your extension */ ++#endif ++ STANDARD_MODULE_PROPERTIES ++}; ++/* }}} */ ++ ++#ifdef COMPILE_DL_VARFILTER ++ZEND_GET_MODULE(varfilter) ++#endif ++ ++/* {{{ PHP_INI ++ */ ++PHP_INI_BEGIN() ++ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_SYSTEM, OnUpdateInt, max_request_variables, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_SYSTEM, OnUpdateInt, max_varname_length, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_value_length", "10000", PHP_INI_SYSTEM, OnUpdateInt, max_value_length, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_SYSTEM, OnUpdateInt, max_array_depth, zend_varfilter_globals, varfilter_globals) ++PHP_INI_END() ++/* }}} */ ++ ++/* {{{ php_varfilter_init_globals ++ */ ++static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals) ++{ ++ varfilter_globals->max_request_variables = 200; ++ varfilter_globals->cur_request_variables = 0; ++ varfilter_globals->max_varname_length = 64; ++ varfilter_globals->max_value_length = 10000; ++ varfilter_globals->max_array_depth = 100; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINIT_FUNCTION ++ */ ++PHP_MINIT_FUNCTION(varfilter) ++{ ++ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL); ++ REGISTER_INI_ENTRIES(); ++ ++ sapi_register_input_filter(varfilter_input_filter); ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MSHUTDOWN_FUNCTION ++ */ ++PHP_MSHUTDOWN_FUNCTION(varfilter) ++{ ++ UNREGISTER_INI_ENTRIES(); ++ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* Remove if there's nothing to do at request start */ ++/* {{{ PHP_RINIT_FUNCTION ++ */ ++PHP_RINIT_FUNCTION(varfilter) ++{ ++ VARFILTER_G(cur_request_variables) = 0; ++ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* Remove if there's nothing to do at request end */ ++/* {{{ PHP_RSHUTDOWN_FUNCTION ++ */ ++PHP_RSHUTDOWN_FUNCTION(varfilter) ++{ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINFO_FUNCTION ++ */ ++PHP_MINFO_FUNCTION(varfilter) ++{ ++ php_info_print_table_start(); ++ php_info_print_table_header(2, "Hardened-PHP's variable filter support", "enabled"); ++ php_info_print_table_end(); ++ ++ DISPLAY_INI_ENTRIES(); ++} ++/* }}} */ ++ ++/* {{{ SAPI_INPUT_FILTER_FUNC ++ */ ++SAPI_INPUT_FILTER_FUNC(varfilter_input_filter) ++{ ++ char *index; ++ unsigned int var_len, depth = 0; ++ ++ /* Drop this variable if the limit is reached */ ++ if (VARFILTER_G(max_request_variables) == VARFILTER_G(cur_request_variables)) { ++ php_security_log("tried to register too many variables"); ++ return 0; ++ } ++ ++ /* Drop this variable if it exceeds the value length limit */ ++ if (VARFILTER_G(max_value_length) < val_len) { ++ php_security_log("tried to register a variable with a too long value"); ++ return 0; ++ } ++ ++ /* Find length of variable name */ ++ index = strchr(var, '['); ++ var_len = index ? index-var : strlen(var); ++ ++ /* Drop this variable if it exceeds the varname length limit */ ++ if (VARFILTER_G(max_varname_length) < var_len) { ++ php_security_log("tried to register a variable with a too long variable name"); ++ return 0; ++ } ++ ++ /* Find out array depth */ ++ while (index) { ++ depth++; ++ index = strchr(index+1, '['); ++ } ++ ++ /* Drop this variable if it exceeds the array depth limit */ ++ if (VARFILTER_G(max_array_depth) < depth) { ++ php_security_log("tried to register a too deep array variable"); ++ return 0; ++ } ++ ++ /* Okay let PHP register this variable */ ++ VARFILTER_G(cur_request_variables)++; ++ ++ if (new_val_len) { ++ *new_val_len = val_len; ++ } ++ ++ return 1; ++} ++/* }}} */ ++ ++ ++/* ++ * 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 ++ */ +diff -Nur php-4.3.11/main/SAPI.c hardened-php-4.3.11-0.2.7/main/SAPI.c +--- php-4.3.11/main/SAPI.c 2005-02-22 15:46:24.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/SAPI.c 2005-04-07 02:08:26.000000000 +0200 +@@ -831,6 +831,12 @@ + return SUCCESS; + } + ++SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)) ++{ ++ sapi_module.input_filter = input_filter; ++ return SUCCESS; ++} ++ + + SAPI_API int sapi_flush(TSRMLS_D) + { +diff -Nur php-4.3.11/main/SAPI.h hardened-php-4.3.11-0.2.7/main/SAPI.h +--- php-4.3.11/main/SAPI.h 2003-04-09 22:27:55.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/main/SAPI.h 2005-04-07 02:08:26.000000000 +0200 +@@ -101,9 +101,14 @@ + char *current_user; + int current_user_length; + +- /* this is necessary for CLI module */ +- int argc; +- char **argv; ++ /* this is necessary for CLI module */ ++ int argc; ++ char **argv; ++ ++#if HARDENED_PHP ++ /* this is necessary for IP logging */ ++ char ip_address[64]; ++#endif + } sapi_request_info; + + +@@ -177,6 +182,7 @@ + SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry); + SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D)); + SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC)); ++SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)); + + SAPI_API int sapi_flush(TSRMLS_D); + SAPI_API struct stat *sapi_get_stat(TSRMLS_D); +@@ -238,8 +244,11 @@ + int (*get_target_uid)(uid_t * TSRMLS_DC); + int (*get_target_gid)(gid_t * TSRMLS_DC); + ++ unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC); ++ + void (*ini_defaults)(HashTable *configuration_hash); + int phpinfo_as_text; ++ + }; + + +@@ -262,16 +271,23 @@ + + #define SAPI_DEFAULT_MIMETYPE "text/html" + #define SAPI_DEFAULT_CHARSET "" ++ ++#if HARDENED_PHP ++#define SAPI_PHP_VERSION_HEADER "X-Powered-By: Hardened-PHP/" PHP_VERSION ++#else + #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION ++#endif + + #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D) + #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC) + + #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC) ++#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) + + SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data); + SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader); + SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data); ++SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter); + + #define STANDARD_SAPI_MODULE_PROPERTIES + +diff -Nur php-4.3.11/main/fopen_wrappers.c hardened-php-4.3.11-0.2.7/main/fopen_wrappers.c +--- php-4.3.11/main/fopen_wrappers.c 2005-02-03 00:44:07.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/fopen_wrappers.c 2005-04-07 02:07:07.000000000 +0200 +@@ -166,6 +166,21 @@ + char *pathbuf; + char *ptr; + char *end; ++ char path_copy[MAXPATHLEN]; ++ int path_len; ++ ++ /* Special case path ends with a trailing slash */ ++ path_len = strlen(path); ++ if (path_len >= MAXPATHLEN) { ++ errno = EPERM; /* we deny permission to open it */ ++ return -1; ++ } ++ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) { ++ memcpy(path_copy, path, path_len+1); ++ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--; ++ path_copy[path_len] = '\0'; ++ path = (const char *)&path_copy; ++ } + + pathbuf = estrdup(PG(open_basedir)); + +diff -Nur php-4.3.11/main/hardened_globals.h hardened-php-4.3.11-0.2.7/main/hardened_globals.h +--- php-4.3.11/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/hardened_globals.h 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,54 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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 | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef HARDENED_GLOBALS_H ++#define HARDENED_GLOBALS_H ++ ++typedef struct _hardened_globals hardened_globals_struct; ++ ++#ifdef ZTS ++# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v) ++extern int hardened_globals_id; ++#else ++# define HG(v) (hardened_globals.v) ++extern struct _hardened_globals hardened_globals; ++#endif ++ ++ ++struct _hardened_globals { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary_1; ++ unsigned int canary_2; ++#endif ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_3; ++ unsigned int canary_4; ++ unsigned int ll_canary_inited; ++#endif ++ unsigned int dummy; ++}; ++ ++ ++#endif /* HARDENED_GLOBALS_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nur php-4.3.11/main/hardened_php.c hardened-php-4.3.11-0.2.7/main/hardened_php.c +--- php-4.3.11/main/hardened_php.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/hardened_php.c 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,205 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: hardened_php.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */ ++ ++#include "php.h" ++ ++#include ++#include ++ ++#if HAVE_UNISTD_H ++#include ++#endif ++#include "SAPI.h" ++#include "php_globals.h" ++ ++#if HARDENED_PHP ++ ++#ifdef HAVE_SYS_SOCKET_H ++#include ++#endif ++ ++#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE) ++#undef AF_UNIX ++#endif ++ ++#if defined(AF_UNIX) ++#include ++#endif ++ ++#define SYSLOG_PATH "/dev/log" ++ ++#include "snprintf.h" ++ ++#ifdef ZTS ++#include "hardened_globals.h" ++int hardened_globals_id; ++#else ++struct _hardened_globals hardened_globals; ++#endif ++ ++static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC) ++{ ++ memset(hardened_globals, 0, sizeof(*hardened_globals)); ++} ++ ++PHPAPI void hardened_startup() ++{ ++#ifdef ZTS ++ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL); ++#else ++ hardened_globals_ctor(&hardened_globals TSRMLS_CC); ++#endif ++} ++ ++PHPAPI void php_security_log(char *str) ++{ ++#if defined(AF_UNIX) ++ int s, r; ++ struct sockaddr_un saun; ++ char buf[1024]; ++ char *ip_address; ++ char *fname; ++ TSRMLS_FETCH(); ++ ++ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC); ++ if (ip_address == NULL) { ++ ip_address = "REMOTE_ADDR not set"; ++ } ++ ++ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC); ++ ++ ap_php_snprintf(buf, 1024, "php security-alert: %s (attacker '%s', file '%s')\n", str, ip_address, fname); ++ ++ s = socket(AF_UNIX, SOCK_DGRAM, 0); ++ if (s == -1) { ++ return; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ s = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (s == -1) { ++ return; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ return; ++ } ++ } ++ send(s, buf, strlen(buf), 0); ++ ++ close(s); ++#endif ++} ++#endif ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++ ++/* will be replaced later with more compatible method */ ++PHPAPI unsigned int php_canary() ++{ ++ time_t t; ++ unsigned int canary; ++ int fd; ++ ++ fd = open("/dev/urandom", 0); ++ if (fd != -1) { ++ int r = read(fd, &canary, sizeof(canary)); ++ close(fd); ++ if (r == sizeof(canary)) { ++ return (canary); ++ } ++ } ++ /* not good but we never want to do this */ ++ time(&t); ++ canary = *(unsigned int *)&t + getpid() << 16; ++ return (canary); ++} ++#endif ++ ++#if HARDENED_PHP_INC_PROTECT ++ ++PHPAPI int php_is_valid_include(zval *z) ++{ ++ char *filename; ++ int len; ++ TSRMLS_FETCH(); ++ ++ /* must be of type string */ ++ if (z->type != IS_STRING || z->value.str.val == NULL) { ++ return (0); ++ } ++ ++ /* short cut */ ++ filename = z->value.str.val; ++ len = z->value.str.len; ++ ++ /* 1. must be shorter than MAXPATHLEN */ ++ if (len > MAXPATHLEN) { ++ php_security_log("Include filename longer than MAXPATHLEN chars"); ++ return (0); ++ } ++ ++ /* 2. must not be cutted */ ++ if (len != strlen(filename)) { ++ php_security_log("Include filename has a \\0 cut"); ++ return (0); ++ } ++ ++ /* 3. must not be a URL */ ++ if (strstr(filename, "://")) { ++ php_security_log("Include filename is an URL"); ++ return (0); ++ } ++ ++ /* 4. must not be an uploaded file */ ++ if (SG(rfc1867_uploaded_files)) { ++ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) { ++ php_security_log("Include filename is an uploaded file"); ++ return (0); ++ } ++ } ++ ++ /* passed all tests */ ++ return (1); ++} ++ ++#endif ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nur php-4.3.11/main/hardened_php.h hardened-php-4.3.11-0.2.7/main/hardened_php.h +--- php-4.3.11/main/hardened_php.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/hardened_php.h 2005-04-07 02:08:45.000000000 +0200 +@@ -0,0 +1,45 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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 | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef HARDENED_PHP_H ++#define HARDENED_PHP_H ++ ++#include "zend.h" ++ ++#if HARDENED_PHP ++PHPAPI void php_security_log(char *str); ++PHPAPI void hardened_startup(); ++#define HARDENED_PHP_VERSION "0.2.7" ++#endif ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++PHPAPI unsigned int php_canary(); ++#endif ++ ++#if HARDENED_PHP_INC_PROTECT ++PHPAPI int php_is_valid_include(zval *z); ++#endif ++ ++#endif /* HARDENED_PHP_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nur php-4.3.11/main/hardened_php.m4 hardened-php-4.3.11-0.2.7/main/hardened_php.m4 +--- php-4.3.11/main/hardened_php.m4 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/hardened_php.m4 2005-04-07 02:08:26.000000000 +0200 +@@ -0,0 +1,95 @@ ++dnl ++dnl $Id: hardened_php.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $ ++dnl ++dnl This file contains Hardened-PHP specific autoconf functions. ++dnl ++ ++AC_ARG_ENABLE(hardened-php-mm-protect, ++[ --disable-hardened-php-mm-protect Disable the Memory Manager protection.],[ ++ DO_HARDENED_PHP_MM_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_MM_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-ll-protect, ++[ --disable-hardened-php-ll-protect Disable the Linked List protection.],[ ++ DO_HARDENED_PHP_LL_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_LL_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-inc-protect, ++[ --disable-hardened-php-inc-protect Disable include/require protection.],[ ++ DO_HARDENED_PHP_INC_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_INC_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-fmt-protect, ++[ --disable-hardened-php-fmt-protect Disable format string protection.],[ ++ DO_HARDENED_PHP_FMT_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_FMT_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-hash-protect, ++[ --disable-hardened-php-hash-protect Disable HashTable destructor protection.],[ ++ DO_HARDENED_PHP_HASH_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_HASH_PROTECT=yes ++]) ++ ++AC_MSG_CHECKING(whether to protect the Zend Memory Manager) ++AC_MSG_RESULT($DO_HARDENED_PHP_MM_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect the Zend Linked Lists) ++AC_MSG_RESULT($DO_HARDENED_PHP_LL_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect include/require statements) ++AC_MSG_RESULT($DO_HARDENED_PHP_INC_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect PHP Format String functions) ++AC_MSG_RESULT($DO_HARDENED_PHP_FMT_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables) ++AC_MSG_RESULT($DO_HARDENED_PHP_HASH_PROTECT) ++ ++ ++AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ ++ ++if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 1, [Memory Manager Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 0, [Memory Manager Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 1, [Linked List Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 0, [Linked List Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 1, [Include/Require Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 0, [Include/Require Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 1, [Fmt String Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 0, [Fmt String Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_HASH_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_HASH_PROTECT, 1, [HashTable DTOR Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_HASH_PROTECT, 0, [HashTable DTOR Protection]) ++fi ++ +diff -Nur php-4.3.11/main/main.c hardened-php-4.3.11-0.2.7/main/main.c +--- php-4.3.11/main/main.c 2005-03-08 22:45:51.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/main.c 2005-04-07 02:08:26.000000000 +0200 +@@ -100,6 +100,10 @@ + PHPAPI int core_globals_id; + #endif + ++#if HARDENED_PHP ++#include "hardened_globals.h" ++#endif ++ + #define ERROR_BUF_LEN 1024 + + typedef struct { +@@ -150,10 +154,33 @@ + */ + static PHP_INI_MH(OnChangeMemoryLimit) + { ++#if HARDENED_PHP ++ long orig_memory_limit; ++ ++ if (entry->modified) { ++ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length); ++ } else { ++ orig_memory_limit = 1<<30; ++ } ++ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) { ++ orig_memory_limit = 1<<30; ++ } ++#endif + if (new_value) { + PG(memory_limit) = zend_atoi(new_value, new_value_length); ++#if HARDENED_PHP ++ if (PG(memory_limit) > orig_memory_limit) { ++ PG(memory_limit) = orig_memory_limit; ++ php_security_log("script tried to increase memory_limit above allowed value"); ++ return FAILURE; ++ } ++#endif + } else { ++#if HARDENED_PHP ++ PG(memory_limit) = orig_memory_limit; ++#else + PG(memory_limit) = 1<<30; /* effectively, no limit */ ++#endif + } + return zend_set_memory_limit(PG(memory_limit)); + } +@@ -1092,6 +1119,10 @@ + tsrm_ls = ts_resource(0); + #endif + ++#if HARDENED_PHP ++ hardened_startup(); ++#endif ++ + sapi_initialize_empty_request(TSRMLS_C); + sapi_activate(TSRMLS_C); + +@@ -1104,6 +1135,12 @@ + php_output_startup(); + php_output_activate(TSRMLS_C); + ++#if HARDENED_PHP_INC_PROTECT ++ zuf.is_valid_include = php_is_valid_include; ++#endif ++#if HARDENED_PHP ++ zuf.security_log_function = php_security_log; ++#endif + zuf.error_function = php_error_cb; + zuf.printf_function = php_printf; + zuf.write_function = php_body_write_wrapper; +@@ -1205,6 +1242,10 @@ + REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS); ++#if HARDENED_PHP ++ REGISTER_MAIN_LONG_CONSTANT("HARDENED_PHP", 1, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_STRINGL_CONSTANT("HARDENED_PHP_VERSION", HARDENED_PHP_VERSION, sizeof(HARDENED_PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS); ++#endif + REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS); + php_output_register_constants(TSRMLS_C); + php_rfc1867_register_constants(TSRMLS_C); +diff -Nur php-4.3.11/main/php.h hardened-php-4.3.11-0.2.7/main/php.h +--- php-4.3.11/main/php.h 2005-03-08 22:45:51.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/php.h 2005-04-07 02:08:26.000000000 +0200 +@@ -35,11 +35,19 @@ + #include "zend_qsort.h" + #include "php_compat.h" + ++ + #include "zend_API.h" + + #undef sprintf + #define sprintf php_sprintf + ++#if HARDENED_PHP ++#if HAVE_REALPATH ++#undef realpath ++#define realpath php_realpath ++#endif ++#endif ++ + /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */ + #undef PHP_DEBUG + #define PHP_DEBUG ZEND_DEBUG +@@ -436,6 +444,10 @@ + #endif + #endif /* !XtOffsetOf */ + ++#if HARDENED_PHP ++#include "hardened_php.h" ++#endif ++ + #endif + + /* +diff -Nur php-4.3.11/main/php_config.h.in hardened-php-4.3.11-0.2.7/main/php_config.h.in +--- php-4.3.11/main/php_config.h.in 2005-03-30 16:35:47.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/main/php_config.h.in 2005-04-07 02:08:26.000000000 +0200 +@@ -839,6 +839,39 @@ + /* Enabling BIND8 compatibility for Panther */ + #undef BIND_8_COMPAT + ++/* Hardened-PHP */ ++#undef HARDENED_PHP ++ ++/* Memory Manager Protection */ ++#undef HARDENED_PHP_MM_PROTECT ++ ++/* Memory Manager Protection */ ++#undef HARDENED_PHP_MM_PROTECT ++ ++/* Linked List Protection */ ++#undef HARDENED_PHP_LL_PROTECT ++ ++/* Linked List Protection */ ++#undef HARDENED_PHP_LL_PROTECT ++ ++/* Include/Require Protection */ ++#undef HARDENED_PHP_INC_PROTECT ++ ++/* Include/Require Protection */ ++#undef HARDENED_PHP_INC_PROTECT ++ ++/* Fmt String Protection */ ++#undef HARDENED_PHP_FMT_PROTECT ++ ++/* Fmt String Protection */ ++#undef HARDENED_PHP_FMT_PROTECT ++ ++/* HashTable DTOR Protection */ ++#undef HARDENED_PHP_HASH_PROTECT ++ ++/* HashTable DTOR Protection */ ++#undef HARDENED_PHP_HASH_PROTECT ++ + /* Whether you have AOLserver */ + #undef HAVE_AOLSERVER + +@@ -1122,6 +1155,12 @@ + /* Define if you have the getaddrinfo function */ + #undef HAVE_GETADDRINFO + ++/* Whether realpath is broken */ ++#undef PHP_BROKEN_REALPATH ++ ++/* Whether realpath is broken */ ++#undef PHP_BROKEN_REALPATH ++ + /* Whether system headers declare timezone */ + #undef HAVE_DECLARED_TIMEZONE + +diff -Nur php-4.3.11/main/php_content_types.c hardened-php-4.3.11-0.2.7/main/php_content_types.c +--- php-4.3.11/main/php_content_types.c 2002-12-31 17:26:14.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/php_content_types.c 2005-04-07 02:08:26.000000000 +0200 +@@ -77,6 +77,7 @@ + sapi_register_post_entries(php_post_entries); + sapi_register_default_post_reader(php_default_post_reader); + sapi_register_treat_data(php_default_treat_data); ++ sapi_register_input_filter(php_default_input_filter); + return SUCCESS; + } + /* }}} */ +diff -Nur php-4.3.11/main/php_variables.c hardened-php-4.3.11-0.2.7/main/php_variables.c +--- php-4.3.11/main/php_variables.c 2004-10-18 17:08:46.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/main/php_variables.c 2005-04-07 02:08:26.000000000 +0200 +@@ -211,17 +211,28 @@ + while (var) { + val = strchr(var, '='); + if (val) { /* have a value */ +- int val_len; ++ unsigned int val_len, new_val_len; + + *val++ = '\0'; + php_url_decode(var, strlen(var)); + val_len = php_url_decode(val, strlen(val)); +- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC); ++ val = estrndup(val, val_len); ++ if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); + } + var = php_strtok_r(NULL, "&", &strtok_buf); + } + } + ++SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter) ++{ ++ /* TODO: check .ini setting here and apply user-defined input filter */ ++ *new_val_len = val_len; ++ return 1; ++} ++ + SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data) + { + char *res = NULL, *var, *val, *separator=NULL; +@@ -299,15 +310,26 @@ + while (var) { + val = strchr(var, '='); + if (val) { /* have a value */ +- int val_len; ++ unsigned int val_len, new_val_len; + + *val++ = '\0'; + php_url_decode(var, strlen(var)); + val_len = php_url_decode(val, strlen(val)); +- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC); ++ val = estrndup(val, val_len); ++ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); + } else { ++ unsigned int val_len, new_val_len; ++ + php_url_decode(var, strlen(var)); +- php_register_variable_safe(var, "", 0, array_ptr TSRMLS_CC); ++ val_len = 0; ++ val = estrndup("", 0); ++ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) { ++ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ efree(val); + } + var = php_strtok_r(NULL, separator, &strtok_buf); + } +diff -Nur php-4.3.11/main/rfc1867.c hardened-php-4.3.11-0.2.7/main/rfc1867.c +--- php-4.3.11/main/rfc1867.c 2005-02-15 01:28:39.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/rfc1867.c 2005-04-07 02:08:26.000000000 +0200 +@@ -891,21 +891,24 @@ + if (!filename && param) { + + char *value = multipart_buffer_read_body(mbuff TSRMLS_CC); ++ unsigned int new_val_len; /* Dummy variable */ + + if (!value) { + value = estrdup(""); + } + ++ if (sapi_module.input_filter(PARSE_POST, param, &value, strlen(value), &new_val_len TSRMLS_CC)) { + #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) +- if (php_mb_encoding_translation(TSRMLS_C)) { +- php_mb_gpc_stack_variable(param, value, &val_list, &len_list, +- &num_vars, &num_vars_max TSRMLS_CC); +- } else { +- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); +- } ++ if (php_mb_encoding_translation(TSRMLS_C)) { ++ php_mb_gpc_stack_variable(param, value, &val_list, &len_list, ++ &num_vars, &num_vars_max TSRMLS_CC); ++ } else { ++ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); ++ } + #else +- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); ++ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); + #endif ++ } + if (!strcasecmp(param, "MAX_FILE_SIZE")) { + max_file_size = atol(value); + } +diff -Nur php-4.3.11/main/snprintf.c hardened-php-4.3.11-0.2.7/main/snprintf.c +--- php-4.3.11/main/snprintf.c 2004-11-16 00:27:26.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/main/snprintf.c 2005-04-07 02:08:26.000000000 +0200 +@@ -850,7 +850,11 @@ + + + case 'n': ++#if HARDENED_PHP_FMT_PROTECT ++ php_security_log("'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = cc; ++#endif + break; + + /* +diff -Nur php-4.3.11/main/spprintf.c hardened-php-4.3.11-0.2.7/main/spprintf.c +--- php-4.3.11/main/spprintf.c 2003-09-29 03:09:36.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/main/spprintf.c 2005-04-07 02:08:26.000000000 +0200 +@@ -531,7 +531,11 @@ + + + case 'n': ++#if HARDENED_PHP_FMT_PROTECT ++ php_security_log("'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = cc; ++#endif + break; + + /* +diff -Nur php-4.3.11/php.ini-dist hardened-php-4.3.11-0.2.7/php.ini-dist +--- php-4.3.11/php.ini-dist 2005-02-14 09:26:10.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/php.ini-dist 2005-04-07 02:08:26.000000000 +0200 +@@ -1109,6 +1109,23 @@ + ;exif.decode_jis_motorola = JIS + ;exif.decode_jis_intel = JIS + ++[varfilter] ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++; Hardened-PHP's variable filter ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++ ++; Maximum number of input variables per request ++varfilter.max_request_variables = 200 ++ ++; Maximum characters in input variable names ++varfilter.max_varname_length = 64 ++ ++; Maximum length of input variable values ++varfilter.max_value_length = 10000 ++ ++; Maximum depth of input variable arrays ++varfilter.max_array_depth = 100 ++ + ; Local Variables: + ; tab-width: 4 + ; End: +diff -Nur php-4.3.11/php.ini-recommended hardened-php-4.3.11-0.2.7/php.ini-recommended +--- php-4.3.11/php.ini-recommended 2005-02-14 09:26:10.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/php.ini-recommended 2005-04-07 02:08:26.000000000 +0200 +@@ -1107,6 +1107,23 @@ + ;exif.decode_jis_motorola = JIS + ;exif.decode_jis_intel = JIS + ++[varfilter] ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++; Hardened-PHP's variable filter ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++ ++; Maximum number of input variables per request ++varfilter.max_request_variables = 200 ++ ++; Maximum characters in input variable names ++varfilter.max_varname_length = 64 ++ ++; Maximum length of input variable values ++varfilter.max_value_length = 10000 ++ ++; Maximum depth of input variable arrays ++varfilter.max_array_depth = 100 ++ + ; Local Variables: + ; tab-width: 4 + ; End: +diff -Nur php-4.3.11/sapi/apache/mod_php4.c hardened-php-4.3.11-0.2.7/sapi/apache/mod_php4.c +--- php-4.3.11/sapi/apache/mod_php4.c 2004-07-21 18:25:28.000000000 +0200 ++++ hardened-php-4.3.11-0.2.7/sapi/apache/mod_php4.c 2005-04-07 02:08:26.000000000 +0200 +@@ -446,7 +446,7 @@ + sapi_apache_get_fd, + sapi_apache_force_http_10, + sapi_apache_get_target_uid, +- sapi_apache_get_target_gid ++ sapi_apache_get_target_gid, + }; + /* }}} */ + +@@ -892,7 +892,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component("Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component("PHP/" PHP_VERSION); ++#endif + } + } + #endif +diff -Nur php-4.3.11/sapi/apache2filter/sapi_apache2.c hardened-php-4.3.11-0.2.7/sapi/apache2filter/sapi_apache2.c +--- php-4.3.11/sapi/apache2filter/sapi_apache2.c 2005-01-07 07:28:36.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/sapi/apache2filter/sapi_apache2.c 2005-04-07 02:08:26.000000000 +0200 +@@ -563,7 +563,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nur php-4.3.11/sapi/apache2handler/sapi_apache2.c hardened-php-4.3.11-0.2.7/sapi/apache2handler/sapi_apache2.c +--- php-4.3.11/sapi/apache2handler/sapi_apache2.c 2005-03-10 12:39:04.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/sapi/apache2handler/sapi_apache2.c 2005-04-07 02:08:26.000000000 +0200 +@@ -345,7 +345,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nur php-4.3.11/sapi/cgi/cgi_main.c hardened-php-4.3.11-0.2.7/sapi/cgi/cgi_main.c +--- php-4.3.11/sapi/cgi/cgi_main.c 2005-02-11 03:12:30.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/sapi/cgi/cgi_main.c 2005-04-07 02:08:26.000000000 +0200 +@@ -1435,11 +1435,19 @@ + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + } ++#if HARDENED_PHP ++#if ZEND_DEBUG ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + php_end_ob_buffers(1 TSRMLS_CC); + exit(1); + break; +diff -Nur php-4.3.11/sapi/cli/php_cli.c hardened-php-4.3.11-0.2.7/sapi/cli/php_cli.c +--- php-4.3.11/sapi/cli/php_cli.c 2005-03-22 16:09:36.000000000 +0100 ++++ hardened-php-4.3.11-0.2.7/sapi/cli/php_cli.c 2005-04-07 02:08:26.000000000 +0200 +@@ -652,11 +652,19 @@ + if (php_request_startup(TSRMLS_C)==FAILURE) { + goto err; + } ++#if HARDENED_PHP ++#if ZEND_DEBUG ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + php_end_ob_buffers(1 TSRMLS_CC); + exit_status=1; + goto out; diff --git a/0.2.7/hardened-php-5.0.4-0.2.7.patch b/0.2.7/hardened-php-5.0.4-0.2.7.patch new file mode 100644 index 0000000..2b1372a --- /dev/null +++ b/0.2.7/hardened-php-5.0.4-0.2.7.patch @@ -0,0 +1,3100 @@ +diff -Nur php-5.0.4/TSRM/TSRM.h hardened-php-5.0.4-0.2.7/TSRM/TSRM.h +--- php-5.0.4/TSRM/TSRM.h 2005-03-11 12:12:07.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/TSRM/TSRM.h 2005-04-07 02:04:38.000000000 +0200 +@@ -33,6 +33,13 @@ + # define TSRM_API + #endif + ++#if HARDENED_PHP ++# if HAVE_REALPATH ++# undef realpath ++# define realpath php_realpath ++# endif ++#endif ++ + /* Only compile multi-threading functions if we're in ZTS mode */ + #ifdef ZTS + +@@ -88,6 +95,7 @@ + + #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts + ++ + #ifdef __cplusplus + extern "C" { + #endif +diff -Nur php-5.0.4/TSRM/tsrm_virtual_cwd.c hardened-php-5.0.4-0.2.7/TSRM/tsrm_virtual_cwd.c +--- php-5.0.4/TSRM/tsrm_virtual_cwd.c 2005-03-11 12:09:42.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/TSRM/tsrm_virtual_cwd.c 2005-04-07 02:04:38.000000000 +0200 +@@ -197,6 +197,165 @@ + return p; + } + ++#if HARDENED_PHP ++CWD_API char *php_realpath(const char *path, char *resolved) ++{ ++ struct stat sb; ++ char *p, *q, *s; ++ size_t left_len, resolved_len; ++ unsigned symlinks; ++ int serrno, slen; ++ int is_dir = 1; ++ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; ++ ++ serrno = errno; ++ symlinks = 0; ++ if (path[0] == '/') { ++ resolved[0] = '/'; ++ resolved[1] = '\0'; ++ if (path[1] == '\0') ++ return (resolved); ++ resolved_len = 1; ++ left_len = strlcpy(left, path + 1, sizeof(left)); ++ } else { ++ if (getcwd(resolved, PATH_MAX) == NULL) { ++ strlcpy(resolved, ".", PATH_MAX); ++ return (NULL); ++ } ++ resolved_len = strlen(resolved); ++ left_len = strlcpy(left, path, sizeof(left)); ++ } ++ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ ++ /* ++ * Iterate over path components in `left'. ++ */ ++ while (left_len != 0) { ++ /* ++ * Extract the next path component and adjust `left' ++ * and its length. ++ */ ++ p = strchr(left, '/'); ++ s = p ? p : left + left_len; ++ if (s - left >= sizeof(next_token)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ memcpy(next_token, left, s - left); ++ next_token[s - left] = '\0'; ++ left_len -= s - left; ++ if (p != NULL) ++ memmove(left, s + 1, left_len + 1); ++ if (resolved[resolved_len - 1] != '/') { ++ if (resolved_len + 1 >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ resolved[resolved_len++] = '/'; ++ resolved[resolved_len] = '\0'; ++ } ++ if (next_token[0] == '\0') ++ continue; ++ else if (strcmp(next_token, ".") == 0) ++ continue; ++ else if (strcmp(next_token, "..") == 0) { ++ /* ++ * Strip the last path component except when we have ++ * single "/" ++ */ ++ if (!is_dir) { ++ errno = ENOENT; ++ return (NULL); ++ } ++ if (resolved_len > 1) { ++ resolved[resolved_len - 1] = '\0'; ++ q = strrchr(resolved, '/'); ++ *q = '\0'; ++ resolved_len = q - resolved; ++ } ++ continue; ++ } ++ ++ /* ++ * Append the next path component and lstat() it. If ++ * lstat() fails we still can return successfully if ++ * there are no more path components left. ++ */ ++ resolved_len = strlcat(resolved, next_token, PATH_MAX); ++ if (resolved_len >= PATH_MAX) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ if (lstat(resolved, &sb) != 0) { ++ if (errno == ENOENT && p == NULL) { ++ errno = serrno; ++ return (resolved); ++ } ++ return (NULL); ++ } ++ if (S_ISLNK(sb.st_mode)) { ++ if (symlinks++ > MAXSYMLINKS) { ++ errno = ELOOP; ++ return (NULL); ++ } ++ slen = readlink(resolved, symlink, sizeof(symlink) - 1); ++ if (slen < 0) ++ return (NULL); ++ symlink[slen] = '\0'; ++ if (symlink[0] == '/') { ++ resolved[1] = 0; ++ resolved_len = 1; ++ } else if (resolved_len > 1) { ++ /* Strip the last path component. */ ++ resolved[resolved_len - 1] = '\0'; ++ q = strrchr(resolved, '/'); ++ *q = '\0'; ++ resolved_len = q - resolved; ++ } ++ ++ /* ++ * If there are any path components left, then ++ * append them to symlink. The result is placed ++ * in `left'. ++ */ ++ if (p != NULL) { ++ if (symlink[slen - 1] != '/') { ++ if (slen + 1 >= sizeof(symlink)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ symlink[slen] = '/'; ++ symlink[slen + 1] = 0; ++ } ++ left_len = strlcat(symlink, left, sizeof(left)); ++ if (left_len >= sizeof(left)) { ++ errno = ENAMETOOLONG; ++ return (NULL); ++ } ++ } ++ left_len = strlcpy(left, symlink, sizeof(left)); ++ } else { ++ if (S_ISDIR(sb.st_mode)) { ++ is_dir = 1; ++ } else { ++ is_dir = 0; ++ } ++ } ++ } ++ ++ /* ++ * Remove trailing slash except when the resolved pathname ++ * is a single "/". ++ */ ++ if (resolved_len > 1 && resolved[resolved_len - 1] == '/') ++ resolved[resolved_len - 1] = '\0'; ++ return (resolved); ++} ++#endif ++ + CWD_API void virtual_cwd_startup(void) + { + char cwd[MAXPATHLEN]; +@@ -321,8 +480,7 @@ + path = resolved_path; + path_length = strlen(path); + } else { +- /* disable for now +- return 1; */ ++ return 1; + } + } + } else { /* Concat current directory with relative path and then run realpath() on it */ +@@ -348,9 +506,8 @@ + path = resolved_path; + path_length = strlen(path); + } else { +- /* disable for now + free(tmp); +- return 1; */ ++ return 1; + } + } + free(tmp); +diff -Nur php-5.0.4/TSRM/tsrm_virtual_cwd.h hardened-php-5.0.4-0.2.7/TSRM/tsrm_virtual_cwd.h +--- php-5.0.4/TSRM/tsrm_virtual_cwd.h 2005-03-11 12:07:17.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/TSRM/tsrm_virtual_cwd.h 2005-04-07 02:04:38.000000000 +0200 +@@ -128,6 +128,22 @@ + + typedef int (*verify_path_func)(const cwd_state *); + ++#ifndef HAVE_STRLCPY ++CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz); ++#undef strlcpy ++#define strlcpy php_strlcpy ++#endif ++ ++#ifndef HAVE_STRLCAT ++CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz); ++#undef strlcat ++#define strlcat php_strlcat ++#endif ++ ++ ++#if HARDENED_PHP ++CWD_API char *php_realpath(const char *path, char *resolved); ++#endif + CWD_API void virtual_cwd_startup(void); + CWD_API void virtual_cwd_shutdown(void); + CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC); +diff -Nur php-5.0.4/Zend/zend.c hardened-php-5.0.4-0.2.7/Zend/zend.c +--- php-5.0.4/Zend/zend.c 2005-03-16 00:47:12.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend.c 2005-04-07 02:04:38.000000000 +0200 +@@ -54,6 +54,12 @@ + ZEND_API void (*zend_unblock_interruptions)(void); + ZEND_API void (*zend_ticks_function)(int ticks); + ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); ++#if HARDENED_PHP ++ZEND_API void (*zend_security_log)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ZEND_API int (*zend_is_valid_include)(zval *z); ++#endif + int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap); + + void (*zend_on_timeout)(int seconds TSRMLS_DC); +@@ -545,6 +551,14 @@ + extern zend_scanner_globals language_scanner_globals; + #endif + ++ /* Set up Hardened-PHP utility functions first */ ++#if HARDENED_PHP ++ zend_security_log = utility_functions->security_log_function; ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ zend_is_valid_include = utility_functions->is_valid_include; ++#endif ++ + #ifdef ZTS + ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor); + #else +diff -Nur php-5.0.4/Zend/zend.h hardened-php-5.0.4-0.2.7/Zend/zend.h +--- php-5.0.4/Zend/zend.h 2005-03-10 12:30:44.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend.h 2005-04-07 02:04:38.000000000 +0200 +@@ -359,6 +359,12 @@ + void (*on_timeout)(int seconds TSRMLS_DC); + int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC); + int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap); ++#if HARDENED_PHP ++ void (*security_log_function)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++ int (*is_valid_include)(zval *z); ++#endif + } zend_utility_functions; + + +@@ -496,6 +502,16 @@ + extern void (*zend_on_timeout)(int seconds TSRMLS_DC); + extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC); + extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap); ++#if HARDENED_PHP ++extern ZEND_API void (*zend_security_log)(char *str); ++#endif ++#if HARDENED_PHP_INC_PROTECT ++extern ZEND_API int (*zend_is_valid_include)(zval *z); ++#endif ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++ZEND_API unsigned int zend_canary(void); ++#endif + + + ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); +@@ -620,6 +636,10 @@ + #define ZEND_MAX_RESERVED_RESOURCES 4 + + ++#if HARDENED_PHP ++#include "hardened_globals.h" ++#endif ++ + #endif /* ZEND_H */ + + /* +diff -Nur php-5.0.4/Zend/zend_API.h hardened-php-5.0.4-0.2.7/Zend/zend_API.h +--- php-5.0.4/Zend/zend_API.h 2005-01-22 13:29:13.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_API.h 2005-04-07 02:04:38.000000000 +0200 +@@ -47,6 +47,7 @@ + #define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name)) + + #define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags }, ++#define ZEND_STATIC_FE(zend_name, name, arg_info) { zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), 0 }, + + #define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0) + #define ZEND_FE(name, arg_info) ZEND_FENTRY(name, ZEND_FN(name), arg_info, 0) +diff -Nur php-5.0.4/Zend/zend_alloc.c hardened-php-5.0.4-0.2.7/Zend/zend_alloc.c +--- php-5.0.4/Zend/zend_alloc.c 2004-08-27 18:49:54.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_alloc.c 2005-04-07 02:12:14.000000000 +0200 +@@ -64,6 +64,11 @@ + # define END_MAGIC_SIZE 0 + #endif + ++#if HARDENED_PHP_MM_PROTECT ++# define CANARY_SIZE sizeof(unsigned int) ++#else ++# define CANARY_SIZE 0 ++#endif + + # if MEMORY_LIMIT + # if ZEND_DEBUG +@@ -104,9 +109,17 @@ + if (p==AG(head)) { \ + AG(head) = p->pNext; \ + } else { \ ++ if (p != p->pLast->pNext) { \ ++ zend_security_log("linked list corrupt on efree() - heap corruption detected"); \ ++ exit(1); \ ++ } \ + p->pLast->pNext = p->pNext; \ + } \ + if (p->pNext) { \ ++ if (p != p->pNext->pLast) { \ ++ zend_security_log("linked list corrupt on efree() - heap corruption detected"); \ ++ exit(1); \ ++ } \ + p->pNext->pLast = p->pLast; \ + } + #else +@@ -145,6 +158,12 @@ + DECLARE_CACHE_VARS(); + TSRMLS_FETCH(); + ++#if HARDENED_PHP_MM_PROTECT ++ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) { ++ zend_security_log("emalloc() - requested size would result in integer overflow"); ++ exit(1); ++ } ++#endif + CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size); + + #if !ZEND_DISABLE_MEMORY_CACHE +@@ -163,6 +182,10 @@ + AG(cache_stats)[CACHE_INDEX][1]++; + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif ++#if HARDENED_PHP_MM_PROTECT ++ p->canary = HG(canary_1); ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + p->cached = 0; + p->size = size; + return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING); +@@ -179,7 +202,7 @@ + AG(allocated_memory_peak) = AG(allocated_memory); + } + #endif +- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE); ++ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE); + #if !ZEND_DISABLE_MEMORY_CACHE + } + #endif +@@ -211,7 +234,10 @@ + # endif + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif +- ++#if HARDENED_PHP_MM_PROTECT ++ p->canary = HG(canary_1); ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING); + } +@@ -239,6 +265,10 @@ + } + } + ++ ++#if HARDENED_PHP ++ zend_security_log("Possible integer overflow catched by safe_emalloc()"); ++#endif + zend_error(E_ERROR, "Possible integer overflow in memory allocation (%zd * %zd + %zd)", nmemb, size, offset); + return 0; + } +@@ -247,9 +277,22 @@ + + ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int *canary_2; ++#endif + zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING); + DECLARE_CACHE_VARS(); + TSRMLS_FETCH(); ++ ++#if HARDENED_PHP_MM_PROTECT ++ canary_2 = (unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE); ++ if (p->canary != HG(canary_1) || *canary_2 != HG(canary_2)) { ++ zend_security_log("canary mismatch on efree() - heap overflow or double efree detected"); ++ exit(1); ++ } ++ /* to catch double efree()s */ ++ *canary_2 = p->canary = 0; ++#endif + + #if defined(ZTS) && TSRM_DEBUG + if (p->thread_id != tsrm_thread_id()) { +@@ -291,23 +334,35 @@ + + ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { +- void *p; +- int final_size = size*nmemb; ++ char *p; ++ size_t _size = nmemb * size; ++ ++ if (nmemb && (_size/nmemb!=size)) { ++#if HARDENED_PHP ++ zend_security_log("Possible integer overflow catched by ecalloc()"); ++#endif ++ fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size); ++#if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID ++ kill(getpid(), SIGSEGV); ++#else ++ exit(1); ++#endif ++ } + +- HANDLE_BLOCK_INTERRUPTIONS(); +- p = _emalloc(final_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); +- if (!p) { +- HANDLE_UNBLOCK_INTERRUPTIONS(); +- return (void *) p; ++ p = (char *) _emalloc(_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ if (p) { ++ memset(p, 0, _size); + } +- memset(p, 0, final_size); +- HANDLE_UNBLOCK_INTERRUPTIONS(); +- return p; ++ ++ return ((void *)p); + } + + + ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary_2; ++#endif + zend_mem_header *p; + zend_mem_header *orig; + DECLARE_CACHE_VARS(); +@@ -319,6 +374,14 @@ + + p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING); + ++#if HARDENED_PHP_MM_PROTECT ++ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE); ++ if (p->canary != HG(canary_1) || canary_2 != HG(canary_2)) { ++ zend_security_log("canary mismatch on erealloc() - heap overflow detected"); ++ exit(1); ++ } ++#endif ++ + #if defined(ZTS) && TSRM_DEBUG + if (p->thread_id != tsrm_thread_id()) { + void *new_p; +@@ -342,7 +405,7 @@ + } + #endif + REMOVE_POINTER_FROM_LIST(p); +- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE); ++ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE); + if (!p) { + if (!allow_failure) { + fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size); +@@ -364,6 +427,9 @@ + memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); + #endif + ++#if HARDENED_PHP_MM_PROTECT ++ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE); ++#endif + p->size = size; + + HANDLE_UNBLOCK_INTERRUPTIONS(); +@@ -439,6 +505,10 @@ + { + AG(head) = NULL; + ++#if HARDENED_PHP_MM_PROTECT ++ HG(canary_1) = zend_canary(); ++ HG(canary_2) = zend_canary(); ++#endif + #if MEMORY_LIMIT + AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */ + AG(allocated_memory) = 0; +diff -Nur php-5.0.4/Zend/zend_alloc.h hardened-php-5.0.4-0.2.7/Zend/zend_alloc.h +--- php-5.0.4/Zend/zend_alloc.h 2004-08-11 08:13:12.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_alloc.h 2005-04-07 02:04:38.000000000 +0200 +@@ -35,6 +35,9 @@ + #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL + + typedef struct _zend_mem_header { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary; ++#endif + #if ZEND_DEBUG + long magic; + char *filename; +diff -Nur php-5.0.4/Zend/zend_builtin_functions.c hardened-php-5.0.4-0.2.7/Zend/zend_builtin_functions.c +--- php-5.0.4/Zend/zend_builtin_functions.c 2005-03-14 10:13:14.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_builtin_functions.c 2005-04-07 02:04:38.000000000 +0200 +@@ -52,6 +52,9 @@ + static ZEND_FUNCTION(crash); + #endif + #endif ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++static ZEND_FUNCTION(heap_overflow); ++#endif + static ZEND_FUNCTION(get_included_files); + static ZEND_FUNCTION(is_subclass_of); + static ZEND_FUNCTION(is_a); +@@ -111,6 +114,9 @@ + ZEND_FE(crash, NULL) + #endif + #endif ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++ ZEND_FE(heap_overflow, NULL) ++#endif + ZEND_FE(get_included_files, NULL) + ZEND_FALIAS(get_required_files, get_included_files, NULL) + ZEND_FE(is_subclass_of, NULL) +@@ -999,6 +1005,19 @@ + + #endif /* ZEND_DEBUG */ + ++ ++#if HARDENED_PHP_MM_PROTECT_DEBUG ++ZEND_FUNCTION(heap_overflow) ++{ ++ char *nowhere = emalloc(10); ++ ++ memcpy(nowhere, "something1234567890", sizeof("something1234567890")); ++ ++ efree(nowhere); ++} ++#endif ++ ++ + /* {{{ proto array get_included_files(void) + Returns an array with the file names that were include_once()'d */ + ZEND_FUNCTION(get_included_files) +diff -Nur php-5.0.4/Zend/zend_canary.c hardened-php-5.0.4-0.2.7/Zend/zend_canary.c +--- php-5.0.4/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_canary.c 2005-04-07 02:04:38.000000000 +0200 +@@ -0,0 +1,58 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */ ++ ++#include "zend.h" ++ ++#include ++#include ++ ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++ ++/* will be replaced later with more compatible method */ ++ZEND_API unsigned int zend_canary() ++{ ++ time_t t; ++ unsigned int canary; ++ int fd; ++ ++ fd = open("/dev/urandom", 0); ++ if (fd != -1) { ++ int r = read(fd, &canary, sizeof(canary)); ++ close(fd); ++ if (r == sizeof(canary)) { ++ return (canary); ++ } ++ } ++ /* not good but we never want to do this */ ++ time(&t); ++ canary = *(unsigned int *)&t + getpid() << 16; ++ return (canary); ++} ++#endif ++ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nur php-5.0.4/Zend/zend_execute.c hardened-php-5.0.4-0.2.7/Zend/zend_execute.c +--- php-5.0.4/Zend/zend_execute.c 2005-03-21 17:22:10.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_execute.c 2005-04-07 02:04:38.000000000 +0200 +@@ -3523,7 +3523,12 @@ + int dummy = 1; + zend_file_handle file_handle; + ++#if HARDENED_PHP_INC_PROTECT ++ if (zend_is_valid_include(inc_filename) ++ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) { ++#else + if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) { ++#endif + + if (!file_handle.opened_path) { + file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len); +@@ -3548,6 +3553,11 @@ + break; + case ZEND_INCLUDE: + case ZEND_REQUIRE: ++#if HARDENED_PHP_INC_PROTECT ++ if (!zend_is_valid_include(inc_filename)) { ++ break; ++ } ++#endif + new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC); + break; + case ZEND_EVAL: { +diff -Nur php-5.0.4/Zend/zend_extensions.h hardened-php-5.0.4-0.2.7/Zend/zend_extensions.h +--- php-5.0.4/Zend/zend_extensions.h 2004-11-25 21:26:48.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_extensions.h 2005-04-07 02:04:38.000000000 +0200 +@@ -24,10 +24,11 @@ + + #include "zend_compile.h" + +-/* The first number is the engine version and the rest is the date. ++/* The first number is a flag saying that Hardened-PHP is used ++ * the second number is the engine version and the rest is the date. + * This way engine 2 API no. is always greater than engine 1 API no.. + */ +-#define ZEND_EXTENSION_API_NO 220040412 ++#define ZEND_EXTENSION_API_NO 1220040412 + + typedef struct _zend_extension_version_info { + int zend_extension_api_no; +diff -Nur php-5.0.4/Zend/zend_hash.c hardened-php-5.0.4-0.2.7/Zend/zend_hash.c +--- php-5.0.4/Zend/zend_hash.c 2004-07-10 09:45:49.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_hash.c 2005-04-07 02:06:13.000000000 +0200 +@@ -21,6 +21,18 @@ + + #include "zend.h" + ++#if HARDENED_PHP_HASH_PROTECT ++ unsigned int zend_hash_canary = 0x1234567; ++ zend_bool zend_hash_canary_inited = 0; ++#endif ++ ++#define CHECK_HASH_CANARY(hash) \ ++ if (zend_hash_canary != (hash)->canary) { \ ++ zend_security_log("Zend HashTable canary was overwritten"); \ ++ exit(1); \ ++ } ++ ++ + #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \ + (element)->pNext = (list_head); \ + (element)->pLast = NULL; \ +@@ -138,6 +150,9 @@ + { + uint i = 3; + Bucket **tmp; ++#if HARDENED_PHP_HASH_PROTECT ++ TSRMLS_FETCH(); ++#endif + + SET_INCONSISTENT(HT_OK); + +@@ -147,6 +162,13 @@ + + ht->nTableSize = 1 << i; + ht->nTableMask = ht->nTableSize - 1; ++#if HARDENED_PHP_HASH_PROTECT ++ if (zend_hash_canary_inited==0) { ++ zend_hash_canary = zend_canary(); ++ zend_hash_canary_inited = 1; ++ } ++ ht->canary = zend_hash_canary; ++#endif + ht->pDestructor = pDestructor; + ht->arBuckets = NULL; + ht->pListHead = NULL; +@@ -226,6 +248,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -291,6 +316,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -366,6 +394,9 @@ + } + #endif + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + UPDATE_DATA(ht, p, pData, nDataSize); +@@ -414,7 +445,7 @@ + IS_CONSISTENT(ht); + + if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */ +- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent); ++ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent); + if (t) { + HANDLE_BLOCK_INTERRUPTIONS(); + ht->arBuckets = t; +@@ -424,6 +455,7 @@ + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } ++ zend_error(E_ERROR, "zend_hash_do_resize - out of memory"); + return FAILURE; + } + return SUCCESS; +@@ -487,6 +519,9 @@ + ht->pInternalPointer = p->pListNext; + } + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { +@@ -516,6 +551,9 @@ + q = p; + p = p->pListNext; + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { +@@ -542,6 +580,9 @@ + q = p; + p = p->pListNext; + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { +@@ -571,6 +612,9 @@ + HANDLE_BLOCK_INTERRUPTIONS(); + + if (ht->pDestructor) { ++#if HARDENED_PHP_HASH_PROTECT ++ CHECK_HASH_CANARY(ht); ++#endif + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { +diff -Nur php-5.0.4/Zend/zend_hash.h hardened-php-5.0.4-0.2.7/Zend/zend_hash.h +--- php-5.0.4/Zend/zend_hash.h 2004-01-08 18:31:47.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_hash.h 2005-04-07 02:04:38.000000000 +0200 +@@ -58,6 +58,9 @@ + } Bucket; + + typedef struct _hashtable { ++#if HARDENED_PHP_HASH_PROTECT ++ unsigned int canary; ++#endif + uint nTableSize; + uint nTableMask; + uint nNumOfElements; +diff -Nur php-5.0.4/Zend/zend_llist.c hardened-php-5.0.4-0.2.7/Zend/zend_llist.c +--- php-5.0.4/Zend/zend_llist.c 2004-01-08 18:31:47.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_llist.c 2005-04-07 02:04:38.000000000 +0200 +@@ -22,9 +22,34 @@ + #include "zend.h" + #include "zend_llist.h" + #include "zend_qsort.h" ++#include "zend_globals.h" ++ ++#define CHECK_LIST_CANARY(list) \ ++ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \ ++ zend_security_log("linked list canary was overwritten"); \ ++ exit(1); \ ++ } ++ ++#define CHECK_LISTELEMENT_CANARY(elem) \ ++ if (HG(canary_3) != (elem)->canary) { \ ++ zend_security_log("linked list element canary was overwritten"); \ ++ exit(1); \ ++ } ++ + + ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent) + { ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ ++ if (!HG(ll_canary_inited)) { ++ HG(canary_3) = zend_canary(); ++ HG(canary_4) = zend_canary(); ++ HG(ll_canary_inited) = 1; ++ } ++ l->canary_h = HG(canary_3); ++ l->canary_t = HG(canary_4); ++#endif + l->head = NULL; + l->tail = NULL; + l->count = 0; +@@ -38,6 +63,11 @@ + { + zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent); + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++ tmp->canary = HG(canary_3); ++#endif + tmp->prev = l->tail; + tmp->next = NULL; + if (l->tail) { +@@ -56,6 +86,11 @@ + { + zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent); + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++ tmp->canary = HG(canary_3); ++#endif + tmp->next = l->head; + tmp->prev = NULL; + if (l->head) { +@@ -93,10 +128,20 @@ + zend_llist_element *current=l->head; + zend_llist_element *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + while (current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(current) ++#endif + next = current->next; + if (compare(current->data, element)) { + DEL_LLIST_ELEMENT(current, l); ++#if HARDENED_PHP_LL_PROTECT ++ current->canary = 0; ++#endif + break; + } + current = next; +@@ -108,7 +153,14 @@ + { + zend_llist_element *current=l->head, *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + while (current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(current) ++#endif + next = current->next; + if (l->dtor) { + l->dtor(current->data); +@@ -133,7 +185,14 @@ + zend_llist_element *old_tail; + void *data; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if ((old_tail = l->tail)) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(old_tail) ++#endif + if (l->tail->prev) { + l->tail->prev->next = NULL; + } +@@ -159,9 +218,16 @@ + { + zend_llist_element *ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(src) ++#endif + zend_llist_init(dst, src->size, src->dtor, src->persistent); + ptr = src->head; + while (ptr) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(ptr) ++#endif + zend_llist_add_element(dst, ptr->data); + ptr = ptr->next; + } +@@ -172,11 +238,21 @@ + { + zend_llist_element *element, *next; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + element=l->head; + while (element) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + next = element->next; + if (func(element->data)) { + DEL_LLIST_ELEMENT(element, l); ++#if HARDENED_PHP_LL_PROTECT ++ element->canary = 0; ++#endif + } + element = next; + } +@@ -187,7 +263,13 @@ + { + zend_llist_element *element; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data TSRMLS_CC); + } + } +@@ -199,6 +281,9 @@ + zend_llist_element **elements; + zend_llist_element *element, **ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + if (l->count <= 0) { + return; + } +@@ -208,6 +293,9 @@ + ptr = &elements[0]; + + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + *ptr++ = element; + } + +@@ -230,7 +318,13 @@ + { + zend_llist_element *element; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data, arg TSRMLS_CC); + } + } +@@ -241,8 +335,14 @@ + zend_llist_element *element; + va_list args; + ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LIST_CANARY(l) ++#endif + va_start(args, num_args); + for (element=l->head; element; element=element->next) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(element) ++#endif + func(element->data, num_args, args TSRMLS_CC); + } + va_end(args); +@@ -251,6 +351,10 @@ + + ZEND_API int zend_llist_count(zend_llist *l) + { ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + return l->count; + } + +@@ -259,8 +363,15 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + *current = l->head; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } else { + return NULL; +@@ -272,8 +383,15 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + *current = l->tail; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } else { + return NULL; +@@ -285,9 +403,19 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + *current = (*current)->next; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } + } +@@ -299,9 +427,19 @@ + { + zend_llist_position *current = pos ? pos : &l->traverse_ptr; + ++#if HARDENED_PHP_LL_PROTECT ++ TSRMLS_FETCH(); ++ CHECK_LIST_CANARY(l) ++#endif + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + *current = (*current)->prev; + if (*current) { ++#if HARDENED_PHP_LL_PROTECT ++ CHECK_LISTELEMENT_CANARY(*current) ++#endif + return (*current)->data; + } + } +diff -Nur php-5.0.4/Zend/zend_llist.h hardened-php-5.0.4-0.2.7/Zend/zend_llist.h +--- php-5.0.4/Zend/zend_llist.h 2004-01-08 18:31:47.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_llist.h 2005-04-07 02:04:38.000000000 +0200 +@@ -23,6 +23,9 @@ + #define ZEND_LLIST_H + + typedef struct _zend_llist_element { ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary; ++#endif + struct _zend_llist_element *next; + struct _zend_llist_element *prev; + char data[1]; /* Needs to always be last in the struct */ +@@ -35,6 +38,9 @@ + typedef void (*llist_apply_func_t)(void * TSRMLS_DC); + + typedef struct _zend_llist { ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_h; /* head */ ++#endif + zend_llist_element *head; + zend_llist_element *tail; + size_t count; +@@ -42,6 +48,9 @@ + llist_dtor_func_t dtor; + unsigned char persistent; + zend_llist_element *traverse_ptr; ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_t; /* tail */ ++#endif + } zend_llist; + + typedef zend_llist_element* zend_llist_position; +diff -Nur php-5.0.4/Zend/zend_modules.h hardened-php-5.0.4-0.2.7/Zend/zend_modules.h +--- php-5.0.4/Zend/zend_modules.h 2005-03-16 00:47:12.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/Zend/zend_modules.h 2005-04-07 02:04:38.000000000 +0200 +@@ -38,7 +38,7 @@ + extern struct _zend_arg_info fourth_arg_force_ref[5]; + extern struct _zend_arg_info all_args_by_ref[1]; + +-#define ZEND_MODULE_API_NO 20041030 ++#define ZEND_MODULE_API_NO 1020041030 + #ifdef ZTS + #define USING_ZTS 1 + #else +diff -Nur php-5.0.4/acinclude.m4 hardened-php-5.0.4-0.2.7/acinclude.m4 +--- php-5.0.4/acinclude.m4 2005-01-25 14:02:45.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/acinclude.m4 2005-04-07 02:04:39.000000000 +0200 +@@ -1169,6 +1169,36 @@ + fi + ]) + ++dnl ++dnl Check for broken realpath() ++dnl ++dnl realpath("/etc/hosts/../passwd",XXX) should not return ++dnl "/etc/passwd" ++dnl ++AC_DEFUN([PHP_AC_BROKEN_REALPATH],[ ++ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[ ++ AC_TRY_RUN([ ++main() { ++ char buf[4096+1]; ++ buf[0] = 0; ++ realpath("/etc/hosts/../passwd", buf); ++ exit(strcmp(buf, "/etc/passwd")==0); ++} ++ ],[ ++ ac_cv_broken_realpath=no ++ ],[ ++ ac_cv_broken_realpath=yes ++ ],[ ++ ac_cv_broken_realpath=no ++ ]) ++ ]) ++ if test "$ac_cv_broken_realpath" = "yes"; then ++ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken]) ++ else ++ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken]) ++ fi ++]) ++ + dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx) + dnl + dnl Basically sets up the link-stage for building module-name +diff -Nur php-5.0.4/configure hardened-php-5.0.4-0.2.7/configure +--- php-5.0.4/configure 2005-04-03 11:42:50.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/configure 2005-04-07 02:04:39.000000000 +0200 +@@ -401,6 +401,16 @@ + ac_default_prefix=/usr/local + # Any additions from configure.in: + ac_help="$ac_help ++ --disable-hardened-php-mm-protect Disable the Memory Manager protection." ++ac_help="$ac_help ++ --disable-hardened-php-ll-protect Disable the Linked List protection." ++ac_help="$ac_help ++ --disable-hardened-php-inc-protect Disable include/require protection." ++ac_help="$ac_help ++ --disable-hardened-php-fmt-protect Disable format string protection." ++ac_help="$ac_help ++ --disable-hardened-php-hash-protect Disable Zend HashTable DTOR protection." ++ac_help="$ac_help + + SAPI modules: + " +@@ -857,6 +867,8 @@ + ac_help="$ac_help + --disable-tokenizer Disable tokenizer support" + ac_help="$ac_help ++ --disable-varfilter Disable Hardened-PHP's variable filter" ++ac_help="$ac_help + --enable-wddx Enable WDDX support." + ac_help="$ac_help + --disable-xml Disable XML support." +@@ -2749,6 +2761,157 @@ + + + ++# Check whether --enable-hardened-php-mm-protect or --disable-hardened-php-mm-protect was given. ++if test "${enable_hardened_php_mm_protect+set}" = set; then ++ enableval="$enable_hardened_php_mm_protect" ++ ++ DO_HARDENED_PHP_MM_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_MM_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-ll-protect or --disable-hardened-php-ll-protect was given. ++if test "${enable_hardened_php_ll_protect+set}" = set; then ++ enableval="$enable_hardened_php_ll_protect" ++ ++ DO_HARDENED_PHP_LL_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_LL_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-inc-protect or --disable-hardened-php-inc-protect was given. ++if test "${enable_hardened_php_inc_protect+set}" = set; then ++ enableval="$enable_hardened_php_inc_protect" ++ ++ DO_HARDENED_PHP_INC_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_INC_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-fmt-protect or --disable-hardened-php-fmt-protect was given. ++if test "${enable_hardened_php_fmt_protect+set}" = set; then ++ enableval="$enable_hardened_php_fmt_protect" ++ ++ DO_HARDENED_PHP_FMT_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_FMT_PROTECT=yes ++ ++fi ++ ++ ++# Check whether --enable-hardened-php-hash-protect or --disable-hardened-php-hash-protect was given. ++if test "${enable_hardened_php_hash_protect+set}" = set; then ++ enableval="$enable_hardened_php_hash_protect" ++ ++ DO_HARDENED_PHP_HASH_PROTECT=$enableval ++ ++else ++ ++ DO_HARDENED_PHP_HASH_PROTECT=yes ++ ++fi ++ ++ ++echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6 ++echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_MM_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6 ++echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_LL_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6 ++echo "configure:2733: checking whether to protect include/require statements" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_INC_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6 ++echo "configure:2737: checking whether to protect PHP Format String functions" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_FMT_PROTECT" 1>&6 ++ ++echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6 ++echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5 ++echo "$ac_t""$DO_HARDENED_PHP_HASH_PROTECT" 1>&6 ++ ++ ++cat >> confdefs.h <<\EOF ++#define HARDENED_PHP 1 ++EOF ++ ++ ++ ++if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_MM_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_MM_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_LL_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_LL_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_INC_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_INC_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_FMT_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_FMT_PROTECT 0 ++EOF ++ ++fi ++ ++if test "$DO_HARDENED_PHP_HASH_PROTECT" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_HASH_PROTECT 1 ++EOF ++ ++else ++ cat >> confdefs.h <<\EOF ++#define HARDENED_PHP_HASH_PROTECT 0 ++EOF ++ ++fi + + + +@@ -17390,6 +17553,62 @@ + fi + + ++ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6 ++echo "configure:14928: checking whether realpath is broken" >&5 ++if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ ++ if test "$cross_compiling" = yes; then ++ ++ ac_cv_broken_realpath=no ++ ++else ++ cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null ++then ++ ++ ac_cv_broken_realpath=no ++ ++else ++ echo "configure: failed program was:" >&5 ++ cat conftest.$ac_ext >&5 ++ rm -fr conftest* ++ ++ ac_cv_broken_realpath=yes ++ ++fi ++rm -fr conftest* ++fi ++ ++ ++fi ++ ++echo "$ac_t""$ac_cv_broken_realpath" 1>&6 ++ if test "$ac_cv_broken_realpath" = "yes"; then ++ cat >> confdefs.h <<\EOF ++#define PHP_BROKEN_REALPATH 1 ++EOF ++ ++ else ++ cat >> confdefs.h <<\EOF ++#define PHP_BROKEN_REALPATH 0 ++EOF ++ ++ fi ++ ++ + echo $ac_n "checking for declared timezone""... $ac_c" 1>&6 + echo "configure:17395: checking for declared timezone" >&5 + if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then +@@ -86878,6 +87097,265 @@ + fi + + ++echo $ac_n "checking whether to enable Hardened-PHP's variable filter""... $ac_c" 1>&6 ++echo "configure:82041: checking whether to enable Hardened-PHP's variable filter" >&5 ++# Check whether --enable-varfilter or --disable-varfilter was given. ++if test "${enable_varfilter+set}" = set; then ++ enableval="$enable_varfilter" ++ PHP_VARFILTER=$enableval ++else ++ ++ PHP_VARFILTER=yes ++ ++ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then ++ PHP_VARFILTER=$PHP_ENABLE_ALL ++ fi ++ ++fi ++ ++ ++ ++ext_output="yes, shared" ++ext_shared=yes ++case $PHP_VARFILTER in ++shared,*) ++ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'` ++ ;; ++shared) ++ PHP_VARFILTER=yes ++ ;; ++no) ++ ext_output=no ++ ext_shared=no ++ ;; ++*) ++ ext_output=yes ++ ext_shared=no ++ ;; ++esac ++ ++ ++ ++echo "$ac_t""$ext_output" 1>&6 ++ ++ ++ ++ ++if test "$PHP_VARFILTER" != "no"; then ++ cat >> confdefs.h <<\EOF ++#define HAVE_VARFILTER 1 ++EOF ++ ++ ++ ext_builddir=ext/varfilter ++ ext_srcdir=$abs_srcdir/ext/varfilter ++ ++ ac_extra= ++ ++ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then ++ ++ ++ ++ case ext/varfilter in ++ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;; ++ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;; ++ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;; ++ esac ++ ++ ++ ++ b_c_pre=$php_c_pre ++ b_cxx_pre=$php_cxx_pre ++ b_c_meta=$php_c_meta ++ b_cxx_meta=$php_cxx_meta ++ b_c_post=$php_c_post ++ b_cxx_post=$php_cxx_post ++ b_lo=$php_lo ++ ++ ++ old_IFS=$IFS ++ for ac_src in varfilter.c; do ++ ++ IFS=. ++ set $ac_src ++ ac_obj=$1 ++ IFS=$old_IFS ++ ++ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo" ++ ++ case $ac_src in ++ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; ++ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;; ++ esac ++ ++ cat >>Makefile.objects<>Makefile.objects<>Makefile.objects<> confdefs.h <>Makefile.objects<>Makefile.objects<&6 +@@ -97351,7 +97829,7 @@ + php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ + strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \ + network.c php_open_temporary_file.c php_logos.c \ +- output.c ; do ++ output.c hardened_php.c ; do + + IFS=. + set $ac_src +@@ -97579,7 +98057,7 @@ + zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ + zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ + zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \ +- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c; do ++ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c; do + + IFS=. + set $ac_src +diff -Nur php-5.0.4/configure.in hardened-php-5.0.4-0.2.7/configure.in +--- php-5.0.4/configure.in 2005-03-30 23:43:12.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/configure.in 2005-04-07 02:04:39.000000000 +0200 +@@ -235,7 +235,7 @@ + sinclude(Zend/acinclude.m4) + sinclude(Zend/Zend.m4) + sinclude(TSRM/tsrm.m4) +- ++sinclude(main/hardened_php.m4) + + + divert(2) +@@ -620,6 +620,7 @@ + AC_FUNC_ALLOCA + dnl PHP_AC_BROKEN_SPRINTF + dnl PHP_AC_BROKEN_SNPRINTF ++PHP_AC_BROKEN_REALPATH + PHP_DECLARED_TIMEZONE + PHP_TIME_R_TYPE + PHP_READDIR_R_TYPE +@@ -1262,7 +1263,7 @@ + php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ + strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \ + network.c php_open_temporary_file.c php_logos.c \ +- output.c ) ++ output.c hardened_php.c ) + + PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \ + plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c) +@@ -1280,7 +1281,7 @@ + zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ + zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ + zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \ +- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c) ++ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c ) + + if test -r "$abs_srcdir/Zend/zend_objects.c"; then + PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c \ +diff -Nur php-5.0.4/ext/standard/array.c hardened-php-5.0.4-0.2.7/ext/standard/array.c +--- php-5.0.4/ext/standard/array.c 2005-03-12 11:12:49.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/ext/standard/array.c 2005-04-07 02:04:39.000000000 +0200 +@@ -1255,6 +1255,31 @@ + } + } + } ++ ++ if (var_name[0] == 'H') { ++ if ((strcmp(var_name, "HTTP_GET_VARS")==0)|| ++ (strcmp(var_name, "HTTP_POST_VARS")==0)|| ++ (strcmp(var_name, "HTTP_POST_FILES")==0)|| ++ (strcmp(var_name, "HTTP_ENV_VARS")==0)|| ++ (strcmp(var_name, "HTTP_SERVER_VARS")==0)|| ++ (strcmp(var_name, "HTTP_SESSION_VARS")==0)|| ++ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)) { ++ return 0; ++ } ++ } else if (var_name[0] == '_') { ++ if ((strcmp(var_name, "_COOKIE")==0)|| ++ (strcmp(var_name, "_ENV")==0)|| ++ (strcmp(var_name, "_FILES")==0)|| ++ (strcmp(var_name, "_GET")==0)|| ++ (strcmp(var_name, "_POST")==0)|| ++ (strcmp(var_name, "_REQUEST")==0)|| ++ (strcmp(var_name, "_SESSION")==0)|| ++ (strcmp(var_name, "_SERVER")==0)) { ++ return 0; ++ } ++ } else if (strcmp(var_name, "GLOBALS")==0) { ++ return 0; ++ } + + return 1; + } +diff -Nur php-5.0.4/ext/standard/basic_functions.c hardened-php-5.0.4-0.2.7/ext/standard/basic_functions.c +--- php-5.0.4/ext/standard/basic_functions.c 2005-03-10 13:10:57.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/ext/standard/basic_functions.c 2005-04-07 02:04:39.000000000 +0200 +@@ -617,7 +617,7 @@ + PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL) + + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) +- PHP_FE(realpath, NULL) ++ PHP_STATIC_FE("realpath", zif_real_path, NULL) + #endif + + #ifdef HAVE_FNMATCH +@@ -3124,6 +3124,34 @@ + memcpy(new_key, prefix, prefix_len); + memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength); + ++ if (new_key[0] == 'H') { ++ if ((strcmp(new_key, "HTTP_GET_VARS")==0)|| ++ (strcmp(new_key, "HTTP_POST_VARS")==0)|| ++ (strcmp(new_key, "HTTP_POST_FILES")==0)|| ++ (strcmp(new_key, "HTTP_ENV_VARS")==0)|| ++ (strcmp(new_key, "HTTP_SERVER_VARS")==0)|| ++ (strcmp(new_key, "HTTP_SESSION_VARS")==0)|| ++ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)) { ++ efree(new_key); ++ return 0; ++ } ++ } else if (new_key[0] == '_') { ++ if ((strcmp(new_key, "_COOKIE")==0)|| ++ (strcmp(new_key, "_ENV")==0)|| ++ (strcmp(new_key, "_FILES")==0)|| ++ (strcmp(new_key, "_GET")==0)|| ++ (strcmp(new_key, "_POST")==0)|| ++ (strcmp(new_key, "_REQUEST")==0)|| ++ (strcmp(new_key, "_SESSION")==0)|| ++ (strcmp(new_key, "_SERVER")==0)) { ++ efree(new_key); ++ return 0; ++ } ++ } else if (strcmp(new_key, "GLOBALS")==0) { ++ efree(new_key); ++ return 0; ++ } ++ + zend_hash_del(&EG(symbol_table), new_key, new_key_len); + ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0); + +diff -Nur php-5.0.4/ext/standard/file.c hardened-php-5.0.4-0.2.7/ext/standard/file.c +--- php-5.0.4/ext/standard/file.c 2005-03-27 17:53:30.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/ext/standard/file.c 2005-04-07 02:04:39.000000000 +0200 +@@ -2044,7 +2044,7 @@ + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) + /* {{{ proto string realpath(string path) + Return the resolved path */ +-PHP_FUNCTION(realpath) ++PHP_FUNCTION(real_path) + { + zval **path; + char resolved_path_buff[MAXPATHLEN]; +diff -Nur php-5.0.4/ext/standard/file.h hardened-php-5.0.4-0.2.7/ext/standard/file.h +--- php-5.0.4/ext/standard/file.h 2004-06-21 23:08:05.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/ext/standard/file.h 2005-04-07 02:04:39.000000000 +0200 +@@ -60,7 +60,7 @@ + PHP_FUNCTION(fd_set); + PHP_FUNCTION(fd_isset); + #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS) +-PHP_FUNCTION(realpath); ++PHP_FUNCTION(real_path); + PHP_FUNCTION(fnmatch); + #endif + PHP_NAMED_FUNCTION(php_if_ftruncate); +diff -Nur php-5.0.4/ext/standard/info.c hardened-php-5.0.4-0.2.7/ext/standard/info.c +--- php-5.0.4/ext/standard/info.c 2004-05-02 15:23:30.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/ext/standard/info.c 2005-04-07 02:04:39.000000000 +0200 +@@ -394,7 +394,7 @@ + + if (flag & PHP_INFO_GENERAL) { + char *zend_version = get_zend_version(); +- char temp_api[10]; ++ char temp_api[11]; + char *logo_guid; + + php_uname = php_get_uname('a'); +@@ -415,11 +415,22 @@ + PUTS("\" alt=\"PHP Logo\" />"); + } + ++#if HARDENED_PHP ++ if (!sapi_module.phpinfo_as_text) { ++ php_printf("

Hardened-PHP Version %s/%s

\n", PHP_VERSION, HARDENED_PHP_VERSION); ++ } else { ++ char temp_ver[40]; ++ ++ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENED_PHP_VERSION); ++ php_info_print_table_row(2, "Hardened-PHP Version", temp_ver); ++ } ++#else + if (!sapi_module.phpinfo_as_text) { + php_printf("

PHP Version %s

\n", PHP_VERSION); + } else { + php_info_print_table_row(2, "PHP Version", PHP_VERSION); +- } ++ } ++#endif + php_info_print_box_end(); + php_info_print_table_start(); + php_info_print_table_row(2, "System", php_uname ); +diff -Nur php-5.0.4/ext/varfilter/CREDITS hardened-php-5.0.4-0.2.7/ext/varfilter/CREDITS +--- php-5.0.4/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/ext/varfilter/CREDITS 2005-04-07 02:04:39.000000000 +0200 +@@ -0,0 +1,2 @@ ++varfilter ++Stefan Esser +\ No newline at end of file +diff -Nur php-5.0.4/ext/varfilter/config.m4 hardened-php-5.0.4-0.2.7/ext/varfilter/config.m4 +--- php-5.0.4/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/ext/varfilter/config.m4 2005-04-07 02:04:39.000000000 +0200 +@@ -0,0 +1,11 @@ ++dnl ++dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++dnl ++ ++PHP_ARG_ENABLE(varfilter, whether to enable Hardened-PHP's variable filter, ++[ --disable-varfilter Disable Hardened-PHP's variable filter], yes) ++ ++if test "$PHP_VARFILTER" != "no"; then ++ AC_DEFINE(HAVE_VARFILTER, 1, [ ]) ++ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared) ++fi +diff -Nur php-5.0.4/ext/varfilter/php_varfilter.h hardened-php-5.0.4-0.2.7/ext/varfilter/php_varfilter.h +--- php-5.0.4/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/ext/varfilter/php_varfilter.h 2005-04-07 02:04:39.000000000 +0200 +@@ -0,0 +1,72 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 4 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2003 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++*/ ++ ++#ifndef PHP_VARFILTER_H ++#define PHP_VARFILTER_H ++ ++extern zend_module_entry varfilter_module_entry; ++#define phpext_varfilter_ptr &varfilter_module_entry ++ ++#ifdef PHP_WIN32 ++#define PHP_VARFILTER_API __declspec(dllexport) ++#else ++#define PHP_VARFILTER_API ++#endif ++ ++#ifdef ZTS ++#include "TSRM.h" ++#endif ++ ++#include "SAPI.h" ++ ++PHP_MINIT_FUNCTION(varfilter); ++PHP_MSHUTDOWN_FUNCTION(varfilter); ++PHP_RINIT_FUNCTION(varfilter); ++PHP_RSHUTDOWN_FUNCTION(varfilter); ++PHP_MINFO_FUNCTION(varfilter); ++ ++ ++ZEND_BEGIN_MODULE_GLOBALS(varfilter) ++ long max_request_variables; ++ long cur_request_variables; ++ long max_varname_length; ++ long max_value_length; ++ long max_array_depth; ++ZEND_END_MODULE_GLOBALS(varfilter) ++ ++ ++#ifdef ZTS ++#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v) ++#else ++#define VARFILTER_G(v) (varfilter_globals.v) ++#endif ++ ++SAPI_INPUT_FILTER_FUNC(varfilter_input_filter); ++ ++#endif /* PHP_VARFILTER_H */ ++ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * indent-tabs-mode: t ++ * End: ++ */ +diff -Nur php-5.0.4/ext/varfilter/varfilter.c hardened-php-5.0.4-0.2.7/ext/varfilter/varfilter.c +--- php-5.0.4/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/ext/varfilter/varfilter.c 2005-04-07 02:04:39.000000000 +0200 +@@ -0,0 +1,196 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 4 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2003 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: | ++ +----------------------------------------------------------------------+ ++ ++ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $ ++*/ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "php.h" ++#include "php_ini.h" ++#include "ext/standard/info.h" ++#include "php_varfilter.h" ++#include "hardened_php.h" ++ ++ZEND_DECLARE_MODULE_GLOBALS(varfilter) ++ ++/* True global resources - no need for thread safety here */ ++static int le_varfilter; ++ ++/* {{{ varfilter_module_entry ++ */ ++zend_module_entry varfilter_module_entry = { ++#if ZEND_MODULE_API_NO >= 20010901 ++ STANDARD_MODULE_HEADER, ++#endif ++ "varfilter", ++ NULL, ++ PHP_MINIT(varfilter), ++ PHP_MSHUTDOWN(varfilter), ++ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */ ++ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */ ++ PHP_MINFO(varfilter), ++#if ZEND_MODULE_API_NO >= 20010901 ++ "0.2.0", /* Replace with version number for your extension */ ++#endif ++ STANDARD_MODULE_PROPERTIES ++}; ++/* }}} */ ++ ++#ifdef COMPILE_DL_VARFILTER ++ZEND_GET_MODULE(varfilter) ++#endif ++ ++/* {{{ PHP_INI ++ */ ++PHP_INI_BEGIN() ++ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_SYSTEM, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_SYSTEM, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_value_length", "10000", PHP_INI_SYSTEM, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals) ++ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_SYSTEM, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals) ++PHP_INI_END() ++/* }}} */ ++ ++/* {{{ php_varfilter_init_globals ++ */ ++static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals) ++{ ++ varfilter_globals->max_request_variables = 200; ++ varfilter_globals->cur_request_variables = 0; ++ varfilter_globals->max_varname_length = 64; ++ varfilter_globals->max_value_length = 10000; ++ varfilter_globals->max_array_depth = 100; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINIT_FUNCTION ++ */ ++PHP_MINIT_FUNCTION(varfilter) ++{ ++ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL); ++ REGISTER_INI_ENTRIES(); ++ ++ sapi_register_input_filter(varfilter_input_filter); ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MSHUTDOWN_FUNCTION ++ */ ++PHP_MSHUTDOWN_FUNCTION(varfilter) ++{ ++ UNREGISTER_INI_ENTRIES(); ++ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* Remove if there's nothing to do at request start */ ++/* {{{ PHP_RINIT_FUNCTION ++ */ ++PHP_RINIT_FUNCTION(varfilter) ++{ ++ VARFILTER_G(cur_request_variables) = 0; ++ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* Remove if there's nothing to do at request end */ ++/* {{{ PHP_RSHUTDOWN_FUNCTION ++ */ ++PHP_RSHUTDOWN_FUNCTION(varfilter) ++{ ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINFO_FUNCTION ++ */ ++PHP_MINFO_FUNCTION(varfilter) ++{ ++ php_info_print_table_start(); ++ php_info_print_table_header(2, "Hardened-PHP's variable filter support", "enabled"); ++ php_info_print_table_end(); ++ ++ DISPLAY_INI_ENTRIES(); ++} ++/* }}} */ ++ ++/* {{{ SAPI_INPUT_FILTER_FUNC ++ */ ++SAPI_INPUT_FILTER_FUNC(varfilter_input_filter) ++{ ++ char *index; ++ unsigned int var_len, depth = 0; ++ ++ /* Drop this variable if the limit is reached */ ++ if (VARFILTER_G(max_request_variables) == VARFILTER_G(cur_request_variables)) { ++ php_security_log("tried to register too many variables"); ++ return 0; ++ } ++ ++ /* Drop this variable if it exceeds the value length limit */ ++ if (VARFILTER_G(max_value_length) < val_len) { ++ php_security_log("tried to register a variable with a too long value"); ++ return 0; ++ } ++ ++ /* Find length of variable name */ ++ index = strchr(var, '['); ++ var_len = index ? index-var : strlen(var); ++ ++ /* Drop this variable if it exceeds the varname length limit */ ++ if (VARFILTER_G(max_varname_length) < var_len) { ++ php_security_log("tried to register a variable with a too long variable name"); ++ return 0; ++ } ++ ++ /* Find out array depth */ ++ while (index) { ++ depth++; ++ index = strchr(index+1, '['); ++ } ++ ++ /* Drop this variable if it exceeds the array depth limit */ ++ if (VARFILTER_G(max_array_depth) < depth) { ++ php_security_log("tried to register a too deep array variable"); ++ return 0; ++ } ++ ++ /* Okay let PHP register this variable */ ++ VARFILTER_G(cur_request_variables)++; ++ ++ if (new_val_len) { ++ *new_val_len = val_len; ++ } ++ ++ return 1; ++} ++/* }}} */ ++ ++ ++/* ++ * 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 ++ */ +diff -Nur php-5.0.4/main/SAPI.c hardened-php-5.0.4-0.2.7/main/SAPI.c +--- php-5.0.4/main/SAPI.c 2005-02-22 15:46:15.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/SAPI.c 2005-04-07 02:04:39.000000000 +0200 +@@ -821,6 +821,12 @@ + zend_hash_del(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1); + } + ++SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)) ++{ ++ sapi_module.input_filter = input_filter; ++ return SUCCESS; ++} ++ + + SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D)) + { +@@ -835,11 +841,6 @@ + return SUCCESS; + } + +-SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)) +-{ +- sapi_module.input_filter = input_filter; +- return SUCCESS; +-} + + SAPI_API int sapi_flush(TSRMLS_D) + { +diff -Nur php-5.0.4/main/SAPI.h hardened-php-5.0.4-0.2.7/main/SAPI.h +--- php-5.0.4/main/SAPI.h 2004-01-08 18:33:04.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/SAPI.h 2005-04-07 02:04:39.000000000 +0200 +@@ -103,9 +103,14 @@ + char *current_user; + int current_user_length; + +- /* this is necessary for CLI module */ +- int argc; +- char **argv; ++ /* this is necessary for CLI module */ ++ int argc; ++ char **argv; ++ ++#if HARDENED_PHP ++ /* this is necessary for IP logging */ ++ char ip_address[64]; ++#endif + } sapi_request_info; + + +@@ -270,7 +275,11 @@ + + #define SAPI_DEFAULT_MIMETYPE "text/html" + #define SAPI_DEFAULT_CHARSET "" ++#if HARDENED_PHP ++#define SAPI_PHP_VERSION_HEADER "X-Powered-By: Hardened-PHP/" PHP_VERSION ++#else + #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION ++#endif + + #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D) + #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC) +diff -Nur php-5.0.4/main/fopen_wrappers.c hardened-php-5.0.4-0.2.7/main/fopen_wrappers.c +--- php-5.0.4/main/fopen_wrappers.c 2005-03-11 07:55:22.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/fopen_wrappers.c 2005-04-07 02:05:49.000000000 +0200 +@@ -163,6 +163,21 @@ + char *pathbuf; + char *ptr; + char *end; ++ char path_copy[MAXPATHLEN]; ++ int path_len; ++ ++ /* Special case path ends with a trailing slash */ ++ path_len = strlen(path); ++ if (path_len >= MAXPATHLEN) { ++ errno = EPERM; /* we deny permission to open it */ ++ return -1; ++ } ++ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) { ++ memcpy(path_copy, path, path_len+1); ++ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--; ++ path_copy[path_len] = '\0'; ++ path = (const char *)&path_copy; ++ } + + pathbuf = estrdup(PG(open_basedir)); + +diff -Nur php-5.0.4/main/hardened_globals.h hardened-php-5.0.4-0.2.7/main/hardened_globals.h +--- php-5.0.4/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/hardened_globals.h 2005-04-07 02:04:39.000000000 +0200 +@@ -0,0 +1,54 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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 | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef HARDENED_GLOBALS_H ++#define HARDENED_GLOBALS_H ++ ++typedef struct _hardened_globals hardened_globals_struct; ++ ++#ifdef ZTS ++# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v) ++extern int hardened_globals_id; ++#else ++# define HG(v) (hardened_globals.v) ++extern struct _hardened_globals hardened_globals; ++#endif ++ ++ ++struct _hardened_globals { ++#if HARDENED_PHP_MM_PROTECT ++ unsigned int canary_1; ++ unsigned int canary_2; ++#endif ++#if HARDENED_PHP_LL_PROTECT ++ unsigned int canary_3; ++ unsigned int canary_4; ++ unsigned int ll_canary_inited; ++#endif ++ unsigned int dummy; ++}; ++ ++ ++#endif /* HARDENED_GLOBALS_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nur php-5.0.4/main/hardened_php.c hardened-php-5.0.4-0.2.7/main/hardened_php.c +--- php-5.0.4/main/hardened_php.c 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/hardened_php.c 2005-04-07 02:04:39.000000000 +0200 +@@ -0,0 +1,205 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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: hardened_php.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */ ++ ++#include "php.h" ++ ++#include ++#include ++ ++#if HAVE_UNISTD_H ++#include ++#endif ++#include "SAPI.h" ++#include "php_globals.h" ++ ++#if HARDENED_PHP ++ ++#ifdef HAVE_SYS_SOCKET_H ++#include ++#endif ++ ++#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE) ++#undef AF_UNIX ++#endif ++ ++#if defined(AF_UNIX) ++#include ++#endif ++ ++#define SYSLOG_PATH "/dev/log" ++ ++#include "snprintf.h" ++ ++#ifdef ZTS ++#include "hardened_globals.h" ++int hardened_globals_id; ++#else ++struct _hardened_globals hardened_globals; ++#endif ++ ++static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC) ++{ ++ memset(hardened_globals, 0, sizeof(*hardened_globals)); ++} ++ ++PHPAPI void hardened_startup() ++{ ++#ifdef ZTS ++ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL); ++#else ++ hardened_globals_ctor(&hardened_globals TSRMLS_CC); ++#endif ++} ++ ++PHPAPI void php_security_log(char *str) ++{ ++#if defined(AF_UNIX) ++ int s, r; ++ struct sockaddr_un saun; ++ char buf[1024]; ++ char *ip_address; ++ char *fname; ++ TSRMLS_FETCH(); ++ ++ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC); ++ if (ip_address == NULL) { ++ ip_address = "REMOTE_ADDR not set"; ++ } ++ ++ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC); ++ ++ ap_php_snprintf(buf, 1024, "php security-alert: %s (attacker '%s', file '%s')\n", str, ip_address, fname); ++ ++ s = socket(AF_UNIX, SOCK_DGRAM, 0); ++ if (s == -1) { ++ return; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ s = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (s == -1) { ++ return; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ return; ++ } ++ } ++ send(s, buf, strlen(buf), 0); ++ ++ close(s); ++#endif ++} ++#endif ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++ ++/* will be replaced later with more compatible method */ ++PHPAPI unsigned int php_canary() ++{ ++ time_t t; ++ unsigned int canary; ++ int fd; ++ ++ fd = open("/dev/urandom", 0); ++ if (fd != -1) { ++ int r = read(fd, &canary, sizeof(canary)); ++ close(fd); ++ if (r == sizeof(canary)) { ++ return (canary); ++ } ++ } ++ /* not good but we never want to do this */ ++ time(&t); ++ canary = *(unsigned int *)&t + getpid() << 16; ++ return (canary); ++} ++#endif ++ ++#if HARDENED_PHP_INC_PROTECT ++ ++PHPAPI int php_is_valid_include(zval *z) ++{ ++ char *filename; ++ int len; ++ TSRMLS_FETCH(); ++ ++ /* must be of type string */ ++ if (z->type != IS_STRING || z->value.str.val == NULL) { ++ return (0); ++ } ++ ++ /* short cut */ ++ filename = z->value.str.val; ++ len = z->value.str.len; ++ ++ /* 1. must be shorter than MAXPATHLEN */ ++ if (len > MAXPATHLEN) { ++ php_security_log("Include filename longer than MAXPATHLEN chars"); ++ return (0); ++ } ++ ++ /* 2. must not be cutted */ ++ if (len != strlen(filename)) { ++ php_security_log("Include filename has a \\0 cut"); ++ return (0); ++ } ++ ++ /* 3. must not be a URL */ ++ if (strstr(filename, "://")) { ++ php_security_log("Include filename is an URL"); ++ return (0); ++ } ++ ++ /* 4. must not be an uploaded file */ ++ if (SG(rfc1867_uploaded_files)) { ++ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) { ++ php_security_log("Include filename is an uploaded file"); ++ return (0); ++ } ++ } ++ ++ /* passed all tests */ ++ return (1); ++} ++ ++#endif ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nur php-5.0.4/main/hardened_php.h hardened-php-5.0.4-0.2.7/main/hardened_php.h +--- php-5.0.4/main/hardened_php.h 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/hardened_php.h 2005-04-07 02:05:01.000000000 +0200 +@@ -0,0 +1,45 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Hardened-PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.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 | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef HARDENED_PHP_H ++#define HARDENED_PHP_H ++ ++#include "zend.h" ++ ++#if HARDENED_PHP ++PHPAPI void php_security_log(char *str); ++PHPAPI void hardened_startup(); ++#define HARDENED_PHP_VERSION "0.2.7" ++#endif ++ ++#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT || HARDENED_PHP_HASH_PROTECT ++PHPAPI unsigned int php_canary(); ++#endif ++ ++#if HARDENED_PHP_INC_PROTECT ++PHPAPI int php_is_valid_include(zval *z); ++#endif ++ ++#endif /* HARDENED_PHP_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nur php-5.0.4/main/hardened_php.m4 hardened-php-5.0.4-0.2.7/main/hardened_php.m4 +--- php-5.0.4/main/hardened_php.m4 1970-01-01 01:00:00.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/hardened_php.m4 2005-04-07 02:04:39.000000000 +0200 +@@ -0,0 +1,95 @@ ++dnl ++dnl $Id: hardened_php.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $ ++dnl ++dnl This file contains Hardened-PHP specific autoconf functions. ++dnl ++ ++AC_ARG_ENABLE(hardened-php-mm-protect, ++[ --disable-hardened-php-mm-protect Disable the Memory Manager protection.],[ ++ DO_HARDENED_PHP_MM_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_MM_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-ll-protect, ++[ --disable-hardened-php-ll-protect Disable the Linked List protection.],[ ++ DO_HARDENED_PHP_LL_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_LL_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-inc-protect, ++[ --disable-hardened-php-inc-protect Disable include/require protection.],[ ++ DO_HARDENED_PHP_INC_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_INC_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-fmt-protect, ++[ --disable-hardened-php-fmt-protect Disable format string protection.],[ ++ DO_HARDENED_PHP_FMT_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_FMT_PROTECT=yes ++]) ++ ++AC_ARG_ENABLE(hardened-php-hash-protect, ++[ --disable-hardened-php-hash-protect Disable HashTable destructor protection.],[ ++ DO_HARDENED_PHP_HASH_PROTECT=$enableval ++],[ ++ DO_HARDENED_PHP_HASH_PROTECT=yes ++]) ++ ++AC_MSG_CHECKING(whether to protect the Zend Memory Manager) ++AC_MSG_RESULT($DO_HARDENED_PHP_MM_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect the Zend Linked Lists) ++AC_MSG_RESULT($DO_HARDENED_PHP_LL_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect include/require statements) ++AC_MSG_RESULT($DO_HARDENED_PHP_INC_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect PHP Format String functions) ++AC_MSG_RESULT($DO_HARDENED_PHP_FMT_PROTECT) ++ ++AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables) ++AC_MSG_RESULT($DO_HARDENED_PHP_HASH_PROTECT) ++ ++ ++AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ ++ ++if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 1, [Memory Manager Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 0, [Memory Manager Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 1, [Linked List Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 0, [Linked List Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 1, [Include/Require Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 0, [Include/Require Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 1, [Fmt String Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 0, [Fmt String Protection]) ++fi ++ ++if test "$DO_HARDENED_PHP_HASH_PROTECT" = "yes"; then ++dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP]) ++ AC_DEFINE(HARDENED_PHP_HASH_PROTECT, 1, [HashTable DTOR Protection]) ++else ++ AC_DEFINE(HARDENED_PHP_HASH_PROTECT, 0, [HashTable DTOR Protection]) ++fi ++ +diff -Nur php-5.0.4/main/main.c hardened-php-5.0.4-0.2.7/main/main.c +--- php-5.0.4/main/main.c 2005-03-24 02:11:35.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/main.c 2005-04-07 02:04:39.000000000 +0200 +@@ -92,6 +92,10 @@ + + #include "SAPI.h" + #include "rfc1867.h" ++#if HARDENED_PHP ++#include "hardened_globals.h" ++#endif ++ + /* }}} */ + + #ifndef ZTS +@@ -116,10 +120,33 @@ + */ + static PHP_INI_MH(OnChangeMemoryLimit) + { ++#if HARDENED_PHP ++ long orig_memory_limit; ++ ++ if (entry->modified) { ++ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length); ++ } else { ++ orig_memory_limit = 1<<30; ++ } ++ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) { ++ orig_memory_limit = 1<<30; ++ } ++#endif + if (new_value) { + PG(memory_limit) = zend_atoi(new_value, new_value_length); ++#if HARDENED_PHP ++ if (PG(memory_limit) > orig_memory_limit) { ++ PG(memory_limit) = orig_memory_limit; ++ php_security_log("script tried to increase memory_limit above allowed value"); ++ return FAILURE; ++ } ++#endif + } else { ++#if HARDENED_PHP ++ PG(memory_limit) = orig_memory_limit; ++#else + PG(memory_limit) = 1<<30; /* effectively, no limit */ ++#endif + } + return zend_set_memory_limit(PG(memory_limit)); + } +@@ -1313,6 +1340,10 @@ + tsrm_ls = ts_resource(0); + #endif + ++#if HARDENED_PHP ++ hardened_startup(); ++#endif ++ + module_shutdown = 0; + module_startup = 1; + sapi_initialize_empty_request(TSRMLS_C); +@@ -1326,6 +1357,12 @@ + + php_output_startup(); + ++#if HARDENED_PHP_INC_PROTECT ++ zuf.is_valid_include = php_is_valid_include; ++#endif ++#if HARDENED_PHP ++ zuf.security_log_function = php_security_log; ++#endif + zuf.error_function = php_error_cb; + zuf.printf_function = php_printf; + zuf.write_function = php_body_write_wrapper; +@@ -1429,6 +1466,10 @@ + REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS); ++#if HARDENED_PHP ++ REGISTER_MAIN_LONG_CONSTANT("HARDENED_PHP", 1, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_STRINGL_CONSTANT("HARDENED_PHP_VERSION", HARDENED_PHP_VERSION, sizeof(HARDENED_PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS); ++#endif + REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS); + php_output_register_constants(TSRMLS_C); + php_rfc1867_register_constants(TSRMLS_C); +diff -Nur php-5.0.4/main/php.h hardened-php-5.0.4-0.2.7/main/php.h +--- php-5.0.4/main/php.h 2005-03-14 10:41:39.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/php.h 2005-04-07 02:04:39.000000000 +0200 +@@ -35,11 +35,19 @@ + #include "zend_qsort.h" + #include "php_compat.h" + ++ + #include "zend_API.h" + + #undef sprintf + #define sprintf php_sprintf + ++#if HARDENED_PHP ++#if HAVE_REALPATH ++#undef realpath ++#define realpath php_realpath ++#endif ++#endif ++ + /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */ + #undef PHP_DEBUG + #define PHP_DEBUG ZEND_DEBUG +@@ -341,6 +349,7 @@ + #define PHP_FUNCTION ZEND_FUNCTION + #define PHP_METHOD ZEND_METHOD + ++#define PHP_STATIC_FE ZEND_STATIC_FE + #define PHP_NAMED_FE ZEND_NAMED_FE + #define PHP_FE ZEND_FE + #define PHP_FALIAS ZEND_FALIAS +@@ -446,6 +455,10 @@ + #endif + #endif /* !XtOffsetOf */ + ++#if HARDENED_PHP ++#include "hardened_php.h" ++#endif ++ + #endif + + /* +diff -Nur php-5.0.4/main/php_config.h.in hardened-php-5.0.4-0.2.7/main/php_config.h.in +--- php-5.0.4/main/php_config.h.in 2005-04-03 11:42:53.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/main/php_config.h.in 2005-04-07 02:04:39.000000000 +0200 +@@ -746,6 +746,39 @@ + /* hardcode for each of the cross compiler host */ + #undef PHP_UNAME + ++/* Hardened-PHP */ ++#undef HARDENED_PHP ++ ++/* Memory Manager Protection */ ++#undef HARDENED_PHP_MM_PROTECT ++ ++/* Memory Manager Protection */ ++#undef HARDENED_PHP_MM_PROTECT ++ ++/* Linked List Protection */ ++#undef HARDENED_PHP_LL_PROTECT ++ ++/* Linked List Protection */ ++#undef HARDENED_PHP_LL_PROTECT ++ ++/* Include/Require Protection */ ++#undef HARDENED_PHP_INC_PROTECT ++ ++/* Include/Require Protection */ ++#undef HARDENED_PHP_INC_PROTECT ++ ++/* Fmt String Protection */ ++#undef HARDENED_PHP_FMT_PROTECT ++ ++/* Fmt String Protection */ ++#undef HARDENED_PHP_FMT_PROTECT ++ ++/* HashTable DTOR Protection */ ++#undef HARDENED_PHP_HASH_PROTECT ++ ++/* HashTable DTOR Protection */ ++#undef HARDENED_PHP_HASH_PROTECT ++ + /* Whether you have AOLserver */ + #undef HAVE_AOLSERVER + +@@ -1077,6 +1110,12 @@ + /* Define if you have the getaddrinfo function */ + #undef HAVE_GETADDRINFO + ++/* Whether realpath is broken */ ++#undef PHP_BROKEN_REALPATH ++ ++/* Whether realpath is broken */ ++#undef PHP_BROKEN_REALPATH ++ + /* Whether system headers declare timezone */ + #undef HAVE_DECLARED_TIMEZONE + +diff -Nur php-5.0.4/main/snprintf.c hardened-php-5.0.4-0.2.7/main/snprintf.c +--- php-5.0.4/main/snprintf.c 2004-11-16 00:14:40.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/main/snprintf.c 2005-04-07 02:04:39.000000000 +0200 +@@ -1013,7 +1013,11 @@ + + + case 'n': ++#if HARDENED_PHP_FMT_PROTECT ++ php_security_log("'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = cc; ++#endif + break; + + /* +diff -Nur php-5.0.4/main/spprintf.c hardened-php-5.0.4-0.2.7/main/spprintf.c +--- php-5.0.4/main/spprintf.c 2004-04-16 01:04:49.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/main/spprintf.c 2005-04-07 02:04:39.000000000 +0200 +@@ -630,7 +630,11 @@ + + + case 'n': ++#if HARDENED_PHP_FMT_PROTECT ++ php_security_log("'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = xbuf->len; ++#endif + break; + + /* +diff -Nur php-5.0.4/php.ini-dist hardened-php-5.0.4-0.2.7/php.ini-dist +--- php-5.0.4/php.ini-dist 2005-03-01 01:25:09.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/php.ini-dist 2005-04-07 02:04:39.000000000 +0200 +@@ -1187,6 +1187,23 @@ + ; instead of original one. + soap.wsdl_cache_ttl=86400 + ++[varfilter] ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++; Hardened-PHP's variable filter ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++ ++; Maximum number of input variables per request ++varfilter.max_request_variables = 200 ++ ++; Maximum characters in input variable names ++varfilter.max_varname_length = 64 ++ ++; Maximum length of input variable values ++varfilter.max_value_length = 10000 ++ ++; Maximum depth of input variable arrays ++varfilter.max_array_depth = 100 ++ + ; Local Variables: + ; tab-width: 4 + ; End: +diff -Nur php-5.0.4/php.ini-recommended hardened-php-5.0.4-0.2.7/php.ini-recommended +--- php-5.0.4/php.ini-recommended 2005-03-01 01:25:09.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/php.ini-recommended 2005-04-07 02:04:39.000000000 +0200 +@@ -1245,6 +1245,23 @@ + ; instead of original one. + soap.wsdl_cache_ttl=86400 + ++[varfilter] ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++; Hardened-PHP's variable filter ++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ++ ++; Maximum number of input variables per request ++varfilter.max_request_variables = 200 ++ ++; Maximum characters in input variable names ++varfilter.max_varname_length = 64 ++ ++; Maximum length of input variable values ++varfilter.max_value_length = 10000 ++ ++; Maximum depth of input variable arrays ++varfilter.max_array_depth = 100 ++ + ; Local Variables: + ; tab-width: 4 + ; End: +diff -Nur php-5.0.4/sapi/apache/mod_php5.c hardened-php-5.0.4-0.2.7/sapi/apache/mod_php5.c +--- php-5.0.4/sapi/apache/mod_php5.c 2004-07-14 11:43:26.000000000 +0200 ++++ hardened-php-5.0.4-0.2.7/sapi/apache/mod_php5.c 2005-04-07 02:04:39.000000000 +0200 +@@ -447,7 +447,7 @@ + sapi_apache_get_fd, + sapi_apache_force_http_10, + sapi_apache_get_target_uid, +- sapi_apache_get_target_gid ++ sapi_apache_get_target_gid, + }; + /* }}} */ + +@@ -899,7 +899,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component("Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component("PHP/" PHP_VERSION); ++#endif + } + } + #endif +diff -Nur php-5.0.4/sapi/apache2filter/sapi_apache2.c hardened-php-5.0.4-0.2.7/sapi/apache2filter/sapi_apache2.c +--- php-5.0.4/sapi/apache2filter/sapi_apache2.c 2005-01-07 07:28:24.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/sapi/apache2filter/sapi_apache2.c 2005-04-07 02:04:39.000000000 +0200 +@@ -572,7 +572,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nur php-5.0.4/sapi/apache2handler/sapi_apache2.c hardened-php-5.0.4-0.2.7/sapi/apache2handler/sapi_apache2.c +--- php-5.0.4/sapi/apache2handler/sapi_apache2.c 2005-03-10 12:23:57.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/sapi/apache2handler/sapi_apache2.c 2005-04-07 02:04:39.000000000 +0200 +@@ -340,7 +340,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if HARDENED_PHP ++ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nur php-5.0.4/sapi/cgi/cgi_main.c hardened-php-5.0.4-0.2.7/sapi/cgi/cgi_main.c +--- php-5.0.4/sapi/cgi/cgi_main.c 2005-02-11 03:06:48.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/sapi/cgi/cgi_main.c 2005-04-07 02:04:39.000000000 +0200 +@@ -1414,11 +1414,19 @@ + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + } ++#if HARDENED_PHP ++#if ZEND_DEBUG ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + php_end_ob_buffers(1 TSRMLS_CC); + exit(1); + break; +diff -Nur php-5.0.4/sapi/cli/php_cli.c hardened-php-5.0.4-0.2.7/sapi/cli/php_cli.c +--- php-5.0.4/sapi/cli/php_cli.c 2005-03-22 16:09:20.000000000 +0100 ++++ hardened-php-5.0.4-0.2.7/sapi/cli/php_cli.c 2005-04-07 02:04:39.000000000 +0200 +@@ -694,11 +694,19 @@ + if (php_request_startup(TSRMLS_C)==FAILURE) { + goto err; + } ++#if HARDENED_PHP ++#if ZEND_DEBUG ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("Hardened-PHP %s/%s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENED_PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + php_end_ob_buffers(1 TSRMLS_CC); + exit_status=1; + goto out; -- cgit v1.3