OpenSSH calls getrrsetbyname() in dns.c:verify_host_key_dns().
It then checks for RRSET_VALIDATED, which is only set if the DNS response
has the 'ad' attribute set.

getrrsetbyname() in turn uses res_.* to do DNS requests, but doesn't set
RES_USE_DNSSEC when doing so.
Thus the DNS query that goes out does not have the 'ad' bit set, causing
the response too to not have 'ad' set.

>From my looking at the call stack there's actually no way for OpenSSH, or
the user via env or /etc/resolv.conf, to set RES_USE_DNSSEC.

It seems the unwind DNS server *unconditionally* returns with 'ad' set, so
it works if (and only if?) unwind is the server queried. This seems like a
bug, and it should probably work with all DNS servers (e.g. 8.8.8.8[3]).

I believe that the fix here should be:

                        else if (!strcmp(tok[i], "dnssec"))
                                ac->ac_options |= RES_USE_DNSSEC;

                        else if (!strcmp(tok[i], "edns0"))
                                ac->ac_options |= RES_USE_EDNS0;


[1]
https://cvsweb.openbsd.org/src/usr.bin/ssh/dns.c?rev=1.41&content-type=text/x-cvsweb-markup
[2]
https://cvsweb.openbsd.org/src/lib/libc/asr/asr.c?rev=1.66&content-type=text/x-cvsweb-markup
[3] I realize that the path from the recursive resolver to the machine must
be secure. I'm using 8.8.8.8 as an example.
https://serverfault.com/questions/1063853/sshfp-not-working

-- 
typedef struct me_s {
 char name[]      = { "Thomas Habets" };
 char email[]     = { "tho...@habets.se <tho...@habets.pp.se>" };
 char kernel[]    = { "Linux" };
 char *pgpKey[]   = { "http://www.habets.pp.se/pubkey.txt"; };
 char pgp[] = { "9907 8698 8A24 F52F 1C2E  87F6 39A4 9EEA 460A 0169" };
 char coolcmd[]   = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;

Reply via email to