diff --git a/ChangeLog b/ChangeLog index 021d0f630..b9930ce72 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-12-08 Werner Koch + + * configure.ac (USE_DNS_CERT): Support via ADNS. + 2009-12-07 Werner Koch * configure.ac: Check for ADNS before checking for the BIND diff --git a/NEWS b/NEWS index 42531c9dd..95cbdb601 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,8 @@ Noteworthy changes in version 2.0.14 * The GPGSM --audit-log feature is now more complete. + * Support DNS lookups for SRV, PKA and CERT on W32. + Noteworthy changes in version 2.0.13 (2009-09-04) ------------------------------------------------- diff --git a/common/ChangeLog b/common/ChangeLog index 31298d1f4..cb3ee4c50 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2009-12-08 Werner Koch + + * dns-cert.c: Add support for ADNS. + 2009-12-07 Werner Koch * pka.c (get_pka_info): Add support for ADNS. diff --git a/common/dns-cert.c b/common/dns-cert.c index ee3b50040..efdefaf16 100644 --- a/common/dns-cert.c +++ b/common/dns-cert.c @@ -1,5 +1,5 @@ /* dns-cert.c - DNS CERT code - * Copyright (C) 2005, 2006 Free Software Foundation, Inc. + * Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc. * * This file is part of GNUPG. * @@ -21,13 +21,19 @@ #include #ifdef USE_DNS_CERT # ifdef HAVE_W32_SYSTEM -# include +# include # else -# include -# include -# include +# include +# include +# include +# endif +# include +#endif +#ifdef USE_ADNS +# include +# ifndef HAVE_ADNS_FREE +# define adns_free free # endif -#include #endif #include "util.h" @@ -40,14 +46,106 @@ #define T_CERT 37 #endif +/* ADNS has no support for CERT yes. */ +#define my_adns_r_cert 37 + + /* Returns -1 on error, 0 for no answer, 1 for PGP provided and 2 for - IPGP provided. */ + IPGP provided. Note that this fucntion retruns the first CERT + found with a supported type; it is expected that only one CERT + record is used. */ int -get_dns_cert (const char *name,size_t max_size,IOBUF *iobuf, - unsigned char **fpr,size_t *fpr_len,char **url) +get_dns_cert (const char *name, size_t max_size, IOBUF *iobuf, + unsigned char **fpr, size_t *fpr_len, char **url) { #ifdef USE_DNS_CERT +#ifdef USE_ADNS + adns_state state; + adns_answer *answer = NULL; + int rc; + unsigned int ctype; + int count; + + rc = adns_init (&state, adns_if_noerrprint, NULL); + if (rc) + { + log_error ("error initializing adns: %s\n", strerror (errno)); + return -1; + } + + rc = adns_synchronous (state, name, (adns_r_unknown | my_adns_r_cert), + adns_qf_quoteok_query, &answer); + if (rc) + { + /* log_error ("DNS query failed: %s\n", strerror (errno)); */ + adns_finish (state); + return -1; + } + if (answer->status != adns_s_ok) + { + /* log_error ("DNS query returned an error: %s (%s)\n", */ + /* adns_strerror (answer->status), */ + /* adns_errabbrev (answer->status)); */ + adns_free (answer); + adns_finish (state); + return 0; + } + + for (rc = 0, count=0; !rc && count < answer->nrrs; count++) + { + int datalen = answer->rrs.byteblock[count].len; + const unsigned char *data = answer->rrs.byteblock[count].data; + + if (datalen < 5) + continue; /* Truncated CERT record - skip. */ + + ctype = ((data[0]<<8)|data[1]); + /* (key tag and algorithm fields are not required.) */ + data += 5; + datalen -= 5; + + if (ctype == 3 && datalen >= 11) + { + /* CERT type is PGP. Gpg checks for a minimum length of 11, + thus we do the same. */ + *iobuf = iobuf_temp_with_content ((char*)data, datalen); + rc = 1; + } + else if (ctype == 6 && datalen && datalen < 1023 + && datalen >= data[0]+1 && fpr && fpr_len && url) + { + /* CERT type is IPGP. We made sure tha the data is + plausible and that the caller requested the + information. */ + *fpr_len = data[0]; + if (*fpr_len) + { + *fpr = xmalloc (*fpr_len); + memcpy (*fpr, data+1, *fpr_len); + } + else + *fpr = NULL; + + if (datalen > *fpr_len + 1) + { + *url = xmalloc (datalen - (*fpr_len+1) + 1); + memcpy (*url, data + (*fpr_len+1), datalen - (*fpr_len+1)); + (*url)[datalen - (*fpr_len+1)] = '\0'; + } + else + *url = NULL; + + rc = 2; + } + } + + adns_free (answer); + adns_finish (state); + return rc; + +#else /*!USE_ADNS*/ + unsigned char *answer; int r,ret=-1; u16 count; @@ -178,8 +276,8 @@ get_dns_cert (const char *name,size_t max_size,IOBUF *iobuf, fail: xfree(answer); - return ret; +#endif /*!USE_ADNS*/ #else /* !USE_DNS_CERT */ return -1; #endif diff --git a/configure.ac b/configure.ac index f3bb2b643..542c642e0 100644 --- a/configure.ac +++ b/configure.ac @@ -826,7 +826,6 @@ if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \ else # If we have no resolver library but ADNS (e.g. under W32) enable the # code parts which can be used with ADNS. - use_dns_cert=no if test x"$have_adns" = xyes ; then DNSLIBS="$ADNSLIBS" AC_DEFINE(USE_ADNS,1,[Use ADNS as resolver library.]) @@ -838,9 +837,14 @@ if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \ if test x"$use_dns_pka" = xyes ; then AC_DEFINE(USE_DNS_PKA,1) fi + + if test x"$use_dns_cert" = xyes ; then + AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT]) + fi else use_dns_srv=no use_dns_pka=no + use_dns_cert=no fi fi