From bafefdd61791f916c7800f08a051a59348252405 Mon Sep 17 00:00:00 2001 From: Nick Kew Date: Sun, 28 Oct 2007 15:49:03 +0000 Subject: [PATCH] Update the patch for environment variable interpolation in ProxyPass/Reverse/etc directives: r421686, r422178, r421686, r421725 That patch stalled on wrowe's veto. This update introduces a new "interpolate" keyword to all directives affected, so should meet his concerns by adding explicit per-directive control (disabled by default). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@589371 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/mod/mod_proxy.xml | 30 ++++++++++++--- modules/proxy/mod_proxy.c | 71 ++++++++++++++++++++++------------- modules/proxy/mod_proxy.h | 1 + 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/docs/manual/mod/mod_proxy.xml b/docs/manual/mod/mod_proxy.xml index bbe6740d75..97a59438f6 100644 --- a/docs/manual/mod/mod_proxy.xml +++ b/docs/manual/mod/mod_proxy.xml @@ -574,7 +574,7 @@ expressions ProxyPass Maps remote servers into the local server URL-space ProxyPass [path] !|url [key=value - [key=value ...]] [nocanon] + [key=value ...]] [nocanon] [interpolate] server configvirtual host directory @@ -850,6 +850,14 @@ expressions removes the normal limited protection against URL-based attacks provided by the proxy.

+

The optional interpolate keyword, in combination with + ProxyPassInterpolateEnv causes the ProxyPass + to interpolate environment variables, using the syntax + ${VARNAME}. Note that many of the standard CGI-derived + environment variables will not exist when this interpolation happens, + so you may still have to resort to mod_rewrite + for complex rules.

+

When used inside a Location section, the first argument is omitted and the local directory is obtained from the ProxyPassReverse Adjusts the URL in HTTP response headers sent from a reverse proxied server -ProxyPassReverse [path] url +ProxyPassReverse [path] url +[interpolate] server configvirtual host directory @@ -950,6 +959,11 @@ proxied server because it doesn't depend on a corresponding ProxyPass directive.

+

The optional interpolate keyword, used together with + ProxyPassInterpolateEnv, enables interpolation + of environment variables specified using the format ${VARNAME}. +

+

When used inside a Location section, the first argument is omitted and the local directory is obtained from the ProxyPassReverseCookieDomain Adjusts the Domain string in Set-Cookie headers from a reverse- proxied server -ProxyPassReverseCookieDomain internal-domain public-domain +ProxyPassReverseCookieDomain internal-domain +public-domain [interpolate] server configvirtual host directory @@ -976,7 +991,8 @@ string in Set-Cookie headers.

ProxyPassReverseCookiePath Adjusts the Path string in Set-Cookie headers from a reverse- proxied server -ProxyPassReverseCookiePath internal-path public-path +ProxyPassReverseCookiePath internal-path +public-path [interpolate] server configvirtual host directory @@ -1357,7 +1373,11 @@ header for proxied requests Available in trunk only -

This directive enables reverse proxies to be dynamically +

