Dear OpenSSH Developers, I'm a member of the Debian System Administration (DSA) team. [1] We manage the Debian Projects computing infrastructure. Recently, DSA had the opportunity to address a member's request that we begin using certificates to authenticate Debian Project machines to ssh clients. We provided a lengthy reply, the summary of which is "we publish SSHFP records; use VerifyHostKeyDNS; set up a local caching resolver to avoid MITM attacks". That said, it seems rather cumbersome to have users install a local caching resolver in order to secure the last mile of DNS queries (who trusts their ISP, after all), so we postulated whether it would be possible to modify openssh such that the ssh client could perform the queries itself. It turns out that this is quite straightforward to implement (see preliminary patch, attached), entirely because you have have well encapsulated the DNS query code. Since we are quite concerned that our project members (let alone our general user population) aren't managing their known_hosts in a secure or timely manner, we are keen on using SSHFP records .. but only if the DNSSEC last mile issue can be addressed in a relatively easy way for users. We propose that openssh be modified as follows: (1) introduce a new ssh_config directive: UnboundConfigurationFile (2) modify getrrsetbyname() such that, if UnboundConfigurationFile is set, then the unbound resolver is used; if not, then libc (3) provide a default unbound configuration in /etc/ssh/ssh_unbound_conf In this way, the standard mode of operation for ssh remains unchanged by default. Users who would like to use SSHFP records in a secure manner would set the configuration directive. Please find attached a preliminary patch that modifies getrrsetbyname() to use libunbound rather than libc. We have proposed [2] this modification to the Debian openssh package maintainers. Knowing that they (and we, too, frankly) would prefer the modification to be adopted by upstream, I've subscribed to the openssh-unix-dev list to begin the discussion (I've carbon copied my DSA colleagues and the openssh package maintainers so that they are aware). If there is interest in this proposal, I would be pleased to work with you to complete the patch. (In the meantime, I'm using openssh patched with libunbound on my macbook since OS/X's libc doesn't support DNSSEC.) Thanks for your consideration, Luca Filipozzi [1] http://www.debian.org/intro/organization [2] http://lists.debian.org/debian-ssh/2012/05/msg00004.html -- Luca Filipozzi Member, Debian System Administration Team
diff -ru openssh-5.9p1/openbsd-compat/getrrsetbyname.c openssh-5.9p1-new/openbsd-compat/getrrsetbyname.c --- openssh-5.9p1/openbsd-compat/getrrsetbyname.c 2009-07-12 18:38:23.000000000 -0700 +++ openssh-5.9p1-new/openbsd-compat/getrrsetbyname.c 2012-05-08 10:24:12.000000000 -0700 @@ -45,6 +45,7 @@ /* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */ +#include <unbound.h> #include "includes.h" #ifndef HAVE_GETRRSETBYNAME @@ -195,7 +196,8 @@ struct rdatainfo *rdata; int length; unsigned int index_ans, index_sig; - u_char answer[ANSWER_BUFFER_SIZE]; + struct ub_ctx *ub_ctx = NULL; + struct ub_result *ub_result; /* check for invalid class and type */ if (rdclass > 0xffff || rdtype > 0xffff) { @@ -215,41 +217,37 @@ goto fail; } - /* initialize resolver */ - if ((_resp->options & RES_INIT) == 0 && res_init() == -1) { + /* create context */ + ub_ctx = ub_ctx_create(); + if (!ub_ctx) { result = ERRSET_FAIL; goto fail; } -#ifdef DEBUG - _resp->options |= RES_DEBUG; -#endif /* DEBUG */ - -#ifdef RES_USE_DNSSEC - /* turn on DNSSEC if EDNS0 is configured */ - if (_resp->options & RES_USE_EDNS0) - _resp->options |= RES_USE_DNSSEC; -#endif /* RES_USE_DNSEC */ - - /* make query */ - length = res_query(hostname, (signed int) rdclass, (signed int) rdtype, - answer, sizeof(answer)); - if (length < 0) { - switch(h_errno) { - case HOST_NOT_FOUND: - result = ERRSET_NONAME; - goto fail; - case NO_DATA: - result = ERRSET_NODATA; - goto fail; - default: - result = ERRSET_FAIL; - goto fail; - } + /* load unbound configuration : FIXME - filename */ + if ((result = ub_ctx_config(ub_ctx, "/opt/local/etc/unbound/unbound.conf")) != 0) { + result = ERRSET_FAIL; + goto fail; + } + + /* execute query */ + if ((result = ub_resolve(ub_ctx, (char*)hostname, rdtype, rdclass, &ub_result)) != 0) { + result = ERRSET_FAIL; + goto fail; + } + + if (ub_result->nxdomain) { + result = ERRSET_NONAME; + goto fail; + } + + if (!ub_result->havedata) { + result = ERRSET_NODATA; + goto fail; } /* parse result */ - response = parse_dns_response(answer, length); + response = parse_dns_response(ub_result->answer_packet, ub_result->answer_len); if (response == NULL) { result = ERRSET_FAIL; goto fail; @@ -333,6 +331,8 @@ } } free_dns_response(response); + ub_resolve_free(ub_result); + ub_ctx_delete(ub_ctx); *res = rrset; return (ERRSET_SUCCESS); @@ -342,6 +342,10 @@ freerrset(rrset); if (response != NULL) free_dns_response(response); + if (ub_result != NULL) + ub_resolve_free(ub_result); + if (ub_ctx != NULL) + ub_ctx_delete(ub_ctx); return (result); }
Attachment:
signature.asc
Description: Digital signature