diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/config.c | 2 | ||||
-rw-r--r-- | server/core.c | 103 | ||||
-rw-r--r-- | server/listen.c | 69 | ||||
-rw-r--r-- | server/log.c | 6 | ||||
-rw-r--r-- | server/util.c | 31 | ||||
-rw-r--r-- | server/vhost.c | 19 |
6 files changed, 190 insertions, 40 deletions
diff --git a/server/config.c b/server/config.c index 3d11ff5..635b65d 100644 --- a/server/config.c +++ b/server/config.c @@ -418,7 +418,7 @@ AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r) } if (!r->handler) { - if (r->content_type) { + if (r->content_type && AP_REQUEST_IS_TRUSTED_CT(r)) { handler = r->content_type; if ((p=ap_strchr_c(handler, ';')) != NULL) { char *new_handler = (char *)apr_pmemdup(r->pool, handler, diff --git a/server/core.c b/server/core.c index e5e059e..843b973 100644 --- a/server/core.c +++ b/server/core.c @@ -4426,6 +4426,25 @@ static const char *set_merge_trailers(cmd_parms *cmd, void *dummy, int arg) return NULL; } +#ifdef WIN32 +static const char *set_unc_list(cmd_parms *cmd, void *d_, int argc, char *const argv[]) +{ + core_server_config *sconf = ap_get_core_module_config(cmd->server->module_config); + int i; + const char *err; + + if ((err = ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST)) != NULL) + return err; + + sconf->unc_list = apr_array_make(cmd->pool, argc, sizeof(char *)); + + for (i = 0; i < argc; i++) { + *(char **)apr_array_push(sconf->unc_list) = apr_pstrdup(cmd->pool, argv[i]); + } + + return NULL; +} +#endif /* Note --- ErrorDocument will now work from .htaccess files. * The AllowOverride of Fileinfo allows webmasters to turn it off */ @@ -4527,6 +4546,10 @@ AP_INIT_TAKE1("FlushMaxThreshold", set_flush_max_threshold, NULL, RSRC_CONF, AP_INIT_TAKE1("FlushMaxPipelined", set_flush_max_pipelined, NULL, RSRC_CONF, "Maximum number of pipelined responses (pending) above which they are " "flushed to the network"), +#ifdef WIN32 +AP_INIT_TAKE_ARGV("UNCList", set_unc_list, NULL, RSRC_CONF, + "Controls what UNC hosts may be looked up"), +#endif /* Old server config file commands */ @@ -4812,7 +4835,7 @@ static int core_override_type(request_rec *r) /* Check for overrides with ForceType / SetHandler */ if (conf->mime_type && strcmp(conf->mime_type, "none")) - ap_set_content_type(r, (char*) conf->mime_type); + ap_set_content_type_ex(r, (char*) conf->mime_type, 1); if (conf->expr_handler) { const char *err; @@ -5632,6 +5655,84 @@ AP_CORE_DECLARE(apr_status_t) ap_get_pollfd_from_conn(conn_rec *c, return ap_run_get_pollfd_from_conn(c, pfd, ptimeout); } +#ifdef WIN32 +static apr_status_t check_unc(const char *path, apr_pool_t *p) +{ + int i; + char *s, *teststring; + apr_status_t rv = APR_EACCES; + core_server_config *sconf = NULL; + + if (!ap_server_conf) { + return APR_SUCCESS; /* this early, if we have a UNC, it's specified by an admin */ + } + + if (!path || (path != ap_strstr_c(path, "\\\\") && + path != ap_strstr_c(path, "//"))) { + return APR_SUCCESS; /* not a UNC */ + } + + sconf = ap_get_core_module_config(ap_server_conf->module_config); + s = teststring = apr_pstrdup(p, path); + *s++ = '/'; + *s++ = '/'; + + ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, + "ap_filepath_merge: check converted path %s allowed %d", + teststring, + sconf->unc_list ? sconf->unc_list->nelts : 0); + + for (i = 0; sconf->unc_list && i < sconf->unc_list->nelts; i++) { + char *configured_unc = ((char **)sconf->unc_list->elts)[i]; + apr_uri_t uri; + if (APR_SUCCESS == apr_uri_parse(p, teststring, &uri) && + (uri.hostinfo == NULL || + !ap_cstr_casecmp(uri.hostinfo, configured_unc))) { + rv = APR_SUCCESS; + ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, + "ap_filepath_merge: match %s %s", + uri.hostinfo, configured_unc); + break; + } + else { + ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, + "ap_filepath_merge: no match %s %s", uri.hostinfo, + configured_unc); + } + } + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(10504) + "ap_filepath_merge: UNC path %s not allowed by UNCList", teststring); + } + + return rv; +} +#endif + +AP_DECLARE(apr_status_t) ap_filepath_merge(char **newpath, + const char *rootpath, + const char *addpath, + apr_int32_t flags, + apr_pool_t *p) +{ +#ifdef WIN32 + apr_status_t rv; + + if (APR_SUCCESS != (rv = check_unc(rootpath, p))) { + return rv; + } + if (APR_SUCCESS != (rv = check_unc(addpath, p))) { + return rv; + } +#undef apr_filepath_merge +#endif + return apr_filepath_merge(newpath, rootpath, addpath, flags, p); +#ifdef WIN32 +#define apr_filepath_merge ap_filepath_merge +#endif +} + + static void register_hooks(apr_pool_t *p) { errorlog_hash = apr_hash_make(p); diff --git a/server/listen.c b/server/listen.c index 5242c2a..9577d60 100644 --- a/server/listen.c +++ b/server/listen.c @@ -19,6 +19,7 @@ #define APR_WANT_STRFUNC #include "apr_want.h" +#include "apr_version.h" #include "ap_config.h" #include "httpd.h" @@ -277,8 +278,32 @@ static apr_status_t close_listeners_on_exec(void *v) return APR_SUCCESS; } +/* Returns non-zero if socket address SA matches hostname, port and + * scope_id. p is used for temporary allocations. */ +static int match_address(const apr_sockaddr_t *sa, + const char *hostname, apr_port_t port, + const char *scope_id, apr_pool_t *p) +{ + const char *old_scope = NULL; + +#if APR_VERSION_AT_LEAST(1,7,0) + /* To be clever here we could correctly match numeric and + * non-numeric zone ids. Ignore failure, old_scope will be left + * as NULL. */ + (void) apr_sockaddr_zone_get(sa, &old_scope, NULL, p); +#endif + + return port == sa->port + && ((!hostname && !sa->hostname) + || (hostname && sa->hostname && !strcmp(sa->hostname, hostname))) + && ((!scope_id && !old_scope) + || (scope_id && old_scope && !strcmp(scope_id, old_scope))); +} + +/* ### This logic doesn't cope with DNS changes across a restart. */ static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, - const char *addr, apr_port_t port) + const char *addr, apr_port_t port, + const char *scope_id, apr_pool_t *temp_pool) { int found = 0; @@ -288,15 +313,10 @@ static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, /* Some listeners are not real so they will not have a bind_addr. */ if (sa) { ap_listen_rec *new; - apr_port_t oldport; - oldport = sa->port; - /* If both ports are equivalent, then if their names are equivalent, - * then we will re-use the existing record. - */ - if (port == oldport && - ((!addr && !sa->hostname) || - ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) { + /* Re-use the existing record if it matches completely + * against an existing listener. */ + if (match_address(sa, addr, port, scope_id, temp_pool)) { found = 1; if (!to) { break; @@ -317,19 +337,21 @@ static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, static const char *alloc_listener(process_rec *process, const char *addr, apr_port_t port, const char* proto, - void *slave) + const char *scope_id, void *slave, + apr_pool_t *temp_pool) { ap_listen_rec *last; apr_status_t status; apr_sockaddr_t *sa; /* see if we've got a listener for this address:port, which is an error */ - if (find_listeners(&ap_listeners, NULL, addr, port)) { + if (find_listeners(&ap_listeners, NULL, addr, port, scope_id, temp_pool)) { return "Cannot define multiple Listeners on the same IP:port"; } /* see if we've got an old listener for this address:port */ - if (find_listeners(&old_listeners, &ap_listeners, addr, port)) { + if (find_listeners(&old_listeners, &ap_listeners, addr, port, + scope_id, temp_pool)) { if (ap_listeners->slave != slave) { return "Cannot define a slave on the same IP:port as a Listener"; } @@ -383,6 +405,18 @@ static const char *alloc_listener(process_rec *process, const char *addr, return "Listen setup failed"; } +#if APR_VERSION_AT_LEAST(1,7,0) + if (scope_id) { + status = apr_sockaddr_zone_set(new->bind_addr, scope_id); + if (status) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool, APLOGNO(10102) + "alloc_listener: failed to set scope for %pI to %s", + new->bind_addr, scope_id); + return "Listen step failed"; + } + } +#endif + /* We need to preserve the order returned by getaddrinfo() */ if (last == NULL) { ap_listeners = last = new; @@ -835,10 +869,14 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, host = NULL; } +#if !APR_VERSION_AT_LEAST(1,7,0) if (scope_id) { - /* XXX scope id support is useful with link-local IPv6 addresses */ - return "Scope id is not supported"; + return apr_pstrcat(cmd->pool, + "Scope ID in address '", argv[0], + "' not supported with APR " APR_VERSION_STRING, + NULL); } +#endif if (!port) { return "Port must be specified"; @@ -856,7 +894,8 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, ap_str_tolower(proto); } - return alloc_listener(cmd->server->process, host, port, proto, NULL); + return alloc_listener(cmd->server->process, host, port, proto, + scope_id, NULL, cmd->temp_pool); } AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, diff --git a/server/log.c b/server/log.c index 22d2f8d..9576d07 100644 --- a/server/log.c +++ b/server/log.c @@ -64,6 +64,10 @@ #undef APLOG_MODULE_INDEX #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX +#ifndef DEFAULT_LOG_TID +#define DEFAULT_LOG_TID NULL +#endif + typedef struct { const char *t_name; int t_val; @@ -990,7 +994,7 @@ static int do_errorlog_default(const ap_errorlog_info *info, char *buf, #if APR_HAS_THREADS field_start = len; len += cpystrn(buf + len, ":tid ", buflen - len); - item_len = log_tid(info, NULL, buf + len, buflen - len); + item_len = log_tid(info, DEFAULT_LOG_TID, buf + len, buflen - len); if (!item_len) len = field_start; else diff --git a/server/util.c b/server/util.c index 45502b8..11d0e40 100644 --- a/server/util.c +++ b/server/util.c @@ -75,17 +75,6 @@ */ #include "test_char.h" -/* Win32/NetWare/OS2 need to check for both forward and back slashes - * in ap_normalize_path() and ap_escape_url(). - */ -#ifdef CASE_BLIND_FILESYSTEM -#define IS_SLASH(s) ((s == '/') || (s == '\\')) -#define SLASHES "/\\" -#else -#define IS_SLASH(s) (s == '/') -#define SLASHES "/" -#endif - /* we know core's module_index is 0 */ #undef APLOG_MODULE_INDEX #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX @@ -492,7 +481,7 @@ AP_DECLARE(apr_status_t) ap_pregsub_ex(apr_pool_t *p, char **result, /* Forward declare */ static char x2c(const char *what); -#define IS_SLASH_OR_NUL(s) (s == '\0' || IS_SLASH(s)) +#define IS_SLASH_OR_NUL(s) (s == '\0' || AP_IS_SLASH(s)) /* * Inspired by mod_jk's jk_servlet_normalize(). @@ -504,7 +493,7 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags) int decode_unreserved = (flags & AP_NORMALIZE_DECODE_UNRESERVED) != 0; int merge_slashes = (flags & AP_NORMALIZE_MERGE_SLASHES) != 0; - if (!IS_SLASH(path[0])) { + if (!AP_IS_SLASH(path[0])) { /* Besides "OPTIONS *", a request-target should start with '/' * per RFC 7230 section 5.3, so anything else is invalid. */ @@ -545,12 +534,12 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags) } } - if (w == 0 || IS_SLASH(path[w - 1])) { + if (w == 0 || AP_IS_SLASH(path[w - 1])) { /* Collapse ///// sequences to / */ - if (merge_slashes && IS_SLASH(path[l])) { + if (merge_slashes && AP_IS_SLASH(path[l])) { do { l++; - } while (IS_SLASH(path[l])); + } while (AP_IS_SLASH(path[l])); continue; } @@ -579,7 +568,7 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags) if (w > 1) { do { w--; - } while (w && !IS_SLASH(path[w - 1])); + } while (w && !AP_IS_SLASH(path[w - 1])); } else { /* Already at root, ignore and return a failure @@ -1915,7 +1904,7 @@ static int unescape_url(char *url, const char *forbid, const char *reserved, char decoded; decoded = x2c(y + 1); if ((decoded == '\0') - || (forbid_slashes && IS_SLASH(decoded)) + || (forbid_slashes && AP_IS_SLASH(decoded)) || (forbid && ap_strchr_c(forbid, decoded))) { badpath = 1; *x = decoded; @@ -1923,7 +1912,7 @@ static int unescape_url(char *url, const char *forbid, const char *reserved, } else if ((keep_unreserved && TEST_CHAR(decoded, T_URI_UNRESERVED)) - || (keep_slashes && IS_SLASH(decoded)) + || (keep_slashes && AP_IS_SLASH(decoded)) || (reserved && ap_strchr_c(reserved, decoded))) { *x++ = *y++; *x++ = *y++; @@ -1950,7 +1939,7 @@ static int unescape_url(char *url, const char *forbid, const char *reserved, AP_DECLARE(int) ap_unescape_url(char *url) { /* Traditional */ - return unescape_url(url, SLASHES, NULL, 0); + return unescape_url(url, AP_SLASHES, NULL, 0); } AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes) { @@ -1960,7 +1949,7 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes) return unescape_url(url, NULL, NULL, 0); } else { /* reserve (do not decode) encoded slashes */ - return unescape_url(url, NULL, SLASHES, 0); + return unescape_url(url, NULL, AP_SLASHES, 0); } } AP_DECLARE(int) ap_unescape_url_ex(char *url, unsigned int flags) diff --git a/server/vhost.c b/server/vhost.c index 489c141..ee93481 100644 --- a/server/vhost.c +++ b/server/vhost.c @@ -23,6 +23,7 @@ #include "apr.h" #include "apr_strings.h" #include "apr_lib.h" +#include "apr_version.h" #define APR_WANT_STRFUNC #include "apr_want.h" @@ -182,9 +183,14 @@ static const char *get_addresses(apr_pool_t *p, const char *w_, if (!host) { return "Missing address for VirtualHost"; } +#if !APR_VERSION_AT_LEAST(1,7,0) if (scope_id) { - return "Scope ids are not supported"; + return apr_pstrcat(p, + "Scope ID in address '", w, + "' not supported with APR " APR_VERSION_STRING, + NULL); } +#endif if (!port && !wild_port) { port = default_port; } @@ -203,6 +209,17 @@ static const char *get_addresses(apr_pool_t *p, const char *w_, "Could not resolve host name %s -- ignoring!", host); return NULL; } +#if APR_VERSION_AT_LEAST(1,7,0) + if (scope_id) { + rv = apr_sockaddr_zone_set(my_addr, scope_id); + if (rv) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, APLOGNO(10103) + "Could not set scope ID %s for %pI -- ignoring!", + scope_id, my_addr); + return NULL; + } + } +#endif } /* Remember all addresses for the host */ |