diff options
Diffstat (limited to 'c_src/dnssec.c')
-rw-r--r-- | c_src/dnssec.c | 116 |
1 files changed, 92 insertions, 24 deletions
diff --git a/c_src/dnssec.c b/c_src/dnssec.c index fe46d3d..6b9431d 100644 --- a/c_src/dnssec.c +++ b/c_src/dnssec.c @@ -19,8 +19,8 @@ * * Output format: * - Lenght of data (4 octets) - * - Return value -- the getdns_return_t value in network byte order - * (2 octets) + * - Status code -- the getdns_return_t value in network byte order (2 + * octets) * - (RR's)* -- if validation succeeded: the DS+RRSIG and the full * chain up to and including the trust anchor; if validation failed: * nothing @@ -33,27 +33,27 @@ #include <string.h> #include <errno.h> #include <time.h> -#include <arpa/inet.h> +#include <endian.h> #include <getopt.h> #include <getdns/getdns.h> #include <getdns/getdns_extra.h> #include "erlport.h" #include "dnssec_test.h" -static int debug = 1; /* DEBUG */ +static int debug = 0; /* DEBUG */ #if defined(TEST) static char *testmode = NULL; #endif static void -print_tree(const getdns_list *tree, const char *name) +print_tree(FILE *fp, const getdns_list *tree, const char *name) { if (name) - printf("* %s\n", name); + fprintf(fp, "* %s\n", name); char *s = getdns_pretty_print_list(tree); - puts(s); + fputs(s, fp); free(s); } @@ -122,19 +122,54 @@ wire_rrs2list(const uint8_t *buf, size_t buf_len, getdns_list **list_out) static int read_trust_anchors(const char *fname, getdns_list **list_out) { + if (debug) + fprintf(stderr, "reading trust anchors from file %s\n", fname); + FILE *fp = fopen(fname, "r"); if (fp == NULL) return -errno; uint8_t *buf = NULL; size_t n = read_file(fp, &buf, 0); - return (int) wire_rrs2list(buf, n, list_out); + if (fclose(fp)) + fprintf(stderr, "unable to close trust anchors file: %d", errno); + int r = wire_rrs2list(buf, n, list_out); + free(buf); + return r; +} + +static getdns_return_t +list2wire(const getdns_list *list, uint8_t *out_buf, size_t *out_buf_len) +{ + size_t list_len; + getdns_return_t r = getdns_list_get_length(list, &list_len); + if (r) + return r; + + getdns_dict *rr = NULL; + uint8_t *buf = NULL; + size_t buf_len = 0; + *out_buf_len = 0; + for (int i = 0; i < list_len; i++) + { + if ((r = getdns_list_get_dict(list, i , &rr))) + return r; + if ((r = getdns_rr_dict2wire(rr, &buf, &buf_len))) + return r; /* FIXME: Risk of leaking buf? */ + memcpy(out_buf, buf, buf_len); + free(buf); + out_buf += buf_len; + *out_buf_len += buf_len; + } + + return r; } #if !defined(TEST) static getdns_return_t validate(const uint8_t *buf, size_t buf_len, getdns_list *trust_anchors, - time_t validation_time, uint32_t skew) + time_t validation_time, uint32_t skew, + uint8_t *out_buf, size_t *out_buf_len) { getdns_return_t r = GETDNS_DNSSEC_INDETERMINATE; getdns_list *list = NULL; @@ -153,6 +188,7 @@ validate(const uint8_t *buf, size_t buf_len, getdns_dict *ds_dict = NULL; getdns_dict *rrsig_ds_dict = NULL; uint32_t rrtype = 0; + /* DS */ if ((r = getdns_list_get_dict(list, 0, &ds_dict))) goto out; if ((r = getdns_dict_get_int(ds_dict, "type", &rrtype))) @@ -164,7 +200,7 @@ validate(const uint8_t *buf, size_t buf_len, } if ((r = getdns_list_set_dict(to_validate, 0, ds_dict))) goto out; - + /* RRSIG DS */ if ((r = getdns_list_get_dict(list, 1, &rrsig_ds_dict))) goto out; if ((r = getdns_dict_get_int(rrsig_ds_dict, "type", &rrtype))) @@ -177,7 +213,7 @@ validate(const uint8_t *buf, size_t buf_len, if ((r = getdns_list_set_dict(to_validate, 1, rrsig_ds_dict))) goto out; - /* The rest is "support records". Copy those to support_records. */ + /* The rest is "support records". Copy them to support_records. */ size_t list_len; if ((r = getdns_list_get_length(list, &list_len))) goto out; @@ -190,11 +226,11 @@ validate(const uint8_t *buf, size_t buf_len, goto out; } - if (debug) + if (0 && debug) { - print_tree(to_validate, "to_validate"); - print_tree(support_records, "support_records"); - print_tree(trust_anchors, "trust_anchors"); + print_tree(stderr, to_validate, "to_validate"); + print_tree(stderr, support_records, "support_records"); + print_tree(stderr, trust_anchors, "trust_anchors"); } r = getdns_validate_dnssec2(to_validate, @@ -203,6 +239,30 @@ validate(const uint8_t *buf, size_t buf_len, validation_time, skew); + if (out_buf && out_buf_len) + { + getdns_return_t r_save = r; + size_t len = 0; + *out_buf_len = 0; + + if ((r = list2wire(to_validate, out_buf, &len))) + goto out; + out_buf += len; + *out_buf_len += len; + + if ((r = list2wire(support_records, out_buf, &len))) + goto out; + out_buf += len; + *out_buf_len += len; + + if ((r = list2wire(trust_anchors, out_buf, &len))) + goto out; + out_buf += len; + *out_buf_len += len; + + r = r_save; + } + out: if (list) getdns_list_destroy(list); @@ -218,25 +278,29 @@ static void loop(getdns_list *trust_anchors) { getdns_return_t r = GETDNS_RETURN_GENERIC_ERROR; - unsigned char buf[65536]; + unsigned char buf[64 * 1024]; /* FIXME */ ssize_t len; while ((len = read_command(buf, sizeof(buf), 4)) > 0) { - unsigned char reply[2]; + unsigned char reply[2 * 64 * 1024]; /* FIXME */ + size_t out_len = 0; #if !defined(TEST) - r = validate(buf, len, trust_anchors, time(NULL), DNSSEC_VALIDATION_SKEW); + r = validate(buf, len, trust_anchors, + time(NULL), DNSSEC_VALIDATION_SKEW, + reply + 2, &out_len); #else r = test_validate(buf, len, trust_anchors, testmode); #endif if (debug) { - switch (r) + int intr = r; /* GETDNS_DNSSEC_SECURE is not in enum getdns_return_t */ + switch (intr) { - case GETDNS_RETURN_GOOD: - fprintf(stderr, "validation success\n"); + case GETDNS_DNSSEC_SECURE: + fprintf(stderr, "validation successful\n"); break; default: fprintf(stderr, "validation error %d (%s)\n", @@ -244,8 +308,12 @@ loop(getdns_list *trust_anchors) } } - *((uint16_t *) reply) = htons(r); - write_reply(reply, 2, 4); + *((uint16_t *) reply) = htobe16(r); + if (debug) + fprintf(stderr, "writing %d octets of data, including status code %d\n", + 2 + out_len, r); + if (write_reply(reply, 2 + out_len, 4)) + fprintf(stderr, "error writing reply\n"); } } @@ -281,7 +349,7 @@ main(int argc, char *argv[]) } /* Read trust anchors file. */ - if (optind >= argc) + if (optind < argc) { int r = read_trust_anchors(argv[optind], &trust_anchors); if (r < 0) |