Bug 181061
Summary: | getaddrinfo in glibc can return IPv6 and IPv4 addresses of different hosts | ||
---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | Peter Bieringer <pb> |
Component: | glibc | Assignee: | Jakub Jelinek <jakub> |
Status: | CLOSED RAWHIDE | QA Contact: | Brian Brock <bbrock> |
Severity: | high | Docs Contact: | |
Priority: | medium | ||
Version: | 10 | CC: | dedourek, drepper, fweimer, jeroen, maurizio.antillon, p |
Target Milestone: | --- | Keywords: | Reopened, Security |
Target Release: | --- | ||
Hardware: | All | ||
OS: | Linux | ||
Whiteboard: | |||
Fixed In Version: | Doc Type: | Bug Fix | |
Doc Text: | Story Points: | --- | |
Clone Of: | Environment: | ||
Last Closed: | 2008-07-29 05:59:08 UTC | Type: | --- |
Regression: | --- | Mount Type: | --- |
Documentation: | --- | CRM: | |
Verified Versions: | Category: | --- | |
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
Cloudforms Team: | --- | Target Upstream Version: | |
Embargoed: |
Description
Peter Bieringer
2006-02-12 16:00:16 UTC
The gethostby* functions are deprecated. They are know to have problems like this. The solution is to use getaddrinfo and getnameinfo. At least the current telnet etc does it. If you find binaries which don't use getaddrinfo file bugs for those packages. After digging through query logs of my nameserver this issue rises up, requests triggered by postfix. So I tracked further on and found,that even "getaddrinfo" has the same bugs! Even in glibc-2.4-8 (FC5) I used the example program from http://en.wikipedia.org/wiki/Getaddrinfo 1) AAAA? min31-4-82-240-184-172.fbx.proxad.net. 2) AAAA? min31-4-82-240-184-172.fbx.proxad.net.muc.bieringer.de. (72) 3) AAAA? min31-4-82-240-184-172.fbx.proxad.net.dyndns.bieringer.de. (75) 4) AAAA? min31-4-82-240-184-172.fbx.proxad.net.domain.example. (70) 5) A? min31-4-82-240-184-172.fbx.proxad.net. (55) So this is *misordered* and can lead to a security problem. Expected lookup way: 1) AAAA? min31-4-82-240-184-172.fbx.proxad.net. 2) A? min31-4-82-240-184-172.fbx.proxad.net. (55) 3) AAAA? min31-4-82-240-184-172.fbx.proxad.net.muc.bieringer.de. (72) 4) A? min31-4-82-240-184-172.fbx.proxad.net.muc.bieringer.de. (72) 5) AAAA? min31-4-82-240-184-172.fbx.proxad.net.dyndns.bieringer.de. (75) 6) A? min31-4-82-240-184-172.fbx.proxad.net.dyndns.bieringer.de. (75) 7) AAAA? min31-4-82-240-184-172.fbx.proxad.net.domain.example. (70) 8) A? min31-4-82-240-184-172.fbx.proxad.net.domain.example. (70) This problem needs to be fixed in all affected glibc versions! Hmm, appending a trailing "." to the queried name, queries would be reduced to 2 ones: 1) AAAA? min31-4-82-240-184-172.fbx.proxad.net. 2) A? min31-4-82-240-184-172.fbx.proxad.net. (55) Can it be that this is a longstanding general problem in glibc using the resolver functions and programmers not always know about this issue? Some server programs do such lookups like: connect $client-ip $client-name = getnameinfo($client-ip) @client-ip-list = getaddrinfo($client-name) If programmer forgot to append a trailing "." to $client-name, such unwanted lookups would be done. The correct way would be: @client-ip-list = getaddrinfo($client-name . ".") I don't believe that any programmer expect the use of search suffices from /etc/resolv.conf in double-reverse lookups. This can lead to interesting scenarios especially in IPv6 enabled environments. Administrator of domains listed in search suffices in /etc/resolv.conf can fake addresses. Let's look into my example: 1) client 82-240-184-172 connects 2) server does a PTR lookup and get min31-4-82-240-184-172.fbx.proxad.net. 3) server (currently) does now a AAAA lookup for min31-4-82-240-184-172.fbx.proxad.net.domain.example. 4) DNS administrator of domain.example is free to provide (faked) information, e.g. via a catch-all or autogenerated In postfix, this lead e.g. to Jul 22 13:13:28 *** postfix/smtpd[27219]: warning: 85.106.187.176: address not listed for hostname dsl85-106-48048.ttnet.net.tr If A lookup didn't receive any result. Tryout for yourself, add "ipv6.bieringer.de" to your search prefices in /etc/resolv.conf on a postfix server system (perhaps other servers are affected, too). The small test program ends with an error: $ ./tgetaddrinfo min31-4-82-240-184-172.fbx.proxad.net error using getnameinfo: ai_family not supported It's simple implementation doesn't expect IPv6 addresses at all So, now I've setup the proper related DNS zone and found, that even "telnet" is not working like expected. Order of tried addresses is wrong. /etc/resolv.conf contains: search 1.getaddrinfo1.bieringer.de 2.getaddrinfo.bieringer.de 3.getaddrinfo.bieringer.de 4.getaddrinfo.bieringer.de Zone contains (feel free to use it for testing). $ dig +short axfr getaddrinfo.bieringer.de @ns.bieringer.de ns.bieringer.de. hostmaster.bieringer.de. 2006072201 86400 7200 2592000 3600 ns.bieringer.de. "*.1.getaddrinfo.bieringer.de has (only) a TXT record" "*.2.getaddrinfo.bieringer.de has AAAA and a TXT record" fec0::2 "*.3.getaddrinfo.bieringer.de has A and a TXT record" 127.0.0.3 "*.4.getaddrinfo.bieringer.de has A, AAAA and a TXT record" fec0::4 127.0.0.4 ns.bieringer.de. hostmaster.bieringer.de. 2006072201 86400 7200 2592000 3600 For local tests add IPv6 addresses here: # for i in 1 2 3 4; do ip addr add fec0::$i dev lo; done $ telnet test.unknown Trying 127.0.0.3... telnet: connect to address 127.0.0.3: Connection refused Trying fec0::2... telnet: connect to address fec0::2: Connection refused This means "telnet" tries to connect 1) test.unknown.3.getaddrinfo.bieringer via IPv4 2) test.unknown.2.getaddrinfo.bieringer via IPv6 This are different hosts and makes no sense, this can be a security issue! I believe now that the resolver implementation and the use in programs lacks of proper (and expected) way of resolving addresses in IPv4/IPv6 environments. This is nothing libc should be concerned about. It's entirely the completely crappy network setup. No, it isn't caused by a crappy network setup! But perhaps I have it not described so clearly that other would understand it before testing byself. Here another try in other words, what happen with current glibc: Starting point: a client wants to connect to "www.redhat.com" /etc/resolv.conf contains search intranet.domain.example domain.example A) IPv4-only setup: ------------------- Following queries were made: v4-1) A www.redhat.com. results usually in 66.187.224.150 in case of no result, next query would be made: v4-2) A www.redhat.com.intranet.domain.example. in case of no result, next query would be made: v4-3) A www.redhat.com.domain.example. no result: client gets no IPv4 address, can't connect Usual result: client gets A 66.187.224.150 (www.redhat.com) B) Mixed IPv4/IPv6 setup ------------------------ First, IPv6 lookups were done: v6-1) AAAA www.redhat.com. ususally no result, because Red Had doesn't provide a AAAA record, so next query would be made: v6-2) AAAA www.redhat.com.intranet.domain.example. in case of no result, next query would be made: v6-3) AAAA www.redhat.com.domain.example. no result: client gets no IPv6 address for now Now independend IPv4 lookups were done: v4-1) A www.redhat.com. results usually in 66.187.224.150 Usual result: client gets A 66.187.224.150 (www.redhat.com) C) Mixed IPv4/IPv6 setup, intranet.domain.example contains a AAAA entry for catch-all or at least for www.redhat.com.intranet.domain.example ------------------------ First, IPv6 lookups were done: v6-1) AAAA www.redhat.com. ususally no result, because Red Had doesn't provide a AAAA record, so next query would be made: v6-2) AAAA www.redhat.com.intranet.domain.example. results (suddenly) in e.g. fec0::1 Now independend IPv4 lookups were done: v4-1) A www.redhat.com. results in 66.187.224.150 Usual result: client gets AAAA fec0::1 (www.redhat.com.intranet.domain.example) A 66.187.224.150 (www.redhat.com) And THIS result is faulty and may not happen. If client now prefers IPv6 addresses for connect, it definitly connects to the wrong host. Note also that in every connect to at least an external host results in an AAAA lookup to the DNS server of intranet.domain.example, which is additional a privacy issue! Clarify summary to the real issue. > The gethostby* functions are deprecated. Then wrap them by letting them call getaddrinfo(). That saves all the issues, even having to port all the 'old' code over to the new functions. Altough it would be better indeed as then maybe they also get support for AAAA/A handling all of a sudden, or better even AF independency. > This is nothing libc should be concerned about. It's entirely the completely crappy network setup. Nopes, this is because of the crappy code in libc. It is not following the RFC. It should do: for $dom in $searchlist { if ($res = lookup($host.$dom, "AAAA")) return $res; if ($res = lookup($host.$dom, "A")) return $res; } and *NOT* for $dom in $searchlist { if ($res = lookup($host.$dom, "AAAA")) return $res; } for $dom in $searchlist { if ($res = lookup($host.$dom, "A")) return $res; } Please fix/correct this. Related RFC is RFC3493 "Basic Socket Interface Extensions for IPv6" section 6.1 See also discussions users: http://www.mail-archive.com/users@ipv6.org/msg02355.html ff usagi-users: http://www.linux-ipv6.org/ml/usagi-users/msg03690.html ff All of the replies tell me, that is is a bug and also interesting, that in *BSD it was already fixed some time ago. Fedora Core 5 is no longer maintained. Is this bug still present in Fedora 7 or Fedora 8? Yes, behavior is still the same Rawhide has a new implementation which shouldn't show this behaviour. Thanks for ignoring this issue for 2.5 years Ulrich. Were I see it manifested is with: clients ----- local DNS server --------- internet If the clients with domain "whatever.net" query "host", then the query order that was done is host.whatever.net IN AAAA host IN AAAA host.whatever.net IN A This will usually just be inefficient. If however the link to the internet is down, then the local DNS server will wait a long time trying to resolve the second query above. Ulrich, which version was stored in rawhide? Fedora 10 still has this issue. It is fixed but we had to disable the functionality because of all those broken DNS servers. Is there a toggle to enable it on a particular system. BTW: is there also an resolver option available which *prohibits* the use of search domains in case of dots >= n are in the name? This would be very helpful. |