Bug 199680

Summary: getaddrinfo in glibc can return IPv6 and IPv4 addresses of different hosts
Product: Red Hat Enterprise Linux 4 Reporter: Peter Bieringer <pb>
Component: glibcAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 4.0CC: drepper, fweimer
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2006-07-26 01:03:18 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-07-21 12:04:33 UTC
+++ This bug was initially created as a clone of Bug #181061 +++

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).

-- Additional comment from drepper on 2006-04-30 13:08 EST --
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.

+++ end of cloning

During investigating the query log of my DNS server I found that postfix uses
this deprecated functions.

postfix:
Jul 21 14:01:59 ***** postfix/smtpd[25451]: connect from
81-202-107-187.user.ono.com[81.202.107.187]
Jul 21 14:02:01 ***** postfix/smtpd[25451]: NOQUEUE: reject: RCPT from
81-202-107-187.user.ono.com[81.202.107.187]: 554 Service unavailable; Client
host [81.202.107.187] blocked using dynablock.njabl.org; Dynamic/Residential IP
range listed by NJABL dynablock - http://njabl.org/dynablock.html;
from=<cyayliddell> to=<mailman> proto=SMTP
helo=<goldwag.com>
Jul 21 14:02:01 ***** postfix/smtpd[25451]: lost connection after RCPT from
81-202-107-187.user.ono.com[81.202.107.187]

named:
Jul 21 14:01:59.391 queries: client ******#55479: query:
81-202-107-187.user.ono.com.bieringer.de IN AAAA

# grep ^search /etc/resolv.conf
search bieringer.de

Used version: postfix-2.2.10 (rebuilded with upgraded sources).

Will notify postfix-devel also about this problem.

Comment 1 Peter Bieringer 2006-07-22 07:50:43 UTC
See here for FC5, getnameinfo resolves addresses in not expecting order, not a
postfix problem:

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=181061

Comment 2 Peter Bieringer 2006-07-22 07:51:24 UTC
Affected glibc version here: glibc-2.3.4-2.19

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

Comment 4 Ulrich Drepper 2006-07-26 01:03:18 UTC
The behaviour wrt to the search path hasn't changed.  Ever, I think.  I see
nothing wrong.  If the resolv.conf file is so dangerously written it's not up to
the implementation to protect the user.

getaddrinfo returns addresses according to the sorting criteria.  It's up to the
application to use the values correctly.

If you ever had a point (which isn't at all obvious from all that nonsense in
the earlier comments) and it is not based on your opinion (like, how the search
path should be handled) make it.

Comment 5 Peter Bieringer 2006-07-26 06:21:29 UTC
Sure you read my comment
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=190495#c29, it need some
time by me to detect from the seen DNS queries in wrong order, what really
causes the problem. It's the lookup mechanism itself. Like mentionend in the
other bugzilla entry, current version works like:

for $suffix in ("", searchsuffices(/etc/resolv.conf)) {
 $result_aaaa = lookup(AAAA,$host.$suffix)
 if (defined $result_aaaa) {
   break;
 };
};
for $suffix in ("", searchsuffices(/etc/resolv.conf)) {
 $result_a = lookup(A, $host.$suffix)
 if ($defined result_a) {
   break;
 };
};
sortresults($result_a, $result_aaaa)


/etc/resolv.conf files usually contain for internal hosts like:

domain intranet.domain.example
search intranet.domain.example domain.example

So in IPv4/IPv6 enabled environments if ever client prefers IPv6 connect, it
takes the first AAAA result from getaddrinfo.

Current behavior leads during getaddrinfo to lookups:
AAAA www.redhat.com.intranet.domain.example.
AAAA www.redhat.com.domain.example.
AAAA www.redhat.com.
A www.redhat.com.

If DNS administrator administrate at least intranet.domain.example and add a
dedicated entry for "www.redhat.com.intranet.domain.example." or a catch-all,
and client IPv6-enabled, administrator can control to deliver a wrong IPv6
address to clients.

