diff options
author | Linus Nordberg <linus@nordu.net> | 2016-03-27 19:27:30 +0200 |
---|---|---|
committer | Linus Nordberg <linus@nordu.net> | 2016-03-27 19:44:25 +0200 |
commit | 56d70baa79ae5907b11445364bbea9b31ee4cd20 (patch) | |
tree | ef0403255a04de75736da82385d282a0198c52c2 /c_src/dnssec.c | |
parent | 9f723f6f1d79c1be460ece10555945346045b175 (diff) |
WIP
Diffstat (limited to 'c_src/dnssec.c')
-rw-r--r-- | c_src/dnssec.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/c_src/dnssec.c b/c_src/dnssec.c new file mode 100644 index 0000000..693d645 --- /dev/null +++ b/c_src/dnssec.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016, NORDUnet A/S. + * See LICENSE for licensing information. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <err.h> +#include <getopt.h> +#include <getdns/getdns.h> +#include "erlport.h" +#include "dnssec_test.h" + +static char *testmode = NULL; + +/* getdns/src/convert.c */ +getdns_return_t getdns_wire2rr_dict(const uint8_t *wire, size_t wire_len, + getdns_dict **rr_dict); + +#if !defined(TEST) +static getdns_return_t +validate(const unsigned char *records, + size_t records_len, + getdns_list *trust_anchors) +{ + getdns_return_t r = GETDNS_DNSSEC_INDETERMINATE; + getdns_list *to_validate = getdns_list_create(); + getdns_list *support_records = getdns_list_create(); + getdns_dict *records_dict = NULL; + + if (to_validate == NULL || support_records == NULL) + { + r = GETDNS_RETURN_MEMORY_ERROR; + goto out; + } + + /* TODO: figure out if we get _all_ RRs in records here bc i have + the feeling that we're not supposed to mix RR types in the same + dict; maybe this will help some: + https://getdnsapi.net/pipermail/users/2015-May/000032.html + */ + r = getdns_wire2rr_dict(records, records_len, &records_dict); + if (r) + goto out; + + /* + to_validate: one dict with the DS and one with a RRSIG for that DS + support_records: DS and DNSKEY dicts with accompanying RRSIG's + trust_anchors: DNSKEY (or DS) + */ + r = getdns_list_set_dict(to_validate, i, records_dict); + if (r) + goto out; + + r = getdns_validate_dnssec(to_validate, + support_records, + trust_anchors); + +out: + if (to_validate) + getdns_list_destroy(to_validate); + if (support_records) + getdns_list_destroy(support_records); + + return r; +} +#endif /* !TEST */ + +static void +loop(getdns_list *trust_anchors) +{ + getdns_return_t r = GETDNS_RETURN_GENERIC_ERROR; + unsigned char buf[65536]; + ssize_t len; + + while ((len = read_command(buf, sizeof(buf), 4)) > 0) + { + unsigned char *reply = NULL; + +#if !defined(TEST) + r = validate(buf, len, trust_anchors); +#else + r = test_validate(buf, len, trust_anchors, testmode); +#endif + + switch (r) + { + case GETDNS_RETURN_GOOD: + reply = (unsigned char *) "valid"; + break; + default: + fprintf(stderr, "error %d\n", r); /* DEBUG */ + reply = (unsigned char *) "err"; + } + + write_reply(reply, strlen((const char *) reply), 4); + } +} + +int +main(int argc, char *argv[]) +{ + int c; + getdns_list *trust_anchors = NULL; + time_t trust_anchor_date; + + while (1) { + static struct option long_options[] = { + {"testmode", required_argument, NULL, 't'}, + {0, 0, 0, 0}}; + + c = getopt_long(argc, argv, "", long_options, NULL); + if (c == -1) + break; + + switch (c) + { +#if defined(TEST) + case 't': + testmode = optarg; + break; +#endif + default: + fprintf(stderr, "dnssecport: bad option: %s", argv[optind]); + return -1; + } + } + + if (optind < argc) /* Using getdns trust anchor. */ + { + trust_anchors = getdns_root_trust_anchor(&trust_anchor_date); + } + + loop(trust_anchors); + + return 0; +} |