From 0573cda1b335a9dfbcc33d5b61964dcaae2ed165 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Sun, 27 Mar 2016 19:27:30 +0200 Subject: WIP --- c_src/Makefile | 17 ++++++ c_src/dnssec.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++ c_src/erlport.c | 119 ++++++++++++++++++++++++++++++++++++++++++ c_src/erlport.h | 18 +++++++ c_src/net_read_write.c | 93 +++++++++++++++++++++++++++++++++ c_src/net_read_write.h | 10 ++++ 6 files changed, 395 insertions(+) create mode 100644 c_src/Makefile create mode 100644 c_src/dnssec.c create mode 100644 c_src/erlport.c create mode 100644 c_src/erlport.h create mode 100644 c_src/net_read_write.c create mode 100644 c_src/net_read_write.h (limited to 'c_src') diff --git a/c_src/Makefile b/c_src/Makefile new file mode 100644 index 0000000..ae9c73e --- /dev/null +++ b/c_src/Makefile @@ -0,0 +1,17 @@ +CC = gcc +#CFLAGS = -Wall -Werror -std=gnu99 +CFLAGS = -Wall -Werror -std=gnu99 -DTEST +LDFLAGS = + +PORTS = dnssecport + +common_OBJS = erlport.o net_read_write.o +dnssecport_OBJS = dnssec.o dnssec_test.o $(common_OBJS) + +all: $(PORTS) + +clean: + rm -f $(common_OBJS) $(dnssecport_OBJS) $(PORTS) + +dnssecport: $(dnssecport_OBJS) + $(CC) -o $@ $^ $(LDFLAGS) -ldl -lgetdns 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 +#include +#include +#include +#include +#include +#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; +} diff --git a/c_src/erlport.c b/c_src/erlport.c new file mode 100644 index 0000000..372f98d --- /dev/null +++ b/c_src/erlport.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014-2015, NORDUnet A/S. + * See LICENSE for licensing information. + */ + +#include +#include +#include +#include +#include +#include + +#include "net_read_write.h" +#include "erlport.h" + +static ssize_t +read_length(size_t length_size) +{ + unsigned char buf[4]; + + if (length_size != 2 && length_size != 4) { + return -1; + } + + if (length_size > sizeof(buf)) { + return -1; + } + + ssize_t ret; + + ret = net_read(0, (char *)buf, length_size); + + if (ret != (ssize_t) length_size) { + return -1; + } + + if (length_size == 2) { + return (ssize_t)(((unsigned long)buf[0] << 8) | (unsigned long)buf[1]); + } else { + return (ssize_t)(((unsigned long)buf[0] << 24) | + ((unsigned long)buf[1] << 16) | + ((unsigned long)buf[2] << 8) | + (unsigned long)buf[3]); + } +} + +ssize_t +read_command(unsigned char *buf, size_t maxlen, size_t length_size) +{ + ssize_t len; + + len = read_length(length_size); + + if (len < 0) { + return -1; + } + + if (len > (ssize_t) maxlen) { + return -1; + } + return net_read(0, (char *)buf, (size_t)len); +} + +static int +write_length(size_t len, size_t length_size) +{ + unsigned char buf[4]; + + if (length_size != 2 && length_size != 4) { + return -1; + } + + if (length_size == 2) { + buf[0] = (len >> 8) & 0xff; + buf[1] = len & 0xff; + } else { + buf[0] = (len >> 24) & 0xff; + buf[1] = (len >> 16) & 0xff; + buf[2] = (len >> 8) & 0xff; + buf[3] = len & 0xff; + } + + ssize_t ret; + + ret = net_write(1, (char *)buf, length_size); + + if (ret < 0) { + return -1; + } + + if (ret != (ssize_t) length_size) { + return -1; + } + + return 0; +} + +int +write_reply(unsigned char *msg, size_t len, size_t length_size) +{ + ssize_t ret; + + ret = write_length(len, length_size); + if (ret < 0) { + return -1; + } + ret = net_write(1, (char *)msg, len); + if (ret < 0) { + return -1; + } + + return 0; +} + +int +write_status(char *msg) +{ + return write_reply((unsigned char *)msg, strlen(msg), 2); +} diff --git a/c_src/erlport.h b/c_src/erlport.h new file mode 100644 index 0000000..58b2591 --- /dev/null +++ b/c_src/erlport.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2014-2015, NORDUnet A/S. + * See LICENSE for licensing information. + */ + +#ifndef ERLPORT_H +#define ERLPORT_H + +ssize_t +read_command(unsigned char *buf, size_t maxlen, size_t length_size); + +int +write_reply(unsigned char *msg, size_t len, size_t length_size); + +int +write_status(char *msg); + +#endif diff --git a/c_src/net_read_write.c b/c_src/net_read_write.c new file mode 100644 index 0000000..f8f14f0 --- /dev/null +++ b/c_src/net_read_write.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include "net_read_write.h" + +/* + * Like read but never return partial data. + */ + +ssize_t +net_read (int fd, void *buf, size_t nbytes) +{ + char *cbuf = (char *)buf; + ssize_t count; + size_t rem = nbytes; + + while (rem > 0) { + count = read (fd, cbuf, rem); + if (count < 0) { + if (errno == EINTR) + continue; + else + return count; + } else if (count == 0) { + return count; + } + cbuf += (size_t) count; + rem -= (size_t) count; + } + return (ssize_t)nbytes; +} + +/* + * Like write but never return partial data. + */ + +ssize_t +net_write (int fd, const void *buf, size_t nbytes) +{ + const char *cbuf = (const char *)buf; + ssize_t count; + size_t rem = nbytes; + + while (rem > 0) { + count = write (fd, cbuf, rem); + if (count < 0) { + if (errno == EINTR) + continue; + else + return count; + } + cbuf += (size_t)count; + rem -= (size_t)count; + } + return (ssize_t)nbytes; +} diff --git a/c_src/net_read_write.h b/c_src/net_read_write.h new file mode 100644 index 0000000..80b92b3 --- /dev/null +++ b/c_src/net_read_write.h @@ -0,0 +1,10 @@ +#ifndef NET_READ_WRITE_H +#define NET_READ_WRITE_H + +ssize_t +net_read (int, void *, size_t); + +ssize_t +net_write (int, const void *, size_t); + +#endif -- cgit v1.1