diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-06-11 16:42:41 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-07-22 18:23:43 +0200 |
commit | e810e79121192de128a7c41d4c2121bc81f28f15 (patch) | |
tree | 7c718be9a6e4204a9f3a15ad1569fba2181a0162 | |
parent | 18bd67731599cdf64e1ad457da73916b5a74c2bd (diff) | |
download | gnutls-ares.tar.gz |
Use libc-ares instead of unbound.ares
-rw-r--r-- | configure.ac | 40 | ||||
-rw-r--r-- | libdane/Makefile.am | 2 | ||||
-rw-r--r-- | libdane/dane-params.c | 1 | ||||
-rw-r--r-- | libdane/dane.c | 277 |
4 files changed, 190 insertions, 130 deletions
diff --git a/configure.ac b/configure.ac index e3882af28e..76a2d0cf6a 100644 --- a/configure.ac +++ b/configure.ac @@ -310,21 +310,20 @@ AC_ARG_ENABLE(libdane, AC_MSG_RESULT($enable_dane) if test "$enable_dane" != "no"; then - LIBS="$oldlibs -lunbound" + LIBS="$oldlibs -lcares" AC_MSG_CHECKING([for unbound library]) AC_LINK_IFELSE([AC_LANG_PROGRAM([ - #include <unbound.h>],[ - struct ub_ctx* ctx; - ctx = ub_ctx_create();])], + #include <ares.h>],[ + ares_query(0,0,0,0,0,0);])], [AC_MSG_RESULT(yes) - AC_SUBST([UNBOUND_LIBS], [-lunbound]) - AC_SUBST([UNBOUND_CFLAGS], []) + AC_SUBST([ARES_LIBS], [-lcares]) + AC_SUBST([ARES_CFLAGS], []) AC_DEFINE([HAVE_DANE], 1, [Enable the DANE library]) enable_dane=yes], [AC_MSG_RESULT(no) AC_MSG_WARN([[ *** -*** libunbound was not found. Libdane will not be built. +*** libc-ares was not found. Libdane will not be built. *** ]]) enable_dane=no]) LIBS="$oldlibs" @@ -332,23 +331,6 @@ fi AM_CONDITIONAL(ENABLE_DANE, test "$enable_dane" = "yes") -AC_ARG_WITH(unbound-root-key-file, AS_HELP_STRING([--with-unbound-root-key-file], - [specify the unbound root key file]), - unbound_root_key_file="$withval", -if test "$have_win" = yes; then - unbound_root_key_file="C:\\Program Files\\Unbound\\root.key" -else - if test -f /var/lib/unbound/root.key;then - unbound_root_key_file="/var/lib/unbound/root.key" - else - unbound_root_key_file="/etc/unbound/root.key" - fi -fi -) - -AC_DEFINE_UNQUOTED([UNBOUND_ROOT_KEY_FILE], - ["$unbound_root_key_file"], [The DNSSEC root key file]) - AC_ARG_WITH(system-priority-file, AS_HELP_STRING([--with-system-priority-file], [specify the system priority file]), system_priority_file="$withval", @@ -837,15 +819,5 @@ AC_MSG_NOTICE([System files: Blacklist file: $with_default_blacklist_file CRL file: $with_default_crl_file Priority file: $system_priority_file - DNSSEC root key file: $unbound_root_key_file ]) -if test ! -f "$unbound_root_key_file"; then -AC_MSG_WARN([[ -*** -*** The DNSSEC root key file in $unbound_root_key_file was not found. -*** This file is needed for the verification of DNSSEC responses. -*** Use the command: unbound-anchor -a "$unbound_root_key_file" -*** to generate or update it. -*** ]]) -fi diff --git a/libdane/Makefile.am b/libdane/Makefile.am index debf502def..72e3fea8ac 100644 --- a/libdane/Makefile.am +++ b/libdane/Makefile.am @@ -43,7 +43,7 @@ libgnutls_dane_la_LIBADD = ../gl/libgnu.la \ libgnutls_dane_la_LDFLAGS += -version-info $(LT_DANE_CURRENT):$(LT_DANE_REVISION):$(LT_DANE_AGE) -libgnutls_dane_la_LIBADD += $(LIBSOCKET) $(UNBOUND_LIBS) +libgnutls_dane_la_LIBADD += $(LIBSOCKET) $(ARES_LIBS) if HAVE_LD_VERSION_SCRIPT libgnutls_dane_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libdane.map diff --git a/libdane/dane-params.c b/libdane/dane-params.c index eff3548cb2..24990f9e34 100644 --- a/libdane/dane-params.c +++ b/libdane/dane-params.c @@ -27,7 +27,6 @@ #include <string.h> #include <errno.h> #include <arpa/inet.h> -#include <unbound.h> #include <gnutls/dane.h> #include <gnutls/x509.h> #include <gnutls/abstract.h> diff --git a/libdane/dane.c b/libdane/dane.c index ad9af867e2..6f4074887e 100644 --- a/libdane/dane.c +++ b/libdane/dane.c @@ -29,17 +29,27 @@ #include <string.h> #include <errno.h> #include <arpa/inet.h> -#include <unbound.h> +#include <ares.h> #include <gnutls/dane.h> #include <gnutls/x509.h> #include <gnutls/abstract.h> #include <gnutls/crypto.h> #include "../lib/gnutls_int.h" -#define MAX_DATA_ENTRIES 100 +#ifdef __sun +# pragma fini(lib_deinit) +# pragma init(lib_init) +# define _CONSTRUCTOR +# define _DESTRUCTOR +#else +# define _CONSTRUCTOR __attribute__((constructor)) +# define _DESTRUCTOR __attribute__((destructor)) +#endif + #define DEBUG #ifdef DEBUG #define gnutls_assert() fprintf(stderr, "ASSERT: %s: %d\n", __FILE__, __LINE__); +#define _gnutls_debug_log(str, ...) fprintf(stderr, str, ##__VA_ARGS__) #define gnutls_assert_val(x) gnutls_assert_val_int(x, __FILE__, __LINE__) static int gnutls_assert_val_int(int val, const char *file, int line) { @@ -49,21 +59,25 @@ static int gnutls_assert_val_int(int val, const char *file, int line) #else #define gnutls_assert() #define gnutls_assert_val(x) (x) +#define _gnutls_debug_log(...) #endif struct dane_state_st { - struct ub_ctx *ctx; + ares_channel channel; unsigned int flags; }; +struct reply_st { + uint8_t usage; + uint8_t selector; + uint8_t mtype; + uint8_t *data; + unsigned data_size; +}; + struct dane_query_st { - struct ub_result *result; - unsigned int data_entries; - dane_cert_usage_t usage[MAX_DATA_ENTRIES]; - dane_cert_type_t type[MAX_DATA_ENTRIES]; - dane_match_type_t match[MAX_DATA_ENTRIES]; - gnutls_datum_t data[MAX_DATA_ENTRIES]; - unsigned int flags; + struct reply_st *entries; + unsigned int n_entries; dane_query_status_t status; }; @@ -91,7 +105,7 @@ dane_query_status_t dane_query_status(dane_query_t q) **/ unsigned int dane_query_entries(dane_query_t q) { - return q->data_entries; + return q->n_entries; } /** @@ -104,7 +118,7 @@ unsigned int dane_query_entries(dane_query_t q) * @data: The DANE data. * * This function will provide the DANE data from the query - * response. + * response. The data should be treated as constant. * * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -112,23 +126,22 @@ unsigned int dane_query_entries(dane_query_t q) int dane_query_data(dane_query_t q, unsigned int idx, unsigned int *usage, unsigned int *type, - unsigned int *match, gnutls_datum_t * data) + unsigned int *match, gnutls_datum_t *data) { - if (idx >= q->data_entries) + if (idx >= q->n_entries) return gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE); if (usage) - *usage = q->usage[idx]; + *usage = q->entries[idx].usage; if (type) - *type = q->type[idx]; + *type = q->entries[idx].selector; if (match) - *match = q->match[idx]; + *match = q->entries[idx].mtype; if (data) { - data->data = q->data[idx].data; - data->size = q->data[idx].size; + data->data = q->entries[idx].data; + data->size = q->entries[idx].data_size; } - return DANE_E_SUCCESS; } @@ -232,55 +245,27 @@ dane_query_to_raw_tlsa(dane_query_t q, unsigned int *data_entries, **/ int dane_state_init(dane_state_t * s, unsigned int flags) { - struct ub_ctx *ctx; int ret; + struct ares_options options; *s = calloc(1, sizeof(struct dane_state_st)); if (*s == NULL) return gnutls_assert_val(DANE_E_MEMORY_ERROR); - ctx = ub_ctx_create(); - if (!ctx) { + memset(&options, 0, sizeof(options)); + options.flags = ARES_FLAG_DNSSEC; + ret = ares_init_options(&(*s)->channel, &options, ARES_OPT_FLAGS); + if (ret != ARES_SUCCESS) { gnutls_assert(); ret = DANE_E_INITIALIZATION_ERROR; goto cleanup; } - ub_ctx_debugout(ctx, stderr); - if (!(flags & DANE_F_IGNORE_LOCAL_RESOLVER)) { - if ((ret = ub_ctx_resolvconf(ctx, NULL)) != 0) { - gnutls_assert(); - ret = DANE_E_INITIALIZATION_ERROR; - goto cleanup; - } - - if ((ret = ub_ctx_hosts(ctx, NULL)) != 0) { - gnutls_assert(); - ret = DANE_E_INITIALIZATION_ERROR; - goto cleanup; - } - } - - /* read public keys for DNSSEC verification */ - if (!(flags & DANE_F_IGNORE_DNSSEC)) { - if ((ret = - ub_ctx_add_ta_file(ctx, - (char *) UNBOUND_ROOT_KEY_FILE)) != - 0) { - gnutls_assert(); - ret = DANE_E_INITIALIZATION_ERROR; - goto cleanup; - } - } - - (*s)->ctx = ctx; (*s)->flags = flags; return DANE_E_SUCCESS; cleanup: - if (ctx) - ub_ctx_delete(ctx); free(*s); return ret; @@ -295,7 +280,7 @@ int dane_state_init(dane_state_t * s, unsigned int flags) **/ void dane_state_deinit(dane_state_t s) { - ub_ctx_delete(s->ctx); + ares_destroy(s->channel); free(s); } @@ -310,14 +295,6 @@ void dane_state_deinit(dane_state_t s) **/ int dane_state_set_dlv_file(dane_state_t s, const char *file) { - int ret; - - ret = - ub_ctx_set_option(s->ctx, (char *) "dlv-anchor-file:", - (void *) file); - if (ret != 0) - return gnutls_assert_val(DANE_E_FILE_ERROR); - return 0; } @@ -330,8 +307,12 @@ int dane_state_set_dlv_file(dane_state_t s, const char *file) **/ void dane_query_deinit(dane_query_t q) { - if (q->result) - ub_resolve_free(q->result); + unsigned i; + + for (i=0;i<q->n_entries;i++) { + free(q->entries[i].data); + } + free(q->entries); free(q); } @@ -362,28 +343,44 @@ dane_raw_tlsa(dane_state_t s, dane_query_t * r, char *const *dane_data, { int ret = DANE_E_SUCCESS; unsigned int i; + unsigned entries = 0; + char *const * p = dane_data; + + while(p[entries]!=NULL) { + entries++; + } *r = calloc(1, sizeof(struct dane_query_st)); if (*r == NULL) return gnutls_assert_val(DANE_E_MEMORY_ERROR); - (*r)->data_entries = 0; + (*r)->n_entries = 0; + + (*r)->entries = calloc(1, sizeof((*r)->entries[0]) * entries); + if ((*r)->entries == NULL) { + free(*r); + return gnutls_assert_val(DANE_E_MEMORY_ERROR); + } - for (i = 0; i < MAX_DATA_ENTRIES; i++) { + for (i = 0; i < entries; i++) { if (dane_data[i] == NULL) break; - if (dane_data_len[i] <= 3) - return + if (dane_data_len[i] <= 3) { + ret = gnutls_assert_val (DANE_E_RECEIVED_CORRUPT_DATA); + goto fail; + } - (*r)->usage[i] = dane_data[i][0]; - (*r)->type[i] = dane_data[i][1]; - (*r)->match[i] = dane_data[i][2]; - (*r)->data[i].data = (void *) &dane_data[i][3]; - (*r)->data[i].size = dane_data_len[i] - 3; - (*r)->data_entries++; + (*r)->entries[i].usage = dane_data[i][0]; + (*r)->entries[i].selector = dane_data[i][1]; + (*r)->entries[i].mtype = dane_data[i][2]; + (*r)->entries[i].data = malloc(dane_data_len[i] - 3); + if ((*r)->entries[i].data != NULL) + memcpy((*r)->entries[i].data, &dane_data[i][3], dane_data_len[i] - 3); + (*r)->entries[i].data_size = dane_data_len[i] - 3; + (*r)->n_entries++; } if (!(s->flags & DANE_F_INSECURE) && !secure) { @@ -405,8 +402,103 @@ dane_raw_tlsa(dane_state_t s, dane_query_t * r, char *const *dane_data, } return ret; +fail: + free((*r)->entries); + free(*r); + return ret; + +} + +static void +query_cb(void *arg, int status, int timeouts, uint8_t *buf, int len) +{ +dane_query_t r = arg; +struct ares_tlsa_reply *p, *replies = NULL; +unsigned entries = 0, i; + + r->status = DANE_QUERY_BOGUS; + if(status != ARES_SUCCESS){ + _gnutls_debug_log("failed to lookup: %s\n", ares_strerror(status)); + return; + } + + status = ares_parse_tlsa_reply(buf, len, &replies); + if (status == ARES_ENODNSSEC) { + r->status = DANE_QUERY_NO_DNSSEC; + return; + } + + if(status != ARES_SUCCESS){ + _gnutls_debug_log("failed to parse TLSA: %s\n", ares_strerror(status)); + return; + } + + p = replies; + while(p != NULL) { + entries++; + p=p->next; + } + + r->entries = calloc(1, entries * sizeof(r->entries[0])); + if (r->entries == NULL) { + goto cleanup; + } + + p = replies; + i = 0; + while(p != NULL) { + r->entries[i].usage = p->usage; + r->entries[i].selector = p->selector; + r->entries[i].mtype = p->mtype; + r->entries[i].data_size = p->data_size; + r->entries[i].data = p->data; /* steal the allocated value */ + p->data = NULL; + i++; + p=p->next; + } + r->status = DANE_QUERY_DNSSEC_VERIFIED; + r->n_entries = entries; + + cleanup: + ares_free_data(replies); + return; +} + +static void _CONSTRUCTOR lib_init(void) +{ +int ret; + + ret = ares_library_init(ARES_LIB_INIT_ALL); + if (ret != ARES_SUCCESS) { + fprintf(stderr, "Error in Ares library initialization: %s\n", ares_strerror(ret)); + } } +static void _DESTRUCTOR lib_deinit(void) +{ + ares_library_cleanup(); +} + +static void wait_ares(ares_channel channel) +{ +struct timeval *tvp, tv; +fd_set read_fds, write_fds; +int nfds, ret; + + for(;;) { + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + nfds = ares_fds(channel, &read_fds, &write_fds); + if(nfds == 0) + break; + + tvp = ares_timeout(channel, NULL, &tv); + ret = select(nfds, &read_fds, &write_fds, NULL, tvp); + if (ret < 0) + break; + ares_process(channel, &read_fds, &write_fds); + } +} /** * dane_query_tlsa: @@ -427,32 +519,29 @@ dane_query_tlsa(dane_state_t s, dane_query_t * r, const char *host, const char *proto, unsigned int port) { char ns[1024]; - int ret; - struct ub_result *result; + int ret, id; + + ret = gnutls_rnd(GNUTLS_RND_NONCE, &id, sizeof(id)); + if (ret < 0) + return gnutls_assert_val(DANE_E_INITIALIZATION_ERROR); + id &= 0x0000ffff; + + *r = calloc(1, sizeof(struct dane_query_st)); + if (*r == NULL) + return gnutls_assert_val(DANE_E_MEMORY_ERROR); snprintf(ns, sizeof(ns), "_%u._%s.%s", port, proto, host); - /* query for webserver */ - ret = ub_resolve(s->ctx, ns, 52, 1, &result); - if (ret != 0) { - return gnutls_assert_val(DANE_E_RESOLVING_ERROR); - } + ares_query(s->channel, ns, 1, 52, query_cb, *r); -/* show first result */ - if (!result->havedata) { - ub_resolve_free(result); - return gnutls_assert_val(DANE_E_NO_DANE_DATA); - } + wait_ares(s->channel); - ret = - dane_raw_tlsa(s, r, result->data, result->len, result->secure, - result->bogus); - if (*r == NULL) { - ub_resolve_free(result); - return ret; + if ((*r)->n_entries == 0) { + free(*r); + return gnutls_assert_val(DANE_E_RESOLVING_ERROR); } - (*r)->result = result; - return ret; + + return 0; } |