|
|
| version 1.1.1.1, 2012/02/21 23:48:05 | version 1.1.1.3, 2013/07/22 01:32:11 |
|---|---|
| Line 2 | Line 2 |
| +----------------------------------------------------------------------+ | +----------------------------------------------------------------------+ |
| | PHP Version 5 | | | PHP Version 5 | |
| +----------------------------------------------------------------------+ | +----------------------------------------------------------------------+ |
| | Copyright (c) 1997-2012 The PHP Group | | | Copyright (c) 1997-2013 The PHP Group | |
| +----------------------------------------------------------------------+ | +----------------------------------------------------------------------+ |
| | This source file is subject to version 3.01 of the PHP license, | | | This source file is subject to version 3.01 of the PHP license, | |
| | that is bundled with this package in the file LICENSE, and is | | | that is bundled with this package in the file LICENSE, and is | |
| Line 39 | Line 39 |
| #include <sys/param.h> | #include <sys/param.h> |
| #endif | #endif |
| #include "safe_mode.h" | |
| #include "ext/standard/head.h" | #include "ext/standard/head.h" |
| #include "ext/standard/php_standard.h" | #include "ext/standard/php_standard.h" |
| #include "zend_compile.h" | #include "zend_compile.h" |
| Line 85 or a tightening during activation/runtime/deactivation | Line 84 or a tightening during activation/runtime/deactivation |
| PHPAPI ZEND_INI_MH(OnUpdateBaseDir) | PHPAPI ZEND_INI_MH(OnUpdateBaseDir) |
| { | { |
| char **p, *pathbuf, *ptr, *end; | char **p, *pathbuf, *ptr, *end; |
| #ifndef ZTS | |
| char *base = (char *) mh_arg2; | |
| #else | |
| char *base = (char *) ts_resource(*((int *) mh_arg2)); | |
| #endif | |
| p = &PG(open_basedir); | p = (char **) (base + (size_t) mh_arg1); |
| if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) { | if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) { |
| /* We're in a PHP_INI_SYSTEM context, no restrictions */ | /* We're in a PHP_INI_SYSTEM context, no restrictions */ |
| Line 333 PHPAPI int php_check_open_basedir_ex(const char *path, | Line 337 PHPAPI int php_check_open_basedir_ex(const char *path, |
| } | } |
| /* }}} */ | /* }}} */ |
| /* {{{ php_check_safe_mode_include_dir | |
| */ | |
| PHPAPI int php_check_safe_mode_include_dir(const char *path TSRMLS_DC) | |
| { | |
| if (PG(safe_mode)) { | |
| if (PG(safe_mode_include_dir) && *PG(safe_mode_include_dir)) { | |
| char *pathbuf; | |
| char *ptr; | |
| char *end; | |
| char resolved_name[MAXPATHLEN]; | |
| /* Resolve the real path into resolved_name */ | |
| if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) { | |
| return -1; | |
| } | |
| pathbuf = estrdup(PG(safe_mode_include_dir)); | |
| ptr = pathbuf; | |
| while (ptr && *ptr) { | |
| end = strchr(ptr, DEFAULT_DIR_SEPARATOR); | |
| if (end != NULL) { | |
| *end = '\0'; | |
| end++; | |
| } | |
| /* Check the path */ | |
| #ifdef PHP_WIN32 | |
| if (strncasecmp(ptr, resolved_name, strlen(ptr)) == 0) | |
| #else | |
| if (strncmp(ptr, resolved_name, strlen(ptr)) == 0) | |
| #endif | |
| { | |
| /* File is in the right directory */ | |
| efree(pathbuf); | |
| return 0; | |
| } | |
| ptr = end; | |
| } | |
| efree(pathbuf); | |
| } | |
| return -1; | |
| } | |
| /* Nothing to check... */ | |
| return 0; | |
| } | |
| /* }}} */ | |
| /* {{{ php_fopen_and_set_opened_path | /* {{{ php_fopen_and_set_opened_path |
| */ | */ |
| static FILE *php_fopen_and_set_opened_path(const char *path, const char *mode, char **opened_path TSRMLS_DC) | static FILE *php_fopen_and_set_opened_path(const char *path, const char *mode, char **opened_path TSRMLS_DC) |
| Line 393 static FILE *php_fopen_and_set_opened_path(const char | Line 348 static FILE *php_fopen_and_set_opened_path(const char |
| } | } |
| fp = VCWD_FOPEN(path, mode); | fp = VCWD_FOPEN(path, mode); |
| if (fp && opened_path) { | if (fp && opened_path) { |
| *opened_path = expand_filepath(path, NULL TSRMLS_CC); | *opened_path = expand_filepath_with_mode(path, NULL, NULL, 0, CWD_EXPAND TSRMLS_CC); |
| } | } |
| return fp; | return fp; |
| } | } |
| Line 403 static FILE *php_fopen_and_set_opened_path(const char | Line 358 static FILE *php_fopen_and_set_opened_path(const char |
| */ | */ |
| PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC) | PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC) |
| { | { |
| FILE *fp; | |
| #ifndef PHP_WIN32 | |
| struct stat st; | |
| #endif | |
| char *path_info; | char *path_info; |
| char *filename = NULL; | char *filename = NULL; |
| char *resolved_path = NULL; | char *resolved_path = NULL; |
| int length; | int length; |
| zend_bool orig_display_errors; | |
| path_info = SG(request_info).request_uri; | path_info = SG(request_info).request_uri; |
| #if HAVE_PWD_H | #if HAVE_PWD_H |
| Line 491 PHPAPI int php_fopen_primary_script(zend_file_handle * | Line 443 PHPAPI int php_fopen_primary_script(zend_file_handle * |
| SG(request_info).path_translated = NULL; | SG(request_info).path_translated = NULL; |
| return FAILURE; | return FAILURE; |
| } | } |
| fp = VCWD_FOPEN(resolved_path, "rb"); | efree(resolved_path); |
| #ifndef PHP_WIN32 | orig_display_errors = PG(display_errors); |
| /* refuse to open anything that is not a regular file */ | PG(display_errors) = 0; |
| if (fp && (0 > fstat(fileno(fp), &st) || !S_ISREG(st.st_mode))) { | if (zend_stream_open(filename, file_handle TSRMLS_CC) == FAILURE) { |
| fclose(fp); | PG(display_errors) = orig_display_errors; |
| fp = NULL; | |
| } | |
| #endif | |
| if (!fp) { | |
| if (SG(request_info).path_translated != filename) { | if (SG(request_info).path_translated != filename) { |
| STR_FREE(filename); | STR_FREE(filename); |
| } | } |
| Line 509 PHPAPI int php_fopen_primary_script(zend_file_handle * | Line 456 PHPAPI int php_fopen_primary_script(zend_file_handle * |
| SG(request_info).path_translated = NULL; | SG(request_info).path_translated = NULL; |
| return FAILURE; | return FAILURE; |
| } | } |
| PG(display_errors) = orig_display_errors; | |
| file_handle->opened_path = resolved_path; | |
| if (SG(request_info).path_translated != filename) { | if (SG(request_info).path_translated != filename) { |
| STR_FREE(SG(request_info).path_translated); /* for same reason as above */ | STR_FREE(SG(request_info).path_translated); /* for same reason as above */ |
| SG(request_info).path_translated = filename; | SG(request_info).path_translated = filename; |
| } | } |
| file_handle->filename = SG(request_info).path_translated; | |
| file_handle->free_filename = 0; | |
| file_handle->handle.fp = fp; | |
| file_handle->type = ZEND_HANDLE_FP; | |
| return SUCCESS; | return SUCCESS; |
| } | } |
| /* }}} */ | /* }}} */ |
| Line 537 PHPAPI char *php_resolve_path(const char *filename, in | Line 478 PHPAPI char *php_resolve_path(const char *filename, in |
| char *actual_path; | char *actual_path; |
| php_stream_wrapper *wrapper; | php_stream_wrapper *wrapper; |
| if (!filename) { | if (!filename || CHECK_NULL_PATH(filename, filename_length)) { |
| return NULL; | return NULL; |
| } | } |
| if (strlen(filename) != filename_length) { | |
| return NULL; | |
| } | |
| /* Don't resolve paths which contain protocol (except of file://) */ | /* Don't resolve paths which contain protocol (except of file://) */ |
| for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); | for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); |
| if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) { | if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) { |
| Line 628 PHPAPI char *php_resolve_path(const char *filename, in | Line 565 PHPAPI char *php_resolve_path(const char *filename, in |
| /* check in calling scripts' current working directory as a fall back case | /* check in calling scripts' current working directory as a fall back case |
| */ | */ |
| if (zend_is_executing(TSRMLS_C)) { | if (zend_is_executing(TSRMLS_C)) { |
| char *exec_fname = zend_get_executed_filename(TSRMLS_C); | const char *exec_fname = zend_get_executed_filename(TSRMLS_C); |
| int exec_fname_length = strlen(exec_fname); | int exec_fname_length = strlen(exec_fname); |
| while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])); | while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])); |
| Line 674 PHPAPI char *php_resolve_path(const char *filename, in | Line 611 PHPAPI char *php_resolve_path(const char *filename, in |
| PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const char *path, char **opened_path TSRMLS_DC) | PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const char *path, char **opened_path TSRMLS_DC) |
| { | { |
| char *pathbuf, *ptr, *end; | char *pathbuf, *ptr, *end; |
| char *exec_fname; | const char *exec_fname; |
| char trypath[MAXPATHLEN]; | char trypath[MAXPATHLEN]; |
| struct stat sb; | |
| FILE *fp; | FILE *fp; |
| int path_length; | int path_length; |
| int filename_length; | int filename_length; |
| Line 693 PHPAPI FILE *php_fopen_with_path(const char *filename, | Line 629 PHPAPI FILE *php_fopen_with_path(const char *filename, |
| filename_length = strlen(filename); | filename_length = strlen(filename); |
| /* Relative path open */ | /* Relative path open */ |
| if (*filename == '.') { | if ((*filename == '.') |
| if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) { | |
| return NULL; | |
| } | |
| return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC); | |
| } | |
| /* | |
| * files in safe_mode_include_dir (or subdir) are excluded from | |
| * safe mode GID/UID checks | |
| */ | |
| /* Absolute path open */ | /* Absolute path open */ |
| if (IS_ABSOLUTE_PATH(filename, filename_length)) { | || IS_ABSOLUTE_PATH(filename, filename_length) |
| if (php_check_safe_mode_include_dir(filename TSRMLS_CC) == 0) { | || (!path || (path && !*path)) |
| /* filename is in safe_mode_include_dir (or subdir) */ | ) { |
| return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC); | |
| } | |
| if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) { | |
| return NULL; | |
| } | |
| return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC); | return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC); |
| } | } |
| if (!path || (path && !*path)) { | |
| if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) { | |
| return NULL; | |
| } | |
| return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC); | |
| } | |
| /* check in provided path */ | /* check in provided path */ |
| /* append the calling scripts' current working directory | /* append the calling scripts' current working directory |
| * as a fall back case | * as a fall back case |
| Line 759 PHPAPI FILE *php_fopen_with_path(const char *filename, | Line 672 PHPAPI FILE *php_fopen_with_path(const char *filename, |
| if (snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename) >= MAXPATHLEN) { | if (snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename) >= MAXPATHLEN) { |
| php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", ptr, filename, MAXPATHLEN); | php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", ptr, filename, MAXPATHLEN); |
| } | } |
| if (PG(safe_mode)) { | |
| if (VCWD_STAT(trypath, &sb) == 0) { | |
| /* file exists ... check permission */ | |
| if (php_check_safe_mode_include_dir(trypath TSRMLS_CC) == 0 || | |
| php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM) | |
| ) { | |
| /* UID ok, or trypath is in safe_mode_include_dir */ | |
| fp = php_fopen_and_set_opened_path(trypath, mode, opened_path TSRMLS_CC); | |
| } else { | |
| fp = NULL; | |
| } | |
| efree(pathbuf); | |
| return fp; | |
| } | |
| } | |
| fp = php_fopen_and_set_opened_path(trypath, mode, opened_path TSRMLS_CC); | fp = php_fopen_and_set_opened_path(trypath, mode, opened_path TSRMLS_CC); |
| if (fp) { | if (fp) { |
| efree(pathbuf); | efree(pathbuf); |
| Line 839 PHPAPI char *expand_filepath(const char *filepath, cha | Line 737 PHPAPI char *expand_filepath(const char *filepath, cha |
| */ | */ |
| PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len TSRMLS_DC) | PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len TSRMLS_DC) |
| { | { |
| return expand_filepath_with_mode(filepath, real_path, relative_to, relative_to_len, CWD_FILEPATH TSRMLS_CC); | |
| } | |
| /* }}} */ | |
| /* {{{ expand_filepath_use_realpath | |
| */ | |
| PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode TSRMLS_DC) | |
| { | |
| cwd_state new_state; | cwd_state new_state; |
| char cwd[MAXPATHLEN]; | char cwd[MAXPATHLEN]; |
| int copy_len; | int copy_len; |
| Line 883 PHPAPI char *expand_filepath_ex(const char *filepath, | Line 789 PHPAPI char *expand_filepath_ex(const char *filepath, |
| new_state.cwd = strdup(cwd); | new_state.cwd = strdup(cwd); |
| new_state.cwd_length = strlen(cwd); | new_state.cwd_length = strlen(cwd); |
| if (virtual_file_ex(&new_state, filepath, NULL, CWD_FILEPATH)) { | if (virtual_file_ex(&new_state, filepath, NULL, realpath_mode TSRMLS_CC)) { |
| free(new_state.cwd); | free(new_state.cwd); |
| return NULL; | return NULL; |
| } | } |