summaryrefslogtreecommitdiff
path: root/modules/proxy/mod_proxy.c
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:17 +0100
committerStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:17 +0100
commit9e615cb6aa4afcee97f8a1646e5a586261a7b81f (patch)
tree0e09fde2404555dc5daf167b38243b5f89c16549 /modules/proxy/mod_proxy.c
parent1acac7a6b494db24f8f58e44dab7657b6de68742 (diff)
downloadapache2-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.c106
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",