diff --git a/ChangeLog b/ChangeLog index b3a1dbc1..e154f85e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,49 @@ -* 2016-??-??: Version 1.0.0 +* 2016-07-14: Version 1.0.0b2 + * Collect coverage information from the unit tests + Thanks Shane Kerr + * pkg-config for the getdns_ext_event library + Thanks Tom Pusateri + * Bugfix: Multiple requests on the same upstream with a transport + that keeps connections open in synchronous stub mode. + * Canonicalized DNSSEC chain with dnssec_return_validation_chain + (when validated) + * A dnssec_return_full_validation_chain extension which includes + then validated resource records. + * Bugfix: Callbacks fired while scheduling (answer from cache) + with the unbound plugable event API + * header extension to set opcode and flags in stub mode + * Unit tests that cover more code + * Static checking with the clang analyzer + * getdns_pretty_print_dict prints dname's as primitives + * Accept just bindata's instead of address dicts. + Allow misshing "address_type" in address dicts. + * TLS session resumption + * -C option to getdns_query to configure context + from a json like formated file. The output of -i (print API + information) can be used as config file directly. + Settings may also be given in this format as arguments of + the getdns_query command directly. + * DNS server mode for getdns_query. Enable by providing addresses + to listen on, either by giving "-z " options or by + providing "listen_addresses" in the config file or settings. + * Bugfixes from deckard testing: CNAME loop protection. + * "srv_addresses" in response dict with getdns_service() + * use libbsd when available + Thanks Guillem Jover + * Bugfix: DNSSEC wildcard validation issue + * Bugfix: TLS timeouts not re-using a connection + * A getdns_context_get_eventloop(), to get the current + (pluggable) eventloop from context + * getdns_query now uses the default event loop (instead of custom) + * Return call_reporting info in case of timeout + Thanks Robert Groenenberg + * Bugfix: Build fails with autoconf 2.63, works with 2.68. + Thanks Robert Groenenberg + * Doxygen output for getdns.h and getdns_extra.h only + * Do not call SSL_library_init() from getdns_context_create() when + the second bit from the set_from_os parameter is set. + +* 2016-03-31: Version 1.0.0b1 * openssl 1.1.0 support * GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST default suffix handling * getdns_context_set_follow_redirects() diff --git a/Makefile.in b/Makefile.in index 331c889e..3f727468 100644 --- a/Makefile.in +++ b/Makefile.in @@ -178,6 +178,7 @@ $(distdir): mkdir -p $(distdir)/src mkdir -p $(distdir)/src/getdns mkdir -p $(distdir)/src/test + mkdir -p $(distdir)/src/test/jsmn mkdir -p $(distdir)/src/extension mkdir -p $(distdir)/src/compat mkdir -p $(distdir)/src/util @@ -224,6 +225,9 @@ $(distdir): cp $(srcdir)/spec/*.tgz $(distdir)/spec || true cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example + cp $(srcdir)/src/test/jsmn/*.[ch] $(distdir)/src/test/jsmn + cp $(srcdir)/src/test/jsmn/LICENSE $(distdir)/src/test/jsmn + cp $(srcdir)/src/test/jsmn/README.md $(distdir)/src/test/jsmn rm -f $(distdir)/Makefile $(distdir)/src/Makefile $(distdir)/src/getdns/getdns.h $(distdir)/spec/example/Makefile $(distdir)/src/test/Makefile $(distdir)/doc/Makefile $(distdir)/src/config.h distcheck: $(distdir).tar.gz diff --git a/README.md b/README.md index 28a4d6ab..b1507f61 100644 --- a/README.md +++ b/README.md @@ -315,6 +315,7 @@ To configure: Contributors ============ +* Claus Assman * Theogene Bucuti * Andrew Cathrow, Verisign Labs * Neil Cook @@ -322,26 +323,34 @@ Contributors * Craig Despeaux, Verisign, Inc. * John Dickinson, Sinodun * Sara Dickinson, Sinodun +* Robert Edmonds * Angelique Finan, Verisign, Inc. +* Simson Garfinkel * Daniel Kahn Gillmor * Neel Goyal, Verisign, Inc. * Bryan Graham, Verisign, Inc. +* Robert Groenenberg * Paul Hoffman * Scott Hollenbeck, Verising, Inc. * Shumon Huque, Verisign Labs +* Jelte Janssen +* Guillem Jover * Shane Kerr * Anthony Kirby * Olaf Kolkman, NLnet Labs * Sanjay Mahurpawar, Verisign, Inc. * Allison Mankin, Verisign, Inc. - Verisign Labs. * Sai Mogali, Verisign, Inc. +* Linus Nordberg * Benno Overeinder, NLnet Labs * Joel Purra +* Tom Pusateri * Prithvi Ranganath, Verisign, Inc. * Rushi Shah, Verisign, Inc. * Vinay Soni, Verisign, Inc. * Melinda Shore, No Mountain Software LLC * Bob Steagall, Verisign, Inc. +* Ondřej Surý * Willem Toorop, NLnet Labs * Gowri Visweswaran, Verisign Labs * Wouter Wijngaards, NLnet Labs diff --git a/configure.ac b/configure.ac index cddf86ac..b2c066a2 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/pkg.m4) AC_INIT([getdns], [1.0.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) -AC_SUBST(RELEASE_CANDIDATE, [b1]) +AC_SUBST(RELEASE_CANDIDATE, [b2]) # Set current date from system if not set AC_ARG_WITH([current-date], @@ -47,7 +47,7 @@ AC_ARG_WITH([current-date], [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"]) AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"]) -AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00100100]) +AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00100200]) AC_SUBST(API_VERSION, ["December 2015"]) AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00]) GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API" @@ -76,9 +76,10 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRE # getdns-0.3.3 had libversion 3:6:2 # getdns-0.5.0 had libversion 4:0:3 # getdns-0.5.1 had libversion 4:1:3 (but should have been getdns-0.6.0) -# getdns-0.9.0 will have libversion 5:0:4 +# getdns-0.9.0 had libversion 5:0:4 +# getdns-1.0.0 will have libversion 5:1:4 # -GETDNS_LIBVERSION=5:0:4 +GETDNS_LIBVERSION=5:1:4 AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_LIBVERSION) diff --git a/project-doc/getdns_query-deamon-behaviour.ods b/project-doc/getdns_query-deamon-behaviour.ods new file mode 100644 index 00000000..041cebc7 Binary files /dev/null and b/project-doc/getdns_query-deamon-behaviour.ods differ diff --git a/project-doc/getdns_query-deamon-behaviour.pdf b/project-doc/getdns_query-deamon-behaviour.pdf new file mode 100644 index 00000000..f97f81b8 Binary files /dev/null and b/project-doc/getdns_query-deamon-behaviour.pdf differ diff --git a/src/context.c b/src/context.c index b46dc3bd..a93e6f14 100644 --- a/src/context.c +++ b/src/context.c @@ -1277,10 +1277,10 @@ getdns_context_create_with_extended_memory_functions( // resolv.conf does not exist on Windows, handle differently #ifndef USE_WINSOCK - if (set_from_os && (r = set_os_defaults(result))) + if ((set_from_os & 1) && (r = set_os_defaults(result))) goto error; #else - if (set_from_os && (r = set_os_defaults_windows(result))) + if ((set_from_os & 1) && (r = set_os_defaults_windows(result))) goto error; #endif @@ -1297,7 +1297,9 @@ getdns_context_create_with_extended_memory_functions( /* Unbound needs SSL to be init'ed this early when TLS is used. However we * don't know that till later so we will have to do this every time. */ - SSL_library_init(); + if ((set_from_os & 2) == 0) + SSL_library_init(); + #ifdef HAVE_LIBUNBOUND result->unbound_ctx = NULL; if ((r = rebuild_ub_ctx(result))) diff --git a/src/convert.c b/src/convert.c index 2539d7bd..9ce2fa39 100644 --- a/src/convert.c +++ b/src/convert.c @@ -51,6 +51,7 @@ #include "dict.h" #include "list.h" #include "convert.h" +#include "debug.h" /* stuff to make it compile pedantically */ #define UNUSED_PARAM(x) ((void)(x)) @@ -611,6 +612,15 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf, if (!wire || !*wire || !wire_len || !msg_dict) return GETDNS_RETURN_INVALID_PARAMETER; +#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG + do { + char *str = gldns_wire2str_pkt((uint8_t *)*wire, *wire_len); + DEBUG_SERVER("_getdns_wire2msg_dict_scan for a packet size: %d: %s\n", + (int)*wire_len, str); + free(str); + } while(0); +#endif + if (!(result = _getdns_dict_create_with_mf(mf)) || !(header = _getdns_dict_create_with_mf(mf)) || !(sections[SECTION_ANSWER] @@ -768,11 +778,12 @@ _getdns_reply_dict2wire( const getdns_dict *reply, gldns_buffer *buf, int reuse_header) { uint8_t header_spc[GLDNS_HEADER_SIZE], *header; - uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN; + uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN, rr_type; size_t pkt_start, i; getdns_list *section; getdns_dict *rr_dict; getdns_bindata *qname; + int remove_dnssec; pkt_start = gldns_buffer_position(buf); if (reuse_header) { @@ -814,11 +825,18 @@ _getdns_reply_dict2wire( buf, pkt_start+GLDNS_ARCOUNT_OFF, 0); } } + remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0; + DEBUG_SERVER("remove_dnssec: %d\n", remove_dnssec); + if (!getdns_dict_get_list(reply, "answer", §ion)) { for ( n = 0, i = 0 ; !getdns_list_get_dict(section, i, &rr_dict); i++) { - if (!_getdns_rr_dict2wire(rr_dict, buf)) + if (remove_dnssec && + !getdns_dict_get_int(rr_dict, "type", &rr_type) && + rr_type == GETDNS_RRTYPE_RRSIG) + continue; + if (!_getdns_rr_dict2wire(rr_dict, buf)) n++; } gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n); @@ -827,7 +845,15 @@ _getdns_reply_dict2wire( for ( n = 0, i = 0 ; !getdns_list_get_dict(section, i, &rr_dict); i++) { - if (!_getdns_rr_dict2wire(rr_dict, buf)) + if (remove_dnssec && + !getdns_dict_get_int(rr_dict, "type", &rr_type) && + ( rr_type == GETDNS_RRTYPE_RRSIG + || rr_type == GETDNS_RRTYPE_NSEC + || rr_type == GETDNS_RRTYPE_NSEC3 + || rr_type == GETDNS_RRTYPE_DS + )) + continue; + if (!_getdns_rr_dict2wire(rr_dict, buf)) n++; } gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_NSCOUNT_OFF, n); @@ -836,6 +862,10 @@ _getdns_reply_dict2wire( for ( n = 0, i = 0 ; !getdns_list_get_dict(section, i, &rr_dict); i++) { + if (remove_dnssec && + !getdns_dict_get_int(rr_dict, "type", &rr_type) && + rr_type == GETDNS_RRTYPE_RRSIG) + continue; if (!_getdns_rr_dict2wire(rr_dict, buf)) n++; } diff --git a/src/dnssec.c b/src/dnssec.c index b46be44b..f567b96b 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -2049,7 +2049,8 @@ static int find_nsec_covering_name( , SECTION_NO_ADDITIONAL) ; i ; i = _getdns_rrset_iter_next(i)) { - if ((n = _getdns_rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC3 + if ((n = _getdns_rrset_iter_value(i)) + && n->rr_type == GETDNS_RRTYPE_NSEC3 /* Get the bitmap rdata field */ && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, n)) @@ -2085,7 +2086,8 @@ static int find_nsec_covering_name( return keytag; } - if ((n = _getdns_rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC + if ((n = _getdns_rrset_iter_value(i)) + && n->rr_type == GETDNS_RRTYPE_NSEC && nsec_covers_name(n, name, NULL) /* Get the bitmap rdata field */ diff --git a/src/getdns/getdns.h.in b/src/getdns/getdns.h.in index fedf9f2f..2a8f7f2a 100644 --- a/src/getdns/getdns.h.in +++ b/src/getdns/getdns.h.in @@ -965,7 +965,8 @@ getdns_service(getdns_context *context, * If used multi-threaded, user must define appropriate OpenSSL callback locking functions * (e.g. CRYPTO_THREADID_set_call) depending on the library version used. * @param context context that can be used immediately with other API calls - * @param set_from_os select to use os defaults or to specify user defined values + * @param set_from_os set to 1 to initialize the context with os defaults + * the second bit set (2) prevents OpenSSL library initialization. * @return GETDNS_RETURN_GOOD on success */ getdns_return_t @@ -977,10 +978,11 @@ getdns_context_create(getdns_context ** context, int set_from_os); * If used multi-threaded, user must define appropriate OpenSSL callback locking functions * (e.g. CRYPTO_THREADID_set_call) depending on the library version used. * @param context context that can be used immediately with other API calls - * @param set_from_os select to use os defaults or to specify user defined values + * @param set_from_os set to 1 to initialize the context with os defaults + * the second bit set (2) prevents OpenSSL library initialization. * @param malloc custom malloc function * @param realloc custom realloc function - * @param malloc custom free function + * @param free custom free function * @return GETDNS_RETURN_GOOD on success */ getdns_return_t @@ -998,10 +1000,12 @@ getdns_context_create_with_memory_functions( * If used multi-threaded, user must define appropriate OpenSSL callback locking functions * (e.g. CRYPTO_THREADID_set_call) depending on the library version used. * @param context context that can be used immediately with other API calls - * @param set_from_os select to use os defaults or to specify user defined values + * @param set_from_os set to 1 to initialize the context with os defaults + * the second bit set (2) prevents OpenSSL library initialization. + * @param userarg parameter passed to the custom malloc, realloc and free functions * @param malloc custom malloc function * @param realloc custom realloc function - * @param malloc custom free function + * @param free custom free function * @return GETDNS_RETURN_GOOD on success */ getdns_return_t diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 3f7647d4..7e2a16e3 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -361,9 +361,9 @@ getdns_context_get_tls_authentication(getdns_context *context, * "chain" context update callbacks and in this way create a subscription * service catering multiple interested parties. * @param context The context to monitor for changes - * @return userarg A user defined argument to be passed to the callback + * @param userarg A user defined argument to be passed to the callback * function. - * @return value The callback function to be called on context value + * @param value The callback function to be called on context value * changes. * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ @@ -399,11 +399,11 @@ const char *getdns_get_errorstr_by_id(uint16_t err); /* dict util */ /* set a string as bindata */ -getdns_return_t getdns_dict_util_set_string(struct getdns_dict * dict, +getdns_return_t getdns_dict_util_set_string(getdns_dict * dict, char *name, const char *value); /* get a string from a dict. the result must be freed if valid */ -getdns_return_t getdns_dict_util_get_string(struct getdns_dict * dict, +getdns_return_t getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result); /** @@ -484,7 +484,7 @@ getdns_dict* getdns_pubkey_pin_create_from_string( * * @param pinset the set of public key pins to check for sanity. This * should be a list of dicts. - * @return errorlist if not NULL, a list of human-readable strings is + * @param errorlist if not NULL, a list of human-readable strings is * appended to errorlist. * @return GETDNS_RETURN_GOOD if the pinset passes the sanity check. */ @@ -592,8 +592,8 @@ getdns_snprint_json_list( * Convert rr_dict to wireformat representation of the resource record. * * @param rr_dict The getdns dict representation of the resource record - * @return wire A newly allocated buffer which will contain the wireformat. - * @return wire_sz The size of the allocated buffer and the wireformat. + * @param wire A newly allocated buffer which will contain the wireformat. + * @param wire_sz The size of the allocated buffer and the wireformat. * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -644,7 +644,7 @@ getdns_rr_dict2wire_scan( * * @param wire Buffer containing the wireformat rr * @param wire_sz Size of the wire buffer - * @return rr_dict The returned rr_dict + * @param rr_dict The returned rr_dict * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -657,7 +657,7 @@ getdns_wire2rr_dict( * @param wire Buffer containing the wireformat rr * @param wire_sz On input the size of the wire buffer * On output the length of the wireformat rr. - * @return rr_dict The returned rr_dict + * @param rr_dict The returned rr_dict * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -673,7 +673,7 @@ getdns_wire2rr_dict_buf( * @param wire_sz On input the size of the wire buffer * On output the size is decreased with the length * of the wireformat resource record. - * @return rr_dict The returned rr_dict + * @param rr_dict The returned rr_dict * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -685,7 +685,7 @@ getdns_wire2rr_dict_scan( * Convert rr_dict to the string representation of the resource record. * * @param rr_dict The getdns dict representation of the resource record - * @return str A newly allocated string representation of the rr + * @param str A newly allocated string representation of the rr * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -735,7 +735,7 @@ getdns_rr_dict2str_scan( * Convert the string representation of the resource record to rr_dict format. * * @param str String representation of the resource record. - * @return rr_dict The result getdns dict representation of the resource record + * @param rr_dict The result getdns dict representation of the resource record * @param origin Default suffix for not fully qualified domain names * @param default_ttl Default ttl * @return GETDNS_RETURN_GOOD on success or an error code on failure. @@ -748,8 +748,8 @@ getdns_str2rr_dict( /** * Read the zonefile and convert to a list of rr_dict's. * - * @param FILE An opened FILE pointer on the zone file. - * @return rr_list The result list of rr_dicts representing the zone file. + * @param in An opened FILE pointer on the zone file. + * @param rr_list The result list of rr_dicts representing the zone file. * @param origin Default suffix for not fully qualified domain names * @param default_ttl Default ttl * @return GETDNS_RETURN_GOOD on success or an error code on failure. @@ -763,8 +763,8 @@ getdns_fp2rr_list( * Convert DNS message dict to wireformat representation. * * @param msg_dict The getdns dict representation of a DNS message - * @return wire A newly allocated buffer which will contain the wireformat. - * @return wire_sz The size of the allocated buffer and the wireformat. + * @param wire A newly allocated buffer which will contain the wireformat. + * @param wire_sz The size of the allocated buffer and the wireformat. * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -815,7 +815,7 @@ getdns_msg_dict2wire_scan( * * @param wire Buffer containing the wireformat rr * @param wire_sz Size of the wire buffer - * @return msg_dict The returned DNS message + * @param msg_dict The returned DNS message * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -828,7 +828,7 @@ getdns_wire2msg_dict( * @param wire Buffer containing the wireformat rr * @param wire_sz On input the size of the wire buffer * On output the length of the wireformat rr. - * @return msg_dict The returned DNS message + * @param msg_dict The returned DNS message * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -844,7 +844,7 @@ getdns_wire2msg_dict_buf( * @param wire_sz On input the size of the wire buffer * On output the size is decreased with the length * of the wireformat DNS message. - * @return msg_dict The returned DNS message + * @param msg_dict The returned DNS message * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t @@ -856,7 +856,7 @@ getdns_wire2msg_dict_scan( * Convert msg_dict to the string representation of the DNS message. * * @param msg_dict The getdns dict representation of the DNS message - * @return str A newly allocated string representation of the rr + * @param str A newly allocated string representation of the rr * @return GETDNS_RETURN_GOOD on success or an error code on failure. */ getdns_return_t diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index 703ee31e..b13580ea 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -421,7 +421,8 @@ enum gldns_enum_edns_option GLDNS_EDNS_DHU = 6, /* RFC6975 */ GLDNS_EDNS_N3U = 7, /* RFC6975 */ GLDNS_EDNS_CLIENT_SUBNET = 8, /* draft-vandergaast-edns-client-subnet */ - GLDNS_EDNS_KEEPALIVE = 11 /* draft-ietf-dnsop-edns-tcp-keepalive*/ + GLDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/ + GLDNS_EDNS_PADDING = 12 /* RFC7830 */ }; typedef enum gldns_enum_edns_option gldns_edns_option; diff --git a/src/gldns/wire2str.c b/src/gldns/wire2str.c index b9a979eb..abc055d7 100644 --- a/src/gldns/wire2str.c +++ b/src/gldns/wire2str.c @@ -166,6 +166,7 @@ static gldns_lookup_table gldns_edns_options_data[] = { { 7, "N3U" }, { 8, "edns-client-subnet" }, { 11, "edns-tcp-keepalive"}, + { 12, "Padding" }, { 0, NULL} }; gldns_lookup_table* gldns_edns_options = gldns_edns_options_data; @@ -1886,7 +1887,10 @@ int gldns_wire2str_edns_option_print(char** s, size_t* sl, break; case GLDNS_EDNS_KEEPALIVE: w += gldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen); - break; + break; + case GLDNS_EDNS_PADDING: + w += print_hex_buf(s, sl, optdata, optlen); + break; default: /* unknown option code */ w += print_hex_buf(s, sl, optdata, optlen); diff --git a/src/rr-iter.c b/src/rr-iter.c index e6a711de..9b332603 100644 --- a/src/rr-iter.c +++ b/src/rr-iter.c @@ -306,7 +306,7 @@ static int rr_owner_equal(_getdns_rr_iter *rr, const uint8_t *name) return (owner = _getdns_owner_if_or_as_decompressed(rr, owner_spc ,&owner_len)) - && _getdns_dname_equal(owner, name); + && name && _getdns_dname_equal(owner, name); } /* First a few filter functions that filter a RR iterator to point only diff --git a/src/test/getdns_context_set_listen_addresses.c b/src/test/getdns_context_set_listen_addresses.c index eeeac3ad..9246b640 100644 --- a/src/test/getdns_context_set_listen_addresses.c +++ b/src/test/getdns_context_set_listen_addresses.c @@ -503,6 +503,72 @@ static void udp_read_cb(void *userarg) close(l->fd); l->fd = -1; +#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG + } else { + char addrbuf[100]; + char hexbuf[4096], *hexptr; + size_t l, i, j; + + if (conn->remote_in.ss_family == AF_INET) { + if (inet_ntop(AF_INET, + &((struct sockaddr_in*)&conn->remote_in)->sin_addr, + addrbuf, sizeof(addrbuf))) { + + l = strlen(addrbuf); + (void) snprintf(addrbuf + l, + sizeof(addrbuf) - l, ":%d", + (int)((struct sockaddr_in*) + &conn->remote_in)->sin_port); + } else + (void) strncpy( + addrbuf, "error ipv4", sizeof(addrbuf)); + + } else if (conn->remote_in.ss_family == AF_INET6) { + addrbuf[0] = '['; + if (inet_ntop(AF_INET6, + &((struct sockaddr_in6*) + &conn->remote_in)->sin6_addr, + addrbuf, sizeof(addrbuf))) { + + l = strlen(addrbuf); + (void) snprintf(addrbuf + l, + sizeof(addrbuf) - l, ":%d", + (int)((struct sockaddr_in6*) + &conn->remote_in)->sin6_port); + } else + (void) strncpy( + addrbuf, "error ipv6", sizeof(addrbuf)); + + } else { + (void) strncpy( + addrbuf, "unknown address", sizeof(addrbuf)); + } + *(hexptr = hexbuf) = 0; + for (i = 0; i < len; i++) { + if (i % 12 == 0) { + hexptr += snprintf(hexptr, + sizeof(hexbuf) - (hexptr - hexbuf) - 1, + "\n%.4x", (int)i); + } else if (i % 4 == 0) { + hexptr += snprintf(hexptr, + sizeof(hexbuf) - (hexptr - hexbuf) - 1, + " "); + } + if (hexptr - hexbuf > sizeof(hexbuf)) + break; + hexptr += snprintf(hexptr, + sizeof(hexbuf) - (hexptr - hexbuf) - 1, + " %.2x", (int)buf[i]); + if (hexptr - hexbuf > sizeof(hexbuf)) + break; + } + DEBUG_SERVER("Received %d bytes from %s: %s\n", + (int)len, addrbuf, hexbuf); + } + if (len == -1) { + ; /* pass */ +#endif + } else if ((r = getdns_wire2msg_dict(buf, len, &request_dict))) ; /* FROMERR on input, ignore */ @@ -673,7 +739,8 @@ static getdns_return_t add_listeners(listen_set *set) } getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, - getdns_request_handler_t request_handler, getdns_list *listen_addresses) + getdns_request_handler_t request_handler, + const getdns_list *listen_addresses) { static const getdns_transport_list_t listen_transports[] = { GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP }; @@ -737,6 +804,8 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, new_set->count = new_set_count * n_transports; (void) memset(new_set->items, 0, sizeof(listener) * new_set_count * n_transports); + for (i = 0; i < new_set->count; i++) + new_set->items[i].fd = -1; (void) memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; @@ -839,7 +908,7 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, /* So the event can be rescheduled */ } } - if ((r = add_listeners(new_set))) { + if (r || (r = add_listeners(new_set))) { for (i = 0; i < new_set->count; i++) new_set->items[i].action = to_remove; diff --git a/src/test/getdns_context_set_listen_addresses.h b/src/test/getdns_context_set_listen_addresses.h index 116634f4..fac16f48 100644 --- a/src/test/getdns_context_set_listen_addresses.h +++ b/src/test/getdns_context_set_listen_addresses.h @@ -35,8 +35,9 @@ typedef void (*getdns_request_handler_t)( getdns_transaction_t request_id ); -getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, - getdns_request_handler_t request_handler, getdns_list *listen_addresses); +getdns_return_t getdns_context_set_listen_addresses( + getdns_context *context, getdns_request_handler_t request_handler, + const getdns_list *listen_addresses); getdns_return_t getdns_reply(getdns_context *context, getdns_transaction_t request_id, getdns_dict *reply); diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 8a7c34d7..5c98d8f9 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #ifndef USE_WINSOCK @@ -70,7 +71,55 @@ static int timeout, edns0_size, padding_blocksize; static int async = 0, interactive = 0; static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL; -int get_rrtype(const char *t); +static int get_rrtype(const char *t) +{ + char buf[1024] = "GETDNS_RRTYPE_"; + uint32_t rrtype; + long int l; + size_t i; + char *endptr; + + if (strlen(t) > sizeof(buf) - 15) + return -1; + for (i = 14; *t && i < sizeof(buf) - 1; i++, t++) + buf[i] = toupper(*t); + buf[i] = '\0'; + + if (!getdns_str2int(buf, &rrtype)) + return (int)rrtype; + + if (strncasecmp(buf + 14, "TYPE", 4) == 0) { + l = strtol(buf + 18, &endptr, 10); + if (!*endptr && l >= 0 && l < 65536) + return l; + } + return -1; +} + +static int get_rrclass(const char *t) +{ + char buf[1024] = "GETDNS_RRCLASS_"; + uint32_t rrclass; + long int l; + size_t i; + char *endptr; + + if (strlen(t) > sizeof(buf) - 16) + return -1; + for (i = 15; *t && i < sizeof(buf) - 1; i++, t++) + buf[i] = toupper(*t); + buf[i] = '\0'; + + if (!getdns_str2int(buf, &rrclass)) + return (int)rrclass; + + if (strncasecmp(buf + 15, "CLASS", 5) == 0) { + l = strtol(buf + 20, &endptr, 10); + if (!*endptr && l >= 0 && l < 65536) + return l; + } + return -1; +} static getdns_return_t fill_transport_list(getdns_context *context, char *transport_list_str, @@ -393,12 +442,11 @@ static void parse_config(const char *config_str) * will get destroyed. */ if (!listen_dict && - !(listen_dict = getdns_dict_create())) { + !(listen_dict = getdns_dict_create())) fprintf(stderr, "Could not create " "listen_dict"); - r = GETDNS_RETURN_MEMORY_ERROR; - } else if ((r = getdns_dict_set_list( + else if ((r = getdns_dict_set_list( listen_dict, "listen_list", list))) fprintf(stderr, "Could not set listen_list"); @@ -427,7 +475,7 @@ static void parse_config(const char *config_str) getdns_return_t parse_args(int argc, char **argv) { getdns_return_t r = GETDNS_RETURN_GOOD; - size_t i, j; + size_t i, j, klass; char *arg, *c, *endptr; int t, print_api_info = 0, print_trust_anchors = 0; getdns_list *upstream_list = NULL; @@ -438,7 +486,6 @@ getdns_return_t parse_args(int argc, char **argv) getdns_bindata bindata; size_t upstream_count = 0; FILE *fh; - uint32_t klass; char *config_file = NULL; long config_file_sz; @@ -457,34 +504,13 @@ getdns_return_t parse_args(int argc, char **argv) break; } } else if (strncmp(arg+1, "specify_class=", 14) == 0) { - if (strncasecmp(arg+15, "IN", 3) == 0) + if ((klass = get_rrclass(arg+15)) >= 0) r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_IN); - else if (strncasecmp(arg+15, "CH", 3) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_CH); - else if (strncasecmp(arg+15, "HS", 3) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_HS); - else if (strncasecmp(arg+15, "NONE", 5) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_NONE); - else if (strncasecmp(arg+15, "ANY", 4) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_ANY); - else if (strncasecmp(arg+15, "CLASS", 5) == 0) { - klass = strtol(arg + 20, &endptr, 10); - if (*endptr || klass > 255) - fprintf(stderr, - "Unknown class: %s\n", - arg+15); - else - r = getdns_dict_set_int(extensions, - "specify_class", klass); - - } else + "specify_class", (uint32_t )klass); + else fprintf(stderr, "Unknown class: %s\n", arg+15); + } else if (arg[1] == '0') { /* Unset all existing extensions*/ getdns_dict_destroy(extensions); @@ -499,8 +525,23 @@ getdns_return_t parse_args(int argc, char **argv) continue; } else if (arg[0] == '@') { - getdns_dict *upstream = _getdns_ipaddr_dict(arg + 1); - if (upstream) { + getdns_dict *upstream; + getdns_bindata *address; + + if ((r = getdns_str2dict(arg + 1, &upstream))) + fprintf(stderr, "Could not convert \"%s\" to " + "an IP dict: %s\n", arg + 1, + getdns_get_errorstr_by_id(r)); + + else if ((r = getdns_dict_get_bindata( + upstream, "address_data", &address))) { + + fprintf(stderr, "\"%s\" did not translate to " + "an IP dict: %s\n", arg + 1, + getdns_get_errorstr_by_id(r)); + + getdns_dict_destroy(upstream); + } else { if (!upstream_list && !(upstream_list = getdns_list_create_with_context(context))){ @@ -521,6 +562,9 @@ getdns_return_t parse_args(int argc, char **argv) continue; } for (c = arg+1; *c; c++) { + getdns_dict *downstream; + getdns_bindata *address; + switch (*c) { case 'a': async = 1; @@ -896,23 +940,33 @@ getdns_return_t parse_args(int argc, char **argv) DEBUG_SERVER("Clear listen list\n"); break; } - getdns_dict *downstream = - _getdns_ipaddr_dict(argv[i]); - if (!downstream) { - fprintf(stderr, "could not parse " - "listen address: %s", argv[i]); + + if ((r = getdns_str2dict(argv[i], &downstream))) + fprintf(stderr, "Could not convert \"%s\" to " + "an IP dict: %s\n", argv[i], + getdns_get_errorstr_by_id(r)); + + else if ((r = getdns_dict_get_bindata( + downstream, "address_data", &address))) { + + fprintf(stderr, "\"%s\" did not translate to " + "an IP dict: %s\n", argv[i], + getdns_get_errorstr_by_id(r)); + + getdns_dict_destroy(downstream); + } else { + if (!listen_list && + !(listen_list = + getdns_list_create_with_context(context))){ + fprintf(stderr, "Could not create " + "downstream list\n"); + return GETDNS_RETURN_MEMORY_ERROR; + } + getdns_list_set_dict(listen_list, + listen_count++, downstream); + getdns_dict_destroy(downstream); + touched_listen_list = 1; } - if (!listen_list && - !(listen_list = - getdns_list_create_with_context(context))){ - fprintf(stderr, "Could not create " - "downstram list\n"); - return GETDNS_RETURN_MEMORY_ERROR; - } - getdns_list_set_dict(listen_list, - listen_count++, downstream); - getdns_dict_destroy(downstream); - touched_listen_list = 1; break; default: fprintf(stderr, "Unknown option " @@ -976,14 +1030,26 @@ getdns_return_t do_the_call(void) { getdns_return_t r; getdns_dict *address = NULL; + getdns_bindata *address_bindata; getdns_dict *response = NULL; char *response_str; uint32_t status; - if (calltype == HOSTNAME && - !(address = _getdns_ipaddr_dict(name))) { - fprintf(stderr, "Could not convert \"%s\" " - "to an IP address", name); + if (calltype != HOSTNAME) + ; /* pass */ + + else if ((r = getdns_str2dict(name, &address))) { + + fprintf(stderr, "Could not convert \"%s\" to an IP dict: %s\n" + , name, getdns_get_errorstr_by_id(r)); + return GETDNS_RETURN_GOOD; + + } else if ((r = getdns_dict_get_bindata( + address, "address_data", &address_bindata))) { + + fprintf(stderr, "Could not convert \"%s\" to an IP dict: %s\n" + , name, getdns_get_errorstr_by_id(r)); + getdns_dict_destroy(address); return GETDNS_RETURN_GOOD; } if (async) { @@ -1132,8 +1198,10 @@ typedef struct dns_msg { getdns_transaction_t request_id; getdns_dict *request; uint32_t rt; + uint32_t ad_bit; uint32_t do_bit; uint32_t cd_bit; + int has_edns0; } dns_msg; #if defined(SERVER_DEBUG) && SERVER_DEBUG @@ -1168,15 +1236,55 @@ void servfail(dns_msg *msg, getdns_dict **resp_p) (void) getdns_dict_set_int(*resp_p, "/header/ad", 0); } -void request_cb(getdns_context *context, getdns_callback_type_t callback_type, +static getdns_return_t _handle_edns0( + getdns_dict *response, int has_edns0) +{ + getdns_return_t r; + getdns_list *additional; + size_t len, i; + getdns_dict *rr; + uint32_t rr_type; + char remove_str[100] = "/replies_tree/0/additional/"; + + if ((r = getdns_dict_set_int( + response, "/replies_tree/0/header/do", 0))) + return r; + if ((r = getdns_dict_get_list(response, "/replies_tree/0/additional", + &additional))) + return r; + if ((r = getdns_list_get_length(additional, &len))) + return r; + for (i = 0; i < len; i++) { + if ((r = getdns_list_get_dict(additional, i, &rr))) + return r; + if ((r = getdns_dict_get_int(rr, "type", &rr_type))) + return r; + if (rr_type != GETDNS_RRTYPE_OPT) + continue; + if (has_edns0) { + (void) getdns_dict_set_int(rr, "do", 0); + break; + } + (void) snprintf(remove_str + 27, 60, "%d", (int)i); + if ((r = getdns_dict_remove_name(response, remove_str))) + return r; + break; + } + return GETDNS_RETURN_GOOD; +} + +static void request_cb( + getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t transaction_id) { dns_msg *msg = (dns_msg *)userarg; uint32_t qid; getdns_return_t r = GETDNS_RETURN_GOOD; - uint32_t n; + uint32_t n, rcode, dnssec_status; - DEBUG_SERVER("reply for: %p %"PRIu64" %d\n", msg, transaction_id, (int)callback_type); + DEBUG_SERVER("reply for: %p %"PRIu64" %d (edns0: %d, do: %d, ad: %d," + " cd: %d)\n", msg, transaction_id, (int)callback_type, + msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit); assert(msg); #if 0 @@ -1195,21 +1303,36 @@ void request_cb(getdns_context *context, getdns_callback_type_t callback_type, SERVFAIL("Could not copy QID", r, msg, &response); else if (getdns_dict_get_int( - response, "/replies_tree/0/header/rcode", &n)) + response, "/replies_tree/0/header/rcode", &rcode)) SERVFAIL("No reply in replies tree", 0, msg, &response); - else if (msg->cd_bit != 1 && !getdns_dict_get_int( - response, "/replies_tree/0/dnssec_status", &n) - && n == GETDNS_DNSSEC_BOGUS) + /* ansers when CD or not BOGUS */ + else if (!msg->cd_bit && !getdns_dict_get_int( + response, "/replies_tree/0/dnssec_status", &dnssec_status) + && dnssec_status == GETDNS_DNSSEC_BOGUS) SERVFAIL("DNSSEC status was bogus", 0, msg, &response); - else if ((r = getdns_dict_get_int( - response, "/replies_tree/0/header/rcode", &n))) - SERVFAIL("Could not get rcode from reply", r, msg, &response); - - else if (n == GETDNS_RCODE_SERVFAIL) + else if (rcode == GETDNS_RCODE_SERVFAIL) servfail(msg, &response); + /* RRsigs when DO and (CD or not BOGUS) + * Implemented in conversion to wireformat function by checking for DO + * bit. In recursing resolution mode we have to copy the do bit from + * the request, because libunbound has it in the answer always. + */ + else if (msg->rt == GETDNS_RESOLUTION_RECURSING && !msg->do_bit && + (r = _handle_edns0(response, msg->has_edns0))) + SERVFAIL("Could not handle EDNS0", r, msg, &response); + + /* AD when (DO or AD) and SECURE */ + else if ((r = getdns_dict_set_int(response,"/replies_tree/0/header/ad", + ((msg->do_bit || msg->ad_bit) + && ( (!msg->cd_bit && dnssec_status == GETDNS_DNSSEC_SECURE) + || ( msg->cd_bit && !getdns_dict_get_int(response, + "/replies_tree/0/dnssec_status", &dnssec_status) + && dnssec_status == GETDNS_DNSSEC_SECURE ))) ? 1 : 0))) + SERVFAIL("Could not set AD bit", r, msg, &response); + else if (msg->rt == GETDNS_RESOLUTION_STUB) ; /* following checks are for RESOLUTION_RECURSING only */ @@ -1256,6 +1379,10 @@ static void incoming_request_handler(getdns_context *context, getdns_dict *qext = NULL; dns_msg *msg = NULL; getdns_dict *response = NULL; + size_t i, len; + getdns_list *additional; + getdns_dict *rr; + uint32_t rr_type; if (!query_extensions_spc && !(query_extensions_spc = getdns_dict_create())) @@ -1277,10 +1404,26 @@ static void incoming_request_handler(getdns_context *context, n = 0; msg->request_id = request_id; msg->request = request; - msg->do_bit = msg->cd_bit = 0; - msg->rt = GETDNS_RESOLUTION_STUB; - (void) getdns_dict_get_int(request, "/additional/0/do", &msg->do_bit); + msg->ad_bit = msg->do_bit = msg->cd_bit = 0; + msg->has_edns0 = 0; + msg->rt = GETDNS_RESOLUTION_RECURSING; + (void) getdns_dict_get_int(request, "/header/ad", &msg->ad_bit); (void) getdns_dict_get_int(request, "/header/cd", &msg->cd_bit); + if (!getdns_dict_get_list(request, "additional", &additional)) { + if (getdns_list_get_length(additional, &len)) + len = 0; + for (i = 0; i < len; i++) { + if (getdns_list_get_dict(additional, i, &rr)) + break; + if (getdns_dict_get_int(rr, "type", &rr_type)) + break; + if (rr_type != GETDNS_RRTYPE_OPT) + continue; + msg->has_edns0 = 1; + (void) getdns_dict_get_int(rr, "do", &msg->do_bit); + break; + } + } if ((r = getdns_context_get_resolution_type(context, &msg->rt))) fprintf(stderr, "Could get resolution type from context: %s\n", getdns_get_errorstr_by_id(r)); @@ -1291,15 +1434,10 @@ static void incoming_request_handler(getdns_context *context, if (!getdns_dict_get_dict(request, "header", &header)) (void)getdns_dict_set_dict(qext, "header", header); - } else if (getdns_dict_get_int(extensions,"dnssec_return_status",&n) || - n == GETDNS_EXTENSION_FALSE) - (void)getdns_dict_set_int(qext, "dnssec_return_status", - msg->do_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE); - - if (!getdns_dict_get_int(qext, "dnssec_return_status", &n) && - n == GETDNS_EXTENSION_TRUE) - (void) getdns_dict_set_int(qext, "dnssec_return_all_statuses", - msg->cd_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE); + } + if (msg->cd_bit) + getdns_dict_set_int(qext, "dnssec_return_all_statuses", + GETDNS_EXTENSION_TRUE); if (!getdns_dict_get_int(request, "/additional/0/extended_rcode",&n)) (void)getdns_dict_set_int( @@ -1363,6 +1501,16 @@ error: if (qname_str) free(qname_str); servfail(msg, &response); +#if defined(SERVER_DEBUG) && SERVER_DEBUG + do { + char *request_str = getdns_pretty_print_dict(request); + char *response_str = getdns_pretty_print_dict(response); + DEBUG_SERVER("request error, request: %s\n, response: %s\n" + , request_str, response_str); + free(response_str); + free(request_str); + } while(0); +#endif if (!response) /* No response, no reply */ _getdns_cancel_reply(context, request_id); @@ -1471,462 +1619,4 @@ done_destroy_context: return r; } -int get_rrtype(const char *t) { - char *endptr; - int r; - - switch (t[0]) { - case 'A': - case 'a': switch (t[1]) { - case '\0': return GETDNS_RRTYPE_A; - case '6': if (t[2] == '\0') return GETDNS_RRTYPE_A6; - return -1; - case 'A': - case 'a': /* before "AA", final "AA" (GETDNS_RRTYPE_AAAA) */ - if ((t[2]|0x20) == 'a' && (t[3]|0x20) == 'a' && t[4] == '\0') - return GETDNS_RRTYPE_AAAA; - return -1; - case 'F': - case 'f': /* before "AF", final "SDB" (GETDNS_RRTYPE_AFSDB) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'd' && (t[4]|0x20) == 'b' && t[5] == '\0') - return GETDNS_RRTYPE_AFSDB; - return -1; - case 'P': - case 'p': /* before "AP", final "L" (GETDNS_RRTYPE_APL) */ - if ((t[2]|0x20) == 'l' && t[3] == '\0') - return GETDNS_RRTYPE_APL; - return -1; - case 'T': - case 't': /* before "AT", final "MA" (GETDNS_RRTYPE_ATMA) */ - if ((t[2]|0x20) == 'm' && (t[3]|0x20) == 'a' && t[4] == '\0') - return GETDNS_RRTYPE_ATMA; - return -1; - case 'X': - case 'x': /* before "AX", final "FR" (GETDNS_RRTYPE_AXFR) */ - if ((t[2]|0x20) == 'f' && (t[3]|0x20) == 'r' && t[4] == '\0') - return GETDNS_RRTYPE_AXFR; - return -1; - default : return -1; - }; - case 'C': - case 'c': switch (t[1]) { - case 'A': - case 'a': /* before "CA", final "A" (GETDNS_RRTYPE_CAA) */ - if ((t[2]|0x20) == 'a' && t[3] == '\0') - return GETDNS_RRTYPE_CAA; - return -1; - case 'D': - case 'd': switch (t[2]) { - case 'N': - case 'n': /* before "CDN", final "SKEY" (GETDNS_RRTYPE_CDNSKEY) */ - if ((t[3]|0x20) == 's' && (t[4]|0x20) == 'k' && (t[5]|0x20) == 'e' && (t[6]|0x20) == 'y' && t[7] == '\0') - return GETDNS_RRTYPE_CDNSKEY; - return -1; - case 'S': - case 's': if (t[3] == '\0') return GETDNS_RRTYPE_CDS; - return -1; - default : return -1; - }; - case 'E': - case 'e': /* before "CE", final "RT" (GETDNS_RRTYPE_CERT) */ - if ((t[2]|0x20) == 'r' && (t[3]|0x20) == 't' && t[4] == '\0') - return GETDNS_RRTYPE_CERT; - return -1; - case 'N': - case 'n': /* before "CN", final "AME" (GETDNS_RRTYPE_CNAME) */ - if ((t[2]|0x20) == 'a' && (t[3]|0x20) == 'm' && (t[4]|0x20) == 'e' && t[5] == '\0') - return GETDNS_RRTYPE_CNAME; - return -1; - case 'S': - case 's': /* before "CS", final "YNC" (GETDNS_RRTYPE_CSYNC) */ - if ((t[2]|0x20) == 'y' && (t[3]|0x20) == 'n' && (t[4]|0x20) == 'c' && t[5] == '\0') - return GETDNS_RRTYPE_CSYNC; - return -1; - - default : return -1; - }; - case 'D': - case 'd': switch (t[1]) { - case 'H': - case 'h': /* before "DH", final "CID" (GETDNS_RRTYPE_DHCID) */ - if ((t[2]|0x20) == 'c' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'd' && t[5] == '\0') - return GETDNS_RRTYPE_DHCID; - return -1; - case 'L': - case 'l': /* before "DL", final "V" (GETDNS_RRTYPE_DLV) */ - if ((t[2]|0x20) == 'v' && t[3] == '\0') - return GETDNS_RRTYPE_DLV; - return -1; - case 'N': - case 'n': switch (t[2]) { - case 'A': - case 'a': /* before "DNA", final "ME" (GETDNS_RRTYPE_DNAME) */ - if ((t[3]|0x20) == 'm' && (t[4]|0x20) == 'e' && t[5] == '\0') - return GETDNS_RRTYPE_DNAME; - return -1; - case 'S': - case 's': /* before "DNS", final "KEY" (GETDNS_RRTYPE_DNSKEY) */ - if ((t[3]|0x20) == 'k' && (t[4]|0x20) == 'e' && (t[5]|0x20) == 'y' && t[6] == '\0') - return GETDNS_RRTYPE_DNSKEY; - return -1; - default : return -1; - }; - case 'S': - case 's': if (t[2] == '\0') return GETDNS_RRTYPE_DS; - return -1; - default : return -1; - }; - case 'E': - case 'e': switch (t[1]) { - case 'I': - case 'i': /* before "EI", final "D" (GETDNS_RRTYPE_EID) */ - if ((t[2]|0x20) == 'd' && t[3] == '\0') - return GETDNS_RRTYPE_EID; - return -1; - case 'U': - case 'u': /* before "EU", next "I" */ - if ((t[2]|0x20) != 'i') - return -1; - switch (t[3]) { - case '4': /* before "EUI4", final "8" (GETDNS_RRTYPE_EUI48) */ - if (t[4] == '8' && t[5] == '\0') - return GETDNS_RRTYPE_EUI48; - return -1; - case '6': /* before "EUI6", final "4" (GETDNS_RRTYPE_EUI64) */ - if (t[4] == '4' && t[5] == '\0') - return GETDNS_RRTYPE_EUI64; - return -1; - default : return -1; - }; - default : return -1; - }; - case 'G': - case 'g': switch (t[1]) { - case 'I': - case 'i': /* before "GI", final "D" (GETDNS_RRTYPE_GID) */ - if ((t[2]|0x20) == 'd' && t[3] == '\0') - return GETDNS_RRTYPE_GID; - return -1; - case 'P': - case 'p': /* before "GP", final "OS" (GETDNS_RRTYPE_GPOS) */ - if ((t[2]|0x20) == 'o' && (t[3]|0x20) == 's' && t[4] == '\0') - return GETDNS_RRTYPE_GPOS; - return -1; - default : return -1; - }; - case 'H': - case 'h': /* before "H", next "I" */ - if ((t[1]|0x20) != 'i') - return -1; - switch (t[2]) { - case 'N': - case 'n': /* before "HIN", final "FO" (GETDNS_RRTYPE_HINFO) */ - if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_HINFO; - return -1; - case 'P': - case 'p': if (t[3] == '\0') return GETDNS_RRTYPE_HIP; - return -1; - default : return -1; - }; - case 'I': - case 'i': switch (t[1]) { - case 'P': - case 'p': /* before "IP", final "SECKEY" (GETDNS_RRTYPE_IPSECKEY) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'e' && (t[4]|0x20) == 'c' && (t[5]|0x20) == 'k' && (t[6]|0x20) == 'e' && (t[7]|0x20) == 'y' && t[8] == '\0') - return GETDNS_RRTYPE_IPSECKEY; - return -1; - case 'S': - case 's': /* before "IS", final "DN" (GETDNS_RRTYPE_ISDN) */ - if ((t[2]|0x20) == 'd' && (t[3]|0x20) == 'n' && t[4] == '\0') - return GETDNS_RRTYPE_ISDN; - return -1; - case 'X': - case 'x': /* before "IX", final "FR" (GETDNS_RRTYPE_IXFR) */ - if ((t[2]|0x20) == 'f' && (t[3]|0x20) == 'r' && t[4] == '\0') - return GETDNS_RRTYPE_IXFR; - return -1; - default : return -1; - }; - case 'K': - case 'k': switch (t[1]) { - case 'E': - case 'e': /* before "KE", final "Y" (GETDNS_RRTYPE_KEY) */ - if ((t[2]|0x20) == 'y' && t[3] == '\0') - return GETDNS_RRTYPE_KEY; - return -1; - case 'X': - case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_KX; - return -1; - default : return -1; - }; - case 'L': - case 'l': switch (t[1]) { - case '3': /* before "L3", final "2" (GETDNS_RRTYPE_L32) */ - if (t[2] == '2' && t[3] == '\0') - return GETDNS_RRTYPE_L32; - return -1; - case '6': /* before "L6", final "4" (GETDNS_RRTYPE_L64) */ - if (t[2] == '4' && t[3] == '\0') - return GETDNS_RRTYPE_L64; - return -1; - case 'O': - case 'o': /* before "LO", final "C" (GETDNS_RRTYPE_LOC) */ - if ((t[2]|0x20) == 'c' && t[3] == '\0') - return GETDNS_RRTYPE_LOC; - return -1; - case 'P': - case 'p': if (t[2] == '\0') return GETDNS_RRTYPE_LP; - return -1; - default : return -1; - }; - case 'M': - case 'm': switch (t[1]) { - case 'A': - case 'a': /* before "MA", next "IL" */ - if ((t[2]|0x20) != 'i' && (t[3]|0x20) != 'l') - return -1; - switch (t[4]) { - case 'A': - case 'a': if (t[5] == '\0') return GETDNS_RRTYPE_MAILA; - return -1; - case 'B': - case 'b': if (t[5] == '\0') return GETDNS_RRTYPE_MAILB; - return -1; - default : return -1; - }; - case 'B': - case 'b': if (t[2] == '\0') return GETDNS_RRTYPE_MB; - return -1; - case 'D': - case 'd': if (t[2] == '\0') return GETDNS_RRTYPE_MD; - return -1; - case 'F': - case 'f': if (t[2] == '\0') return GETDNS_RRTYPE_MF; - return -1; - case 'G': - case 'g': if (t[2] == '\0') return GETDNS_RRTYPE_MG; - return -1; - case 'I': - case 'i': /* before "MI", final "NFO" (GETDNS_RRTYPE_MINFO) */ - if ((t[2]|0x20) == 'n' && (t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_MINFO; - return -1; - case 'R': - case 'r': if (t[2] == '\0') return GETDNS_RRTYPE_MR; - return -1; - case 'X': - case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_MX; - return -1; - default : return -1; - }; - case 'N': - case 'n': switch (t[1]) { - case 'A': - case 'a': /* before "NA", final "PTR" (GETDNS_RRTYPE_NAPTR) */ - if ((t[2]|0x20) == 'p' && (t[3]|0x20) == 't' && (t[4]|0x20) == 'r' && t[5] == '\0') - return GETDNS_RRTYPE_NAPTR; - return -1; - case 'I': - case 'i': switch (t[2]) { - case 'D': - case 'd': if (t[3] == '\0') return GETDNS_RRTYPE_NID; - return -1; - case 'M': - case 'm': /* before "NIM", final "LOC" (GETDNS_RRTYPE_NIMLOC) */ - if ((t[3]|0x20) == 'l' && (t[4]|0x20) == 'o' && (t[5]|0x20) == 'c' && t[6] == '\0') - return GETDNS_RRTYPE_NIMLOC; - return -1; - case 'N': - case 'n': /* before "NIN", final "FO" (GETDNS_RRTYPE_NINFO) */ - if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_NINFO; - return -1; - default : return -1; - }; - case 'S': - case 's': switch (t[2]) { - case '\0': return GETDNS_RRTYPE_NS; - case 'A': - case 'a': /* before "NSA", final "P" (GETDNS_RRTYPE_NSAP) */ - if ((t[3]|0x20) == 'p' && t[4] == '\0') - return GETDNS_RRTYPE_NSAP; - return -1; - case 'E': - case 'e': /* before "NSE", final "C3PARAM" (GETDNS_RRTYPE_NSEC3PARAM) */ - if ((t[3]|0x20) == 'c' && t[4] == '3' && (t[5]|0x20) == 'p' && (t[6]|0x20) == 'a' && (t[7]|0x20) == 'r' && (t[8]|0x20) == 'a' && (t[9]|0x20) == 'm' && t[10] == '\0') - return GETDNS_RRTYPE_NSEC3PARAM; - return -1; - default : return -1; - }; - case 'U': - case 'u': /* before "NU", final "LL" (GETDNS_RRTYPE_NULL) */ - if ((t[2]|0x20) == 'l' && (t[3]|0x20) == 'l' && t[4] == '\0') - return GETDNS_RRTYPE_NULL; - return -1; - case 'X': - case 'x': /* before "NX", final "T" (GETDNS_RRTYPE_NXT) */ - if ((t[2]|0x20) == 't' && t[3] == '\0') - return GETDNS_RRTYPE_NXT; - return -1; - default : return -1; - }; - case 'O': - case 'o': /* before "O", next "P" */ - if ((t[1]|0x20) != 'p') - return -1; - switch (t[2]) { - case 'E': - case 'e': /* before "OPE", final "NPGPKEY" (GETDNS_RRTYPE_OPENPGPKEY) */ - if ((t[3]|0x20) == 'n' && (t[4]|0x20) == 'p' && (t[5]|0x20) == 'g' && (t[6]|0x20) == 'p' && (t[7]|0x20) == 'k' && (t[8]|0x20) == 'e' && (t[9]|0x20) == 'y' && t[10] == '\0') - return GETDNS_RRTYPE_OPENPGPKEY; - return -1; - case 'T': - case 't': if (t[3] == '\0') return GETDNS_RRTYPE_OPT; - return -1; - default : return -1; - }; - case 'P': - case 'p': switch (t[1]) { - case 'T': - case 't': /* before "PT", final "R" (GETDNS_RRTYPE_PTR) */ - if ((t[2]|0x20) == 'r' && t[3] == '\0') - return GETDNS_RRTYPE_PTR; - return -1; - case 'X': - case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_PX; - return -1; - default : return -1; - }; - case 'R': - case 'r': switch (t[1]) { - case 'K': - case 'k': /* before "RK", final "EY" (GETDNS_RRTYPE_RKEY) */ - if ((t[2]|0x20) == 'e' && (t[3]|0x20) == 'y' && t[4] == '\0') - return GETDNS_RRTYPE_RKEY; - return -1; - case 'P': - case 'p': if (t[2] == '\0') return GETDNS_RRTYPE_RP; - return -1; - case 'R': - case 'r': /* before "RR", final "SIG" (GETDNS_RRTYPE_RRSIG) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'g' && t[5] == '\0') - return GETDNS_RRTYPE_RRSIG; - return -1; - case 'T': - case 't': if (t[2] == '\0') return GETDNS_RRTYPE_RT; - return -1; - default : return -1; - }; - case 'S': - case 's': switch (t[1]) { - case 'I': - case 'i': switch (t[2]) { - case 'G': - case 'g': if (t[3] == '\0') return GETDNS_RRTYPE_SIG; - return -1; - case 'N': - case 'n': /* before "SIN", final "K" (GETDNS_RRTYPE_SINK) */ - if ((t[3]|0x20) == 'k' && t[4] == '\0') - return GETDNS_RRTYPE_SINK; - return -1; - default : return -1; - }; - case 'O': - case 'o': /* before "SO", final "A" (GETDNS_RRTYPE_SOA) */ - if ((t[2]|0x20) == 'a' && t[3] == '\0') - return GETDNS_RRTYPE_SOA; - return -1; - case 'P': - case 'p': /* before "SP", final "F" (GETDNS_RRTYPE_SPF) */ - if ((t[2]|0x20) == 'f' && t[3] == '\0') - return GETDNS_RRTYPE_SPF; - return -1; - case 'R': - case 'r': /* before "SR", final "V" (GETDNS_RRTYPE_SRV) */ - if ((t[2]|0x20) == 'v' && t[3] == '\0') - return GETDNS_RRTYPE_SRV; - return -1; - case 'S': - case 's': /* before "SS", final "HFP" (GETDNS_RRTYPE_SSHFP) */ - if ((t[2]|0x20) == 'h' && (t[3]|0x20) == 'f' && (t[4]|0x20) == 'p' && t[5] == '\0') - return GETDNS_RRTYPE_SSHFP; - return -1; - default : return -1; - }; - case 'T': - case 't': switch (t[1]) { - case 'A': - case 'a': /* before "TA", final "LINK" (GETDNS_RRTYPE_TALINK) */ - if ((t[2]|0x20) == 'l' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'n' && (t[5]|0x20) == 'k' && t[6] == '\0') - return GETDNS_RRTYPE_TALINK; - return -1; - case 'K': - case 'k': /* before "TK", final "EY" (GETDNS_RRTYPE_TKEY) */ - if ((t[2]|0x20) == 'e' && (t[3]|0x20) == 'y' && t[4] == '\0') - return GETDNS_RRTYPE_TKEY; - return -1; - case 'L': - case 'l': /* before "TL", final "SA" (GETDNS_RRTYPE_TLSA) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'a' && t[4] == '\0') - return GETDNS_RRTYPE_TLSA; - return -1; - case 'S': - case 's': /* before "TS", final "IG" (GETDNS_RRTYPE_TSIG) */ - if ((t[2]|0x20) == 'i' && (t[3]|0x20) == 'g' && t[4] == '\0') - return GETDNS_RRTYPE_TSIG; - return -1; - case 'X': - case 'x': /* before "TX", final "T" (GETDNS_RRTYPE_TXT) */ - if ((t[2]|0x20) == 't' && t[3] == '\0') - return GETDNS_RRTYPE_TXT; - return -1; - case 'Y': - case 'y': /* before "TY", then "PE" followed by a number */ - if ((t[2]|0x20) == 'p' && (t[3]|0x20) == 'e' && t[4] != '\0') { - r = (int) strtol(t + 4, &endptr, 10); - if (*endptr == '\0') return r; - } - return -1; - default : return -1; - }; - case 'U': - case 'u': switch (t[1]) { - case 'I': - case 'i': switch (t[2]) { - case 'D': - case 'd': if (t[3] == '\0') return GETDNS_RRTYPE_UID; - return -1; - case 'N': - case 'n': /* before "UIN", final "FO" (GETDNS_RRTYPE_UINFO) */ - if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_UINFO; - return -1; - default : return -1; - }; - case 'N': - case 'n': /* before "UN", final "SPEC" (GETDNS_RRTYPE_UNSPEC) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'p' && (t[4]|0x20) == 'e' && (t[5]|0x20) == 'c' && t[6] == '\0') - return GETDNS_RRTYPE_UNSPEC; - return -1; - case 'R': - case 'r': /* before "UR", final "I" (GETDNS_RRTYPE_URI) */ - if ((t[2]|0x20) == 'i' && t[3] == '\0') - return GETDNS_RRTYPE_URI; - return -1; - default : return -1; - }; - case 'W': - case 'w': /* before "W", final "KS" (GETDNS_RRTYPE_WKS) */ - if ((t[1]|0x20) == 'k' && (t[2]|0x20) == 's' && t[3] == '\0') - return GETDNS_RRTYPE_WKS; - return -1; - case 'X': - case 'x': /* before "X", final "25" (GETDNS_RRTYPE_X25) */ - if (t[1] == '2' && t[2] == '5' && t[3] == '\0') - return GETDNS_RRTYPE_X25; - return -1; - default : return -1; - }; -} diff --git a/src/test/getdns_str2dict.c b/src/test/getdns_str2dict.c index 7cfc875c..28323d9d 100644 --- a/src/test/getdns_str2dict.c +++ b/src/test/getdns_str2dict.c @@ -233,21 +233,6 @@ static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t, return *value != NULL; } -getdns_dict * -_getdns_ipaddr_dict(const char *ipstr) -{ - char value_str[3072]; - size_t size = strlen(ipstr); - - if (size >= sizeof(value_str)) - return NULL; - - (void) memcpy(value_str, ipstr, size); - value_str[size] = '\0'; - - return _getdns_ipaddr_dict_mf(&_getdns_plain_mem_funcs, value_str); -} - static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t, getdns_bindata **value) { @@ -425,7 +410,10 @@ static int _jsmn_get_dict(struct mem_funcs *mf, const char *js, jsmntok_t *t, char key_spc[1024], *key = NULL; getdns_item child_item; - for (i = 0; i < t->size; i++) { + if (t->size <= 0) + *r = GETDNS_RETURN_GOOD; + + else for (i = 0; i < t->size; i++) { if (t[j].type != JSMN_STRING && t[j].type != JSMN_PRIMITIVE) { @@ -499,7 +487,10 @@ static int _jsmn_get_list(struct mem_funcs *mf, const char *js, jsmntok_t *t, size_t i, j = 1, index = 0; getdns_item child_item; - for (i = 0; i < t->size; i++) { + if (t->size <= 0) + *r = GETDNS_RETURN_GOOD; + + else for (i = 0; i < t->size; i++) { j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r); if (*r) break; @@ -658,8 +649,48 @@ getdns_str2dict(const char *str, getdns_dict **dict) return r; else if (item.dtype != t_dict) { + uint8_t buf[16]; + getdns_dict *dict_r; + + if (item.dtype != t_bindata) + r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + else if (item.data.bindata->size == 4 && + inet_pton(AF_INET, str, buf) == 1) { + + if (!(dict_r = getdns_dict_create())) + r = GETDNS_RETURN_MEMORY_ERROR; + + else if ((r = getdns_dict_util_set_string( + dict_r, "address_type", "IPv4"))) + getdns_dict_destroy(dict_r); + + else if ((r = getdns_dict_set_bindata( + dict_r, "address_data", item.data.bindata))) + getdns_dict_destroy(dict_r); + else + *dict = dict_r; + + } else if (item.data.bindata->size == 16 && + inet_pton(AF_INET6, str, buf) == 1) { + + if (!(dict_r = getdns_dict_create())) + r = GETDNS_RETURN_MEMORY_ERROR; + + else if ((r = getdns_dict_util_set_string( + dict_r, "address_type", "IPv6"))) + getdns_dict_destroy(dict_r); + + else if ((r = getdns_dict_set_bindata( + dict_r, "address_data", item.data.bindata))) + getdns_dict_destroy(dict_r); + else + *dict = dict_r; + } else + r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; + _getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item); - return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + return r; } *dict = item.data.dict; return GETDNS_RETURN_GOOD; diff --git a/src/test/getdns_str2dict.h b/src/test/getdns_str2dict.h index f8d7e926..71cb26c8 100644 --- a/src/test/getdns_str2dict.h +++ b/src/test/getdns_str2dict.h @@ -29,8 +29,6 @@ #define GETDNS_STR2DICT_H_ #include "getdns/getdns.h" -getdns_dict *_getdns_ipaddr_dict(const char *ipstr); - getdns_return_t getdns_str2dict(const char *str, getdns_dict **dict); getdns_return_t getdns_str2list(const char *str, getdns_list **list); getdns_return_t getdns_str2bindata(const char *str, getdns_bindata **bindata); diff --git a/src/util-internal.c b/src/util-internal.c index 47a3fd21..6934958d 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -54,7 +54,7 @@ getdns_return_t -getdns_dict_util_get_string(struct getdns_dict * dict, char *name, char **result) +getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result) { struct getdns_bindata *bindata = NULL; if (!result) { diff --git a/src/util/import.sh b/src/util/import.sh index ee903681..82f03921 100755 --- a/src/util/import.sh +++ b/src/util/import.sh @@ -44,6 +44,10 @@ do -e 's/secalgo_ds_digest/_getdns_secalgo_ds_digest/g' \ -e 's/dnskey_algo_id_is_supported/_getdns_dnskey_algo_id_is_supported/g' \ -e 's/verify_canonrrset/_getdns_verify_canonrrset/g' \ + -e 's/nsec3_hash_algo_size_supported/_getdns_nsec3_hash_algo_size_supported/g' \ + -e 's/secalgo_nsec3_hash/_getdns_secalgo_nsec3_hash/g' \ + -e 's/secalgo_hash_sha256/_getdns_secalgo_hash_sha256/g' \ + -e 's/ecdsa_evp_workaround_init/_getdns_ecdsa_evp_workaround_init/g' \ -e 's/LDNS_/GLDNS_/g' \ -e 's/enum sec_status/int/g' \ -e 's/sec_status_bogus/0/g' \ diff --git a/src/util/val_secalgo.c b/src/util/val_secalgo.c index b04400cc..edbf538b 100644 --- a/src/util/val_secalgo.c +++ b/src/util/val_secalgo.c @@ -72,7 +72,7 @@ /* return size of digest if supported, or 0 otherwise */ size_t -nsec3_hash_algo_size_supported(int id) +_getdns_nsec3_hash_algo_size_supported(int id) { switch(id) { case NSEC3_HASH_SHA1: @@ -84,7 +84,7 @@ nsec3_hash_algo_size_supported(int id) /* perform nsec3 hash. return false on failure */ int -secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, +_getdns_secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, unsigned char* res) { switch(algo) { @@ -96,6 +96,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, } } +void +_getdns_secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) +{ + (void)SHA256(buf, len, res); +} + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo. @@ -342,6 +348,23 @@ i * the '44' is the total remaining length. } #endif /* USE_ECDSA */ +#ifdef USE_ECDSA_EVP_WORKAROUND +static EVP_MD ecdsa_evp_256_md; +static EVP_MD ecdsa_evp_384_md; +void _getdns_ecdsa_evp_workaround_init(void) +{ + /* openssl before 1.0.0 fixes RSA with the SHA256 + * hash in EVP. We create one for ecdsa_sha256 */ + ecdsa_evp_256_md = *EVP_sha256(); + ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC; + ecdsa_evp_256_md.verify = (void*)ECDSA_verify; + + ecdsa_evp_384_md = *EVP_sha384(); + ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC; + ecdsa_evp_384_md.verify = (void*)ECDSA_verify; +} +#endif /* USE_ECDSA_EVP_WORKAROUND */ + /** * Setup key and digest for verification. Adjust sig if necessary. * @@ -470,20 +493,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, return 0; } #ifdef USE_ECDSA_EVP_WORKAROUND - /* openssl before 1.0.0 fixes RSA with the SHA256 - * hash in EVP. We create one for ecdsa_sha256 */ - { - static int md_ecdsa_256_done = 0; - static EVP_MD md; - if(!md_ecdsa_256_done) { - EVP_MD m = *EVP_sha256(); - md_ecdsa_256_done = 1; - m.required_pkey_type[0] = (*evp_key)->type; - m.verify = (void*)ECDSA_verify; - md = m; - } - *digest_type = &md; - } + *digest_type = &ecdsa_evp_256_md; #else *digest_type = EVP_sha256(); #endif @@ -497,20 +507,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, return 0; } #ifdef USE_ECDSA_EVP_WORKAROUND - /* openssl before 1.0.0 fixes RSA with the SHA384 - * hash in EVP. We create one for ecdsa_sha384 */ - { - static int md_ecdsa_384_done = 0; - static EVP_MD md; - if(!md_ecdsa_384_done) { - EVP_MD m = *EVP_sha384(); - md_ecdsa_384_done = 1; - m.required_pkey_type[0] = (*evp_key)->type; - m.verify = (void*)ECDSA_verify; - md = m; - } - *digest_type = &md; - } + *digest_type = &ecdsa_evp_384_md; #else *digest_type = EVP_sha384(); #endif @@ -544,7 +541,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, { const EVP_MD *digest_type; EVP_MD_CTX* ctx; - int res, dofree = 0; + int res, dofree = 0, docrypto_free = 0; EVP_PKEY *evp_key = NULL; if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { @@ -563,7 +560,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_PKEY_free(evp_key); return 0; } - dofree = 1; + docrypto_free = 1; } #endif #if defined(USE_ECDSA) && defined(USE_DSA) @@ -593,6 +590,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, log_err("EVP_MD_CTX_new: malloc failure"); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); + else if(docrypto_free) CRYPTO_free(sigblock); return 0; } if(EVP_VerifyInit(ctx, digest_type) == 0) { @@ -600,6 +598,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); + else if(docrypto_free) CRYPTO_free(sigblock); return 0; } if(EVP_VerifyUpdate(ctx, (unsigned char*)gldns_buffer_begin(buf), @@ -608,15 +607,21 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); + else if(docrypto_free) CRYPTO_free(sigblock); return 0; } res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key); +#ifdef HAVE_EVP_MD_CTX_NEW EVP_MD_CTX_destroy(ctx); +#else + EVP_MD_CTX_cleanup(ctx); + free(ctx); +#endif EVP_PKEY_free(evp_key); - if(dofree) - free(sigblock); + if(dofree) free(sigblock); + else if(docrypto_free) CRYPTO_free(sigblock); if(res == 1) { return 1; @@ -644,7 +649,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, /* return size of digest if supported, or 0 otherwise */ size_t -nsec3_hash_algo_size_supported(int id) +_getdns_nsec3_hash_algo_size_supported(int id) { switch(id) { case NSEC3_HASH_SHA1: @@ -656,7 +661,7 @@ nsec3_hash_algo_size_supported(int id) /* perform nsec3 hash. return false on failure */ int -secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, +_getdns_secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, unsigned char* res) { switch(algo) { @@ -668,6 +673,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, } } +void +_getdns_secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) +{ + (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len); +} + size_t _getdns_ds_digest_size_supported(int algo) { @@ -1185,6 +1196,9 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, #include "macros.h" #include "rsa.h" #include "dsa.h" +#ifdef HAVE_NETTLE_DSA_COMPAT_H +#include "dsa-compat.h" +#endif #include "asn1.h" #ifdef USE_ECDSA #include "ecdsa.h" @@ -1236,7 +1250,7 @@ _digest_nettle(int algo, uint8_t* buf, size_t len, /* return size of digest if supported, or 0 otherwise */ size_t -nsec3_hash_algo_size_supported(int id) +_getdns_nsec3_hash_algo_size_supported(int id) { switch(id) { case NSEC3_HASH_SHA1: @@ -1248,7 +1262,7 @@ nsec3_hash_algo_size_supported(int id) /* perform nsec3 hash. return false on failure */ int -secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, +_getdns_secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, unsigned char* res) { switch(algo) { @@ -1260,6 +1274,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, } } +void +_getdns_secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) +{ + _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res); +} + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo. diff --git a/src/util/val_secalgo.h b/src/util/val_secalgo.h index 917ebc00..704449ec 100644 --- a/src/util/val_secalgo.h +++ b/src/util/val_secalgo.h @@ -45,7 +45,7 @@ struct gldns_buffer; /** Return size of nsec3 hash algorithm, 0 if not supported */ -size_t nsec3_hash_algo_size_supported(int id); +size_t _getdns_nsec3_hash_algo_size_supported(int id); /** * Hash a single hash call of an NSEC3 hash algorithm. @@ -56,9 +56,17 @@ size_t nsec3_hash_algo_size_supported(int id); * @param res: result stored here (must have sufficient space). * @return false on failure. */ -int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, +int _getdns_secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, unsigned char* res); +/** + * Calculate the sha256 hash for the data buffer into the result. + * @param buf: buffer to digest. + * @param len: length of the buffer to digest. + * @param res: result is stored here (space 256/8 bytes). + */ +void _getdns_secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res); + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo.