From patchwork Tue Nov 18 12:40:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Simerda X-Patchwork-Id: 3784 Received: (qmail 26601 invoked by alias); 18 Nov 2014 12:40:31 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 26588 invoked by uid 89); 18 Nov 2014 12:40:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx6-phx2.redhat.com Date: Tue, 18 Nov 2014 07:40:24 -0500 (EST) From: Pavel Simerda To: libc-alpha Cc: Tomas Hozza , Petr Spacek , Alexandre Oliva , siddhesh@redhat.com, schwab@suse.de, neleai@seznam.cz Message-ID: <1593405040.320240.1416314424126.JavaMail.zimbra@redhat.com> In-Reply-To: <756749060.300961.1416308457339.JavaMail.zimbra@redhat.com> Subject: [RFC] support for trusted validating resolver configuration MIME-Version: 1.0 Hello all, the trusted and untrusted resolver configuration is still an outstanding issue for us. We are looking for a way to configure a list of trusted name servers that can be used for validation. In most cases this would be simply "localhost" or "127.0.0.1" where a local valdating resolver would be other scenarios could be supported as well. One way to achieve that is an additional directive written in /etc/resolv.conf that would say the name servers are to be trusted, another is to have an separate directive to actually list the trusted nameservers. I became interested in a different way that doesn't affect /etc/resolv.conf which is written and read by many security unaware tools. That is to create a special version of the file just for security aware tools. For now I'm using the name /etc/resolv-secure.conf. Goals: * Applications can rely on the AD flag coming from the library. - It's either cleared out or it comes from a trusted validating resolver. Solution: * When /etc/resolv-secure.conf exists, it is used instead of /etc/resolv.conf and all name servers are trusted for DNSSEC validation. Queries are sent with AD flag set, answers are passed to the application without changing the flag. * When /etc/resolv-secure.conf doesn't exist, /etc/resolv.conf is used and no servers are trusted for DNSSEC validation. Queries are preferably sent without the AD flag and the AD flags in responses are cleared out before passing them to the application. (Corner cases like unreadable /etc/resolv-secure.conf are yet to be defined.) A proof of concept patch is attached. I tried it and it worked for me. I used netresolve[1] tools to perform the testing. [1] https://sourceware.org/git/?p=netresolve.git;a=blob;f=README;hb=HEAD Advantages: * Simple logic, based on the existance of /etc/resolv-secure.conf. * Backwards compatibility for free. - Supporting software writes both resolv.conf and resolv-secure.conf and reads resolv-secure.conf falling back to resolv.conf when missing. - Other software writes resolv.conf (thus won't overwrite resolv-secure.conf) and reads resolv.conf. * Format of /etc/resolv-secure.conf is identical to that of /etc/resolv.conf. - It is easy to update security aware software to use the new file and fallback to the old one. * Easy to support in dynamic configuration tools like dnssec-trigger. - The tool simply stores its resolv.conf somewhere in /run and creates symlinks /etc/resolv.conf and /etc/resolv-secure.conf. - Any other tools will immediatly learn where the data comes from by checking the symlink target and act accordingly. Disadvantages: * A new file to look into for DNS configuration. Resources: * fedora: glibc ticket: https://bugzilla.redhat.com/show_bug.cgi?id=1164339 * fedora: c-ares ticket: https://bugzilla.redhat.com/show_bug.cgi?id=1164337 * fedora: dnssec-trigger ticket: https://bugzilla.redhat.com/show_bug.cgi?id=1165126 Cheers, Pavel From 05583564e627edbe2a8bfea7b28e6ea9732c438e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20=C5=A0imerda?= Date: Sun, 16 Nov 2014 00:28:04 +0100 Subject: [PATCH] don't blindly trust AD flag, support /etc/resolv-secure.conf --- resolv/res_init.c | 13 ++++++++++++- resolv/res_mkquery.c | 2 ++ resolv/res_query.c | 4 ++++ resolv/resolv.h | 3 ++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/resolv/res_init.c b/resolv/res_init.c index ea133f8..a063b29 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -234,7 +234,12 @@ __res_vinit(res_state statp, int preinit) { (line[sizeof(name) - 1] == ' ' || \ line[sizeof(name) - 1] == '\t')) - if ((fp = fopen(_PATH_RESCONF, "rce")) != NULL) { + bool secure = true; + const char *path; +resolvconf: + path = secure ? "/etc/resolv-secure.conf" : _PATH_RESCONF; + + if ((fp = fopen(path, "rce")) != NULL) { /* No threads use this stream. */ __fsetlocking (fp, FSETLOCKING_BYCALLER); /* read the config file */ @@ -426,6 +431,12 @@ __res_vinit(res_state statp, int preinit) { statp->nsort = nsort; #endif (void) fclose(fp); + + if (secure) + statp->trust_ad_flag = true; + } else if (secure) { + secure = false; + goto resolvconf; } if (__builtin_expect(statp->nscount == 0, 0)) { statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 1635e6a..f89935d 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -143,6 +143,8 @@ res_nmkquery(res_state statp, hp->opcode = op; hp->rd = (statp->options & RES_RECURSE) != 0; hp->rcode = NOERROR; + if (statp->trust_ad_flag) + hp->ad = 1; cp = buf + HFIXEDSZ; buflen -= HFIXEDSZ; dpp = dnptrs; diff --git a/resolv/res_query.c b/resolv/res_query.c index e4ee2a6..b1edc88 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -242,6 +242,10 @@ __libc_res_nquery(res_state statp, /* __libc_res_nsend might have reallocated the buffer. */ hp = (HEADER *) *answerp; + /* Clear untrusted AD flag. */ + if (!statp->trust_ad_flag) + hp->ad = 0; + /* We simplify the following tests by assigning HP to HP2 or vice versa. It is easy to verify that this is the same as ignoring all tests of HP or HP2. */ diff --git a/resolv/resolv.h b/resolv/resolv.h index 53c3bba..1b51e5c 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -117,7 +117,8 @@ struct __res_state { unsigned ndots:4; /* threshold for initial abs. query */ unsigned nsort:4; /* number of elements in sort_list[] */ unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */ - unsigned unused:23; + unsigned trust_ad_flag:1; /* trust AD flag from the server */ + unsigned unused:22; struct { struct in_addr addr; u_int32_t mask; -- 1.8.5.5