From: Jim Jagielski Date: Mon, 14 Oct 2002 14:11:24 +0000 (+0000) Subject: Haven't heard any vetoes regarding this, so might as well fold it X-Git-Tag: 2.0.44~292 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62f1105335f6458635c2e40813647c5f055b6da3;p=thirdparty%2Fapache%2Fhttpd.git Haven't heard any vetoes regarding this, so might as well fold it in. Not too happy about cluttering up the list of directives either. But, at least, it allows 2.0 to proxy stupid IIS as much as 1.3. Docs to come soon. PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@97202 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 632c728aa8c..93623a2f915 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ Changes with Apache 2.0.44 + *) Add the ProxyBadHeader directive, which gives the admin some + control on how mod_proxy should handle bogus HTTP headers from + proxied servers. This allows 2.0 to "emulate" 1.3's behavior if + desired. [Jim Jagielski] + *) Change the LDAP modules to export their symbols correctly during a Windows build. Add dsp files for Windows. Update README.ldap file for Windows build instructions. diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 58eadbf989a..1092cce7788 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -63,8 +63,6 @@ #include "apr_optional.h" -extern module AP_MODULE_DECLARE_DATA proxy_module; - #ifndef MAX #define MAX(x,y) ((x) >= (y) ? (x) : (y)) #endif @@ -499,10 +497,12 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s) ps->maxfwd_set = 0; ps->error_override = 0; ps->error_override_set = 0; - ps->preserve_host_set =0; - ps->preserve_host =0; - ps->timeout=0; - ps->timeout_set=0; + ps->preserve_host_set = 0; + ps->preserve_host = 0; + ps->timeout = 0; + ps->timeout_set = 0; + ps->badopt = bad_error; + ps->badopt_set = 0; return ps; } @@ -529,6 +529,7 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) ps->error_override = (overrides->error_override_set == 0) ? base->error_override : overrides->error_override; ps->preserve_host = (overrides->preserve_host_set == 0) ? base->preserve_host : overrides->preserve_host; ps->timeout= (overrides->timeout_set == 0) ? base->timeout : overrides->timeout; + ps->badopt = (overrides->badopt_set == 0) ? base->badopt : overrides->badopt; return ps; } @@ -914,6 +915,27 @@ static const char* return NULL; } +static const char* + set_bad_opt(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, "IsError") == 0) + psf->badopt = bad_error; + else if (strcasecmp(arg, "Ignore") == 0) + psf->badopt = bad_ignore; + else if (strcasecmp(arg, "StartBody") == 0) + psf->badopt = bad_body; + else { + return "ProxyBadHeader must be one of: " + "IsError | Ignore | StartBody"; + } + + psf->badopt_set = 1; + 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, @@ -1042,6 +1064,8 @@ static const command_rec proxy_cmds[] = AP_INIT_TAKE1("ProxyTimeout", set_proxy_timeout, NULL, RSRC_CONF, "Set the timeout (in seconds) for a proxied connection. " "This overrides the server timeout"), + AP_INIT_TAKE1("ProxyBadHeader", set_bad_opt, NULL, RSRC_CONF, + "How to handle bad header line in response: IsError | Ignore | StartBody"), {NULL} }; diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index b971ceff871..930aa97b3c1 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -195,6 +195,12 @@ typedef struct { int preserve_host_set; apr_interval_time_t timeout; apr_interval_time_t timeout_set; + enum { + bad_error, + bad_ignore, + bad_body + } badopt; /* how to deal with bad headers */ + char badopt_set; } proxy_server_conf; @@ -284,4 +290,7 @@ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, ap PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c); PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c); +/* For proxy_util */ +extern module AP_MODULE_DECLARE_DATA proxy_module; + #endif /*MOD_PROXY_H*/ diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index d989372c777..e447f98fe7e 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -433,6 +433,11 @@ PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *r int len; char *value, *end; char field[MAX_STRING_LEN]; + int saw_headers = 0; + void *sconf = r->server->module_config; + proxy_server_conf *psc; + + psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); headers_out = apr_table_make(r->pool, 20); @@ -444,19 +449,47 @@ PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *r if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */ - /* Buggy MS IIS servers sometimes return invalid headers - * (an extra "HTTP/1.0 200, OK" line sprinkled in between - * the usual MIME headers). Try to deal with it in a sensible - * way, but log the fact. - * XXX: The mask check is buggy if we ever see an HTTP/1.10 */ + /* We may encounter invalid headers, usually from buggy + * MS IIS servers, so we need to determine just how to handle + * them. We can either ignore them, assume that they mark the + * start-of-body (eg: a missing CRLF) or (the default) mark + * the headers as totally bogus and return a 500. The sole + * exception is an extra "HTTP/1.0 200, OK" line sprinkled + * in between the usual MIME headers, which is a favorite + * IIS bug. + */ + /* XXX: The mask check is buggy if we ever see an HTTP/1.10 */ if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) { - /* Nope, it wasn't even an extra HTTP header. Give up. */ - return NULL; + if (psc->badopt == bad_error) { + /* Nope, it wasn't even an extra HTTP header. Give up. */ + return NULL; + } + else if (psc->badopt == bad_body) { + /* if we've already started loading headers_out, then + * return what we've accumulated so far, in the hopes + * that they are useful. Otherwise, we completely bail. + */ + /* FIXME: We've already scarfed the supposed 1st line of + * the body, so the actual content may end up being bogus + * as well. If the content is HTML, we may be lucky. + */ + if (saw_headers) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, + "proxy: Starting body due to bogus non-header in headers " + "returned by %s (%s)", r->uri, r->method); + return headers_out; + } else { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, + "proxy: No HTTP headers " + "returned by %s (%s)", r->uri, r->method); + return NULL; + } + } } - + /* this is the psc->badopt == bad_ignore case */ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, - "proxy: Ignoring duplicate HTTP header " + "proxy: Ignoring bogus HTTP header " "returned by %s (%s)", r->uri, r->method); continue; } @@ -475,6 +508,7 @@ PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *r /* make sure we add so as not to destroy duplicated headers */ apr_table_add(headers_out, buffer, value); + saw_headers = 1; /* the header was too long; at the least we should skip extra data */ if (len >= size - 1) {