#include "apr_optional.h"
-extern module AP_MODULE_DECLARE_DATA proxy_module;
-
#ifndef MAX
#define MAX(x,y) ((x) >= (y) ? (x) : (y))
#endif
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;
}
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;
}
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,
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}
};
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);
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;
}
/* 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) {