Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/log-message-tags/next-number
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10543
10544
25 changes: 25 additions & 0 deletions modules/proxy/mod_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,8 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s)
ps->id = apr_psprintf(p, "p%x", 1); /* simply for storage size */
ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */
ps->viaopt_set = 0; /* 0 means default */
ps->underscored_headers = underscored_headers_allow; /* don't introduce breaking change */
ps->underscored_headers_set = 0;
ps->req = 0;
ps->max_balancers = 0;
ps->bal_persist = 0;
Expand Down Expand Up @@ -1752,6 +1754,8 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
ps->id = (overrides->id == NULL) ? base->id : overrides->id;
ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt;
ps->viaopt_set = overrides->viaopt_set || base->viaopt_set;
ps->underscored_headers = (overrides->underscored_headers_set == 0) ? base->underscored_headers : overrides->underscored_headers;
ps->underscored_headers_set = overrides->underscored_headers_set || base->underscored_headers_set;
ps->req = (overrides->req_set == 0) ? base->req : overrides->req;
ps->req_set = overrides->req_set || base->req_set;
ps->bgrowth = (overrides->bgrowth_set == 0) ? base->bgrowth : overrides->bgrowth;
Expand Down Expand Up @@ -2577,6 +2581,25 @@ static const char*
return NULL;
}

static const char*
set_underscored_headers(cmd_parms *parms, void *dummy, const char *arg)
{
proxy_server_conf *psf =
ap_get_module_config(parms->server->module_config, &proxy_module);

if (strcasecmp(arg, "Allow") == 0)
psf->underscored_headers = underscored_headers_allow;
else if (strcasecmp(arg, "Drop") == 0)
psf->underscored_headers = underscored_headers_drop;
else if (strcasecmp(arg, "Reject") == 0)
psf->underscored_headers = underscored_headers_reject;
else
return "ProxyUnderscoredHeaders must be one of: Allow | Drop | Reject";

psf->underscored_headers_set = 1;
return NULL;
}

static const char*
set_bad_opt(cmd_parms *parms, void *dummy, const char *arg)
{
Expand Down Expand Up @@ -3066,6 +3089,8 @@ static const command_rec proxy_cmds[] =
"The default intranet domain name (in absence of a domain in the URL)"),
AP_INIT_TAKE1("ProxyVia", set_via_opt, NULL, RSRC_CONF,
"Configure Via: proxy header header to one of: on | off | block | full"),
AP_INIT_TAKE1("ProxyUnderscoredHeaders", set_underscored_headers, NULL, RSRC_CONF,
"Handling of headers with underscores to backend: allow | drop | reject"),
AP_INIT_ITERATE("ProxyErrorOverride", set_proxy_error_override, NULL, RSRC_CONF|ACCESS_CONF,
"use our error handling pages instead of the servers' we are proxying"),
AP_INIT_FLAG("ProxyPreserveHost", set_preserve_host, NULL, RSRC_CONF|ACCESS_CONF,
Expand Down
6 changes: 6 additions & 0 deletions modules/proxy/mod_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ typedef struct {
via_block,
via_full
} viaopt; /* how to deal with proxy Via: headers */
enum {
underscored_headers_allow,
underscored_headers_drop,
underscored_headers_reject
} underscored_headers;
apr_size_t recv_buffer_size;
apr_size_t io_buffer_size;
long maxfwd;
Expand All @@ -194,6 +199,7 @@ typedef struct {

unsigned int req_set:1;
unsigned int viaopt_set:1;
unsigned int underscored_headers_set:1;
unsigned int recv_buffer_size_set:1;
unsigned int io_buffer_size_set:1;
unsigned int maxfwd_set:1;
Expand Down
35 changes: 35 additions & 0 deletions modules/proxy/mod_proxy_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@ static int (*ap_proxy_clear_connection_fn)(request_rec *r, apr_table_t *headers)
static apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n,
request_rec *r, int flags, int *read);

static int filter_underscored_headers(request_rec *r, proxy_server_conf *conf)
{
const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
int i;

if (conf->underscored_headers == underscored_headers_allow)
return OK;

for (i = 0; i < hdrs_arr->nelts; i++) {
if (!hdrs[i].key) continue;
if (!ap_strchr(hdrs[i].key, '_')) continue;
if (conf->underscored_headers == underscored_headers_drop) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"dropped underscored header '%s'", hdrs[i].key);
apr_table_unset(r->headers_in, hdrs[i].key);
}
if (conf->underscored_headers == underscored_headers_reject) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(10543)
"rejected request for underscored header '%s'",
hdrs[i].key);
return HTTP_BAD_REQUEST;
}
}

return OK;
}

static const char *get_url_scheme(const char **url, int *is_ssl)
{
const char *u = *url;
Expand Down Expand Up @@ -1966,6 +1994,13 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
}
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "HTTP: serving URL %s", url);

/* check if any request header contains underscore (_),
drop such header or reject the whole request accordingly to conf
*/
if ((status = filter_underscored_headers(r, conf)) != OK) {
return status;
}

/* create space for state information */
if ((status = ap_proxy_acquire_connection(scheme, &backend,
worker, r->server)) != OK) {
Expand Down