If implementation is like

for $suffix in ("", searchsuffices(/etc/resolv.conf)) {
 $result_aaaa = lookup(AAAA,$host.$suffix)
 $result_a = lookup(A, $host.$suffix)
 if (defined $result_aaaa || $defined result_a) {
   break;
 };
}
sortresults($result_a, $result_aaaa)

such can only happen, if www.redhat.com neither provides an A nor an AAAA record
at all, which results in the same behavior of current IPv4-only environments.

Should I open a new bug to track this issue with a better topic like
"getaddrinfo can return addresses of different hosts in case of IPv4 and IPv6
and search prefices are used"?

Since IPv6 implementation was added to glibc, it's definitly a behavior change.

BTW: your comment "It's up to the application to use the values correctly" is
easy written, but how should application know, that the IPv6 address returned by
getaddrinfo is from a different hostname lookup than the IPv4 one.

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

Comment 7 Peter Bieringer 2006-08-11 08:29:39 UTC
See also comment from Jeroen Massar in
https://bugzilla.redhat.com/bugzilla/process_bug.cgi#c9, which mention, that
current implementation is not according RFC.

Comment 8 Peter Bieringer 2006-08-11 08:31:14 UTC
BTW: is this bug locked? I can't reopen it, but I thought I am the owner...

Comment 9 Peter Bieringer 2006-08-11 08:32:36 UTC
Grmm, can one fix bugzilla also to rewrite URLs proper after submission...here
the correct one: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=181061#c9

Comment 12 Peter Bieringer 2006-08-23 09:38:29 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 13 Peter Bieringer 2006-08-26 17:43:47 UTC
Just note how on an IPv6 enabled Microsoft Windows XP SP2 works:

scenario:
additional search domains: 2.getaddrinfo.bieringer.de  3.getaddrinfo.bieringer.de

telnet www.redhat.com 80

triggers following lookups:

AAAA? www.redhat.com. (32)
AAAA? www.redhat.com.2.getaddrinfo.bieringer.de. (59)
 results in  www.redhat.com.2.getaddrinfo.bieringer.de. AAAA fec0::2 (148)
A? www.redhat.com. (32)
 results in www.redhat.com. A 209.132.177.50 (150)
 
While also XP starts not needed query for AAAA
www.redhat.com.2.getaddrinfo.bieringer.de. it is smart enough to give "A
209.132.177.50" a precedence and connects to 209.132.177.50 port 80.

There must be a "smart" mechanism, because it does normally also prefer IPv6
instead of IPv4 which can be easily tested executing "telnet www.bieringer.de 80".

Linux with current glibc would connect to fec0::2 port 80

So now Linux would have a different behavior than *BSD and Microsoft Windows XP.

Comment 15 ritz 2006-08-29 16:18:43 UTC
* From solaris man pages

SunOS 5.10          Last change: 16 Mar 2004  
Sockets Library Functions                    getaddrinfo(3SOCKET)

     AAAA  records  and  A records, and getaddrinfo() returns the
     combined results of both queries. Any IPv4  addresses  found
     are returned as IPv4-mapped IPv6 addresses.
     ...
    AF_INET6 addresses returned by the fourth argument of getad-
     drinfo() are ordered according to the algorithm described in
     RFC 3484, Default Address Selection  for  Internet  Protocol
     version  6 (IPv6). The addresses are ordered using a list of
     pair-wise comparison rules which are applied in order. If  a
     rule determines that one address is better than another, the
     remaining rules are irrelevant to the  comparison  of  those
     two  addresses. If two addresses are equivalent according to
     one rule, the remaining rules  act  as  a  tie-breaker.  The
     address  ordering  list of pair-wise comparison rules follow


Comment 16 ritz 2006-08-29 16:19:55 UTC
Additional notes : http://www.bieringer.de/linux/IPv6/getaddrinfo/index.html