From c77e6abe3b1d3d612bcf5ce694c8c937cf031fbb Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 17 Sep 2020 11:31:43 +0000 Subject: [PATCH] mod_proxy: Add support for an optional third argument to ProxyRemote* to configure the Basic auth credentials to send to the remote proxy. (Note that credentials are always sent w/o waiting for a challenge as with proxy-chain-auth, and only Basic is supported - both of which are not exactly ideal - but better than nothing.) * modules/proxy/mod_proxy.h (struct proxy_remote): Add creds field. * modules/proxy/mod_proxy.c (proxy_handler): Pass forward proxy credentials via r->notes. (add_proxy): Take credentials and base64-encode into ->creds field if passed. (add_proxy_noregex, add_proxy_regex): Take optional creds argument. * modules/proxy/proxy_util.c (ap_proxy_determine_connection): Use proxy credentials from r->notes if available. (ap_proxy_create_hdrbrgd): Set Proxy-Authorization header from credentials in r->notes if present. PR: 37355 Github: closes #135 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1881790 13f79535-47bb-0310-9956-ffa450edef68 --- changes-entries/pr37355.txt | 3 +++ docs/manual/mod/mod_proxy.xml | 12 +++++++++++- modules/proxy/mod_proxy.c | 34 ++++++++++++++++++++++++---------- modules/proxy/mod_proxy.h | 1 + modules/proxy/proxy_util.c | 20 +++++++++++++++----- 5 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 changes-entries/pr37355.txt diff --git a/changes-entries/pr37355.txt b/changes-entries/pr37355.txt new file mode 100644 index 0000000000..3fbf5c75b4 --- /dev/null +++ b/changes-entries/pr37355.txt @@ -0,0 +1,3 @@ + *) mod_proxy: Add optional third argument for ProxyRemote, which + configures Basic authentication credentials to pass to the remote + proxy. PR 37355. [Joe Orton] diff --git a/docs/manual/mod/mod_proxy.xml b/docs/manual/mod/mod_proxy.xml index 99659a06e6..ec7c2af746 100644 --- a/docs/manual/mod/mod_proxy.xml +++ b/docs/manual/mod/mod_proxy.xml @@ -671,9 +671,10 @@ context in 2.3.3 and later. ProxyRemote Remote proxy used to handle certain requests -ProxyRemote match remote-server +ProxyRemote match remote-server [username:password] server configvirtual host +The optional third argument is usable only in httpd 2.5.1 and later.

This defines remote proxies to this proxy. match is either the @@ -707,6 +708,15 @@ ProxyRemote ftp http://ftpproxy.mydomain:8080

This option also supports reverse proxy configuration; a backend webserver can be embedded within a virtualhost URL space even if that server is hidden by another forward proxy.

+ +

An optional third argument username:password may be + given, which defines the Basic authentication credentials to pass + to the configured remote proxy. The credentials will always be + sent without first waiting for the remote proxy to send a Basic + authentication challenge. The Proxy-Chain-Auth environment + variable has no effect if this argument is used.