This directive, together with the interpolate argument to + ProxyPass, ProxyPassReverse, + ProxyPassReverseCookieDomain and + ProxyPassReverseCookiePath + enables reverse proxies to be dynamically configured using environment variables, which may be set by another module such as mod_rewrite. It affects the ProxyPass, diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 5862354504..626cbd56e7 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -492,8 +492,10 @@ static apr_array_header_t *proxy_vars(request_rec *r, for (i = 0; i < hdr->nelts; ++i) { struct proxy_alias *newcopy = apr_array_push(ret); - newcopy->fake = proxy_interpolate(r, old[i].fake); - newcopy->real = proxy_interpolate(r, old[i].real); + newcopy->fake = (old[i].flags & PROXYPASS_INTERPOLATE) + ? proxy_interpolate(r, old[i].fake) : old[i].fake; + newcopy->real = (old[i].flags & PROXYPASS_INTERPOLATE) + ? proxy_interpolate(r, old[i].real) : old[i].real; } return ret; } @@ -526,9 +528,10 @@ static int proxy_trans(request_rec *r) */ for (i = 0; i < conf->aliases->nelts; i++) { - unsigned int nocanon = ent[i].flags & PROXYPASS_NOCANON; + unsigned int nocanon = ent[i].flags & PROXYPASS_NOCANON; const char *use_uri = nocanon ? r->unparsed_uri : r->uri; - if (dconf->interpolate_env == 1) { + if ((dconf->interpolate_env == 1) + && (ent[i].flags & PROXYPASS_INTERPOLATE)) { fake = proxy_interpolate(r, ent[i].fake); real = proxy_interpolate(r, ent[i].real); } @@ -545,7 +548,7 @@ static int proxy_trans(request_rec *r) if (nocanon && ap_regexec(ent[i].regex, r->unparsed_uri, AP_MAX_REG_MATCH, reg1, 0)) { mismatch = 1; - use_uri = r->uri; + use_uri = r->uri; } found = ap_pregsub(r->pool, real, use_uri, AP_MAX_REG_MATCH, (use_uri == r->uri) ? regm : reg1); @@ -581,7 +584,7 @@ static int proxy_trans(request_rec *r) if (nocanon && len != alias_match(r->unparsed_uri, ent[i].fake)) { mismatch = 1; - use_uri = r->uri; + use_uri = r->uri; } found = apr_pstrcat(r->pool, "proxy:", real, use_uri + len, NULL); @@ -1230,6 +1233,9 @@ static const char * else if (!strcasecmp(word,"nocanon")) { flags |= PROXYPASS_NOCANON; } + else if (!strcasecmp(word,"interpolate")) { + flags |= PROXYPASS_INTERPOLATE; + } else { char *val = strchr(word, '='); if (!val) { @@ -1327,31 +1333,41 @@ static const char * } -static const char * - add_pass_reverse(cmd_parms *cmd, void *dconf, const char *f, const char *r) +static const char * add_pass_reverse(cmd_parms *cmd, void *dconf, const char *f, + const char *r, const char *i) { proxy_dir_conf *conf = dconf; struct proxy_alias *new; + const char *fake; + const char *real; + const char *interp; - if (r!=NULL && cmd->path == NULL ) { - new = apr_array_push(conf->raliases); - new->fake = f; - new->real = r; - } else if (r==NULL && cmd->path != NULL) { - new = apr_array_push(conf->raliases); - new->fake = cmd->path; - new->real = f; - } else { - if ( r == NULL) + if (cmd->path == NULL) { + fake = f; + real = r; + interp = i; + if (r == NULL || !strcasecmp(r, "interpolate")) { return "ProxyPassReverse needs a path when not defined in a location"; - else + } + } + else { + fake = cmd->path; + real = f; + if (r && strcasecmp(r, "interpolate")) { return "ProxyPassReverse can not have a path when defined in a location"; + } + interp = r; } + new = apr_array_push(conf->raliases); + new->fake = fake; + new->real = real; + new->flags = interp ? PROXYPASS_INTERPOLATE : 0; + return NULL; } -static const char* - cookie_path(cmd_parms *cmd, void *dconf, const char *f, const char *r) +static const char* cookie_path(cmd_parms *cmd, void *dconf, const char *f, + const char *r, const char *interp) { proxy_dir_conf *conf = dconf; struct proxy_alias *new; @@ -1359,11 +1375,12 @@ static const char* new = apr_array_push(conf->cookie_paths); new->fake = f; new->real = r; + new->flags = interp ? PROXYPASS_INTERPOLATE : 0; return NULL; } -static const char* - cookie_domain(cmd_parms *cmd, void *dconf, const char *f, const char *r) +static const char* cookie_domain(cmd_parms *cmd, void *dconf, const char *f, + const char *r, const char *interp) { proxy_dir_conf *conf = dconf; struct proxy_alias *new; @@ -1371,7 +1388,7 @@ static const char* new = apr_array_push(conf->cookie_domains); new->fake = f; new->real = r; - + new->flags = interp ? PROXYPASS_INTERPOLATE : 0; return NULL; } @@ -1990,11 +2007,11 @@ static const command_rec proxy_cmds[] = "a virtual path and a URL"), AP_INIT_RAW_ARGS("ProxyPassMatch", add_pass_regex, NULL, RSRC_CONF|ACCESS_CONF, "a virtual path and a URL"), - AP_INIT_TAKE12("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF|ACCESS_CONF, + AP_INIT_TAKE123("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF|ACCESS_CONF, "a virtual path and a URL for reverse proxy behaviour"), - AP_INIT_TAKE2("ProxyPassReverseCookiePath", cookie_path, NULL, + AP_INIT_TAKE23("ProxyPassReverseCookiePath", cookie_path, NULL, RSRC_CONF|ACCESS_CONF, "Path rewrite rule for proxying cookies"), - AP_INIT_TAKE2("ProxyPassReverseCookieDomain", cookie_domain, NULL, + AP_INIT_TAKE23("ProxyPassReverseCookieDomain", cookie_domain, NULL, RSRC_CONF|ACCESS_CONF, "Domain rewrite rule for proxying cookies"), AP_INIT_ITERATE("ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, "A list of names, hosts or domains to which the proxy will not connect"), diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 8659602268..da2b5a7053 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -110,6 +110,7 @@ struct proxy_remote { }; #define PROXYPASS_NOCANON 0x01 +#define PROXYPASS_INTERPOLATE 0x02 struct proxy_alias { const char *real; const char *fake; -- 2.40.0