This patch adds a directive that controls how the proxy module should
handle bogus headers when reading headers... Right now, any bogus
header results in in BAD_GATEWAY... 1.3 was somewhat more resiliant.


Index: modules/proxy/mod_proxy.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/proxy/mod_proxy.c,v
retrieving revision 1.89
diff -u -r1.89 mod_proxy.c
--- modules/proxy/mod_proxy.c   8 Sep 2002 17:56:18 -0000       1.89
+++ modules/proxy/mod_proxy.c   7 Oct 2002 18:54:03 -0000
@@ -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 @@
     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 @@
     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 @@
     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 @@
     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}
 };
Index: modules/proxy/mod_proxy.h
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/proxy/mod_proxy.h,v
retrieving revision 1.84
diff -u -r1.84 mod_proxy.h
--- modules/proxy/mod_proxy.h   11 Jul 2002 18:45:22 -0000      1.84
+++ modules/proxy/mod_proxy.h   7 Oct 2002 18:54:04 -0000
@@ -195,6 +195,12 @@
     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;
 
@@ -283,5 +289,8 @@
 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, 
apr_sockaddr_t *, const char *, proxy_server_conf *, server_rec *, apr_pool_t *);
 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*/
Index: modules/proxy/proxy_util.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/proxy/proxy_util.c,v
retrieving revision 1.98
diff -u -r1.98 proxy_util.c
--- modules/proxy/proxy_util.c  25 Aug 2002 20:40:11 -0000      1.98
+++ modules/proxy/proxy_util.c  7 Oct 2002 18:54:05 -0000
@@ -433,6 +433,11 @@
     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,46 @@
 
        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. 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 +507,7 @@
 
         /* 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) { 
-- 
===========================================================================
   Jim Jagielski   [|]   [EMAIL PROTECTED]   [|]   http://www.jaguNET.com/
      "A society that will trade a little liberty for a little order
             will lose both and deserve neither" - T.Jefferson

Reply via email to