diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index ae95002cf7..89d562c904 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -2275,6 +2275,7 @@ TO_REMOVE+=/usr/lib/libedit.so TO_REMOVE+=/usr/lib/profile/libedit.a TO_REMOVE+=/lib/libedit.so.5 TO_REMOVE+=/usr/lib/libprivate_ldns.so.1 +TO_REMOVE+=/usr/lib/libprivate_ldns.so.2 TO_REMOVE+=/usr/lib/profile/libprivate_ldns.a TO_REMOVE+=/usr/lib/libprivate_ssh.so.4 TO_REMOVE+=/usr/lib/profile/libprivate_ssh.a diff --git a/contrib/ldns/README.DELETED b/contrib/ldns/README.DELETED index a0801db0b5..f76fa91088 100644 --- a/contrib/ldns/README.DELETED +++ b/contrib/ldns/README.DELETED @@ -5,6 +5,7 @@ Makefile.in README README.git README.snapshots +README-Travis.md aclocal.m4 acx_nlnetlabs.m4 ax_pkg_swig.m4 @@ -45,6 +46,7 @@ ldns/net.h.in ldns/util.h.in libdns.doxygen libdns.vim +libdns.doxygen.in linktest.c ltmain.sh m4/ diff --git a/contrib/ldns/README.DRAGONFLY b/contrib/ldns/README.DRAGONFLY index a8315a1c51..d5e94b384c 100644 --- a/contrib/ldns/README.DRAGONFLY +++ b/contrib/ldns/README.DRAGONFLY @@ -4,10 +4,10 @@ LDNS Original source can be downloaded from: http://www.nlnetlabs.nl/downloads/ldns/ -file = ldns-1.7.1.tar.gz -date = 26 July 2019 -size = 1244394 -sha1 = d075a08972c0f573101fb4a6250471daaa53cb3e +file = ldns-1.8.3.tar.gz +date = 15 August 2022 +size = 1299856 +sha1 = 2796cc49636f68260c9662b60d5a7c9e6eed195c A list of files and directories removed is in README.DELETED diff --git a/contrib/ldns/buffer.c b/contrib/ldns/buffer.c index e008831fcc..8f6aab59ea 100644 --- a/contrib/ldns/buffer.c +++ b/contrib/ldns/buffer.c @@ -63,6 +63,7 @@ ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity) ldns_buffer_invariant(buffer); assert(buffer->_position <= capacity); + assert(!buffer->_fixed); data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity); if (!data) { @@ -79,7 +80,6 @@ bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount) { ldns_buffer_invariant(buffer); - assert(!buffer->_fixed); if (buffer->_capacity < buffer->_position + amount) { size_t new_capacity = buffer->_capacity * 3 / 2; diff --git a/contrib/ldns/dane.c b/contrib/ldns/dane.c index 30dc1f7005..b8487b53a8 100644 --- a/contrib/ldns/dane.c +++ b/contrib/ldns/dane.c @@ -1,7 +1,7 @@ /* * Verify or create TLS authentication with DANE (RFC6698) * - * (c) NLnetLabs 2012 + * (c) NLnetLabs 2012-2020 * * See the file LICENSE for the license. * @@ -29,6 +29,63 @@ #include #endif +/* OpenSSL context options. At the moment, disable SSLv2, SSLv3 + * and Compression, if available. TLSv1.0 is allowed at the moment. + * TLSv1.1 is the first to provide elliptic curves, so it is usually + * allowed in a TLS stack. TLSv1.2 is the first to provide authentication + * modes of operation, like GCM. The defines below are a moving + * target based on OpenSSL library version. Grep is useful to find + * the defines: grep -IR SSL_OP_NO_ /usr/include/openssl. + */ +#ifdef HAVE_SSL +# ifdef SSL_OP_NO_SSLv2 + const long NoOpenSSLv2 = SSL_OP_NO_SSLv2; +# else + const long NoOpenSSLv2 = 0L; +# endif +# ifdef SSL_OP_NO_SSLv3 + const long NoOpenSSLv3 = SSL_OP_NO_SSLv3; +# else + const long NoOpenSSLv3 = 0L; +# endif +# ifdef SSL_OP_NO_TLSv1 + const long NoOpenTLSv1 = SSL_OP_NO_TLSv1; +# else + const long NoOpenTLSv1 = 0L; +# endif +# ifdef SSL_OP_NO_DTLSv1 + const long NoOpenDTLSv1 = SSL_OP_NO_DTLSv1; +# else + const long NoOpenDTLSv1 = 0L; +# endif +# ifdef SSL_OP_NO_COMPRESSION + const long NoOpenSSLCompression = SSL_OP_NO_COMPRESSION; +# else + const long NoOpenSSLCompression = 0L; +# endif +#endif + +#if defined(USE_DANE_VERIFY) && defined(USE_DANE_TA_USAGE) +static SSL_CTX* +ldns_dane_new_ssl_context(void) +{ + SSL_CTX* ssl_ctx; + + ssl_ctx = SSL_CTX_new(TLS_client_method()); + if (ssl_ctx != NULL) + { + /* ldns allows TLS and DTLS v1.0 at the moment. Some may disagree. + * Sometime in the future they may be disabled, too. Maybe + * --disable-tlsv1 and --disable-dtlsv1 should be configure options. + */ + long flags = NoOpenSSLv2 | NoOpenSSLv3 | NoOpenSSLCompression; + SSL_CTX_set_options(ssl_ctx, flags); + } + + return ssl_ctx; +} +#endif + ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name, uint16_t port, ldns_dane_transport transport) @@ -193,7 +250,7 @@ ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs, } -/* Orinary PKIX validation of cert (with extra_certs to help) +/* Ordinary PKIX validation of cert (with extra_certs to help) * against the CA's in store, but also return the validation chain. */ static ldns_status @@ -641,7 +698,7 @@ ldns_dane_verify_rr(const ldns_rr* tlsa_rr, * verification. We use these undocumented means with the ldns * dane function prototypes which did only offline dane verification. */ - if (!(ssl_ctx = SSL_CTX_new(TLS_client_method()))) + if (!(ssl_ctx = ldns_dane_new_ssl_context())) s = LDNS_STATUS_MEM_ERR; else if (SSL_CTX_dane_enable(ssl_ctx) <= 0) @@ -841,7 +898,7 @@ ldns_dane_verify(const ldns_rr_list* tlsas, * verification. We use these undocumented means with the ldns * dane function prototypes which did only offline dane verification. */ - if (!(ssl_ctx = SSL_CTX_new(TLS_client_method()))) + if (!(ssl_ctx = ldns_dane_new_ssl_context())) s = LDNS_STATUS_MEM_ERR; else if (SSL_CTX_dane_enable(ssl_ctx) <= 0) diff --git a/contrib/ldns/dname.c b/contrib/ldns/dname.c index 17afe1d333..4f311ee298 100644 --- a/contrib/ldns/dname.c +++ b/contrib/ldns/dname.c @@ -3,7 +3,7 @@ * * dname specific rdata implementations * A dname is a rdf structure with type LDNS_RDF_TYPE_DNAME - * It is not a /real/ type! All function must therefor check + * It is not a /real/ type! All function must therefore check * for LDNS_RDF_TYPE_DNAME. * * a Net::DNS like library for C diff --git a/contrib/ldns/dnssec.c b/contrib/ldns/dnssec.c index 52c35ee760..fbaa518a8c 100644 --- a/contrib/ldns/dnssec.c +++ b/contrib/ldns/dnssec.c @@ -332,6 +332,7 @@ uint16_t ldns_calc_keytag_raw(const uint8_t* key, size_t keysize) } #ifdef HAVE_SSL +#ifdef USE_DSA DSA * ldns_key_buf2dsa(const ldns_buffer *key) { @@ -380,7 +381,7 @@ ldns_key_buf2dsa_raw(const unsigned char* key, size_t len) BN_free(Y); return NULL; } -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) #ifndef S_SPLINT_S dsa->p = P; dsa->q = Q; @@ -407,6 +408,7 @@ ldns_key_buf2dsa_raw(const unsigned char* key, size_t len) #endif /* OPENSSL_VERSION_NUMBER */ return dsa; } +#endif /* USE_DSA */ RSA * ldns_key_buf2rsa(const ldns_buffer *key) @@ -432,7 +434,7 @@ ldns_key_buf2rsa_raw(const unsigned char* key, size_t len) return NULL; /* need some smart comment here XXX*/ /* the exponent is too large so it's places - * futher...???? */ + * further...???? */ memmove(&int16, key+1, 2); exp = ntohs(int16); offset = 3; @@ -466,7 +468,7 @@ ldns_key_buf2rsa_raw(const unsigned char* key, size_t len) BN_free(modulus); return NULL; } -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) #ifndef S_SPLINT_S rsa->n = modulus; rsa->e = exponent; @@ -910,7 +912,7 @@ ldns_dnssec_create_nsec3(const ldns_dnssec_name *from, cur_rrsets = from->rrsets; while (cur_rrsets) { /* Do not include non-authoritative rrsets on the delegation point - * in the type bitmap. Potentionally not skipping insecure + * in the type bitmap. Potentially not skipping insecure * delegation should have been done earlier, in function * ldns_dnssec_zone_create_nsec3s, or even earlier in: * ldns_dnssec_zone_sign_nsec3_flg . @@ -1332,6 +1334,8 @@ ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { salt_length = ldns_rdf_data(salt_rdf)[0]; + if((size_t)salt_length+1 > ldns_rdf_size(salt_rdf)) + return NULL; salt = LDNS_XMALLOC(uint8_t, salt_length); if(!salt) return NULL; memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); @@ -1904,7 +1908,7 @@ ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, const ldns_rdf *sig_rdf) { /* convert from two BIGNUMs in the rdata buffer, to ASN notation. - * ASN preable: 30440220 0220 + * ASN preamble: 30440220 0220 * the '20' is the length of that field (=bnsize). * the '44' is the total remaining length. * if negative, start with leading zero. diff --git a/contrib/ldns/dnssec_sign.c b/contrib/ldns/dnssec_sign.c index c6d1dd2f34..41d845f3fa 100644 --- a/contrib/ldns/dnssec_sign.c +++ b/contrib/ldns/dnssec_sign.c @@ -24,6 +24,9 @@ #endif #endif /* HAVE_SSL */ +#define LDNS_SIGN_WITH_ZONEMD ( LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384 \ + | LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512 ) + ldns_rr * ldns_create_empty_rrsig(const ldns_rr_list *rrset, const ldns_key *current_key) @@ -325,14 +328,6 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) return signatures; } -/** - * Sign data with DSA - * - * \param[in] to_sign The ldns_buffer containing raw data that is - * to be signed - * \param[in] key The DSA key structure to sign with - * \return ldns_rdf for the RRSIG ldns_rr - */ ldns_rdf * ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) { @@ -413,11 +408,14 @@ ldns_pkey_is_ecdsa(EVP_PKEY* pkey) { EC_KEY* ec; const EC_GROUP* g; -#ifdef HAVE_EVP_PKEY_BASE_ID +#ifdef HAVE_EVP_PKEY_GET_BASE_ID + if(EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC) + return 0; +#elif defined(HAVE_EVP_PKEY_BASE_ID) if(EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) return 0; #else - if(EVP_PKEY_type(key->type) != EVP_PKEY_EC) + if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) return 0; #endif ec = EVP_PKEY_get1_EC_KEY(pkey); @@ -529,7 +527,9 @@ ldns_sign_public_evp(ldns_buffer *to_sign, #ifdef USE_DSA #ifndef S_SPLINT_S /* unfortunately, OpenSSL output is different from DNS DSA format */ -# ifdef HAVE_EVP_PKEY_BASE_ID +# ifdef HAVE_EVP_PKEY_GET_BASE_ID + if (EVP_PKEY_get_base_id(key) == EVP_PKEY_DSA) { +# elif defined(HAVE_EVP_PKEY_BASE_ID) if (EVP_PKEY_base_id(key) == EVP_PKEY_DSA) { # else if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) { @@ -541,7 +541,9 @@ ldns_sign_public_evp(ldns_buffer *to_sign, #endif #if defined(USE_ECDSA) if( -# ifdef HAVE_EVP_PKEY_BASE_ID +# ifdef HAVE_EVP_PKEY_GET_BASE_ID + EVP_PKEY_get_base_id(key) +# elif defined(HAVE_EVP_PKEY_BASE_ID) EVP_PKEY_base_id(key) # else EVP_PKEY_type(key->type) @@ -655,7 +657,7 @@ ldns_dnssec_addresses_on_glue_list( /* ldns_rr_list_push_rr() * returns false when unable * to increase the capacity - * of the ldsn_rr_list + * of the ldns_rr_list */ } } @@ -666,20 +668,6 @@ ldns_dnssec_addresses_on_glue_list( return LDNS_STATUS_OK; } -/** - * Marks the names in the zone that are occluded. Those names will be skipped - * when walking the tree with the ldns_dnssec_name_node_next_nonglue() - * function. But watch out! Names that are partially occluded (like glue with - * the same name as the delegation) will not be marked and should specifically - * be taken into account separately. - * - * When glue_list is given (not NULL), in the process of marking the names, all - * glue resource records will be pushed to that list, even glue at delegation names. - * - * \param[in] zone the zone in which to mark the names - * \param[in] glue_list the list to which to push the glue rrs - * \return LDNS_STATUS_OK on success, an error code otherwise - */ ldns_status ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, ldns_rr_list *glue_list) @@ -691,7 +679,7 @@ ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, /* When the cut is caused by a delegation, below_delegation will be 1. * When caused by a DNAME, below_delegation will be 0. */ - int below_delegation = -1; /* init suppresses comiler warning */ + int below_delegation = -1; /* init suppresses compiler warning */ ldns_status s; if (!zone || !zone->names) { @@ -713,7 +701,7 @@ ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, * FIXME! If there are labels in between the SOA and * the cut, going from the authoritative space (below * the SOA) up into occluded space again, will not be - * detected with the contruct below! + * detected with the construct below! */ if (ldns_dname_is_subdomain(owner, cut) && !ldns_dnssec_rrsets_contains_type( @@ -759,16 +747,6 @@ ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, return LDNS_STATUS_OK; } -/** - * Marks the names in the zone that are occluded. Those names will be skipped - * when walking the tree with the ldns_dnssec_name_node_next_nonglue() - * function. But watch out! Names that are partially occluded (like glue with - * the same name as the delegation) will not be marked and should specifically - * be taken into account separately. - * - * \param[in] zone the zone in which to mark the names - * \return LDNS_STATUS_OK on success, an error code otherwise - */ ldns_status ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone) { @@ -812,17 +790,24 @@ ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, uint32_t nsec_ttl; ldns_dnssec_rrsets *soa; - /* the TTL of NSEC rrs should be set to the minimum TTL of - * the zone SOA (RFC4035 Section 2.3) + /* The TTL value for any NSEC RR SHOULD be the same TTL value as the + * lesser of the MINIMUM field of the SOA record and the TTL of the SOA + * itself. This matches the definition of the TTL for negative + * responses in [RFC2308]. (draft-ietf-dnsop-nsec-ttl-01 update of + * RFC4035 Section 2.3) */ soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); /* did the caller actually set it? if not, * fall back to default ttl */ - if (soa && soa->rrs && soa->rrs->rr - && (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) { - nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); + if (soa && soa->rrs && soa->rrs->rr) { + ldns_rr *soa_rr = soa->rrs->rr; + ldns_rdf *min_rdf = ldns_rr_rdf(soa_rr, 6); + + nsec_ttl = min_rdf == NULL + || ldns_rr_ttl(soa_rr) < ldns_rdf2native_int32(min_rdf) + ? ldns_rr_ttl(soa_rr) : ldns_rdf2native_int32(min_rdf); } else { nsec_ttl = LDNS_DEFAULT_TTL; } @@ -906,17 +891,24 @@ ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, return LDNS_STATUS_ERR; } - /* the TTL of NSEC rrs should be set to the minimum TTL of - * the zone SOA (RFC4035 Section 2.3) + /* The TTL value for any NSEC RR SHOULD be the same TTL value as the + * lesser of the MINIMUM field of the SOA record and the TTL of the SOA + * itself. This matches the definition of the TTL for negative + * responses in [RFC2308]. (draft-ietf-dnsop-nsec-ttl-01 update of + * RFC4035 Section 2.3) */ soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); /* did the caller actually set it? if not, * fall back to default ttl */ - if (soa && soa->rrs && soa->rrs->rr - && ldns_rr_rdf(soa->rrs->rr, 6) != NULL) { - nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); + if (soa && soa->rrs && soa->rrs->rr) { + ldns_rr *soa_rr = soa->rrs->rr; + ldns_rdf *min_rdf = ldns_rr_rdf(soa_rr, 6); + + nsec_ttl = min_rdf == NULL + || ldns_rr_ttl(soa_rr) < ldns_rdf2native_int32(min_rdf) + ? ldns_rr_ttl(soa_rr) : ldns_rdf2native_int32(min_rdf); } else { nsec_ttl = LDNS_DEFAULT_TTL; } @@ -1141,17 +1133,22 @@ ldns_key_list_filter_for_dnskey(ldns_key_list *key_list, int flags) if (!ldns_key_list_key_count(key_list)) return; + /* Mark all KSKs */ for (i = 0; i < ldns_key_list_key_count(key_list); i++) { key = ldns_key_list_key(key_list, i); - if ((ldns_key_flags(key) & LDNS_KEY_SEP_KEY) && !saw_ksk) - saw_ksk = ldns_key_algorithm(key); - algos[ldns_key_algorithm(key)] = true; + if ((ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) { + if (!saw_ksk) + saw_ksk = ldns_key_algorithm(key); + algos[ldns_key_algorithm(key)] = true; + } } if (!saw_ksk) - return; - else - algos[saw_ksk] = 0; + return; /* No KSKs means sign using all ZSKs */ + /* Deselect the ZSKs so they do not sign DNSKEY RRs. + * Except with the LDNS_SIGN_WITH_ALL_ALGORITHMS flag, then use it, + * but only if it has an algorithm for which there is no KSK + */ for (i =0; i < ldns_key_list_key_count(key_list); i++) { key = ldns_key_list_key(key_list, i); if (!(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) { @@ -1159,15 +1156,15 @@ ldns_key_list_filter_for_dnskey(ldns_key_list *key_list, int flags) * Still use it if it has a unique algorithm though! */ if ((flags & LDNS_SIGN_WITH_ALL_ALGORITHMS) && - algos[ldns_key_algorithm(key)]) - algos[ldns_key_algorithm(key)] = false; + !algos[ldns_key_algorithm(key)]) + algos[ldns_key_algorithm(key)] = true; else ldns_key_set_use(key, 0); } } } -/** If there are no ZSKs use KSK as ZSK */ +/** If there are no ZSKs use KSKs as ZSK too */ static void ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list, int flags) { @@ -1183,17 +1180,22 @@ ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list, int flags) if (!ldns_key_list_key_count(key_list)) return; + /* Mark all ZSKs */ for (i = 0; i < ldns_key_list_key_count(key_list); i++) { key = ldns_key_list_key(key_list, i); - if (!(ldns_key_flags(key) & LDNS_KEY_SEP_KEY) && !saw_zsk) - saw_zsk = ldns_key_algorithm(key); - algos[ldns_key_algorithm(key)] = true; + if (!(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) { + if (!saw_zsk) + saw_zsk = ldns_key_algorithm(key); + algos[ldns_key_algorithm(key)] = true; + } } if (!saw_zsk) - return; - else - algos[saw_zsk] = 0; + return; /* No ZSKs means sign using all KSKs */ + /* Deselect the KSKs so they do not sign non DNSKEY RRs. + * Except with the LDNS_SIGN_WITH_ALL_ALGORITHMS flag, then use it, + * but only if it has an algorithm for which there is no ZSK + */ for (i = 0; i < ldns_key_list_key_count(key_list); i++) { key = ldns_key_list_key(key_list, i); if((ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) { @@ -1201,8 +1203,8 @@ ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list, int flags) * Still use it if it has a unique algorithm though! */ if ((flags & LDNS_SIGN_WITH_ALL_ALGORITHMS) && - algos[ldns_key_algorithm(key)]) - algos[ldns_key_algorithm(key)] = false; + !algos[ldns_key_algorithm(key)]) + algos[ldns_key_algorithm(key)] = true; else ldns_key_set_use(key, 0); } @@ -1365,6 +1367,8 @@ ldns_dnssec_zone_sign(ldns_dnssec_zone *zone, return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0); } +ldns_status dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, ldns_key_list *key_list, int flags); ldns_status ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, @@ -1374,25 +1378,46 @@ ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, int flags) { ldns_status result = LDNS_STATUS_OK; + ldns_dnssec_rrsets zonemd_rrset; + bool zonemd_added = false; if (!zone || !new_rrs || !key_list) { return LDNS_STATUS_ERR; } - + if (flags & LDNS_SIGN_WITH_ZONEMD) { + ldns_dnssec_rrsets **rrsets_ref = &zone->soa->rrsets; + + while (*rrsets_ref + && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD) + rrsets_ref = &(*rrsets_ref)->next; + if (!*rrsets_ref + || (*rrsets_ref)->type > LDNS_RR_TYPE_ZONEMD) { + zonemd_rrset.rrs = NULL; + zonemd_rrset.type = LDNS_RR_TYPE_ZONEMD; + zonemd_rrset.signatures = NULL; + zonemd_rrset.next = *rrsets_ref; + *rrsets_ref = &zonemd_rrset; + zonemd_added = true; + } + } /* zone is already sorted */ result = ldns_dnssec_zone_mark_glue(zone); if (result != LDNS_STATUS_OK) { return result; } - /* check whether we need to add nsecs */ - if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) { + if ((flags & LDNS_SIGN_NO_KEYS_NO_NSECS) + && ldns_key_list_key_count(key_list) < 1) + ; /* pass */ + + else if (zone->names + && !((ldns_dnssec_name *)zone->names->root->data)->nsec) { + result = ldns_dnssec_zone_create_nsecs(zone, new_rrs); if (result != LDNS_STATUS_OK) { return result; } } - result = ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, @@ -1400,7 +1425,18 @@ ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, arg, flags); - return result; + if (zonemd_added) { + ldns_dnssec_rrsets **rrsets_ref + = &zone->soa->rrsets; + + while (*rrsets_ref + && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD) + rrsets_ref = &(*rrsets_ref)->next; + *rrsets_ref = zonemd_rrset.next; + } + return flags & LDNS_SIGN_WITH_ZONEMD + ? dnssec_zone_equip_zonemd(zone, new_rrs, key_list, flags) + : result; } ldns_status @@ -1436,6 +1472,8 @@ ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, { ldns_rr *nsec3, *nsec3param; ldns_status result = LDNS_STATUS_OK; + bool zonemd_added = false; + ldns_dnssec_rrsets zonemd_rrset; /* zone is already sorted */ result = ldns_dnssec_zone_mark_glue(zone); @@ -1454,7 +1492,13 @@ ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, } nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec; - if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) { + + /* check whether we need to add nsecs */ + if ((signflags & LDNS_SIGN_NO_KEYS_NO_NSECS) + && ldns_key_list_key_count(key_list) < 1) + ; /* pass */ + + else if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) { /* no need to recreate */ } else { if (!ldns_dnssec_zone_find_rrset(zone, @@ -1481,6 +1525,23 @@ ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, } ldns_rr_list_push_rr(new_rrs, nsec3param); } + if (signflags & LDNS_SIGN_WITH_ZONEMD) { + ldns_dnssec_rrsets **rrsets_ref + = &zone->soa->rrsets; + + while (*rrsets_ref + && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD) + rrsets_ref = &(*rrsets_ref)->next; + if (!*rrsets_ref + || (*rrsets_ref)->type > LDNS_RR_TYPE_ZONEMD) { + zonemd_rrset.rrs = NULL; + zonemd_rrset.type = LDNS_RR_TYPE_ZONEMD; + zonemd_rrset.signatures = NULL; + zonemd_rrset.next = *rrsets_ref; + *rrsets_ref = &zonemd_rrset; + zonemd_added = true; + } + } result = ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm, @@ -1489,6 +1550,15 @@ ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, salt_length, salt, map); + if (zonemd_added) { + ldns_dnssec_rrsets **rrsets_ref + = &zone->soa->rrsets; + + while (*rrsets_ref + && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD) + rrsets_ref = &(*rrsets_ref)->next; + *rrsets_ref = zonemd_rrset.next; + } if (result != LDNS_STATUS_OK) { return result; } @@ -1501,8 +1571,12 @@ ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, arg, signflags); } + if (result || !zone->names) + return result; - return result; + return signflags & LDNS_SIGN_WITH_ZONEMD + ? dnssec_zone_equip_zonemd(zone, new_rrs, key_list, signflags) + : result; } ldns_status diff --git a/contrib/ldns/dnssec_verify.c b/contrib/ldns/dnssec_verify.c index d22962eb90..d76f32eba7 100644 --- a/contrib/ldns/dnssec_verify.c +++ b/contrib/ldns/dnssec_verify.c @@ -21,7 +21,7 @@ ldns_dnssec_data_chain_new(void) ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1); if(!nc) return NULL; /* - * not needed anymore because CALLOC initalizes everything to zero. + * not needed anymore because CALLOC initializes everything to zero. nc->rrset = NULL; nc->parent_type = 0; @@ -597,7 +597,9 @@ ldns_dnssec_trust_tree_print_sm_fmt(FILE *out, if (tree->parent_status[i] == LDNS_STATUS_SSL_ERR) { printf("; SSL Error: "); +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(HAVE_LIBRESSL) ERR_load_crypto_strings(); +#endif ERR_print_errors_fp(stdout); printf("\n"); } @@ -1501,7 +1503,7 @@ ldns_dnssec_verify_denial(ldns_rr *rr, ldns_rr_list *rrsigs) { ldns_rdf *rr_name; - ldns_rdf *wildcard_name; + ldns_rdf *wildcard_name = NULL; ldns_rdf *chopped_dname; ldns_rr *cur_nsec; size_t i; @@ -1512,14 +1514,19 @@ ldns_dnssec_verify_denial(ldns_rr *rr, bool type_covered = false; bool wildcard_covered = false; bool wildcard_type_covered = false; + bool rr_name_is_root = false; - wildcard_name = ldns_dname_new_frm_str("*"); rr_name = ldns_rr_owner(rr); - chopped_dname = ldns_dname_left_chop(rr_name); - result = ldns_dname_cat(wildcard_name, chopped_dname); - ldns_rdf_deep_free(chopped_dname); - if (result != LDNS_STATUS_OK) { - return result; + rr_name_is_root = ldns_rdf_size(rr_name) == 1 + && *ldns_rdf_data(rr_name) == 0; + if (!rr_name_is_root) { + wildcard_name = ldns_dname_new_frm_str("*"); + chopped_dname = ldns_dname_left_chop(rr_name); + result = ldns_dname_cat(wildcard_name, chopped_dname); + ldns_rdf_deep_free(chopped_dname); + if (result != LDNS_STATUS_OK) { + return result; + } } for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { @@ -1546,6 +1553,9 @@ ldns_dnssec_verify_denial(ldns_rr *rr, name_covered = true; } + if (rr_name_is_root) + continue; + if (ldns_dname_compare(wildcard_name, ldns_rr_owner(cur_nsec)) == 0) { if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), @@ -1566,6 +1576,9 @@ ldns_dnssec_verify_denial(ldns_rr *rr, return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; } + if (rr_name_is_root) + return LDNS_STATUS_OK; + if (wildcard_type_covered || !wildcard_covered) { return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; } @@ -2390,8 +2403,12 @@ ldns_verify_rrsig_keylist_time( ldns_rr_list *good_keys) { ldns_status result; - ldns_rr_list *valid = ldns_rr_list_new(); - if (!valid) + ldns_rr_list *valid; + + if (!good_keys) + valid = NULL; + + else if (!(valid = ldns_rr_list_new())) return LDNS_STATUS_MEM_ERR; result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid); diff --git a/contrib/ldns/dnssec_zone.c b/contrib/ldns/dnssec_zone.c index e089754ddb..7be6791e7f 100644 --- a/contrib/ldns/dnssec_zone.c +++ b/contrib/ldns/dnssec_zone.c @@ -323,7 +323,7 @@ ldns_dnssec_name_new(void) return NULL; } /* - * not needed anymore because CALLOC initalizes everything to zero. + * not needed anymore because CALLOC initializes everything to zero. new_name->name = NULL; new_name->rrsets = NULL; @@ -370,9 +370,10 @@ ldns_dnssec_name_free_internal(ldns_dnssec_name *name, ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep); } if (name->hashed_name) { - if (deep) { - ldns_rdf_deep_free(name->hashed_name); - } + /* Hashed name is always allocated when signing, + * so always deep free + */ + ldns_rdf_deep_free(name->hashed_name); } LDNS_FREE(name); } @@ -588,7 +589,7 @@ rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t) /* When the zone is first read into an list and then inserted into an * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next) * to each other. Because ldns-verify-zone (the only program that uses this - * function) uses the rbtree mostly for sequentual walking, this results + * function) uses the rbtree mostly for sequential walking, this results * in a speed increase (of 15% on linux) because we have less CPU-cache misses. */ #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */ @@ -604,9 +605,13 @@ ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) { LDNS_FREE(node); } +ldns_status _ldns_rr_new_frm_fp_l_internal(ldns_rr **newrr, FILE *fp, + uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, + int *line_nr, bool *explicit_ttl); + ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin, - uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr) + uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr) { ldns_rr* cur_rr; size_t i; @@ -626,7 +631,7 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* or nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will hold the NSEC3s that still didn't have a matching name in the zone tree, even after all names were read. They can only match - after the zone is equiped with all the empty non terminals. */ + after the zone is equipped with all the empty non terminals. */ ldns_rbtree_t todo_nsec3_ents; ldns_rbnode_t *new_node; ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new(); @@ -636,13 +641,19 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* or #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP ldns_zone* zone = NULL; #else - uint32_t my_ttl = ttl; + ldns_rr *prev_rr = NULL; + uint32_t my_ttl = default_ttl; + /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default + * to the last explicitly stated values.' + */ + bool ttl_from_TTL = false; + bool explicit_ttl = false; #endif ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v); #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP - status = ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr); + status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr); if (status != LDNS_STATUS_OK) goto error; #endif @@ -672,13 +683,61 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* or status = LDNS_STATUS_OK; #else while (!feof(fp)) { + /* If ttl came from $TTL line, then it should be the default. + * (RFC 2308 Section 4) + * Otherwise it "defaults to the last explicitly stated value" + * (RFC 1035 Section 5.1) + */ + if (ttl_from_TTL) + my_ttl = default_ttl; status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin, - &my_prev, line_nr); - + &my_prev, line_nr, &explicit_ttl); #endif switch (status) { case LDNS_STATUS_OK: +#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP + if (explicit_ttl) { + if (!ttl_from_TTL) { + /* No $TTL, so ttl "defaults to the + * last explicitly stated value" + * (RFC 1035 Section 5.1) + */ + my_ttl = ldns_rr_ttl(cur_rr); + } + /* When ttl is implicit, try to adhere to the rules as + * much as possible. (also for compatibility with bind) + * This was changed when fixing an issue with ZONEMD + * which hashes the TTL too. + */ + } else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG + || ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) { + if (ldns_rr_rd_count(cur_rr) >= 4 + && ldns_rdf_get_type(ldns_rr_rdf(cur_rr, 3)) == LDNS_RDF_TYPE_INT32) + + /* SIG without explicit ttl get ttl + * from the original_ttl field + * (RFC 2535 Section 7.2) + * + * Similarly for RRSIG, but stated less + * specifically in the spec. + * (RFC 4034 Section 3) + */ + ldns_rr_set_ttl(cur_rr, + ldns_rdf2native_int32( + ldns_rr_rdf(rr, 3))); + + } else if (prev_rr + && ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr) + && ldns_dname_compare( ldns_rr_owner(prev_rr) + , ldns_rr_owner(cur_rr)) == 0) + + /* "TTLs of all RRs in an RRSet must be the same" + * (RFC 2881 Section 5.2) + */ + ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr)); + prev_rr = cur_rr; +#endif status = ldns_dnssec_zone_add_rr(newzone, cur_rr); if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) { @@ -698,9 +757,16 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* or break; + case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ +#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP + default_ttl = my_ttl; + ttl_from_TTL = true; +#endif + status = LDNS_STATUS_OK; + break; + case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ - case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ status = LDNS_STATUS_OK; break; @@ -793,10 +859,21 @@ ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) { LDNS_FREE(node); } +static void +ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) { + (void) arg; + LDNS_FREE(node); +} + void ldns_dnssec_zone_free(ldns_dnssec_zone *zone) { if (zone) { + if (zone->hashed_names) { + ldns_traverse_postorder(zone->hashed_names, + ldns_hashed_names_node_free, NULL); + LDNS_FREE(zone->hashed_names); + } if (zone->names) { /* destroy all name structures within the tree */ ldns_traverse_postorder(zone->names, @@ -812,6 +889,11 @@ void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone) { if (zone) { + if (zone->hashed_names) { + ldns_traverse_postorder(zone->hashed_names, + ldns_hashed_names_node_free, NULL); + LDNS_FREE(zone->hashed_names); + } if (zone->names) { /* destroy all name structures within the tree */ ldns_traverse_postorder(zone->names, @@ -833,12 +915,6 @@ static void ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone, ldns_dnssec_name* name, ldns_rr* nsec3rr); -static void -ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) { - (void) arg; - LDNS_FREE(node); -} - static void ldns_dnssec_zone_hashed_names_from_nsec3( ldns_dnssec_zone* zone, ldns_rr* nsec3rr) @@ -908,20 +984,22 @@ ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone, static ldns_rbnode_t * ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) { ldns_rdf *hashed_name; + ldns_rbnode_t *to_return; - hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); - if (hashed_name == NULL) { - return NULL; - } if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){ ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr); } if (zone->hashed_names == NULL) { - ldns_rdf_deep_free(hashed_name); return NULL; } - return ldns_rbtree_search(zone->hashed_names, hashed_name); + hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); + if (hashed_name == NULL) { + return NULL; + } + to_return = ldns_rbtree_search(zone->hashed_names, hashed_name); + ldns_rdf_deep_free(hashed_name); + return to_return; } ldns_status @@ -1127,6 +1205,7 @@ ldns_dnssec_zone_add_empty_nonterminals_nsec3( } node = ldns_rbtree_search(nsec3s, ent_hashed_name); + ldns_rdf_deep_free(ent_hashed_name); if (!node) { ldns_rdf_deep_free(l1); ldns_rdf_deep_free(l2); @@ -1201,3 +1280,706 @@ ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone) } return false; } + +/* + * Stuff for calculating and verifying zone digests + */ +typedef enum dnssec_zone_rr_iter_state { + DNSSEC_ZONE_RR_ITER_LT_RRSIG + , DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC + , DNSSEC_ZONE_RR_ITER_REST + , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC + , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST + , DNSSEC_ZONE_RR_ITER_NSEC3 + , DNSSEC_ZONE_RR_ITER_FINI +} dnssec_zone_rr_iter_state; + +typedef struct dnssec_zone_rr_iter { + ldns_dnssec_zone *zone; + ldns_rbnode_t *node; + ldns_dnssec_name *name; + ldns_dnssec_rrsets *rrsets; + ldns_dnssec_rrs *rrs; + ldns_dnssec_rrsets *rrsets4rrsigs; + ldns_rbnode_t *nsec3_node; + ldns_dnssec_name *nsec3_name; + dnssec_zone_rr_iter_state state; + ldns_rdf *apex_name; + uint8_t apex_labs; +} dnssec_zone_rr_iter; + +INLINE void +dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i) +{ + /* Make sure the i->name is "in zone" (i.e. below the apex) */ + if (i->apex_name) { + ldns_rdf *name = (ldns_rdf *)i->node->key; + + while (i->name && name != i->apex_name /* not apex */ + + && ( ldns_dname_label_count(name) != i->apex_labs + || ldns_dname_compare(name, i->apex_name)) /* not apex */ + + && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) { + + /* next name */ + i->node = ldns_rbtree_next(i->node); + if (i->node == LDNS_RBTREE_NULL) + i->name = NULL; + else { + i->name = (ldns_dnssec_name *)i->node->data; + name = (ldns_rdf *)i->node->key; + } + } + } + /* determine state */ + if (!i->name) { + if (!i->nsec3_name) + i->state = DNSSEC_ZONE_RR_ITER_FINI; + else { + i->rrs = i->nsec3_name->nsec_signatures; + i->state = DNSSEC_ZONE_RR_ITER_NSEC3; + } + } else if (!i->nsec3_name) { + i->rrsets = i->name->rrsets; + i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG; + + } else if (ldns_dname_compare( ldns_rr_owner(i->nsec3_name->nsec) + , (ldns_rdf *)i->node->key) < 0) { + i->rrs = i->nsec3_name->nsec_signatures; + i->state = DNSSEC_ZONE_RR_ITER_NSEC3; + } else { + i->rrsets = i->name->rrsets; + i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG; + } +} + +/** + * Iterate over the RR's in the ldns_dnssec_zone in canonical order. + * There are three possible paths through the RR's in a ldns_dnssec_name. + * + * 1. There is no NSEC: + * + * 1.1. All the RRs in the name->rrsets with type < RRSIG, + * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG + * + * 1.2. Then all the RRSIGs from name->rrsets (likely none) + * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC + * + * 1.3. Finally the remaining RRs in name->rrsets (type > RRSIG) + * state: DNSSEC_ZONE_RR_ITER_REST + * + * + * 2. There is a NSEC of type NSEC with this name: + * + * 2.1. All the RRs in the name->rrsets with type < RRSIG, + * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG + * + * 2.2. Then all the RRSIGs from name->rrsets with type < NSEC + * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC + * + * 2.3. Then the signatures of the NSEC RR, followed by + * the signatures of the remaining name->rrsets (type > NSEC), + * followed by the NSEC rr. + * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC + * + * 2.4. Finally the remaining RRs in name->rrsets (type > RRSIG) + * state: DNSSEC_ZONE_RR_ITER_REST + * + * + * 3. There is a NSEC of type NSEC3 for this name: + * + * 3.1. If the NSEC3 name is before the name for other RRsets in the zone, + * Then all signatures of the NSEC3 RR, followed by the NSEC3 + * state: DNSSEC_ZONE_RR_ITER_NSEC3 + * + * otherwise follow path for "no NSEC" for the name for other RRsets + */ +static ldns_rr * +dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i) +{ + ldns_rr *nsec3; + + for (;;) { + if (i->rrs) { + ldns_rr *rr = i->rrs->rr; + i->rrs = i->rrs->next; + return rr; + } + switch (i->state) { + case DNSSEC_ZONE_RR_ITER_LT_RRSIG: + if (i->rrsets + && i->rrsets->type < LDNS_RR_TYPE_RRSIG) { + + i->rrs = i->rrsets->rrs; + i->rrsets = i->rrsets->next; + break; + } + i->rrsets4rrsigs = i->name->rrsets; + if (i->name->nsec && ldns_rr_get_type(i->name->nsec) + == LDNS_RR_TYPE_NSEC) { + + i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC; + break; + } + i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC; + /* fallthrough */ + + case DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC: + if (i->rrsets4rrsigs) { + i->rrs = i->rrsets4rrsigs->signatures; + i->rrsets4rrsigs = i->rrsets4rrsigs->next; + break; + } + i->state = DNSSEC_ZONE_RR_ITER_REST; + /* fallthrough */ + + case DNSSEC_ZONE_RR_ITER_REST: + if (i->rrsets) { + i->rrs = i->rrsets->rrs; + i->rrsets = i->rrsets->next; + break; + } + /* next name */ + i->node = ldns_rbtree_next(i->node); + i->name = i->node == LDNS_RBTREE_NULL ? NULL + : (ldns_dnssec_name *)i->node->data; + + dnssec_zone_rr_iter_set_state_for_next_name(i); + break; + + case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC: + if (i->rrsets4rrsigs + && i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) { + + i->rrs = i->rrsets4rrsigs->signatures; + i->rrsets4rrsigs = i->rrsets4rrsigs->next; + break; + } + i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST; + i->rrs = i->name->nsec_signatures; + break; + + case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST: + if (i->rrsets4rrsigs) { + i->rrs = i->rrsets4rrsigs->signatures; + i->rrsets4rrsigs = i->rrsets4rrsigs->next; + break; + } + i->state = DNSSEC_ZONE_RR_ITER_REST; + return i->name->nsec; + + case DNSSEC_ZONE_RR_ITER_NSEC3: + nsec3 = i->nsec3_name->nsec; + + /* next nsec3 */ + do { + i->nsec3_node + = ldns_rbtree_next(i->nsec3_node); + i->nsec3_name + = i->nsec3_node == LDNS_RBTREE_NULL ? NULL + : (ldns_dnssec_name*)i->nsec3_node->data; + + /* names for glue can be in the hashed_names + * tree, but will not have a NSEC3 + */ + } while (i->nsec3_name && !i->nsec3_name->nsec); + + dnssec_zone_rr_iter_set_state_for_next_name(i); + return nsec3; + + case DNSSEC_ZONE_RR_ITER_FINI: + return NULL; + } + } +} + +static ldns_rr * +dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone) +{ + if (!i || !zone) + return NULL; + + memset(i, 0, sizeof(*i)); + i->zone = zone; + if (zone->soa && zone->soa->name) { + i->apex_name = zone->soa->name; + i->apex_labs = ldns_dname_label_count(i->apex_name); + } else + i->apex_name = NULL; + + + i->node = ldns_rbtree_first(zone->names); + i->name = i->node == LDNS_RBTREE_NULL ? NULL + : (ldns_dnssec_name *)i->node->data; + + if (zone->hashed_names) { + do { + i->nsec3_node = ldns_rbtree_first(zone->hashed_names); + i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ?NULL + : (ldns_dnssec_name*)i->nsec3_node->data; + } while (i->nsec3_name && !i->nsec3_name->nsec); + } + dnssec_zone_rr_iter_set_state_for_next_name(i); + return dnssec_zone_rr_iter_next(i); +} + +enum enum_zonemd_scheme { + ZONEMD_SCHEME_FIRST = 1, + ZONEMD_SCHEME_SIMPLE = 1, + ZONEMD_SCHEME_LAST = 1 +}; +typedef enum enum_zonemd_scheme zonemd_scheme; + +enum enum_zonemd_hash { + ZONEMD_HASH_FIRST = 1, + ZONEMD_HASH_SHA384 = 1, + ZONEMD_HASH_SHA512 = 2, + ZONEMD_HASH_LAST = 2 +}; +typedef enum enum_zonemd_hash zonemd_hash; + +struct struct_zone_digester { + ldns_sha384_CTX sha384_CTX; + ldns_sha512_CTX sha512_CTX; + unsigned simple_sha384 : 1; + unsigned simple_sha512 : 1; + unsigned double_sha384 : 1; + unsigned double_sha512 : 1; +}; +typedef struct struct_zone_digester zone_digester; + +INLINE bool zone_digester_set(zone_digester *zd) +{ return zd && (zd->simple_sha384 || zd->simple_sha512); } + +INLINE void zone_digester_init(zone_digester *zd) +{ memset(zd, 0, sizeof(*zd)); } + +static ldns_status +zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash) +{ + if (!zd) + return LDNS_STATUS_NULL; + + switch (scheme) { + case ZONEMD_SCHEME_SIMPLE: + switch (hash) { + case ZONEMD_HASH_SHA384: + if (zd->double_sha384) + return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE; + + else if (zd->simple_sha384) { + zd->simple_sha384 = 0; + zd->double_sha384 = 1; + return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE; + } + ldns_sha384_init(&zd->sha384_CTX); + zd->simple_sha384 = 1; + break; + + case ZONEMD_HASH_SHA512: + if (zd->double_sha512) + return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE; + + else if (zd->simple_sha512) { + zd->simple_sha512 = 0; + zd->double_sha512 = 1; + return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE; + } + ldns_sha512_init(&zd->sha512_CTX); + zd->simple_sha512 = 1; + break; + default: + return LDNS_STATUS_ZONEMD_UNKNOWN_HASH; + } + break; + default: + return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME; + } + return LDNS_STATUS_OK; +} + +static ldns_status +zone_digester_update(zone_digester *zd, ldns_rr *rr) +{ + uint8_t data[65536]; + ldns_buffer buf; + ldns_status st; + + buf._data = data; + buf._position = 0; + buf._limit = sizeof(data); + buf._capacity = sizeof(data); + buf._fixed = 1; + buf._status = LDNS_STATUS_OK; + + if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER))) + return st; + + if (zd->simple_sha384) + ldns_sha384_update(&zd->sha384_CTX, data, buf._position); + + if (zd->simple_sha512) + ldns_sha512_update(&zd->sha512_CTX, data, buf._position); + + return LDNS_STATUS_OK; +} + +INLINE ldns_rr * +new_zonemd(ldns_rr *soa, zonemd_hash hash) +{ + ldns_rr *rr = NULL; + uint8_t *data = NULL; + ldns_rdf *rdf; + size_t md_len = hash == ZONEMD_HASH_SHA384 + ? LDNS_SHA384_DIGEST_LENGTH + : LDNS_SHA512_DIGEST_LENGTH; + + if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD))) + return NULL; + + if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa)))) + goto error; + + ldns_rr_set_owner(rr, rdf); + ldns_rr_set_class(rr, ldns_rr_get_class(soa)); + ldns_rr_set_ttl(rr, ldns_rr_ttl(soa)); + + if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2)))) + goto error; + ldns_rr_set_rdf(rr, rdf, 0); + + if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1))) + goto error; + ldns_rr_set_rdf(rr, rdf, 1); + + if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash))) + goto error; + ldns_rr_set_rdf(rr, rdf, 2); + + if (!(data = LDNS_XMALLOC(uint8_t, md_len))) + goto error; + + if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data))) + goto error; + ldns_rr_set_rdf(rr, rdf, 3); + + return rr; +error: + if (data) + LDNS_FREE(data); + ldns_rr_free(rr); + return NULL; +} + +static ldns_rr_list * +zone_digester_export( + zone_digester *zd, ldns_rr *soa, ldns_status *ret_st) +{ + ldns_status st = LDNS_STATUS_OK; + ldns_rr_list *rr_list = NULL; + ldns_rr *sha384 = NULL; + ldns_rr *sha512 = NULL; + + if (!zd || !soa) + st = LDNS_STATUS_NULL; + + else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA + || ldns_rr_rd_count(soa) < 3) + st = LDNS_STATUS_ZONEMD_INVALID_SOA; + + else if (!(rr_list = ldns_rr_list_new())) + st = LDNS_STATUS_MEM_ERR; + + else if (zd->simple_sha384 + && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384))) + st = LDNS_STATUS_MEM_ERR; + + else if (zd->simple_sha512 + && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512))) + st = LDNS_STATUS_MEM_ERR; + + else if (zd->simple_sha384 + && !ldns_rr_list_push_rr(rr_list, sha384)) + st = LDNS_STATUS_MEM_ERR; + + else if (zd->simple_sha512 + && !ldns_rr_list_push_rr(rr_list, sha512)) { + if (zd->simple_sha384) + sha384 = NULL; /* deleted by ldns_rr_list_deep_free */ + st = LDNS_STATUS_MEM_ERR; + + } else { + if (sha384) + ldns_sha384_final( ldns_rdf_data(ldns_rr_rdf(sha384,3)) + , &zd->sha384_CTX); + if (sha512) + ldns_sha512_final( ldns_rdf_data(ldns_rr_rdf(sha512,3)) + , &zd->sha512_CTX); + return rr_list; + } + if (ret_st) + *ret_st = st; + if (sha384) + ldns_rr_free(sha384); + if (sha512) + ldns_rr_free(sha512); + if (rr_list) + ldns_rr_list_deep_free(rr_list); + return NULL; +} + +static ldns_status +ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd) +{ + ldns_status st = LDNS_STATUS_OK; + dnssec_zone_rr_iter rr_iter; + ldns_rr *rr; + ldns_rdf *apex_name; /* name of zone apex */ + + if (!zone || !zd || !zone->soa || !zone->soa->name) + return LDNS_STATUS_NULL; + + apex_name = zone->soa->name; + for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone) + ; rr && !st + ; rr = dnssec_zone_rr_iter_next(&rr_iter)) { + /* Skip apex ZONEMD RRs */ + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_ZONEMD + && !ldns_dname_compare(ldns_rr_owner(rr), apex_name)) + continue; + /* Skip RRSIGs for apex ZONEMD RRs */ + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG + && LDNS_RR_TYPE_ZONEMD == ldns_rdf2rr_type( + ldns_rr_rrsig_typecovered(rr)) + && !ldns_dname_compare(ldns_rr_owner(rr), apex_name)) + continue; + st = zone_digester_update(zd, rr); + } + return st; +} + +ldns_status +ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone) +{ + ldns_dnssec_rrsets *zonemd, *soa; + zone_digester zd; + ldns_dnssec_rrs *rrs; + ldns_rr *soa_rr; + ldns_status st; + uint8_t simple_sha384[LDNS_SHA384_DIGEST_LENGTH]; + uint8_t simple_sha512[LDNS_SHA512_DIGEST_LENGTH]; + size_t valid_zonemds; + + if (!zone) + return LDNS_STATUS_NULL; + + zonemd = ldns_dnssec_zone_find_rrset( + zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD); + if (!zonemd) { + ldns_rbnode_t *nsec3_node; + + /* we need proof of non-existence for ZONEMD at the apex */ + if (zone->soa->nsec) { + if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap( + zone->soa->nsec), + LDNS_RR_TYPE_ZONEMD)) + return LDNS_STATUS_NO_ZONEMD; + + } else if (!zone->soa->hashed_name || !zone->hashed_names) + return LDNS_STATUS_NO_ZONEMD; + + else if (LDNS_RBTREE_NULL == + (nsec3_node = ldns_rbtree_search( zone->hashed_names + , zone->soa->hashed_name))) + return LDNS_STATUS_NO_ZONEMD; + else { + ldns_dnssec_name *nsec3 + = (ldns_dnssec_name *)nsec3_node->data; + if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap( + nsec3->nsec), + LDNS_RR_TYPE_ZONEMD)) + return LDNS_STATUS_NO_ZONEMD; + } + /* ZONEMD at apex does really not exist */ + return LDNS_STATUS_OK; + } + soa = ldns_dnssec_zone_find_rrset( + zone, zone->soa->name, LDNS_RR_TYPE_SOA); + if (!soa || !soa->rrs || !soa->rrs->rr) + return LDNS_STATUS_ZONEMD_INVALID_SOA; + + soa_rr = soa->rrs->rr; + if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA + || ldns_rr_rd_count(soa_rr) < 3) + return LDNS_STATUS_ZONEMD_INVALID_SOA; + + zone_digester_init(&zd); + for (rrs = zonemd->rrs; rrs; rrs = rrs->next) { + if (!rrs->rr + || ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD + || ldns_rr_rd_count(rrs->rr) < 4) + continue; + + /* serial should match SOA's serial */ + if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2)) + != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0))) + continue; + + /* Add (scheme, hash) to digester */ + zone_digester_add(&zd, + ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)), + ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 2))); + } + if (!zone_digester_set(&zd)) + return LDNS_STATUS_NO_VALID_ZONEMD; + + if ((st = ldns_digest_zone(zone, &zd))) + return st; + + if (zd.simple_sha384) + ldns_sha384_final(simple_sha384, &zd.sha384_CTX); + if (zd.simple_sha512) + ldns_sha512_final(simple_sha512, &zd.sha512_CTX); + + valid_zonemds = 0; + for (rrs = zonemd->rrs; rrs; rrs = rrs->next) { + if (!rrs->rr + || ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD + || ldns_rr_rd_count(rrs->rr) < 4) + continue; + + /* serial should match SOA's serial */ + if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2)) + != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0))) + continue; + + if (ZONEMD_SCHEME_SIMPLE != + ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1))) + continue; + + if (ZONEMD_HASH_SHA384 + == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2)) + && LDNS_SHA384_DIGEST_LENGTH + == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3)) + && memcmp( simple_sha384 + , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3)) + , LDNS_SHA384_DIGEST_LENGTH) == 0) + + valid_zonemds += 1; + + if (ZONEMD_HASH_SHA512 + == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2)) + && LDNS_SHA512_DIGEST_LENGTH + == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3)) + && memcmp( simple_sha512 + , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3)) + , LDNS_SHA512_DIGEST_LENGTH) == 0) + + valid_zonemds += 1; + } + return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD; +} + +#ifdef HAVE_SSL +static ldns_status +rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs, + ldns_rr_list *new_rrs) +{ + ldns_rr *rr = NULL; + + if (!rr_list || !rrs) + return LDNS_STATUS_NULL; + + if (ldns_rr_list_rr_count(rr_list) == 0) + return LDNS_STATUS_OK; + + if (!*rrs) { + if (!(*rrs = ldns_dnssec_rrs_new())) + return LDNS_STATUS_MEM_ERR; + (*rrs)->rr = ldns_rr_list_pop_rr(rr_list); + if (new_rrs) + ldns_rr_list_push_rr(new_rrs, (*rrs)->rr); + } + while ((rr = ldns_rr_list_pop_rr(rr_list))) { + ldns_status st; + + if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) { + ldns_rr_list_push_rr(rr_list, rr); + return st; + } else if (new_rrs) + ldns_rr_list_push_rr(new_rrs, rr); + } + return LDNS_STATUS_OK; +} + + +ldns_status +dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags) +{ + ldns_status st = LDNS_STATUS_OK; + zone_digester zd; + ldns_rr_list *zonemd_rr_list = NULL; + ldns_rr_list *zonemd_rrsigs = NULL; + ldns_dnssec_rrsets *soa_rrset; + ldns_rr *soa_rr = NULL; + ldns_dnssec_rrsets **rrset_ref; + ldns_dnssec_rrsets *zonemd_rrset; + + zone_digester_init(&zd); + if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384) + zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE + , ZONEMD_HASH_SHA384); + + if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512) + zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE + , ZONEMD_HASH_SHA512); + + if ((st = ldns_digest_zone(zone, &zd))) + return st; + + soa_rrset = ldns_dnssec_zone_find_rrset( + zone, zone->soa->name, LDNS_RR_TYPE_SOA); + if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr) + return LDNS_STATUS_ZONEMD_INVALID_SOA; + soa_rr = soa_rrset->rrs->rr; + + if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st))) + return st; + + /* - replace or add ZONEMD rrset */ + rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */ + while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD) + rrset_ref = &(*rrset_ref)->next; + if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) { + /* reuse zonemd rrset */ + zonemd_rrset = *rrset_ref; + ldns_dnssec_rrs_free(zonemd_rrset->rrs); + zonemd_rrset->rrs = NULL; + ldns_dnssec_rrs_free(zonemd_rrset->signatures); + zonemd_rrset->signatures = NULL; + } else { + /* insert zonemd rrset */ + zonemd_rrset = ldns_dnssec_rrsets_new(); + if (!zonemd_rrset) { + ldns_rr_list_deep_free(zonemd_rr_list); + return LDNS_STATUS_MEM_ERR; + } + zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD; + zonemd_rrset->next = *rrset_ref; + *rrset_ref = zonemd_rrset; + } + if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list))) + st = rr_list2dnssec_rrs( zonemd_rrsigs + , &zonemd_rrset->signatures, new_rrs); + if (!st) + st = rr_list2dnssec_rrs( zonemd_rr_list + , &zonemd_rrset->rrs, new_rrs); + ldns_rr_list_deep_free(zonemd_rr_list); + ldns_rr_list_deep_free(zonemd_rrsigs); + return st; +} + +#endif /* HAVE_SSL */ + diff --git a/contrib/ldns/drill/chasetrace.c b/contrib/ldns/drill/chasetrace.c index dd495db5a9..3bd59563c5 100644 --- a/contrib/ldns/drill/chasetrace.c +++ b/contrib/ldns/drill/chasetrace.c @@ -171,7 +171,7 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, } /* transfer some properties of local_res to res, - * because they were given on the commandline */ + * because they were given on the command line */ ldns_resolver_set_ip6(res, ldns_resolver_ip6(local_res)); ldns_resolver_set_port(res, diff --git a/contrib/ldns/drill/dnssec.c b/contrib/ldns/drill/dnssec.c index d41704925d..687cfe55a5 100644 --- a/contrib/ldns/drill/dnssec.c +++ b/contrib/ldns/drill/dnssec.c @@ -180,7 +180,20 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis ldns_rr_list *nsecs; ldns_status result; - + const ldns_rr_descriptor *descriptor; + + if (!pkt) { + descriptor = ldns_rr_descript(type); + + printf("NETWORk ERROR! Cannot verify denial for: "); + ldns_rdf_print(stdout, name); + printf(" type "); + if (descriptor && descriptor->_name) + printf("%s", descriptor->_name); + else + printf("TYPE%u", type); + return LDNS_STATUS_CRYPTO_NO_RRSIG; + } if (verbosity >= 5) { printf("VERIFY DENIAL FROM:\n"); ldns_pkt_print(stdout, pkt); diff --git a/contrib/ldns/drill/drill.c b/contrib/ldns/drill/drill.c index 6efd29a5ca..611c81f3a8 100644 --- a/contrib/ldns/drill/drill.c +++ b/contrib/ldns/drill/drill.c @@ -59,7 +59,7 @@ usage(FILE *stream, const char *progname) fprintf(stream, "\t-6\t\tstay on ip6\n"); fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n"); fprintf(stream, "\t-b \tuse as the buffer size (defaults to 512 b)\n"); - fprintf(stream, "\t-c \tuse file for rescursive nameserver configuration" + fprintf(stream, "\t-c \tuse file for recursive nameserver configuration" "\n\t\t\t(/etc/resolv.conf)\n"); fprintf(stream, "\t-k \tspecify a file that contains a trusted DNSSEC key [**]\n"); fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n"); @@ -173,6 +173,8 @@ main(int argc, char *argv[]) int r; WSADATA wsa_data; #endif + ldns_output_format_storage fmt_storage; + ldns_output_format* fmt = ldns_output_format_init(&fmt_storage); int_type = -1; serv = NULL; type = 0; int_clas = -1; name = NULL; clas = 0; @@ -201,6 +203,7 @@ main(int argc, char *argv[]) qusevc = false; qrandom = true; key_verified = NULL; + ldns_edns_option_list* edns_list = NULL; ldns_init_random(NULL, 0); @@ -247,6 +250,7 @@ main(int argc, char *argv[]) verbosity = atoi(optarg); break; case 'Q': + fmt->flags |= LDNS_FMT_SHORT; verbosity = -1; break; case 'f': @@ -454,6 +458,31 @@ main(int argc, char *argv[]) serv = argv[i] + 1; continue; } + /* if ^+ then it's an EDNS option */ + if (argv[i][0] == '+') { + if (!strcmp(argv[i]+1, "nsid")) { + ldns_edns_option *edns; + edns_list = ldns_edns_option_list_new(); + + /* create NSID EDNS*/ + edns = ldns_edns_new_from_data(LDNS_EDNS_NSID, 0, NULL); + + if (edns_list == NULL || edns == NULL) { + error("EDNS option could not be allocated"); + break; + } + + if (!(ldns_edns_option_list_push(edns_list, edns))) { + error("EDNS option NSID could not be attached"); + break; + } + continue; + } + else { + error("Unsupported argument after '+'"); + break; + } + } /* if has a dot, it's a name */ if (strchr(argv[i], '.')) { name = argv[i]; @@ -793,7 +822,7 @@ main(int argc, char *argv[]) } status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags); if(status != LDNS_STATUS_OK) { - error("%s", "making query: %s", + error("%s", "making query: %s", ldns_get_errorstr_by_id(status)); } dump_hex(qpkt, query_file); @@ -864,9 +893,22 @@ main(int argc, char *argv[]) } else { /* create a packet and set the RD flag on it */ pkt = NULL; - status = ldns_resolver_query_status( - &pkt, res, qname, - type, clas, qflags); + + status = ldns_resolver_prepare_query_pkt(&qpkt, + res, qname, type, clas, qflags); + if(status != LDNS_STATUS_OK) { + error("%s", "making query: %s", + ldns_get_errorstr_by_id(status)); + } + + if (edns_list) { + /* attach the structed EDNS options */ + ldns_pkt_set_edns_option_list(qpkt, edns_list); + } + + status = ldns_resolver_send_pkt(&pkt, res, qpkt); + ldns_pkt_free(qpkt); + if (status != LDNS_STATUS_OK) { error("error sending query: %s" , ldns_get_errorstr_by_id( @@ -875,12 +917,13 @@ main(int argc, char *argv[]) } } - if (!pkt) { + /* now handling the response message/packet */ + if (!pkt) { mesg("No packet received"); result = EXIT_FAILURE; } else { + ldns_pkt_print_fmt(stdout, fmt, pkt); if (verbosity != -1) { - ldns_pkt_print(stdout, pkt); if (ldns_pkt_tc(pkt)) { fprintf(stdout, "\n;; WARNING: The answer packet was truncated; you might want to\n"); @@ -994,9 +1037,17 @@ main(int argc, char *argv[]) xfree(tsig_algorithm); #ifdef HAVE_SSL - CRYPTO_cleanup_all_ex_data(); - ERR_free_strings(); - EVP_cleanup(); +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(HAVE_LIBRESSL) +#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA + CRYPTO_cleanup_all_ex_data (); +#endif +#ifdef HAVE_ERR_FREE_STRINGS + ERR_free_strings (); +#endif +#ifdef HAVE_EVP_CLEANUP + EVP_cleanup (); +#endif +#endif #endif #ifdef USE_WINSOCK WSACleanup(); diff --git a/contrib/ldns/drill/securetrace.c b/contrib/ldns/drill/securetrace.c index 6967265de5..90014b4e30 100644 --- a/contrib/ldns/drill/securetrace.c +++ b/contrib/ldns/drill/securetrace.c @@ -137,7 +137,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_list *correct_key_list; ldns_rr_list *trusted_ds_rrs; bool new_keys_trusted = false; - ldns_rr_list *current_correct_keys; + ldns_rr_list *current_correct_keys = NULL; ldns_rr_list *dataset; ldns_rr_list *nsec_rrs = NULL; @@ -520,8 +520,8 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, labels[i-1]); printf(", but valid CNAME"); } else { - printf("[B] Unable to verify de" - "nial of existence for "); + printf(BOGUS " Unable to verify " + "denial of existence for "); ldns_rdf_print(stdout, labels[i-1]); printf(", because of BOGUS CNAME"); @@ -644,7 +644,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, printf(";; No DS for "); ldns_rdf_print(stdout, labels[i - 1]); } else { - printf("[B] Unable to verify denial of existence for "); + printf(BOGUS " Unable to verify denial of existence for "); ldns_rdf_print(stdout, labels[i - 1]); printf(" DS: %s\n", ldns_get_errorstr_by_id(status)); } @@ -748,7 +748,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, } printf("\n"); } else { - printf("[B] Unable to verify denial of existence for "); + printf(BOGUS " Unable to verify denial of existence for "); ldns_rdf_print(stdout, name); printf(" type "); if (descriptor && descriptor->_name) { @@ -774,7 +774,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_list_deep_free(ds_sig_list); ds_sig_list = NULL; } - printf(";;" SELF " self sig OK; " BOGUS " bogus; " TRUST " trusted\n"); + printf(";;" SELF " self sig OK; " BOGUS " bogus; " TRUST " trusted; " UNSIGNED " unsigned\n"); /* verbose mode? printf("Trusted keys:\n"); ldns_rr_list_print(stdout, trusted_keys); diff --git a/contrib/ldns/duration.c b/contrib/ldns/duration.c index 0a8d79b519..abff9a074f 100644 --- a/contrib/ldns/duration.c +++ b/contrib/ldns/duration.c @@ -190,121 +190,51 @@ ldns_duration_create_from_string(const char* str) /** - * Get the number of digits in a number. - * + * Helper func for ldns_duration2string below. If t > 0, + * scan print t and c on buf, forwarding buf. Return 0 on success. */ -static size_t -digits_in_number(time_t duration) +static inline int dur_scan_print(char **buf, char *eob, char c, time_t t) { - unsigned int i = (unsigned int) duration; - size_t n = 1; - - while (i >= 100000000) { - n += 8; - i /= 100000000; + if (t > 0) { + int r = snprintf(*buf, eob - *buf, "%u%c", (unsigned)t, c); + if (r < 0 || (*buf += r) >= eob) + return -1; } - if (i >= 10000) { n += 4; i /= 10000; } - if (i >= 100 ) { n += 2; i /= 100; } - if (i >= 10 ) { n += 1; } - return n; + return 0; } - /** * Convert a duration to a string. * */ char* -ldns_duration2string(const ldns_duration_type* duration) +ldns_duration2string(const ldns_duration_type* d) { - char* str = NULL; - size_t count = 2; - int T = 0; - char num[sizeof(unsigned int) + 2]; - - if (!duration) { - return NULL; - } - - if (duration->years > 0) { - count = count + 1 + digits_in_number(duration->years); - } - if (duration->months > 0) { - count = count + 1 + digits_in_number(duration->months); - } - if (duration->weeks > 0) { - count = count + 1 + digits_in_number(duration->weeks); - } - if (duration->days > 0) { - count = count + 1 + digits_in_number(duration->days); - } - if (duration->hours > 0) { - count = count + 1 + digits_in_number(duration->hours); - T = 1; - } - if (duration->minutes > 0) { - count = count + 1 + digits_in_number(duration->minutes); - T = 1; - } - if (duration->seconds > 0) { - count = count + 1 + digits_in_number(duration->seconds); - T = 1; - } - if (T) { - count++; - } - - if (!(str = (char*) calloc(count, sizeof(char)))) - return NULL; - str[0] = 'P'; - str[1] = '\0'; - - if (duration->years > 0) { - count = digits_in_number(duration->years); - assert(count <= sizeof(num) - 2); - snprintf(num, count+2, "%uY", (unsigned int) duration->years); - str = strncat(str, num, count+2); - } - if (duration->months > 0) { - count = digits_in_number(duration->months); - assert(count <= sizeof(num) - 2); - snprintf(num, count+2, "%uM", (unsigned int) duration->months); - str = strncat(str, num, count+2); - } - if (duration->weeks > 0) { - count = digits_in_number(duration->weeks); - assert(count <= sizeof(num) - 2); - snprintf(num, count+2, "%uW", (unsigned int) duration->weeks); - str = strncat(str, num, count+2); - } - if (duration->days > 0) { - count = digits_in_number(duration->days); - assert(count <= sizeof(num) - 2); - snprintf(num, count+2, "%uD", (unsigned int) duration->days); - str = strncat(str, num, count+2); - } - if (T) { - str = strcat(str, "T"); - } - if (duration->hours > 0) { - count = digits_in_number(duration->hours); - assert(count <= sizeof(num) - 2); - snprintf(num, count+2, "%uH", (unsigned int) duration->hours); - str = strncat(str, num, count+2); - } - if (duration->minutes > 0) { - count = digits_in_number(duration->minutes); - assert(count <= sizeof(num) - 2); - snprintf(num, count+2, "%uM", (unsigned int) duration->minutes); - str = strncat(str, num, count+2); - } - if (duration->seconds > 0) { - count = digits_in_number(duration->seconds); - assert(count <= sizeof(num) - 2); - snprintf(num, count+2, "%uS", (unsigned int) duration->seconds); - str = strncat(str, num, count+2); - } - return str; + /* Max string size should be 7 * 40 + 3 on a 127 bits machine + * So 300 (< 273) is more than enough. + */ + char buf[300] = "P0D", *eob = buf + sizeof(buf), *p = buf + 1; + + if (!d) + return NULL; + + if (dur_scan_print(&p, eob, 'Y', d->years) + || dur_scan_print(&p, eob, 'M', d->months) + || dur_scan_print(&p, eob, 'W', d->weeks) + || dur_scan_print(&p, eob, 'D', d->days)) + return NULL; + + if (d->hours || d->minutes || d->seconds) { + if (p > (eob - 2)) + return NULL; /* Error; no space left on buf for 'T' */ + + *p++ = 'T'; *p = 0; + if (dur_scan_print(&p, eob, 'H', d->hours) + || dur_scan_print(&p, eob, 'M', d->minutes) + || dur_scan_print(&p, eob, 'S', d->seconds)) + return NULL; + } + return strdup(buf); } diff --git a/contrib/ldns/edns.c b/contrib/ldns/edns.c new file mode 100644 index 0000000000..3d002d67ed --- /dev/null +++ b/contrib/ldns/edns.c @@ -0,0 +1,436 @@ +/* + * edns.c + * + * edns implementation + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2022 + * + * See the file LICENSE for the license + */ + +#include + +#define LDNS_OPTIONLIST_INIT 8 + +/* + * Access functions + * functions to get and set type checking + */ + +/* read */ +size_t +ldns_edns_get_size(const ldns_edns_option *edns) +{ + assert(edns != NULL); + return edns->_size; +} + +ldns_edns_option_code +ldns_edns_get_code(const ldns_edns_option *edns) +{ + assert(edns != NULL); + return edns->_code; +} + +uint8_t * +ldns_edns_get_data(const ldns_edns_option *edns) +{ + assert(edns != NULL); + return edns->_data; +} + +ldns_buffer * +ldns_edns_get_wireformat_buffer(const ldns_edns_option *edns) +{ + uint16_t option; + size_t size; + uint8_t* data; + ldns_buffer* buffer; + + if (edns == NULL) { + return NULL; + } + + option = ldns_edns_get_code(edns); + size = ldns_edns_get_size(edns); + data = ldns_edns_get_data(edns); + + buffer = ldns_buffer_new(size + 4); + + if (buffer == NULL) { + return NULL; + } + + ldns_buffer_write_u16(buffer, option); + ldns_buffer_write_u16(buffer, size); + ldns_buffer_write(buffer, data, size); + + ldns_buffer_flip(buffer); + + return buffer; +} + +/* write */ +void +ldns_edns_set_size(ldns_edns_option *edns, size_t size) +{ + assert(edns != NULL); + edns->_size = size; +} + +void +ldns_edns_set_code(ldns_edns_option *edns, ldns_edns_option_code code) +{ + assert(edns != NULL); + edns->_code = code; +} + +void +ldns_edns_set_data(ldns_edns_option *edns, void *data) +{ + /* only copy the pointer */ + assert(edns != NULL); + edns->_data = data; +} + +/* note: data must be allocated memory */ +ldns_edns_option * +ldns_edns_new(ldns_edns_option_code code, size_t size, void *data) +{ + ldns_edns_option *edns; + edns = LDNS_MALLOC(ldns_edns_option); + if (!edns) { + return NULL; + } + ldns_edns_set_code(edns, code); + ldns_edns_set_size(edns, size); + ldns_edns_set_data(edns, data); + + return edns; +} + +ldns_edns_option * +ldns_edns_new_from_data(ldns_edns_option_code code, size_t size, const void *data) +{ + ldns_edns_option *edns; + edns = LDNS_MALLOC(ldns_edns_option); + if (!edns) { + return NULL; + } + edns->_data = LDNS_XMALLOC(uint8_t, size); + if (!edns->_data) { + LDNS_FREE(edns); + return NULL; + } + + /* set the values */ + ldns_edns_set_code(edns, code); + ldns_edns_set_size(edns, size); + memcpy(edns->_data, data, size); + + return edns; +} + +ldns_edns_option * +ldns_edns_clone(ldns_edns_option *edns) +{ + ldns_edns_option *new_option; + + assert(edns != NULL); + + new_option = ldns_edns_new_from_data(ldns_edns_get_code(edns), + ldns_edns_get_size(edns), + ldns_edns_get_data(edns)); + + return new_option; +} + +void +ldns_edns_deep_free(ldns_edns_option *edns) +{ + if (edns) { + if (edns->_data) { + LDNS_FREE(edns->_data); + } + LDNS_FREE(edns); + } +} + +void +ldns_edns_free(ldns_edns_option *edns) +{ + if (edns) { + LDNS_FREE(edns); + } +} + +ldns_edns_option_list* +ldns_edns_option_list_new() +{ + ldns_edns_option_list *option_list = LDNS_MALLOC(ldns_edns_option_list); + if(!option_list) { + return NULL; + } + + option_list->_option_count = 0; + option_list->_option_capacity = 0; + option_list->_options_size = 0; + option_list->_options = NULL; + return option_list; +} + +ldns_edns_option_list * +ldns_edns_option_list_clone(ldns_edns_option_list *old_list) +{ + size_t i; + ldns_edns_option_list *new_list; + + if (!old_list) { + return NULL; + } + + new_list = ldns_edns_option_list_new(); + if (!new_list) { + return NULL; + } + + if (old_list->_option_count == 0) { + return new_list; + } + + /* adding options also updates the total options size */ + for (i = 0; i < old_list->_option_count; i++) { + ldns_edns_option *option = ldns_edns_clone(ldns_edns_option_list_get_option(old_list, i)); + if (!ldns_edns_option_list_push(new_list, option)) { + ldns_edns_deep_free(option); + ldns_edns_option_list_deep_free(new_list); + return NULL; + } + } + return new_list; +} + +void +ldns_edns_option_list_free(ldns_edns_option_list *option_list) +{ + if (option_list) { + LDNS_FREE(option_list->_options); + LDNS_FREE(option_list); + } +} + +void +ldns_edns_option_list_deep_free(ldns_edns_option_list *option_list) +{ + size_t i; + + if (option_list) { + for (i=0; i < ldns_edns_option_list_get_count(option_list); i++) { + ldns_edns_deep_free(ldns_edns_option_list_get_option(option_list, i)); + } + ldns_edns_option_list_free(option_list); + } +} + +size_t +ldns_edns_option_list_get_count(const ldns_edns_option_list *option_list) +{ + if (option_list) { + return option_list->_option_count; + } else { + return 0; + } +} + +ldns_edns_option * +ldns_edns_option_list_get_option(const ldns_edns_option_list *option_list, size_t index) +{ + if (option_list && index < ldns_edns_option_list_get_count(option_list)) { + assert(option_list->_options[index]); + return option_list->_options[index]; + } else { + return NULL; + } +} + +size_t +ldns_edns_option_list_get_options_size(const ldns_edns_option_list *option_list) +{ + if (option_list) { + return option_list->_options_size; + } else { + return 0; + } +} + + +ldns_edns_option * +ldns_edns_option_list_set_option(ldns_edns_option_list *option_list, + ldns_edns_option *option, size_t index) +{ + ldns_edns_option* old; + + assert(option_list != NULL); + + if (index > ldns_edns_option_list_get_count(option_list)) { + return NULL; + } + + if (option == NULL) { + return NULL; + } + + old = ldns_edns_option_list_get_option(option_list, index); + + /* shrink the total EDNS size if the old EDNS option exists */ + if (old != NULL) { + option_list->_options_size -= (ldns_edns_get_size(old) + 4); + } + + option_list->_options_size += (ldns_edns_get_size(option) + 4); + + option_list->_options[index] = option; + return old; +} + +bool +ldns_edns_option_list_push(ldns_edns_option_list *option_list, + ldns_edns_option *option) +{ + size_t cap; + size_t option_count; + + assert(option_list != NULL); + + if (option == NULL) { + return false; + } + + cap = option_list->_option_capacity; + option_count = ldns_edns_option_list_get_count(option_list); + + /* verify we need to grow the array to fit the new option */ + if (option_count+1 > cap) { + ldns_edns_option **new_list; + + /* initialize the capacity if needed, otherwise grow by doubling */ + if (cap == 0) { + cap = LDNS_OPTIONLIST_INIT; /* initial list size */ + } else { + cap *= 2; + } + + new_list = LDNS_XREALLOC(option_list->_options, + ldns_edns_option *, cap); + + if (!new_list) { + return false; + } + + option_list->_options = new_list; + option_list->_option_capacity = cap; + } + + /* add the new option */ + ldns_edns_option_list_set_option(option_list, option, + option_list->_option_count); + option_list->_option_count += 1; + + return true; +} + +ldns_edns_option * +ldns_edns_option_list_pop(ldns_edns_option_list *option_list) +{ + ldns_edns_option* pop; + size_t count; + size_t cap; + + assert(option_list != NULL); + + cap = option_list->_option_capacity; + count = ldns_edns_option_list_get_count(option_list); + + if (count == 0) { + return NULL; + } + /* get the last option from the list */ + pop = ldns_edns_option_list_get_option(option_list, count-1); + + /* shrink the array */ + if (cap > LDNS_OPTIONLIST_INIT && count-1 <= cap/2) { + ldns_edns_option **new_list; + + cap /= 2; + + new_list = LDNS_XREALLOC(option_list->_options, + ldns_edns_option *, cap); + if (new_list) { + option_list->_options = new_list; + } + /* if the realloc fails, the capacity for the list remains unchanged */ + } + + /* shrink the total EDNS size of the options if the popped EDNS option exists */ + if (pop != NULL) { + option_list->_options_size -= (ldns_edns_get_size(pop) + 4); + } + + option_list->_option_count = count - 1; + + return pop; +} + +ldns_buffer * +ldns_edns_option_list2wireformat_buffer(const ldns_edns_option_list *option_list) +{ + size_t i, list_size, options_size, option, size; + ldns_buffer* buffer; + ldns_edns_option *edns; + uint8_t* data = NULL; + + if (!option_list) { + return NULL; + } + + /* get the number of EDNS options in the list*/ + list_size = ldns_edns_option_list_get_count(option_list); + + /* create buffer the size of the total EDNS wireformat options */ + options_size = ldns_edns_option_list_get_options_size(option_list); + buffer = ldns_buffer_new(options_size); + + if (!buffer) { + return NULL; + } + + /* write individual serialized EDNS options to final buffer*/ + for (i = 0; i < list_size; i++) { + edns = ldns_edns_option_list_get_option(option_list, i); + + if (edns == NULL) { + /* this shouldn't be possible */ + return NULL; + } + + option = ldns_edns_get_code(edns); + size = ldns_edns_get_size(edns); + data = ldns_edns_get_data(edns); + + /* make sure the option fits */ + if (!(ldns_buffer_available(buffer, size + 4))) { + ldns_buffer_free(buffer); + return NULL; + } + + ldns_buffer_write_u16(buffer, option); + ldns_buffer_write_u16(buffer, size); + ldns_buffer_write(buffer, data, size); + } + + ldns_buffer_flip(buffer); + + return buffer; +} diff --git a/contrib/ldns/error.c b/contrib/ldns/error.c index 7943017a90..e3fd121127 100644 --- a/contrib/ldns/error.c +++ b/contrib/ldns/error.c @@ -1,6 +1,6 @@ /* * a error2str function to make sense of all the - * error codes we have laying ardoun + * error codes we have laying around * * a Net::DNS like library for C * LibDNS Team @ NLnet Labs @@ -157,6 +157,33 @@ ldns_lookup_table ldns_error_str[] = { "X509_STORE_CTX_set0_dane() functions within OpenSSL >= 1.1.0 " "to be able to verify the DANE-TA usage type." }, #endif + { LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE, "A ZONEMD with the same " + " and hash algorithm occurred more than once." }, + { LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME, "Unknown ZONEMD " }, + { LDNS_STATUS_ZONEMD_UNKNOWN_HASH, "Unknown ZONEMD hash algorithm" }, + { LDNS_STATUS_ZONEMD_INVALID_SOA, + "Missing or invalid SOA to associate with ZONEMD RR" }, + { LDNS_STATUS_NO_ZONEMD, + "NSEC(3) RRs indicate that a ZONEMD exists, " + "but it is not found in the zone" }, + { LDNS_STATUS_NO_VALID_ZONEMD, + "No ZONEMD matching the zone data was found" }, + { LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR, "Syntax error in a key in " + "the ServiceParam rdata field of SVCB or HTTPS RR" }, + { LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR, "Syntax error in a value in " + "the ServiceParam rdata field of SVCB or HTTPS RR" }, + { LDNS_STATUS_RESERVED_SVCPARAM_KEY, + "key65535 is reserved and MUST NOT be used " + "in the ServiceParam rdata field of SVCB or HTTPS RR" }, + { LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED, + "A value was found for a key that SHOULD not have a value " + "in the ServiceParam rdata field of SVCB or HTTPS RR" }, + { LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE, + "A key was found more than once " + "in the ServiceParam rdata field of SVCB or HTTPS RR" }, + { LDNS_STATUS_INVALID_SVCPARAM_VALUE, + "Invalid wireformat of a value " + "in the ServiceParam rdata field of SVCB or HTTPS RR" }, { 0, NULL } }; diff --git a/contrib/ldns/host2str.c b/contrib/ldns/host2str.c index 3ca23c2017..7282db9ee2 100644 --- a/contrib/ldns/host2str.c +++ b/contrib/ldns/host2str.c @@ -43,6 +43,10 @@ #define INET6_ADDRSTRLEN 46 #endif +/* Internal helper function */ +ldns_edns_option_list* +pkt_edns_data2edns_option_list(const ldns_rdf *edns_data); + /* lookup tables for standard DNS stuff */ /* Taken from RFC 2535, section 7. */ @@ -54,29 +58,28 @@ ldns_lookup_table ldns_algorithms[] = { { LDNS_RSASHA1, "RSASHA1" }, { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" }, { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, -#ifdef USE_SHA2 { LDNS_RSASHA256, "RSASHA256"}, { LDNS_RSASHA512, "RSASHA512"}, -#endif -#ifdef USE_GOST { LDNS_ECC_GOST, "ECC-GOST"}, -#endif -#ifdef USE_ECDSA { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, -#endif -#ifdef USE_ED25519 { LDNS_ED25519, "ED25519"}, -#endif -#ifdef USE_ED448 { LDNS_ED448, "ED448"}, -#endif { LDNS_INDIRECT, "INDIRECT" }, { LDNS_PRIVATEDNS, "PRIVATEDNS" }, { LDNS_PRIVATEOID, "PRIVATEOID" }, { 0, NULL } }; +/* Hashing algorithms used in the DS record */ +ldns_lookup_table ldns_hashes[] = { + {LDNS_SHA1 , "SHA1" }, /* RFC 4034 */ + {LDNS_SHA256 , "SHA256" }, /* RFC 4509 */ + {LDNS_HASH_GOST, "HASH-GOST" }, /* RFC 5933 */ + {LDNS_SHA384 , "SHA384" }, /* RFC 6605 */ + { 0, NULL } +}; + /* Taken from RFC 4398 */ ldns_lookup_table ldns_cert_algorithms[] = { { LDNS_CERT_PKIX, "PKIX" }, @@ -414,7 +417,7 @@ ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf) char date_buf[16]; memset(&tm, 0, sizeof(tm)); - if (ldns_serial_arithmitics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm) + if (ldns_serial_arithmetics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm) && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { ldns_buffer_printf(output, "%s", date_buf); } @@ -709,8 +712,8 @@ ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf) uint32_t longitude; uint32_t latitude; uint32_t altitude; - char northerness; - char easterness; + char latitude_hemisphere; + char longitude_hemisphere; uint32_t h; uint32_t m; double s; @@ -734,10 +737,10 @@ ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf) altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]); if (latitude > equator) { - northerness = 'N'; + latitude_hemisphere = 'N'; latitude = latitude - equator; } else { - northerness = 'S'; + latitude_hemisphere = 'S'; latitude = equator - latitude; } h = latitude / (1000 * 60 * 60); @@ -746,13 +749,13 @@ ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf) latitude = latitude % (1000 * 60); s = (double) latitude / 1000.0; ldns_buffer_printf(output, "%02u %02u %0.3f %c ", - h, m, s, northerness); + h, m, s, latitude_hemisphere); if (longitude > equator) { - easterness = 'E'; + longitude_hemisphere = 'E'; longitude = longitude - equator; } else { - easterness = 'W'; + longitude_hemisphere = 'W'; longitude = equator - longitude; } h = longitude / (1000 * 60 * 60); @@ -761,8 +764,7 @@ ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf) longitude = longitude % (1000 * 60); s = (double) longitude / (1000.0); ldns_buffer_printf(output, "%02u %02u %0.3f %c ", - h, m, s, easterness); - + h, m, s, longitude_hemisphere); s = ((double) altitude) / 100; s -= 100000; @@ -851,6 +853,8 @@ ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf) endservent(); #endif } + /* exit from loop before integer overflow */ + if(current_service == 65535) { break; } } return ldns_buffer_status(output); } @@ -1281,7 +1285,7 @@ ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf) ldns_buffer_printf(output, "%02x", (int) *data); } - ldns_buffer_write_u8(output, (uint8_t) ' '); + ldns_buffer_write_char(output, (uint8_t) ' '); if (ldns_buffer_reserve(output, ldns_b64_ntop_calculate_size(pk_size))) { @@ -1299,7 +1303,7 @@ ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf) return ldns_buffer_status(output); } -/* implementation mimiced from ldns_rdf2buffer_str_ipseckey */ +/* implementation mimicked from ldns_rdf2buffer_str_ipseckey */ ldns_status ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, const ldns_rdf *rdf) { @@ -1386,6 +1390,231 @@ ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, const ldns_rdf *rdf) return ldns_buffer_status(output); } +#ifdef RRTYPE_SVCB_HTTPS +ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key); + +static ldns_status +svcparam_mandatory2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) +{ + if (sz % 2) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + svcparam_key2buffer_str(output, ldns_read_uint16(data)); + for (data += 2, sz -= 2; sz; data += 2, sz -= 2) { + ldns_buffer_write_char(output, ','); + svcparam_key2buffer_str(output, ldns_read_uint16(data)); + } + return ldns_buffer_status(output); +} + +static ldns_status +svcparam_alpn2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) +{ + uint8_t *eod = data + sz, *dp; + bool quote = false; + size_t i; + + for (dp = data; dp < eod && !quote; dp += 1 + *dp) { + if (dp + 1 + *dp > eod) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + for (i = 0; i < *dp; i++) + if (isspace(dp[i + 1])) + break; + quote = i < *dp; + } + if (quote) + ldns_buffer_write_char(output, '"'); + while (data < eod) { + uint8_t *eot = data + 1 + *data; + + if (eot > eod) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + if (eod - data < (int)sz) + ldns_buffer_write_char(output, ','); + + for (data += 1; data < eot; data += 1) { + uint8_t ch = *data; + + if (isprint(ch) || ch == '\t') { + if (ch == '"' || ch == ',' || ch == '\\') + ldns_buffer_write_char(output, '\\'); + ldns_buffer_write_char(output, ch); + } else + ldns_buffer_printf(output, "\\%03u" + , (unsigned)ch); + } + } + if (quote) + ldns_buffer_write_char(output, '"'); + return ldns_buffer_status(output); +} + +static ldns_status +svcparam_port2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) +{ + if (sz != 2) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + ldns_buffer_printf(output, "%d", (int)ldns_read_uint16(data)); + return ldns_buffer_status(output); +} + +static ldns_status +svcparam_ipv4hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) +{ + char str[INET_ADDRSTRLEN]; + + if (sz % 4 || !inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN)) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + ldns_buffer_write_chars(output, str); + + for (data += 4, sz -= 4; sz ; data += 4, sz -= 4 ) { + ldns_buffer_write_char(output, ','); + if (!inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN)) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + ldns_buffer_write_chars(output, str); + } + return ldns_buffer_status(output); +} + +static ldns_status +svcparam_ech2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) +{ + size_t str_sz = ldns_b64_ntop_calculate_size(sz); + int written; + + if (!ldns_buffer_reserve(output, str_sz)) + return LDNS_STATUS_MEM_ERR; + + written = ldns_b64_ntop( data, sz + , (char *)ldns_buffer_current(output), str_sz); + if (written > 0) + ldns_buffer_skip(output, written); + else + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + return ldns_buffer_status(output); +} + +static ldns_status +svcparam_ipv6hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) +{ + char str[INET6_ADDRSTRLEN]; + + if (sz % 16 || !inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN)) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + ldns_buffer_write_chars(output, str); + + for (data += 16, sz -= 16; sz ; data += 16, sz -= 16) { + ldns_buffer_write_char(output, ','); + if (!inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN)) + return LDNS_STATUS_INVALID_SVCPARAM_VALUE; + + ldns_buffer_write_chars(output, str); + } + return ldns_buffer_status(output); +} + +static ldns_status +svcparam_value2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) +{ + uint8_t *eod = data + sz, *dp; + bool quote = false; + + for (dp = data; dp < eod && !isspace(*dp); dp++) + ; /* pass */ + + if ((quote = dp < eod)) + ldns_buffer_write_char(output, '"'); + + for (dp = data; dp < eod; dp++) { + uint8_t ch = *dp; + + if (isprint(ch) || ch == '\t') { + if (ch == '"' || ch == '\\') + ldns_buffer_write_char(output, '\\'); + ldns_buffer_write_char(output, ch); + } else + ldns_buffer_printf(output, "\\%03u", (unsigned)ch); + } + if (quote) + ldns_buffer_write_char(output, '"'); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint8_t *data, *dp, *next_dp = NULL; + size_t sz; + ldns_status st; + + if (!output) + return LDNS_STATUS_NULL; + + if (!rdf || !(data = ldns_rdf_data(rdf)) || !(sz = ldns_rdf_size(rdf))) + /* No svcparams is just fine. Just nothing to print. */ + return LDNS_STATUS_OK; + + for (dp = data; dp + 4 <= data + sz; dp = next_dp) { + ldns_svcparam_key key = ldns_read_uint16(dp); + uint16_t val_sz = ldns_read_uint16(dp + 2); + + if ((next_dp = dp + 4 + val_sz) > data + sz) + return LDNS_STATUS_RDATA_OVERFLOW; + + if (dp > data) + ldns_buffer_write_char(output, ' '); + + if ((st = svcparam_key2buffer_str(output, key))) + return st; + + if (val_sz == 0) + continue; + dp += 4; + ldns_buffer_write_char(output, '='); + switch (key) { + case LDNS_SVCPARAM_KEY_MANDATORY: + st = svcparam_mandatory2buffer_str(output, val_sz, dp); + break; + case LDNS_SVCPARAM_KEY_ALPN: + st = svcparam_alpn2buffer_str(output, val_sz, dp); + break; + case LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN: + return LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED; + case LDNS_SVCPARAM_KEY_PORT: + st = svcparam_port2buffer_str(output, val_sz, dp); + break; + case LDNS_SVCPARAM_KEY_IPV4HINT: + st = svcparam_ipv4hint2buffer_str(output, val_sz, dp); + break; + case LDNS_SVCPARAM_KEY_ECH: + st = svcparam_ech2buffer_str(output, val_sz, dp); + break; + case LDNS_SVCPARAM_KEY_IPV6HINT: + st = svcparam_ipv6hint2buffer_str(output, val_sz, dp); + break; + default: + st = svcparam_value2buffer_str(output, val_sz, dp); + break; + } + if (st) + return st; + } + return ldns_buffer_status(output); +} +#else /* #ifdef RRTYPE_SVCB_HTTPS */ +ldns_status +ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf) +{ + (void)output; (void)rdf; + return LDNS_STATUS_NOT_IMPL; +} +#endif /* #ifdef RRTYPE_SVCB_HTTPS */ static ldns_status ldns_rdf2buffer_str_fmt(ldns_buffer *buffer, @@ -1505,6 +1734,9 @@ ldns_rdf2buffer_str_fmt(ldns_buffer *buffer, case LDNS_RDF_TYPE_AMTRELAY: res = ldns_rdf2buffer_str_amtrelay(buffer, rdf); break; + case LDNS_RDF_TYPE_SVCPARAMS: + res = ldns_rdf2buffer_str_svcparams(buffer, rdf); + break; } } else { /** This will write mangled RRs */ @@ -1584,45 +1816,50 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output, fmt_st = (ldns_output_format_storage*) ldns_output_format_default; } - if (!rr) { - if (LDNS_COMMENT_NULLS & fmt_st->flags) { - ldns_buffer_printf(output, "; (null)\n"); + if (!(fmt_st->flags & LDNS_FMT_SHORT)) { + if (!rr) { + if (LDNS_COMMENT_NULLS & fmt_st->flags) { + ldns_buffer_printf(output, "; (null)\n"); + } + return ldns_buffer_status(output); + } + if (ldns_rr_owner(rr)) { + status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr)); + } + if (status != LDNS_STATUS_OK) { + return status; } - return ldns_buffer_status(output); - } - if (ldns_rr_owner(rr)) { - status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr)); - } - if (status != LDNS_STATUS_OK) { - return status; - } - /* TTL should NOT be printed if it is a question */ - if (!ldns_rr_is_question(rr)) { - ldns_buffer_printf(output, "\t%d", ldns_rr_ttl(rr)); - } + /* TTL should NOT be printed if it is a question */ + if (!ldns_rr_is_question(rr)) { + ldns_buffer_printf(output, "\t%u", (unsigned)ldns_rr_ttl(rr)); + } - ldns_buffer_printf(output, "\t"); - status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr)); - if (status != LDNS_STATUS_OK) { - return status; - } - ldns_buffer_printf(output, "\t"); + ldns_buffer_printf(output, "\t"); + status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr)); + if (status != LDNS_STATUS_OK) { + return status; + } + ldns_buffer_printf(output, "\t"); - if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) { - return ldns_rr2buffer_str_rfc3597(output, rr); - } - status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr)); - if (status != LDNS_STATUS_OK) { - return status; - } + if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) { + return ldns_rr2buffer_str_rfc3597(output, rr); + } + status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr)); + if (status != LDNS_STATUS_OK) { + return status; + } - if (ldns_rr_rd_count(rr) > 0) { - ldns_buffer_printf(output, "\t"); - } else if (!ldns_rr_is_question(rr)) { - ldns_buffer_printf(output, "\t\\# 0"); - } + if (ldns_rr_rd_count(rr) > 0) { + ldns_buffer_printf(output, "\t"); + } else if (!ldns_rr_is_question(rr)) { + ldns_buffer_printf(output, "\t\\# 0"); + } + } else if (ldns_rr_rd_count(rr) == 0) { + /* assert(fmt_st->flags & LDNS_FMT_SHORT); */ + ldns_buffer_printf(output, "# 0"); + } for (i = 0; i < ldns_rr_rd_count(rr); i++) { /* ldns_rdf2buffer_str handles NULL input fine! */ if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) && @@ -1758,7 +1995,7 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output, node->data )); } - ldns_rdf_free(key); + ldns_rdf_deep_free(key); } key = ldns_b32_ext2dname( ldns_nsec3_next_owner(rr)); @@ -1776,7 +2013,7 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output, node->data )); } - ldns_rdf_free(key); + ldns_rdf_deep_free(key); } } ldns_buffer_printf(output, "}"); @@ -1869,6 +2106,579 @@ ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt) return ldns_buffer_status(output); } + +/* print EDNS option data in the Dig format: 76 61 6c 69 ... */ +static void +ldns_edns_hex_data2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + size_t j; + for (j = 0; j < len; j++) { + ldns_buffer_printf(output, " %02x", data[j]); + } +} + +static ldns_status +ldns_edns_llq2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + /* LLQ constants */ + const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC", + "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"}; + const unsigned int llq_errors_num = 7; + const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"}; + const unsigned int llq_opcodes_num = 3; + + uint16_t version, llq_opcode, error_code; + uint64_t llq_id; + uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */ + + ldns_buffer_printf(output, "; Long-Lived Query:"); + + /* read the record */ + if(len != 18) { + ldns_buffer_printf(output, " malformed LLQ "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + version = ldns_read_uint16(data); + llq_opcode = ldns_read_uint16(data+2); + error_code = ldns_read_uint16(data+4); + memmove(&llq_id, data+6, sizeof(uint64_t)); + lease_life = ldns_read_uint32(data+14); + + /* print option field entires */ + ldns_buffer_printf(output, "v%d ", (int)version); + + if(llq_opcode < llq_opcodes_num) { + ldns_buffer_printf(output, "%s", llq_opcodes[llq_opcode]); + } else { + ldns_buffer_printf(output, "opcode %d", (int)llq_opcode); + } + + if(error_code < llq_errors_num) + ldns_buffer_printf(output, " %s", llq_errors[error_code]); + else { + ldns_buffer_printf(output, " error %d", (int)error_code); + } + +#ifndef USE_WINSOCK + ldns_buffer_printf(output, " id %llx lease-life %lu", + (unsigned long long)llq_id, (unsigned long)lease_life); +#else + ldns_buffer_printf(output, " id %I64x lease-life %lu", + (unsigned long long)llq_id, (unsigned long)lease_life); +#endif + return ldns_buffer_status(output); +} + + +static ldns_status +ldns_edns_ul2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + uint32_t lease; + + ldns_buffer_printf(output, "; Update Lease:"); + + if(len != 4) { + ldns_buffer_printf(output, " malformed UL "); + ldns_edns_hex_data2buffer_str(output, data, len); + return ldns_buffer_status(output); + } + lease = ldns_read_uint32(data); + ldns_buffer_printf(output, "lease %lu", (unsigned long)lease); + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_nsid2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + size_t i, printed=0; + + ldns_buffer_printf(output, "; NSID:"); + ldns_edns_hex_data2buffer_str(output, data, len); + + /* print the human-readable text string */ + for(i = 0; i < len; i++) { + if(isprint((unsigned char)data[i]) || data[i] == '\t') { + if(!printed) { + ldns_buffer_printf(output, " ("); + printed = 1; + } + ldns_buffer_printf(output, "%c", (char)data[i]); + } + } + if(printed) + ldns_buffer_printf(output, ")"); + return ldns_buffer_status(output); +} + + +static ldns_status +ldns_edns_dau2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + size_t i; + ldns_lookup_table *lt; + + ldns_buffer_printf(output, "; DNSSEC Algorithm Understood (DAU):"); + + for(i = 0; i name) { + ldns_buffer_printf(output, " %s", lt->name); + } else { + ldns_buffer_printf(output, " ALG%u", data[i]); + } + } + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_dhu2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + size_t i; + ldns_lookup_table *lt; + + ldns_buffer_printf(output, "; DS Hash Understood (DHU):"); + + for(i = 0; i < len; i++) { + lt = ldns_lookup_by_id(ldns_hashes, data[i]); + if (lt && lt->name) { + ldns_buffer_printf(output, " %s", lt->name); + } else { + ldns_buffer_printf(output, " ALG%u", data[i]); + } + } + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_d3u2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + size_t i; + + ldns_buffer_printf(output, "; NSEC3 Hash Understood (N3U):"); + + for(i=0; i 4) { + ldns_buffer_printf(output, "trailingdata:"); + ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4); + ldns_buffer_printf(output, " "); + len = 4+4; + } + memmove(ip4, data+4, len-4); + if(!inet_ntop(AF_INET, ip4, buf, (socklen_t) sizeof(buf))) { + ldns_buffer_printf(output, "ip4ntoperror "); + ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4); + } else { + ldns_buffer_printf(output, "%s", buf); + } + } else if(family == 2) { + /* IPv6 */ + char buf[64]; + uint8_t ip6[16]; + memset(ip6, 0, sizeof(ip6)); + if(len-4 > 16) { + ldns_buffer_printf(output, "trailingdata:"); + ldns_edns_hex_data2buffer_str(output, data+4+16, len-4-16); + ldns_buffer_printf(output, " "); + len = 4+16; + } + memmove(ip6, data+4, len-4); +#ifdef AF_INET6 + if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t) sizeof(buf))) { + ldns_buffer_printf(output, "ip6ntoperror "); + ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4); + } else { + ldns_buffer_printf(output, "%s", buf); + } +#else + ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4); +#endif + } else { + /* unknown */ + ldns_buffer_printf(output, "family %d ", (int)family); + ldns_edns_hex_data2buffer_str(output, data, len); + } + ldns_buffer_printf(output, "/%d scope /%d", (int)source, (int)scope); + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_expire2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + + ldns_buffer_printf(output, "; EXPIRE:"); + + if (!(len == 0) || len == 4) { + ldns_buffer_printf(output, "malformed expire "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + + // TODO can this output be more accurate? + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); +} + + +static ldns_status +ldns_edns_cookie2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + ldns_buffer_printf(output, "; COOKIE:"); + + /* the size of an EDNS cookie is restricted by RFC 7873 */ + if (!(len == 8 || (len >= 16 && len < 40))) { + ldns_buffer_printf(output, "malformed cookie "); + ldns_edns_hex_data2buffer_str(output, data, len); + } + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_keepalive2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + uint16_t timeout; + + ldns_buffer_printf(output, "; KEEPALIVE:"); + + if(!(len == 0 || len == 2)) { + ldns_buffer_printf(output, "malformed keepalive "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + + if(len == 0) { + ldns_buffer_printf(output, "no timeout value (only valid for client option)"); + } else { + timeout = ldns_read_uint16(data); + ldns_buffer_printf(output, "timeout value in units of 100ms %u", (int)timeout); + } + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_padding2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + ldns_buffer_printf(output, "; PADDING: "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_chain2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + ldns_rdf** temp = NULL; + + ldns_buffer_printf(output, "; CHAIN: "); + + if (ldns_str2rdf_dname(temp, (char*) data) != LDNS_STATUS_OK) { + ldns_buffer_printf(output, "malformed chain "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + + ldns_characters2buffer_str(output, len, data); + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_key_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + size_t i; + + ldns_buffer_printf(output, "; KEY TAG: "); + + if(len < 2 || len % 2 != 0) { + ldns_buffer_printf(output, "malformed key tag "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + + for (i = 0; i < len; i += 2) { + uint16_t tag = ldns_read_uint16(data); + + ldns_buffer_printf(output, " %hu", tag); + } + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_ede2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + size_t i; + uint16_t ede; + ldns_buffer_printf(output, "; EDE:"); + + if(len < 2) { + ldns_buffer_printf(output, "malformed ede "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + + ede = ldns_read_uint16(data); + + switch (ede) { + case LDNS_EDE_OTHER: + ldns_buffer_printf(output, " 0 (Other): "); + break; + case LDNS_EDE_UNSUPPORTED_DNSKEY_ALG: + ldns_buffer_printf(output, " 1 (Unsupported DNSKEY Algorithm)"); + break; + case LDNS_EDE_UNSUPPORTED_DS_DIGEST: + ldns_buffer_printf(output, " 2 (Unsupported DS Digest type)"); + break; + case LDNS_EDE_STALE_ANSWER: + ldns_buffer_printf(output, " 3 (Stale Answer)"); + break; + case LDNS_EDE_FORGED_ANSWER: + ldns_buffer_printf(output, " 4 (Forged Answer)"); + break; + case LDNS_EDE_DNSSEC_INDETERMINATE: + ldns_buffer_printf(output, " 5 (DNSSEC Indeterminate)"); + break; + case LDNS_EDE_DNSSEC_BOGUS: + ldns_buffer_printf(output, " 6 (DNSSEC Bogus)"); + break; + case LDNS_EDE_SIGNATURE_EXPIRED: + ldns_buffer_printf(output, " 7 (Signature Expired)"); + break; + case LDNS_EDE_SIGNATURE_NOT_YET_VALID: + ldns_buffer_printf(output, " 8 (Signature Not Yet Valid)"); + break; + case LDNS_EDE_DNSKEY_MISSING: + ldns_buffer_printf(output, " 9 (DNSKEY Missing)"); + break; + case LDNS_EDE_RRSIGS_MISSING: + ldns_buffer_printf(output, " 10 (RRSIGs Missing)"); + break; + case LDNS_EDE_NO_ZONE_KEY_BIT_SET: + ldns_buffer_printf(output, " 11 (No Zone Key Bit Set)"); + break; + case LDNS_EDE_NSEC_MISSING: + ldns_buffer_printf(output, " 12 (NSEC Missing)"); + break; + case LDNS_EDE_CACHED_ERROR: + ldns_buffer_printf(output, " 13 (Cached Error)"); + break; + case LDNS_EDE_NOT_READY: + ldns_buffer_printf(output, " 14 (Not Ready)"); + break; + case LDNS_EDE_BLOCKED: + ldns_buffer_printf(output, " 15 (Blocked)"); + break; + case LDNS_EDE_CENSORED: + ldns_buffer_printf(output, " 16 (Censored)"); + break; + case LDNS_EDE_FILTERED: + ldns_buffer_printf(output, " 17 (Filtered)"); + break; + case LDNS_EDE_PROHIBITED: + ldns_buffer_printf(output, " 18 (Prohibited)"); + break; + case LDNS_EDE_STALE_NXDOMAIN_ANSWER: + ldns_buffer_printf(output, " 19 (NXDOMAIN Answer)"); + break; + case LDNS_EDE_NOT_AUTHORITATIVE: + ldns_buffer_printf(output, " 20 (Not Authoritative)"); + break; + case LDNS_EDE_NOT_SUPPORTED: + ldns_buffer_printf(output, " 21 (Not Supported)"); + break; + case LDNS_EDE_NO_REACHABLE_AUTHORITY: + ldns_buffer_printf(output, " 22 (No Reachable Authority)"); + break; + case LDNS_EDE_NETWORK_ERROR: + ldns_buffer_printf(output, " 23 (Network Error)"); + break; + case LDNS_EDE_INVALID_DATA: + ldns_buffer_printf(output, " 24 (Invalid Data)"); + break; + case LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID: + ldns_buffer_printf(output, " 25 (Signature Expired Before Valid)"); + break; + case LDNS_EDE_TOO_EARLY: + ldns_buffer_printf(output, " 26 (Too Early)"); + break; + default: + ldns_buffer_printf(output, " %02x", data[0]); + ldns_buffer_printf(output, " %02x", data[1]); + break; + } + + /* skip the EDE code in the output */ + data += 2; + len -= 2; + + if (len > 2) { + /* format the hex bytes */ + ldns_buffer_printf(output, ":"); + for (i = 0; i < len; i++) { + ldns_buffer_printf(output, " %02x", data[i]); + } + + /* format the human-readable string */ + ldns_buffer_printf(output, " ("); + ldns_characters2buffer_str(output, len, data); + ldns_buffer_printf(output, ")"); + } + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_client_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + ldns_buffer_printf(output, "; CLIENT-TAG:"); + + if (len > 2) { + ldns_buffer_printf(output, "malformed client-tag "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); +} + +static ldns_status +ldns_edns_server_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len) +{ + ldns_buffer_printf(output, "; SERVER-TAG:"); + + if (len > 2) { + ldns_buffer_printf(output, "malformed server-tag "); + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); + } + + ldns_edns_hex_data2buffer_str(output, data, len); + + return ldns_buffer_status(output); +} + +ldns_status +ldns_edns_option_list2buffer_str(ldns_buffer *output, ldns_edns_option_list* edns_list) +{ + size_t count = ldns_edns_option_list_get_count(edns_list); + size_t i, size; + uint8_t* data; + + for (i = 0; i < count; i++) { + ldns_edns_option_code code; + ldns_edns_option* edns = ldns_edns_option_list_get_option(edns_list, i); + + if (!edns) { + break; + } + + code = ldns_edns_get_code(edns); + size = ldns_edns_get_size(edns); + data = ldns_edns_get_data(edns); + + switch(code) { + case LDNS_EDNS_LLQ: + ldns_edns_llq2buffer_str(output, data, size); + break; + case LDNS_EDNS_UL: + ldns_edns_ul2buffer_str(output, data, size); + break; + case LDNS_EDNS_NSID: + ldns_edns_nsid2buffer_str(output, data, size); + break; + case LDNS_EDNS_DAU: + ldns_edns_dau2buffer_str(output, data, size); + break; + case LDNS_EDNS_DHU: + ldns_edns_dhu2buffer_str(output, data, size); + break; + case LDNS_EDNS_N3U: + ldns_edns_d3u2buffer_str(output, data, size); + break; + case LDNS_EDNS_CLIENT_SUBNET: + ldns_edns_subnet2buffer_str(output, data, size); + break; + case LDNS_EDNS_EXPIRE: + ldns_edns_expire2buffer_str(output, data, size); + break; + case LDNS_EDNS_COOKIE: + ldns_edns_cookie2buffer_str(output, data, size); + break; + case LDNS_EDNS_KEEPALIVE: + ldns_edns_keepalive2buffer_str(output, data, size); + break; + case LDNS_EDNS_PADDING: + ldns_edns_padding2buffer_str(output, data, size); + break; + case LDNS_EDNS_CHAIN: + ldns_edns_chain2buffer_str(output, data, size); + break; + case LDNS_EDNS_KEY_TAG: + ldns_edns_key_tag2buffer_str(output, data, size); + break; + case LDNS_EDNS_EDE: + ldns_edns_ede2buffer_str(output, data, size); + break; + case LDNS_EDNS_CLIENT_TAG: + ldns_edns_client_tag2buffer_str(output, data, size); + break; + case LDNS_EDNS_SERVER_TAG: + ldns_edns_server_tag2buffer_str(output, data, size); + break; + default: + ldns_buffer_printf(output, "; OPT=%d:", code); + ldns_edns_hex_data2buffer_str(output, data, size); + break; + } + ldns_buffer_printf(output, "\n"); + } + + return ldns_buffer_status(output); +} + + ldns_status ldns_pkt2buffer_str_fmt(ldns_buffer *output, const ldns_output_format *fmt, const ldns_pkt *pkt) @@ -1878,13 +2688,18 @@ ldns_pkt2buffer_str_fmt(ldns_buffer *output, char *tmp; struct timeval time; time_t time_tt; + int short_fmt = fmt && (fmt->flags & LDNS_FMT_SHORT); if (!pkt) { ldns_buffer_printf(output, "null"); return LDNS_STATUS_OK; } - if (ldns_buffer_status_ok(output)) { + if (!ldns_buffer_status_ok(output)) { + return ldns_buffer_status(output); + } + + if (!short_fmt) { status = ldns_pktheader2buffer_str(output, pkt); if (status != LDNS_STATUS_OK) { return status; @@ -1906,15 +2721,16 @@ ldns_pkt2buffer_str_fmt(ldns_buffer *output, ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, ";; ANSWER SECTION:\n"); - for (i = 0; i < ldns_pkt_ancount(pkt); i++) { - status = ldns_rr2buffer_str_fmt(output, fmt, - ldns_rr_list_rr( - ldns_pkt_answer(pkt), i)); - if (status != LDNS_STATUS_OK) { - return status; - } - + } + for (i = 0; i < ldns_pkt_ancount(pkt); i++) { + status = ldns_rr2buffer_str_fmt(output, fmt, + ldns_rr_list_rr( + ldns_pkt_answer(pkt), i)); + if (status != LDNS_STATUS_OK) { + return status; } + } + if (!short_fmt) { ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n"); @@ -1940,7 +2756,7 @@ ldns_pkt2buffer_str_fmt(ldns_buffer *output, } ldns_buffer_printf(output, "\n"); - /* add some futher fields */ + /* add some further fields */ ldns_buffer_printf(output, ";; Query time: %d msec\n", ldns_pkt_querytime(pkt)); if (ldns_pkt_edns(pkt)) { @@ -1959,11 +2775,20 @@ ldns_pkt2buffer_str_fmt(ldns_buffer *output, ldns_buffer_printf(output, " ; udp: %u\n", ldns_pkt_edns_udp_size(pkt)); - if (ldns_pkt_edns_data(pkt)) { - ldns_buffer_printf(output, ";; Data: "); - (void)ldns_rdf2buffer_str(output, - ldns_pkt_edns_data(pkt)); - ldns_buffer_printf(output, "\n"); + if (pkt->_edns_list) + ldns_edns_option_list2buffer_str(output, pkt->_edns_list); + + else if (ldns_pkt_edns_data(pkt)) { + ldns_edns_option_list* edns_list; + /* parse the EDNS data into separate EDNS options + * and add them to the list */ + if ((edns_list = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(pkt)))) { + ldns_edns_option_list2buffer_str(output, edns_list); + ldns_edns_option_list_deep_free(edns_list); + } else { + ldns_buffer_printf(output, ";; Data: "); + (void)ldns_rdf2buffer_str(output, ldns_pkt_edns_data(pkt)); + } } } if (ldns_pkt_tsig(pkt)) { @@ -1984,8 +2809,6 @@ ldns_pkt2buffer_str_fmt(ldns_buffer *output, ldns_buffer_printf(output, ";; MSG SIZE rcvd: %d\n", (int)ldns_pkt_size(pkt)); - } else { - return ldns_buffer_status(output); } return status; } @@ -2133,7 +2956,9 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) unsigned char *bignum; #ifdef HAVE_SSL RSA *rsa; +#ifdef USE_DSA DSA *dsa; +#endif /* USE_DSA */ #endif /* HAVE_SSL */ if (!k) { @@ -2207,7 +3032,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) const BIGNUM *n=NULL, *e=NULL, *d=NULL, *p=NULL, *q=NULL, *dmp1=NULL, *dmq1=NULL, *iqmp=NULL; -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) n = rsa->n; e = rsa->e; d = rsa->d; @@ -2243,6 +3068,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) RSA_free(rsa); break; +#ifdef USE_DSA case LDNS_SIGN_DSA: case LDNS_SIGN_DSA_NSEC3: dsa = ldns_key_dsa_key(k); @@ -2259,7 +3085,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) if(1) { const BIGNUM *p=NULL, *q=NULL, *g=NULL, *priv_key=NULL, *pub_key=NULL; -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) #ifndef S_SPLINT_S p = dsa->p; q = dsa->q; @@ -2283,6 +3109,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) goto error; } break; +#endif /* USE_DSA */ case LDNS_SIGN_ECC_GOST: /* no format defined, use blob */ #if defined(HAVE_SSL) && defined(USE_GOST) @@ -2407,7 +3234,7 @@ ldns_buffer2str(ldns_buffer *buffer) if (!ldns_buffer_reserve(buffer, 1)) { return NULL; } - ldns_buffer_write_u8(buffer, (uint8_t) '\0'); + ldns_buffer_write_char(buffer, (uint8_t) '\0'); if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) { return NULL; } @@ -2430,7 +3257,7 @@ ldns_buffer_export2str(ldns_buffer *buffer) if (! ldns_buffer_reserve(buffer, 1)) { return NULL; } - ldns_buffer_write_u8(buffer, 0); + ldns_buffer_write_char(buffer, 0); /* reallocate memory to the size of the string and export */ ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer)); diff --git a/contrib/ldns/host2wire.c b/contrib/ldns/host2wire.c index a12b6b035e..d153921479 100644 --- a/contrib/ldns/host2wire.c +++ b/contrib/ldns/host2wire.c @@ -374,6 +374,20 @@ compression_node_free(ldns_rbnode_t *node, void *arg) ldns_status ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) +{ + ldns_status status; + ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))ldns_dname_compare); + + status = ldns_pkt2buffer_wire_compress(buffer, packet, compression_data); + + ldns_traverse_postorder(compression_data,compression_node_free,NULL); + ldns_rbtree_free(compression_data); + + return status; +} + +ldns_status +ldns_pkt2buffer_wire_compress(ldns_buffer *buffer, const ldns_pkt *packet, ldns_rbtree_t *compression_data) { ldns_rr_list *rr_list; uint16_t i; @@ -382,8 +396,9 @@ ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) ldns_rr *edns_rr; uint8_t edata[4]; - ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))ldns_dname_compare); - + ldns_buffer *edns_buf = NULL; + ldns_rdf *edns_rdf = NULL; + (void) ldns_hdr2buffer_wire(buffer, packet); rr_list = ldns_pkt_question(packet); @@ -428,11 +443,22 @@ ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet)); ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata)); /* don't forget to add the edns rdata (if any) */ - if (packet->_edns_data) - ldns_rr_push_rdf (edns_rr, packet->_edns_data); + if ((edns_buf = ldns_edns_option_list2wireformat_buffer(packet->_edns_list))) { + edns_rdf = ldns_rdf_new( LDNS_RDF_TYPE_UNKNOWN + , ldns_buffer_limit(edns_buf) + , ldns_buffer_export(edns_buf)); + ldns_buffer_free(edns_buf); + } + if (edns_rdf) + ldns_rr_push_rdf(edns_rr, edns_rdf); + else if (packet->_edns_data) + ldns_rr_push_rdf(edns_rr, packet->_edns_data); (void)ldns_rr2buffer_wire_compress(buffer, edns_rr, LDNS_SECTION_ADDITIONAL, compression_data); - /* take the edns rdata back out of the rr before we free rr */ - if (packet->_edns_data) + /* if the rdata of the OPT came from packet->_edns_data + * we need to take it back out of the edns_rr before we free it + * so packet->_edns_data doesn't get freed + */ + if (!edns_rdf && packet->_edns_data) (void)ldns_rr_pop_rdf (edns_rr); ldns_rr_free(edns_rr); } @@ -443,9 +469,6 @@ ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL, compression_data); } - ldns_traverse_postorder(compression_data,compression_node_free,NULL); - ldns_rbtree_free(compression_data); - return LDNS_STATUS_OK; } diff --git a/contrib/ldns/keys.c b/contrib/ldns/keys.c index 016f973111..78bea9721c 100644 --- a/contrib/ldns/keys.c +++ b/contrib/ldns/keys.c @@ -15,6 +15,7 @@ #include #ifdef HAVE_SSL +#include #include #include #include @@ -83,7 +84,7 @@ ldns_key_new(void) if (!newkey) { return NULL; } else { - /* some defaults - not sure wether to do this */ + /* some defaults - not sure whether to do this */ ldns_key_set_use(newkey, true); ldns_key_set_flags(newkey, LDNS_KEY_ZONE_KEY); ldns_key_set_origttl(newkey, 0); @@ -775,7 +776,7 @@ ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr) } /* I could use functions again, but that seems an overkill, - * allthough this also looks tedious + * although this also looks tedious */ /* Modules, rsa->n */ @@ -860,7 +861,7 @@ ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr) } #endif /* splint */ -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) # ifndef S_SPLINT_S rsa->n = n; rsa->e = e; @@ -904,6 +905,7 @@ ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr) return NULL; } +#ifdef USE_DSA DSA * ldns_key_new_frm_fp_dsa(FILE *f) { @@ -980,7 +982,7 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr)) } #endif /* splint */ -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) # ifndef S_SPLINT_S dsa->p = p; dsa->q = q; @@ -1014,6 +1016,7 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr)) BN_free(pub_key); return NULL; } +#endif /* USE_DSA */ unsigned char * ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size) @@ -1148,9 +1151,9 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) #endif /* HAVE_EVP_PKEY_KEYGEN */ #endif /* HAVE_SSL */ break; +#ifdef USE_DSA case LDNS_SIGN_DSA: case LDNS_SIGN_DSA_NSEC3: -#ifdef USE_DSA #ifdef HAVE_SSL # if OPENSSL_VERSION_NUMBER < 0x00908000L d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL); @@ -1443,7 +1446,7 @@ ldns_key_set_keytag(ldns_key *k, uint16_t tag) size_t ldns_key_list_key_count(const ldns_key_list *key_list) { - return key_list->_key_count; + return key_list ? key_list->_key_count : 0; } ldns_key * @@ -1657,7 +1660,7 @@ ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size) if (!k) { return false; } -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) n = k->n; e = k->e; #else @@ -1877,10 +1880,10 @@ ldns_key2rr(const ldns_key *k) #endif size++; break; +#ifdef USE_DSA case LDNS_SIGN_DSA: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA)); -#ifdef USE_DSA #ifdef HAVE_SSL dsa = ldns_key_dsa_key(k); if (dsa) { @@ -1900,10 +1903,10 @@ ldns_key2rr(const ldns_key *k) #endif /* HAVE_SSL */ #endif /* USE_DSA */ break; +#ifdef USE_DSA case LDNS_SIGN_DSA_NSEC3: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3)); -#ifdef USE_DSA #ifdef HAVE_SSL dsa = ldns_key_dsa_key(k); if (dsa) { @@ -2164,7 +2167,9 @@ ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name) ldns_lookup_table aliases[] = { /* from bind dnssec-keygen */ {LDNS_SIGN_HMACMD5, "HMAC-MD5"}, +#ifdef USE_DSA {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"}, +#endif /* USE_DSA */ {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"}, /* old ldns usage, now RFC names */ #ifdef USE_DSA diff --git a/contrib/ldns/ldns/buffer.h b/contrib/ldns/ldns/buffer.h index f49a550bbd..79ae0f5cc1 100644 --- a/contrib/ldns/ldns/buffer.h +++ b/contrib/ldns/ldns/buffer.h @@ -399,6 +399,22 @@ ldns_buffer_write_string(ldns_buffer *buffer, const char *str) ldns_buffer_write(buffer, str, strlen(str)); } +/** + * copies the given (null-delimited) string to the current position at the buffer + * increasing the capacity if necessary + * \param[in] buffer the buffer + * \param[in] str the string to write + */ +INLINE void +ldns_buffer_write_chars(ldns_buffer *buffer, const char *str) +{ + if (!ldns_buffer_reserve(buffer, strlen(str))) + buffer->_status = LDNS_STATUS_MEM_ERR; + else + ldns_buffer_write_string(buffer, str); +} + + /** * writes the given byte of data at the given position in the buffer * \param[in] buffer the buffer @@ -424,6 +440,21 @@ ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data) buffer->_position += sizeof(data); } +/** + * writes the given byte of data at the current position in the buffer + * increasing the capacity if necessary + * \param[in] buffer the buffer + * \param[in] data the 8 bits to write + */ +INLINE void +ldns_buffer_write_char(ldns_buffer *buffer, uint8_t data) +{ + if (!ldns_buffer_reserve(buffer, sizeof(data))) + buffer->_status = LDNS_STATUS_MEM_ERR; + else + ldns_buffer_write_u8(buffer, data); +} + /** * writes the given 2 byte integer at the given position in the buffer * \param[in] buffer the buffer diff --git a/contrib/ldns/ldns/common.h b/contrib/ldns/ldns/common.h index 9abd9b9396..27f858dd9e 100644 --- a/contrib/ldns/ldns/common.h +++ b/contrib/ldns/ldns/common.h @@ -27,6 +27,9 @@ #define LDNS_BUILD_CONFIG_USE_DANE 1 #define LDNS_BUILD_CONFIG_HAVE_B32_PTON 0 #define LDNS_BUILD_CONFIG_HAVE_B32_NTOP 0 +#define LDNS_BUILD_CONFIG_USE_DSA 1 +#define LDNS_BUILD_CONFIG_USE_ED25519 1 +#define LDNS_BUILD_CONFIG_USE_ED448 1 /* * HAVE_STDBOOL_H is not available when distributed as a library, but no build diff --git a/contrib/ldns/ldns/dane.h b/contrib/ldns/ldns/dane.h index 3bde546391..b5366e0e5c 100644 --- a/contrib/ldns/ldns/dane.h +++ b/contrib/ldns/ldns/dane.h @@ -43,7 +43,7 @@ enum ldns_enum_tlsa_certificate_usage /** CA constraint */ LDNS_TLSA_USAGE_PKIX_TA = 0, LDNS_TLSA_USAGE_CA_CONSTRAINT = 0, - /** Sevice certificate constraint */ + /** Service certificate constraint */ LDNS_TLSA_USAGE_PKIX_EE = 1, LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT = 1, /** Trust anchor assertion */ diff --git a/contrib/ldns/ldns/dnssec.h b/contrib/ldns/ldns/dnssec.h index 9881fda723..6ce305aeb7 100644 --- a/contrib/ldns/ldns/dnssec.h +++ b/contrib/ldns/ldns/dnssec.h @@ -355,7 +355,7 @@ uint8_t ldns_nsec3_salt_length(const ldns_rr *nsec3_rr); /** * Returns the salt bytes used in the given NSEC3 RR * \param[in] *nsec3_rr The RR to read from - * \return The salt in bytes, this is alloced, so you need to free it + * \return The salt in bytes, this is alloc'ed, so you need to free it */ uint8_t *ldns_nsec3_salt_data(const ldns_rr *nsec3_rr); diff --git a/contrib/ldns/ldns/dnssec_sign.h b/contrib/ldns/ldns/dnssec_sign.h index a88a46affa..4523811f1a 100644 --- a/contrib/ldns/ldns/dnssec_sign.h +++ b/contrib/ldns/ldns/dnssec_sign.h @@ -12,8 +12,11 @@ extern "C" { /* sign functions */ /** Sign flag that makes DNSKEY type signed by all keys, not only by SEP keys*/ -#define LDNS_SIGN_DNSKEY_WITH_ZSK 1 -#define LDNS_SIGN_WITH_ALL_ALGORITHMS 2 +#define LDNS_SIGN_DNSKEY_WITH_ZSK 1 +#define LDNS_SIGN_WITH_ALL_ALGORITHMS 2 +#define LDNS_SIGN_NO_KEYS_NO_NSECS 4 +#define LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384 8 +#define LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512 16 /** * Create an empty RRSIG RR (i.e. without the actual signature data) @@ -46,9 +49,10 @@ ldns_rr_list *ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys); #if LDNS_BUILD_CONFIG_HAVE_SSL /** * Sign a buffer with the DSA key (hash with SHA1) - * \param[in] to_sign buffer with the data - * \param[in] key the key to use - * \return a ldns_rdf with the signed data + * + * \param[in] to_sign The ldns_buffer containing raw data that is to be signed + * \param[in] key The DSA key structure to sign with + * \return a ldns_rdf for the RRSIG ldns_rr */ ldns_rdf *ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key); @@ -109,7 +113,7 @@ ldns_dnssec_zone_mark_and_get_glue( * be taken into account separately. * * \param[in] zone the zone in which to mark the names - * \return LDNS_STATUS_OK on succesful completion + * \return LDNS_STATUS_OK on successful completion, an error code otherwise */ ldns_status ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone); diff --git a/contrib/ldns/ldns/dnssec_verify.h b/contrib/ldns/ldns/dnssec_verify.h index 80881c682f..0ce6ec99d2 100644 --- a/contrib/ldns/ldns/dnssec_verify.h +++ b/contrib/ldns/ldns/dnssec_verify.h @@ -592,7 +592,7 @@ ldns_status ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, * \param[in] packet_qtype The original query RR type * \param[in] packet_nodata True if the providing packet had an empty ANSWER * section - * \param[in] match On match, the given (reference to a) pointer will be set + * \param[out] match On match, the given (reference to a) pointer will be set * to point to the matching nsec resource record. * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code * containing the reason they do not otherwise diff --git a/contrib/ldns/ldns/dnssec_zone.h b/contrib/ldns/ldns/dnssec_zone.h index e97ea30c60..156e391023 100644 --- a/contrib/ldns/ldns/dnssec_zone.h +++ b/contrib/ldns/ldns/dnssec_zone.h @@ -53,7 +53,7 @@ struct ldns_struct_dnssec_name * Usually, the name is a pointer to the owner name of the first rr for * this name, but sometimes there is no actual data to point to, * for instance in - * names representing empty nonterminals. If so, set alloced to true to + * names representing empty nonterminals. If so, set name_alloced to true to * indicate that this data must also be freed when the name is freed */ bool name_alloced; @@ -93,7 +93,7 @@ struct ldns_struct_dnssec_zone { ldns_dnssec_name *soa; /** tree of ldns_dnssec_names */ ldns_rbtree_t *names; - /** tree of ldns_dnssec_names by nsec3 hashes (when applicible) */ + /** tree of ldns_dnssec_names by nsec3 hashes (when applicable) */ ldns_rbtree_t *hashed_names; /** points to the first added NSEC3 rr whose parameters will be * assumed for all subsequent NSEC3 rr's and which will be used @@ -204,7 +204,7 @@ ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr); /** - * Print the given list of rrsets to the fiven file descriptor + * Print the given list of rrsets to the given file descriptor * * \param[in] out the file descriptor to print to * \param[in] rrsets the list of RRsets to print @@ -215,7 +215,7 @@ void ldns_dnssec_rrsets_print(FILE *out, bool follow); /** - * Print the given list of rrsets to the fiven file descriptor + * Print the given list of rrsets to the given file descriptor * * \param[in] out the file descriptor to print to * \param[in] fmt the format of the textual representation @@ -297,12 +297,12 @@ void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec); /** * Compares the domain names of the two arguments in their - * canonical ordening. + * canonical ordering. * * \param[in] a The first dnssec_name to compare * \param[in] b The second dnssec_name to compare * \return -1 if the domain name of a comes before that of b in canonical - * ordening, 1 if it is the other way around, and 0 if they are + * ordering, 1 if it is the other way around, and 0 if they are * equal */ int ldns_dnssec_name_cmp(const void *a, const void *b); @@ -476,6 +476,8 @@ ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone); */ bool ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone); +ldns_status ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone); + #ifdef __cplusplus } #endif diff --git a/contrib/ldns/ldns/edns.h b/contrib/ldns/ldns/edns.h new file mode 100644 index 0000000000..594fda22f7 --- /dev/null +++ b/contrib/ldns/ldns/edns.h @@ -0,0 +1,272 @@ +/* + * edns.h + * + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2022 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_EDNS_H +#define LDNS_EDNS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * EDNS option codes + */ +enum ldns_enum_edns_option +{ + LDNS_EDNS_LLQ = 1, /* RFC8764 */ + LDNS_EDNS_UL = 2, /* http://files.dns-sd.org/draft-sekar-dns-ul.txt */ + LDNS_EDNS_NSID = 3, /* RFC5001 */ + /* 4 draft-cheshire-edns0-owner-option */ + LDNS_EDNS_DAU = 5, /* RFC6975 */ + LDNS_EDNS_DHU = 6, /* RFC6975 */ + LDNS_EDNS_N3U = 7, /* RFC6975 */ + LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */ + LDNS_EDNS_EXPIRE = 9, /* RFC7314 */ + LDNS_EDNS_COOKIE = 10, /* RFC7873 */ + LDNS_EDNS_KEEPALIVE = 11, /* RFC7828*/ + LDNS_EDNS_PADDING = 12, /* RFC7830 */ + LDNS_EDNS_CHAIN = 13, /* RFC7901 */ + LDNS_EDNS_KEY_TAG = 14, /* RFC8145 */ + LDNS_EDNS_EDE = 15, /* RFC8914 */ + LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */ + LDNS_EDNS_SERVER_TAG = 17 /* draft-bellis-dnsop-edns-tags-01 */ +}; +typedef enum ldns_enum_edns_option ldns_edns_option_code; + +/** + * Extended DNS Error (RFC 8914) codes + */ +enum ldns_edns_enum_ede_code +{ + LDNS_EDE_OTHER = 0, + LDNS_EDE_UNSUPPORTED_DNSKEY_ALG = 1, + LDNS_EDE_UNSUPPORTED_DS_DIGEST = 2, + LDNS_EDE_STALE_ANSWER = 3, + LDNS_EDE_FORGED_ANSWER = 4, + LDNS_EDE_DNSSEC_INDETERMINATE = 5, + LDNS_EDE_DNSSEC_BOGUS = 6, + LDNS_EDE_SIGNATURE_EXPIRED = 7, + LDNS_EDE_SIGNATURE_NOT_YET_VALID = 8, + LDNS_EDE_DNSKEY_MISSING = 9, + LDNS_EDE_RRSIGS_MISSING = 10, + LDNS_EDE_NO_ZONE_KEY_BIT_SET = 11, + LDNS_EDE_NSEC_MISSING = 12, + LDNS_EDE_CACHED_ERROR = 13, + LDNS_EDE_NOT_READY = 14, + LDNS_EDE_BLOCKED = 15, + LDNS_EDE_CENSORED = 16, + LDNS_EDE_FILTERED = 17, + LDNS_EDE_PROHIBITED = 18, + LDNS_EDE_STALE_NXDOMAIN_ANSWER = 19, + LDNS_EDE_NOT_AUTHORITATIVE = 20, + LDNS_EDE_NOT_SUPPORTED = 21, + LDNS_EDE_NO_REACHABLE_AUTHORITY = 22, + LDNS_EDE_NETWORK_ERROR = 23, + LDNS_EDE_INVALID_DATA = 24, + LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID = 25, + LDNS_EDE_TOO_EARLY = 26 +}; +typedef enum ldns_edns_enum_ede_code ldns_edns_ede_code; + +/** + * The struct that stores an ordered EDNS option. + * An EDNS option is structed as follows: + +0 (MSB) +1 (LSB) + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + 0: | OPTION-CODE | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + 2: | OPTION-LENGTH | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + 4: | | + / OPTION-DATA / + / / + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + */ +struct ldns_struct_edns_option { + ldns_edns_option_code _code; + size_t _size; + void *_data; +}; +typedef struct ldns_struct_edns_option ldns_edns_option; + + +/* + * Array structure to store multiple EDNS options + */ +struct ldns_struct_edns_option_list +{ + size_t _option_count; /* the number of EDNS options in the list */ + size_t _option_capacity; /* the amount of options that fit into the list */ + size_t _options_size; /* the total size of the options serialized */ + ldns_edns_option **_options; +}; +typedef struct ldns_struct_edns_option_list ldns_edns_option_list; + +/* + * Access functions + * do this as functions to get type checking + */ + +/** + * returns the size of the EDNS data. + * \param[in] *edns the EDNS struct to read from + * \return uint16_t with the size + */ +size_t ldns_edns_get_size(const ldns_edns_option *edns); + +/** + * returns the option code of the EDNS data. + * \param[in] *edns the EDNS struct to read from + * \return uint16_t with the size + */ +ldns_edns_option_code ldns_edns_get_code(const ldns_edns_option *edns); + +/** + * returns the EDNS option data. + * \param[in] *edns the EDNS option to read from + * \return uint8_t* pointer to the EDNS option's data + */ +uint8_t *ldns_edns_get_data(const ldns_edns_option *edns); + + +/** + * serialise the EDNS option into wireformat. + * \param[in] *edns the EDNS option to read from + * \return ldns_buffer* the buffer containing the data + */ +ldns_buffer *ldns_edns_get_wireformat_buffer(const ldns_edns_option *edns); + +/* Constructors and destructors*/ + +/** + * allocates a new EDNS structure and fills it. This function *DOES NOT* copy + * the contents from the data parameter. + * \param[in] code the EDNS code + * \param[in] size size of the buffer + * \param[in] data pointer to the buffer to be assigned + * \return the new EDNS structure or NULL on failure + */ +ldns_edns_option *ldns_edns_new(ldns_edns_option_code code, size_t size, void *data); + +/** + * allocates a new EDNS structure and fills it. This function *DOES* copy + * the contents from the data parameter. + * \param[in] code the EDNS code + * \param[in] size size of the buffer + * \param[in] data pointer to the buffer to be assigned + * \return the new EDNS structure or NULL on failure + */ +ldns_edns_option *ldns_edns_new_from_data(ldns_edns_option_code code, size_t size, const void *data); + +/** + * clone an EDNS option + * \param[in] edns the EDNS option + * \return the new EDNS structure + */ +ldns_edns_option *ldns_edns_clone(ldns_edns_option *edns); + +/** + * free the EDNS option. Use deep_free if the _data member is allocated. + * \param[in] edns the EDNS option to free + */ +void ldns_edns_deep_free(ldns_edns_option *edns); +void ldns_edns_free(ldns_edns_option *edns); + +/** + * allocates space for a new list of EDNS options + * \return the new EDNS option list or NULL on failure + */ +ldns_edns_option_list* ldns_edns_option_list_new(void); + +/** + * clone the EDNS options list and it's contents + * \param[in] options_list the EDNS options_list to read from + * \return the new EDNS option list + */ +ldns_edns_option_list *ldns_edns_option_list_clone(ldns_edns_option_list *options_list); + +/** + * free the EDNS option list. Use deep_free to free the options options + * in the list as well. + * \param[in] options_list the EDNS option to free + */ +void ldns_edns_option_list_free(ldns_edns_option_list *options_list); +void ldns_edns_option_list_deep_free(ldns_edns_option_list *options_list); + +/* edns_option_list functions */ + +/** + * returns the number of options in the EDNS options list. + * \param[in] options_list the EDNS options_list to read from + * \return the number of EDNS options + */ +size_t ldns_edns_option_list_get_count(const ldns_edns_option_list *options_list); + +/** + * returns the EDNS option as the specified index in the list of EDNS options. + * \param[in] options_list the EDNS options_list to read from + * \param[in] index the location of the EDNS option to get in the list + * \return the EDNS option located at the index or NULL on failure + */ +ldns_edns_option* ldns_edns_option_list_get_option(const ldns_edns_option_list *options_list, + size_t index); + + +/** + * returns the total size of all the individual EDNS options in the EDNS list. + * \param[in] options_list the EDNS options_list to read from + * \return the total size of the options combined + */ +size_t ldns_edns_option_list_get_options_size(const ldns_edns_option_list *options_list); + +/** + * adds an EDNS option to the list of options at the specified index. Also + * returns the option that was previously at that index. + * \param[in] options_list the EDNS options_list to add to + * \param[in] option the EDNS option to add to the list + * \param[in] index the index in the list where to set the option + * \return the EDNS option previously located at the index + */ +ldns_edns_option *ldns_edns_option_list_set_option(ldns_edns_option_list *options_list, + ldns_edns_option *option, size_t index); + +/** + * adds an EDNS option at the end of the list of options. + * \param[in] options_list the EDNS options_list to add to + * \param[in] option the (non-NULL) EDNS option to add to the list + * \return true on success and false of failure + */ +bool ldns_edns_option_list_push(ldns_edns_option_list *options_list, + ldns_edns_option *option); + +/** + * removes and returns the EDNS option at the end of the list of options. + * \param[in] options_list the EDNS options_list to add to + * \return the EDNS option at the end of the list, or NULL on failure + */ +ldns_edns_option* ldns_edns_option_list_pop(ldns_edns_option_list *options_list); + +/** + * serializes all the EDNS options into a single wireformat buffer + * \param[in] option_list the EDNS options_list to combine into one wireformat + * \return the filled buffer or NULL on failure + */ +ldns_buffer *ldns_edns_option_list2wireformat_buffer(const ldns_edns_option_list *option_list); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_EDNS_H */ diff --git a/contrib/ldns/ldns/error.h b/contrib/ldns/ldns/error.h index 15f49a28e1..2429b7703d 100644 --- a/contrib/ldns/ldns/error.h +++ b/contrib/ldns/ldns/error.h @@ -129,7 +129,19 @@ enum ldns_enum_status { LDNS_STATUS_RDATA_OVERFLOW, LDNS_STATUS_SYNTAX_SUPERFLUOUS_TEXT_ERR, LDNS_STATUS_NSEC3_DOMAINNAME_OVERFLOW, - LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA + LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA, + LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE, + LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME, + LDNS_STATUS_ZONEMD_UNKNOWN_HASH, + LDNS_STATUS_ZONEMD_INVALID_SOA, + LDNS_STATUS_NO_ZONEMD, + LDNS_STATUS_NO_VALID_ZONEMD, + LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR, + LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR, + LDNS_STATUS_RESERVED_SVCPARAM_KEY, + LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED, + LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE, + LDNS_STATUS_INVALID_SVCPARAM_VALUE }; typedef enum ldns_enum_status ldns_status; diff --git a/contrib/ldns/ldns/host2str.h b/contrib/ldns/ldns/host2str.h index 4b443d05f4..79f5561a94 100644 --- a/contrib/ldns/ldns/host2str.h +++ b/contrib/ldns/ldns/host2str.h @@ -65,6 +65,8 @@ extern "C" { #define LDNS_FMT_ZEROIZE_RRSIGS (1 << 9) #define LDNS_FMT_PAD_SOA_SERIAL (1 << 10) #define LDNS_FMT_RFC3597 (1 << 11) /* yes */ +/** Prints only answer section of packets and only rdata of RRs **/ +#define LDNS_FMT_SHORT (1 << 12) #define LDNS_FMT_FLAGS_WITH_DATA 2 @@ -76,11 +78,11 @@ extern "C" { /** * Output format specifier * - * Determines how Packets, Resource Records and Resource record data fiels are + * Determines how Packets, Resource Records and Resource record data field are * formatted when printing or converting to string. * Currently it is only used to specify what aspects of a Resource Record are * annotated in the comment section of the textual representation the record. - * This is speciefed with flags and potential exra data (such as for example + * This is specified with flags and potential extra data (such as for example * a lookup map of hashes to real names for annotation NSEC3 records). */ struct ldns_struct_output_format @@ -110,7 +112,7 @@ typedef struct ldns_struct_output_format_storage ldns_output_format_storage; */ extern const ldns_output_format *ldns_output_format_nocomments; /** - * Standard output format record that annotated only DNSKEY RR's with commenti + * Standard output format record that annotated only DNSKEY RR's with comment * text. */ extern const ldns_output_format *ldns_output_format_onlykeyids; @@ -513,6 +515,17 @@ ldns_status ldns_rr2buffer_str_fmt(ldns_buffer *output, */ ldns_status ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt); +/** + * Converts the list of EDNS options to presentation + * format (as char *) and appends it to the given buffer + * + * \param[in] output pointer to the buffer to append the data to + * \param[in] edns_list the list of EDNS options + * \return status + */ +ldns_status ldns_edns_option_list2buffer_str(ldns_buffer *output, + ldns_edns_option_list* edns_list); + /** * Converts the data in the DNS packet to presentation * format (as char *) and appends it to the given buffer @@ -646,6 +659,14 @@ ldns_status ldns_rdf2buffer_str_hip(ldns_buffer *output, ldns_status ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, const ldns_rdf *rdf); +/** + * Converts an LDNS_RDF_TYPE_SVCPARAMS rdata element to presentation format. + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_svcparams(ldns_buffer *output, + const ldns_rdf *rdf); /** * Converts the data in the rdata field to presentation format and diff --git a/contrib/ldns/ldns/host2wire.h b/contrib/ldns/ldns/host2wire.h index 94693cda36..4378f3366f 100644 --- a/contrib/ldns/ldns/host2wire.h +++ b/contrib/ldns/ldns/host2wire.h @@ -130,7 +130,7 @@ ldns_status ldns_rrsig2buffer_wire(ldns_buffer *output, const ldns_rr *sigrr); * Converts an rr's rdata to wireformat, while excluding * the ownername and all the stuff before the rdata. * This is needed in DNSSEC keytag calculation, the ds - * calcalution from the key and maybe elsewhere. + * calculation from the key and maybe elsewhere. * * \param[out] *output buffer where to put the result * \param[in] *rr rr to operate on @@ -146,6 +146,15 @@ ldns_status ldns_rr_rdata2buffer_wire(ldns_buffer *output, const ldns_rr *rr); */ ldns_status ldns_pkt2buffer_wire(ldns_buffer *output, const ldns_pkt *pkt); +/** + * Copies the packet data to the buffer in wire format + * \param[out] *output buffer to append the result to + * \param[in] *pkt packet to convert + * \param[out] *compression_data data structure holding state for compression + * \return ldns_status + */ +ldns_status ldns_pkt2buffer_wire_compress(ldns_buffer *output, const ldns_pkt *pkt, ldns_rbtree_t *compression_data); + /** * Copies the rr_list data to the buffer in wire format * \param[out] *output buffer to append the result to @@ -187,6 +196,10 @@ ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t * given packet in that array. The result_size value contains the * length of the array, if it succeeds, and 0 otherwise (in which case * the function also returns NULL) + * + * \param[out] dest pointer to the array of bytes to be created + * \param[in] p the packet to convert + * \param[out] size the size of the converted result */ ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *p, size_t *size); diff --git a/contrib/ldns/ldns/keys.h b/contrib/ldns/ldns/keys.h index df4bb22b26..847825e533 100644 --- a/contrib/ldns/ldns/keys.h +++ b/contrib/ldns/ldns/keys.h @@ -55,16 +55,8 @@ enum ldns_enum_algorithm LDNS_ECC_GOST = 12, /* RFC 5933 */ LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */ LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */ -#ifdef USE_ED25519 - /* this ifdef is internal to ldns, because we do not want to export - * the symbol. Users can define it if they want access, - * the feature is not fully implemented at this time and openssl - * does not support it fully either (also for ED448). */ - LDNS_ED25519 = 15, /* draft-ietf-curdle-dnskey-ed25519 */ -#endif -#ifdef USE_ED448 - LDNS_ED448 = 16, /* draft-ietf-curdle-dnskey-ed448 */ -#endif + LDNS_ED25519 = 15, /* RFC 8080 */ + LDNS_ED448 = 16, /* RFC 8080 */ LDNS_INDIRECT = 252, LDNS_PRIVATEDNS = 253, LDNS_PRIVATEOID = 254 @@ -90,20 +82,24 @@ enum ldns_enum_signing_algorithm { LDNS_SIGN_RSAMD5 = LDNS_RSAMD5, LDNS_SIGN_RSASHA1 = LDNS_RSASHA1, +#if LDNS_BUILD_CONFIG_USE_DSA LDNS_SIGN_DSA = LDNS_DSA, +#endif /* LDNS_BUILD_CONFIG_USE_DSA */ LDNS_SIGN_RSASHA1_NSEC3 = LDNS_RSASHA1_NSEC3, LDNS_SIGN_RSASHA256 = LDNS_RSASHA256, LDNS_SIGN_RSASHA512 = LDNS_RSASHA512, +#if LDNS_BUILD_CONFIG_USE_DSA LDNS_SIGN_DSA_NSEC3 = LDNS_DSA_NSEC3, +#endif /* LDNS_BUILD_CONFIG_USE_DSA */ LDNS_SIGN_ECC_GOST = LDNS_ECC_GOST, LDNS_SIGN_ECDSAP256SHA256 = LDNS_ECDSAP256SHA256, LDNS_SIGN_ECDSAP384SHA384 = LDNS_ECDSAP384SHA384, -#ifdef USE_ED25519 +#if LDNS_BUILD_CONFIG_USE_ED25519 LDNS_SIGN_ED25519 = LDNS_ED25519, -#endif -#ifdef USE_ED448 +#endif /* LDNS_BUILD_CONFIG_USE_ED25519 */ +#if LDNS_BUILD_CONFIG_USE_ED448 LDNS_SIGN_ED448 = LDNS_ED448, -#endif +#endif /* LDNS_BUILD_CONFIG_USE_ED448 */ LDNS_SIGN_HMACMD5 = 157, /* not official! This type is for TSIG, not DNSSEC */ LDNS_SIGN_HMACSHA1 = 158, /* not official! This type is for TSIG, not DNSSEC */ LDNS_SIGN_HMACSHA256 = 159, /* ditto */ @@ -231,8 +227,14 @@ ldns_status ldns_key_new_frm_fp_l(ldns_key **k, FILE *fp, int *line_nr); /** * Read the key with the given id from the given engine and store it * in the given ldns_key structure. The algorithm type is set + * + * \param[out] key the new ldns_key structure + * \param[in] e the engine from which to read the key + * \param[in] key_id the id of the key with which to lookup the key in the engine + * \param[in] a the algorithm to set for this key + * \return an error or LDNS_STATUS_OK */ -ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm); +ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm a); /** @@ -242,9 +244,7 @@ ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldn * \return NULL on failure otherwise a RSA structure */ RSA *ldns_key_new_frm_fp_rsa(FILE *fp); -#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ -#if LDNS_BUILD_CONFIG_HAVE_SSL /** * frm_fp helper function. This function parses the * remainder of the (RSA) priv. key file generated from bind9 @@ -253,9 +253,9 @@ RSA *ldns_key_new_frm_fp_rsa(FILE *fp); * \return NULL on failure otherwise a RSA structure */ RSA *ldns_key_new_frm_fp_rsa_l(FILE *fp, int *line_nr); -#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ -#if LDNS_BUILD_CONFIG_HAVE_SSL + +# if LDNS_BUILD_CONFIG_USE_DSA /** * frm_fp helper function. This function parses the * remainder of the (DSA) priv. key file @@ -263,9 +263,7 @@ RSA *ldns_key_new_frm_fp_rsa_l(FILE *fp, int *line_nr); * \return NULL on failure otherwise a RSA structure */ DSA *ldns_key_new_frm_fp_dsa(FILE *fp); -#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ -#if LDNS_BUILD_CONFIG_HAVE_SSL /** * frm_fp helper function. This function parses the * remainder of the (DSA) priv. key file @@ -274,9 +272,8 @@ DSA *ldns_key_new_frm_fp_dsa(FILE *fp); * \return NULL on failure otherwise a RSA structure */ DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr); -#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ +# endif /* LDNS_BUILD_CONFIG_USE_DSA */ -#if LDNS_BUILD_CONFIG_HAVE_SSL /** * frm_fp helper function. This function parses the * remainder of the (HMAC-MD5) key file @@ -286,9 +283,7 @@ DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr); * \return NULL on failure otherwise a newly allocated char buffer */ unsigned char *ldns_key_new_frm_fp_hmac(FILE *fp, size_t *hmac_size); -#endif -#if LDNS_BUILD_CONFIG_HAVE_SSL /** * frm_fp helper function. This function parses the * remainder of the (HMAC-MD5) key file @@ -301,13 +296,14 @@ unsigned char *ldns_key_new_frm_fp_hmac(FILE *fp, size_t *hmac_size); unsigned char *ldns_key_new_frm_fp_hmac_l(FILE *fp, int *line_nr, size_t *hmac_size); #endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ -/* acces write functions */ +/* access write functions */ /** * Set the key's algorithm * \param[in] k the key * \param[in] l the algorithm */ void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l); + #if LDNS_BUILD_CONFIG_HAVE_SSL /** * Set the key's evp key @@ -324,6 +320,7 @@ void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e); */ void ldns_key_set_rsa_key(ldns_key *k, RSA *r); +# if LDNS_BUILD_CONFIG_USE_DSA /** * Set the key's dsa data * The dsa data should be freed by the user. @@ -331,6 +328,7 @@ void ldns_key_set_rsa_key(ldns_key *k, RSA *r); * \param[in] d the dsa data */ void ldns_key_set_dsa_key(ldns_key *k, DSA *d); +# endif /* LDNS_BUILD_CONFIG_USE_DSA */ /** * Assign the key's rsa data @@ -340,6 +338,7 @@ void ldns_key_set_dsa_key(ldns_key *k, DSA *d); */ void ldns_key_assign_rsa_key(ldns_key *k, RSA *r); +# if LDNS_BUILD_CONFIG_USE_DSA /** * Assign the key's dsa data * The dsa data will be freed automatically when the key is freed. @@ -347,6 +346,7 @@ void ldns_key_assign_rsa_key(ldns_key *k, RSA *r); * \param[in] d the dsa data */ void ldns_key_assign_dsa_key(ldns_key *k, DSA *d); +# endif /* LDNS_BUILD_CONFIG_USE_DSA */ /** * Get the PKEY id for GOST, loads GOST into openssl as a side effect. @@ -423,7 +423,7 @@ void ldns_key_set_flags(ldns_key *k, uint16_t flags); /** * Set the keylist's key count to count * \param[in] key the key - * \param[in] count the cuont + * \param[in] count the count */ void ldns_key_list_set_key_count(ldns_key_list *key, size_t count); @@ -463,13 +463,13 @@ RSA *ldns_key_rsa_key(const ldns_key *k); * \return the RSA * structure in the key */ EVP_PKEY *ldns_key_evp_key(const ldns_key *k); -#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ +# if LDNS_BUILD_CONFIG_USE_DSA /** * returns the (openssl) DSA struct contained in the key */ -#if LDNS_BUILD_CONFIG_HAVE_SSL DSA *ldns_key_dsa_key(const ldns_key *k); +# endif /* LDNS_BUILD_CONFIG_USE_DSA */ #endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ /** @@ -523,7 +523,7 @@ uint32_t ldns_key_inception(const ldns_key *k); /** * return the key's expiration date * \param[in] k the key - * \return the experiration date + * \return the expiration date */ uint32_t ldns_key_expiration(const ldns_key *k); /** diff --git a/contrib/ldns/ldns/ldns.h b/contrib/ldns/ldns/ldns.h index 60663ef95c..9b0bc066b0 100644 --- a/contrib/ldns/ldns/ldns.h +++ b/contrib/ldns/ldns/ldns.h @@ -101,6 +101,7 @@ Or you can just use the menu above to browse through the API docs. #include #include #include +#include #include #include #include diff --git a/contrib/ldns/ldns/net.h b/contrib/ldns/ldns/net.h index d074f20ace..0fbf1544d5 100644 --- a/contrib/ldns/ldns/net.h +++ b/contrib/ldns/ldns/net.h @@ -30,7 +30,7 @@ extern "C" { */ /** - * Sends a buffer to an ip using udp and return the respons as a ldns_pkt + * Sends a buffer to an ip using udp and return the response as a ldns_pkt * \param[in] qbin the ldns_buffer to be send * \param[in] to the ip addr to send to * \param[in] tolen length of the ip addr @@ -90,7 +90,7 @@ int ldns_tcp_bgsend2(ldns_buffer *qbin, const struct sockaddr_storage *to, sockl int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); /** - * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt + * Sends a buffer to an ip using tcp and return the response as a ldns_pkt * \param[in] qbin the ldns_buffer to be send * \param[in] qbin the ldns_buffer to be send * \param[in] to the ip addr to send to @@ -233,7 +233,7 @@ struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, u * returns an rdf with the sockaddr info. works for ip4 and ip6 * \param[in] sock the struct sockaddr_storage to convert * \param[in] port what port was used. When NULL this is not set - * \return ldns_rdf* wth the address + * \return ldns_rdf* with the address */ ldns_rdf * ldns_sockaddr_storage2rdf(const struct sockaddr_storage *sock, uint16_t *port); @@ -241,7 +241,7 @@ ldns_rdf * ldns_sockaddr_storage2rdf(const struct sockaddr_storage *sock, uint16 * Prepares the resolver for an axfr query * The query is sent and the answers can be read with ldns_axfr_next * \param[in] resolver the resolver to use - * \param[in] domain the domain to exfr + * \param[in] domain the domain to axfr * \param[in] c the class to use * \return ldns_status the status of the transfer */ diff --git a/contrib/ldns/ldns/packet.h b/contrib/ldns/ldns/packet.h index 2e5ee8bde1..2c60609fc0 100644 --- a/contrib/ldns/ldns/packet.h +++ b/contrib/ldns/ldns/packet.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -251,12 +252,14 @@ struct ldns_struct_pkt uint8_t _edns_extended_rcode; /** EDNS Version */ uint8_t _edns_version; - /* OPT pseudo-RR presence flag */ - uint8_t _edns_present; + /* OPT pseudo-RR presence flag */ + uint8_t _edns_present; /** Reserved EDNS data bits */ uint16_t _edns_z; /** Arbitrary EDNS rdata */ ldns_rdf *_edns_data; + /** Structed EDNS data */ + ldns_edns_option_list *_edns_list; /** Question section */ ldns_rr_list *_question; /** Answer section */ @@ -355,9 +358,9 @@ bool ldns_pkt_ad(const ldns_pkt *p); */ ldns_pkt_opcode ldns_pkt_get_opcode(const ldns_pkt *p); /** - * Return the packet's respons code + * Return the packet's response code * \param[in] p the packet - * \return the respons code + * \return the response code */ ldns_pkt_rcode ldns_pkt_get_rcode(const ldns_pkt *p); /** @@ -586,7 +589,7 @@ void ldns_pkt_set_ad(ldns_pkt *p, bool b); */ void ldns_pkt_set_opcode(ldns_pkt *p, ldns_pkt_opcode c); /** - * Set the packet's respons code + * Set the packet's response code * \param[in] p the packet * \param[in] c the rcode */ @@ -687,7 +690,7 @@ uint8_t ldns_pkt_edns_version(const ldns_pkt *packet); */ uint16_t ldns_pkt_edns_z(const ldns_pkt *packet); /** - * return the packet's edns data + * return the packet's EDNS data * \param[in] packet the packet * \return the data */ @@ -729,6 +732,16 @@ void ldns_pkt_set_edns_unassigned(ldns_pkt *packet, uint16_t value); */ bool ldns_pkt_edns(const ldns_pkt *packet); +/** + * Returns a list of structured EDNS options. The list will be automatically + * freed when the packet is freed. The option list can be manipulated and + * will be used when converting the packet to wireformat with ldns_pkt2wire. + * + * \param[in] packet the packet which contains the EDNS data + * \return the list of EDNS options + */ +ldns_edns_option_list* ldns_pkt_edns_get_option_list(ldns_pkt *packet); + /** * Set the packet's edns udp size * \param[in] packet the packet @@ -754,12 +767,20 @@ void ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v); */ void ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z); /** - * Set the packet's edns data + * Set the packet's EDNS data * \param[in] packet the packet * \param[in] data the data */ void ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data); +/** + * Set the packet's structured EDNS data. Once an edns_option_list is set + * (or get), the option list will be used for converting into wireformat. + * \param[in] packet the packet + * \param[in] list the options list that will create the data + */ +void ldns_pkt_set_edns_option_list(ldns_pkt *packet, ldns_edns_option_list *list); + /** * allocates and initializes a ldns_pkt structure. * \return pointer to the new packet @@ -849,7 +870,7 @@ void ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr); void ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr); /** - * directly set the auhority section + * directly set the authority section * \param[in] p packet to operate on * \param[in] rr rrlist to set */ diff --git a/contrib/ldns/ldns/parse.h b/contrib/ldns/ldns/parse.h index 0e9034c341..ba7edf5679 100644 --- a/contrib/ldns/ldns/parse.h +++ b/contrib/ldns/ldns/parse.h @@ -69,6 +69,32 @@ ssize_t ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit); */ ssize_t ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr); +/** + * returns a token/char from the stream f. + * This function deals with ( and ) in the stream, + * and ignores when it finds them. + * \param[in] *f the file to read from + * \param[out] **token this should be a reference to a string buffer in which + * the token is put. A new buffer will be allocated when + * *token is NULL and fixed is false. If the buffer is too + * small to hold the token, the buffer is reallocated with + * double the size (of limit). + * If fixed is true, the string buffer may not be NULL + * and limit must be set to the buffer size. In that case + * no reallocations will be done. + * \param[in,out] *limit reference to the size of the token buffer. Will be + * reset to the new limit of the token buffer if the + * buffer is reallocated. + * \param [in] fixed If fixed is false, the token buffer is allowed to grow + * when needed (by way of reallocation). If true, the token + * buffer will not be resized. + * \param[in] *delim chars at which the parsing should stop + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return LDNS_STATUS_OK on success, LDNS_STATUS_SYNTAX_EMPTY when no token + * was read and an error otherwise. + */ +ldns_status ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed, const char *delim, int *line_nr); + /** * returns a token/char from the buffer b. * This function deals with ( and ) in the buffer, @@ -86,9 +112,9 @@ ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t l * after the keyword + k_del until we hit d_del * \param[in] f file pointer to read from * \param[in] keyword keyword to look for - * \param[in] k_del keyword delimeter + * \param[in] k_del keyword delimiter * \param[out] data the data found - * \param[in] d_del the data delimeter + * \param[in] d_del the data delimiter * \param[in] data_limit maximum size the the data buffer * \return the number of character read */ @@ -99,9 +125,9 @@ ssize_t ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, * after the keyword + k_del until we hit d_del * \param[in] f file pointer to read from * \param[in] keyword keyword to look for - * \param[in] k_del keyword delimeter + * \param[in] k_del keyword delimiter * \param[out] data the data found - * \param[in] d_del the data delimeter + * \param[in] d_del the data delimiter * \param[in] data_limit maximum size the the data buffer * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) @@ -114,9 +140,9 @@ ssize_t ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del * after the keyword + k_del until we hit d_del * \param[in] b buffer pointer to read from * \param[in] keyword keyword to look for - * \param[in] k_del keyword delimeter + * \param[in] k_del keyword delimiter * \param[out] data the data found - * \param[in] d_del the data delimeter + * \param[in] d_del the data delimiter * \param[in] data_limit maximum size the the data buffer * \return the number of character read */ diff --git a/contrib/ldns/ldns/radix.h b/contrib/ldns/ldns/radix.h index ec70565a3c..4cb42b48ba 100644 --- a/contrib/ldns/ldns/radix.h +++ b/contrib/ldns/ldns/radix.h @@ -154,7 +154,7 @@ ldns_radix_node_t* ldns_radix_search(ldns_radix_t* tree, const uint8_t* key, * @param tree: tree to insert to. * @param key: key. * @param len: length of key. - * @param result: the radix node with the exact or closest match. NULL if + * @param[out] result: the radix node with the exact or closest match. NULL if * the key is smaller than the smallest key in the tree. * @return 1 if exact match, 0 otherwise. * @@ -198,7 +198,7 @@ ldns_radix_node_t* ldns_radix_prev(ldns_radix_node_t* node); * Split radix tree intwo. * @param tree1: one tree. * @param num: number of elements to split off. - * @param tree2: another tree. + * @param[out] tree2: another tree. * @return: status. * */ diff --git a/contrib/ldns/ldns/rbtree.h b/contrib/ldns/ldns/rbtree.h index 0747a8e5b8..4cfaf38297 100644 --- a/contrib/ldns/ldns/rbtree.h +++ b/contrib/ldns/ldns/rbtree.h @@ -151,7 +151,7 @@ ldns_rbnode_t *ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key); * Find, but match does not have to be exact. * @param rbtree: tree to find in. * @param key: key to find position of. - * @param result: set to the exact node if present, otherwise to element that + * @param[out] result: set to the exact node if present, otherwise to element that * precedes the position of key in the tree. NULL if no smaller element. * @return: true if exact match in result. Else result points to <= element, * or NULL if key is smaller than the smallest key. diff --git a/contrib/ldns/ldns/rdata.h b/contrib/ldns/ldns/rdata.h index 2767e8b00b..c8a0396cfd 100644 --- a/contrib/ldns/ldns/rdata.h +++ b/contrib/ldns/ldns/rdata.h @@ -142,6 +142,9 @@ enum ldns_enum_rdf_type /** draft-ietf-mboned-driad-amt-discovery **/ LDNS_RDF_TYPE_AMTRELAY, + /** draft-ietf-dnsop-svcb-https **/ + LDNS_RDF_TYPE_SVCPARAMS, + /* Aliases */ LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC }; @@ -165,7 +168,23 @@ enum ldns_enum_cert_algorithm }; typedef enum ldns_enum_cert_algorithm ldns_cert_algorithm; - +/** + * keys types in SVCPARAMS rdata fields + */ +enum ldns_enum_svcparam_key +{ + LDNS_SVCPARAM_KEY_MANDATORY = 0, + LDNS_SVCPARAM_KEY_ALPN = 1, + LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN = 2, + LDNS_SVCPARAM_KEY_PORT = 3, + LDNS_SVCPARAM_KEY_IPV4HINT = 4, + LDNS_SVCPARAM_KEY_ECH = 5, + LDNS_SVCPARAM_KEY_IPV6HINT = 6, + LDNS_SVCPARAM_KEY_DOHPATH = 7, + LDNS_SVCPARAM_KEY_LAST_KEY = 7, + LDNS_SVCPARAM_KEY_RESERVED = 65535 +}; +typedef enum ldns_enum_svcparam_key ldns_svcparam_key; /** * Resource record data field. @@ -243,7 +262,7 @@ uint8_t *ldns_rdf_data(const ldns_rdf *rd); /** * allocates a new rdf structure and fills it. * This function DOES NOT copy the contents from - * the buffer, unlinke ldns_rdf_new_frm_data() + * the buffer, unlike ldns_rdf_new_frm_data() * \param[in] type type of the rdf * \param[in] size size of the buffer * \param[in] data pointer to the buffer to be copied @@ -254,7 +273,7 @@ ldns_rdf *ldns_rdf_new(ldns_rdf_type type, size_t size, void *data); /** * allocates a new rdf structure and fills it. * This function _does_ copy the contents from - * the buffer, unlinke ldns_rdf_new() + * the buffer, unlike ldns_rdf_new() * \param[in] type type of the rdf * \param[in] size size of the buffer * \param[in] data pointer to the buffer to be copied diff --git a/contrib/ldns/ldns/resolver.h b/contrib/ldns/ldns/resolver.h index 84128dfecf..e8459db7a3 100644 --- a/contrib/ldns/ldns/resolver.h +++ b/contrib/ldns/ldns/resolver.h @@ -250,7 +250,7 @@ bool ldns_resolver_dnssec_cd(const ldns_resolver *r); /** * Get the resolver's DNSSEC anchors * \param[in] r the resolver - * \return an rr_list containg trusted DNSSEC anchors + * \return an rr_list containing trusted DNSSEC anchors */ ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r); /** @@ -730,7 +730,7 @@ ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **r, FILE *fp, int *line_nr ldns_status ldns_resolver_new_frm_file(ldns_resolver **r, const char *filename); /** - * Frees the allocated space for this resolver. Only frees the resolver pionter! You should probably be using _deep_free. + * Frees the allocated space for this resolver. Only frees the resolver pointer! You should probably be using _deep_free. * \param res resolver to free */ void ldns_resolver_free(ldns_resolver *res); @@ -766,7 +766,7 @@ bool ldns_axfr_complete(const ldns_resolver *resolver); /** * Returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer - * uasable for instance to get the error code on failure + * usable for instance to get the error code on failure * \param[in] res the resolver that was used in the axfr transfer * \return ldns_pkt the last packet sent */ diff --git a/contrib/ldns/ldns/rr.h b/contrib/ldns/ldns/rr.h index 89cc0b6f00..44d54121f4 100644 --- a/contrib/ldns/ldns/rr.h +++ b/contrib/ldns/ldns/rr.h @@ -156,7 +156,7 @@ enum ldns_enum_rr_type LDNS_RR_TYPE_DNAME = 39, /** dnsind-kitchen-sink-02.txt */ LDNS_RR_TYPE_SINK = 40, - /** Pseudo OPT record... */ + /** OPT record RFC 6891 */ LDNS_RR_TYPE_OPT = 41, /** RFC3123 */ LDNS_RR_TYPE_APL = 42, @@ -191,7 +191,9 @@ enum ldns_enum_rr_type LDNS_RR_TYPE_CDNSKEY = 60, /* RFC 7344 */ LDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ LDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ - LDNS_RR_TYPE_ZONEMD = 63, /* draft-wessels-dns-zone-digest */ + LDNS_RR_TYPE_ZONEMD = 63, /* draft-ietf-dnsop-dns-zone-digest */ + LDNS_RR_TYPE_SVCB = 64, /* draft-ietf-dnsop-svcb-https */ + LDNS_RR_TYPE_HTTPS = 65, /* draft-ietf-dnsop-svcb-https */ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ @@ -525,7 +527,7 @@ void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class); * \param[in] *rr the rr to operate on * \param[in] *f the rdf to set * \param[in] position the position the set the rdf - * \return the old value in the rr, NULL on failyre + * \return the old value in the rr, NULL on failure */ ldns_rdf* ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position); @@ -815,7 +817,7 @@ int ldns_rr_compare_wire(const ldns_buffer *rr1_buf, const ldns_buffer *rr2_buf) bool ldns_rr_compare_ds(const ldns_rr *rr1, const ldns_rr *rr2); /** - * compares two rr listss. + * compares two rr lists. * \param[in] rrl1 the first one * \param[in] rrl2 the second one * \return 0 if equal diff --git a/contrib/ldns/ldns/rr_functions.h b/contrib/ldns/ldns/rr_functions.h index 09a28dd7f8..5a84d40b13 100644 --- a/contrib/ldns/ldns/rr_functions.h +++ b/contrib/ldns/ldns/rr_functions.h @@ -121,9 +121,9 @@ bool ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f); */ ldns_rdf* ldns_rr_rrsig_expiration(const ldns_rr *r); /** - * sets the expireation date of a LDNS_RR_TYPE_RRSIG rr + * sets the expiration date of a LDNS_RR_TYPE_RRSIG rr * \param[in] r the rr to use - * \param[in] f the expireation date to set + * \param[in] f the expiration date to set * \return true on success, false otherwise */ bool ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f); diff --git a/contrib/ldns/ldns/sha1.h b/contrib/ldns/ldns/sha1.h index d5b1082e67..bc98411209 100644 --- a/contrib/ldns/ldns/sha1.h +++ b/contrib/ldns/ldns/sha1.h @@ -1,6 +1,13 @@ #ifndef LDNS_SHA1_H #define LDNS_SHA1_H +#include /* uint32_t and friends */ +#include /* size_t and NULL */ + +#if LDNS_BUILD_CONFIG_HAVE_INTTYPES_H +# include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -29,7 +36,7 @@ void ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ct * available * \return the SHA1 digest of the given data */ -unsigned char *ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest); +unsigned char *ldns_sha1(const unsigned char *data, unsigned int data_len, unsigned char *digest); #ifdef __cplusplus } diff --git a/contrib/ldns/ldns/sha2.h b/contrib/ldns/ldns/sha2.h index 238767af45..c3c1f1a096 100644 --- a/contrib/ldns/ldns/sha2.h +++ b/contrib/ldns/ldns/sha2.h @@ -46,23 +46,16 @@ #ifndef __LDNS_SHA2_H__ #define __LDNS_SHA2_H__ -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Import u_intXX_t size_t type definitions from system headers. You - * may need to change this, or define these things yourself in this - * file. - */ -#include +#include /* uint32_t and friends */ +#include /* size_t and NULL */ #if LDNS_BUILD_CONFIG_HAVE_INTTYPES_H +# include +#endif -#include - -#endif /* LDNS_BUILD_CONFIG_HAVE_INTTYPES_H */ +#ifdef __cplusplus +extern "C" { +#endif /*** SHA-256/384/512 Various Length Definitions ***********************/ @@ -116,7 +109,7 @@ void ldns_sha512_final(uint8_t[LDNS_SHA512_DIGEST_LENGTH], ldns_sha512_CTX*); * available * \return the SHA1 digest of the given data */ -unsigned char *ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest); +unsigned char *ldns_sha256(const unsigned char *data, unsigned int data_len, unsigned char *digest); /** * Convenience function to digest a fixed block of data at once. @@ -128,7 +121,7 @@ unsigned char *ldns_sha256(unsigned char *data, unsigned int data_len, unsigned * available * \return the SHA1 digest of the given data */ -unsigned char *ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest); +unsigned char *ldns_sha384(const unsigned char *data, unsigned int data_len, unsigned char *digest); /** * Convenience function to digest a fixed block of data at once. @@ -140,7 +133,7 @@ unsigned char *ldns_sha384(unsigned char *data, unsigned int data_len, unsigned * available * \return the SHA1 digest of the given data */ -unsigned char *ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest); +unsigned char *ldns_sha512(const unsigned char *data, unsigned int data_len, unsigned char *digest); #ifdef __cplusplus } diff --git a/contrib/ldns/ldns/str2host.h b/contrib/ldns/ldns/str2host.h index e6f7004366..2892db0bfb 100644 --- a/contrib/ldns/ldns/str2host.h +++ b/contrib/ldns/ldns/str2host.h @@ -32,7 +32,7 @@ extern "C" { /** * convert a byte into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] bytestr the string to be converted * \return ldns_status */ @@ -40,7 +40,7 @@ ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr); /** * convert a string to a int16 in wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] shortstr the string to be converted * \return ldns_status */ @@ -48,7 +48,7 @@ ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr); /** * convert a strings into a 4 byte int in wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] longstr the string to be converted * \return ldns_status */ @@ -56,21 +56,21 @@ ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr); /** * convert a time string to a time value in wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] time the string to be converted * \return ldns_status */ ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time); /* convert string with NSEC3 salt to wireformat) - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * return ldns_status */ ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *nsec3_salt); /* convert a time period (think TTL's) to wireformat) - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * return ldns_status */ @@ -78,7 +78,7 @@ ldns_status ldns_str2rdf_period(ldns_rdf **rd, const char *str); /** * convert str with an A record into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -86,7 +86,7 @@ ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str); /** * convert the str with an AAAA record into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -94,7 +94,7 @@ ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str); /** * convert a string into wireformat (think txt record) - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted (NULL terminated) * \return ldns_status */ @@ -102,7 +102,7 @@ ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str); /** * convert str with the apl record into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -110,7 +110,7 @@ ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str); /** * convert the string with the b64 data into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -118,7 +118,7 @@ ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str); /** * convert the string with the b32 ext hex data into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -126,7 +126,7 @@ ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str); /** * convert a hex value into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -134,7 +134,7 @@ ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str); /** * convert string with nsec into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -142,7 +142,7 @@ ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str); /** * convert a rrtype into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -150,7 +150,7 @@ ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str); /** * convert string with a classname into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -158,7 +158,7 @@ ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str); /** * convert an certificate algorithm value into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -166,7 +166,7 @@ ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str); /** * convert an algorithm value into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -174,7 +174,7 @@ ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str); /** * convert a tlsa certificate usage value into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -182,7 +182,7 @@ ldns_status ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str); /** * convert a tlsa selector value into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -190,7 +190,7 @@ ldns_status ldns_str2rdf_selector(ldns_rdf **rd, const char *str); /** * convert a tlsa matching type value into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -198,7 +198,7 @@ ldns_status ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str); /** * convert a string with a unknown RR into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -206,7 +206,7 @@ ldns_status ldns_str2rdf_unknown(ldns_rdf **rd, const char *str); /** * convert string with a protocol service into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -214,7 +214,7 @@ ldns_status ldns_str2rdf_service(ldns_rdf **rd, const char *str); /** * convert a string with a LOC RR into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -222,7 +222,7 @@ ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str); /** * convert string with a WKS RR into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -230,7 +230,7 @@ ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str); /** * convert a str with a NSAP RR into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -238,7 +238,7 @@ ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str); /** * convert a str with a ATMA RR into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -246,7 +246,7 @@ ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str); /** * convert a str with a IPSECKEY RR into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -254,7 +254,7 @@ ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str); /** * convert a dname string into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -262,7 +262,7 @@ ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str); /** * convert 4 * 16bit hex separated by colons into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -270,7 +270,7 @@ ldns_status ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str); /** * convert 6 hex bytes separated by dashes into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -278,7 +278,7 @@ ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str); /** * convert 8 hex bytes separated by dashes into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -286,7 +286,7 @@ ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str); /** * Convert a non-zero sequence of US-ASCII letters and numbers into wireformat - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -295,7 +295,7 @@ ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str); /** * Convert a encoding of the value field as specified * [RFC1035], Section 5.1., encoded as one bug chunk of data. - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ @@ -305,23 +305,33 @@ ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str); * Convert a " " encoding of the value field as specified * in Section 6. of [RFC5205], encoded as wireformat as specified in Section 5. * of [RFC5205]. - * \param[in] rd the rdf where to put the data + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str); /** - * Concert a" " encoding + * Convert a " " encoding * of the value field as specified in Section 4.3.1 of * [draft-ietf-mboned-driad-amt-discovery], encoded as wireformat as specified in - * ection 4.2 of [draft-ietf-mboned-driad-amt-discovery] - * \param[in] rd the rdf where to put the data + * Section 4.2 of [draft-ietf-mboned-driad-amt-discovery] + * \param[out] rd the rdf where to put the data * \param[in] str the string to be converted * \return ldns_status */ ldns_status ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str); +/** + * Convert a series of "key[=]" encodings to wireformat as described in + * [draft-ietf-dnsop-svcb-https]. + * \param[out] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str); + + #ifdef __cplusplus } #endif diff --git a/contrib/ldns/ldns/util.h b/contrib/ldns/ldns/util.h index 0e7ead89f1..1d8fa8836a 100644 --- a/contrib/ldns/ldns/util.h +++ b/contrib/ldns/ldns/util.h @@ -27,8 +27,8 @@ extern "C" { #define dprintf(X,Y) fprintf(stderr, (X), (Y)) /* #define dprintf(X, Y) */ -#define LDNS_VERSION "1.7.1" -#define LDNS_REVISION ((1<<16)|(7<<8)|(1)) +#define LDNS_VERSION "1.8.3" +#define LDNS_REVISION ((1<<16)|(8<<8)|(3)) /** * splint static inline workaround @@ -274,19 +274,22 @@ time_t mktime_from_utc(const struct tm *tm); /** * The function interprets time as the number of seconds since epoch - * with respect to now using serial arithmitics (rfc1982). + * with respect to now using serial arithmetics (rfc1982). * That number of seconds is then converted to broken-out time information. * This is especially useful when converting the inception and expiration * fields of RRSIG records. * * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) - * to be intepreted as a serial arithmitics number relative to now. + * to be interpreted as a serial arithmetics number relative to now. * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) * to which the time value is compared to determine the final value. * \param[out] result the struct with the broken-out time information * \return result on success or NULL on error */ -struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); +struct tm * ldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result); + +/* previously used wrong spelling */ +#define ldns_serial_arithmitics_gmtime_r ldns_serial_arithmetics_gmtime_r /** * Seed the random function. diff --git a/contrib/ldns/ldns/wire2host.h b/contrib/ldns/ldns/wire2host.h index 6a7999c31d..67b385c163 100644 --- a/contrib/ldns/ldns/wire2host.h +++ b/contrib/ldns/ldns/wire2host.h @@ -118,7 +118,7 @@ extern "C" { * This function will initialize and allocate memory space for the packet * structure. * - * \param[in] packet pointer to the structure to hold the packet + * \param[out] packet pointer to the structure to hold the packet * \param[in] data pointer to the buffer with the data * \param[in] len the length of the data buffer (in bytes) * \return LDNS_STATUS_OK if everything succeeds, error otherwise @@ -130,7 +130,7 @@ ldns_status ldns_wire2pkt(ldns_pkt **packet, const uint8_t *data, size_t len); * This function will initialize and allocate memory space for the packet * structure. * - * \param[in] packet pointer to the structure to hold the packet + * \param[out] packet pointer to the structure to hold the packet * \param[in] buffer the buffer with the data * \return LDNS_STATUS_OK if everything succeeds, error otherwise */ @@ -142,7 +142,7 @@ ldns_status ldns_buffer2pkt_wire(ldns_pkt **packet, const ldns_buffer *buffer); * space for the dname structure. The length of the wiredata of this rdf * is added to the *pos value. * - * \param[in] dname pointer to the structure to hold the rdata value + * \param[out] dname pointer to the structure to hold the rdata value * \param[in] wire pointer to the buffer with the data * \param[in] max the length of the data buffer (in bytes) * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes @@ -177,7 +177,7 @@ ldns_status ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t * * structure. * The length of the wiredata of this rr is added to the *pos value. * - * \param[in] rr pointer to the structure to hold the rdata value + * \param[out] rr pointer to the structure to hold the rdata value * \param[in] wire pointer to the buffer with the data * \param[in] max the length of the data buffer (in bytes) * \param[in] pos the position of the rr in the buffer (ie. the number of bytes diff --git a/contrib/ldns/ldns/zone.h b/contrib/ldns/ldns/zone.h index f30d7c48cf..805661f878 100644 --- a/contrib/ldns/ldns/zone.h +++ b/contrib/ldns/ldns/zone.h @@ -97,7 +97,7 @@ void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist); * copying, so the rr_list structure inside z is modified! * \param[in] z the zone to add to * \param[in] list the list to add - * \return a true on succes otherwise falsed + * \return a true on success otherwise false */ bool ldns_zone_push_rr_list(ldns_zone *z, const ldns_rr_list *list); @@ -106,7 +106,7 @@ bool ldns_zone_push_rr_list(ldns_zone *z, const ldns_rr_list *list); * copying, so the rr_list structure inside z is modified! * \param[in] z the zone to add to * \param[in] rr the rr to add - * \return a true on succes otherwise falsed + * \return a true on success otherwise false */ bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr); diff --git a/contrib/ldns/net.c b/contrib/ldns/net.c index 38d00cffac..57d4dff24d 100644 --- a/contrib/ldns/net.c +++ b/contrib/ldns/net.c @@ -463,7 +463,7 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin, } /* set to nonblocking, so if the checksum is bad, it becomes - * an EGAIN error and the ldns_udp_send function does not block, + * an EAGAIN error and the ldns_udp_send function does not block, * but returns a 'NETWORK_ERROR' much like a timeout. */ ldns_sock_nonblock(sockfd); diff --git a/contrib/ldns/packet.c b/contrib/ldns/packet.c index a57e1901e0..afa59005c3 100644 --- a/contrib/ldns/packet.c +++ b/contrib/ldns/packet.c @@ -638,6 +638,15 @@ ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data) packet->_edns_data = data; } +void +ldns_pkt_set_edns_option_list(ldns_pkt *packet, ldns_edns_option_list *list) +{ + if (packet->_edns_list) + ldns_edns_option_list_deep_free(packet->_edns_list); + packet->_edns_list = list; +} + + void ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count) { @@ -738,15 +747,93 @@ ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list) } bool -ldns_pkt_edns(const ldns_pkt *pkt) { +ldns_pkt_edns(const ldns_pkt *pkt) +{ return (ldns_pkt_edns_udp_size(pkt) > 0 || ldns_pkt_edns_extended_rcode(pkt) > 0 || ldns_pkt_edns_data(pkt) || ldns_pkt_edns_do(pkt) || + pkt->_edns_list || pkt->_edns_present ); } +ldns_edns_option_list* +pkt_edns_data2edns_option_list(const ldns_rdf *edns_data) +{ + size_t pos = 0; + ldns_edns_option_list* edns_list; + size_t max; + const uint8_t* wire; + + if (!edns_data) + return NULL; + + max = ldns_rdf_size(edns_data); + wire = ldns_rdf_data(edns_data); + if (!max) + return NULL; + + if (!(edns_list = ldns_edns_option_list_new())) + return NULL; + + while (pos < max) { + ldns_edns_option* edns; + uint8_t *data; + + if (pos + 4 > max) { /* make sure the header is */ + ldns_edns_option_list_deep_free(edns_list); + return NULL; + } + ldns_edns_option_code code = ldns_read_uint16(&wire[pos]); + size_t size = ldns_read_uint16(&wire[pos+2]); + pos += 4; + + if (pos + size > max) { /* make sure the size fits the data */ + ldns_edns_option_list_deep_free(edns_list); + return NULL; + } + data = LDNS_XMALLOC(uint8_t, size); + + if (!data) { + ldns_edns_option_list_deep_free(edns_list); + return NULL; + } + memcpy(data, &wire[pos], size); + pos += size; + + edns = ldns_edns_new(code, size, data); + + if (!edns) { + ldns_edns_option_list_deep_free(edns_list); + return NULL; + } + if (!ldns_edns_option_list_push(edns_list, edns)) { + ldns_edns_option_list_deep_free(edns_list); + return NULL; + } + } + return edns_list; + +} + +ldns_edns_option_list* +ldns_pkt_edns_get_option_list(ldns_pkt *packet) +{ + /* return the list if it already exists */ + if (packet->_edns_list != NULL) + return packet->_edns_list; + + /* if the list doesn't exists, we create it by parsing the + * packet->_edns_data + */ + if (!ldns_pkt_edns_data(packet)) + return NULL; + + return ( packet->_edns_list + = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(packet))); +} + /* Create/destroy/convert functions */ @@ -796,8 +883,9 @@ ldns_pkt_new(void) ldns_pkt_set_edns_version(packet, 0); ldns_pkt_set_edns_z(packet, 0); ldns_pkt_set_edns_data(packet, NULL); + packet->_edns_list = NULL; packet->_edns_present = false; - + ldns_pkt_set_tsig(packet, NULL); return packet; @@ -814,6 +902,7 @@ ldns_pkt_free(ldns_pkt *packet) ldns_rr_list_deep_free(packet->_additional); ldns_rr_free(packet->_tsig_rr); ldns_rdf_deep_free(packet->_edns_data); + ldns_edns_option_list_deep_free(packet->_edns_list); ldns_rdf_deep_free(packet->_answerfrom); LDNS_FREE(packet); } @@ -1163,6 +1252,9 @@ ldns_pkt_clone(const ldns_pkt *pkt) ldns_pkt_set_edns_data(new_pkt, ldns_rdf_clone(ldns_pkt_edns_data(pkt))); ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt)); + if (pkt->_edns_list) + ldns_pkt_set_edns_option_list(new_pkt, + ldns_edns_option_list_clone(pkt->_edns_list)); ldns_rr_list_deep_free(new_pkt->_question); ldns_rr_list_deep_free(new_pkt->_answer); diff --git a/contrib/ldns/parse.c b/contrib/ldns/parse.c index 947dbb8984..9698ba71e8 100644 --- a/contrib/ldns/parse.c +++ b/contrib/ldns/parse.c @@ -27,31 +27,45 @@ ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit) return ldns_fget_token_l(f, token, delim, limit, NULL); } -ssize_t -ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr) +ldns_status +ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed + , const char *delim, int *line_nr) { int c, prev_c; - int p; /* 0 -> no parenthese seen, >0 nr of ( seen */ + int p; /* 0 -> no parentheses seen, >0 nr of ( seen */ int com, quoted; - char *t; + char *t, *old_token; size_t i; const char *d; const char *del; - /* standard delimeters */ + /* standard delimiters */ if (!delim) { /* from isspace(3) */ del = LDNS_PARSE_NORMAL; } else { del = delim; } + if (!token || !limit) + return LDNS_STATUS_NULL; + + if (fixed) { + if (*token == NULL || *limit == 0) + return LDNS_STATUS_NULL; + } else if (*token == NULL) { + *limit = LDNS_MAX_LINELEN; + if (!(*token = LDNS_XMALLOC(char, *limit + 1))) + return LDNS_STATUS_MEM_ERR; + + } else if (*limit == 0) + return LDNS_STATUS_ERR; p = 0; i = 0; com = 0; quoted = 0; prev_c = 0; - t = token; + t = *token; if (del[0] == '"') { quoted = 1; } @@ -79,7 +93,8 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li if (p < 0) { /* more ) then ( - close off the string */ *t = '\0'; - return 0; + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY + : LDNS_STATUS_OK; } /* do something with comments ; */ @@ -113,14 +128,27 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li continue; } - if (c == '\n' && p != 0 && t > token) { + if (c == '\n' && p != 0 && t > *token) { /* in parentheses */ if (line_nr) { *line_nr = *line_nr + 1; } - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { - *t = '\0'; - return -1; + if (*limit > 0 + && (i >= *limit || (size_t)(t - *token) >= *limit)) { + if (fixed) { + *t = '\0'; + return LDNS_STATUS_SYNTAX_ERR; + } + old_token = *token; + *limit *= 2; + *token = LDNS_XREALLOC(*token, char, *limit + 1); + if (*token == NULL) { + *token = old_token; + *t = '\0'; + return LDNS_STATUS_MEM_ERR; + } + if (*token != old_token) + t = *token + (t - old_token); } *t++ = ' '; prev_c = c; @@ -139,30 +167,42 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li if (c != '\0' && c != '\n') { i++; } - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { - *t = '\0'; - return -1; + if (*limit > 0 + && (i >= *limit || (size_t)(t - *token) >= *limit)) { + if (fixed) { + *t = '\0'; + return LDNS_STATUS_SYNTAX_ERR; + } + old_token = *token; + *limit *= 2; + *token = LDNS_XREALLOC(*token, char, *limit + 1); + if (*token == NULL) { + *token = old_token; + *t = '\0'; + return LDNS_STATUS_MEM_ERR; + } + if (*token != old_token) + t = *token + (t - old_token); } if (c != '\0' && c != '\n') { *t++ = c; } + if (c == '\n' && line_nr) { + *line_nr = *line_nr + 1; + } if (c == '\\' && prev_c == '\\') prev_c = 0; else prev_c = c; } *t = '\0'; if (c == EOF) { - return (ssize_t)i; + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK; } - if (i == 0) { - /* nothing read */ - return -1; - } if (p != 0) { - return -1; + return LDNS_STATUS_SYNTAX_ERR; } - return (ssize_t)i; + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK; tokenread: if(*del == '"') /* do not skip over quotes, they are significant */ @@ -170,10 +210,21 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li else ldns_fskipcs_l(f, del, line_nr); *t = '\0'; if (p != 0) { - return -1; + return LDNS_STATUS_SYNTAX_ERR; } + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK; +} - return (ssize_t)i; + +ssize_t +ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr) +{ + if (limit == 0) + limit = LDNS_MAX_LINELEN; + if (ldns_fget_token_l_st(f, &token, &limit, true, delim, line_nr)) + return -1; + else + return (ssize_t)strlen(token); } ssize_t @@ -223,7 +274,7 @@ ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) { int c, lc; - int p; /* 0 -> no parenthese seen, >0 nr of ( seen */ + int p; /* 0 -> no parentheses seen, >0 nr of ( seen */ int com, quoted; char *t; size_t i; diff --git a/contrib/ldns/rbtree.c b/contrib/ldns/rbtree.c index 01ae9c7042..d43081a1b5 100644 --- a/contrib/ldns/rbtree.c +++ b/contrib/ldns/rbtree.c @@ -71,7 +71,7 @@ static void ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node) static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent); /* - * Creates a new red black tree, intializes and returns a pointer to it. + * Creates a new red black tree, initializes and returns a pointer to it. * * Return NULL on failure. * diff --git a/contrib/ldns/rdata.c b/contrib/ldns/rdata.c index caf853d618..3f899a217e 100644 --- a/contrib/ldns/rdata.c +++ b/contrib/ldns/rdata.c @@ -363,6 +363,9 @@ ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str) case LDNS_RDF_TYPE_AMTRELAY: status = ldns_str2rdf_amtrelay(&rdf, str); break; + case LDNS_RDF_TYPE_SVCPARAMS: + status = ldns_str2rdf_svcparams(&rdf, str); + break; case LDNS_RDF_TYPE_NONE: default: /* default default ??? */ @@ -621,7 +624,7 @@ ldns_octet(char *word, size_t *length) return LDNS_STATUS_DDD_OVERFLOW; } } else { - /* an espaced character, like \ ? + /* an escaped character, like \ ? * remove the '\' keep the rest */ *p = *++s; (*length)++; diff --git a/contrib/ldns/resolver.c b/contrib/ldns/resolver.c index 84dfe95ba0..f9ec65a559 100644 --- a/contrib/ldns/resolver.c +++ b/contrib/ldns/resolver.c @@ -780,7 +780,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) if(!line_nr) line_nr = &lnr; if(!fp) { - myfp = fopen("/etc/resolv.conf", "r"); + myfp = fopen(LDNS_RESOLV_CONF, "r"); if(!myfp) return LDNS_STATUS_FILE_ERR; } diff --git a/contrib/ldns/rr.c b/contrib/ldns/rr.c index 6642aca775..95ab71d349 100644 --- a/contrib/ldns/rr.c +++ b/contrib/ldns/rr.c @@ -20,6 +20,12 @@ #define LDNS_TTL_DATALEN 21 #define LDNS_RRLIST_INIT 8 +#define _IS_WHITESPACE(chr) \ + ( NULL != strchr( LDNS_PARSE_NO_NL, chr) ) + +#define _BUFFER_IS_AT_WHITESPACE(rd_buf) \ + _IS_WHITESPACE(*(ldns_buffer_current(rd_buf))) + ldns_rr * ldns_rr_new(void) { @@ -111,8 +117,9 @@ ldns_rdf_type_maybe_quoted(ldns_rdf_type rdf_type) */ static ldns_status ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, - uint32_t default_ttl, const ldns_rdf *origin, - ldns_rdf **prev, bool question) + uint32_t default_ttl, const ldns_rdf *origin, + ldns_rdf **prev, bool question, + bool *explicit_ttl) { ldns_rr *new; const ldns_rr_descriptor *desc; @@ -198,6 +205,9 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, } else { ttl_val = default_ttl; } + if (explicit_ttl) + *explicit_ttl = false; + /* we not ASSUMING the TTL is missing and that * the rest of the RR is still there. That is * CLASS TYPE RDATA @@ -217,6 +227,9 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, strlcpy(type, ttl, type_sz); } } else { + if (explicit_ttl) + *explicit_ttl = true; + if (-1 == ldns_bget_token( rr_buf, clas, "\t\n ", LDNS_SYNTAX_DATALEN)) { @@ -259,7 +272,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, } ldns_buffer_new_frm_data(rd_buf, rdata, strlen(rdata)); - if (strlen(owner) <= 1 && strncmp(owner, "@", 1) == 0) { + if (strncmp(owner, "@", 1) == 0) { if (origin) { ldns_rr_set_owner(new, ldns_rdf_clone(origin)); } else if (prev && *prev) { @@ -347,11 +360,12 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, switch (ldns_rr_descriptor_field_type(desc, r_cnt)) { case LDNS_RDF_TYPE_B64 : case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */ - case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */ - case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */ + case LDNS_RDF_TYPE_NSEC : /* tain whitespace, only if */ + case LDNS_RDF_TYPE_LOC : /* it is the last rd field. */ + case LDNS_RDF_TYPE_WKS : case LDNS_RDF_TYPE_IPSECKEY : case LDNS_RDF_TYPE_AMTRELAY : - case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { + case LDNS_RDF_TYPE_SVCPARAMS : if (r_cnt == r_max - 1) { delimiters = "\n"; break; } @@ -364,16 +378,19 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, desc, r_cnt)) && ldns_buffer_remaining(rd_buf) > 0){ - /* skip spaces */ - while (*(ldns_buffer_current(rd_buf)) == ' ') { + /* skip whitespace */ + while (ldns_buffer_remaining(rd_buf) > 0 && + _BUFFER_IS_AT_WHITESPACE(rd_buf)) { ldns_buffer_skip(rd_buf, 1); } - if (*(ldns_buffer_current(rd_buf)) == '\"') { + if (ldns_buffer_remaining(rd_buf) > 0 && + *(ldns_buffer_current(rd_buf)) == '\"') { delimiters = "\"\0"; ldns_buffer_skip(rd_buf, 1); quoted = true; - } else if (ldns_rr_descriptor_field_type(desc, r_cnt) + } + if (!quoted && ldns_rr_descriptor_field_type(desc, r_cnt) == LDNS_RDF_TYPE_LONG_STR) { status = LDNS_STATUS_SYNTAX_RDATA_ERR; @@ -385,9 +402,9 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, * _maximum() only */ - /* skip spaces */ + /* skip whitespace */ while (ldns_buffer_position(rd_buf) < ldns_buffer_limit(rd_buf) - && *(ldns_buffer_current(rd_buf)) == ' ' + && _BUFFER_IS_AT_WHITESPACE(rd_buf) && !quoted) { ldns_buffer_skip(rd_buf, 1); @@ -409,7 +426,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, /* unknown RR data */ if (strncmp(rd, "\\#", 2) == 0 && !quoted && - (rd_strlen == 2 || rd[2]==' ')) { + (rd_strlen == 2 || _IS_WHITESPACE(rd[2]))) { was_unknown_rr_format = 1; /* go back to before \# @@ -579,10 +596,12 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, LDNS_RDF_TYPE_DNAME, ".") ); - } else if (r && rd_strlen >= 1 && origin && - !ldns_dname_str_absolute(rd)) { + } else if (r && rd_strlen >= 1 + && (origin || rr_type == LDNS_RR_TYPE_SOA) + && !ldns_dname_str_absolute(rd)) { - status = ldns_dname_cat(r, origin); + status = ldns_dname_cat(r, origin + ? origin : ldns_rr_owner(new)); if (status != LDNS_STATUS_OK) { goto error; } @@ -600,14 +619,6 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, } ldns_rr_push_rdf(new, r); } - if (quoted) { - if (ldns_buffer_available(rd_buf, 1)) { - ldns_buffer_skip(rd_buf, 1); - } else { - done = true; - } - } - } /* for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) */ LDNS_FREE(rd); LDNS_FREE(xtok); @@ -671,7 +682,8 @@ ldns_rr_new_frm_str(ldns_rr **newrr, const char *str, default_ttl, origin, prev, - false); + false, + NULL); } ldns_status @@ -683,7 +695,8 @@ ldns_rr_new_question_frm_str(ldns_rr **newrr, const char *str, 0, origin, prev, - true); + true, + NULL); } /* Strip whitespace from the start and the end of . */ @@ -709,43 +722,28 @@ ldns_rr_new_frm_fp(ldns_rr **newrr, FILE *fp, uint32_t *ttl, ldns_rdf **origin, } ldns_status -ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr) +_ldns_rr_new_frm_fp_l_internal(ldns_rr **newrr, FILE *fp, + uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, + int *line_nr, bool *explicit_ttl) { - char *line; + char *line = NULL; + size_t limit = 0; const char *endptr; /* unused */ ldns_rr *rr; uint32_t ttl; ldns_rdf *tmp; ldns_status s; - ssize_t size; if (default_ttl) { ttl = *default_ttl; } else { ttl = 0; } - - line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); - if (!line) { - return LDNS_STATUS_MEM_ERR; - } - /* read an entire line in from the file */ - if ((size = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, LDNS_MAX_LINELEN, line_nr)) == -1) { - LDNS_FREE(line); - /* if last line was empty, we are now at feof, which is not - * always a parse error (happens when for instance last line - * was a comment) - */ - return LDNS_STATUS_SYNTAX_ERR; - } - - /* we can have the situation, where we've read ok, but still got - * no bytes to play with, in this case size is 0 - */ - if (size == 0) { + if ((s = ldns_fget_token_l_st( fp, &line, &limit, false + , LDNS_PARSE_SKIP_SPACE, line_nr))) { LDNS_FREE(line); - return LDNS_STATUS_SYNTAX_EMPTY; + return s; } if (strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { @@ -775,9 +773,11 @@ ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf return LDNS_STATUS_SYNTAX_EMPTY; } else { if (origin && *origin) { - s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, *origin, prev); + s = ldns_rr_new_frm_str_internal(&rr, (const char*)line, + ttl, *origin, prev, false, explicit_ttl); } else { - s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, NULL, prev); + s = ldns_rr_new_frm_str_internal(&rr, (const char*)line, + ttl, NULL, prev, false, explicit_ttl); } } LDNS_FREE(line); @@ -792,6 +792,14 @@ ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf return s; } +ldns_status +ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, + ldns_rdf **origin, ldns_rdf **prev, int *line_nr) +{ + return _ldns_rr_new_frm_fp_l_internal(newrr, fp, default_ttl, origin, + prev, line_nr, NULL); +} + void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner) { @@ -836,7 +844,7 @@ ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position) rd_count = ldns_rr_rd_count(rr); if (position < rd_count) { - /* dicard the old one */ + /* discard the old one */ pop = rr->_rdata_fields[position]; rr->_rdata_fields[position] = (ldns_rdf*)f; return pop; @@ -1190,6 +1198,7 @@ ldns_rr_list_pop_rr(ldns_rr_list *rr_list) rr_list->_rrs = a; rr_list->_rr_capacity = cap; } + /* if the realloc fails, the capacity for the list remains unchanged */ } ldns_rr_list_set_rr_count(rr_list, rr_count - 1); @@ -1317,7 +1326,7 @@ ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr) return false; } /* ok, still alive - check if the rr already - * exists - if so, dont' add it */ + * exists - if so, don't add it */ for(i = 0; i < rr_count; i++) { if(ldns_rr_compare( ldns_rr_list_rr(rr_list, i), rr) == 0) { @@ -1968,7 +1977,13 @@ static const ldns_rdf_type type_zonemd_wireformat[] = { LDNS_RDF_TYPE_INT32, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX }; - +#ifdef RRTYPE_SVCB_HTTPS +static const ldns_rdf_type type_svcb_wireformat[] = { + LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_DNAME, + LDNS_RDF_TYPE_SVCPARAMS +}; +#endif /* nsec3 is some vars, followed by same type of data of nsec */ static const ldns_rdf_type type_nsec3_wireformat[] = { /* LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/ @@ -2215,11 +2230,20 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { #else {LDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, #endif + /* 62 */ + {LDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 63 */ + {LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#ifdef RRTYPE_SVCB_HTTPS + /* 64 */ + {LDNS_RR_TYPE_SVCB, "SVCB", 2, 3, type_svcb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 65 */ + {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 3, type_svcb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, -{LDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#else {LDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#endif {LDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, @@ -2489,7 +2513,7 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { /*---------------------------------------------------------------------------* * The functions below return an bitmap RDF with the space required to set * or unset all known RR types. Arguably these functions are better situated - * in rdata.c, however for the space calculation it is necesarry to walk + * in rdata.c, however for the space calculation it is necessary to walk * through rdata_field_descriptors which is not easily possible from anywhere * other than rr.c where it is declared static. * diff --git a/contrib/ldns/rr_functions.c b/contrib/ldns/rr_functions.c index 20a0bfaa1a..b9b9eae5be 100644 --- a/contrib/ldns/rr_functions.c +++ b/contrib/ldns/rr_functions.c @@ -24,7 +24,7 @@ * return a specific rdf * \param[in] type type of RR * \param[in] rr the rr itself - * \param[in] pos at which postion to get it + * \param[in] pos at which position to get it * \return the rdf sought */ static ldns_rdf * @@ -41,7 +41,7 @@ ldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos) * \param[in] type type of RR * \param[in] rr the rr itself * \param[in] rdf the rdf to set - * \param[in] pos at which postion to set it + * \param[in] pos at which position to set it * \return true or false */ static bool @@ -269,14 +269,17 @@ ldns_rr_dnskey_key_size_raw(const unsigned char* keydata, const size_t len, const ldns_algorithm alg) { +#ifdef USE_DSA /* for DSA keys */ uint8_t t; +#endif /* USE_DSA */ /* for RSA keys */ uint16_t exp; uint16_t int16; switch ((ldns_signing_algorithm)alg) { +#ifdef USE_DSA case LDNS_SIGN_DSA: case LDNS_SIGN_DSA_NSEC3: if (len > 0) { @@ -286,6 +289,7 @@ ldns_rr_dnskey_key_size_raw(const unsigned char* keydata, return 0; } break; +#endif /* USE_DSA */ case LDNS_SIGN_RSAMD5: case LDNS_SIGN_RSASHA1: case LDNS_SIGN_RSASHA1_NSEC3: diff --git a/contrib/ldns/sha1.c b/contrib/ldns/sha1.c index 96e8f96830..9b7e60ece0 100644 --- a/contrib/ldns/sha1.c +++ b/contrib/ldns/sha1.c @@ -168,7 +168,7 @@ ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *co } unsigned char * -ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest) +ldns_sha1(const unsigned char *data, unsigned int data_len, unsigned char *digest) { ldns_sha1_ctx ctx; ldns_sha1_init(&ctx); diff --git a/contrib/ldns/sha2.c b/contrib/ldns/sha2.c index e0b1f4b911..8988ee06d0 100644 --- a/contrib/ldns/sha2.c +++ b/contrib/ldns/sha2.c @@ -73,7 +73,7 @@ * Please make sure that your system defines BYTE_ORDER. If your * architecture is little-endian, make sure it also defines * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are - * equivilent. + * equivalent. * * If your system does not define the above, then you can do so by * hand like this: @@ -554,7 +554,7 @@ typedef union _ldns_sha2_buffer_union { uint64_t* theLongs; } ldns_sha2_buffer_union; -void ldns_sha256_final(sha2_byte digest[], ldns_sha256_CTX* context) { +void ldns_sha256_final(sha2_byte digest[LDNS_SHA256_DIGEST_LENGTH], ldns_sha256_CTX* context) { sha2_word32 *d = (sha2_word32*)digest; size_t usedspace; ldns_sha2_buffer_union cast_var; @@ -621,7 +621,7 @@ void ldns_sha256_final(sha2_byte digest[], ldns_sha256_CTX* context) { } unsigned char * -ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest) +ldns_sha256(const unsigned char *data, unsigned int data_len, unsigned char *digest) { ldns_sha256_CTX ctx; ldns_sha256_init(&ctx); @@ -905,7 +905,7 @@ static void ldns_sha512_Last(ldns_sha512_CTX* context) { ldns_sha512_Transform(context, (sha2_word64*)context->buffer); } -void ldns_sha512_final(sha2_byte digest[], ldns_sha512_CTX* context) { +void ldns_sha512_final(sha2_byte digest[LDNS_SHA512_DIGEST_LENGTH], ldns_sha512_CTX* context) { sha2_word64 *d = (sha2_word64*)digest; /* Sanity check: */ @@ -935,7 +935,7 @@ void ldns_sha512_final(sha2_byte digest[], ldns_sha512_CTX* context) { } unsigned char * -ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest) +ldns_sha512(const unsigned char *data, unsigned int data_len, unsigned char *digest) { ldns_sha512_CTX ctx; ldns_sha512_init(&ctx); @@ -958,7 +958,7 @@ void ldns_sha384_update(ldns_sha384_CTX* context, const sha2_byte* data, size_t ldns_sha512_update((ldns_sha512_CTX*)context, data, len); } -void ldns_sha384_final(sha2_byte digest[], ldns_sha384_CTX* context) { +void ldns_sha384_final(sha2_byte digest[LDNS_SHA384_DIGEST_LENGTH], ldns_sha384_CTX* context) { sha2_word64 *d = (sha2_word64*)digest; /* Sanity check: */ @@ -988,7 +988,7 @@ void ldns_sha384_final(sha2_byte digest[], ldns_sha384_CTX* context) { } unsigned char * -ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest) +ldns_sha384(const unsigned char *data, unsigned int data_len, unsigned char *digest) { ldns_sha384_CTX ctx; ldns_sha384_init(&ctx); diff --git a/contrib/ldns/str2host.c b/contrib/ldns/str2host.c index 0bf62d106e..5b78e5bc59 100644 --- a/contrib/ldns/str2host.c +++ b/contrib/ldns/str2host.c @@ -304,7 +304,7 @@ parse_char(uint8_t *ch_p, const char** str_p) /* * No special care is taken, all dots are translated into - * label seperators. + * label separators. * Could be made more efficient....we do 3 memcpy's in total... */ ldns_status @@ -344,7 +344,7 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str) pq = buf; label_len = 0; for (s = str; *s; s++, q++) { - if (q > buf + LDNS_MAX_DOMAINLEN) { + if (q >= buf + LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } *q = 0; @@ -378,7 +378,7 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str) /* add root label if last char was not '.' */ if (!ldns_dname_str_absolute(str)) { - if (q > buf + LDNS_MAX_DOMAINLEN) { + if (q >= buf + LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } if (label_len > LDNS_MAX_LABELLEN) { @@ -879,13 +879,16 @@ loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) /* read [.][mM] */ /* into mantissa exponent format for LOC type */ uint32_t meters = 0, cm = 0, val; + char* cm_endstr; while (isblank((unsigned char)*my_str)) { my_str++; } meters = (uint32_t)strtol(my_str, &my_str, 10); if (*my_str == '.') { my_str++; - cm = (uint32_t)strtol(my_str, &my_str, 10); + cm = (uint32_t)strtol(my_str, &cm_endstr, 10); + if (cm_endstr - my_str == 1) cm *= 10; + my_str = cm_endstr; } if (meters >= 1) { *e = 2; @@ -926,8 +929,8 @@ ldns_str2rdf_loc(ldns_rdf **rd, const char *str) uint8_t vert_pre_b = 1, vert_pre_e = 3; double s = 0.0; - bool northerness; - bool easterness; + bool northern_hemisphere; + bool eastern_hemisphere; char *my_str = (char *) str; @@ -963,9 +966,9 @@ ldns_str2rdf_loc(ldns_rdf **rd, const char *str) } if (*my_str == 'N') { - northerness = true; + northern_hemisphere = true; } else if (*my_str == 'S') { - northerness = false; + northern_hemisphere = false; } else { return LDNS_STATUS_INVALID_STR; } @@ -979,7 +982,7 @@ ldns_str2rdf_loc(ldns_rdf **rd, const char *str) latitude = (uint32_t) s; latitude += 1000 * 60 * m; latitude += 1000 * 60 * 60 * h; - if (northerness) { + if (northern_hemisphere) { latitude = equator + latitude; } else { latitude = equator - latitude; @@ -1020,9 +1023,9 @@ ldns_str2rdf_loc(ldns_rdf **rd, const char *str) } if (*my_str == 'E') { - easterness = true; + eastern_hemisphere = true; } else if (*my_str == 'W') { - easterness = false; + eastern_hemisphere = false; } else { return LDNS_STATUS_INVALID_STR; } @@ -1037,7 +1040,7 @@ ldns_str2rdf_loc(ldns_rdf **rd, const char *str) longitude += 1000 * 60 * m; longitude += 1000 * 60 * 60 * h; - if (easterness) { + if (eastern_hemisphere) { longitude += equator; } else { longitude = equator - longitude; @@ -1415,8 +1418,8 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) LDNS_FREE(publickey); LDNS_FREE(token); ldns_buffer_free(str_buf); - ldns_rdf_free(gateway_rdf); - ldns_rdf_free(publickey_rdf); + ldns_rdf_deep_free(gateway_rdf); + ldns_rdf_deep_free(publickey_rdf); LDNS_FREE(data); if(!*rd) return LDNS_STATUS_MEM_ERR; return LDNS_STATUS_OK; @@ -1547,16 +1550,19 @@ ldns_str2rdf_long_str(ldns_rdf **rd, const char *str) return LDNS_STATUS_SYNTAX_BAD_ESCAPE; } if (!(length = (size_t)(dp - data))) { + /* An empty string is a data buffer of 0 bytes. The rdf for + * this long string has to have length 0 and point to NULL. + */ LDNS_FREE(data); - return LDNS_STATUS_SYNTAX_EMPTY; - } - /* Lose the overmeasure */ - data = LDNS_XREALLOC(dp = data, uint8_t, length); - if (! data) { - LDNS_FREE(dp); - return LDNS_STATUS_MEM_ERR; + data = NULL; + } else { + /* Lose the overmeasure */ + data = LDNS_XREALLOC(dp = data, uint8_t, length); + if (! data) { + LDNS_FREE(dp); + return LDNS_STATUS_MEM_ERR; + } } - /* Create rdf */ *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data); if (! *rd) { @@ -1800,3 +1806,632 @@ ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str) if(!*rd) return LDNS_STATUS_MEM_ERR; return LDNS_STATUS_OK; } + +#ifdef RRTYPE_SVCB_HTTPS +static int +network_uint16_cmp(const void *a, const void *b) +{ + return ((int)ldns_read_uint16(a)) - ((int)ldns_read_uint16(b)); +} + +static ldns_status parse_svcparam_key(const char **s, ldns_svcparam_key *key); +static ldns_status +parse_svcparam_mandatory(const char **s, uint8_t **dp, uint8_t *eod) +{ + bool quoted = false; + uint8_t *keys = *dp; + int prev_key; + + if (**s == '"') { + *s += 1; + quoted = true; + } + for (;;) { + ldns_status st; + ldns_svcparam_key key; + + if ((st = parse_svcparam_key(s, &key))) + return st; + + if (*dp + 2 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + ldns_write_uint16(*dp, key); + *dp += 2; + + if (**s == ',') + *s += 1; + else + break; + } + if (quoted) { + if (**s != '"') + return LDNS_STATUS_INVALID_STR; + *s += 1; + } + if (*dp - keys == 0) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + if (**s && !isspace((unsigned char)**s)) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + /* In draft-ietf-dnsop-svcb-https-02 Section 7: + * + * In wire format, the keys are represented by their numeric + * values in network byte order, concatenated in ascending order. + */ + qsort(keys, (*dp - keys) / 2, 2, network_uint16_cmp); + + /* In draft-ietf-dnsop-svcb-https-02 Section 7: + * + * Keys ...... MUST NOT appear more than once. + */ + prev_key = -1; + while (keys < *dp) { + uint16_t key = ldns_read_uint16(keys); + + if (key == prev_key) { + /* "Be conservative in what you send, + * be liberal in what you accept" + * + * Instead of + * `return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE;`, + * + * we eliminate the double occurrence. + */ + memmove(keys - 2, keys, *dp - keys); + *dp -= 2; + } else { + prev_key = key; + keys += 2; + } + } + return LDNS_STATUS_OK; +} + +INLINE bool parse_escape2(uint8_t *ch_p, const char** str_p) +{ *str_p += 1; return parse_escape(ch_p, str_p); } + +static ldns_status +parse_svcparam_alpn(const char **s, uint8_t **dp, uint8_t *eod) +{ + uint8_t *val; + size_t len; + + if (*dp + 1 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + *dp += 1; + val = *dp; + if (**s == '"') { + *s += 1; + while (**s != '"') { + if (**s == 0) + return LDNS_STATUS_INVALID_STR; + + else if (**s == ',') { + len = *dp - val; + if (len == 0 || len > 255) + return LDNS_STATUS_INVALID_STR; + val[-1] = len; + if (*dp + 1 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + *dp += 1; + val = *dp; + *s += 1; + + } else if (*dp + 1 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + else if (**s != '\\') + *(*dp)++ = (uint8_t)*(*s)++; + + else if (!parse_escape2(*dp, s)) + return LDNS_STATUS_SYNTAX_BAD_ESCAPE; + else + *dp += 1; + } + *s += 1; + + } else while (**s && !isspace((unsigned char)**s)) { + if (**s == ',') { + len = *dp - val; + if (len == 0 || len > 255) + return LDNS_STATUS_INVALID_STR; + val[-1] = len; + if (*dp + 1 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + *dp += 1; + val = *dp; + *s += 1; + + } else if (*dp + 1 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + else if (**s != '\\') + *(*dp)++ = (uint8_t)*(*s)++; + + else if (!parse_escape2(*dp, s)) + return LDNS_STATUS_SYNTAX_BAD_ESCAPE; + else + *dp += 1; + } + len = *dp - val; + if (len == 0 || len > 255) + return LDNS_STATUS_INVALID_STR; + val[-1] = len; + return **s && !isspace((unsigned char)**s) + ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR + : LDNS_STATUS_OK; +} + +static ldns_status +parse_svcparam_value(const char **s, uint8_t **dp, uint8_t *eod) +{ + if (**s == '"') { + *s += 1; + while (**s != '"') { + if (**s == 0) + return LDNS_STATUS_INVALID_STR; + + else if (*dp + 1 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + else if (**s != '\\') + *(*dp)++ = (uint8_t)*(*s)++; + + else if (!parse_escape2(*dp, s)) + return LDNS_STATUS_SYNTAX_BAD_ESCAPE; + else + *dp += 1; + } + *s += 1; + + } else while (**s && !isspace((unsigned char)**s)) { + if (*dp + 1 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + else if (**s != '\\') + *(*dp)++ = (uint8_t)*(*s)++; + + else if (!parse_escape2(*dp, s)) + return LDNS_STATUS_SYNTAX_BAD_ESCAPE; + else + *dp += 1; + } + return **s && !isspace((unsigned char)**s) + ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR + : LDNS_STATUS_OK; +} + +static ldns_status +parse_svcparam_port(const char **s, uint8_t **dp, uint8_t *eod) +{ + uint8_t *val = *dp; + ldns_status st; + size_t len; + char num_str[6]; + char *endptr; + unsigned long int num; + + if ((st = parse_svcparam_value(s, dp, eod))) + return st; + len = *dp - val; + if (len == 0 || len > 5) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + memcpy(num_str, val, len); + num_str[len] = 0; + num = strtoul(num_str, &endptr, 10); + if (*endptr) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + ldns_write_uint16(val, num); + *dp = val + 2; + return LDNS_STATUS_OK; +} + +static ldns_status +parse_svcparam_ipv4hint(const char **s, uint8_t **dp, uint8_t *eod) +{ + bool quoted = false; + + if (**s == '"') { + *s += 1; + quoted = true; + } + for (;;) { + const char *ipv4_start = *s; + char ipv4_str[16]; + size_t len; + + while (isdigit((unsigned char)**s) || **s == '.') + *s += 1; + + len = *s - ipv4_start; + if (len == 0 || len > 15) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + if (*dp + 4 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + memcpy(ipv4_str, ipv4_start, len); + ipv4_str[len] = 0; + if (inet_pton(AF_INET, ipv4_str, *dp) != 1) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + *dp += 4; + if (**s == ',') + *s += 1; + else + break; + } + if (quoted) { + if (**s != '"') + return LDNS_STATUS_INVALID_STR; + *s += 1; + } + return **s && !isspace((unsigned char)**s) + ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR + : LDNS_STATUS_OK; +} + +static ldns_status +parse_svcparam_ech(const char **s, uint8_t **dp, uint8_t *eod) +{ + bool quoted = false; + const char *b64_str; + size_t len, pad, out_len; + char in_buf[4096]; + char *in = in_buf; + int out; + + if (**s == '"') { + *s += 1; + quoted = true; + } + b64_str = *s; + while (isalnum((unsigned char)**s) || **s == '+' + || **s == '/' + || **s == '=') + *s += 1; + + len = *s - b64_str; + pad = len % 4; + pad = pad ? 4 - pad : 0; + if (len == 0 || pad == 3) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + if (quoted) { + if (**s != '"') + return LDNS_STATUS_INVALID_STR; + *s += 1; + } + if (**s && !isspace((unsigned char)**s)) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + out_len = ldns_b64_pton_calculate_size(len); + if (*dp + out_len > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + if (len + pad > sizeof(in_buf) - 1 + && !(in = LDNS_XMALLOC(char, len + pad + 1))) + return LDNS_STATUS_MEM_ERR; + + memcpy(in, b64_str, len); + while (pad--) + in[len++] = '='; + in[len] = 0; + out = ldns_b64_pton(in, *dp, out_len); + if (in != in_buf) + LDNS_FREE(in); + + if (out <= 0) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + *dp += out; + return LDNS_STATUS_OK; +} + +static ldns_status +parse_svcparam_ipv6hint(const char **s, uint8_t **dp, uint8_t *eod) +{ + bool quoted = false; + + if (**s == '"') { + *s += 1; + quoted = true; + } + for (;;) { + const char *ipv6_start = *s; + char ipv6_str[INET6_ADDRSTRLEN]; + size_t len; + + while (isxdigit((unsigned char)**s) || **s == ':' || **s == '.') + *s += 1; + + len = *s - ipv6_start; + if (len == 0 || len > INET6_ADDRSTRLEN) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + if (*dp + 16 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + memcpy(ipv6_str, ipv6_start, len); + ipv6_str[len] = 0; + if (inet_pton(AF_INET6, ipv6_str, *dp) != 1) + return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; + + *dp += 16; + if (**s == ',') + *s += 1; + else + break; + } + if (quoted) { + if (**s != '"') + return LDNS_STATUS_INVALID_STR; + *s += 1; + } + return **s && !isspace((unsigned char)**s) + ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR + : LDNS_STATUS_OK; +} + +struct struct_svcparam_key_def { + const char *str; + size_t len; +}; +typedef struct struct_svcparam_key_def svcparam_key_def; + +static svcparam_key_def svcparam_key_defs[] = { { "mandatory" , 9 } + , { "alpn" , 4 } + , { "no-default-alpn", 15 } + , { "port" , 4 } + , { "ipv4hint" , 8 } + , { "ech" , 3 } + , { "ipv6hint" , 8 } + , { "dohpath" , 7 } }; + +static const size_t svcparam_key_defs_len = sizeof(svcparam_key_defs) + / sizeof(svcparam_key_def); + +/* svcparam_key2buffer_str() should actually be in host2str.c, but we need the + * svcparam_key_defs for it and it is not an exposed symbol anyway. + */ +ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key) +{ + if (key <= LDNS_SVCPARAM_KEY_LAST_KEY) + ldns_buffer_write_string(output, svcparam_key_defs[key].str); + else + ldns_buffer_printf(output, "key%d", (int)key); + return ldns_buffer_status(output); +} + +static ldns_status +parse_svcparam_key(const char **s, ldns_svcparam_key *key) +{ + size_t i, len; + const char *key_str = *s; + char num_str[6]; + char *endptr; + unsigned long int num; + + /* parse key */ + while (islower((unsigned char)**s) || isdigit((unsigned char)**s) + || **s == '-') + *s += 1; + + len = *s - key_str; + for (i = 0; i < svcparam_key_defs_len; i++) { + if (len == svcparam_key_defs[i].len + && !strncmp(key_str, svcparam_key_defs[i].str, len)) { + *key = i; + return LDNS_STATUS_OK; + } + } + /* Also allow "echconfig" from earlier draft versions. */ + if (len == 9 && !strncmp(key_str, "echconfig", 9)) { + *key = LDNS_SVCPARAM_KEY_ECH; + return LDNS_STATUS_OK; + } + if (len < 4 || len > 8 || strncmp(key_str, "key", 3)) + return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR; + + memcpy(num_str, key_str + 3, len - 3); + num_str[len - 3] = 0; + num = strtoul(num_str, &endptr, 10); + if (*endptr || num > 65535) + return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR; + + /* key65535 is Reserved to be an ("Invalid key"), though there is no + * physiological reason to deny usage. We restrict ourselves to the + * anatomical limitations only to maximize serviceability. + * ``` + * if (num == 65535) + * return LDNS_STATUS_RESERVED_SVCPARAM_KEY; + * ``` + */ + *key = num; + return LDNS_STATUS_OK; +} + +static ldns_status +parse_svcparam(const char **s, uint8_t **dp, uint8_t *eod) +{ + ldns_svcparam_key key; + ldns_status st; + uint8_t *val; + + if (*dp + 4 > eod) + return LDNS_STATUS_RDATA_OVERFLOW; + + if ((st = parse_svcparam_key(s, &key))) + return st; + + ldns_write_uint16(*dp, key); + ldns_write_uint16(*dp + 2, 0); + *dp += 4; + if (isspace((unsigned char)**s) || !**s) + return LDNS_STATUS_OK; + + else if (**s != '=') + return LDNS_STATUS_SYNTAX_ERR; + *s += 1; + val = *dp; + switch(key) { + case LDNS_SVCPARAM_KEY_MANDATORY: + st = parse_svcparam_mandatory(s, dp, eod); + break; + case LDNS_SVCPARAM_KEY_ALPN: + st = parse_svcparam_alpn(s, dp, eod); + break; + case LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN: + return LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED; + case LDNS_SVCPARAM_KEY_PORT: + st = parse_svcparam_port(s, dp, eod); + break; + case LDNS_SVCPARAM_KEY_IPV4HINT: + st = parse_svcparam_ipv4hint(s, dp, eod); + break; + case LDNS_SVCPARAM_KEY_ECH: + st = parse_svcparam_ech(s, dp, eod); + break; + case LDNS_SVCPARAM_KEY_IPV6HINT: + st = parse_svcparam_ipv6hint(s, dp, eod); + break; + default: + st = parse_svcparam_value(s, dp, eod); + break; + } + if (st) + return st; + ldns_write_uint16(val - 2, *dp - val); + return LDNS_STATUS_OK; +} + +static int +svcparam_ptr_cmp(const void *a, const void *b) +{ + uint8_t *x = *(uint8_t **)a , *y = *(uint8_t **)b; + uint16_t x_type = ldns_read_uint16(x), y_type = ldns_read_uint16(y); + uint16_t x_len , y_len; + + if (x_type != y_type) + return x_type > y_type ? 1 : -1; + + x_len = ldns_read_uint16(x + 2); + y_len = ldns_read_uint16(y + 2); + + return x_len != y_len + ? (x_len > y_len ? 1 : -1) + : (x_len == 0 ? 0 : memcmp(x + 4, y + 4, x_len)); +} + +ldns_status +ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str) +{ + uint8_t *data, *dp, *eod, *p, *new_data; + ldns_status st = LDNS_STATUS_OK; + size_t length, i; + size_t nparams = 0; + uint8_t **svcparams; + int prev_key; + + if (!rd || !str) + return LDNS_STATUS_NULL; + + length = strlen(str); + /* Worst case space requirement. We'll realloc to actual size later. */ + if (!(dp = data = LDNS_XMALLOC(uint8_t, length * 4))) + return LDNS_STATUS_MEM_ERR; + eod = data + length * 4; + + /* Fill data with parsed bytes */ + for (;;) { + while (isspace((unsigned char)*str)) + str += 1; + if(!*str) + break; + if ((st = parse_svcparam(&str, &dp, eod))) { + LDNS_FREE(data); + return st; + } + nparams += 1; + } + + /* draft-ietf-dnsop-svcb-https-02 in Section 2.2: + * + * SvcParamKeys SHALL appear in increasing numeric order + * + * A svcparams array (with pointers to the individual key, value pairs) + * is created to qsort the pairs in increasing numeric order. + */ + if (!(svcparams = LDNS_XMALLOC(uint8_t *, nparams))) { + LDNS_FREE(data); + return LDNS_STATUS_MEM_ERR; + } + for ( p = data, i = 0 + ; p < dp && i < nparams + ; p += 4 + ldns_read_uint16(p + 2)) + svcparams[i++] = p; + + qsort(svcparams, i, sizeof(uint8_t *), svcparam_ptr_cmp); + + /* Write out the (key, value) pairs to a newly allocated data in + * sorted order. + */ + length = dp - data; + if (!(new_data = LDNS_XMALLOC(uint8_t, length))) { + LDNS_FREE(data); + LDNS_FREE(svcparams); + return LDNS_STATUS_MEM_ERR; + } + prev_key = -1; + for ( p = new_data, i = 0 + ; p < new_data + length && i < nparams + ; p += 4 + ldns_read_uint16(p + 2), i += 1) { + uint16_t key = ldns_read_uint16(svcparams[i]); + + /* In draft-ietf-dnsop-svcb-https-02 Section 2.1: + * + * SvcParams ...... keys MUST NOT be repeated. + * + * ldns will not impose this limitation on the library user, + * but we can merge completely equal repetitions into one. + * So, not doing + * ``` + * if (key == prev_key) + * return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE; + * ``` + * but instead: + */ + if (key == prev_key && ldns_read_uint16(svcparams[i] + 2) + == ldns_read_uint16(svcparams[i - 1] + 2) + && 0 == memcmp( svcparams[i ] + 4 + , svcparams[i - 1] + 4 + , ldns_read_uint16(svcparams[i] + 2))) { + p -= 4 + ldns_read_uint16(svcparams[i] + 2); + continue; + } + memcpy(p, svcparams[i], 4 + ldns_read_uint16(svcparams[i] + 2)); + prev_key = key; + } + LDNS_FREE(data); + LDNS_FREE(svcparams); + + /* Create rdf */ + *rd = ldns_rdf_new(LDNS_RDF_TYPE_SVCPARAMS, p - new_data, new_data); + if (! *rd) { + LDNS_FREE(new_data); + return LDNS_STATUS_MEM_ERR; + } + return LDNS_STATUS_OK; +} +#else /* #ifdef RRTYPE_SVCB_HTTPS */ +ldns_status +ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str) +{ + (void)rd; (void)str; + return LDNS_STATUS_NOT_IMPL; +} +#endif /* #ifdef RRTYPE_SVCB_HTTPS */ diff --git a/contrib/ldns/tsig.c b/contrib/ldns/tsig.c index 458861a15b..26a1e73f1d 100644 --- a/contrib/ldns/tsig.c +++ b/contrib/ldns/tsig.c @@ -196,7 +196,7 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, const uint8_t *pkt_wire, size_t pkt_wire_ return LDNS_STATUS_MEM_ERR; } /* - * prepare the digestable information + * prepare the digestible information */ data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (!data_buffer) { @@ -354,7 +354,13 @@ ldns_pkt_tsig_verify_next(ldns_pkt *pkt, const uint8_t *wire, size_t wirelen, co return false; } /* use time insensitive memory compare */ - if(CRYPTO_memcmp(ldns_rdf_data(pkt_mac_rdf), ldns_rdf_data(my_mac_rdf), + if( +#ifdef HAVE_CRYPTO_MEMCMP + CRYPTO_memcmp +#else + memcmp +#endif + (ldns_rdf_data(pkt_mac_rdf), ldns_rdf_data(my_mac_rdf), ldns_rdf_size(my_mac_rdf)) == 0) { ldns_rdf_deep_free(my_mac_rdf); return true; diff --git a/contrib/ldns/util.c b/contrib/ldns/util.c index 1216134f96..807a99e230 100644 --- a/contrib/ldns/util.c +++ b/contrib/ldns/util.c @@ -293,25 +293,35 @@ ldns_gmtime64_r(int64_t clock, struct tm *result) #endif /* SIZEOF_TIME_T <= 4 */ static int64_t -ldns_serial_arithmitics_time(int32_t time, time_t now) +ldns_serial_arithmetics_time(int32_t time, time_t now) { - int32_t offset = time - (int32_t) now; + /* Casting due to https://github.com/NLnetLabs/ldns/issues/71 */ + int32_t offset = (int32_t) ((uint32_t) time - (uint32_t) now); return (int64_t) now + offset; } - struct tm * -ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) +ldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result) { #if SIZEOF_TIME_T <= 4 - int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); + int64_t secs_since_epoch = ldns_serial_arithmetics_time(time, now); return ldns_gmtime64_r(secs_since_epoch, result); #else - time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); + time_t secs_since_epoch = ldns_serial_arithmetics_time(time, now); return gmtime_r(&secs_since_epoch, result); #endif } +#ifdef ldns_serial_arithmitics_gmtime_r +#undef ldns_serial_arithmitics_gmtime_r +#endif +/* alias function because of previously used wrong spelling */ +struct tm * +ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) +{ + return ldns_serial_arithmetics_gmtime_r(time, now, result); +} + /** * Init the random source * applications should call this if they need entropy data within ldns @@ -377,7 +387,7 @@ ldns_init_random(FILE *fd, unsigned int size) RAND_seed(seed, (int) size); #else /* Seed the standard prng, only uses the first - * unsigned sizeof(unsiged int) bytes found in the entropy pool + * unsigned sizeof(unsigned int) bytes found in the entropy pool */ memcpy(&seed_i, seed, sizeof(seed_i)); srandom(seed_i); diff --git a/contrib/ldns/wire2host.c b/contrib/ldns/wire2host.c index 1473a9478d..63b67a0d17 100644 --- a/contrib/ldns/wire2host.c +++ b/contrib/ldns/wire2host.c @@ -273,6 +273,7 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos) case LDNS_RDF_TYPE_IPSECKEY: case LDNS_RDF_TYPE_LONG_STR: case LDNS_RDF_TYPE_AMTRELAY: + case LDNS_RDF_TYPE_SVCPARAMS: case LDNS_RDF_TYPE_NONE: /* * Read to end of rr rdata @@ -310,7 +311,6 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos) return LDNS_STATUS_OK; } - /* TODO: can *pos be incremented at READ_INT? or maybe use something like RR_CLASS(wire)? diff --git a/contrib/ldns/zone.c b/contrib/ldns/zone.c index e952074823..9a5d4c4e9e 100644 --- a/contrib/ldns/zone.c +++ b/contrib/ldns/zone.c @@ -180,7 +180,7 @@ ldns_zone_new(void) return z; } -/* we regocnize: +/* we recognize: * $TTL, $ORIGIN */ ldns_status @@ -189,19 +189,28 @@ ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t t return ldns_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); } +ldns_status _ldns_rr_new_frm_fp_l_internal(ldns_rr **newrr, FILE *fp, + uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, + int *line_nr, bool *explicit_ttl); + /* XXX: class is never used */ ldns_status -ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t ttl, - ldns_rr_class ATTR_UNUSED(c), int *line_nr) +ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, const ldns_rdf *origin, + uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int *line_nr) { ldns_zone *newzone; - ldns_rr *rr; + ldns_rr *rr, *prev_rr = NULL; uint32_t my_ttl; ldns_rdf *my_origin; ldns_rdf *my_prev; bool soa_seen = false; /* 2 soa are an error */ ldns_status s; ldns_status ret; + /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default + * to the last explicitly stated values.' + */ + bool ttl_from_TTL = false; + bool explicit_ttl = false; /* most cases of error are memory problems */ ret = LDNS_STATUS_MEM_ERR; @@ -210,7 +219,7 @@ ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t my_origin = NULL; my_prev = NULL; - my_ttl = ttl; + my_ttl = default_ttl; if (origin) { my_origin = ldns_rdf_clone(origin); @@ -224,9 +233,58 @@ ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t if (!newzone) goto error; while(!feof(fp)) { - s = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, &my_prev, line_nr); + /* If ttl came from $TTL line, then it should be the default. + * (RFC 2308 Section 4) + * Otherwise it "defaults to the last explicitly stated value" + * (RFC 1035 Section 5.1) + */ + if (ttl_from_TTL) + my_ttl = default_ttl; + s = _ldns_rr_new_frm_fp_l_internal(&rr, fp, &my_ttl, &my_origin, + &my_prev, line_nr, &explicit_ttl); switch (s) { case LDNS_STATUS_OK: + if (explicit_ttl) { + if (!ttl_from_TTL) { + /* No $TTL, so ttl "defaults to the + * last explicitly stated value" + * (RFC 1035 Section 5.1) + */ + my_ttl = ldns_rr_ttl(rr); + } + /* When ttl is implicit, try to adhere to the rules as + * much as possible. (also for compatibility with bind) + * This was changed when fixing an issue with ZONEMD + * which hashes the TTL too. + */ + } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SIG + || ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { + if (ldns_rr_rd_count(rr) >= 4 + && ldns_rdf_get_type(ldns_rr_rdf(rr, 3)) == LDNS_RDF_TYPE_INT32) + + /* SIG without explicit ttl get ttl + * from the original_ttl field + * (RFC 2535 Section 7.2) + * + * Similarly for RRSIG, but stated less + * specifically in the spec. + * (RFC 4034 Section 3) + */ + ldns_rr_set_ttl(rr, + ldns_rdf2native_int32( + ldns_rr_rdf(rr, 3))); + + } else if (prev_rr + && ldns_rr_get_type(prev_rr) == ldns_rr_get_type(rr) + && ldns_dname_compare( ldns_rr_owner(prev_rr) + , ldns_rr_owner(rr)) == 0) + + /* "TTLs of all RRs in an RRSet must be the same" + * (RFC 2881 Section 5.2) + */ + ldns_rr_set_ttl(rr, ldns_rr_ttl(prev_rr)); + + prev_rr = rr; if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { if (soa_seen) { /* second SOA @@ -245,19 +303,25 @@ ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t } /* a normal RR - as sofar the DNS is normal */ - if (!ldns_zone_push_rr(newzone, rr)) goto error; + if (!ldns_zone_push_rr(newzone, rr)) { + ldns_rr_free(rr); + goto error; + } + break; case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ case LDNS_STATUS_SYNTAX_TTL: /* the function set the ttl */ + default_ttl = my_ttl; + ttl_from_TTL = true; break; case LDNS_STATUS_SYNTAX_ORIGIN: /* the function set the origin */ break; case LDNS_STATUS_SYNTAX_INCLUDE: ret = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; - break; + goto error; default: ret = s; goto error; diff --git a/lib/libldns/Makefile b/lib/libldns/Makefile index 5668e210db..ee172f5020 100644 --- a/lib/libldns/Makefile +++ b/lib/libldns/Makefile @@ -3,14 +3,14 @@ LDNS= ${.CURDIR}/../../contrib/ldns LIB= private_ldns -SHLIB_MAJOR= 2 +SHLIB_MAJOR= 3 PRIVATELIB= shpub NO_STRICT_ALIASING= SRCS+= buffer.c dname.c dnssec.c dnssec_verify.c dnssec_zone.c \ error.c higher.c host2str.c host2wire.c keys.c net.c \ - packet.c parse.c rbtree.c rdata.c resolver.c \ + edns.c packet.c parse.c rbtree.c rdata.c resolver.c \ rr.c rr_functions.c sha1.c sha2.c \ str2host.c tsig.c util.c wire2host.c zone.c # not needed in base but included: diff --git a/lib/libldns/ldns/common.h b/lib/libldns/ldns/common.h index 9abd9b9396..dcc54db378 100644 --- a/lib/libldns/ldns/common.h +++ b/lib/libldns/ldns/common.h @@ -27,6 +27,9 @@ #define LDNS_BUILD_CONFIG_USE_DANE 1 #define LDNS_BUILD_CONFIG_HAVE_B32_PTON 0 #define LDNS_BUILD_CONFIG_HAVE_B32_NTOP 0 +#define LDNS_BUILD_CONFIG_USE_DSA 1 +#define LDNS_BUILD_CONFIG_USE_ED25519 0 +#define LDNS_BUILD_CONFIG_USE_ED448 0 /* * HAVE_STDBOOL_H is not available when distributed as a library, but no build diff --git a/lib/libldns/ldns/config.h b/lib/libldns/ldns/config.h index 0993c32416..ccbdb30f7a 100644 --- a/lib/libldns/ldns/config.h +++ b/lib/libldns/ldns/config.h @@ -31,6 +31,15 @@ /* Define to 1 if you have the `calloc' function. */ #define HAVE_CALLOC 1 +/* Define to 1 if you have the `CONF_modules_unload' function. */ +#define HAVE_CONF_MODULES_UNLOAD 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the `CRYPTO_memcmp' function. */ +#define HAVE_CRYPTO_MEMCMP 1 + /* Define to 1 if you have the `ctime_r' function. */ #define HAVE_CTIME_R 1 @@ -40,6 +49,10 @@ /* Is a CAPATH given at configure time */ #define HAVE_DANE_CA_PATH 0 +/* Define to 1 if you have the declaration of `EVP_PKEY_base_id', and to 0 if + you don't. */ +#define HAVE_DECL_EVP_PKEY_BASE_ID 1 + /* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you don't. */ #define HAVE_DECL_NID_ED25519 0 @@ -80,21 +93,33 @@ /* Define to 1 if you have the `endservent' function. */ #define HAVE_ENDSERVENT 1 -/* Define to 1 if you have the `ENGINE_load_cryptodev' function. */ -/* #undef HAVE_ENGINE_LOAD_CRYPTODEV */ +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_free' function. */ +/* #undef HAVE_ENGINE_FREE */ + +/* Define to 1 if you have the `ERR_free_strings' function. */ +#define HAVE_ERR_FREE_STRINGS 1 /* Define to 1 if you have the `ERR_load_crypto_strings' function. */ #define HAVE_ERR_LOAD_CRYPTO_STRINGS 1 +/* Define to 1 if you have the `EVP_cleanup' function. */ +#define HAVE_EVP_CLEANUP 1 + /* Define to 1 if you have the `EVP_dss1' function. */ #define HAVE_EVP_DSS1 1 /* Define to 1 if you have the `EVP_MD_CTX_new' function. */ #define HAVE_EVP_MD_CTX_NEW 1 -/* Define to 1 if you have the `EVP_PKEY_base_id' function. */ +/* Define to 1 if you have the EVP_PKEY_base_id function or macro. */ #define HAVE_EVP_PKEY_BASE_ID 1 +/* Define to 1 if you have the `EVP_PKEY_get_base_id' function. */ +/* #undef HAVE_EVP_PKEY_GET_BASE_ID */ + /* Define to 1 if you have the `EVP_PKEY_keygen' function. */ #define HAVE_EVP_PKEY_KEYGEN 1 @@ -113,6 +138,9 @@ /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 +/* if fork is available for compile */ +#define HAVE_FORK_AVAILABLE 1 + /* Whether getaddrinfo is available */ #define HAVE_GETADDRINFO 1 @@ -122,9 +150,6 @@ /* Define to 1 if you have the `gmtime_r' function. */ #define HAVE_GMTIME_R 1 -/* If you have HMAC_Update */ -#define HAVE_HMAC_UPDATE 1 - /* Define to 1 if you have the `inet_aton' function. */ #define HAVE_INET_ATON 1 @@ -155,19 +180,15 @@ /* Define to 1 if you have the `localtime_r' function. */ #define HAVE_LOCALTIME_R 1 -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MINIX_CONFIG_H */ + /* Define to 1 if you have the header file. */ #define HAVE_NETDB_H 1 @@ -201,9 +222,18 @@ /* Define to 1 if you have the header file. */ /* #undef HAVE_NET_IF_H */ +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_CONF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + /* Define to 1 if you have the header file. */ #define HAVE_OPENSSL_ERR_H 1 +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_EVP_H 1 + /* Define to 1 if you have the `OPENSSL_init_crypto' function. */ #define HAVE_OPENSSL_INIT_CRYPTO 1 @@ -228,10 +258,6 @@ /* Define to 1 if you have the `random' function. */ #define HAVE_RANDOM 1 -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#define HAVE_REALLOC 1 - /* Define to 1 if you have the `sleep' function. */ #define HAVE_SLEEP 1 @@ -250,6 +276,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 @@ -283,6 +312,9 @@ /* define if you have sys/types.h */ #define HAVE_SYS_TYPES_H 1 +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TARGETCONDITIONALS_H */ + /* Define to 1 if you have the `timegm' function. */ #define HAVE_TIMEGM 1 @@ -298,6 +330,9 @@ /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ +/* Define to 1 if you have the header file. */ +#define HAVE_WCHAR_H 1 + /* Define to 1 if you have the header file. */ /* #undef HAVE_WINSOCK2_H */ @@ -329,7 +364,7 @@ #define PACKAGE_NAME "ldns" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "ldns 1.7.1" +#define PACKAGE_STRING "ldns 1.8.3" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "libdns" @@ -338,7 +373,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.7.1" +#define PACKAGE_VERSION "1.8.3" /* Define this to enable RR type AMTRELAY. */ /* #undef RRTYPE_AMTRELAY */ @@ -358,13 +393,18 @@ /* Define this to enable RR type RKEY. */ /* #undef RRTYPE_RKEY */ +/* Define this to enable RR types SVCB and HTTPS. */ +#define RRTYPE_SVCB_HTTPS /**/ + /* Define this to enable RR type TA. */ /* #undef RRTYPE_TA */ /* The size of `time_t', as computed by sizeof. */ #define SIZEOF_TIME_T 8 -/* Define to 1 if you have the ANSI C header files. */ +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ #define STDC_HEADERS 1 /* Define this to enable messages to stderr. */ @@ -404,21 +444,87 @@ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# define _DARWIN_C_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif -/* Enable threading extensions on Solaris. */ +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# define _HPUX_ALT_XOPEN_SOCKET_API 1 +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +/* # undef _MINIX */ +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# define _NETBSD_SOURCE 1 +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# define _OPENBSD_SOURCE 1 +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +/* # undef _POSIX_SOURCE */ +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +/* # undef _POSIX_1_SOURCE */ +#endif +/* Enable POSIX-compatible threading on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS 1 #endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# define __STDC_WANT_IEC_60559_BFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# define __STDC_WANT_IEC_60559_DFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# define __STDC_WANT_LIB_EXT2__ 1 +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# define __STDC_WANT_MATH_SPEC_FUNCS__ 1 +#endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # define _TANDEM_SOURCE 1 #endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# define __EXTENSIONS__ 1 +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +/* # undef _XOPEN_SOURCE */ #endif @@ -440,18 +546,8 @@ # endif #endif -/* Define to 1 if on MINIX. */ -/* #undef _MINIX */ - /* Enable for compile on Minix */ -/* #undef _NETBSD_SOURCE */ - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ +#define _NETBSD_SOURCE 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ @@ -483,15 +579,9 @@ /* Define to `size_t' if does not define. */ /* #undef intptr_t */ -/* Define to rpl_malloc if the replacement function should be used. */ -/* #undef malloc */ - -/* Define to `int' if does not define. */ +/* Define as a signed integer type capable of holding a process identifier. */ /* #undef pid_t */ -/* Define to rpl_realloc if the replacement function should be used. */ -/* #undef realloc */ - /* Define to `unsigned int' if does not define. */ /* #undef size_t */ diff --git a/lib/libldns/ldns/net.h b/lib/libldns/ldns/net.h index d074f20ace..0fbf1544d5 100644 --- a/lib/libldns/ldns/net.h +++ b/lib/libldns/ldns/net.h @@ -30,7 +30,7 @@ extern "C" { */ /** - * Sends a buffer to an ip using udp and return the respons as a ldns_pkt + * Sends a buffer to an ip using udp and return the response as a ldns_pkt * \param[in] qbin the ldns_buffer to be send * \param[in] to the ip addr to send to * \param[in] tolen length of the ip addr @@ -90,7 +90,7 @@ int ldns_tcp_bgsend2(ldns_buffer *qbin, const struct sockaddr_storage *to, sockl int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); /** - * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt + * Sends a buffer to an ip using tcp and return the response as a ldns_pkt * \param[in] qbin the ldns_buffer to be send * \param[in] qbin the ldns_buffer to be send * \param[in] to the ip addr to send to @@ -233,7 +233,7 @@ struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, u * returns an rdf with the sockaddr info. works for ip4 and ip6 * \param[in] sock the struct sockaddr_storage to convert * \param[in] port what port was used. When NULL this is not set - * \return ldns_rdf* wth the address + * \return ldns_rdf* with the address */ ldns_rdf * ldns_sockaddr_storage2rdf(const struct sockaddr_storage *sock, uint16_t *port); @@ -241,7 +241,7 @@ ldns_rdf * ldns_sockaddr_storage2rdf(const struct sockaddr_storage *sock, uint16 * Prepares the resolver for an axfr query * The query is sent and the answers can be read with ldns_axfr_next * \param[in] resolver the resolver to use - * \param[in] domain the domain to exfr + * \param[in] domain the domain to axfr * \param[in] c the class to use * \return ldns_status the status of the transfer */ diff --git a/lib/libldns/ldns/util.h b/lib/libldns/ldns/util.h index 0e7ead89f1..1d8fa8836a 100644 --- a/lib/libldns/ldns/util.h +++ b/lib/libldns/ldns/util.h @@ -27,8 +27,8 @@ extern "C" { #define dprintf(X,Y) fprintf(stderr, (X), (Y)) /* #define dprintf(X, Y) */ -#define LDNS_VERSION "1.7.1" -#define LDNS_REVISION ((1<<16)|(7<<8)|(1)) +#define LDNS_VERSION "1.8.3" +#define LDNS_REVISION ((1<<16)|(8<<8)|(3)) /** * splint static inline workaround @@ -274,19 +274,22 @@ time_t mktime_from_utc(const struct tm *tm); /** * The function interprets time as the number of seconds since epoch - * with respect to now using serial arithmitics (rfc1982). + * with respect to now using serial arithmetics (rfc1982). * That number of seconds is then converted to broken-out time information. * This is especially useful when converting the inception and expiration * fields of RRSIG records. * * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) - * to be intepreted as a serial arithmitics number relative to now. + * to be interpreted as a serial arithmetics number relative to now. * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) * to which the time value is compared to determine the final value. * \param[out] result the struct with the broken-out time information * \return result on success or NULL on error */ -struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); +struct tm * ldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result); + +/* previously used wrong spelling */ +#define ldns_serial_arithmitics_gmtime_r ldns_serial_arithmetics_gmtime_r /** * Seed the random function. diff --git a/usr.bin/drill/drill.1 b/usr.bin/drill/drill.1 index 85f75ce5a0..712dffb02a 100644 --- a/usr.bin/drill/drill.1 +++ b/usr.bin/drill/drill.1 @@ -1,5 +1,5 @@ .\" @(#)drill.1 1.7.0 14-Jul-2004 OF; -.TH drill 1 "16 Jul 2020" +.TH drill 1 "12 Nov 2022" .SH NAME drill \- get (debug) information out of DNS(SEC) .SH SYNOPSIS