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);
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;
* 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;
}
/* 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) {