From: Michał Kępień Date: Wed, 25 Oct 2017 07:21:57 +0000 (+0200) Subject: [master] Rename nsec3param_salt_totext() to dns_nsec3param_salttotext(), make it... X-Git-Tag: v9.12.0b2~69 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=910a01550a95bd0b40a778f759534991c92257d4;p=thirdparty%2Fbind9.git [master] Rename nsec3param_salt_totext() to dns_nsec3param_salttotext(), make it public, add unit tests 4786. [cleanup] Turn nsec3param_salt_totext() into a public function, dns_nsec3param_salttotext(), and add unit tests for it. [RT #46289] --- diff --git a/CHANGES b/CHANGES index a31e863b97a..a3e51633296 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +4787. [cleanup] Turn nsec3param_salt_totext() into a public function, + dns_nsec3param_salttotext(), and add unit tests for it. + [RT #46289] + 4786. [func] The "filter-aaaa-on-v4" and "filter-aaaa-on-v6" options are no longer conditionally compiled. [RT #46340] diff --git a/lib/dns/include/dns/nsec3.h b/lib/dns/include/dns/nsec3.h index 63307ce057e..54abd56a57c 100644 --- a/lib/dns/include/dns/nsec3.h +++ b/lib/dns/include/dns/nsec3.h @@ -235,6 +235,19 @@ dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target, * 'buf' should be at least src->length + 1 in size. */ +isc_result_t +dns_nsec3param_salttotext(dns_rdata_nsec3param_t *nsec3param, char *dst, + size_t dstlen); +/*%< + * Convert the salt of given NSEC3PARAM RDATA into hex-encoded, NULL-terminated + * text stored at "dst". + * + * Requires: + * + *\li "dst" to have enough space (as indicated by "dstlen") to hold the + * resulting text and its NULL-terminating byte. + */ + isc_result_t dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, dns_zone_t *zone, isc_boolean_t nonsec, diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index a679a2e9bba..1a8dcbc2b9e 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -1009,6 +1009,42 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name, return (result); } +isc_result_t +dns_nsec3param_salttotext(dns_rdata_nsec3param_t *nsec3param, char *dst, + size_t dstlen) +{ + isc_result_t result; + isc_region_t r; + isc_buffer_t b; + + REQUIRE(nsec3param != NULL); + REQUIRE(dst != NULL); + + if (nsec3param->salt_length == 0) { + if (dstlen < 2U) { + return (ISC_R_NOSPACE); + } + strlcpy(dst, "-", dstlen); + return (ISC_R_SUCCESS); + } + + r.base = nsec3param->salt; + r.length = nsec3param->salt_length; + isc_buffer_init(&b, dst, (unsigned int)dstlen); + + result = isc_hex_totext(&r, 2, "", &b); + if (result != ISC_R_SUCCESS) { + return (result); + } + + if (isc_buffer_availablelength(&b) < 1) { + return (ISC_R_NOSPACE); + } + isc_buffer_putuint8(&b, 0); + + return (ISC_R_SUCCESS); +} + isc_result_t dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, dns_zone_t *zone, isc_boolean_t nonsec, diff --git a/lib/dns/tests/dnstest.c b/lib/dns/tests/dnstest.c index 092c155ee15..4b6079269fb 100644 --- a/lib/dns/tests/dnstest.c +++ b/lib/dns/tests/dnstest.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -100,7 +101,7 @@ create_managers(void) { CHECK(isc_task_create(taskmgr, 0, &maintask)); return (ISC_R_SUCCESS); - cleanup: + cleanup: cleanup_managers(); return (result); } @@ -158,7 +159,7 @@ dns_test_begin(FILE *logfile, isc_boolean_t start_managers) { return (ISC_R_SUCCESS); - cleanup: + cleanup: dns_test_end(); return (result); } @@ -434,3 +435,58 @@ dns_test_getdata(const char *file, unsigned char *buf, isc_stdio_close(f); return (result); } + +isc_result_t +dns_test_rdata_fromstring(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype, unsigned char *dst, + size_t dstlen, const char *src) +{ + isc_buffer_t source, target; + isc_lex_t *lex = NULL; + isc_result_t result; + size_t length; + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + REQUIRE(dst != NULL); + REQUIRE(src != NULL); + + /* + * Set up source to hold the input string. + */ + length = strlen(src); + isc_buffer_constinit(&source, src, length); + isc_buffer_add(&source, length); + + /* + * Create a lexer as one is required by dns_rdata_fromtext(). + */ + result = isc_lex_create(mctx, 64, &lex); + if (result != ISC_R_SUCCESS) { + return (result); + } + + /* + * Point lexer at source. + */ + result = isc_lex_openbuffer(lex, &source); + if (result != ISC_R_SUCCESS) { + goto destroy_lexer; + } + + /* + * Set up target for storing uncompressed wire form of provided RDATA. + */ + isc_buffer_init(&target, dst, dstlen); + + /* + * Parse input string, determining result. + */ + result = dns_rdata_fromtext(rdata, rdclass, rdtype, lex, dns_rootname, + 0, NULL, &target, NULL); + + destroy_lexer: + isc_lex_destroy(&lex); + + return (result); +} diff --git a/lib/dns/tests/dnstest.h b/lib/dns/tests/dnstest.h index 61ae1bef227..569ab806c1a 100644 --- a/lib/dns/tests/dnstest.h +++ b/lib/dns/tests/dnstest.h @@ -80,3 +80,13 @@ dns_test_getdata(const char *file, unsigned char *buf, char * dns_test_tohex(const unsigned char *data, size_t len, char *buf, size_t buflen); + +/*% + * Try parsing text form RDATA in "src" (of class "rdclass" and type "rdtype") + * into a structure representing that RDATA at "rdata", storing the + * uncompressed wire form of that RDATA at "dst", which is "dstlen" bytes long. + */ +isc_result_t +dns_test_rdata_fromstring(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype, unsigned char *dst, + size_t dstlen, const char *src); diff --git a/lib/dns/tests/nsec3_test.c b/lib/dns/tests/nsec3_test.c index a5dd44d7de2..ef7f7898eb1 100644 --- a/lib/dns/tests/nsec3_test.c +++ b/lib/dns/tests/nsec3_test.c @@ -43,6 +43,82 @@ iteration_test(const char *file, unsigned int expected) { dns_db_detach(&db); } +/*% + * Structure containing parameters for nsec3param_salttotext_test(). + */ +typedef struct { + const char *nsec3param_text; /* NSEC3PARAM RDATA in text form */ + const char *expected_salt; /* string expected in target buffer */ +} nsec3param_salttotext_test_params_t; + +/*% + * Check whether dns_nsec3param_salttotext() handles supplied text form + * NSEC3PARAM RDATA correctly: test whether the result of calling the former is + * as expected and whether it properly checks available buffer space. + * + * Assumes supplied text form NSEC3PARAM RDATA is valid as testing handling of + * invalid NSEC3PARAM RDATA is out of scope of this unit test. + */ +static void +nsec3param_salttotext_test(const nsec3param_salttotext_test_params_t *params) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3param_t nsec3param; + unsigned char buf[1024]; + isc_result_t result; + char salt[64]; + size_t length; + + /* + * Prepare a dns_rdata_nsec3param_t structure for testing. + */ + result = dns_test_rdata_fromstring(&rdata, dns_rdataclass_in, + dns_rdatatype_nsec3param, buf, + sizeof(buf), + params->nsec3param_text); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Check typical use. + */ + result = dns_nsec3param_salttotext(&nsec3param, salt, sizeof(salt)); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "\"%s\": expected success, got %s\n", + params->nsec3param_text, isc_result_totext(result)); + ATF_CHECK_EQ_MSG(strcmp(salt, params->expected_salt), 0, + "\"%s\": expected salt \"%s\", got \"%s\"", + params->nsec3param_text, params->expected_salt, salt); + + /* + * Ensure available space in the buffer is checked before the salt is + * printed to it and that the amount of space checked for includes the + * terminating NULL byte. + */ + length = strlen(params->expected_salt); + ATF_REQUIRE(length < sizeof(salt) - 1); /* prevent buffer overwrite */ + ATF_REQUIRE(length > 0U); /* prevent length underflow */ + + result = dns_nsec3param_salttotext(&nsec3param, salt, length - 1); + ATF_CHECK_EQ_MSG(result, ISC_R_NOSPACE, + "\"%s\": expected a %lu-byte target buffer to be " + "rejected, got %s\n", + params->nsec3param_text, length - 1, + isc_result_totext(result)); + result = dns_nsec3param_salttotext(&nsec3param, salt, length); + ATF_CHECK_EQ_MSG(result, ISC_R_NOSPACE, + "\"%s\": expected a %lu-byte target buffer to be " + "rejected, got %s\n", + params->nsec3param_text, length, + isc_result_totext(result)); + result = dns_nsec3param_salttotext(&nsec3param, salt, length + 1); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "\"%s\": expected a %lu-byte target buffer to be " + "accepted, got %s\n", + params->nsec3param_text, length + 1, + isc_result_totext(result)); +} + /* * Individual unit tests */ @@ -68,6 +144,40 @@ ATF_TC_BODY(max_iterations, tc) { dns_test_end(); } + +ATF_TC(nsec3param_salttotext); +ATF_TC_HEAD(nsec3param_salttotext, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_nsec3param_salttotext()"); +} +ATF_TC_BODY(nsec3param_salttotext, tc) { + isc_result_t result; + size_t i; + + const nsec3param_salttotext_test_params_t tests[] = { + /* + * Tests with non-empty salts. + */ + { "0 0 10 0123456789abcdef", "0123456789ABCDEF" }, + { "0 1 11 0123456789abcdef", "0123456789ABCDEF" }, + { "1 0 12 42", "42" }, + { "1 1 13 42", "42" }, + /* + * Test with empty salt. + */ + { "0 0 0 -", "-" }, + }; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + nsec3param_salttotext_test(&tests[i]); + } + + dns_test_end(); +} #else ATF_TC(untested); ATF_TC_HEAD(untested, tc) { @@ -85,6 +195,7 @@ ATF_TC_BODY(untested, tc) { ATF_TP_ADD_TCS(tp) { #if defined(OPENSSL) || defined(PKCS11CRYPTO) ATF_TP_ADD_TC(tp, max_iterations); + ATF_TP_ADD_TC(tp, nsec3param_salttotext); #else ATF_TP_ADD_TC(tp, untested); #endif diff --git a/lib/dns/tests/rdata_test.c b/lib/dns/tests/rdata_test.c index 2b23c922702..8fabf522f3b 100644 --- a/lib/dns/tests/rdata_test.c +++ b/lib/dns/tests/rdata_test.c @@ -141,38 +141,18 @@ static void check_text_ok_single(const text_ok_t *text_ok, dns_rdataclass_t rdclass, dns_rdatatype_t type, size_t structsize) { - isc_buffer_t source, target; + dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char buf_fromtext[1024]; char buf_totext[1024] = { 0 }; - isc_lex_t *lex = NULL; + isc_buffer_t target; isc_result_t result; - dns_rdata_t rdata; - size_t length; - /* - * Set up lexer to read data. - */ - result = isc_lex_create(mctx, 64, &lex); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - length = strlen(text_ok->text_in); - isc_buffer_constinit(&source, text_ok->text_in, length); - isc_buffer_add(&source, length); - result = isc_lex_openbuffer(lex, &source); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - /* - * Initialize target structures. - */ - isc_buffer_init(&target, buf_fromtext, sizeof(buf_fromtext)); - dns_rdata_init(&rdata); /* * Try converting text form RDATA into uncompressed wire form. */ - result = dns_rdata_fromtext(&rdata, rdclass, type, lex, dns_rootname, - 0, NULL, &target, NULL); - /* - * Destroy lexer now to simplify error handling below. - */ - isc_lex_destroy(&lex); + result = dns_test_rdata_fromstring(&rdata, rdclass, type, buf_fromtext, + sizeof(buf_fromtext), + text_ok->text_in); /* * Check whether result is as expected. */ diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index bd60f743faa..6747ade8ee1 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -637,6 +637,7 @@ dns_nsec3_supportedhash dns_nsec3_typepresent dns_nsec3param_deletechains dns_nsec3param_fromprivate +dns_nsec3param_salttotext dns_nsec3param_toprivate dns_nsec_build dns_nsec_buildrdata diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 4966de4cc35..4e608d0cf79 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -3303,50 +3303,6 @@ resume_signingwithkey(dns_zone_t *zone) { } } -/* - * Convert the salt of given NSEC3PARAM RDATA into hex-encoded, NULL-terminated - * text stored at "dst". - * - * Requires: - * "dst" to have enough space (as indicated by "dstlen") to hold the - * resulting text and its NULL-terminating byte. - */ -static isc_result_t -nsec3param_salt_totext(dns_rdata_nsec3param_t *nsec3param, char *dst, - size_t dstlen) -{ - isc_result_t result; - isc_region_t r; - isc_buffer_t b; - - REQUIRE(nsec3param != NULL); - REQUIRE(dst != NULL); - - if (nsec3param->salt_length == 0) { - if (dstlen < 2U) { - return (ISC_R_NOSPACE); - } - strlcpy(dst, "-", dstlen); - return (ISC_R_SUCCESS); - } - - r.base = nsec3param->salt; - r.length = nsec3param->salt_length; - isc_buffer_init(&b, dst, (unsigned int)dstlen); - - result = isc_hex_totext(&r, 2, "", &b); - if (result != ISC_R_SUCCESS) { - return (result); - } - - if (isc_buffer_availablelength(&b) < 1) { - return (ISC_R_NOSPACE); - } - isc_buffer_putuint8(&b, 0); - - return (ISC_R_SUCCESS); -} - /* * Initiate adding/removing NSEC3 records belonging to the chain defined by the * supplied NSEC3PARAM RDATA. @@ -3450,7 +3406,8 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { strlcat(flags, "|OPTOUT", sizeof(flags)); } } - result = nsec3param_salt_totext(nsec3param, saltbuf, sizeof(saltbuf)); + result = dns_nsec3param_salttotext(nsec3param, saltbuf, + sizeof(saltbuf)); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_zone_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)", @@ -17258,7 +17215,7 @@ dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { REQUIRE(DNS_ZONE_VALID(zone)); - result = nsec3param_salt_totext(nsec3param, salt, sizeof(salt)); + result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt)); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_zone_log(zone, ISC_LOG_NOTICE, "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",