diff options
author | Werner Koch <wk@gnupg.org> | 2009-12-08 13:20:11 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2009-12-08 13:20:11 +0100 |
commit | bb861ac7303cd8f4f054337d7f9997e41df28c17 (patch) | |
tree | 25e53b9263cbb5d342d096de6b14220d8cd39fce /common | |
parent | common/ (diff) | |
download | gnupg2-bb861ac7303cd8f4f054337d7f9997e41df28c17.tar.xz gnupg2-bb861ac7303cd8f4f054337d7f9997e41df28c17.zip |
Support CERT records via ADNS
Diffstat (limited to 'common')
-rw-r--r-- | common/ChangeLog | 4 | ||||
-rw-r--r-- | common/dns-cert.c | 116 |
2 files changed, 111 insertions, 9 deletions
diff --git a/common/ChangeLog b/common/ChangeLog index df058a8fe..f71e0e354 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2009-12-08 Werner Koch <wk@g10code.com> + + * dns-cert.c (get_dns_cert): Add support for ADNS. + 2009-12-08 Marcus Brinkmann <marcus@g10code.de> * asshelp.c (start_new_gpg_agent): Convert posix FD to assuan FD. diff --git a/common/dns-cert.c b/common/dns-cert.c index ee3b50040..54441d308 100644 --- a/common/dns-cert.c +++ b/common/dns-cert.c @@ -21,13 +21,19 @@ #include <sys/types.h> #ifdef USE_DNS_CERT # ifdef HAVE_W32_SYSTEM -# include <windows.h> +# include <windows.h> # else -# include <netinet/in.h> -# include <arpa/nameser.h> -# include <resolv.h> +# include <netinet/in.h> +# include <arpa/nameser.h> +# include <resolv.h> +# endif +# include <string.h> +#endif +#ifdef USE_ADNS +# include <adns.h> +# ifndef HAVE_ADNS_FREE +# define adns_free free # endif -#include <string.h> #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 |