diff --git a/CHANGES b/CHANGES index c5143a89c4a5ea8b13b5fcdcf9fdb3e6aee3846d..2b62238ed93cbe1f671b2c950ac7b26afbcc2a6b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +5126. [bug] Named incorrectly accepted empty base64 and hex encoded + fields when reading master files. [GL #807] + 5125. [bug] Allow for up to 100 records or 64k of data when caching a negative response. [GL #804] diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh index 96215663b5cb2410c8d6031c32c6e66bafec8b92..022c3111cdabc0a7208be657d6681336424eec8d 100644 --- a/bin/tests/system/checkzone/tests.sh +++ b/bin/tests/system/checkzone/tests.sh @@ -36,15 +36,16 @@ done for db in zones/bad*.db do echo_i "checking $db ($n)" - ret=0 + ret=0 v=0 case $db in zones/bad-dns-sd-reverse.db) - $CHECKZONE -k fail -i local 0.0.0.0.in-addr.arpa $db > test.out.$n 2>&1 && ret=1 + $CHECKZONE -k fail -i local 0.0.0.0.in-addr.arpa $db > test.out.$n 2>&1 || v=$? ;; *) - $CHECKZONE -i local example $db > test.out.$n 2>&1 && ret=1 + $CHECKZONE -i local example $db > test.out.$n 2>&1 || v=$? ;; esac + test $v = 1 || ret=1 n=`expr $n + 1` if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` diff --git a/bin/tests/system/checkzone/zones/bad-dhcid.db b/bin/tests/system/checkzone/zones/bad-dhcid.db new file mode 100644 index 0000000000000000000000000000000000000000..74381086d4a83d3a635852071d8c481087b872c0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-dhcid.db @@ -0,0 +1,2 @@ +@ 3600 DHCID +@ 3600 DHCID diff --git a/bin/tests/system/checkzone/zones/bad-eid.db b/bin/tests/system/checkzone/zones/bad-eid.db new file mode 100644 index 0000000000000000000000000000000000000000..65a44fd83ef062ea4d7aed369adb8b4077b81320 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-eid.db @@ -0,0 +1,2 @@ +@ EID +@ EID diff --git a/bin/tests/system/checkzone/zones/bad-nimloc.db b/bin/tests/system/checkzone/zones/bad-nimloc.db new file mode 100644 index 0000000000000000000000000000000000000000..fa059416d92f99fdaa37cfc5936b8ae7d03896f4 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-nimloc.db @@ -0,0 +1,2 @@ +@ 3600 NIMLOC +@ 3600 NIMLOC diff --git a/bin/tests/system/checkzone/zones/crashzone.db b/bin/tests/system/checkzone/zones/crashzone.db index c390d0c13e22e9e8539969c6d7251960bff58aa0..c6bd4e948dcca0a37512732e81d71d870a19bc3e 100644 --- a/bin/tests/system/checkzone/zones/crashzone.db +++ b/bin/tests/system/checkzone/zones/crashzone.db @@ -14,7 +14,7 @@ dyn.example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. ( 1209600 ; expire (2 weeks) 7200 ; minimum (2 hours) ) - 7200 RRSIG SOA 7 3 7200 2010 20100225214229 30323 dyn.example.net. + 7200 RRSIG SOA 7 3 7200 2010 20100225214229 30323 dyn.example.net. MuyI 7200 NS ns1.example.net. 7200 NS ns2.example.net. 3600 RRSIG DNSKEY 7 3 3600 20100227180048 ( diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 577dea9e02971bb4e32f4d9344268c6c42330da2..9e91ac3892dc0e0c9dd7516c6f4203f656cd0d21 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -888,13 +888,16 @@ unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type, if (result != ISC_R_SUCCESS) return (result); - result = isc_hex_tobuffer(lexer, buf, - (unsigned int)token.value.as_ulong); - if (result != ISC_R_SUCCESS) - goto failure; - if (isc_buffer_usedlength(buf) != token.value.as_ulong) { - result = ISC_R_UNEXPECTEDEND; - goto failure; + if (token.value.as_ulong != 0U) { + result = isc_hex_tobuffer(lexer, buf, + (unsigned int)token.value.as_ulong); + if (result != ISC_R_SUCCESS) { + goto failure; + } + if (isc_buffer_usedlength(buf) != token.value.as_ulong) { + result = ISC_R_UNEXPECTEDEND; + goto failure; + } } if (dns_rdatatype_isknown(type)) { diff --git a/lib/dns/rdata/generic/cert_37.c b/lib/dns/rdata/generic/cert_37.c index 237a806f0dfedd8feaba610ae12f3e2e30e771ce..a0ac76915375929529c25a30a7f0fd8bc78b7332 100644 --- a/lib/dns/rdata/generic/cert_37.c +++ b/lib/dns/rdata/generic/cert_37.c @@ -55,7 +55,7 @@ fromtext_cert(ARGS_FROMTEXT) { RETTOK(dns_secalg_fromtext(&secalg, &token.value.as_textregion)); RETERR(mem_tobuffer(target, &secalg, 1)); - return (isc_base64_tobuffer(lexer, target, -1)); + return (isc_base64_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c index f86bad7bd41ec346ed7878e0cf486398f7646f9d..a03798f32747080c2c48fa66cd9d9218509ecb27 100644 --- a/lib/dns/rdata/generic/ds_43.c +++ b/lib/dns/rdata/generic/ds_43.c @@ -82,7 +82,7 @@ generic_fromtext_ds(ARGS_FROMTEXT) { length = ISC_SHA384_DIGESTLENGTH; break; default: - length = -1; + length = -2; break; } return (isc_hex_tobuffer(lexer, target, length)); diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c index f68f0b84573eb7680f4db6d2a6f6e5960566a74f..6b3c076a9b739339b3b390ebec1ab44ce9eb8cbe 100644 --- a/lib/dns/rdata/generic/ipseckey_45.c +++ b/lib/dns/rdata/generic/ipseckey_45.c @@ -108,7 +108,7 @@ fromtext_ipseckey(ARGS_FROMTEXT) { /* * Public key. */ - return (isc_base64_tobuffer(lexer, target, -1)); + return (isc_base64_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c index edb02177b03b8a068113cf9c5cd223a92ea31af0..b6e5e7570db5a6ba96125bbf0ded012c56fb61ad 100644 --- a/lib/dns/rdata/generic/key_25.c +++ b/lib/dns/rdata/generic/key_25.c @@ -21,7 +21,6 @@ static inline isc_result_t generic_fromtext_key(ARGS_FROMTEXT) { - isc_result_t result; isc_token_t token; dns_secalg_t alg; dns_secproto_t proto; @@ -55,7 +54,7 @@ generic_fromtext_key(ARGS_FROMTEXT) { if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); - result = isc_base64_tobuffer(lexer, target, -1); + result = isc_base64_tobuffer(lexer, target, -2); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c index 30ba9676e7ff39848d1072f501b750aae81b87ba..f5e7399f490dc2117404d4db1d6862fe823bed1e 100644 --- a/lib/dns/rdata/generic/keydata_65533.c +++ b/lib/dns/rdata/generic/keydata_65533.c @@ -21,7 +21,6 @@ static inline isc_result_t fromtext_keydata(ARGS_FROMTEXT) { - isc_result_t result; isc_token_t token; dns_secalg_t alg; dns_secproto_t proto; @@ -76,7 +75,7 @@ fromtext_keydata(ARGS_FROMTEXT) { if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); - result = isc_base64_tobuffer(lexer, target, -1); + result = isc_base64_tobuffer(lexer, target, -2); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/rdata/generic/openpgpkey_61.c b/lib/dns/rdata/generic/openpgpkey_61.c index 52c87d4552727ebe54ae272a50841e9062a91d93..e2c55a8c3e42aa469587865cc978b24ff7a2cc06 100644 --- a/lib/dns/rdata/generic/openpgpkey_61.c +++ b/lib/dns/rdata/generic/openpgpkey_61.c @@ -28,7 +28,7 @@ fromtext_openpgpkey(ARGS_FROMTEXT) { /* * Keyring. */ - return (isc_base64_tobuffer(lexer, target, -1)); + return (isc_base64_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c index 8bc8d21f3f87000089e8cabc0cf14ac7667bd861..d3e6a562565c0a468fb9e6f86560f432c4752b6f 100644 --- a/lib/dns/rdata/generic/rrsig_46.c +++ b/lib/dns/rdata/generic/rrsig_46.c @@ -140,7 +140,7 @@ fromtext_rrsig(ARGS_FROMTEXT) { /* * Sig. */ - return (isc_base64_tobuffer(lexer, target, -1)); + return (isc_base64_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c index ca0ce4ea2ffcbcdba8d34e8ae8ee2a6489de1b9d..87b20316b57809d84de03f5ee5b30f281800d297 100644 --- a/lib/dns/rdata/generic/sig_24.c +++ b/lib/dns/rdata/generic/sig_24.c @@ -112,7 +112,7 @@ fromtext_sig(ARGS_FROMTEXT) { /* * Sig. */ - return (isc_base64_tobuffer(lexer, target, -1)); + return (isc_base64_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/sshfp_44.c b/lib/dns/rdata/generic/sshfp_44.c index 1b5d7ca51f356978c100baed9dd8cc85b55aaf16..c4209f4abc93a02e64ae896771e039ce63bedf0a 100644 --- a/lib/dns/rdata/generic/sshfp_44.c +++ b/lib/dns/rdata/generic/sshfp_44.c @@ -50,7 +50,7 @@ fromtext_sshfp(ARGS_FROMTEXT) { /* * Digest. */ - return (isc_hex_tobuffer(lexer, target, -1)); + return (isc_hex_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/tlsa_52.c b/lib/dns/rdata/generic/tlsa_52.c index 1224dc19aab366ce72ef395f148a8b118d6d6ad0..69867e72bfa0d9d6a640e5edfa71487c8fd12914 100644 --- a/lib/dns/rdata/generic/tlsa_52.c +++ b/lib/dns/rdata/generic/tlsa_52.c @@ -56,7 +56,7 @@ generic_fromtext_tlsa(ARGS_FROMTEXT) { /* * Certificate Association Data. */ - return (isc_hex_tobuffer(lexer, target, -1)); + return (isc_hex_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/in_1/dhcid_49.c b/lib/dns/rdata/in_1/dhcid_49.c index 1f2c30d8834dadb144a04beac6a25357331f0ec3..4a52d58e27e81d8eb599199ec58c595ef841f2ae 100644 --- a/lib/dns/rdata/in_1/dhcid_49.c +++ b/lib/dns/rdata/in_1/dhcid_49.c @@ -29,7 +29,7 @@ fromtext_in_dhcid(ARGS_FROMTEXT) { UNUSED(options); UNUSED(callbacks); - return (isc_base64_tobuffer(lexer, target, -1)); + return (isc_base64_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/in_1/eid_31.c b/lib/dns/rdata/in_1/eid_31.c index f7059612612fbc8369d9bd9eae68294605f98b49..9768d383a6e187c5035f579dc3967e6c0cbfa7ec 100644 --- a/lib/dns/rdata/in_1/eid_31.c +++ b/lib/dns/rdata/in_1/eid_31.c @@ -28,7 +28,7 @@ fromtext_in_eid(ARGS_FROMTEXT) { UNUSED(rdclass); UNUSED(callbacks); - return (isc_hex_tobuffer(lexer, target, -1)); + return (isc_hex_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/dns/rdata/in_1/nimloc_32.c b/lib/dns/rdata/in_1/nimloc_32.c index 10db1cfea44f129a20b04b821ac777bc16181169..bf7429232b7fc97d42349d581ad8bfbb8c3aef43 100644 --- a/lib/dns/rdata/in_1/nimloc_32.c +++ b/lib/dns/rdata/in_1/nimloc_32.c @@ -28,7 +28,7 @@ fromtext_in_nimloc(ARGS_FROMTEXT) { UNUSED(rdclass); UNUSED(callbacks); - return (isc_hex_tobuffer(lexer, target, -1)); + return (isc_hex_tobuffer(lexer, target, -2)); } static inline isc_result_t diff --git a/lib/isc/base32.c b/lib/isc/base32.c index bb8c2e19c5f0e0b9e6c2743b906e7fced998e167..557b543eaef69498c35c832d0ac71da3234ba02e 100644 --- a/lib/isc/base32.c +++ b/lib/isc/base32.c @@ -282,31 +282,43 @@ static isc_result_t base32_tobuffer(isc_lex_t *lexer, const char base[], bool pad, isc_buffer_t *target, int length) { + unsigned int before, after; base32_decode_ctx_t ctx; isc_textregion_t *tr; isc_token_t token; bool eol; + REQUIRE(length >= -2); + base32_decode_init(&ctx, length, base, pad, target); + before = isc_buffer_usedlength(target); while (!ctx.seen_end && (ctx.length != 0)) { unsigned int i; - if (length > 0) + if (length > 0) { eol = false; - else + } else { eol = true; + } RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, eol)); - if (token.type != isc_tokentype_string) + if (token.type != isc_tokentype_string) { break; + } tr = &token.value.as_textregion; - for (i = 0; i < tr->length; i++) + for (i = 0; i < tr->length; i++) { RETERR(base32_decode_char(&ctx, tr->base[i])); + } } - if (ctx.length < 0 && !ctx.seen_end) + after = isc_buffer_usedlength(target); + if (ctx.length < 0 && !ctx.seen_end) { isc_lex_ungettoken(lexer, &token); + } RETERR(base32_decode_finish(&ctx)); + if (length == -2 && before == after) { + return (ISC_R_UNEXPECTEDEND); + } return (ISC_R_SUCCESS); } diff --git a/lib/isc/base64.c b/lib/isc/base64.c index c7a1722ddde6de6f720ebc90f3a98c4e6b4c4b05..1eaf0141e06f59321380058eb8e99cee7fbbef48 100644 --- a/lib/isc/base64.c +++ b/lib/isc/base64.c @@ -173,31 +173,43 @@ base64_decode_finish(base64_decode_ctx_t *ctx) { isc_result_t isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) { + unsigned int before, after; base64_decode_ctx_t ctx; isc_textregion_t *tr; isc_token_t token; bool eol; + REQUIRE(length >= -2); + base64_decode_init(&ctx, length, target); + before = isc_buffer_usedlength(target); while (!ctx.seen_end && (ctx.length != 0)) { unsigned int i; - if (length > 0) + if (length > 0) { eol = false; - else + } else { eol = true; + } RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, eol)); - if (token.type != isc_tokentype_string) + if (token.type != isc_tokentype_string) { break; + } tr = &token.value.as_textregion; - for (i = 0; i < tr->length; i++) + for (i = 0; i < tr->length; i++) { RETERR(base64_decode_char(&ctx, tr->base[i])); + } } - if (ctx.length < 0 && !ctx.seen_end) + after = isc_buffer_usedlength(target); + if (ctx.length < 0 && !ctx.seen_end) { isc_lex_ungettoken(lexer, &token); + } RETERR(base64_decode_finish(&ctx)); + if (length == -2 && before == after) { + return (ISC_R_UNEXPECTEDEND); + } return (ISC_R_SUCCESS); } diff --git a/lib/isc/hex.c b/lib/isc/hex.c index 6d231abe5ba693b1118e0ae7f164de5e5b7f52d7..d19dc1540387873ada41c022b300e3bf56d5c665 100644 --- a/lib/isc/hex.c +++ b/lib/isc/hex.c @@ -121,31 +121,43 @@ hex_decode_finish(hex_decode_ctx_t *ctx) { isc_result_t isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) { + unsigned int before, after; hex_decode_ctx_t ctx; isc_textregion_t *tr; isc_token_t token; bool eol; + REQUIRE(length >= -2); + hex_decode_init(&ctx, length, target); + before = isc_buffer_usedlength(target); while (ctx.length != 0) { unsigned int i; - if (length > 0) + if (length > 0) { eol = false; - else + } else { eol = true; + } RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, eol)); - if (token.type != isc_tokentype_string) + if (token.type != isc_tokentype_string) { break; + } tr = &token.value.as_textregion; - for (i = 0; i < tr->length; i++) + for (i = 0; i < tr->length; i++) { RETERR(hex_decode_char(&ctx, tr->base[i])); + } } - if (ctx.length < 0) + after = isc_buffer_usedlength(target); + if (ctx.length < 0) { isc_lex_ungettoken(lexer, &token); + } RETERR(hex_decode_finish(&ctx)); + if (length == -2 && before == after) { + return (ISC_R_UNEXPECTEDEND); + } return (ISC_R_SUCCESS); } diff --git a/lib/isc/include/isc/base32.h b/lib/isc/include/isc/base32.h index 96fe2cef21f6b4cc6868ef563e4a217991872490..6ac9fcf21b3a053c33dea58e29a15d63386b95fa 100644 --- a/lib/isc/include/isc/base32.h +++ b/lib/isc/include/isc/base32.h @@ -96,18 +96,27 @@ isc_result_t isc_base32hexnp_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length); /*!< * \brief Convert text encoded in base32, base32hex, or base32hex - * non-padded from a lexer context into data. + * non-padded from a lexer context into `target`. If 'length' is + * non-negative, it is the expected number of encoded octets to convert. + * + * If 'length' is -1 then 0 or more encoded octets are expected. + * If 'length' is -2 then 1 or more encoded octets are expected. + * + * Returns: + *\li #ISC_R_BADBASE32 -- invalid base32 encoding. + *\li #ISC_R_UNEXPECTEDEND: the text does not contain the expected + * number of encoded octets. * * Requires: - *\li 'lex' is a valid lexer context + *\li 'lexer' is a valid lexer context *\li 'target' is a buffer containing binary data - *\li 'length' is an integer + *\li 'length' is -2, -1, or non-negative * * Ensures: *\li target will contain the data represented by the base32 encoded - * string parsed by the lexer. No more than length bytes will be read, - * if length is positive. The 'used' pointer in target will be - * advanced as necessary. + * string parsed by the lexer. No more than `length` octets will + * be read, if `length` is non-negative. The 'used' pointer in + * 'target' will be advanced as necessary. */ isc_result_t diff --git a/lib/isc/include/isc/base64.h b/lib/isc/include/isc/base64.h index 1504d3d49719718454be13e0289983200b19903a..108bdae02c56f67ffe8d9c27b1b5e821596a93c0 100644 --- a/lib/isc/include/isc/base64.h +++ b/lib/isc/include/isc/base64.h @@ -71,22 +71,30 @@ isc_base64_decodestring(const char *cstr, isc_buffer_t *target); isc_result_t isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length); /*!< - * \brief Convert base64 encoded text from a lexer context into data. + * \brief Convert base64 encoded text from a lexer context into + * `target`. If 'length' is non-negative, it is the expected number of + * encoded octets to convert. + * + * If 'length' is -1 then 0 or more encoded octets are expected. + * If 'length' is -2 then 1 or more encoded octets are expected. + * + * Returns: + *\li #ISC_R_BADBASE64 -- invalid base64 encoding. + *\li #ISC_R_UNEXPECTEDEND: the text does not contain the expected + * number of encoded octets. * * Requires: - *\li 'lex' is a valid lexer context + *\li 'lexer' is a valid lexer context *\li 'target' is a buffer containing binary data - *\li 'length' is an integer + *\li 'length' is -2, -1, or non-negative * * Ensures: *\li target will contain the data represented by the base64 encoded - * string parsed by the lexer. No more than length bytes will be read, - * if length is positive. The 'used' pointer in target will be - * advanced as necessary. + * string parsed by the lexer. No more than `length` octets will + * be read, if `length` is non-negative. The 'used' pointer in + * 'target' will be advanced as necessary. */ - - ISC_LANG_ENDDECLS #endif /* ISC_BASE64_H */ diff --git a/lib/isc/include/isc/hex.h b/lib/isc/include/isc/hex.h index 3e09e59d3aaae17688be24d1285964e0671f271a..b021e0515a194e09c8fd1716ec29b1ebb6af9321 100644 --- a/lib/isc/include/isc/hex.h +++ b/lib/isc/include/isc/hex.h @@ -71,21 +71,30 @@ isc_hex_decodestring(const char *cstr, isc_buffer_t *target); isc_result_t isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length); /*!< - * \brief Convert hex encoded text from a lexer context into data. + * \brief Convert hex-encoded text from a lexer context into + * `target`. If 'length' is non-negative, it is the expected number of + * encoded octets to convert. + * + * If 'length' is -1 then 0 or more encoded octets are expected. + * If 'length' is -2 then 1 or more encoded octets are expected. + * + * Returns: + *\li #ISC_R_BADHEX -- invalid hex encoding + *\li #ISC_R_UNEXPECTEDEND: the text does not contain the expected + * number of encoded octets. * * Requires: - *\li 'lex' is a valid lexer context + *\li 'lexer' is a valid lexer context *\li 'target' is a buffer containing binary data - *\li 'length' is an integer + *\li 'length' is -2, -1, or non-negative * * Ensures: *\li target will contain the data represented by the hex encoded - * string parsed by the lexer. No more than length bytes will be read, - * if length is positive. The 'used' pointer in target will be - * advanced as necessary. + * string parsed by the lexer. No more than `length` octets will + * be read, if `length` is non-negative. The 'used' pointer in + * 'target' will be advanced as necessary. */ - ISC_LANG_ENDDECLS #endif /* ISC_HEX_H */