summaryrefslogtreecommitdiff
path: root/c_src/dnssec.c
diff options
context:
space:
mode:
Diffstat (limited to 'c_src/dnssec.c')
-rw-r--r--c_src/dnssec.c116
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)