Bug 181061

Summary: getaddrinfo in glibc can return IPv6 and IPv4 addresses of different hosts
Product: [Fedora] Fedora Reporter: Peter Bieringer <pb>
Component: glibcAssignee: Jakub Jelinek <jakub>
Status: CLOSED RAWHIDE QA Contact: Brian Brock <bbrock>
Severity: high Docs Contact:
Priority: medium    
Version: 10CC: 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
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.12) Gecko/20060202 Fedora/1.0.7-1.2.fc4 Firefox/1.0.7

Description of problem:
gethostbyname try to resolve addresses in a not expected manner, this causes timeouts during address resolving

Version-Release number of selected component (if applicable):
glibc-2.3.5-10.3

How reproducible:
Always

Steps to Reproduce:
1. create /etc/resolv.conf like
search test.example.de example.de dyndns.example.de
nameserver 127.0.0.1
2. console 1: tcpdump -n port domain
3. console 2: telnet test1    or   telnet test1.test2.example2.de


Actual Results:  Several lookups:
AAAA test1.test.example.de
AAAA test1.example.de
AAAA test1.dyndns.example.de   <- this wins before A test1.test.example.de
A test1.test.example.de
A test1.example.de
A test1.dyndns.example.de



Expected Results:  Proper order like:

AAAA test1.test.example.de
A test1.test.example.de
AAAA test1.example.de
A test1.example.de
AAAA test1.dyndns.example.de
A test1.dyndns.example.de

Additional info:

Imho this is a security issue because it can be used to distribute a not expected AAAA entry to a client in case of a dual-stack (IPv4/IPv6) environment.

Is this fixed in glibc-2.4? Can this be fixed for glibc-2.3?

BTW: this can also lead to delays for web browsing on IPv6 enabled systems (using e.g. firefox, which is IPv6 enabled now).

Comment 1 Ulrich Drepper 2006-04-30 17:08:24 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.

Comment 2 Peter Bieringer 2006-07-22 07:47:44 UTC
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!

Comment 3 Peter Bieringer 2006-07-22 11:11:41 UTC
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

Comment 4 Peter Bieringer 2006-07-22 12:40:20 UTC
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.


Comment 5 Peter Bieringer 2006-07-23 12:06:04 UTC
See also https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=190495#c29

Comment 6 Ulrich Drepper 2006-08-02 02:13:56 UTC
This is nothing libc should be concerned about.  It's entirely the completely
crappy network setup.

Comment 7 Peter Bieringer 2006-08-02 05:13:04 UTC
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!

Comment 8 Peter Bieringer 2006-08-10 17:10:01 UTC
Clarify summary to the real issue.

Comment 9 Jeroen Massar 2006-08-11 07:24:39 UTC
> 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.


Comment 10 Peter Bieringer 2006-08-11 08:28:00 UTC
Related RFC is RFC3493 "Basic Socket Interface Extensions for IPv6" section 6.1

Comment 11 Peter Bieringer 2006-08-23 09:38:34 UTC
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.

Comment 12 petrosyan 2008-03-11 00:22:28 UTC
Fedora Core 5 is no longer maintained. Is this bug still present in Fedora 7 or
Fedora 8?

Comment 13 Peter Bieringer 2008-03-11 06:26:46 UTC
Yes, behavior is still the same

Comment 14 Ulrich Drepper 2008-07-29 05:59:08 UTC
Rawhide has a new implementation which shouldn't show this behaviour.

Comment 15 Pádraig Brady 2009-01-19 14:28:46 UTC
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.

Comment 16 Peter Bieringer 2009-04-01 21:01:01 UTC
Ulrich, which version was stored in rawhide? Fedora 10 still has this issue.

Comment 17 Ulrich Drepper 2009-04-01 21:10:48 UTC
It is fixed but we had to disable the functionality because of all those broken DNS servers.

Comment 18 Peter Bieringer 2009-04-01 21:21:23 UTC
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.