This is the mail archive of the mailing list for the glibc project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] support for trusted validating resolver configuration

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


 * Applications can rely on the AD flag coming from the library.
    - It's either cleared out or it comes from a trusted validating resolver.


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



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


 * A new file to look into for DNS configuration.


 * fedora: glibc ticket:
 * fedora: c-ares ticket:
 * fedora: dnssec-trigger ticket:


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;
+	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;
 	    (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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]