diff options
Diffstat (limited to 'contrib/unbound/sldns')
| -rw-r--r-- | contrib/unbound/sldns/keyraw.c | 6 | ||||
| -rw-r--r-- | contrib/unbound/sldns/parse.c | 55 | ||||
| -rw-r--r-- | contrib/unbound/sldns/parse.h | 6 | ||||
| -rw-r--r-- | contrib/unbound/sldns/parseutil.c | 45 | ||||
| -rw-r--r-- | contrib/unbound/sldns/parseutil.h | 4 | ||||
| -rw-r--r-- | contrib/unbound/sldns/pkthdr.h | 4 | ||||
| -rw-r--r-- | contrib/unbound/sldns/rrdef.c | 26 | ||||
| -rw-r--r-- | contrib/unbound/sldns/rrdef.h | 54 | ||||
| -rw-r--r-- | contrib/unbound/sldns/str2wire.c | 207 | ||||
| -rw-r--r-- | contrib/unbound/sldns/str2wire.h | 13 | ||||
| -rw-r--r-- | contrib/unbound/sldns/wire2str.c | 160 | ||||
| -rw-r--r-- | contrib/unbound/sldns/wire2str.h | 28 |
12 files changed, 512 insertions, 96 deletions
diff --git a/contrib/unbound/sldns/keyraw.c b/contrib/unbound/sldns/keyraw.c index befe1f722424..42a9262a30da 100644 --- a/contrib/unbound/sldns/keyraw.c +++ b/contrib/unbound/sldns/keyraw.c @@ -124,7 +124,7 @@ uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize) size_t i; uint32_t ac32 = 0; for (i = 0; i < keysize; ++i) { - ac32 += (i & 1) ? key[i] : key[i] << 8; + ac32 += ((i & 1)) ? key[i] : key[i] << 8; } ac32 += (ac32 >> 16) & 0xFFFF; return (uint16_t) (ac32 & 0xFFFF); @@ -195,6 +195,7 @@ void sldns_key_EVP_unload_gost(void) } #endif /* USE_GOST */ +#ifdef USE_DSA /* Retrieve params as BIGNUM from raw buffer */ static int sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p, @@ -271,7 +272,7 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len) return NULL; } if (!DSA_set0_key(dsa, Y, NULL)) { - /* QPG attached, cleaned up by DSA_fre() */ + /* QPG attached, cleaned up by DSA_free() */ DSA_free(dsa); BN_free(Y); return NULL; @@ -370,6 +371,7 @@ EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len) return evp_key; #endif } +#endif /* USE_DSA */ /* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */ static int diff --git a/contrib/unbound/sldns/parse.c b/contrib/unbound/sldns/parse.c index 491c8f51bf10..8ea084661db6 100644 --- a/contrib/unbound/sldns/parse.c +++ b/contrib/unbound/sldns/parse.c @@ -34,7 +34,7 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l { int c, prev_c; int p; /* 0 -> no parentheses seen, >0 nr of ( seen */ - int com, quoted; + int com, quoted, only_blank; char *t; size_t i; const char *d; @@ -53,6 +53,7 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l com = 0; quoted = 0; prev_c = 0; + only_blank = 1; /* Assume we got only <blank> until now */ t = token; if (del[0] == '"') { quoted = 1; @@ -101,6 +102,22 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l if (line_nr) { *line_nr = *line_nr + 1; } + if (only_blank && i > 0) { + /* Got only <blank> so far. Reset and try + * again with the next line. + */ + i = 0; + t = token; + } + if (p == 0) { + /* If p != 0 then the next line is a continuation. So + * we assume that the next line starts with a blank only + * if it is actually a new line. + */ + only_blank = 1; /* Assume next line starts with + * <blank>. + */ + } if (p == 0 && i > 0) { goto tokenread; } else { @@ -131,12 +148,29 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l /* check if we hit the delim */ for (d = del; *d; d++) { - if (c == *d && i > 0 && prev_c != '\\' && p == 0) { - if (c == '\n' && line_nr) { - *line_nr = *line_nr + 1; - } - goto tokenread; + if (c == *d) + break; + } + + if (c == *d && i > 0 && prev_c != '\\' && p == 0) { + if (c == '\n' && line_nr) { + *line_nr = *line_nr + 1; } + if (only_blank) { + /* Got only <blank> so far. Reset and + * try again with the next line. + */ + i = 0; + t = token; + only_blank = 1; + prev_c = c; + continue; + } + goto tokenread; + } + if (c != ' ' && c != '\t') { + /* Found something that is not <blank> */ + only_blank= 0; } if (c != '\0' && c != '\n') { i++; @@ -149,8 +183,13 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l if (c != '\0' && c != '\n') { *t++ = c; } - if (c == '\n' && line_nr) { - *line_nr = *line_nr + 1; + if (c == '\n') { + if (line_nr) { + *line_nr = *line_nr + 1; + } + only_blank = 1; /* Assume next line starts with + * <blank>. + */ } if (c == '\\' && prev_c == '\\') prev_c = 0; diff --git a/contrib/unbound/sldns/parse.h b/contrib/unbound/sldns/parse.h index fa8f51a924c4..504a78b676e2 100644 --- a/contrib/unbound/sldns/parse.h +++ b/contrib/unbound/sldns/parse.h @@ -106,7 +106,7 @@ ssize_t sldns_bget_token(struct sldns_buffer *b, char *token, const char *delim, * \param[in] k_del keyword delimiter * \param[out] data the data found * \param[in] d_del the data delimiter - * \param[in] data_limit maximum size the the data buffer + * \param[in] data_limit maximum size the data buffer * \return the number of character read */ ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); @@ -119,7 +119,7 @@ ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, * \param[in] k_del keyword delimiter * \param[out] data the data found * \param[in] d_del the data delimiter - * \param[in] data_limit maximum size the the data buffer + * \param[in] data_limit maximum size the data buffer * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) * \return the number of character read @@ -134,7 +134,7 @@ ssize_t sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_de * \param[in] k_del keyword delimiter * \param[out] data the data found * \param[in] d_del the data delimiter - * \param[in] data_limit maximum size the the data buffer + * \param[in] data_limit maximum size the data buffer * \return the number of character read */ ssize_t sldns_bget_keyword_data(struct sldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); diff --git a/contrib/unbound/sldns/parseutil.c b/contrib/unbound/sldns/parseutil.c index ba71df55d501..f696c6af1331 100644 --- a/contrib/unbound/sldns/parseutil.c +++ b/contrib/unbound/sldns/parseutil.c @@ -209,11 +209,13 @@ sldns_hexdigit_to_int(char ch) } uint32_t -sldns_str2period(const char *nptr, const char **endptr) +sldns_str2period(const char *nptr, const char **endptr, int* overflow) { int sign = 0; uint32_t i = 0; uint32_t seconds = 0; + const uint32_t maxint = 0xffffffff; + *overflow = 0; for(*endptr = nptr; **endptr; (*endptr)++) { switch (**endptr) { @@ -236,26 +238,46 @@ sldns_str2period(const char *nptr, const char **endptr) break; case 's': case 'S': + if(seconds > maxint-i) { + *overflow = 1; + return 0; + } seconds += i; i = 0; break; case 'm': case 'M': + if(i > maxint/60 || seconds > maxint-(i*60)) { + *overflow = 1; + return 0; + } seconds += i * 60; i = 0; break; case 'h': case 'H': + if(i > maxint/(60*60) || seconds > maxint-(i*60*60)) { + *overflow = 1; + return 0; + } seconds += i * 60 * 60; i = 0; break; case 'd': case 'D': + if(i > maxint/(60*60*24) || seconds > maxint-(i*60*60*24)) { + *overflow = 1; + return 0; + } seconds += i * 60 * 60 * 24; i = 0; break; case 'w': case 'W': + if(i > maxint/(60*60*24*7) || seconds > maxint-(i*60*60*24*7)) { + *overflow = 1; + return 0; + } seconds += i * 60 * 60 * 24 * 7; i = 0; break; @@ -269,15 +291,27 @@ sldns_str2period(const char *nptr, const char **endptr) case '7': case '8': case '9': + if(i > maxint/10 || i*10 > maxint - (**endptr - '0')) { + *overflow = 1; + return 0; + } i *= 10; i += (**endptr - '0'); break; default: + if(seconds > maxint-i) { + *overflow = 1; + return 0; + } seconds += i; /* disregard signedness */ return seconds; } } + if(seconds > maxint-i) { + *overflow = 1; + return 0; + } seconds += i; /* disregard signedness */ return seconds; @@ -402,11 +436,13 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz, /* ........ ........ ....4444 4....... ........ */ c = src[3] >> 7 ; + ATTR_FALLTHROUGH /* fallthrough */ case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c]; /* ........ .......3 3333.... ........ ........ */ c = src[2] >> 4 ; + ATTR_FALLTHROUGH /* fallthrough */ case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c]; @@ -415,6 +451,7 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz, /* .....111 11...... ........ ........ ........ */ c = src[1] >> 6 ; + ATTR_FALLTHROUGH /* fallthrough */ case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c]; @@ -426,11 +463,14 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz, switch (src_sz) { case 1: dst[2] = '='; dst[3] = '='; + ATTR_FALLTHROUGH /* fallthrough */ case 2: dst[4] = '='; + ATTR_FALLTHROUGH /* fallthrough */ case 3: dst[5] = '='; dst[6] = '='; + ATTR_FALLTHROUGH /* fallthrough */ case 4: dst[7] = '='; } @@ -543,17 +583,20 @@ sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz, /* ........ ........ ........ .55555.. ........ */ /* ........ ........ ....4444 4....... ........ */ dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; + ATTR_FALLTHROUGH /* fallthrough */ case 5: /* ........ ........ ....4444 4....... ........ */ /* ........ .......3 3333.... ........ ........ */ dst[2] = buf[3] << 4 | buf[4] >> 1; + ATTR_FALLTHROUGH /* fallthrough */ case 4: /* ........ .......3 3333.... ........ ........ */ /* ........ ..22222. ........ ........ ........ */ /* .....111 11...... ........ ........ ........ */ dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; + ATTR_FALLTHROUGH /* fallthrough */ case 2: /* .....111 11...... ........ ........ ........ */ diff --git a/contrib/unbound/sldns/parseutil.h b/contrib/unbound/sldns/parseutil.h index 208fd2fbca8b..683f34e23070 100644 --- a/contrib/unbound/sldns/parseutil.h +++ b/contrib/unbound/sldns/parseutil.h @@ -74,9 +74,11 @@ struct tm * sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct t * converts a ttl value (like 5d2h) to a long. * \param[in] nptr the start of the string * \param[out] endptr points to the last char in case of error + * \param[out] overflow returns if the string causes integer overflow error, + * the number is too big, string of digits too long. * \return the convert duration value */ -uint32_t sldns_str2period(const char *nptr, const char **endptr); +uint32_t sldns_str2period(const char *nptr, const char **endptr, int* overflow); /** * Returns the int value of the given (hex) digit diff --git a/contrib/unbound/sldns/pkthdr.h b/contrib/unbound/sldns/pkthdr.h index de9952ea71f8..c32e7d285567 100644 --- a/contrib/unbound/sldns/pkthdr.h +++ b/contrib/unbound/sldns/pkthdr.h @@ -97,18 +97,22 @@ extern "C" { #define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) */ #define LDNS_QDCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF)) +#define LDNS_QDCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_QDCOUNT_OFF, i)) /* Counter of the answer section */ #define LDNS_ANCOUNT_OFF 6 #define LDNS_ANCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF)) +#define LDNS_ANCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ANCOUNT_OFF, i)) /* Counter of the authority section */ #define LDNS_NSCOUNT_OFF 8 #define LDNS_NSCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF)) +#define LDNS_NSCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_NSCOUNT_OFF, i)) /* Counter of the additional section */ #define LDNS_ARCOUNT_OFF 10 #define LDNS_ARCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF)) +#define LDNS_ARCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ARCOUNT_OFF, i)) /** * The sections of a packet diff --git a/contrib/unbound/sldns/rrdef.c b/contrib/unbound/sldns/rrdef.c index fe5c8e104a88..9e2100d53843 100644 --- a/contrib/unbound/sldns/rrdef.c +++ b/contrib/unbound/sldns/rrdef.c @@ -72,7 +72,7 @@ static const sldns_rdf_type type_nsap_wireformat[] = { LDNS_RDF_TYPE_NSAP }; static const sldns_rdf_type type_nsap_ptr_wireformat[] = { - LDNS_RDF_TYPE_STR + LDNS_RDF_TYPE_UNQUOTED }; static const sldns_rdf_type type_sig_wireformat[] = { LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32, @@ -86,7 +86,7 @@ static const sldns_rdf_type type_px_wireformat[] = { LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME }; static const sldns_rdf_type type_gpos_wireformat[] = { - LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR + LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED }; static const sldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA }; static const sldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC }; @@ -381,9 +381,9 @@ static sldns_rr_descriptor rdata_field_descriptors[] = { /* 63 */ {LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 64 */ - {LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 }, /* 65 */ - {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 }, {(enum sldns_enum_rr_type)0, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {(enum sldns_enum_rr_type)0, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {(enum sldns_enum_rr_type)0, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, @@ -617,6 +617,12 @@ static sldns_rr_descriptor rdata_field_descriptors[] = { {(enum sldns_enum_rr_type)0, "TYPE258", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, #endif +{(enum sldns_enum_rr_type)0, "TYPE259", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{(enum sldns_enum_rr_type)0, "TYPE260", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + + /* 261 */ + {LDNS_RR_TYPE_RESINFO, "RESINFO", 1, 0, NULL, LDNS_RDF_TYPE_UNQUOTED, LDNS_RR_NO_COMPRESS, 0 }, + /* split in array, no longer contiguous */ #ifdef DRAFT_RRTYPES @@ -702,7 +708,11 @@ sldns_get_rr_type_by_name(const char *name) /* TYPEXX representation */ if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) { - return atoi(name + 4); + unsigned int a = atoi(name + 4); + if (a > LDNS_RR_TYPE_LAST) { + return (enum sldns_enum_rr_type)0; + } + return a; } /* Normal types */ @@ -740,7 +750,11 @@ sldns_get_rr_class_by_name(const char *name) /* CLASSXX representation */ if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) { - return atoi(name + 5); + unsigned int a = atoi(name + 5); + if (a > LDNS_RR_CLASS_LAST) { + return (enum sldns_enum_rr_class)0; + } + return a; } /* Normal types */ diff --git a/contrib/unbound/sldns/rrdef.h b/contrib/unbound/sldns/rrdef.h index 42d5de064eea..540468889880 100644 --- a/contrib/unbound/sldns/rrdef.h +++ b/contrib/unbound/sldns/rrdef.h @@ -196,8 +196,8 @@ enum sldns_enum_rr_type LDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ LDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ LDNS_RR_TYPE_ZONEMD = 63, /* draft-ietf-dnsop-dns-zone-digest-12 */ - LDNS_RR_TYPE_SVCB = 64, /* draft-ietf-dnsop-svcb-https-04 */ - LDNS_RR_TYPE_HTTPS = 65, /* draft-ietf-dnsop-svcb-https-04 */ + LDNS_RR_TYPE_SVCB = 64, /* draft-ietf-dnsop-svcb-https-04 */ + LDNS_RR_TYPE_HTTPS = 65, /* draft-ietf-dnsop-svcb-https-04 */ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ @@ -229,6 +229,8 @@ enum sldns_enum_rr_type LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */ LDNS_RR_TYPE_AVC = 258, + LDNS_RR_TYPE_RESINFO = 261, /* RFC 9606 */ + /** DNSSEC Trust Authorities */ LDNS_RR_TYPE_TA = 32768, /* RFC 4431, 5074, DNSSEC Lookaside Validation */ @@ -341,6 +343,9 @@ enum sldns_enum_rdf_type /** 8 * 8 bit hex numbers separated by dashes. For EUI64. */ LDNS_RDF_TYPE_EUI64, + /** Character string without quotes. */ + LDNS_RDF_TYPE_UNQUOTED, + /** A non-zero sequence of US-ASCII letters and numbers in lower case. * For CAA. */ @@ -433,12 +438,52 @@ enum sldns_enum_edns_option LDNS_EDNS_DHU = 6, /* RFC6975 */ LDNS_EDNS_N3U = 7, /* RFC6975 */ LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */ + LDNS_EDNS_COOKIE = 10, /* RFC7873 */ LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/ LDNS_EDNS_PADDING = 12, /* RFC7830 */ - LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */ + LDNS_EDNS_EDE = 15, /* RFC8914 */ + LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */ + LDNS_EDNS_REPORT_CHANNEL = 18, /* RFC9567 */ + LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST = 65534 }; typedef enum sldns_enum_edns_option sldns_edns_option; +enum sldns_enum_ede_code +{ + LDNS_EDE_NONE = -1, /* EDE undefined for internal use */ + 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, + LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS = 27, + LDNS_EDE_BADPROXYPOLICY = 28, + LDNS_EDE_SYNTHESIZED = 29 +}; +typedef enum sldns_enum_ede_code sldns_ede_code; + #define LDNS_EDNS_MASK_DO_BIT 0x8000 /** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */ @@ -450,6 +495,9 @@ typedef enum sldns_enum_edns_option sldns_edns_option; #define LDNS_TSIG_ERROR_BADNAME 20 #define LDNS_TSIG_ERROR_BADALG 21 +/** DNS Cookie extended rcode */ +#define LDNS_EXT_RCODE_BADCOOKIE 23 + /** * Contains all information about resource record types. * diff --git a/contrib/unbound/sldns/str2wire.c b/contrib/unbound/sldns/str2wire.c index d2cefae1c09e..392fc8f1d32a 100644 --- a/contrib/unbound/sldns/str2wire.c +++ b/contrib/unbound/sldns/str2wire.c @@ -249,11 +249,16 @@ rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len, int* not_there, uint32_t* ttl, uint32_t default_ttl) { const char* endptr; + int overflow; if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL, sldns_buffer_position(strbuf)); } - *ttl = (uint32_t) sldns_str2period(token, &endptr); + *ttl = (uint32_t) sldns_str2period(token, &endptr, &overflow); + if(overflow) { + return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, + sldns_buffer_position(strbuf)); + } if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) { *not_there = 1; @@ -352,7 +357,7 @@ rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_t r_max) break; default : break; } - return "\n\t "; + return "\n\t "; } /* Syntactic sugar for sldns_rr_new_frm_str_internal */ @@ -360,7 +365,8 @@ static int sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type) { return rdf_type == LDNS_RDF_TYPE_STR || - rdf_type == LDNS_RDF_TYPE_LONG_STR; + rdf_type == LDNS_RDF_TYPE_LONG_STR || + rdf_type == LDNS_RDF_TYPE_UNQUOTED; } /** see if rdata is quoted */ @@ -373,7 +379,8 @@ rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters, /* skip spaces */ while(sldns_buffer_remaining(strbuf) > 0 && - *(sldns_buffer_current(strbuf)) == ' ') { + (*(sldns_buffer_current(strbuf)) == ' ' || + *(sldns_buffer_current(strbuf)) == '\t')) { sldns_buffer_skip(strbuf, 1); } @@ -442,7 +449,7 @@ rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len, sldns_buffer_position(strbuf)); } hex_data_size = (size_t)atoi(token); - if(hex_data_size > LDNS_MAX_RDFLEN || + if(hex_data_size > LDNS_MAX_RDFLEN || *rr_cur_len + hex_data_size > *rr_len) { return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, sldns_buffer_position(strbuf)); @@ -561,7 +568,7 @@ sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len, /* check if not quoted yet, and we have encountered quotes */ if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && slen >= 2 && - (token[0] == '"' || token[0] == '\'') && + (token[0] == '"' || token[0] == '\'') && (token[slen-1] == '"' || token[slen-1] == '\'')) { /* move token two smaller (quotes) with endnull */ memmove(token, token+1, slen-2); @@ -606,7 +613,7 @@ sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len, /* add space */ /* when addlen < 2, the token buffer is full considering the NULL byte * from strlen and will lead to buffer overflow with the second - * assignement below. */ + * assignment below. */ if(addlen < 2) return 0; token[*token_strlen] = ' '; token[++(*token_strlen)] = 0; @@ -670,10 +677,10 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len) ,sldns_str2wire_svcparam_key_cmp); - /* The code below revolves around sematic errors in the SVCParam set. + /* The code below revolves around semantic errors in the SVCParam set. * So long as we do not distinguish between running Unbound as a primary * or as a secondary, we default to secondary behavior and we ignore the - * sematic errors. */ + * semantic errors. */ #ifdef SVCB_SEMANTIC_ERRORS { @@ -692,7 +699,7 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len) mandatory = svcparams[i]; } - /* 4. verify that all the SvcParamKeys in mandatory are present */ + /* Verify that all the SvcParamKeys in mandatory are present */ if(mandatory) { /* Divide by sizeof(uint16_t)*/ uint16_t mandatory_nkeys = sldns_read_uint16(mandatory + 2) / sizeof(uint16_t); @@ -775,10 +782,11 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, /* unknown RR data */ if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 && - !quoted && (token_strlen == 2 || token[2]==' ')) { + !quoted && (token_strlen == 2 || token[2]==' ' || + token[2]=='\t')) { was_unknown_rr_format = 1; if((status=rrinternal_parse_unknown(strbuf, token, - token_len, rr, rr_len, &rr_cur_len, + token_len, rr, rr_len, &rr_cur_len, pre_data_pos)) != 0) return status; } else if(token_strlen > 0 || quoted) { @@ -837,7 +845,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) { size_t rdata_len = rr_cur_len - dname_len - 10; uint8_t *rdata = rr+dname_len + 10; - + /* skip 1st rdata field SvcPriority (uint16_t) */ if (rdata_len < sizeof(uint16_t)) return LDNS_WIREPARSE_ERR_OK; @@ -849,7 +857,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, while (rdata_len && *rdata != 0) { uint8_t label_len; - if (*rdata & 0xC0) + if ((*rdata & 0xC0)) return LDNS_WIREPARSE_ERR_OK; label_len = *rdata + 1; @@ -1055,12 +1063,15 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, return s; } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { const char* end = NULL; + int overflow = 0; strlcpy((char*)rr, line, *len); *len = 0; *dname_len = 0; if(!parse_state) return LDNS_WIREPARSE_ERR_OK; parse_state->default_ttl = sldns_str2period( - sldns_strip_ws(line+5), &end); + sldns_strip_ws(line+5), &end, &overflow); + if(overflow) + return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; } else if (strncmp(line, "$INCLUDE", 8) == 0) { strlcpy((char*)rr, line, *len); *len = 0; @@ -1113,36 +1124,40 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len) return key_value; } else switch (key_len) { - case sizeof("mandatory")-1: - if (!strncmp(key, "mandatory", sizeof("mandatory")-1)) - return SVCB_KEY_MANDATORY; - if (!strncmp(key, "echconfig", sizeof("echconfig")-1)) - return SVCB_KEY_ECH; /* allow "echconfig as well as "ech" */ + case 3: + if (!strncmp(key, "ech", key_len)) + return SVCB_KEY_ECH; break; - case sizeof("alpn")-1: - if (!strncmp(key, "alpn", sizeof("alpn")-1)) + case 4: + if (!strncmp(key, "alpn", key_len)) return SVCB_KEY_ALPN; - if (!strncmp(key, "port", sizeof("port")-1)) + if (!strncmp(key, "port", key_len)) return SVCB_KEY_PORT; break; - case sizeof("no-default-alpn")-1: - if (!strncmp( key , "no-default-alpn" - , sizeof("no-default-alpn")-1)) - return SVCB_KEY_NO_DEFAULT_ALPN; + case 7: + if (!strncmp(key, "dohpath", key_len)) + return SVCB_KEY_DOHPATH; break; - case sizeof("ipv4hint")-1: - if (!strncmp(key, "ipv4hint", sizeof("ipv4hint")-1)) + case 8: + if (!strncmp(key, "ipv4hint", key_len)) return SVCB_KEY_IPV4HINT; - if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1)) + if (!strncmp(key, "ipv6hint", key_len)) return SVCB_KEY_IPV6HINT; break; - case sizeof("ech")-1: - if (!strncmp(key, "ech", sizeof("ech")-1)) - return SVCB_KEY_ECH; + case 9: + if (!strncmp(key, "mandatory", key_len)) + return SVCB_KEY_MANDATORY; + if (!strncmp(key, "echconfig", key_len)) + return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */ + break; + + case 15: + if (!strncmp(key, "no-default-alpn", key_len)) + return SVCB_KEY_NO_DEFAULT_ALPN; break; default: @@ -1356,7 +1371,7 @@ sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len) */ qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp); - /* The code below revolves around sematic errors in the SVCParam set. + /* The code below revolves around semantic errors in the SVCParam set. * So long as we do not distinguish between running Unbound as a primary * or as a secondary, we default to secondary behavior and we ignore the * semantic errors. */ @@ -1467,7 +1482,7 @@ sldns_str2wire_svcbparam_alpn_value(const char* val, size_t str_len; size_t dst_len; size_t val_len; - + val_len = strlen(val); if (val_len > sizeof(unescaped_dst)) { @@ -1501,7 +1516,34 @@ sldns_str2wire_svcbparam_alpn_value(const char* val, sldns_write_uint16(rd + 2, dst_len); memcpy(rd + 4, unescaped_dst, dst_len); *rd_len = 4 + dst_len; - + + return LDNS_WIREPARSE_ERR_OK; +} + +static int +sldns_str2wire_svcbparam_dohpath_value(const char* val, + uint8_t* rd, size_t* rd_len) +{ + size_t val_len; + + /* RFC6570#section-2.1 + * "The characters outside of expressions in a URI Template string are + * intended to be copied literally" + * Practically this means we do not have to look for "double escapes" + * like in the alpn value list. + */ + + val_len = strlen(val); + + if (*rd_len < 4 + val_len) { + return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; + } + + sldns_write_uint16(rd, SVCB_KEY_DOHPATH); + sldns_write_uint16(rd + 2, val_len); + memcpy(rd + 4, val, val_len); + *rd_len = 4 + val_len; + return LDNS_WIREPARSE_ERR_OK; } @@ -1525,6 +1567,7 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len, case SVCB_KEY_PORT: case SVCB_KEY_IPV4HINT: case SVCB_KEY_IPV6HINT: + case SVCB_KEY_DOHPATH: return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM; #endif default: @@ -1556,6 +1599,8 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len, return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len); case SVCB_KEY_ALPN: return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len); + case SVCB_KEY_DOHPATH: + return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len); default: str_len = strlen(val); if (*rd_len < 4 + str_len) @@ -1583,28 +1628,28 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_ /* case: key=value */ if (eq_pos != NULL && eq_pos[1]) { val_in = eq_pos + 1; - + /* unescape characters and "" blocks */ if (*val_in == '"') { val_in++; while (*val_in != '"' - && (unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val) + && (size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) && sldns_parse_char( (uint8_t*) val_out, &val_in)) { val_out++; } } else { - while ((unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val) + while ((size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) && sldns_parse_char( (uint8_t*) val_out, &val_in)) { val_out++; } } *val_out = 0; - return sldns_str2wire_svcparam_value(str, eq_pos - str, - unescaped_val[0] ? unescaped_val : NULL, rd, rd_len); + return sldns_str2wire_svcparam_value(str, eq_pos - str, + unescaped_val[0] ? unescaped_val : NULL, rd, rd_len); } /* case: key= */ - else if (eq_pos != NULL && !(eq_pos[1])) { + else if (eq_pos != NULL && !(eq_pos[1])) { return sldns_str2wire_svcparam_value(str, eq_pos - str, NULL, rd, rd_len); } /* case: key */ @@ -1675,6 +1720,8 @@ int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, return sldns_str2wire_eui48_buf(str, rd, len); case LDNS_RDF_TYPE_EUI64: return sldns_str2wire_eui64_buf(str, rd, len); + case LDNS_RDF_TYPE_UNQUOTED: + return sldns_str2wire_unquoted_buf(str, rd, len); case LDNS_RDF_TYPE_TAG: return sldns_str2wire_tag_buf(str, rd, len); case LDNS_RDF_TYPE_LONG_STR: @@ -2157,9 +2204,13 @@ int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len) int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) { const char* end; - uint32_t p = sldns_str2period(str, &end); + int overflow; + uint32_t p = sldns_str2period(str, &end, &overflow); if(*end != 0) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); + if(overflow) + return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, + end-str); if(*len < 4) return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; sldns_write_uint32(rd, p); @@ -2411,12 +2462,13 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) (void)strlcpy(proto_str, token, sizeof(proto_str)); } else { int serv_port; - struct servent *serv = getservbyname(token, proto_str); - if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); + if(atoi(token) != 0) serv_port=atoi(token); + else if(strcmp(token, "0") == 0) serv_port=0; else if(strcasecmp(token, "domain")==0) serv_port=53; else { - serv_port = atoi(token); - if(serv_port == 0 && strcmp(token, "0") != 0) { + struct servent *serv = getservbyname(token, proto_str); + if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); + else { #ifdef HAVE_ENDSERVENT endservent(); #endif @@ -2426,16 +2478,16 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, sldns_buffer_position(&strbuf)); } - if(serv_port < 0 || serv_port > 65535) { + } + if(serv_port < 0 || serv_port > 65535) { #ifdef HAVE_ENDSERVENT - endservent(); + endservent(); #endif #ifdef HAVE_ENDPROTOENT - endprotoent(); + endprotoent(); #endif - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, - sldns_buffer_position(&strbuf)); - } + return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, + sldns_buffer_position(&strbuf)); } if(rd_len < 1+serv_port/8+1) { /* bitmap is larger, init new bytes at 0 */ @@ -2505,12 +2557,42 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) { const char* s = str; size_t slen = strlen(str); - size_t dlen = 0; /* number of hexdigits parsed */ + size_t dlen = 0; /* number of hexdigits parsed for hex, + digits for E.164 */ - /* just a hex string with optional dots? */ - /* notimpl e.164 format */ if(slen > LDNS_MAX_RDFLEN*2) return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; + if(*len < 1) + return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; + if(*s == 0) { + /* empty string */ + rd[0] = 0; + *len = 1; + return LDNS_WIREPARSE_ERR_OK; + } + if(s[0] == '+') { + rd[0] = 1; /* E.164 format */ + /* digits '0'..'9', with skipped dots. */ + s++; + while(*s) { + if(isspace((unsigned char)*s) || *s == '.') { + s++; + continue; + } + if(*s < '0' || *s > '9') + return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-str); + if(*len < dlen + 2) + return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, + s-str); + rd[dlen+1] = *s++; + dlen++; + } + *len = dlen+1; + return LDNS_WIREPARSE_ERR_OK; + } + + rd[0] = 0; /* AESA format */ + /* hex, with skipped dots. */ while(*s) { if(isspace((unsigned char)*s) || *s == '.') { s++; @@ -2518,17 +2600,17 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) } if(!isxdigit((unsigned char)*s)) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - if(*len < dlen/2 + 1) + if(*len < dlen/2 + 2) return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, s-str); if((dlen&1)==0) - rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; - else rd[dlen/2] += sldns_hexdigit_to_int(*s++); + rd[dlen/2 + 1] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; + else rd[dlen/2 + 1] += sldns_hexdigit_to_int(*s++); dlen++; } if((dlen&1)!=0) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - *len = dlen/2; + *len = dlen/2 + 1; return LDNS_WIREPARSE_ERR_OK; } @@ -2697,6 +2779,11 @@ int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) return LDNS_WIREPARSE_ERR_OK; } +int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len) +{ + return sldns_str2wire_str_buf(str, rd, len); +} + int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) { size_t slen = strlen(str); diff --git a/contrib/unbound/sldns/str2wire.h b/contrib/unbound/sldns/str2wire.h index baee4236fe55..db6528a2f9bf 100644 --- a/contrib/unbound/sldns/str2wire.h +++ b/contrib/unbound/sldns/str2wire.h @@ -38,7 +38,8 @@ struct sldns_struct_lookup_table; #define SVCB_KEY_IPV4HINT 4 #define SVCB_KEY_ECH 5 #define SVCB_KEY_IPV6HINT 6 -#define SVCPARAMKEY_COUNT 7 +#define SVCB_KEY_DOHPATH 7 +#define SVCPARAMKEY_COUNT 8 #define MAX_NUMBER_OF_SVCPARAMS 64 @@ -236,6 +237,7 @@ uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len); #define LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE 385 #define LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA 386 + /** * Get reference to a constant string for the (parse) error. * @param e: error return value @@ -550,6 +552,15 @@ int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len); int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len); /** + * Convert rdf of type LDNS_RDF_TYPE_UNQUOTED from string to wireformat. + * @param str: the text to convert for this rdata element. + * @param rd: rdata buffer for the wireformat. + * @param len: length of rd buffer on input, used length on output. + * @return 0 on success, error on failure. + */ +int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len); + +/** * Convert rdf of type LDNS_RDF_TYPE_TAG from string to wireformat. * @param str: the text to convert for this rdata element. * @param rd: rdata buffer for the wireformat. diff --git a/contrib/unbound/sldns/wire2str.c b/contrib/unbound/sldns/wire2str.c index b70efe299d4b..1bc5b9cf6e93 100644 --- a/contrib/unbound/sldns/wire2str.c +++ b/contrib/unbound/sldns/wire2str.c @@ -159,7 +159,7 @@ static sldns_lookup_table sldns_wireparse_errors_data[] = { "Mandatory SvcParamKey is missing"}, { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY, "Keys in SvcParam mandatory MUST be unique" }, - { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY, + { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY, "mandatory MUST not be included as mandatory parameter" }, { LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX, "Could not parse port SvcParamValue" }, @@ -192,12 +192,51 @@ static sldns_lookup_table sldns_edns_options_data[] = { { 6, "DHU" }, { 7, "N3U" }, { 8, "edns-client-subnet" }, + { 10, "COOKIE" }, { 11, "edns-tcp-keepalive"}, { 12, "Padding" }, + { 15, "EDE"}, { 0, NULL} }; sldns_lookup_table* sldns_edns_options = sldns_edns_options_data; +/* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */ +static sldns_lookup_table sldns_edns_ede_codes_data[] = { + { LDNS_EDE_NONE, "None" }, + { LDNS_EDE_OTHER, "Other Error" }, + { LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" }, + { LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" }, + { LDNS_EDE_STALE_ANSWER, "Stale Answer" }, + { LDNS_EDE_FORGED_ANSWER, "Forged Answer" }, + { LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" }, + { LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" }, + { LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" }, + { LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" }, + { LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" }, + { LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" }, + { LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" }, + { LDNS_EDE_NSEC_MISSING, "NSEC Missing" }, + { LDNS_EDE_CACHED_ERROR, "Cached Error" }, + { LDNS_EDE_NOT_READY, "Not Ready" }, + { LDNS_EDE_BLOCKED, "Blocked" }, + { LDNS_EDE_CENSORED, "Censored" }, + { LDNS_EDE_FILTERED, "Filtered" }, + { LDNS_EDE_PROHIBITED, "Prohibited" }, + { LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" }, + { LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" }, + { LDNS_EDE_NOT_SUPPORTED, "Not Supported" }, + { LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" }, + { LDNS_EDE_NETWORK_ERROR, "Network Error" }, + { LDNS_EDE_INVALID_DATA, "Invalid Data" }, + { LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID, "Signature Expired Before Valid" }, + { LDNS_EDE_TOO_EARLY, "Non-Replayable Transactions Received in 0-RTT Data" }, + { LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS, "Unsupported NSEC3 Iterations Value" }, + { LDNS_EDE_BADPROXYPOLICY, "Unable to Conform to Policy" }, + { LDNS_EDE_SYNTHESIZED, "Synthesized Answer" }, + { 0, NULL} +}; +sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data; + static sldns_lookup_table sldns_tsig_errors_data[] = { { LDNS_TSIG_ERROR_NOERROR, "NOERROR" }, { LDNS_RCODE_FORMERR, "FORMERR" }, @@ -223,7 +262,7 @@ sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data; /* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */ const char *svcparamkey_strs[] = { "mandatory", "alpn", "no-default-alpn", "port", - "ipv4hint", "ech", "ipv6hint" + "ipv4hint", "ech", "ipv6hint", "dohpath" }; char* sldns_wire2str_pkt(uint8_t* data, size_t len) @@ -486,7 +525,7 @@ int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, uint8_t* rr = *d; size_t rrlen = *dlen, dname_off, rdlen, ordlen; uint16_t rrtype = 0; - + if(*dlen >= 3 && (*d)[0]==0 && sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) { /* perform EDNS OPT processing */ @@ -1070,7 +1109,7 @@ static int sldns_wire2str_svcparam_mandatory2str(char** s, assert(data_len > 0); if (data_len % sizeof(uint16_t)) - return -1; // wireformat error, data_len must be multiple of shorts + return -1; /* wireformat error, data_len must be multiple of shorts */ w += sldns_str_print(s, slen, "="); w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data)); data += 2; @@ -1118,7 +1157,7 @@ static int sldns_wire2str_svcparam_alpn2str(char** s, w += sldns_str_print(s, slen, "%s", ","); } w += sldns_str_print(s, slen, "\""); - + return w; } @@ -1138,7 +1177,7 @@ static int sldns_wire2str_svcparam_ech2str(char** s, (*s) += size; (*slen) -= size; - w += sldns_str_print(s, slen, "\""); + w += sldns_str_print(s, slen, "\""); return w + size; } @@ -1161,7 +1200,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl /* verify that we have data_len data */ if (data_len > *dlen) - return -1; + return -1; written_chars += sldns_print_svcparamkey(s, slen, svcparamkey); if (!data_len) { @@ -1173,6 +1212,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl case SVCB_KEY_IPV4HINT: case SVCB_KEY_IPV6HINT: case SVCB_KEY_MANDATORY: + case SVCB_KEY_DOHPATH: return -1; default: return written_chars; @@ -1200,6 +1240,9 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl case SVCB_KEY_ECH: r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d); break; + case SVCB_KEY_DOHPATH: + ATTR_FALLTHROUGH + /* fallthrough */ default: r = sldns_str_print(s, slen, "=\""); @@ -1221,7 +1264,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl } if (r <= 0) return -1; /* wireformat error */ - + written_chars += r; *d += data_len; *dlen -= data_len; @@ -1301,6 +1344,8 @@ int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, return sldns_wire2str_eui48_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_EUI64: return sldns_wire2str_eui64_scan(d, dlen, s, slen); + case LDNS_RDF_TYPE_UNQUOTED: + return sldns_wire2str_unquoted_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_TAG: return sldns_wire2str_tag_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_LONG_STR: @@ -1550,7 +1595,7 @@ int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) unsigned i, bit, window, block_len; uint16_t t; int w = 0; - + /* check for errors */ while(pl) { if(pl < 2) return -1; @@ -1827,7 +1872,33 @@ int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) { - return print_remainder_hex("", d, dl, s, sl); + uint8_t format; + int w = 0; + size_t i; + + if(*dl < 1) return -1; + format = (*d)[0]; + (*d)+=1; + (*dl)-=1; + + if(format == 0) { + /* AESA format (ATM End System Address). */ + return print_remainder_hex("", d, dl, s, sl); + } else if(format == 1) { + /* E.164 format. */ + w += sldns_str_print(s, sl, "+"); + for(i=0; i<*dl; i++) { + if((*d)[i] < '0' || (*d)[0] > '9') + return -1; + w += sldns_str_print(s, sl, "%c", (*d)[i]); + } + (*d) += *dl; + (*dl) = 0; + } else { + /* Unknown format. */ + return -1; + } + return w; } /* internal scan routine that can modify arguments on failure */ @@ -1978,6 +2049,26 @@ int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) return w; } +int sldns_wire2str_unquoted_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) +{ + int w = 0; + size_t i, len; + if(*dl < 1) return -1; + len = **d; + if(*dl < 1+len) return -1; + (*d)++; + (*dl)--; + for(i=0; i<len; i++) { + if(isspace((unsigned char)(*d)[i]) || (*d)[i] == '(' || + (*d)[i] == ')' || (*d)[i] == '\'') + w += sldns_str_print(s, sl, "\\%c", (char)(*d)[i]); + else w += str_char_print(s, sl, (*d)[i]); + } + (*d)+=len; + (*dl)-=len; + return w; +} + int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) { size_t i, n; @@ -2230,6 +2321,52 @@ static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, return w; } +int sldns_wire2str_edns_ede_print(char** s, size_t* sl, + uint8_t* data, size_t len) +{ + uint16_t ede_code; + int w = 0; + sldns_lookup_table *lt; + size_t i; + int printable; + + if(len < 2) { + w += sldns_str_print(s, sl, "malformed ede "); + w += print_hex_buf(s, sl, data, len); + return w; + } + + ede_code = sldns_read_uint16(data); + lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code); + if(lt && lt->name) + w += sldns_str_print(s, sl, "%s", lt->name); + else w += sldns_str_print(s, sl, "%d", (int)ede_code); + + if(len == 2) + return w; + + w += sldns_str_print(s, sl, " "); + + /* If it looks like text, show it as text. */ + printable=1; + for(i=2; i<len; i++) { + if(isprint((unsigned char)data[i]) || data[i] == '\t') + continue; + printable = 0; + break; + } + if(printable) { + w += sldns_str_print(s, sl, "\""); + for(i=2; i<len; i++) { + w += str_char_print(s, sl, data[i]); + } + w += sldns_str_print(s, sl, "\""); + } else { + w += print_hex_buf(s, sl, data+2, len-2); + } + return w; +} + int sldns_wire2str_edns_option_print(char** s, size_t* sl, uint16_t option_code, uint8_t* optdata, size_t optlen) { @@ -2264,6 +2401,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl, case LDNS_EDNS_PADDING: w += print_hex_buf(s, sl, optdata, optlen); break; + case LDNS_EDNS_EDE: + w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen); + break; default: /* unknown option code */ w += print_hex_buf(s, sl, optdata, optlen); diff --git a/contrib/unbound/sldns/wire2str.h b/contrib/unbound/sldns/wire2str.h index 548c66300d92..36c58b8b064d 100644 --- a/contrib/unbound/sldns/wire2str.h +++ b/contrib/unbound/sldns/wire2str.h @@ -36,6 +36,8 @@ extern struct sldns_struct_lookup_table* sldns_opcodes; extern struct sldns_struct_lookup_table* sldns_edns_flags; /** EDNS option codes */ extern struct sldns_struct_lookup_table* sldns_edns_options; +/** EDNS EDE codes */ +extern struct sldns_struct_lookup_table* sldns_edns_ede_codes; /** error string from wireparse */ extern struct sldns_struct_lookup_table* sldns_wireparse_errors; /** tsig errors are the rcodes with extra (higher) values */ @@ -260,7 +262,7 @@ int sldns_wire2str_rdata_unknown_scan(uint8_t** data, size_t* data_len, * @param pkt: packet for decompression, if NULL no decompression. * @param pktlen: length of packet buffer. * @param comprloop: inout bool, that is set true if compression loop failure - * happens. Pass in 0, if passsed in as true, a lower bound is set + * happens. Pass in 0, if passed in as true, a lower bound is set * on compression loops to stop arbitrary long packet parse times. * This is meant so you can set it to 0 at the start of a list of dnames, * and then scan all of them in sequence, if a loop happens, it becomes @@ -918,6 +920,19 @@ int sldns_wire2str_eui64_scan(uint8_t** data, size_t* data_len, char** str, size_t* str_len); /** + * Scan wireformat UNQUOTED field to string, with user buffers. + * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). + * @param data: wireformat data. + * @param data_len: length of data buffer. + * @param str: string buffer. + * @param str_len: length of string buffer. + * @return number of characters (except null) needed to print. + * Can return -1 on failure. + */ +int sldns_wire2str_unquoted_scan(uint8_t** data, size_t* data_len, char** str, + size_t* str_len); + +/** * Scan wireformat TAG field to string, with user buffers. * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). * @param data: wireformat data. @@ -1021,6 +1036,17 @@ int sldns_wire2str_edns_subnet_print(char** str, size_t* str_len, uint8_t* option_data, size_t option_len); /** + * Print EDNS EDE option data to string. User buffers, moves string pointers. + * @param str: string buffer. + * @param str_len: length of string buffer. + * @param option_data: buffer with EDNS option code data. + * @param option_len: length of the data for this option. + * @return number of characters (except null) needed to print. + */ +int sldns_wire2str_edns_ede_print(char** str, size_t* str_len, + uint8_t* option_data, size_t option_len); + +/** * Print an EDNS option as OPT: VALUE. User buffers, moves string pointers. * @param str: string buffer. * @param str_len: length of string buffer. |
