+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]
* '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,
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,
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/hex.h>
+#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/os.h>
#include <isc/print.h>
CHECK(isc_task_create(taskmgr, 0, &maintask));
return (ISC_R_SUCCESS);
- cleanup:
+ cleanup:
cleanup_managers();
return (result);
}
return (ISC_R_SUCCESS);
- cleanup:
+ cleanup:
dns_test_end();
return (result);
}
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);
+}
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);
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
*/
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) {
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
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.
*/
dns_nsec3_typepresent
dns_nsec3param_deletechains
dns_nsec3param_fromprivate
+dns_nsec3param_salttotext
dns_nsec3param_toprivate
dns_nsec_build
dns_nsec_buildrdata
}
}
-/*
- * 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.
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)",
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)",