+
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 33060b08f2..c01cdc6436 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -1461,11 +1461,20 @@ static int proxy_handler(request_rec *r) /* handle the scheme */ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01142) "Trying to run scheme_handler against proxy"); + + if (ents[i].creds) { + apr_table_set(r->notes, "proxy-basic-creds", ents[i].creds); + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "Using proxy auth creds %s", ents[i].creds); + } + access_status = proxy_run_scheme_handler(r, worker, conf, url, ents[i].hostname, ents[i].port); + if (ents[i].creds) apr_table_unset(r->notes, "proxy-basic-creds"); + /* Did the scheme handler process the request? */ if (access_status != DECLINED) { const char *cl_a; @@ -1917,8 +1926,8 @@ static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv) return new; } -static const char * - add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, int regex) +static const char *add_proxy(cmd_parms *cmd, void *dummy, const char *f1, + const char *r1, const char *creds, int regex) { server_rec *s = cmd->server; proxy_server_conf *conf = @@ -1976,19 +1985,24 @@ static const char * new->port = port; new->regexp = reg; new->use_regex = regex; + if (creds) { + new->creds = apr_pstrcat(cmd->pool, "Basic ", + ap_pbase64encode(cmd->pool, (char *)creds), + NULL); + } return NULL; } -static const char * - add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1) +static const char *add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1, + const char *r1, const char *creds) { - return add_proxy(cmd, dummy, f1, r1, 0); + return add_proxy(cmd, dummy, f1, r1, creds, 0); } -static const char * - add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1) +static const char *add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1, + const char *r1, const char *creds) { - return add_proxy(cmd, dummy, f1, r1, 1); + return add_proxy(cmd, dummy, f1, r1, creds, 1); } PROXY_DECLARE(const char *) ap_proxy_de_socketfy(apr_pool_t *p, const char *url) @@ -3046,9 +3060,9 @@ static const command_rec proxy_cmds[] = "location, in regular expression syntax"), AP_INIT_FLAG("ProxyRequests", set_proxy_req, NULL, RSRC_CONF, "on if the true proxy requests should be accepted"), - AP_INIT_TAKE2("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF, + AP_INIT_TAKE23("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF, "a scheme, partial URL or '*' and a proxy server"), - AP_INIT_TAKE2("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF, + AP_INIT_TAKE23("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF, "a regex pattern and a proxy server"), AP_INIT_FLAG("ProxyPassInterpolateEnv", ap_set_flag_slot_char, (void*)APR_OFFSETOF(proxy_dir_conf, interpolate_env), diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 6f7d0b2b03..664ee0b0d9 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -116,6 +116,7 @@ struct proxy_remote { const char *protocol; /* the scheme used to talk to this proxy */ const char *hostname; /* the hostname of this proxy */ ap_regex_t *regexp; /* compiled regex (if any) for the remote */ + const char *creds; /* auth credentials (if any) for the proxy */ int use_regex; /* simple boolean. True if we have a regex pattern */ apr_port_t port; /* the port for this proxy */ }; diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 85af865749..7d9ea177c4 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -2562,11 +2562,15 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, * So let's make it configurable by env. * The logic here is the same used in mod_proxy_http. */ - proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization"); + proxy_auth = apr_table_get(r->notes, "proxy-basic-creds"); + if (proxy_auth == NULL) + proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization"); + if (proxy_auth != NULL && proxy_auth[0] != '\0' && - (r->user == NULL || /* we haven't yet authenticated */ - apr_table_get(r->subprocess_env, "Proxy-Chain-Auth"))) { + (r->user == NULL /* we haven't yet authenticated */ + || apr_table_get(r->subprocess_env, "Proxy-Chain-Auth") + || apr_table_get(r->notes, "proxy-basic-creds"))) { forward->proxy_auth = apr_pstrdup(conn->pool, proxy_auth); } } @@ -2798,7 +2802,8 @@ static apr_status_t send_http_connect(proxy_conn_rec *backend, nbytes = apr_snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0" CRLF, forward->target_host, forward->target_port); - /* Add proxy authorization from the initial request if necessary */ + /* Add proxy authorization from the configuration, or initial + * request if necessary */ if (forward->proxy_auth != NULL) { nbytes += apr_snprintf(buffer + nbytes, sizeof(buffer) - nbytes, "Proxy-Authorization: %s" CRLF, @@ -3741,7 +3746,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, apr_bucket *e; int do_100_continue; conn_rec *origin = p_conn->connection; - const char *fpr1; + const char *fpr1, *creds; proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_module); /* @@ -3920,6 +3925,11 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, return HTTP_BAD_REQUEST; } + creds = apr_table_get(r->notes, "proxy-basic-creds"); + if (creds) { + apr_table_mergen(r->headers_in, "Proxy-Authorization", creds); + } + /* send request headers */ headers_in_array = apr_table_elts(r->headers_in); headers_in = (const apr_table_entry_t *) headers_in_array->elts;