From fbae577a542d1ad69ca96401acbdc04bbb843e46 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 23 Dec 2015 17:15:45 +0100 Subject: [PATCH] Setting of root servers test with getdns_query -f yeti.key -R yeti.hints nlnetlabs.nl A +dnssec_return_status where yeti.key comes from: https://raw.githubusercontent.com/BII-Lab/Yeti-Project/master/domain/named.cache and yeti.hints from: https://raw.githubusercontent.com/BII-Lab/Yeti-Project/master/domain/KSK.pub --- src/context.c | 152 ++++++++++++++++++++++++++-------------- src/context.h | 3 +- src/convert.c | 6 +- src/test/getdns_query.c | 65 ++++++++++++++++- 4 files changed, 165 insertions(+), 61 deletions(-) diff --git a/src/context.c b/src/context.c index adeb0752..00c685ce 100644 --- a/src/context.c +++ b/src/context.c @@ -96,7 +96,6 @@ getdns_port_str_array[] = { /* Private functions */ static getdns_return_t create_default_namespaces(struct getdns_context *context); static getdns_return_t create_default_dns_transports(struct getdns_context *context); -static struct getdns_list *create_default_root_servers(void); static getdns_return_t set_os_defaults(struct getdns_context *); static int transaction_id_cmp(const void *, const void *); static void dispatch_updated(struct getdns_context *, uint16_t); @@ -439,16 +438,6 @@ read_more: ; } } -/** - * Helper to get the default root servers. - * TODO: Implement - */ -static struct getdns_list * -create_default_root_servers() -{ - return NULL; -} - /** * check a file for changes since the last check * and refresh the current data if changes are detected @@ -910,7 +899,8 @@ getdns_context_create_with_extended_memory_functions( result->timeout = 5000; result->idle_timeout = 0; result->follow_redirects = GETDNS_REDIRECTS_FOLLOW; - result->dns_root_servers = create_default_root_servers(); + result->dns_root_servers = NULL; + result->root_servers_fn[0] = 0; result->append_name = GETDNS_APPEND_NAME_ALWAYS; result->suffix = NULL; @@ -1074,7 +1064,11 @@ getdns_context_destroy(struct getdns_context *context) if (context->tls_ctx) SSL_CTX_free(context->tls_ctx); - getdns_list_destroy(context->dns_root_servers); + if (context->dns_root_servers) + getdns_list_destroy(context->dns_root_servers); + if (context->root_servers_fn[0]) + unlink(context->root_servers_fn); + getdns_list_destroy(context->suffix); if (context->trust_anchors && @@ -1585,49 +1579,97 @@ getdns_context_set_follow_redirects(struct getdns_context *context, * */ getdns_return_t -getdns_context_set_dns_root_servers(struct getdns_context *context, - struct getdns_list * addresses) +getdns_context_set_dns_root_servers( + getdns_context *context, getdns_list *addresses) { - struct getdns_list *copy = NULL; - size_t count = 0; - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - if (context->resolution_type_set != 0) { - /* already setup */ - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; - } - if (addresses != NULL) { - if (_getdns_list_copy(addresses, ©) != GETDNS_RETURN_GOOD) { - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; - } - addresses = copy; - getdns_list_get_length(addresses, &count); - if (count == 0) { - getdns_list_destroy(addresses); - addresses = NULL; - } else { - size_t i = 0; - getdns_return_t r = GETDNS_RETURN_GOOD; - /* validate and add ip str */ - for (i = 0; i < count; ++i) { - struct getdns_dict *dict = NULL; - getdns_list_get_dict(addresses, i, &dict); - if (r != GETDNS_RETURN_GOOD) { - break; - } - } - if (r != GETDNS_RETURN_GOOD) { - getdns_list_destroy(addresses); - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; - } - } - } + char tmpfn[L_tmpnam]; + FILE *fh; + size_t i; + getdns_dict *rr_dict; + getdns_return_t r; + getdns_bindata *addr_bd; + char dst[2048]; + size_t dst_len; + getdns_list *newlist; - getdns_list_destroy(context->dns_root_servers); - context->dns_root_servers = addresses; + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; - dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS); + if (!addresses) { +#ifdef HAVE_LIBUNBOUND + if (ub_ctx_set_option( + context->unbound_ctx, "root-hints:", "")) + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; +#endif + if (context->dns_root_servers) + getdns_list_destroy(context->dns_root_servers); + context->dns_root_servers = NULL; - return GETDNS_RETURN_GOOD; + if (context->root_servers_fn[0]) + unlink(context->root_servers_fn); + context->root_servers_fn[0] = 0; + + dispatch_updated( + context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS); + return GETDNS_RETURN_GOOD; + } + if (!tmpnam(tmpfn)) + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; + + if (!(fh = fopen(tmpfn, "w"))) + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; + + for (i=0; (!(r = getdns_list_get_dict(addresses, i, &rr_dict))); i++) { + dst_len = sizeof(dst); + if (!getdns_rr_dict2str_buf(rr_dict, dst, &dst_len)) + + fprintf(fh, "%s", dst); + + else if (getdns_dict_get_bindata( + rr_dict, "address_data", &addr_bd) && + getdns_dict_get_bindata( + rr_dict, "/rdata/ipv4_address", &addr_bd) && + getdns_dict_get_bindata( + rr_dict, "/rdata/ipv6_address", &addr_bd)) + + ; /* pass */ + + else if (addr_bd->size == 16 && + inet_ntop(AF_INET6, addr_bd->data, dst, sizeof(dst))) + + fprintf(fh, ". NS %zu.root-servers.getdnsapi.net.\n" + "%zu.root-servers.getdnsapi.net. AAAA %s\n", + i, i, dst); + + else if (addr_bd->size == 4 && + inet_ntop(AF_INET, addr_bd->data, dst, sizeof(dst))) + + fprintf(fh, ". NS %zu.root-servers.getdnsapi.net.\n" + "%zu.root-servers.getdnsapi.net. A %s\n", + i, i, dst); + } + fclose(fh); +#ifdef HAVE_LIBUNBOUND + if (ub_ctx_set_option( + context->unbound_ctx, "root-hints:", tmpfn)) { + unlink(tmpfn); + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; + } +#endif + if (_getdns_list_copy(addresses, &newlist)) { + unlink(tmpfn); + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; + } + if (context->dns_root_servers) + getdns_list_destroy(context->dns_root_servers); + context->dns_root_servers = newlist; + + if (context->root_servers_fn[0]) + unlink(context->root_servers_fn); + (void) memcpy(context->root_servers_fn, tmpfn, L_tmpnam); + + dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS); + return GETDNS_RETURN_GOOD; } /* getdns_context_set_dns_root_servers */ /* @@ -2317,6 +2359,9 @@ ub_setup_recursing(struct ub_ctx *ctx, getdns_context *context) /* TODO: use the root servers via root hints file */ (void) ub_ctx_set_fwd(ctx, NULL); if (!context->unbound_ta_set && context->trust_anchors) { + /* fprintf(stderr, "set root hints %d\n", + ub_ctx_set_option(ctx, "root-hints:", "/home/willem/test.hints")); */ + for ( rr = _getdns_rr_iter_init( &rr_spc , context->trust_anchors , context->trust_anchors_len) @@ -2995,9 +3040,8 @@ getdns_context_get_dns_root_servers(getdns_context *context, RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); *value = NULL; - if (context->dns_root_servers) { + if (context->dns_root_servers) return _getdns_list_copy(context->dns_root_servers, value); - } return GETDNS_RETURN_GOOD; } diff --git a/src/context.h b/src/context.h index cc345983..264cb687 100644 --- a/src/context.h +++ b/src/context.h @@ -168,7 +168,8 @@ struct getdns_context { uint64_t timeout; uint64_t idle_timeout; getdns_redirects_t follow_redirects; - struct getdns_list *dns_root_servers; + getdns_list *dns_root_servers; + char root_servers_fn[L_tmpnam]; getdns_append_name_t append_name; struct getdns_list *suffix; uint8_t *trust_anchors; diff --git a/src/convert.c b/src/convert.c index 2c9440b3..9e42dce0 100644 --- a/src/convert.c +++ b/src/convert.c @@ -393,7 +393,6 @@ getdns_rr_dict2str( free(buf); return r; } - buf[buf_len] = 0; *str = buf; return GETDNS_RETURN_GOOD; } @@ -459,9 +458,10 @@ getdns_rr_dict2str_scan( *str = prev_str + sz_needed; *str_len = prev_str_len - sz_needed; r = GETDNS_RETURN_NEED_MORE_SPACE; - } else + } else { *str_len = sz; - + *str = 0; + } if (buf != buf_spc) GETDNS_FREE(rr_dict->mf, buf); return r; diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index aeed3602..2d00c985 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -465,6 +465,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-d\tclear edns0 do bit\n"); fprintf(out, "\t-e \tSet idle timeout in miliseconds\n"); fprintf(out, "\t-F \tread the queries from the specified file\n"); + fprintf(out, "\t-f \tRead DNSSEC trust anchors from \n"); fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-H\thostname lookup. ( must be an IP address; is ignored)\n"); fprintf(out, "\t-h\tPrint this help\n"); @@ -478,6 +479,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-p\tPretty print response dict\n"); fprintf(out, "\t-P \tPad TLS queries to a multiple of blocksize\n"); fprintf(out, "\t-r\tSet recursing resolution type\n"); + fprintf(out, "\t-R \tRead root hints from \n"); fprintf(out, "\t-q\tQuiet mode - don't print response\n"); fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n"); fprintf(out, "\t-S\tservice lookup ( is ignored)\n"); @@ -507,7 +509,8 @@ static getdns_return_t validate_chain(getdns_dict *response) if (!(to_validate = getdns_list_create())) return GETDNS_RETURN_MEMORY_ERROR; - trust_anchor = getdns_root_trust_anchor(NULL); + if (getdns_context_get_dnssec_trust_anchors(context, &trust_anchor)) + trust_anchor = getdns_root_trust_anchor(NULL); if ((r = getdns_dict_get_list( response, "validation_chain", &validation_chain))) @@ -677,8 +680,9 @@ getdns_return_t parse_args(int argc, char **argv) char *arg, *c, *endptr; int t, print_api_info = 0, print_trust_anchors = 0; getdns_list *upstream_list = NULL; - getdns_list *tas = NULL; + getdns_list *tas = NULL, *hints = NULL; size_t upstream_count = 0; + FILE *fh; for (i = 1; i < argc; i++) { arg = argv[i]; @@ -758,6 +762,33 @@ getdns_return_t parse_args(int argc, char **argv) case 'd': (void) getdns_context_set_edns_do_bit(context, 0); break; + case 'f': + if (c[1] != 0 || ++i >= argc || !*argv[i]) { + fprintf(stderr, "file name expected " + "after -f\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (!(fh = fopen(argv[i], "r"))) { + fprintf(stderr, "Could not open \"%s\"" + ": %s\n",argv[i], strerror(errno)); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (getdns_fp2rr_list(fh, &tas, NULL, 3600)) { + fprintf(stderr,"Could not parse " + "\"%s\"\n", argv[i]); + return GETDNS_RETURN_GENERIC_ERROR; + } + fclose(fh); + if (getdns_context_set_dnssec_trust_anchors( + context, tas)) { + fprintf(stderr,"Could not set " + "trust anchors from \"%s\"\n", + argv[i]); + return GETDNS_RETURN_GENERIC_ERROR; + } + getdns_list_destroy(tas); + tas = NULL; + break; case 'F': if (c[1] != 0 || ++i >= argc || !*argv[i]) { fprintf(stderr, "file name expected " @@ -826,6 +857,33 @@ getdns_return_t parse_args(int argc, char **argv) context, GETDNS_RESOLUTION_RECURSING); break; + case 'R': + if (c[1] != 0 || ++i >= argc || !*argv[i]) { + fprintf(stderr, "file name expected " + "after -f\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (!(fh = fopen(argv[i], "r"))) { + fprintf(stderr, "Could not open \"%s\"" + ": %s\n",argv[i], strerror(errno)); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (getdns_fp2rr_list(fh, &hints, NULL, 3600)) { + fprintf(stderr,"Could not parse " + "\"%s\"\n", argv[i]); + return GETDNS_RETURN_GENERIC_ERROR; + } + fclose(fh); + if (getdns_context_set_dns_root_servers( + context, hints)) { + fprintf(stderr,"Could not set " + "root servers from \"%s\"\n", + argv[i]); + return GETDNS_RETURN_GENERIC_ERROR; + } + getdns_list_destroy(hints); + hints = NULL; + break; case 's': getdns_context_set_resolution_type( context, GETDNS_RESOLUTION_STUB); @@ -932,7 +990,8 @@ next: ; return CONTINUE; } if (print_trust_anchors) { - if ((tas = getdns_root_trust_anchor(NULL))) { + if (!getdns_context_get_dnssec_trust_anchors(context, &tas)) { + /* if ((tas = getdns_root_trust_anchor(NULL))) { */ fprintf(stdout, "%s\n", getdns_pretty_print_list(tas)); return CONTINUE; } else