diff options
author | Werner Koch <wk@gnupg.org> | 2011-11-30 17:14:08 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2011-11-30 17:34:49 +0100 |
commit | 31f548a18aed729c05ea367f2d8a8104480430d5 (patch) | |
tree | d3033d8ffbdc23f6115243cdb65b4438d19ac846 /common | |
parent | * common/estream.c (es_fopenmem_init): New. (diff) | |
download | gnupg2-31f548a18aed729c05ea367f2d8a8104480430d5.tar.xz gnupg2-31f548a18aed729c05ea367f2d8a8104480430d5.zip |
Rewrite dns-cert.c to not use the gpg-only iobuf stuff.
* common/dns-cert.c: Remove iobuf.h.
(get_dns_cert): Rename to _get_dns_cert. Remove MAX_SIZE arg. Change
iobuf arg to a estream-t. Rewrite function to make use of estream
instead of iobuf. Require all parameters. Return an gpg_error_t
error instead of the type. Add arg ERRSOURCE.
* common/dns-cert.h (get_dns_cert): New macro to pass the error source
to _gpg_dns_cert.
* common/t-dns-cert.c (main): Adjust for changes in get_dns_cert.
* g10/keyserver.c (keyserver_import_cert): Ditto.
* doc/gpg.texi (GPG Configuration Options): Remove max-cert-size.
Diffstat (limited to 'common')
-rw-r--r-- | common/ChangeLog | 15 | ||||
-rw-r--r-- | common/dns-cert.c | 195 | ||||
-rw-r--r-- | common/dns-cert.h | 9 | ||||
-rw-r--r-- | common/t-dns-cert.c | 32 |
4 files changed, 162 insertions, 89 deletions
diff --git a/common/ChangeLog b/common/ChangeLog index d5682fc4b..96e4e31a2 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,18 @@ +2011-11-30 Werner Koch <wk@gnupg.org> + + Rewrite dns-cert.c to not use the gpg-only iobuf stuff. + * dns-cert.c: Remove iobuf.h. + (get_dns_cert): Rename to _get_dns_cert. Remove MAX_SIZE arg. + Change iobuf arg to a estream-t. Rewrite function to make use of + estream instead of iobuf. Require all parameters. Return an + gpg_error_t error instead of the type. Add arg ERRSOURCE. + * dns-cert.h (get_dns_cert): New macro to pass the error source to + _gpg_dns_cert. + * t-dns-cert.c (main): Adjust for changes in get_dns_cert. + + * estream.c (es_fopenmem_init): New. + * estream.h (es_fopenmem_init): New. + 2011-11-29 Werner Koch <wk@g10code.com> * estream.c (func_mem_create): Don't set FUNC_REALLOC if GROW is diff --git a/common/dns-cert.c b/common/dns-cert.c index 9b6c6c893..56af13a1d 100644 --- a/common/dns-cert.c +++ b/common/dns-cert.c @@ -37,7 +37,6 @@ #endif #include "util.h" -#include "iobuf.h" #include "dns-cert.h" /* Not every installation has gotten around to supporting CERTs @@ -63,48 +62,58 @@ #define CERTTYPE_OID 254 /* OID private. */ -/* Returns -1 on error, 0 for no answer, 1 for PGP provided and 2 for - IPGP provided. Note that this function returns 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) +/* Returns 0 on success or an error code. If a PGP CERT record was + found, a new estream with that key will be returned at R_KEY and + the other return parameters are set to NULL/0. If an IPGP CERT + record was found the fingerprint is stored as an allocated block at + R_FPR and its length at R_FPRLEN; an URL is is allocated as a + string and returned at R_URL. Note that this function returns the + first CERT found with a supported type; it is expected that only + one CERT record is used. */ +gpg_error_t +_get_dns_cert (const char *name, estream_t *r_key, + unsigned char **r_fpr, size_t *r_fprlen, char **r_url, + gpg_err_source_t errsource) { #ifdef USE_DNS_CERT #ifdef USE_ADNS + gpg_error_t err; adns_state state; adns_answer *answer = NULL; - int rc; unsigned int ctype; int count; - rc = adns_init (&state, adns_if_noerrprint, NULL); - if (rc) + *r_key = NULL; + *r_fpr = NULL; + *r_fprlen = 0; + *r_url = NULL; + + if (adns_init (&state, adns_if_noerrprint, NULL)) { + err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); log_error ("error initializing adns: %s\n", strerror (errno)); - return -1; + return err; } - rc = adns_synchronous (state, name, (adns_r_unknown | my_adns_r_cert), - adns_qf_quoteok_query, &answer); - if (rc) + if (adns_synchronous (state, name, (adns_r_unknown | my_adns_r_cert), + adns_qf_quoteok_query, &answer)) { + err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); /* log_error ("DNS query failed: %s\n", strerror (errno)); */ adns_finish (state); - return -1; + return err; } 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; + err = gpg_err_make (errsource, GPG_ERR_NOT_FOUND); + goto leave; } - for (rc = 0, count = 0; !rc && count < answer->nrrs; count++) + err = gpg_err_make (errsource, GPG_ERR_NOT_FOUND); + for (count = 0; count < answer->nrrs; count++) { int datalen = answer->rrs.byteblock[count].len; const unsigned char *data = answer->rrs.byteblock[count].data; @@ -121,8 +130,12 @@ get_dns_cert (const char *name, size_t max_size, IOBUF * iobuf, { /* 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; + *r_key = es_fopenmem_init (0, "rwb", data, datalen); + if (!*r_key) + err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); + else + err = 0; + goto leave; } else if (ctype == CERTTYPE_IPGP && datalen && datalen < 1023 && datalen >= data[0] + 1 && fpr && fpr_len && url) @@ -130,50 +143,68 @@ get_dns_cert (const char *name, size_t max_size, IOBUF * iobuf, /* CERT type is IPGP. We made sure that the data is plausible and that the caller requested this information. */ - *fpr_len = data[0]; - if (*fpr_len) + *r_fprlen = data[0]; + if (*r_fprlen) { - *fpr = xmalloc (*fpr_len); - memcpy (*fpr, data + 1, *fpr_len); + *r_fpr = xtrymalloc (*r_fprlen); + if (!*r_fpr) + { + err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); + goto leave; + } + memcpy (*r_fpr, data + 1, *r_fprlen); } else - *fpr = NULL; + *r_fpr = NULL; - if (datalen > *fpr_len + 1) + if (datalen > *r_fprlen + 1) { - *url = xmalloc (datalen - (*fpr_len + 1) + 1); - memcpy (*url, data + (*fpr_len + 1), datalen - (*fpr_len + 1)); - (*url)[datalen - (*fpr_len + 1)] = '\0'; + *url = xtrymalloc (datalen - (*r_fprlen + 1) + 1); + if (!*r_url) + { + err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); + xfree (*r_fpr); + *r_fpr = NULL; + goto leave; + } + memcpy (*url, data + (*r_fprlen + 1), datalen - (*r_fprlen + 1)); + (*url)[datalen - (*r_fprlen + 1)] = '\0'; } else - *url = NULL; + *r_url = NULL; - rc = 2; + err = 0; + goto leave; } } + leave: adns_free (answer); adns_finish (state); - return rc; + return err; #else /*!USE_ADNS*/ + gpg_error_t err; unsigned char *answer; - int ret = -1; int r; u16 count; - if (fpr) - *fpr = NULL; + *r_key = NULL; + *r_fpr = NULL; + *r_fprlen = 0; + *r_url = NULL; - if (url) - *url = NULL; + /* Allocate a 64k buffer which is the limit for an DNS response. */ + answer = xtrymalloc (65536); + if (!answer) + return gpg_err_make (errsource, gpg_err_code_from_syserror ()); - answer = xmalloc (max_size); + err = gpg_err_make (errsource, GPG_ERR_NOT_FOUND); - r = res_query (name, C_IN, T_CERT, answer, max_size); + r = res_query (name, C_IN, T_CERT, answer, 65536); /* Not too big, not too small, no errors and at least 1 answer. */ - if (r >= sizeof (HEADER) && r <= max_size + if (r >= sizeof (HEADER) && r <= 65536 && (((HEADER *) answer)->rcode) == NOERROR && (count = ntohs (((HEADER *) answer)->ancount))) { @@ -188,8 +219,10 @@ get_dns_cert (const char *name, size_t max_size, IOBUF * iobuf, rc = dn_skipname (pt, emsg); if (rc == -1) - goto fail; - + { + err = gpg_err_make (errsource, GPG_ERR_INV_OBJ); + goto leave; + } pt += rc + QFIXEDSZ; /* There are several possible response types for a CERT request. @@ -204,7 +237,10 @@ get_dns_cert (const char *name, size_t max_size, IOBUF * iobuf, rc = dn_skipname (pt, emsg); /* the name we just queried for */ if (rc == -1) - break; + { + err = gpg_err_make (errsource, GPG_ERR_INV_OBJ); + goto leave; + } pt += rc; @@ -248,39 +284,54 @@ get_dns_cert (const char *name, size_t max_size, IOBUF * iobuf, /* 15 bytes takes us to here */ - if (ctype == CERTTYPE_PGP && iobuf && dlen) + if (ctype == CERTTYPE_PGP && dlen) { /* PGP type */ - *iobuf = iobuf_temp_with_content ((char *) pt, dlen); - ret = 1; - break; + *r_key = es_fopenmem_init (0, "rwb", pt, dlen); + if (!*r_key) + err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); + else + err = 0; + goto leave; } else if (ctype == CERTTYPE_IPGP - && dlen && dlen < 1023 && dlen >= pt[0] + 1 - && fpr && fpr_len && url) + && dlen && dlen < 1023 && dlen >= pt[0] + 1) { /* IPGP type */ - *fpr_len = pt[0]; - - if (*fpr_len) + *r_fprlen = pt[0]; + if (*r_fprlen) { - *fpr = xmalloc (*fpr_len); - memcpy (*fpr, &pt[1], *fpr_len); + *r_fpr = xtrymalloc (*r_fprlen); + if (!*r_fpr) + { + err = gpg_err_make (errsource, + gpg_err_code_from_syserror ()); + goto leave; + } + memcpy (*r_fpr, &pt[1], *r_fprlen); } else - *fpr = NULL; + *r_fpr = NULL; - if (dlen > *fpr_len + 1) + if (dlen > *r_fprlen + 1) { - *url = xmalloc (dlen - (*fpr_len + 1) + 1); - memcpy (*url, &pt[*fpr_len + 1], dlen - (*fpr_len + 1)); - (*url)[dlen - (*fpr_len + 1)] = '\0'; + *r_url = xtrymalloc (dlen - (*r_fprlen + 1) + 1); + if (!*r_fpr) + { + err = gpg_err_make (errsource, + gpg_err_code_from_syserror ()); + xfree (*r_fpr); + *r_fpr = NULL; + goto leave; + } + memcpy (*r_url, &pt[*r_fprlen + 1], dlen - (*r_fprlen + 1)); + (*r_url)[dlen - (*r_fprlen + 1)] = '\0'; } else - *url = NULL; + *r_url = NULL; - ret = 2; - break; + err = 0; + goto leave; } /* Neither type matches, so go around to the next answer. */ @@ -288,18 +339,18 @@ get_dns_cert (const char *name, size_t max_size, IOBUF * iobuf, } } - fail: + leave: xfree (answer); - return ret; + return err; + #endif /*!USE_ADNS */ #else /* !USE_DNS_CERT */ (void)name; - (void)max_size; - (void)iobuf; - (void)fpr; - (void)fpr_len; - (void)url; + (void)r_key; + (void)r_fpr; + (void)r_fprlen; + (void)r_url; - return -1; + return gpg_err_make (errsource, GPG_ERR_NOT_SUPPORTED); #endif } diff --git a/common/dns-cert.h b/common/dns-cert.h index ebfeec838..a1d3d86da 100644 --- a/common/dns-cert.h +++ b/common/dns-cert.h @@ -19,8 +19,13 @@ #ifndef GNUPG_COMMON_DNS_CERT_H #define GNUPG_COMMON_DNS_CERT_H -int get_dns_cert (const char *name, size_t max_size, iobuf_t *iobuf, - unsigned char **fpr, size_t *fpr_len, char **url); +gpg_error_t _get_dns_cert (const char *name, estream_t *r_key, + unsigned char **r_fpr, size_t *r_fprlen, + char **r_url, + gpg_err_source_t errsource); +#define get_dns_cert(a,b,c,d,e) \ + _get_dns_cert ((a),(b),(c),(d),(e), GPG_ERR_SOURCE_DEFAULT); + #endif /*GNUPG_COMMON_DNS_CERT_H*/ diff --git a/common/t-dns-cert.c b/common/t-dns-cert.c index f3e8892a7..1dcae6f29 100644 --- a/common/t-dns-cert.c +++ b/common/t-dns-cert.c @@ -23,18 +23,17 @@ #include <assert.h> #include "util.h" -#include "iobuf.h" #include "dns-cert.h" int main (int argc, char **argv) { + gpg_error_t err; unsigned char *fpr; size_t fpr_len; char *url; - int rc; - iobuf_t iobuf; + estream_t key; char const *name; if (argc) @@ -55,18 +54,19 @@ main (int argc, char **argv) printf ("CERT lookup on `%s'\n", name); - rc = get_dns_cert (name, 65536, &iobuf, &fpr, &fpr_len, &url); - if (rc == -1) - fputs ("lookup result: error\n", stdout); - else if (!rc) - fputs ("lookup result: no answer\n", stdout); - else if (rc == 1) + err = get_dns_cert (name, &key, &fpr, &fpr_len, &url); + if (err) + printf ("get_dns_cert failed: %s <%s>\n", + gpg_strerror (err), gpg_strsource (err)); + else if (key) { - printf ("lookup result: %d bytes\n", - (int)iobuf_get_temp_length(iobuf)); - iobuf_close (iobuf); + int count = 0; + + while (es_getc (key) != EOF) + count++; + printf ("Key found (%d bytes)\n", count); } - else if (rc == 2) + else { if (fpr) { @@ -85,9 +85,11 @@ main (int argc, char **argv) else printf ("No URL found\n"); - xfree (fpr); - xfree (url); } + es_fclose (key); + xfree (fpr); + xfree (url); + return 0; } |