From 211b8084ee4391baec35e8c5bd75a9ecbcb889a7 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 6 Oct 2015 19:57:00 +0200 Subject: [PATCH] dirmngr: Improve DNS code to retrieve arbitrary records. * dirmngr/dns-cert.c (get_dns_cert): Add hack to retrieve arbitrary resource records. * dirmngr/dns-cert.h (DNS_CERTTYPE_RRBASE): New. (DNS_CERTTYPE_RR61): New. -- This has been tested with ADNS on Unix and with the standard resolver. Because ADNS works it should also work on Windows. Signed-off-by: Werner Koch --- dirmngr/dns-cert.c | 55 +++++++++++++++++++++++++++++++++++++++++++--- dirmngr/dns-cert.h | 4 +++- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/dirmngr/dns-cert.c b/dirmngr/dns-cert.c index 03c1de1e6..3845a4b25 100644 --- a/dirmngr/dns-cert.c +++ b/dirmngr/dns-cert.c @@ -99,7 +99,11 @@ get_dns_cert (const char *name, int want_certtype, return err; } - if (adns_synchronous (state, name, (adns_r_unknown | my_adns_r_cert), + if (adns_synchronous (state, name, + (adns_r_unknown + | (want_certtype < DNS_CERTTYPE_RRBASE + ? my_adns_r_cert + : (want_certtype - DNS_CERTTYPE_RRBASE))), adns_qf_quoteok_query, &answer)) { err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); @@ -122,6 +126,26 @@ get_dns_cert (const char *name, int want_certtype, int datalen = answer->rrs.byteblock[count].len; const unsigned char *data = answer->rrs.byteblock[count].data; + /* First check for our generic RR hack. */ + if (datalen + && want_certtype >= DNS_CERTTYPE_RRBASE + && ((want_certtype - DNS_CERTTYPE_RRBASE) + == (answer->type & ~adns_r_unknown))) + { + /* Found the requested record - return it. */ + *r_key = xtrymalloc (datalen); + if (!*r_key) + err = gpg_err_make (default_errsource, + gpg_err_code_from_syserror ()); + else + { + memcpy (*r_key, data, datalen); + *r_keylen = datalen; + err = 0; + } + goto leave; + } + if (datalen < 5) continue; /* Truncated CERT record - skip. */ @@ -219,7 +243,11 @@ get_dns_cert (const char *name, int want_certtype, err = gpg_err_make (default_errsource, GPG_ERR_NOT_FOUND); - r = res_query (name, C_IN, T_CERT, answer, 65536); + r = res_query (name, C_IN, + (want_certtype < DNS_CERTTYPE_RRBASE + ? T_CERT + : (want_certtype - DNS_CERTTYPE_RRBASE)), + answer, 65536); /* Not too big, not too small, no errors and at least 1 answer. */ if (r >= sizeof (HEADER) && r <= 65536 && (((HEADER *) answer)->rcode) == NOERROR @@ -283,7 +311,28 @@ get_dns_cert (const char *name, int want_certtype, pt += 2; /* Check the type and parse. */ - if (type == T_CERT) + if (want_certtype >= DNS_CERTTYPE_RRBASE + && type == (want_certtype - DNS_CERTTYPE_RRBASE) + && r_key) + { + *r_key = xtrymalloc (dlen); + if (!*r_key) + err = gpg_err_make (default_errsource, + gpg_err_code_from_syserror ()); + else + { + memcpy (*r_key, pt, dlen); + *r_keylen = dlen; + err = 0; + } + goto leave; + } + else if (want_certtype >= DNS_CERTTYPE_RRBASE) + { + /* We did not found the requested RR. */ + pt += dlen; + } + else if (type == T_CERT) { /* We got a CERT type. */ ctype = buf16_to_u16 (pt); diff --git a/dirmngr/dns-cert.h b/dirmngr/dns-cert.h index 5a579ec1f..9dbc58c23 100644 --- a/dirmngr/dns-cert.h +++ b/dirmngr/dns-cert.h @@ -43,7 +43,9 @@ #define DNS_CERTTYPE_IACPKIX 8 /* The URL of an Attribute Certificate. */ #define DNS_CERTTYPE_URI 253 /* URI private. */ #define DNS_CERTTYPE_OID 254 /* OID private. */ - +/* Hacks for our implementation. */ +#define DNS_CERTTYPE_RRBASE 1024 /* Base of special constants. */ +#define DNS_CERTTYPE_RR61 (DNS_CERTTYPE_RRBASE + 61) gpg_error_t get_dns_cert (const char *name, int want_certtype, void **r_key, size_t *r_keylen,