Bug 35122

Summary: Apache does not accept IPv6 addresses with a scope id in the Host: header
Product: Apache httpd-2 Reporter: Henryk Pl <henryk>
Component: CoreAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: RESOLVED WONTFIX    
Severity: normal CC: masa141421356
Priority: P2    
Version: 2.0.54   
Target Milestone: ---   
Hardware: Other   
OS: other   

Description Henryk Pl 2005-05-30 16:36:11 UTC
When entering a scoped IPv6 address (e.g.
http://[fe80::23a:45ff:fe42:4aac%wlan0]/) in my browser (Galeon, Firefox, etc.)
that same address is put in the HTTP Host: header (which is correct in my
opinion). Apache then responds with a 400 Bad Request and logs "Client sent
malformed Host header" in the error log. 

The problem is in fix_hostname() in server/vhost.c:715. Before that line
apr_parse_addr_port() is called and parses the address correctly, but
    if (rv != APR_SUCCESS || scope_id) {
        goto bad;
    }
rejects it.

Reproduceable: Always
Steps to reproduce: (replace fe80::23a:45ff:fe42:4aac%wlan0 with an actual
link-local IPv6 address and the corresponding interface)
1. telnet -6 fe80::23a:45ff:fe42:4aac%wlan0 80
2. Enter 
GET / HTTP/1.1
Host: [fe80::23a:45ff:fe42:4aac%wlan0]
Connection: close

Actual result: 400 Bad Request error
Expected result: No error

Suggested fix: Remove the || scope_id on the beforementioned line.
Comment 1 Paul Querna 2005-06-03 01:09:46 UTC
Ive seen this code before, but I didn't understood why we can't accept the scope_id.

Anyone?
Comment 2 Henryk Pl 2005-06-05 05:11:00 UTC
According to the svn log this code was added by Jeff Trawick 4 years ago, so he
would be the only one to know for sure. 

After looking at more of the code my best guess is that scope ids are not
allowed in the Host: header because they are not allowed in the vhost
configuration (in get_addresses(): if (scope_id) { return "Scope ids are not
supported"; }). And they are probably not allowed in the vhost configuration
because the semantics are not obvious and/or nobody wanted to implement them.

However, that's IMHO no good reason to reject a scope id in the Host: header
with a 400 Bad Request message indicating a client error (if anything it's a
server error, so 501 Not Implemented would be more appropriate). Simply ignoring
the scope id should be acceptable as an easy fix, although not completely
correct. The correct solution (I think) would be to allow scoped addresses in
the vhost configuration and store the scope together with the IP address. Then
get the scope from the sockets of incoming requests and compare that to the
stored scope, as if it was part of the IP address (which it is, kind of).
Comment 3 Jeff Trawick 2005-06-05 15:49:43 UTC
I assumed that scope id in the IPv6 literal address notation is interesting only
to the machine where it was used, and was used to select an interface to use on
the outbound, or identify an interface on the outbound.  It is not part of the
IPv6 header after all.  So a client may indeed specify a scope id on a connect()
but it doesn't make since in a Host since the client's view of the scope isn't
interesting on the server (the server may indeed get a different scope in
sin6_scope_id when the client address is reported from accept() or getpeername()).

Based on this discussion I'm willing to assume that this understanding was
naive/incomplete/completely-ignorant/etc.  Do you have a pointer to a good
description?
Comment 4 Henryk Pl 2005-06-05 17:03:19 UTC
I'm sorry, it looks like you are right. I browsed through the RFCs: 2616
references 2396 when it comes to the Host: header which doesn't allow literal
IPv6 addresses at all, so it's probably not relevant. Then there is 4007 (pretty
new) which more or less forbids scope ids in the Host: header:

|                Hence, the format MUST be used only within a
| node and MUST NOT be sent on the wire unless every node that
| interprets the format agrees on the semantics.
 -- RFC 4007, section 11.2

I also checked some more browsers and the only one accepting scoped IPv6 address
besides the different Gecko derivatives seems to be Konqueror (at least on my
system): Konqueror does not include the scope id in the Host: header. However
Konqueror also does not include the port number if it's the default port while
Gecko seems to copy the host verbatim from the address bar.

Conclusion (and to correct my earlier statement): In principle it is not correct
of the browser to include the scope id into the Host: header. However, I still
believe that it would not hurt to simply ignore it in the server. Especially
since other likely malformed formats are already ignored, and also because it is
similar to the handling of a port number (accept, but ignore and override with
the actual port of the socket when matching) in the Host: header.
Comment 5 Masahiro Yamada 2008-11-10 19:43:43 UTC
See also:
 https://bugzilla.mozilla.org/show_bug.cgi?id=464162

Comment 6 Masahiro Yamada 2008-12-06 06:08:55 UTC
Now, this problem on Firefox is fixed on Trunk.

Comment 7 Masahiro Yamada 2009-07-04 17:01:48 UTC
Firefox 3.5 contains fix of this problem.
(fixed at 1.9.1 branch or later)
Comment 8 Nick Kew 2010-07-19 20:37:20 UTC
Seems to be a bug only in a "be liberal in what you accept" sense.  Changing this would add complexity and scope for something more serious.