Hi all,

I recently decided to add SSHFP records for my servers, since I never
memorize or write down my key fingerprints.  I learned that if I
want ssh(1) to trust these records, DNSSEC needs to be enabled for my
zone.  To validate these records, ssh(1) is using getrrsetbyname(3),
which checks if the AD (Authentic Data) flag is set in the response.

To get a response with the AD flag set, the request itself also needs
to have the AD flag set.  It turns out that getrrsetbyname(3) doesn't
set this and will therefore never get a validated response, unless the
resolver is configured to always send it, no matter what the client
requested.

It seems like unwind(8) behaves this way but it also responds with the
RRSIG records, which is extra overhead and ignored by getrrsetbyname(3).

This was mentioned a few years ago [0] and the solution suggested was
to add the RES_USE_DNSSEC to _res.options, which also makes the resolver
respond with the extra RRSIG records.

Instead, by only setting the AD flag, both the request and the response
has the same size as without the flag set.  The patch below will add
RES_USE_AD as an option to _res.options and set it by default.
This is also the default behaviour in dig(1), which I understand is a
bit different, but that sure added some confusion while debugging this.

This let you run unbound(8) or any other validating resolver on your
local network and getrrsetbyname(3) will trust it.  Do read the CAVEATS
in the manual of getrrsetbyname(3) though.

As a side note, I noticed that the default value of _res.options was the
same value as RES_DEFAULT, so I changed it to RES_DEFAULT instead, for
the sake of consistency.

Thoughts?


Yours,
Jesper Wallin

[0] https://marc.info/?t=149983843200002&r=1&w=2


Index: include/resolv.h
===================================================================
RCS file: /cvs/src/include/resolv.h,v
retrieving revision 1.22
diff -u -p -r1.22 resolv.h
--- include/resolv.h    14 Jan 2019 06:23:06 -0000      1.22
+++ include/resolv.h    17 Jul 2020 21:25:30 -0000
@@ -191,8 +191,9 @@ struct __res_state_ext {
 /* DNSSEC extensions: use higher bit to avoid conflict with ISC use */
 #define        RES_USE_DNSSEC  0x20000000      /* use DNSSEC using OK bit in 
OPT */
 #define        RES_USE_CD      0x10000000      /* set Checking Disabled flag */
+#define        RES_USE_AD      0x80000000      /* set Authentic Data flag */
 
-#define RES_DEFAULT    (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+#define RES_DEFAULT    (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH | RES_USE_AD)
 
 /*
  * Resolver "pfcode" values.  Used by dig.
Index: lib/libc/asr/asr.c
===================================================================
RCS file: /cvs/src/lib/libc/asr/asr.c,v
retrieving revision 1.64
diff -u -p -r1.64 asr.c
--- lib/libc/asr/asr.c  6 Jul 2020 13:33:05 -0000       1.64
+++ lib/libc/asr/asr.c  17 Jul 2020 21:25:30 -0000
@@ -511,7 +511,7 @@ asr_ctx_create(void)
        if ((ac = calloc(1, sizeof(*ac))) == NULL)
                return (NULL);
 
-       ac->ac_options = RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
+       ac->ac_options = RES_DEFAULT;
        ac->ac_refcount = 1;
        ac->ac_ndots = 1;
        ac->ac_family[0] = AF_INET;
Index: lib/libc/asr/res_mkquery.c
===================================================================
RCS file: /cvs/src/lib/libc/asr/res_mkquery.c,v
retrieving revision 1.13
diff -u -p -r1.13 res_mkquery.c
--- lib/libc/asr/res_mkquery.c  14 Jan 2019 06:49:42 -0000      1.13
+++ lib/libc/asr/res_mkquery.c  17 Jul 2020 21:25:30 -0000
@@ -62,6 +62,8 @@ res_mkquery(int op, const char *dname, i
                h.flags |= RD_MASK;
        if (ac->ac_options & RES_USE_CD)
                h.flags |= CD_MASK;
+       if (ac->ac_options & RES_USE_AD)
+               h.flags |= AD_MASK;
        h.qdcount = 1;
        if (ac->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC))
                h.arcount = 1;
Index: lib/libc/asr/res_send_async.c
===================================================================
RCS file: /cvs/src/lib/libc/asr/res_send_async.c,v
retrieving revision 1.39
diff -u -p -r1.39 res_send_async.c
--- lib/libc/asr/res_send_async.c       28 Sep 2019 11:21:07 -0000      1.39
+++ lib/libc/asr/res_send_async.c       17 Jul 2020 21:25:30 -0000
@@ -378,6 +378,8 @@ setup_query(struct asr_query *as, const 
                h.flags |= RD_MASK;
        if (as->as_ctx->ac_options & RES_USE_CD)
                h.flags |= CD_MASK;
+       if (as->as_ctx->ac_options & RES_USE_AD)
+               h.flags |= AD_MASK;
        h.qdcount = 1;
        if (as->as_ctx->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC))
                h.arcount = 1;
Index: lib/libc/net/res_init.3
===================================================================
RCS file: /cvs/src/lib/libc/net/res_init.3,v
retrieving revision 1.4
diff -u -p -r1.4 res_init.3
--- lib/libc/net/res_init.3     25 Apr 2020 21:06:17 -0000      1.4
+++ lib/libc/net/res_init.3     17 Jul 2020 21:25:30 -0000
@@ -206,6 +206,8 @@ uses 4096 bytes as input buffer size.
 Request that the resolver uses
 Domain Name System Security Extensions (DNSSEC),
 as defined in RFCs 4033, 4034, and 4035.
+.It Dv RES_USE_AD
+Set the Authentic Data flag on queries.
 .It Dv RES_USE_CD
 Set the Checking Disabled flag on queries.
 .El

Reply via email to