dnssec-signzone.c revision 7f35bf8e1702d751e949390d93b0b9cbb8fda8a2
5347c0fcb04eaea19d9f39795646239f487c6207Tinderbox User * Portions Copyright (C) 1999, 2000 Internet Software Consortium.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
5347c0fcb04eaea19d9f39795646239f487c6207Tinderbox User * Permission to use, copy, modify, and distribute this software for any
5347c0fcb04eaea19d9f39795646239f487c6207Tinderbox User * purpose with or without fee is hereby granted, provided that the above
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * copyright notice and this permission notice appear in all copies.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM AND
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * NETWORK ASSOCIATES DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User * SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE CONSORTIUM OR NETWORK
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * ASSOCIATES BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * PERFORMANCE OF THIS SOFTWARE.
f9ce6280cec79deb16ff6d9807aa493ff23e10d9Tinderbox User/*#define USE_ZONESTATUS*/
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox Usertypedef struct signer_array_struct signer_array_t;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntstatic isc_stdtime_t starttime = 0, endtime = 0, now;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntstatic inline void
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox Userset_bit(unsigned char *array, unsigned int index, unsigned int bit) {
8a48b6b9b6fa8486f24b22d1972b2b6ebb36a4a4Tinderbox Usersignwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
8a48b6b9b6fa8486f24b22d1972b2b6ebb36a4a4Tinderbox User result = dns_dnssec_sign(name, rdataset, key, &starttime, &endtime,
8a48b6b9b6fa8486f24b22d1972b2b6ebb36a4a4Tinderbox User fatal("key '%s/%s/%d' failed to sign data: %s",
8a48b6b9b6fa8486f24b22d1972b2b6ebb36a4a4Tinderbox User nametostr(dst_key_name(key)), algtostr(dst_key_alg(key)),
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User result = dns_dnssec_verify(name, rdataset, key,
e2f974003e61b59321a99f01a6f43576d9b76231Tinderbox User vbprintf(3, "\tsignature failed to verify\n");
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User return (ISC_TF(dns_name_equal(dst_key_name(key->key),
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User (dst_key_flags(key->key) & DNS_KEYFLAG_OWNERMASK) ==
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User * Finds the key that generated a SIG, if possible. First look at the keys
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User * that we've loaded already, and then see if there's a key on disk.
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User dns_name_equal(&sig->signer, dst_key_name(key->key)))
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User result = dst_key_fromfile(&sig->signer, sig->keyid, sig->algorithm,
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User key = isc_mem_get(mctx, sizeof(signer_key_t));
3ba1f79ade054aa6a0dc5032502bcdcf357cd7bdTinderbox User result = dst_key_fromfile(&sig->signer, sig->keyid, sig->algorithm,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * Check to see if we expect to find a key at this name. If we see a SIG
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * and can't find the signing key that we expect to find, we drop the sig.
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * I'm not sure if this is completely correct, but it seems to work.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntexpecttofindkey(dns_name_t *name, dns_db_t *db, dns_dbversion_t *version) {
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User result = dns_db_find(db, name, version, dns_rdatatype_key, options,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt fatal("failure looking for '%s KEY' in database: %s",
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox Usersetverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, sig);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt trdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); \
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User tdata = isc_mem_get(mctx, sizeof(signer_array_t)); \
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt isc_buffer_init(&b, tdata->array, sizeof(tdata->array));
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * Signs a set. Goes through contortions to decide if each SIG should
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * be dropped or retained, and then determines if any new SIGs need to
9d557856c2a19ec95ee73245f60a92f8675cf5baTinderbox User * be generated.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntsignset(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
1700442a7751c2bbdafe2d039cebbd8316496957Tinderbox User isc_boolean_t notsigned = ISC_TRUE, nosigs = ISC_FALSE;
1700442a7751c2bbdafe2d039cebbd8316496957Tinderbox User isc_boolean_t wassignedby[256], nowsignedby[256];
1700442a7751c2bbdafe2d039cebbd8316496957Tinderbox User for (i = 0; i < 256; i++)
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_db_findrdataset(db, node, version, dns_rdatatype_sig,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt vbprintf(1, "%s/%s:\n", nametostr(name), typetostr(set->type));
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User dns_rdataset_current(&oldsigset, &oldsigrdata);
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User result = dns_rdata_tostruct(&oldsigrdata, &sig, mctx);
3241ddcf9354c5ab50f4df5a656e72a5c68e172bTinderbox User expired = ISC_TF(now + cycle > sig.timeexpire);
3241ddcf9354c5ab50f4df5a656e72a5c68e172bTinderbox User /* sig is dropped and not replaced */
3241ddcf9354c5ab50f4df5a656e72a5c68e172bTinderbox User "invalid validity period\n",
3241ddcf9354c5ab50f4df5a656e72a5c68e172bTinderbox User /* sig is dropped and not replaced */
3241ddcf9354c5ab50f4df5a656e72a5c68e172bTinderbox User "private key not found\n",
3241ddcf9354c5ab50f4df5a656e72a5c68e172bTinderbox User "key not found\n",
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User "\tsig by %s/%s/%d retained\n",
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "\tsig by %s/%s/%d dropped - "
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "failed to verify");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "\tsig by %s/%s/%d retained\n",
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "\tsig by %s/%s/%d "
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "dropped - %s\n",
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "failed to verify");
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User ISC_LIST_APPEND(siglist.rdata, trdata, link);
0226754d9e537fd56b690d5890cfe215a6c59f89Tinderbox User signwithkey(name, set, trdata, key->key, &b);
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User ISC_LIST_APPEND(siglist.rdata, trdata, link);
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User check_result(result, "dns_db_dns_rdataset_first()/next()");
6b7cba2b10d6cb5363d94b434b0d22ecfb33a6f3Tinderbox User for (i = 0; i < 256; i++)
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User (notsigned || (wassignedby[alg] && !nowsignedby[alg])))
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User signwithkey(name, set, trdata, key->key, &b);
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User ISC_LIST_APPEND(siglist.rdata, trdata, link);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_rdatalist_tordataset(&siglist, &sigset);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_db_addrdataset(db, node, version, 0, &sigset,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt else if (!nosigs) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * If this is compiled in, running a signed set through the
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * signer with no private keys causes DNS_R_BADDB to occur
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * later. This is bad.
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User result = dns_db_deleterdataset(db, node, version,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User check_result(result, "dns_db_deleterdataset");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt fatal("File is currently signed but no private keys were "
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User "found. This won't work.");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt signer_array_t *next = ISC_LIST_NEXT(tdata, link);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt/* Determine if a KEY set contains a null key */
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt fatal("could not convert KEY into internal format");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * Looks for signatures of the zone keys by the parent, and imports them
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox Userimportparentsig(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
6b7cba2b10d6cb5363d94b434b0d22ecfb33a6f3Tinderbox User isc_buffer_init(&b, filename, sizeof(filename) - 10);
6b7cba2b10d6cb5363d94b434b0d22ecfb33a6f3Tinderbox User result = dns_name_totext(name, ISC_FALSE, &b);
6b7cba2b10d6cb5363d94b434b0d22ecfb33a6f3Tinderbox User strcpy((char *)r.base + r.length, "signedkey");
6b7cba2b10d6cb5363d94b434b0d22ecfb33a6f3Tinderbox User result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
d7a61cfbe56ebfa1682e949e48b4d08840234d8fTinderbox User result = dns_db_load(newdb, (char *)filename);
6b7cba2b10d6cb5363d94b434b0d22ecfb33a6f3Tinderbox User result = dns_db_findnode(newdb, name, ISC_FALSE, &newnode);
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User result = dns_db_findrdataset(newdb, newnode, NULL, dns_rdatatype_key,
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User if (dns_rdataset_count(set) != dns_rdataset_count(&newset))
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User check_result(result, "dns_rdataset_first()");
006283c42350464bc285c4481bce0a3b5a3dd8d0Tinderbox User for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(set)) {
006283c42350464bc285c4481bce0a3b5a3dd8d0Tinderbox User check_result(result, "dns_rdataset_first()");
6758b59e57af88bdf466e63c0856043df44f8dd0Tinderbox User if (dns_rdata_compare(&rdata, &newrdata) == 0)
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt vbprintf(2, "found the parent's signature of our zone key\n");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_db_addrdataset(db, node, version, 0, &sigset, 0, NULL);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * Looks for our signatures of child keys. If present, inform the caller,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * who will set the zone status (KEY) bit in the NXT record.
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User isc_buffer_init(&b, filename, sizeof(filename) - 10);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_db_findnode(newdb, name, ISC_FALSE, &newnode);
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User result = dns_db_findrdataset(newdb, newnode, NULL, dns_rdatatype_key,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(&sigset)) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_rdata_tostruct(&sigrdata, &sig, mctx);
46472a450e043434d78fa18edc73bca8c47f3981Tinderbox User result = dns_dnssec_verify(name, &set, key->key,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * Signs all records at a name. This mostly just signs each set individually,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * but also adds the SIG bit to any NXTs generated earlier, deals with
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * parent/child KEY signatures, and handles other exceptional cases.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntsignname(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User static int warnwild = 0;
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User fprintf(stderr, "%s: warning: BIND 9 doesn't properly "
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User "handle wildcards in secure zones:\n",
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User fprintf(stderr, "\t- wildcard nonexistence proof is "
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User "not generated by the server\n");
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User fprintf(stderr, "\t- wildcard nonexistence proof is "
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User "not required by the resolver\n");
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User fprintf(stderr, "%s: warning: wildcard name seen: %s\n",
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt /* Is this a delegation point? */
a179cbdf652095d00e7774320592f25eab0210d8Tinderbox User result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
a179cbdf652095d00e7774320592f25eab0210d8Tinderbox User check_result(result, "dns_db_allrdatasets()");
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User dns_rdatasetiter_current(rdsiter, &rdataset);
6b7cba2b10d6cb5363d94b434b0d22ecfb33a6f3Tinderbox User /* If this is a SIG set, skip it. */
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User * If this is a KEY set at the apex, look for a signedkey file.
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User if (rdataset.type == dns_rdatatype_key && atorigin) {
f33abec8a62ab6f2b867d7189dfffa72592c027bTinderbox User importparentsig(db, version, node, name, &rdataset);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * If this name is a delegation point, skip all records
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * except an NXT set, unless we're using null keys, in
46472a450e043434d78fa18edc73bca8c47f3981Tinderbox User * which case we need to check for a null key and add one
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * if it's not present.
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User * There probably should be a dns_nxtsetbit, but it can get
221870ba7bf08daf55db5a69a4de4bbdc4f2a93cTinderbox User * complicated if we need to extend the length of the
221870ba7bf08daf55db5a69a4de4bbdc4f2a93cTinderbox User * bit set. In this case, since the NXT bit is set and
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * SIG < NXT and KEY < NXT, the easy way works.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt unsigned char *nxt_bits;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein "setting KEY bit in NXT\n",
isc_buffer_usedregion(&b, &r);
dns_rdatatype_key, &r);
link);
result =
&keyset);
NULL);
skip:
static inline isc_boolean_t
if (!active)
if (!active) {
dns_rdatatype_nxt, 0);
return (active);
static inline isc_result_t
if (!active) {
return (result);
static inline isc_result_t
return (ISC_R_SUCCESS);
return (result);
lastcut);
if (!atorigin) {
0, &rdsiter);
sizeof(dns_name_t));
int len;
unsigned int nkeys, i;
for (i = 0; i < nkeys; i++) {
static isc_stdtime_t
char *endp;
usage(void) {
exit(0);
int i, ch;
char *endp;
unsigned int eflags;
switch (ch) {
usage();
if (!pseudorandom)
usage();
if (argc == 0) {
for (i = 0; i < argc; i++) {
usage();
argv[i]);