diff -rU 10 httpd-2.4.33/modules/mappers/mod_alias.c httpd-2.4.33-patched/modules/mappers/mod_alias.c --- httpd-2.4.33/modules/mappers/mod_alias.c 2018-02-13 23:43:36.000000000 +0000 +++ httpd-2.4.33-patched/modules/mappers/mod_alias.c 2018-07-07 16:06:47.270120336 +0100 @@ -46,20 +46,21 @@ } alias_entry; typedef struct { apr_array_header_t *aliases; apr_array_header_t *redirects; } alias_server_conf; typedef struct { unsigned int alias_set:1; unsigned int redirect_set:1; + apr_array_header_t *aliases; apr_array_header_t *redirects; const ap_expr_info_t *alias; char *handler; const ap_expr_info_t *redirect; int redirect_status; /* 301, 302, 303, 410, etc */ } alias_dir_conf; module AP_MODULE_DECLARE_DATA alias_module; static char magic_error_value; @@ -72,20 +73,21 @@ a->aliases = apr_array_make(p, 20, sizeof(alias_entry)); a->redirects = apr_array_make(p, 20, sizeof(alias_entry)); return a; } static void *create_alias_dir_config(apr_pool_t *p, char *d) { alias_dir_conf *a = (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf)); + a->aliases = apr_array_make(p, 2, sizeof(alias_entry)); a->redirects = apr_array_make(p, 2, sizeof(alias_entry)); return a; } static void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv) { alias_server_conf *a = (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf)); alias_server_conf *base = (alias_server_conf *) basev; alias_server_conf *overrides = (alias_server_conf *) overridesv; @@ -95,109 +97,128 @@ return a; } static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv) { alias_dir_conf *a = (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf)); alias_dir_conf *base = (alias_dir_conf *) basev; alias_dir_conf *overrides = (alias_dir_conf *) overridesv; + a->aliases = apr_array_append(p, overrides->aliases, base->aliases); a->redirects = apr_array_append(p, overrides->redirects, base->redirects); a->alias = (overrides->alias_set == 0) ? base->alias : overrides->alias; a->handler = (overrides->alias_set == 0) ? base->handler : overrides->handler; a->alias_set = overrides->alias_set || base->alias_set; a->redirect = (overrides->redirect_set == 0) ? base->redirect : overrides->redirect; a->redirect_status = (overrides->redirect_set == 0) ? base->redirect_status : overrides->redirect_status; a->redirect_set = overrides->redirect_set || base->redirect_set; return a; } /* need prototype for overlap check */ static int alias_matches(const char *uri, const char *alias_fakename); -static const char *add_alias_internal(cmd_parms *cmd, void *dummy, +static const char *add_alias_internal(cmd_parms *cmd, alias_dir_conf *dirconf, const char *fake, const char *real, int use_regex) { + alias_entry *new; server_rec *s = cmd->server; - alias_server_conf *conf = ap_get_module_config(s->module_config, - &alias_module); - alias_entry *new = apr_array_push(conf->aliases); - alias_entry *entries = (alias_entry *)conf->aliases->elts; - int i; + alias_server_conf *serverconf = ap_get_module_config(s->module_config, + &alias_module); /* XXX: real can NOT be relative to DocumentRoot here... compat bug. */ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); if (err != NULL) { return err; } - if (use_regex) { - new->regexp = ap_pregcomp(cmd->pool, fake, AP_REG_EXTENDED); - if (new->regexp == NULL) - return "Regular expression could not be compiled."; - new->real = real; - } - else { - /* XXX This may be optimized, but we must know that new->real - * exists. If so, we can dir merge later, trusing new->real - * and just canonicalizing the remainder. Not till I finish - * cleaning out the old ap_canonical stuff first. - */ - new->real = real; - } - new->fake = fake; - new->handler = cmd->info; - /* check for overlapping (Script)Alias directives * and throw a warning if found one */ if (!use_regex) { - for (i = 0; i < conf->aliases->nelts - 1; ++i) { - alias_entry *alias = &entries[i]; + int num_server_elts = serverconf->aliases->nelts; + int num_dir_elts = dirconf->aliases->nelts; + int total_elts = num_server_elts + num_dir_elts; + int i; + + for (i = 0; i < total_elts; ++i) { + alias_entry *alias; + if (i < num_server_elts) { + alias = &serverconf->aliases->elts[i]; + } + else { + alias = &dirconf->aliases->elts[i - num_server_elts]; + } if ( (!alias->regexp && alias_matches(fake, alias->fake) > 0) || (alias->regexp && !ap_regexec(alias->regexp, fake, 0, NULL, 0))) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00671) "The %s directive in %s at line %d will probably " "never match because it overlaps an earlier " "%sAlias%s.", cmd->cmd->name, cmd->directive->filename, cmd->directive->line_num, alias->handler ? "Script" : "", alias->regexp ? "Match" : ""); break; /* one warning per alias should be sufficient */ } } } + /* Add a new entry for the alias in either the server or per-directory + * (including e.g. section) configuration, as appropriate. + */ + if (cmd->path) { + new = apr_array_push(dirconf->aliases); + } + else { + new = apr_array_push(serverconf->aliases); + } + + if (use_regex) { + new->regexp = ap_pregcomp(cmd->pool, fake, AP_REG_EXTENDED); + if (new->regexp == NULL) + return "Regular expression could not be compiled."; + new->real = real; + } + else { + /* XXX This may be optimized, but we must know that new->real + * exists. If so, we can dir merge later, trusing new->real + * and just canonicalizing the remainder. Not till I finish + * cleaning out the old ap_canonical stuff first. + */ + new->real = real; + } + new->fake = fake; + new->handler = cmd->info; + return NULL; } -static const char *add_alias(cmd_parms *cmd, void *dummy, const char *fake, +static const char *add_alias(cmd_parms *cmd, void *dirconfv, const char *fake, const char *real) { + alias_dir_conf *dirconf = (alias_dir_conf *) dirconfv; if (real) { - return add_alias_internal(cmd, dummy, fake, real, 0); + return add_alias_internal(cmd, dirconf, fake, real, 0); } else { - alias_dir_conf *dirconf = (alias_dir_conf *) dummy; - const char *err = ap_check_cmd_context(cmd, NOT_IN_DIRECTORY|NOT_IN_FILES); if (err != NULL) { return err; } if (!cmd->path) { return "Alias must have two arguments when used globally"; } @@ -211,24 +232,24 @@ } dirconf->handler = cmd->info; dirconf->alias_set = 1; return NULL; } } -static const char *add_alias_regex(cmd_parms *cmd, void *dummy, +static const char *add_alias_regex(cmd_parms *cmd, void *dirconfv, const char *fake, const char *real) { - return add_alias_internal(cmd, dummy, fake, real, 1); + return add_alias_internal(cmd, (alias_dir_conf *) dirconfv, fake, real, 1); } static const char *add_redirect_internal(cmd_parms *cmd, alias_dir_conf *dirconf, const char *arg1, const char *arg2, const char *arg3, int use_regex) { alias_entry *new; server_rec *s = cmd->server; alias_server_conf *serverconf = ap_get_module_config(s->module_config, @@ -598,29 +619,44 @@ } return NULL; } static int translate_alias_redir(request_rec *r) { ap_conf_vector_t *sconf = r->server->module_config; alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module); + void *dconf = r->per_dir_config; + alias_dir_conf *dirconf = + (alias_dir_conf *) ap_get_module_config(dconf, &alias_module); char *ret; int status; if (r->uri[0] != '/' && r->uri[0] != '\0') { return DECLINED; } + /* Look for matching redirections in the following order: + * - The whole- redirect in the that is relevant to + * this request, if there is one. + * - An unconditional server / vhost redirect. + * - A per-directory redirect at the top-level for the server / vhost, + * which may have come from a conditional section -- we only expect + * that much to have been merged into r->per_dir_config at this point, + * since we are still translating URLs and mapping them to the file + * system. + */ if ((ret = try_redirect(r, &status)) != NULL || (ret = try_alias_list(r, serverconf->redirects, 1, &status)) + != NULL + || (ret = try_alias_list(r, dirconf->redirects, 1, &status)) != NULL) { if (ret == PREGSUB_ERROR) return HTTP_INTERNAL_SERVER_ERROR; if (ap_is_HTTP_REDIRECT(status)) { if (ret[0] == '/') { char *orig_target = ret; ret = ap_construct_url(r->pool, ret, r); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673) "incomplete redirection target of '%s' for " @@ -640,22 +676,34 @@ */ if (r->args && !ap_strchr(ret, '?')) { ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL); } apr_table_setn(r->headers_out, "Location", ret); } } return status; } + /* Look for matching aliases in the following order: + * - The whole- alias in the that is relevant to this + * request, if there is one. + * - An unconditional server / vhost alias. + * - A per-directory alias at the top-level for the server / vhost, + * which may have come from a conditional section -- we only expect + * that much to have been merged into r->per_dir_config since at this + * point we are translating URLs, before mapping to the file system can + * occur. + */ if ((ret = try_alias(r)) != NULL || (ret = try_alias_list(r, serverconf->aliases, 0, &status)) + != NULL + || (ret = try_alias_list(r, dirconf->aliases, 0, &status)) != NULL) { r->filename = ret; return OK; } return DECLINED; } static int fixup_redir(request_rec *r) {