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;