Hello Sara, strong +1, awesome work!
best regards marcus Wednesday, January 17, 2007, 2:07:15 AM, you wrote: > Index: main/php_globals.h > =================================================================== > RCS file: /repository/php-src/main/php_globals.h,v > retrieving revision 1.109 > diff -u -p -r1.109 php_globals.h > --- main/php_globals.h 1 Jan 2007 09:29:35 -0000 1.109 > +++ main/php_globals.h 17 Jan 2007 00:55:27 -0000 > @@ -124,7 +124,8 @@ struct _php_core_globals { > zend_bool modules_activated; > zend_bool file_uploads; > zend_bool during_request_startup; > - zend_bool allow_url_fopen; > + char *allow_url_fopen_list; > + char *allow_url_include_list; > zend_bool always_populate_raw_post_data; > zend_bool report_zend_debug; > > @@ -137,7 +138,6 @@ struct _php_core_globals { > > char *disable_functions; > char *disable_classes; > - zend_bool allow_url_include; > #ifdef PHP_WIN32 > zend_bool com_initialized; > #endif > Index: main/main.c > =================================================================== > RCS file: /repository/php-src/main/main.c,v > retrieving revision 1.719 > diff -u -p -r1.719 main.c > --- main/main.c 9 Jan 2007 18:38:38 -0000 1.719 > +++ main/main.c 17 Jan 2007 00:55:27 -0000 > @@ -420,8 +420,8 @@ PHP_INI_BEGIN() > PHP_INI_ENTRY("disable_functions", "", > PHP_INI_SYSTEM, NULL) > PHP_INI_ENTRY("disable_classes", "", > PHP_INI_SYSTEM, NULL) > > - STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", > PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, > php_core_globals, core_globals) > - STD_PHP_INI_BOOLEAN("allow_url_include", "0", > PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, > php_core_globals, core_globals) > + STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", > PHP_INI_ALL, OnUpdateAllowUrl, > allow_url_fopen_list, php_core_globals, core_globals) > + STD_PHP_INI_BOOLEAN("allow_url_include", "0", > PHP_INI_ALL, OnUpdateAllowUrl, > allow_url_include_list, php_core_globals, core_globals) > STD_PHP_INI_BOOLEAN("always_populate_raw_post_data", > "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, > always_populate_raw_post_data, php_core_globals, > core_globals) > STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, > OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals) > STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, > OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals) > @@ -1507,6 +1507,12 @@ static void core_globals_dtor(php_core_g > if (core_globals->disable_classes) { > free(core_globals->disable_classes); > } > + if (core_globals->allow_url_fopen_list) { > + free(core_globals->allow_url_fopen_list); > + } > + if (core_globals->allow_url_include_list) { > + free(core_globals->allow_url_include_list); > + } > } > /* }}} */ > > Index: main/php_streams.h > =================================================================== > RCS file: /repository/php-src/main/php_streams.h,v > retrieving revision 1.123 > diff -u -p -r1.123 php_streams.h > --- main/php_streams.h 16 Jan 2007 20:36:04 -0000 1.123 > +++ main/php_streams.h 17 Jan 2007 00:55:27 -0000 > @@ -21,6 +21,8 @@ > #ifndef PHP_STREAMS_H > #define PHP_STREAMS_H > > +#include "php_ini.h" > + > #ifdef HAVE_SYS_TIME_H > #include <sys/time.h> > #endif > @@ -165,7 +167,7 @@ typedef struct _php_stream_wrapper_ops { > struct _php_stream_wrapper { > php_stream_wrapper_ops *wops; /* operations the wrapper can perform > */ > void *abstract; /* context for the > wrapper */ > - int is_url; /* so > that PG(allow_url_fopen) can be respected */ > + int is_url; /* so > that PG(allow_url_fopen_list)/PG(allow_url_include_list) can be respected */ > > /* support for wrappers to return (multiple) error messages to the > stream opener */ > int err_count; > @@ -658,6 +660,11 @@ PHPAPI void php_stream_wrapper_log_error > PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream > **newstream, int flags STREAMS_DC TSRMLS_DC); > #define php_stream_make_seekable(origstream, newstream, > flags) _php_stream_make_seekable((origstream), (newstream), (flags) > STREAMS_CC TSRMLS_CC) > > +PHP_INI_MH(OnUpdateAllowUrl); > +PHPAPI int php_stream_wrapper_is_allowed(const char *wrapper, int > wrapper_len, const char *setting TSRMLS_DC); > +#define php_stream_allow_url_fopen(wrapper, wrapper_len) > php_stream_wrapper_is_allowed((wrapper), (wrapper_len), > PG(allow_url_fopen_list) TSRMLS_CC) > +#define php_stream_allow_url_include(wrapper, wrapper_len) > php_stream_wrapper_is_allowed((wrapper), (wrapper_len), > PG(allow_url_include_list) TSRMLS_CC) > + > /* Give other modules access to the url_stream_wrappers_hash and > stream_filters_hash */ > PHPAPI HashTable *_php_stream_get_url_stream_wrappers_hash(TSRMLS_D); > #define php_stream_get_url_stream_wrappers_hash() > _php_stream_get_url_stream_wrappers_hash(TSRMLS_C) > Index: main/streams/streams.c > =================================================================== > RCS file: /repository/php-src/main/streams/streams.c,v > retrieving revision 1.146 > diff -u -p -r1.146 streams.c > --- main/streams/streams.c 16 Jan 2007 20:36:04 -0000 1.146 > +++ main/streams/streams.c 17 Jan 2007 00:55:27 -0000 > @@ -2096,6 +2096,9 @@ PHPAPI php_stream_wrapper *php_stream_lo > } > /* TODO: curl based streams probably support file:// properly */ > if (!protocol || !strncasecmp(protocol, "file", n)) { > + /* fall back on regular file access */ > + php_stream_wrapper *plain_files_wrapper = > &php_plain_files_wrapper; > + > if (protocol) { > int localhost = 0; > > @@ -2132,32 +2135,37 @@ PHPAPI php_stream_wrapper *php_stream_lo > return NULL; > } > > + /* The file:// wrapper may have been disabled/overridden */ > if (FG(stream_wrappers)) { > - /* The file:// wrapper may have been > disabled/overridden */ > - > - if (wrapperpp) { > - /* It was found so go ahead and provide it */ > - return *wrapperpp; > - } > - > - /* Check again, the original check might have not > known the protocol name */ > - if (zend_hash_find(wrapper_hash, "file", > sizeof("file"), (void**)&wrapperpp) == SUCCESS) { > - return *wrapperpp; > + if (!wrapperpp || zend_hash_find(wrapper_hash, > "file", sizeof("file"), (void**)&wrapperpp) == FAILURE) { > + if (options & REPORT_ERRORS) { > + php_error_docref(NULL TSRMLS_CC, > E_WARNING, "Plainfiles wrapper disabled"); > + } > + return NULL; > } > > + /* Handles overridden plain files wrapper */ > + plain_files_wrapper = *wrapperpp; > + } > + > + if (!php_stream_allow_url_fopen("file", sizeof("file") - 1) || > + ((options & STREAM_OPEN_FOR_INCLUDE) && > !php_stream_allow_url_include("file", sizeof("file") - 1)) ) { > if (options & REPORT_ERRORS) { > - php_error_docref(NULL TSRMLS_CC, > E_WARNING, "Plainfiles wrapper disabled"); > + php_error_docref(NULL TSRMLS_CC, > E_WARNING, "file:// wrapper is disabled in the server configuration"); > } > return NULL; > } > - > - /* fall back on regular file access */ > - return &php_plain_files_wrapper; > + > + return plain_files_wrapper; > } > > - if ((wrapperpp && (*wrapperpp)->is_url) && (!PG(allow_url_fopen) > || ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include))) ) { > + if (!php_stream_allow_url_fopen(protocol, n) || > + ((options & STREAM_OPEN_FOR_INCLUDE) && > !php_stream_allow_url_include(protocol, n)) ) { > if (options & REPORT_ERRORS) { > - php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL > file-access is disabled in the server configuration"); > + /* protocol[n] probably isn't '\0' */ > + char *protocol_dup = estrndup(protocol, n); > + php_error_docref(NULL TSRMLS_CC, E_WARNING, > "%s:// wrapper is disabled in the server configuration", protocol_dup); > + efree(protocol_dup); > } > return NULL; > } > @@ -2866,6 +2874,230 @@ PHPAPI int _php_stream_path_decode(php_s > } > /* }}} */ > > +/* {{{ allow_url_fopen / allow_url_include Handlers */ > + > +PHPAPI int php_stream_wrapper_is_allowed(const char *wrapper, int > wrapper_len, const char *setting TSRMLS_DC) > +{ > + int setting_len = setting ? strlen(setting) : 0; > + const char *s = setting, *e = s + setting_len; > + > + if (wrapper_len == (sizeof("zlib") - 1) && strncasecmp("zlib", > wrapper, sizeof("zlib") - 1) == 0) { > + wrapper = "compress.zlib"; > + wrapper_len = sizeof("compress.zlib") - 1; > + } > + > + if (!setting || !setting_len) { > + /* NULL or empty indicates that only is_url == 0 wrappers are > allowed */ > + HashTable *wrapper_hash = (FG(stream_wrappers) ? > FG(stream_wrappers) : &url_stream_wrappers_hash); > + php_stream_wrapper **wrapperpp; > + char *wrapper_dup; > + > + if (wrapper_len == (sizeof("file") - 1) && > strncasecmp("file", wrapper, sizeof("file") - 1) == 0) { > + /* file:// is non-url */ > + return 1; > + } > + > + wrapper_dup = estrndup(wrapper, wrapper_len); > + php_strtolower(wrapper_dup, wrapper_len); > + if (FAILURE == zend_hash_find(wrapper_hash, wrapper_dup, > wrapper_len + 1, (void**)&wrapperpp)) { > + /* Wrapper not found */ > + efree(wrapper_dup); > + return 0; > + } > + > + if ((*wrapperpp)->is_url) { > + return 0; > + } > + > + /* Wrapper exists and is not is_url */ > + return 1; > + } > + > + if (setting_len == 1 && *setting == '*') { > + /* "*" means everything is allowed */ > + return 1; > + } > + > + /* Otherwise, scan list */ > + while (s < e) { > + const char *p = php_memnstr((char*)s, ":", 1, (char*)e); > + > + if (!p) { > + p = e; > + } > + > + if (wrapper_len == (p - s) && > + strncasecmp(s, wrapper, p - s) == 0) { > + /* wrapper found in list */ > + return 1; > + } > + > + s = p + 1; > + } > + > + return 0; > +} > + > +/* allow_url_*_list accepts: > + * > + * 1/on to enable all URL prefixes > + * 0/off to disable all is_url=1 wrappers > + * A colon delimited list of wrappers to allow (wildcards allowed) > + * e.g. file:gzip:compress.*:php > + */ > +PHP_INI_MH(OnUpdateAllowUrl) > +{ > +#ifndef ZTS > + char *base = (char *) mh_arg2; > +#else > + char *base = (char *) ts_resource(*((int *) mh_arg2)); > +#endif > + char **allow = (char **) (base+(size_t) mh_arg1); > + > + /* BC Enable */ > + if ((new_value_length == 1 && *new_value == '1') || > + (new_value_length == (sizeof("on") - 1) && > strncasecmp(new_value, "on", sizeof("on") - 1) == 0) ) { > + > + if (*allow && strcmp(*allow, "*") == 0) { > + /* Turning on, but that's no change from current, so > leave it alone */ > + return SUCCESS; > + } > + > + if (stage != PHP_INI_STAGE_STARTUP) { > + /* Not already on, and not in SYSTEM context, fail */ > + return FAILURE; > + } > + > + /* Otherwise, turn on setting */ > + if (*allow) { > + free(*allow); > + } > + > + *allow = zend_strndup("*", 1); > + > + return SUCCESS; > + } > + > + /* BC disable */ > + if ((new_value_length == 1 && *new_value == '0') || > + (new_value_length == (sizeof("off") - 1) && > strncasecmp(new_value, "off", sizeof("off") - 1) == 0) ) { > + > + /* Always permit shutting off allowurl settings */ > + if (*allow) { > + free(*allow); > + } > + *allow = NULL; > + > + return SUCCESS; > + } > + > + /* Specify as list */ > + if (stage == PHP_INI_STAGE_STARTUP) { > + /* Always allow new settings in startup stage */ > + if (*allow) { > + free(*allow); > + } > + *allow = zend_strndup(new_value, new_value_length); > + > + return SUCCESS; > + } > + > + /* In PERDIR/RUNTIME context, do more work to ensure we're only > tightening the restriction */ > + > + if (*allow && strcmp(*allow, "*") == 0) { > + /* Currently allowing everying, so whatever we set it to will > be more restrictive */ > + free(*allow); > + *allow = zend_strndup(new_value, new_value_length); > + > + return SUCCESS; > + } > + > + if (!*allow) { > + /* Currently allowing anything with is_url == 0 > + * So long as this list doesn't contain any is_url == 1, > allow it > + */ > + HashTable *wrapper_hash = (FG(stream_wrappers) ? > FG(stream_wrappers) : &url_stream_wrappers_hash); > + char *s = new_value, *e = new_value + new_value_length; > + > + while (s < e) { > + php_stream_wrapper **wrapper; > + char *p = php_memnstr(s, ":", 1, e); > + char *scan; > + int scan_len; > + > + if (!p) { > + p = e; > + } > + > + /* file:// is never a URL */ > + if ( (p - s) == (sizeof("file") - 1) && > strncasecmp(s, "file", sizeof("file") - 1) == 0 ) { > + /* file is not a URL */ > + s = p + 1; > + continue; > + } > + > + if ( (p - s) == (sizeof("zlib") - 1) && > strncasecmp(s, "zlib", sizeof("zlib") - 1) == 0 ) { > + /* Wastful since we know that > compress.zlib is already lower cased, but forgivable */ > + scan = estrndup("compress.zlib", > sizeof("compress.zlib") - 1); > + scan_len = sizeof("compress.zlib") - 1; > + } else { > + scan = estrndup(s, p - s);; > + scan_len = p - s; > + php_strtolower(scan, scan_len); > + } > + > + if (FAILURE == zend_hash_find(wrapper_hash, scan, > scan_len + 1, (void**) &wrapper)) { > + /* Unknown wrapper, not allowed in this > context */ > + efree(scan); > + return FAILURE; > + } > + efree(scan); > + > + if ((*wrapper)->is_url) { > + /* Disallowed is_url wrapper specified > when trying to escape is_url == 0 context */ > + return FAILURE; > + } > + > + /* Seems alright so far... */ > + s = p+1; > + } > + > + /* All tests passed, allow it */ > + *allow = zend_strndup(new_value, new_value_length); > + > + return SUCCESS; > + } > + > + /* The current allows are restricted to a specific list, > + * Make certain that our new list is a subset of that list > + */ > + { > + char *s = new_value, *e = new_value + new_value_length; > + > + while (s < e) { > + char *p = php_memnstr(s, ":", 1, e); > + > + if (!p) { > + p = e; > + } > + > + if (!php_stream_wrapper_is_allowed(s, p - s, *allow > TSRMLS_CC)) { > + /* Current settings don't allow this wrapper, > deny */ > + return FAILURE; > + } > + > + s = p + 1; > + } > + > + free(*allow); > + *allow = zend_strndup(new_value, new_value_length); > + > + return SUCCESS; > + } > +} > + > +/* }}} */ > + > /* > * Local variables: > * tab-width: 4 > Index: ext/standard/php_fopen_wrapper.c > =================================================================== > RCS file: /repository/php-src/ext/standard/php_fopen_wrapper.c,v > retrieving revision 1.58 > diff -u -p -r1.58 php_fopen_wrapper.c > --- ext/standard/php_fopen_wrapper.c 1 Jan 2007 09:29:32 -0000 1.58 > +++ ext/standard/php_fopen_wrapper.c 17 Jan 2007 00:55:27 -0000 > @@ -187,7 +187,8 @@ php_stream * php_stream_url_wrap_php(php > } > > if (!strcasecmp(path, "input")) { > - if ((options & STREAM_OPEN_FOR_INCLUDE) && > !PG(allow_url_include) ) { > + /* Override default behavior for php://input when used as > an include and allow_url_include is being used in BC (off) mode */ > + if ((options & STREAM_OPEN_FOR_INCLUDE) && > !PG(allow_url_include_list) ) { > if (options & REPORT_ERRORS) { > php_error_docref(NULL TSRMLS_CC, > E_WARNING, "URL file-access is disabled in the server configuration"); > } > @@ -197,7 +198,8 @@ php_stream * php_stream_url_wrap_php(php > } > > if (!strcasecmp(path, "stdin")) { > - if ((options & STREAM_OPEN_FOR_INCLUDE) && > !PG(allow_url_include) ) { > + /* Override default behavior for php://stdin when used as > an include and allow_url_include is being used in BC (off) mode */ > + if ((options & STREAM_OPEN_FOR_INCLUDE) && > !PG(allow_url_include_list) ) { > if (options & REPORT_ERRORS) { > php_error_docref(NULL TSRMLS_CC, > E_WARNING, "URL file-access is disabled in the server configuration"); > } > Index: ext/soap/php_xml.c > =================================================================== > RCS file: /repository/php-src/ext/soap/php_xml.c,v > retrieving revision 1.31 > diff -u -p -r1.31 php_xml.c > --- ext/soap/php_xml.c 17 Jan 2007 00:22:48 -0000 1.31 > +++ ext/soap/php_xml.c 17 Jan 2007 00:55:27 -0000 > @@ -80,16 +80,19 @@ xmlDocPtr soap_xmlParseFile(const char * > { > xmlParserCtxtPtr ctxt = NULL; > xmlDocPtr ret; > - zend_bool old_allow_url_fopen; > + char *old_allow_url_fopen_list; > > /* > xmlInitParser(); > */ > > - old_allow_url_fopen = PG(allow_url_fopen); > - zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > + old_allow_url_fopen_list = PG(allow_url_fopen_list); > + if (!old_allow_url_fopen_list) { > + old_allow_url_fopen_list = ""; > + } > + zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), "*", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > ctxt = xmlCreateFileParserCtxt(filename); > - zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen ? "1" : "0", 1, > PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > + zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen_list, > strlen(old_allow_url_fopen_list), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > if (ctxt) { > ctxt->keepBlanks = 0; > ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace; > Index: ext/soap/php_http.c > =================================================================== > RCS file: /repository/php-src/ext/soap/php_http.c,v > retrieving revision 1.100 > diff -u -p -r1.100 php_http.c > --- ext/soap/php_http.c 17 Jan 2007 00:22:48 -0000 1.100 > +++ ext/soap/php_http.c 17 Jan 2007 00:55:27 -0000 > @@ -232,7 +232,7 @@ int make_http_soap_request(zval *this_p > int content_type_xml = 0; > char *content_encoding; > char *http_msg = NULL; > - zend_bool old_allow_url_fopen; > + char *old_allow_url_fopen_list; > soap_client_object *client; > > if (this_ptr == NULL || Z_TYPE_P(this_ptr) != IS_OBJECT) { > @@ -317,13 +317,16 @@ try_again: > return FALSE; > } > > - old_allow_url_fopen = PG(allow_url_fopen); > - zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > + old_allow_url_fopen_list = PG(allow_url_fopen_list); > + if (!old_allow_url_fopen_list) { > + old_allow_url_fopen_list = ""; > + } > + zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), "*", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > if (use_ssl && php_stream_locate_url_wrapper("https://", NULL, > STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) == NULL) { > php_url_free(phpurl); > if (request != buf) {efree(request);} > add_soap_fault(this_ptr, "HTTP", "SSL support is not > available in this build", NULL, NULL TSRMLS_CC); > - zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen ? "1" : "0", 1, > PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > + zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen_list, > strlen(old_allow_url_fopen_list), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > return FALSE; > } > > @@ -376,11 +379,11 @@ try_again: > php_url_free(phpurl); > if (request != buf) {efree(request);} > add_soap_fault(this_ptr, "HTTP", "Could not > connect to host", NULL, NULL TSRMLS_CC); > - zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen ? "1" : "0", 1, > PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > + zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen_list, > strlen(old_allow_url_fopen_list), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > return FALSE; > } > } > - zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen ? "1" : "0", 1, > PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > + zend_alter_ini_entry("allow_url_fopen", > sizeof("allow_url_fopen"), old_allow_url_fopen_list, > strlen(old_allow_url_fopen_list), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME); > > if (stream) { > if (client->url) { Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php