From: Evan Hunt Date: Wed, 1 Mar 2023 02:29:38 +0000 (-0800) Subject: add basic test for TSIG key dump/restore functionality X-Git-Tag: v9.19.12~74^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e914c5e194ab8f604b28d1de81dc514a23f3c3ac;p=thirdparty%2Fbind9.git add basic test for TSIG key dump/restore functionality stop and restart the server in the 'tsiggss' test, in order to confirm that GSS negotiated TSIG keys are saved and restored when named loads. added logging to dns_tsigkey_createfromkey() to indicate whether a key has been statically configured, generated via GSS negotiation, or restored from a file. --- diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 8c30438cc25..97b53f1b2fa 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -884,8 +884,8 @@ setup_text_key(void) { } result = dns_tsigkey_create(&keyname, hmacname, secretstore, - (int)secretsize, false, NULL, 0, 0, mctx, - NULL, &tsigkey); + (int)secretsize, false, false, NULL, 0, 0, + mctx, NULL, &tsigkey); failure: if (result != ISC_R_SUCCESS) { printf(";; Couldn't create key %s: %s\n", keynametext, @@ -1186,8 +1186,8 @@ setup_file_key(void) { if (hmacname != NULL) { result = dns_tsigkey_createfromkey( - dst_key_name(dstkey), hmacname, dstkey, false, NULL, 0, - 0, mctx, NULL, &tsigkey); + dst_key_name(dstkey), hmacname, dstkey, false, false, + NULL, 0, 0, mctx, NULL, &tsigkey); if (result != ISC_R_SUCCESS) { printf(";; Couldn't create key %s: %s\n", keynametext, isc_result_totext(result)); diff --git a/bin/named/server.c b/bin/named/server.c index 8ca6872ded3..f40a641e323 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -7548,7 +7548,8 @@ generate_session_key(const char *filename, const char *keynamestr, /* Store the key in tsigkey. */ isc_stdtime_get(&now); CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key, false, - NULL, now, now, mctx, NULL, &tsigkey)); + false, NULL, now, now, mctx, NULL, + &tsigkey)); /* Dump the key to the key file. */ fp = named_os_openfile(filename, S_IRUSR | S_IWUSR, first_time); diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c index 6d596ab27ff..d20ab721031 100644 --- a/bin/named/tsigconf.c +++ b/bin/named/tsigconf.c @@ -106,8 +106,8 @@ add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, isc_stdtime_get(&now); ret = dns_tsigkey_create(&keyname, alg, secret, secretlen, - false, NULL, now, now, mctx, ring, - &tsigkey); + false, false, NULL, now, now, mctx, + ring, &tsigkey); isc_mem_put(mctx, secret, secretalloc); secret = NULL; if (ret != ISC_R_SUCCESS) { diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 60a3874a6a6..e93b8abc2bb 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -542,7 +542,8 @@ setup_keystr(void) { debug("keycreate"); result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen, - false, NULL, 0, 0, gmctx, NULL, &tsigkey); + false, false, NULL, 0, 0, gmctx, NULL, + &tsigkey); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", keystr, isc_result_totext(result)); @@ -676,8 +677,8 @@ setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { } if (hmacname != NULL) { result = dns_tsigkey_createfromkey( - dst_key_name(dstkey), hmacname, dstkey, false, NULL, 0, - 0, mctx, NULL, &tsigkey); + dst_key_name(dstkey), hmacname, dstkey, false, false, + NULL, 0, 0, mctx, NULL, &tsigkey); dst_key_free(&dstkey); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", @@ -1710,7 +1711,8 @@ evaluate_key(char *cmdline) { dns_tsigkey_detach(&tsigkey); } result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen, - false, NULL, 0, 0, gmctx, NULL, &tsigkey); + false, false, NULL, 0, 0, gmctx, NULL, + &tsigkey); isc_mem_free(gmctx, secret); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s %s: %s\n", diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 3969495821f..ebf4d525228 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -56,8 +56,6 @@ export WIRETEST=$TOP_BUILDDIR/bin/tests/wire_test export BIGKEY=$TOP_BUILDDIR/bin/tests/system/rsabigexponent/bigkey export GENCHECK=$TOP_BUILDDIR/bin/tests/system/rndc/gencheck -export KEYCREATE=$TOP_BUILDDIR/bin/tests/system/tkey/keycreate -export KEYDELETE=$TOP_BUILDDIR/bin/tests/system/tkey/keydelete export MAKEJOURNAL=$TOP_BUILDDIR/bin/tests/system/makejournal export PIPEQUERIES=$TOP_BUILDDIR/bin/tests/system/pipelined/pipequeries diff --git a/bin/tests/system/tsiggss/tests.sh b/bin/tests/system/tsiggss/tests.sh index ee592bb4705..32abb28f951 100644 --- a/bin/tests/system/tsiggss/tests.sh +++ b/bin/tests/system/tsiggss/tests.sh @@ -168,6 +168,18 @@ n=$((n+1)) if [ "$ret" -ne 0 ]; then echo_i "failed"; fi status=$((status+ret)) +echo_i "stop and start server to check key restoration ($n)" +ret=0 +gss_keys=$(grep 'tsig key.*generated' ns1/named.run | wc -l) +stop_server --use-rndc --port "${CONTROLPORT}" ns1 +start_server --noclean --restart --port "${PORT}" ns1 +restored_keys=$(grep 'tsig key.*restored from file' ns1/named.run | wc -l) +[ "$gss_keys" -ne 0 ] || ret=1 +[ "$restored_keys" -ne 0 ] || ret=1 +[ "$gss_keys" -eq "$restored_keys" ] || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + [ $status -eq 0 ] && echo_i "tsiggss tests all OK" kill `cat authsock.pid` diff --git a/fuzz/dns_message_checksig.c b/fuzz/dns_message_checksig.c index b7407f3dd6c..5c8f81aeb91 100644 --- a/fuzz/dns_message_checksig.c +++ b/fuzz/dns_message_checksig.c @@ -263,8 +263,8 @@ LLVMFuzzerInitialize(int *argc __attribute__((unused)), } result = dns_tsigkey_create(name, dns_tsig_hmacsha256_name, secret, - sizeof(secret), false, NULL, 0, 0, mctx, - ring, &tsigkey); + sizeof(secret), false, false, NULL, 0, 0, + mctx, ring, &tsigkey); if (result != ISC_R_SUCCESS) { fprintf(stderr, "dns_tsigkey_create failed: %s\n", isc_result_totext(result)); diff --git a/lib/dns/include/dns/tsig.h b/lib/dns/include/dns/tsig.h index 48292a1da45..bb72d01e17a 100644 --- a/lib/dns/include/dns/tsig.h +++ b/lib/dns/include/dns/tsig.h @@ -72,15 +72,16 @@ struct dns_tsigkey { /* Unlocked */ unsigned int magic; /*%< Magic number. */ isc_mem_t *mctx; - dst_key_t *key; /*%< Key */ - dns_name_t name; /*%< Key name */ - const dns_name_t *algorithm; /*%< Algorithm name */ - dns_name_t *creator; /*%< name that created secret */ - bool generated; /*%< was this generated? */ - isc_stdtime_t inception; /*%< start of validity period */ - isc_stdtime_t expire; /*%< end of validity period */ - dns_tsig_keyring_t *ring; /*%< the enclosing keyring */ - isc_refcount_t refs; /*%< reference counter */ + dst_key_t *key; /*%< Key */ + dns_name_t name; /*%< Key name */ + const dns_name_t *algorithm; /*%< Algorithm name */ + dns_name_t *creator; /*%< name that created secret */ + bool generated : 1; /*%< key was auto-generated */ + bool restored : 1; /*%< key was restored at startup */ + isc_stdtime_t inception; /*%< start of validity period */ + isc_stdtime_t expire; /*%< end of validity period */ + dns_tsig_keyring_t *ring; /*%< the enclosing keyring */ + isc_refcount_t refs; /*%< reference counter */ ISC_LINK(dns_tsigkey_t) link; }; @@ -102,13 +103,14 @@ dns_tsigkey_identity(const dns_tsigkey_t *tsigkey); isc_result_t dns_tsigkey_create(const dns_name_t *name, const dns_name_t *algorithm, unsigned char *secret, int length, bool generated, - const dns_name_t *creator, isc_stdtime_t inception, - isc_stdtime_t expire, isc_mem_t *mctx, - dns_tsig_keyring_t *ring, dns_tsigkey_t **key); + bool restored, const dns_name_t *creator, + isc_stdtime_t inception, isc_stdtime_t expire, + isc_mem_t *mctx, dns_tsig_keyring_t *ring, + dns_tsigkey_t **key); isc_result_t dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, - dst_key_t *dstkey, bool generated, + dst_key_t *dstkey, bool generated, bool restored, const dns_name_t *creator, isc_stdtime_t inception, isc_stdtime_t expire, isc_mem_t *mctx, dns_tsig_keyring_t *ring, dns_tsigkey_t **key); diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index a452c45b115..45ac21c0030 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -269,8 +269,8 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin, } #endif /* HAVE_GSSAPI */ RETERR(dns_tsigkey_createfromkey( - name, &tkeyin->algorithm, dstkey, true, principal, now, - expire, ring->mctx, ring, &tsigkey)); + name, &tkeyin->algorithm, dstkey, true, false, + principal, now, expire, ring->mctx, ring, &tsigkey)); dst_key_free(&dstkey); tkeyout->inception = now; tkeyout->expire = expire; @@ -861,8 +861,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, RETERR(dns_tsigkey_createfromkey( tkeyname, (win2k ? DNS_TSIG_GSSAPIMS_NAME : DNS_TSIG_GSSAPI_NAME), dstkey, - true, NULL, rtkey.inception, rtkey.expire, ring->mctx, ring, - outkey)); + true, false, NULL, rtkey.inception, rtkey.expire, ring->mctx, + ring, outkey)); dst_key_free(&dstkey); dns_rdata_freestruct(&rtkey); return (result); diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 54f3d2e5dfa..8eef675b826 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -150,7 +150,7 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) { strlcpy(namestr, "", sizeof(namestr)); } - if (key != NULL && key->generated && key->creator) { + if (key != NULL && key->generated && key->creator != NULL) { dns_name_format(key->creator, creatorstr, sizeof(creatorstr)); } else { strlcpy(creatorstr, "", sizeof(creatorstr)); @@ -239,11 +239,11 @@ keyring_add(dns_tsig_keyring_t *ring, const dns_name_t *name, isc_result_t dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, - dst_key_t *dstkey, bool generated, + dst_key_t *dstkey, bool generated, bool restored, const dns_name_t *creator, isc_stdtime_t inception, isc_stdtime_t expire, isc_mem_t *mctx, dns_tsig_keyring_t *ring, dns_tsigkey_t **key) { - dns_tsigkey_t *tkey; + dns_tsigkey_t *tkey = NULL; isc_result_t ret; unsigned int refs = 0; unsigned int dstalg = 0; @@ -255,8 +255,16 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, REQUIRE(key != NULL || ring != NULL); tkey = isc_mem_get(mctx, sizeof(dns_tsigkey_t)); + *tkey = (dns_tsigkey_t){ + .generated = generated, + .restored = restored, + .ring = ring, + .inception = inception, + .expire = expire, + .name = DNS_NAME_INITEMPTY, + .link = ISC_LINK_INITIALIZER, + }; - dns_name_init(&tkey->name, NULL); dns_name_dup(name, mctx, &tkey->name); (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); @@ -273,7 +281,7 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, goto cleanup_name; } } else { - dns_name_t *tmpname; + dns_name_t *tmpname = NULL; if (dstkey != NULL) { ret = DNS_R_BADALG; goto cleanup_name; @@ -289,15 +297,11 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t)); dns_name_init(tkey->creator, NULL); dns_name_dup(creator, mctx, tkey->creator); - } else { - tkey->creator = NULL; } - tkey->key = NULL; if (dstkey != NULL) { dst_key_attach(dstkey, &tkey->key); } - tkey->ring = ring; if (key != NULL) { refs = 1; @@ -307,13 +311,7 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, } isc_refcount_init(&tkey->refs, refs); - - tkey->generated = generated; - tkey->inception = inception; - tkey->expire = expire; - tkey->mctx = NULL; isc_mem_attach(mctx, &tkey->mctx); - ISC_LINK_INIT(tkey, link); tkey->magic = TSIG_MAGIC; @@ -342,6 +340,14 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, *key = tkey; } + if (tkey->restored) { + tsig_log(tkey, ISC_LOG_DEBUG(3), "restored from file"); + } else if (tkey->generated) { + tsig_log(tkey, ISC_LOG_DEBUG(3), "generated"); + } else { + tsig_log(tkey, ISC_LOG_DEBUG(3), "statically configured"); + } + return (ISC_R_SUCCESS); cleanup_refs: @@ -553,7 +559,7 @@ restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) { return (result); } - result = dns_tsigkey_createfromkey(name, algorithm, dstkey, true, + result = dns_tsigkey_createfromkey(name, algorithm, dstkey, true, true, creator, inception, expire, ring->mctx, ring, NULL); if (dstkey != NULL) { @@ -658,9 +664,10 @@ dns_tsigkey_identity(const dns_tsigkey_t *tsigkey) { isc_result_t dns_tsigkey_create(const dns_name_t *name, const dns_name_t *algorithm, unsigned char *secret, int length, bool generated, - const dns_name_t *creator, isc_stdtime_t inception, - isc_stdtime_t expire, isc_mem_t *mctx, - dns_tsig_keyring_t *ring, dns_tsigkey_t **key) { + bool restored, const dns_name_t *creator, + isc_stdtime_t inception, isc_stdtime_t expire, + isc_mem_t *mctx, dns_tsig_keyring_t *ring, + dns_tsigkey_t **key) { dst_key_t *dstkey = NULL; isc_result_t result; unsigned int dstalg = 0; @@ -690,8 +697,8 @@ dns_tsigkey_create(const dns_name_t *name, const dns_name_t *algorithm, } result = dns_tsigkey_createfromkey(name, algorithm, dstkey, generated, - creator, inception, expire, mctx, - ring, key); + restored, creator, inception, expire, + mctx, ring, key); if (dstkey != NULL) { dst_key_free(&dstkey); } @@ -1170,9 +1177,9 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, } if (ret != ISC_R_SUCCESS) { msg->tsigstatus = dns_tsigerror_badkey; - ret = dns_tsigkey_create(keyname, &tsig.algorithm, NULL, - 0, false, NULL, now, now, mctx, - NULL, &msg->tsigkey); + ret = dns_tsigkey_create( + keyname, &tsig.algorithm, NULL, 0, false, false, + NULL, now, now, mctx, NULL, &msg->tsigkey); if (ret != ISC_R_SUCCESS) { return (ret); } diff --git a/tests/dns/tsig_test.c b/tests/dns/tsig_test.c index d00266bf14a..02b5926f0cc 100644 --- a/tests/dns/tsig_test.c +++ b/tests/dns/tsig_test.c @@ -295,8 +295,8 @@ ISC_RUN_TEST_IMPL(tsig_tcp) { assert_int_equal(result, ISC_R_SUCCESS); result = dns_tsigkey_create(keyname, dns_tsig_hmacsha256_name, secret, - sizeof(secret), false, NULL, 0, 0, mctx, - ring, &key); + sizeof(secret), false, false, NULL, 0, 0, + mctx, ring, &key); assert_int_equal(result, ISC_R_SUCCESS); assert_non_null(key);