]> granicus.if.org Git - apache/commitdiff
Fix the mass vhosting security problem spotted by Lars, as in 1.3
authorTony Finch <fanf@apache.org>
Tue, 21 Dec 1999 11:33:23 +0000 (11:33 +0000)
committerTony Finch <fanf@apache.org>
Tue, 21 Dec 1999 11:33:23 +0000 (11:33 +0000)
Submitted by: Ben Hyde
Reviewed by: Tony Finch

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84349 13f79535-47bb-0310-9956-ffa450edef68

modules/http/http_protocol.c
server/vhost.c

index 0e53623bb5de9edd0bd968d3f44b871d2de956a0..e111ce3ca5e0c89138b41a3c66972c7d8cc3679c 100644 (file)
@@ -1033,7 +1033,7 @@ request_rec *ap_read_request(conn_rec *conn)
     r->status = HTTP_OK;                         /* Until further notice. */
 
     /* update what we think the virtual host is based on the headers we've
-     * now read
+     * now read. may update status.
      */
     ap_update_vhost_from_headers(r);
 
@@ -1056,6 +1056,8 @@ request_rec *ap_read_request(conn_rec *conn)
         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                       "client sent HTTP/1.1 request without hostname "
                       "(see RFC2068 section 9, and 14.23): %s", r->uri);
+    }
+    if (r->status != HTTP_OK) {
         ap_send_error_response(r, 0);
         ap_run_log_transaction(r);
         return r;
index a039a164b3eada04072873630cbcf6e2fb243276..fcb25e61d00f297f129771cd6a92692d4482cb5c 100644 (file)
@@ -658,22 +658,51 @@ void ap_fini_vhost_config(ap_context_t *p, server_rec *main_s)
  * run-time vhost matching functions
  */
 
-/* Remove :port and optionally a single trailing . from the hostname, this
- * canonicalizes it somewhat.
+/* Lowercase and remove any trailing dot and/or :port from the hostname,
+ * and check that it is sane.
  */
 static void fix_hostname(request_rec *r)
 {
-    const char *hostname = r->hostname;
-    char *host = ap_getword(r->pool, &hostname, ':');  /* get rid of port */
-    size_t l;
-
-    /* trim a trailing . */
-    l = strlen(host);
-    if (l > 0 && host[l-1] == '.') {
-        host[l-1] = '\0';
+    char *host = ap_palloc(r->pool, strlen(r->hostname) + 1);
+    const char *src;
+    char *dst;
+
+    /* check and copy the host part */
+    src = r->hostname;
+    dst = host;
+    while (*src) {
+       if (!isalnum(*src) && *src != '.' && *src != '-') {
+           if (*src == ':')
+               break;
+           else
+               goto bad;
+       } else {
+           *dst++ = *src++;
+       }
+    }
+    /* check the port part */
+    if (*src++ == ':') {
+       while (*src) {
+           if (!isdigit(*src++)) {
+               goto bad;
+           }
+       }
+    }
+    /* strip trailing gubbins */
+    if (dst > host && dst[-1] == '.') {
+       dst[-1] = '\0';
+    } else {
+       dst[0] = '\0';
     }
 
     r->hostname = host;
+    return;
+
+bad:
+    r->status = HTTP_BAD_REQUEST;
+    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+                 "Client sent malformed Host header");
+    return;
 }
 
 
@@ -876,6 +905,8 @@ void ap_update_vhost_from_headers(request_rec *r)
     /* must set this for HTTP/1.1 support */
     if (r->hostname || (r->hostname = ap_table_get(r->headers_in, "Host"))) {
        fix_hostname(r);
+       if (r->status != HTTP_OK)
+           return;
     }
     /* check if we tucked away a name_chain */
     if (r->connection->vhost_lookup_data) {