diff options
author | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:17 +0100 |
---|---|---|
committer | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:17 +0100 |
commit | 9e615cb6aa4afcee97f8a1646e5a586261a7b81f (patch) | |
tree | 0e09fde2404555dc5daf167b38243b5f89c16549 /modules/proxy/mod_proxy.c | |
parent | 1acac7a6b494db24f8f58e44dab7657b6de68742 (diff) | |
download | apache2-9e615cb6aa4afcee97f8a1646e5a586261a7b81f.tar.gz |
Upstream tarball 2.2.8upstream/2.2.8
Diffstat (limited to 'modules/proxy/mod_proxy.c')
-rw-r--r-- | modules/proxy/mod_proxy.c | 106 |
1 files changed, 82 insertions, 24 deletions
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 18b554a7..de48638b 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -85,9 +85,10 @@ static const char *set_worker_param(apr_pool_t *p, * in error state, it will be retried after that timeout. */ ival = atoi(val); - if (ival < 1) - return "Retry must be at least one second"; + if (ival < 0) + return "Retry must be a positive value"; worker->retry = apr_time_from_sec(ival); + worker->retry_set = 1; } else if (!strcasecmp(key, "ttl")) { /* Time in seconds that will destroy all the connections @@ -219,12 +220,12 @@ static const char *set_worker_param(apr_pool_t *p, else worker->status &= ~PROXY_WORKER_HOT_STANDBY; } - else if (*v == 'I' || *v == 'i') { - if (mode) - worker->status |= PROXY_WORKER_IGNORE_ERRORS; - else - worker->status &= ~PROXY_WORKER_IGNORE_ERRORS; - } + else if (*v == 'I' || *v == 'i') { + if (mode) + worker->status |= PROXY_WORKER_IGNORE_ERRORS; + else + worker->status &= ~PROXY_WORKER_IGNORE_ERRORS; + } else { return "Unknown status parameter option"; } @@ -439,7 +440,9 @@ static int proxy_trans(request_rec *r) int i, len; struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts; ap_regmatch_t regm[AP_MAX_REG_MATCH]; + ap_regmatch_t reg1[AP_MAX_REG_MATCH]; char *found = NULL; + int mismatch = 0; if (r->proxyreq) { /* someone has already set up the proxy, it was possibly ourselves @@ -454,13 +457,22 @@ static int proxy_trans(request_rec *r) */ for (i = 0; i < conf->aliases->nelts; i++) { + unsigned int nocanon = ent[i].flags & PROXYPASS_NOCANON; + const char *use_uri = nocanon ? r->unparsed_uri : r->uri; if (ent[i].regex) { if (!ap_regexec(ent[i].regex, r->uri, AP_MAX_REG_MATCH, regm, 0)) { if ((ent[i].real[0] == '!') && (ent[i].real[1] == '\0')) { return DECLINED; } - found = ap_pregsub(r->pool, ent[i].real, r->uri, AP_MAX_REG_MATCH, - regm); + /* test that we haven't reduced the URI */ + if (nocanon && ap_regexec(ent[i].regex, r->unparsed_uri, + AP_MAX_REG_MATCH, reg1, 0)) { + mismatch = 1; + use_uri = r->uri; + } + found = ap_pregsub(r->pool, ent[i].real, use_uri, + AP_MAX_REG_MATCH, + (use_uri == r->uri) ? regm : reg1); /* Note: The strcmp() below catches cases where there * was no regex substitution. This is so cases like: * @@ -478,8 +490,8 @@ static int proxy_trans(request_rec *r) found = apr_pstrcat(r->pool, "proxy:", found, NULL); } else { - found = apr_pstrcat(r->pool, "proxy:", ent[i].real, r->uri, - NULL); + found = apr_pstrcat(r->pool, "proxy:", ent[i].real, + use_uri, NULL); } } } @@ -490,15 +502,31 @@ static int proxy_trans(request_rec *r) if ((ent[i].real[0] == '!') && (ent[i].real[1] == '\0')) { return DECLINED; } - + if (nocanon + && len != alias_match(r->unparsed_uri, ent[i].fake)) { + mismatch = 1; + use_uri = r->uri; + } found = apr_pstrcat(r->pool, "proxy:", ent[i].real, - r->uri + len, NULL); + use_uri + len, NULL); } } + if (mismatch) { + /* We made a reducing transformation, so we can't safely use + * unparsed_uri. Safe fallback is to ignore nocanon. + */ + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, + "Unescaped URL path matched ProxyPass; ignoring unsafe nocanon"); + } + if (found) { r->filename = found; r->handler = "proxy-server"; r->proxyreq = PROXYREQ_REVERSE; + if (nocanon && !mismatch) { + /* mod_proxy_http needs to be told. Different module. */ + apr_table_setn(r->notes, "proxy-nocanon", "1"); + } return OK; } } @@ -691,8 +719,10 @@ static int proxy_handler(request_rec *r) /* set configured max-forwards */ maxfwd = conf->maxfwd; } - apr_table_set(r->headers_in, "Max-Forwards", - apr_psprintf(r->pool, "%ld", (maxfwd > 0) ? maxfwd : 0)); + if (maxfwd >= 0) { + apr_table_set(r->headers_in, "Max-Forwards", + apr_psprintf(r->pool, "%ld", maxfwd)); + } if (r->method_number == M_TRACE) { core_server_config *coreconf = (core_server_config *) @@ -708,7 +738,7 @@ static int proxy_handler(request_rec *r) apr_table_setn(r->notes, "verbose-error-to", "*"); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: TRACE forbidden by server configuration"); - return HTTP_FORBIDDEN; + return HTTP_METHOD_NOT_ALLOWED; } /* Can't test ap_should_client_block, we aren't ready to send @@ -859,7 +889,7 @@ static int proxy_handler(request_rec *r) "If you are using a DSO version of mod_proxy, make sure " "the proxy submodules are included in the configuration " "using LoadModule.", r->uri); - access_status = HTTP_FORBIDDEN; + access_status = HTTP_INTERNAL_SERVER_ERROR; goto cleanup; } cleanup: @@ -994,6 +1024,9 @@ static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv) = apr_array_append(p, base->cookie_domains, add->cookie_domains); new->cookie_path_str = base->cookie_path_str; new->cookie_domain_str = base->cookie_domain_str; + new->ftp_directory_charset = add->ftp_directory_charset ? + add->ftp_directory_charset : + base->ftp_directory_charset; return new; } @@ -1087,6 +1120,7 @@ static const char * const apr_table_entry_t *elts; int i; int use_regex = is_regex; + unsigned int flags = 0; while (*arg) { word = ap_getword_conf(cmd->pool, &arg); @@ -1100,8 +1134,12 @@ static const char * } f = word; } - else if (!r) + else if (!r) { r = word; + } + else if (!strcasecmp(word,"nocanon")) { + flags |= PROXYPASS_NOCANON; + } else { char *val = strchr(word, '='); if (!val) { @@ -1132,6 +1170,7 @@ static const char * new = apr_array_push(conf->aliases); new->fake = apr_pstrdup(cmd->pool, f); new->real = apr_pstrdup(cmd->pool, r); + new->flags = flags; if (use_regex) { new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED); if (new->regex == NULL) @@ -1146,7 +1185,7 @@ static const char * arr = apr_table_elts(params); elts = (const apr_table_entry_t *)arr->elts; - /* Distinguish the balancer from woker */ + /* Distinguish the balancer from worker */ if (strncasecmp(r, "balancer:", 9) == 0) { proxy_balancer *balancer = ap_proxy_get_balancer(cmd->pool, conf, r); if (!balancer) { @@ -1169,6 +1208,9 @@ static const char * const char *err = ap_proxy_add_worker(&worker, cmd->pool, conf, r); if (err) return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL); + } else { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, + "worker %s already used by another worker", worker->name); } PROXY_COPY_CONF_PARAMS(worker, conf); @@ -1436,9 +1478,6 @@ static const char * proxy_server_conf *psf = ap_get_module_config(parms->server->module_config, &proxy_module); long s = atol(arg); - if (s < 0) { - return "ProxyMaxForwards must be greater or equal to zero.."; - } psf->maxfwd = s; psf->maxfwd_set = 1; @@ -1575,6 +1614,9 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg) const char *err; if ((err = ap_proxy_add_worker(&worker, cmd->pool, conf, name)) != NULL) return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL); + } else { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, + "worker %s already used by another worker", worker->name); } PROXY_COPY_CONF_PARAMS(worker, conf); @@ -1685,6 +1727,15 @@ static const char * return NULL; } +static const char *set_ftp_directory_charset(cmd_parms *cmd, void *dconf, + const char *arg) +{ + proxy_dir_conf *conf = dconf; + + conf->ftp_directory_charset = arg; + return NULL; +} + static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config) { proxy_server_conf *sconf = ap_get_module_config(s->module_config, @@ -1892,6 +1943,8 @@ static const command_rec proxy_cmds[] = "Configure Status: proxy status to one of: on | off | full"), AP_INIT_RAW_ARGS("ProxySet", set_proxy_param, NULL, RSRC_CONF|ACCESS_CONF, "A balancer or worker name with list of params"), + AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL, + RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"), {NULL} }; @@ -1978,7 +2031,12 @@ static int proxy_status_hook(request_rec *r, int flags) ap_rputs("\n\n<table border=\"0\"><tr>" "<th>SSes</th><th>Timeout</th><th>Method</th>" "</tr>\n<tr>", r); - ap_rvputs(r, "<td>", balancer->sticky, NULL); + if (balancer->sticky) { + ap_rvputs(r, "<td>", balancer->sticky, NULL); + } + else { + ap_rputs("<td> - ", r); + } ap_rprintf(r, "</td><td>%" APR_TIME_T_FMT "</td>", apr_time_sec(balancer->timeout)); ap_rprintf(r, "<td>%s</td>\n", |