mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
2943. [func] Add support to load new keys into managed zones
without signing immediately with "rndc loadkeys".
Add support to link keys with "dnssec-keygen -S"
and "dnssec-settime -S". [RT #21351]
This commit is contained in:
parent
6ee897e2b3
commit
c6f4972c74
16 changed files with 809 additions and 196 deletions
5
CHANGES
5
CHANGES
|
|
@ -1,3 +1,8 @@
|
|||
2943. [func] Add support to load new keys into managed zones
|
||||
without signing immediately with "rndc loadkeys".
|
||||
Add support to link keys with "dnssec-keygen -S"
|
||||
and "dnssec-settime -S". [RT #21351]
|
||||
|
||||
2942. [contrib] zone2sqlite failed to setup the entropy sources.
|
||||
[RT #21610]
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: dnssec-keygen.c,v 1.112 2010/01/19 23:48:55 tbox Exp $ */
|
||||
/* $Id: dnssec-keygen.c,v 1.113 2010/08/16 22:21:06 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
|
|
@ -92,27 +92,27 @@ usage(void) {
|
|||
"NSEC3RSASHA1 if using -3)\n");
|
||||
fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
|
||||
fprintf(stderr, " -b <key size in bits>:\n");
|
||||
fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " DH:\t\t[128..4096]\n");
|
||||
fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
|
||||
fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible "
|
||||
fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA);
|
||||
fprintf(stderr, " DH:\t\t[128..4096]\n");
|
||||
fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
|
||||
fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible "
|
||||
"by 64\n");
|
||||
fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
|
||||
fprintf(stderr, " HMAC-SHA1:\t[1..160]\n");
|
||||
fprintf(stderr, " HMAC-SHA224:\t[1..224]\n");
|
||||
fprintf(stderr, " HMAC-SHA256:\t[1..256]\n");
|
||||
fprintf(stderr, " HMAC-SHA384:\t[1..384]\n");
|
||||
fprintf(stderr, " HMAC-SHA512:\t[1..512]\n");
|
||||
fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
|
||||
fprintf(stderr, " HMAC-SHA1:\t[1..160]\n");
|
||||
fprintf(stderr, " HMAC-SHA224:\t[1..224]\n");
|
||||
fprintf(stderr, " HMAC-SHA256:\t[1..256]\n");
|
||||
fprintf(stderr, " HMAC-SHA384:\t[1..384]\n");
|
||||
fprintf(stderr, " HMAC-SHA512:\t[1..512]\n");
|
||||
fprintf(stderr, " (if using the default algorithm, key size\n"
|
||||
" defaults to 2048 for KSK, or 1024 for all "
|
||||
"others)\n");
|
||||
fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | "
|
||||
"USER | OTHER\n");
|
||||
fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
|
||||
fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
|
||||
fprintf(stderr, " -c <class>: (default: IN)\n");
|
||||
fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
|
||||
#ifdef USE_PKCS11
|
||||
|
|
@ -136,7 +136,7 @@ usage(void) {
|
|||
|
||||
fprintf(stderr, " -h: print usage and exit\n");
|
||||
fprintf(stderr, " -m <memory debugging mode>:\n");
|
||||
fprintf(stderr, " usage | trace | record | size | mctx\n");
|
||||
fprintf(stderr, " usage | trace | record | size | mctx\n");
|
||||
fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n");
|
||||
fprintf(stderr, "Timing options:\n");
|
||||
fprintf(stderr, " -P date/[+-]offset/none: set key publication date "
|
||||
|
|
@ -151,6 +151,11 @@ usage(void) {
|
|||
fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
|
||||
fprintf(stderr, " -C: generate a backward-compatible key, omitting "
|
||||
"all dates\n");
|
||||
fprintf(stderr, " -S <key>: generate a successor to an existing "
|
||||
"key\n");
|
||||
fprintf(stderr, " -i <interval>: prepublication interval for "
|
||||
"successor key "
|
||||
"(default: 30 days)\n");
|
||||
fprintf(stderr, "Output:\n");
|
||||
fprintf(stderr, " K<name>+<alg>+<id>.key, "
|
||||
"K<name>+<alg>+<id>.private\n");
|
||||
|
|
@ -190,7 +195,7 @@ progress(int p)
|
|||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
char *algname = NULL, *nametype = NULL, *type = NULL;
|
||||
char *algname = NULL, *nametype = NULL, *type = NULL;
|
||||
char *classname = NULL;
|
||||
char *endp;
|
||||
dst_key_t *key = NULL;
|
||||
|
|
@ -207,6 +212,8 @@ main(int argc, char **argv) {
|
|||
isc_textregion_t r;
|
||||
char filename[255];
|
||||
const char *directory = NULL;
|
||||
const char *predecessor = NULL;
|
||||
dst_key_t *prevkey = NULL;
|
||||
isc_buffer_t buf;
|
||||
isc_log_t *log = NULL;
|
||||
isc_entropy_t *ectx = NULL;
|
||||
|
|
@ -222,6 +229,7 @@ main(int argc, char **argv) {
|
|||
isc_stdtime_t publish = 0, activate = 0, revoke = 0;
|
||||
isc_stdtime_t inactive = 0, delete = 0;
|
||||
isc_stdtime_t now;
|
||||
int prepub = -1;
|
||||
isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE;
|
||||
isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE;
|
||||
isc_boolean_t setdel = ISC_FALSE;
|
||||
|
|
@ -243,7 +251,7 @@ main(int argc, char **argv) {
|
|||
/*
|
||||
* Process memory debugging argument first.
|
||||
*/
|
||||
#define CMDLINE_FLAGS "3a:b:Cc:d:E:eFf:g:K:km:n:p:qr:s:T:t:v:hGP:A:R:I:D:"
|
||||
#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:km:n:P:p:qR:r:S:s:T:t:v:"
|
||||
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
|
||||
switch (ch) {
|
||||
case 'm':
|
||||
|
|
@ -436,6 +444,12 @@ main(int argc, char **argv) {
|
|||
unsetdel = ISC_TRUE;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
predecessor = isc_commandline_argument;
|
||||
break;
|
||||
case 'i':
|
||||
prepub = strtottl(isc_commandline_argument);
|
||||
break;
|
||||
case 'F':
|
||||
/* Reserved for FIPS mode */
|
||||
/* FALLTHROUGH */
|
||||
|
|
@ -467,87 +481,205 @@ main(int argc, char **argv) {
|
|||
|
||||
setup_logging(verbose, mctx, &log);
|
||||
|
||||
if (argc < isc_commandline_index + 1)
|
||||
fatal("the key name was not specified");
|
||||
if (argc > isc_commandline_index + 1)
|
||||
fatal("extraneous arguments");
|
||||
if (predecessor == NULL) {
|
||||
if (prepub == -1)
|
||||
prepub = 0;
|
||||
|
||||
if (algname == NULL) {
|
||||
use_default = ISC_TRUE;
|
||||
if (use_nsec3)
|
||||
algname = strdup(DEFAULT_NSEC3_ALGORITHM);
|
||||
else
|
||||
algname = strdup(DEFAULT_ALGORITHM);
|
||||
if (verbose > 0)
|
||||
fprintf(stderr, "no algorithm specified; "
|
||||
"defaulting to %s\n", algname);
|
||||
}
|
||||
if (argc < isc_commandline_index + 1)
|
||||
fatal("the key name was not specified");
|
||||
if (argc > isc_commandline_index + 1)
|
||||
fatal("extraneous arguments");
|
||||
|
||||
if (strcasecmp(algname, "RSA") == 0) {
|
||||
fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n"
|
||||
"If you still wish to use RSA (RSAMD5) please "
|
||||
"specify \"-a RSAMD5\"\n");
|
||||
return (1);
|
||||
} else if (strcasecmp(algname, "HMAC-MD5") == 0) {
|
||||
options |= DST_TYPE_KEY;
|
||||
alg = DST_ALG_HMACMD5;
|
||||
} else if (strcasecmp(algname, "HMAC-SHA1") == 0) {
|
||||
options |= DST_TYPE_KEY;
|
||||
alg = DST_ALG_HMACSHA1;
|
||||
} else if (strcasecmp(algname, "HMAC-SHA224") == 0) {
|
||||
options |= DST_TYPE_KEY;
|
||||
alg = DST_ALG_HMACSHA224;
|
||||
} else if (strcasecmp(algname, "HMAC-SHA256") == 0) {
|
||||
options |= DST_TYPE_KEY;
|
||||
alg = DST_ALG_HMACSHA256;
|
||||
} else if (strcasecmp(algname, "HMAC-SHA384") == 0) {
|
||||
options |= DST_TYPE_KEY;
|
||||
alg = DST_ALG_HMACSHA384;
|
||||
} else if (strcasecmp(algname, "HMAC-SHA512") == 0) {
|
||||
options |= DST_TYPE_KEY;
|
||||
alg = DST_ALG_HMACSHA512;
|
||||
} else {
|
||||
r.base = algname;
|
||||
r.length = strlen(algname);
|
||||
ret = dns_secalg_fromtext(&alg, &r);
|
||||
dns_fixedname_init(&fname);
|
||||
name = dns_fixedname_name(&fname);
|
||||
isc_buffer_init(&buf, argv[isc_commandline_index],
|
||||
strlen(argv[isc_commandline_index]));
|
||||
isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
|
||||
ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
fatal("unknown algorithm %s", algname);
|
||||
if (alg == DST_ALG_DH)
|
||||
options |= DST_TYPE_KEY;
|
||||
}
|
||||
fatal("invalid key name %s: %s",
|
||||
argv[isc_commandline_index],
|
||||
isc_result_totext(ret));
|
||||
|
||||
if (use_nsec3 &&
|
||||
alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 &&
|
||||
alg != DST_ALG_RSASHA256 && alg!= DST_ALG_RSASHA512) {
|
||||
fatal("%s is incompatible with NSEC3; "
|
||||
"do not use the -3 option", algname);
|
||||
}
|
||||
|
||||
if (type != NULL && (options & DST_TYPE_KEY) != 0) {
|
||||
if (strcasecmp(type, "NOAUTH") == 0)
|
||||
flags |= DNS_KEYTYPE_NOAUTH;
|
||||
else if (strcasecmp(type, "NOCONF") == 0)
|
||||
flags |= DNS_KEYTYPE_NOCONF;
|
||||
else if (strcasecmp(type, "NOAUTHCONF") == 0) {
|
||||
flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF);
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
}
|
||||
else if (strcasecmp(type, "AUTHCONF") == 0)
|
||||
/* nothing */;
|
||||
else
|
||||
fatal("invalid type %s", type);
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
if (use_default) {
|
||||
size = ((kskflag & DNS_KEYFLAG_KSK) != 0) ? 2048 : 1024;
|
||||
if (algname == NULL) {
|
||||
use_default = ISC_TRUE;
|
||||
if (use_nsec3)
|
||||
algname = strdup(DEFAULT_NSEC3_ALGORITHM);
|
||||
else
|
||||
algname = strdup(DEFAULT_ALGORITHM);
|
||||
if (verbose > 0)
|
||||
fprintf(stderr, "key size not specified; "
|
||||
"defaulting to %d\n", size);
|
||||
} else {
|
||||
fatal("key size not specified (-b option)");
|
||||
fprintf(stderr, "no algorithm specified; "
|
||||
"defaulting to %s\n", algname);
|
||||
}
|
||||
|
||||
if (strcasecmp(algname, "RSA") == 0) {
|
||||
fprintf(stderr, "The use of RSA (RSAMD5) is not "
|
||||
"recommended.\nIf you still wish to "
|
||||
"use RSA (RSAMD5) please specify "
|
||||
"\"-a RSAMD5\"\n");
|
||||
return (1);
|
||||
} else if (strcasecmp(algname, "HMAC-MD5") == 0)
|
||||
alg = DST_ALG_HMACMD5;
|
||||
else if (strcasecmp(algname, "HMAC-SHA1") == 0)
|
||||
alg = DST_ALG_HMACSHA1;
|
||||
else if (strcasecmp(algname, "HMAC-SHA224") == 0)
|
||||
alg = DST_ALG_HMACSHA224;
|
||||
else if (strcasecmp(algname, "HMAC-SHA256") == 0)
|
||||
alg = DST_ALG_HMACSHA256;
|
||||
else if (strcasecmp(algname, "HMAC-SHA384") == 0)
|
||||
alg = DST_ALG_HMACSHA384;
|
||||
else if (strcasecmp(algname, "HMAC-SHA512") == 0)
|
||||
alg = DST_ALG_HMACSHA512;
|
||||
else {
|
||||
r.base = algname;
|
||||
r.length = strlen(algname);
|
||||
ret = dns_secalg_fromtext(&alg, &r);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
fatal("unknown algorithm %s", algname);
|
||||
if (alg == DST_ALG_DH)
|
||||
options |= DST_TYPE_KEY;
|
||||
}
|
||||
|
||||
if (use_nsec3 &&
|
||||
alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 &&
|
||||
alg != DST_ALG_RSASHA256 && alg!= DST_ALG_RSASHA512) {
|
||||
fatal("%s is incompatible with NSEC3; "
|
||||
"do not use the -3 option", algname);
|
||||
}
|
||||
|
||||
if (type != NULL && (options & DST_TYPE_KEY) != 0) {
|
||||
if (strcasecmp(type, "NOAUTH") == 0)
|
||||
flags |= DNS_KEYTYPE_NOAUTH;
|
||||
else if (strcasecmp(type, "NOCONF") == 0)
|
||||
flags |= DNS_KEYTYPE_NOCONF;
|
||||
else if (strcasecmp(type, "NOAUTHCONF") == 0) {
|
||||
flags |= (DNS_KEYTYPE_NOAUTH |
|
||||
DNS_KEYTYPE_NOCONF);
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
}
|
||||
else if (strcasecmp(type, "AUTHCONF") == 0)
|
||||
/* nothing */;
|
||||
else
|
||||
fatal("invalid type %s", type);
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
if (use_default) {
|
||||
if ((kskflag & DNS_KEYFLAG_KSK) != 0)
|
||||
size = 2048;
|
||||
else
|
||||
size = 1024;
|
||||
if (verbose > 0)
|
||||
fprintf(stderr, "key size not "
|
||||
"specified; defaulting "
|
||||
"to %d\n", size);
|
||||
} else {
|
||||
fatal("key size not specified (-b option)");
|
||||
}
|
||||
}
|
||||
|
||||
if (!oldstyle && prepub > 0) {
|
||||
if (setpub && setact && (activate - prepub) < publish)
|
||||
fatal("Activation and publication dates "
|
||||
"are closer together than the\n\t"
|
||||
"prepublication interval.");
|
||||
|
||||
if (!setpub && !setact) {
|
||||
setpub = setact = ISC_TRUE;
|
||||
publish = now;
|
||||
activate = now + prepub;
|
||||
} else if (setpub && !setact) {
|
||||
setact = ISC_TRUE;
|
||||
activate = publish + prepub;
|
||||
} else if (setact && !setpub) {
|
||||
setpub = ISC_TRUE;
|
||||
publish = activate - prepub;
|
||||
}
|
||||
|
||||
if ((activate - prepub) < now)
|
||||
fatal("Time until activation is shorter "
|
||||
"than the\n\tprepublication interval.");
|
||||
}
|
||||
} else {
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
isc_stdtime_t when;
|
||||
int major, minor;
|
||||
|
||||
if (prepub == -1)
|
||||
prepub = (30 * 86400);
|
||||
|
||||
if (algname != NULL)
|
||||
fatal("-S and -a cannot be used together");
|
||||
if (size >= 0)
|
||||
fatal("-S and -b cannot be used together");
|
||||
if (nametype != NULL)
|
||||
fatal("-S and -n cannot be used together");
|
||||
if (type != NULL)
|
||||
fatal("-S and -t cannot be used together");
|
||||
if (setpub || unsetpub)
|
||||
fatal("-S and -P cannot be used together");
|
||||
if (setact || unsetact)
|
||||
fatal("-S and -A cannot be used together");
|
||||
if (use_nsec3)
|
||||
fatal("-S and -3 cannot be used together");
|
||||
if (oldstyle)
|
||||
fatal("-S and -C cannot be used together");
|
||||
if (genonly)
|
||||
fatal("-S and -G cannot be used together");
|
||||
|
||||
ret = dst_key_fromnamedfile(predecessor, directory,
|
||||
DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
|
||||
mctx, &prevkey);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
fatal("Invalid keyfile %s: %s",
|
||||
filename, isc_result_totext(ret));
|
||||
if (!dst_key_isprivate(prevkey))
|
||||
fatal("%s is not a private key", filename);
|
||||
|
||||
name = dst_key_name(prevkey);
|
||||
alg = dst_key_alg(prevkey);
|
||||
size = dst_key_size(prevkey);
|
||||
flags = dst_key_flags(prevkey);
|
||||
|
||||
dst_key_format(prevkey, keystr, sizeof(keystr));
|
||||
dst_key_getprivateformat(prevkey, &major, &minor);
|
||||
if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
|
||||
fatal("Key %s has incompatible format version %d.%d\n\t"
|
||||
"It is not possible to generate a successor key.",
|
||||
keystr, major, minor);
|
||||
|
||||
ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
fatal("Key %s has no activation date.\n\t"
|
||||
"You must use dnssec-settime -A to set one "
|
||||
"before generating a successor.", keystr);
|
||||
|
||||
ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
fatal("Key %s has no inactivation date.\n\t"
|
||||
"You must use dnssec-settime -I to set one "
|
||||
"before generating a successor.", keystr);
|
||||
|
||||
publish = activate - prepub;
|
||||
if (publish < now)
|
||||
fatal("Key %s becomes inactive\n\t"
|
||||
"sooner than the prepublication period "
|
||||
"for the new key ends.\n\t"
|
||||
"Either change the inactivation date with "
|
||||
"dnssec-settime -I,\n\t"
|
||||
"or use the -i option to set a shorter "
|
||||
"prepublication interval.", keystr);
|
||||
|
||||
ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
fprintf(stderr, "%s: WARNING: Key %s has no removal "
|
||||
"date;\n\t it will remain in the zone "
|
||||
"indefinitely after rollover.\n\t "
|
||||
"You can use dnssec-settime -D to "
|
||||
"change this.\n", program, keystr);
|
||||
|
||||
setpub = setact = ISC_TRUE;
|
||||
}
|
||||
|
||||
switch (alg) {
|
||||
|
|
@ -572,6 +704,7 @@ main(int argc, char **argv) {
|
|||
fatal("invalid DSS key size: %d", size);
|
||||
break;
|
||||
case DST_ALG_HMACMD5:
|
||||
options |= DST_TYPE_KEY;
|
||||
if (size < 1 || size > 512)
|
||||
fatal("HMAC-MD5 key size %d out of range", size);
|
||||
if (dbits != 0 && (dbits < 80 || dbits > 128))
|
||||
|
|
@ -581,6 +714,7 @@ main(int argc, char **argv) {
|
|||
dbits);
|
||||
break;
|
||||
case DST_ALG_HMACSHA1:
|
||||
options |= DST_TYPE_KEY;
|
||||
if (size < 1 || size > 160)
|
||||
fatal("HMAC-SHA1 key size %d out of range", size);
|
||||
if (dbits != 0 && (dbits < 80 || dbits > 160))
|
||||
|
|
@ -590,6 +724,7 @@ main(int argc, char **argv) {
|
|||
dbits);
|
||||
break;
|
||||
case DST_ALG_HMACSHA224:
|
||||
options |= DST_TYPE_KEY;
|
||||
if (size < 1 || size > 224)
|
||||
fatal("HMAC-SHA224 key size %d out of range", size);
|
||||
if (dbits != 0 && (dbits < 112 || dbits > 224))
|
||||
|
|
@ -599,6 +734,7 @@ main(int argc, char **argv) {
|
|||
dbits);
|
||||
break;
|
||||
case DST_ALG_HMACSHA256:
|
||||
options |= DST_TYPE_KEY;
|
||||
if (size < 1 || size > 256)
|
||||
fatal("HMAC-SHA256 key size %d out of range", size);
|
||||
if (dbits != 0 && (dbits < 128 || dbits > 256))
|
||||
|
|
@ -608,6 +744,7 @@ main(int argc, char **argv) {
|
|||
dbits);
|
||||
break;
|
||||
case DST_ALG_HMACSHA384:
|
||||
options |= DST_TYPE_KEY;
|
||||
if (size < 1 || size > 384)
|
||||
fatal("HMAC-384 key size %d out of range", size);
|
||||
if (dbits != 0 && (dbits < 192 || dbits > 384))
|
||||
|
|
@ -617,6 +754,7 @@ main(int argc, char **argv) {
|
|||
dbits);
|
||||
break;
|
||||
case DST_ALG_HMACSHA512:
|
||||
options |= DST_TYPE_KEY;
|
||||
if (size < 1 || size > 512)
|
||||
fatal("HMAC-SHA512 key size %d out of range", size);
|
||||
if (dbits != 0 && (dbits < 256 || dbits > 512))
|
||||
|
|
@ -685,16 +823,6 @@ main(int argc, char **argv) {
|
|||
fatal("a key with algorithm '%s' cannot be a zone key",
|
||||
algname);
|
||||
|
||||
dns_fixedname_init(&fname);
|
||||
name = dns_fixedname_name(&fname);
|
||||
isc_buffer_init(&buf, argv[isc_commandline_index],
|
||||
strlen(argv[isc_commandline_index]));
|
||||
isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
|
||||
ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
fatal("invalid key name %s: %s", argv[isc_commandline_index],
|
||||
isc_result_totext(ret));
|
||||
|
||||
switch(alg) {
|
||||
case DNS_KEYALG_RSAMD5:
|
||||
case DNS_KEYALG_RSASHA1:
|
||||
|
|
@ -763,9 +891,18 @@ main(int argc, char **argv) {
|
|||
/*
|
||||
* Set key timing metadata (unless using -C)
|
||||
*
|
||||
* Publish and activation dates are set to "now" by default,
|
||||
* but can be overridden. Creation date is always set to
|
||||
* "now".
|
||||
* Creation date is always set to "now".
|
||||
*
|
||||
* For a new key without an explicit predecessor, publish
|
||||
* and activation dates are set to "now" by default, but
|
||||
* can both be overridden.
|
||||
*
|
||||
* For a successor key, activation is set to match the
|
||||
* predecessor's inactivation date. Publish is set to 30
|
||||
* days earlier than that (XXX: this should be configurable).
|
||||
* If either of the resulting dates are in the past, that's
|
||||
* an error; the inactivation date of the predecessor key
|
||||
* must be updated before a successor key can be created.
|
||||
*/
|
||||
if (!oldstyle) {
|
||||
dst_key_settime(key, DST_TIME_CREATED, now);
|
||||
|
|
@ -860,6 +997,8 @@ main(int argc, char **argv) {
|
|||
ret = dst_key_buildfilename(key, 0, NULL, &buf);
|
||||
printf("%s\n", filename);
|
||||
dst_key_free(&key);
|
||||
if (prevkey != NULL)
|
||||
dst_key_free(&prevkey);
|
||||
|
||||
cleanup_logging(&log);
|
||||
cleanup_entropy(&ectx);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- $Id: dnssec-keygen.docbook,v 1.33 2009/11/03 21:44:46 each Exp $ -->
|
||||
<!-- $Id: dnssec-keygen.docbook,v 1.34 2010/08/16 22:21:06 marka Exp $ -->
|
||||
<refentry id="man.dnssec-keygen">
|
||||
<refentryinfo>
|
||||
<date>June 30, 2000</date>
|
||||
|
|
@ -71,6 +71,7 @@
|
|||
<arg><option>-g <replaceable class="parameter">generator</replaceable></option></arg>
|
||||
<arg><option>-h</option></arg>
|
||||
<arg><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg>
|
||||
<arg><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
|
||||
<arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
|
||||
<arg><option>-k</option></arg>
|
||||
<arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
|
||||
|
|
@ -78,6 +79,7 @@
|
|||
<arg><option>-q</option></arg>
|
||||
<arg><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg>
|
||||
<arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
|
||||
<arg><option>-S <replaceable class="parameter">key</replaceable></option></arg>
|
||||
<arg><option>-s <replaceable class="parameter">strength</replaceable></option></arg>
|
||||
<arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
|
||||
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
|
||||
|
|
@ -341,6 +343,21 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-S <replaceable class="parameter">key</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Create a new key which is an explicit successor to an
|
||||
existing key. The name, algorithm, size, and type of the
|
||||
key will be set to match the existing key. The activation
|
||||
date of the new key will be set to the inactivation date of
|
||||
the existing one. The publication date will be set to the
|
||||
activation date minus the prepublication interval, which
|
||||
defaults to 30 days.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-s <replaceable class="parameter">strength</replaceable></term>
|
||||
<listitem>
|
||||
|
|
@ -463,6 +480,34 @@
|
|||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-i <replaceable class="parameter">interval</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the prepublication interval for a key. If set, then
|
||||
the publication and activation dates must be separated by at least
|
||||
this much time. If the activation date is specified but the
|
||||
publication date isn't, then the publication date will default
|
||||
to this much time before the activation date; conversely, if
|
||||
the publication date is specified but activation date isn't,
|
||||
then activation will be set to this much time after publication.
|
||||
</para>
|
||||
<para>
|
||||
If the key is being created as an explicit successor to another
|
||||
key, then the default prepublication interval is 30 days;
|
||||
otherwise it is zero.
|
||||
</para>
|
||||
<para>
|
||||
As with date offsets, if the argument is followed by one of
|
||||
the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
|
||||
interval is measured in years, months, weeks, days, hours,
|
||||
or minutes, respectively. Without a suffix, the interval is
|
||||
measured in seconds.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: dnssec-settime.c,v 1.25 2010/02/03 01:02:37 each Exp $ */
|
||||
/* $Id: dnssec-settime.c,v 1.26 2010/08/16 22:21:06 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
|
|
@ -117,20 +117,27 @@ printtime(dst_key_t *key, int type, const char *tag, isc_boolean_t epoch,
|
|||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
isc_result_t result;
|
||||
isc_result_t result;
|
||||
#ifdef USE_PKCS11
|
||||
const char *engine = "pkcs11";
|
||||
const char *engine = "pkcs11";
|
||||
#else
|
||||
const char *engine = NULL;
|
||||
const char *engine = NULL;
|
||||
#endif
|
||||
char *filename = NULL, *directory = NULL;
|
||||
char newname[1024];
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
char *endp, *p;
|
||||
int ch;
|
||||
isc_entropy_t *ectx = NULL;
|
||||
dst_key_t *key = NULL;
|
||||
isc_buffer_t buf;
|
||||
char *filename = NULL, *directory = NULL;
|
||||
char newname[1024];
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
char *endp, *p;
|
||||
int ch;
|
||||
isc_entropy_t *ectx = NULL;
|
||||
const char *predecessor = NULL;
|
||||
dst_key_t *prevkey = NULL;
|
||||
dst_key_t *key = NULL;
|
||||
isc_buffer_t buf;
|
||||
dns_name_t *name = NULL;
|
||||
dns_secalg_t alg = 0;
|
||||
unsigned int size = 0;
|
||||
isc_uint16_t flags = 0;
|
||||
int prepub = -1;
|
||||
isc_stdtime_t now;
|
||||
isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0;
|
||||
isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE;
|
||||
|
|
@ -159,8 +166,8 @@ main(int argc, char **argv) {
|
|||
|
||||
isc_stdtime_get(&now);
|
||||
|
||||
while ((ch = isc_commandline_parse(argc, argv,
|
||||
"E:fK:uhp:v:P:A:R:I:D:")) != -1) {
|
||||
#define CMDLINE_FLAGS "A:D:E:fhI:i:K:P:p:R:S:uv:"
|
||||
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
|
||||
switch (ch) {
|
||||
case 'E':
|
||||
engine = isc_commandline_argument;
|
||||
|
|
@ -293,6 +300,12 @@ main(int argc, char **argv) {
|
|||
now, now);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
predecessor = isc_commandline_argument;
|
||||
break;
|
||||
case 'i':
|
||||
prepub = strtottl(isc_commandline_argument);
|
||||
break;
|
||||
case '?':
|
||||
if (isc_commandline_option != '?')
|
||||
fprintf(stderr, "%s: invalid argument -%c\n",
|
||||
|
|
@ -314,17 +327,6 @@ main(int argc, char **argv) {
|
|||
if (argc > isc_commandline_index + 1)
|
||||
fatal("Extraneous arguments");
|
||||
|
||||
if (directory != NULL) {
|
||||
filename = argv[isc_commandline_index];
|
||||
} else {
|
||||
result = isc_file_splitpath(mctx, argv[isc_commandline_index],
|
||||
&directory, &filename);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("cannot process filename %s: %s",
|
||||
argv[isc_commandline_index],
|
||||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
if (ectx == NULL)
|
||||
setup_entropy(mctx, NULL, &ectx);
|
||||
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
|
||||
|
|
@ -337,6 +339,105 @@ main(int argc, char **argv) {
|
|||
isc_result_totext(result));
|
||||
isc_entropy_stopcallbacksources(ectx);
|
||||
|
||||
if (predecessor != NULL) {
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
isc_stdtime_t when;
|
||||
int major, minor;
|
||||
|
||||
if (prepub == -1)
|
||||
prepub = (30 * 86400);
|
||||
|
||||
if (setpub || unsetpub)
|
||||
fatal("-S and -P cannot be used together");
|
||||
if (setact || unsetact)
|
||||
fatal("-S and -A cannot be used together");
|
||||
|
||||
result = dst_key_fromnamedfile(predecessor, directory,
|
||||
DST_TYPE_PUBLIC |
|
||||
DST_TYPE_PRIVATE,
|
||||
mctx, &prevkey);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("Invalid keyfile %s: %s",
|
||||
filename, isc_result_totext(result));
|
||||
if (!dst_key_isprivate(prevkey))
|
||||
fatal("%s is not a private key", filename);
|
||||
|
||||
name = dst_key_name(prevkey);
|
||||
alg = dst_key_alg(prevkey);
|
||||
size = dst_key_size(prevkey);
|
||||
flags = dst_key_flags(prevkey);
|
||||
|
||||
dst_key_format(prevkey, keystr, sizeof(keystr));
|
||||
dst_key_getprivateformat(prevkey, &major, &minor);
|
||||
if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
|
||||
fatal("Predecessor has incompatible format "
|
||||
"version %d.%d\n\t", major, minor);
|
||||
|
||||
result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("Predecessor has no activation date. "
|
||||
"You must set one before\n\t"
|
||||
"generating a successor.");
|
||||
|
||||
result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &act);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("Predecessor has no inactivation date. "
|
||||
"You must set one before\n\t"
|
||||
"generating a successor.");
|
||||
|
||||
pub = act - prepub;
|
||||
if (pub < now)
|
||||
fatal("Predecessor will become inactive before the\n\t"
|
||||
"prepublication period ends. Either change "
|
||||
"its inactivation date,\n\t"
|
||||
"or use the -i option to set a shorter "
|
||||
"prepublication interval.");
|
||||
|
||||
result = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fprintf(stderr, "%s: WARNING: Predecessor has no "
|
||||
"removal date;\n\t"
|
||||
"it will remain in the zone "
|
||||
"indefinitely after rollover.\n",
|
||||
program);
|
||||
|
||||
changed = setpub = setact = ISC_TRUE;
|
||||
dst_key_free(&prevkey);
|
||||
} else {
|
||||
if (prepub < 0)
|
||||
prepub = 0;
|
||||
|
||||
if (prepub > 0) {
|
||||
if (setpub && setact && (act - prepub) < pub)
|
||||
fatal("Activation and publication dates "
|
||||
"are closer together than the\n\t"
|
||||
"prepublication interval.");
|
||||
|
||||
if (setpub && !setact) {
|
||||
setact = ISC_TRUE;
|
||||
act = pub + prepub;
|
||||
} else if (setact && !setpub) {
|
||||
setpub = ISC_TRUE;
|
||||
pub = act - prepub;
|
||||
}
|
||||
|
||||
if ((act - prepub) < now)
|
||||
fatal("Time until activation is shorter "
|
||||
"than the\n\tprepublication interval.");
|
||||
}
|
||||
}
|
||||
|
||||
if (directory != NULL) {
|
||||
filename = argv[isc_commandline_index];
|
||||
} else {
|
||||
result = isc_file_splitpath(mctx, argv[isc_commandline_index],
|
||||
&directory, &filename);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("cannot process filename %s: %s",
|
||||
argv[isc_commandline_index],
|
||||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
result = dst_key_fromnamedfile(filename, directory,
|
||||
DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
|
||||
mctx, &key);
|
||||
|
|
@ -349,6 +450,17 @@ main(int argc, char **argv) {
|
|||
|
||||
dst_key_format(key, keystr, sizeof(keystr));
|
||||
|
||||
if (predecessor != NULL) {
|
||||
if (!dns_name_equal(name, dst_key_name(key)))
|
||||
fatal("Key name mismatch");
|
||||
if (alg != dst_key_alg(key))
|
||||
fatal("Key algorithm mismatch");
|
||||
if (size != dst_key_size(key))
|
||||
fatal("Key size mismatch");
|
||||
if (flags != dst_key_flags(key))
|
||||
fatal("Key flags mismatch");
|
||||
}
|
||||
|
||||
if (force)
|
||||
set_keyversion(key);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- $Id: dnssec-settime.docbook,v 1.10 2010/03/09 03:35:34 marka Exp $ -->
|
||||
<!-- $Id: dnssec-settime.docbook,v 1.11 2010/08/16 22:21:06 marka Exp $ -->
|
||||
<refentry id="man.dnssec-settime">
|
||||
<refentryinfo>
|
||||
<date>July 15, 2009</date>
|
||||
|
|
@ -211,6 +211,47 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-S <replaceable class="parameter">predecessor key</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Select a key for which the key being modified will be an
|
||||
explicit successor. The name, algorithm, size, and type of the
|
||||
predecessor key must exactly match those of the key being
|
||||
modified. The activation date of the successor key will be set
|
||||
to the inactivation date of the predecessor. The publication
|
||||
date will be set to the activation date minus the prepublication
|
||||
interval, which defaults to 30 days.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-i <replaceable class="parameter">interval</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the prepublication interval for a key. If set, then
|
||||
the publication and activation dates must be separated by at least
|
||||
this much time. If the activation date is specified but the
|
||||
publication date isn't, then the publication date will default
|
||||
to this much time before the activation date; conversely, if
|
||||
the publication date is specified but activation date isn't,
|
||||
then activation will be set to this much time after publication.
|
||||
</para>
|
||||
<para>
|
||||
If the key is being set to be an explicit successor to another
|
||||
key, then the default prepublication interval is 30 days;
|
||||
otherwise it is zero.
|
||||
</para>
|
||||
<para>
|
||||
As with date offsets, if the argument is followed by one of
|
||||
the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
|
||||
interval is measured in years, months, weeks, days, hours,
|
||||
or minutes, respectively. Without a suffix, the interval is
|
||||
measured in seconds.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: control.c,v 1.39 2010/07/11 00:12:57 each Exp $ */
|
||||
/* $Id: control.c,v 1.40 2010/08/16 22:21:06 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
|
|
@ -189,8 +189,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
|
|||
result = ns_server_notifycommand(ns_g_server, command, text);
|
||||
} else if (command_compare(command, NS_COMMAND_VALIDATION)) {
|
||||
result = ns_server_validation(ns_g_server, command);
|
||||
} else if (command_compare(command, NS_COMMAND_SIGN)) {
|
||||
result = ns_server_sign(ns_g_server, command);
|
||||
} else if (command_compare(command, NS_COMMAND_SIGN) ||
|
||||
command_compare(command, NS_COMMAND_LOADKEYS)) {
|
||||
result = ns_server_rekey(ns_g_server, command);
|
||||
} else if (command_compare(command, NS_COMMAND_ADDZONE)) {
|
||||
result = ns_server_add_zone(ns_g_server, command);
|
||||
} else if (command_compare(command, NS_COMMAND_DELZONE)) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: control.h,v 1.30 2010/07/11 00:12:57 each Exp $ */
|
||||
/* $Id: control.h,v 1.31 2010/08/16 22:21:06 marka Exp $ */
|
||||
|
||||
#ifndef NAMED_CONTROL_H
|
||||
#define NAMED_CONTROL_H 1
|
||||
|
|
@ -59,6 +59,7 @@
|
|||
#define NS_COMMAND_NOTIFY "notify"
|
||||
#define NS_COMMAND_VALIDATION "validation"
|
||||
#define NS_COMMAND_SIGN "sign"
|
||||
#define NS_COMMAND_LOADKEYS "loadkeys"
|
||||
#define NS_COMMAND_ADDZONE "addzone"
|
||||
#define NS_COMMAND_DELZONE "delzone"
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.h,v 1.108 2010/07/11 00:12:57 each Exp $ */
|
||||
/* $Id: server.h,v 1.109 2010/08/16 22:21:06 marka Exp $ */
|
||||
|
||||
#ifndef NAMED_SERVER_H
|
||||
#define NAMED_SERVER_H 1
|
||||
|
|
@ -295,11 +295,14 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
|
|||
isc_buffer_t *text);
|
||||
|
||||
/*%
|
||||
* Update a zone's DNSKEY set from the key repository, and re-sign the
|
||||
* zone if there were any changes.
|
||||
* Update a zone's DNSKEY set from the key repository. If
|
||||
* the command that triggered the call to this function was "sign",
|
||||
* then force a full signing of the zone. If it was "loadkeys",
|
||||
* then don't sign the zone; any needed changes to signatures can
|
||||
* take place incrementally.
|
||||
*/
|
||||
isc_result_t
|
||||
ns_server_sign(ns_server_t *server, char *args);
|
||||
ns_server_rekey(ns_server_t *server, char *args);
|
||||
|
||||
/*%
|
||||
* Dump the current recursive queries.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.c,v 1.579 2010/08/13 14:33:31 fdupont Exp $ */
|
||||
/* $Id: server.c,v 1.580 2010/08/16 22:21:06 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
|
|
@ -6466,14 +6466,18 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Act on a "sign" command from the command channel.
|
||||
* Act on a "sign" or "loadkeys" command from the command channel.
|
||||
*/
|
||||
isc_result_t
|
||||
ns_server_sign(ns_server_t *server, char *args) {
|
||||
ns_server_rekey(ns_server_t *server, char *args) {
|
||||
isc_result_t result;
|
||||
dns_zone_t *zone = NULL;
|
||||
dns_zonetype_t type;
|
||||
isc_uint16_t keyopts;
|
||||
isc_boolean_t fullsign = ISC_FALSE;
|
||||
|
||||
if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0)
|
||||
fullsign = ISC_TRUE;
|
||||
|
||||
result = zone_from_args(server, args, &zone, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
|
|
@ -6488,10 +6492,14 @@ ns_server_sign(ns_server_t *server, char *args) {
|
|||
}
|
||||
|
||||
keyopts = dns_zone_getkeyopts(zone);
|
||||
if ((keyopts & DNS_ZONEKEY_ALLOW) != 0)
|
||||
dns_zone_rekey(zone);
|
||||
else
|
||||
|
||||
/* "rndc loadkeys" requires "auto-dnssec maintain". */
|
||||
if ((keyopts & DNS_ZONEKEY_ALLOW) == 0)
|
||||
result = ISC_R_NOPERM;
|
||||
else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign)
|
||||
result = ISC_R_NOPERM;
|
||||
else
|
||||
dns_zone_rekey(zone, fullsign);
|
||||
|
||||
dns_zone_detach(&zone);
|
||||
return (result);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
; PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
; $Id: root.db.in,v 1.5 2010/01/18 23:48:40 tbox Exp $
|
||||
; $Id: root.db.in,v 1.6 2010/08/16 22:21:06 marka Exp $
|
||||
|
||||
$TTL 30
|
||||
. IN SOA a.root.servers.nil. each.isc.org. (
|
||||
|
|
@ -23,6 +23,7 @@ $TTL 30
|
|||
600 ; minimum
|
||||
)
|
||||
. NS a.root-servers.nil.
|
||||
. TXT "root zone"
|
||||
a.root-servers.nil. A 10.53.0.1
|
||||
|
||||
example. NS ns2.example.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: tests.sh,v 1.10 2010/06/07 04:45:43 marka Exp $
|
||||
# $Id: tests.sh,v 1.11 2010/08/16 22:21:06 marka Exp $
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
|
@ -666,19 +666,19 @@ file="ns1/`cat vanishing.key`.private"
|
|||
rm -f $file
|
||||
|
||||
echo "I:preparing ZSK roll"
|
||||
newid=`sed 's/^K.+007+0*//' < standby.key`
|
||||
file="ns1/`cat standby.key`.key"
|
||||
$SETTIME -A now $file > /dev/null
|
||||
oldfile=`cat active.key`
|
||||
oldid=`sed 's/^K.+007+0*//' < active.key`
|
||||
file="ns1/`cat active.key`.key"
|
||||
$SETTIME -I now -D now+10 $file > /dev/null
|
||||
newfile=`cat standby.key`
|
||||
newid=`sed 's/^K.+007+0*//' < standby.key`
|
||||
$SETTIME -K ns1 -I now -D now+15 $oldfile > /dev/null
|
||||
$SETTIME -K ns1 -i 0 -S $oldfile $newfile > /dev/null
|
||||
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 sign . 2>&1 | sed 's/^/I:ns1 /'
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . 2>&1 | sed 's/^/I:ns1 /'
|
||||
|
||||
echo "I:revoking key to duplicated key ID"
|
||||
$SETTIME -R now ns2/Kbar.+005+30676.key > /dev/null
|
||||
$SETTIME -R now -K ns2 Kbar.+005+30676.key > /dev/null
|
||||
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 sign bar. 2>&1 | sed 's/^/I:ns2 /'
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 loadkeys bar. 2>&1 | sed 's/^/I:ns2 /'
|
||||
|
||||
echo "I:waiting for changes to take effect"
|
||||
sleep 5
|
||||
|
|
@ -691,6 +691,30 @@ n=`expr $n + 1`
|
|||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking former standby key has only signed incrementally ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
|
||||
grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
|
||||
grep 'RRSIG.*'" $oldid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:forcing full sign"
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 sign . 2>&1 | sed 's/^/I:ns1 /'
|
||||
|
||||
echo "I:waiting for change to take effect"
|
||||
sleep 5
|
||||
|
||||
echo "I:checking former standby key has now signed fully ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
|
||||
grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
|
||||
grep 'RRSIG.*'" $oldid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:waiting for former active key to be removed"
|
||||
sleep 10
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: tests.sh,v 1.5 2010/05/06 11:28:20 marka Exp $
|
||||
# $Id: tests.sh,v 1.6 2010/08/16 22:21:06 marka Exp $
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
|
@ -42,6 +42,13 @@ czsk3=`$KEYGEN -q -r $RANDFILE -A none $czone`
|
|||
# inactive
|
||||
czsk4=`$KEYGEN -q -r $RANDFILE -P now-24h -A now-24h -I now $czone`
|
||||
|
||||
# active in 12 hours, inactive 12 hours after that...
|
||||
czsk5=`$KEYGEN -q -r $RANDFILE -P now+12h -A now+12h -I now+24h $czone`
|
||||
|
||||
# explicit successor to czk5
|
||||
# (suppressing warning about lack of removal date)
|
||||
czsk6=`$KEYGEN -q -r $RANDFILE -S $czsk5 -i 6h 2>&-`
|
||||
|
||||
# active ksk
|
||||
cksk1=`$KEYGEN -q -r $RANDFILE -fk $czone`
|
||||
|
||||
|
|
@ -69,6 +76,8 @@ czactive=`echo $czsk1 | sed 's/^K.*+005+0*//'`
|
|||
czgenerated=`echo $czsk2 | sed 's/^K.*+005+0*//'`
|
||||
czpublished=`echo $czsk3 | sed 's/^K.*+005+0*//'`
|
||||
czinactive=`echo $czsk4 | sed 's/^K.*+005+0*//'`
|
||||
czpredecessor=`echo $czsk5 | sed 's/^K.*+005+0*//'`
|
||||
czsuccessor=`echo $czsk6 | sed 's/^K.*+005+0*//'`
|
||||
ckactive=`echo $cksk1 | sed 's/^K.*+005+0*//'`
|
||||
ckpublished=`echo $cksk2 | sed 's/^K.*+005+0*//'`
|
||||
ckprerevoke=`echo $cksk3 | sed 's/^K.*+005+0*//'`
|
||||
|
|
@ -115,6 +124,10 @@ grep "key id = $czinactive" $cfile.signed > /dev/null || ret=1
|
|||
# should not be there, hence the &&
|
||||
grep "key id = $ckprerevoke" $cfile.signed > /dev/null && ret=1
|
||||
grep "key id = $czgenerated" $cfile.signed > /dev/null && ret=1
|
||||
grep "key id = $czpredecessor" $cfile.signed && echo pred is there
|
||||
grep "key id = $czsuccessor" $cfile.signed && echo succ is there
|
||||
#grep "key id = $czpredecessor" $cfile.signed > /dev/null && ret=1
|
||||
#grep "key id = $czsuccessor" $cfile.signed > /dev/null && ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
|
@ -141,6 +154,8 @@ grep "$ckrevoked" other.sigs > /dev/null && ret=1
|
|||
grep "$czpublished" other.sigs > /dev/null && ret=1
|
||||
grep "$czinactive" other.sigs > /dev/null && ret=1
|
||||
grep "$czgenerated" other.sigs > /dev/null && ret=1
|
||||
grep "$czpredecessor" other.sigs > /dev/null && ret=1
|
||||
grep "$czsuccessor" other.sigs > /dev/null && ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.461 2010/08/11 18:14:19 each Exp $ -->
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.462 2010/08/16 22:21:06 marka Exp $ -->
|
||||
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>BIND 9 Administrator Reference Manual</title>
|
||||
|
||||
|
|
@ -1179,10 +1179,11 @@ zone "eng.example.com" {
|
|||
Fetch all DNSSEC keys for the given zone
|
||||
from the key directory (see
|
||||
<command>key-directory</command> in
|
||||
<xref linkend="options"/>), and merge them
|
||||
into the zone's DNSKEY RRset. If the DNSKEY RRset
|
||||
is changed as a result of this, then the zone is
|
||||
automatically re-signed with the new key set.
|
||||
<xref linkend="options"/>). If they are within
|
||||
their publication period, merge them into the
|
||||
zone's DNSKEY RRset. If the DNSKEY RRset
|
||||
is changed, then the zone is automatically
|
||||
re-signed with the new key set.
|
||||
</para>
|
||||
<para>
|
||||
This command requires that the
|
||||
|
|
@ -1197,6 +1198,34 @@ zone "eng.example.com" {
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><userinput>loadkeys <replaceable>zone</replaceable>
|
||||
<optional><replaceable>class</replaceable>
|
||||
<optional><replaceable>view</replaceable></optional></optional></userinput></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Fetch all DNSSEC keys for the given zone
|
||||
from the key directory (see
|
||||
<command>key-directory</command> in
|
||||
<xref linkend="options"/>). If they are within
|
||||
their publication period, merge them into the
|
||||
zone's DNSKEY RRset. Unlike <command>rndc
|
||||
sign</command>, however, the zone is not
|
||||
immediately re-signed by the new keys, but is
|
||||
allowed to incrementally re-sign over time.
|
||||
</para>
|
||||
<para>
|
||||
This command requires that the
|
||||
<command>auto-dnssec</command> zone option to
|
||||
be set to <literal>maintain</literal> or
|
||||
<literal>create</literal>, and also requires
|
||||
the zone to be configured to allow dynamic DNS.
|
||||
See <xref linkend="dynamic_update_policies"/> for
|
||||
more details.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><userinput>freeze
|
||||
<optional><replaceable>zone</replaceable>
|
||||
|
|
@ -10614,16 +10643,27 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
|
|||
</para>
|
||||
<para>
|
||||
<command>auto-dnssec allow;</command> permits
|
||||
keys to be updated and the zone re-signed whenever the
|
||||
user issues the command <command>rndc sign
|
||||
keys to be updated and the zone fully re-signed
|
||||
whenever the user issues the command <command>rndc sign
|
||||
<replaceable>zonename</replaceable></command>.
|
||||
</para>
|
||||
<para>
|
||||
<command>auto-dnssec maintain;</command> includes the
|
||||
above, but also automatically adjusts the zone's DNSSEC
|
||||
keys on schedule, according to the keys' timing metadata
|
||||
(see <xref linkend="man.dnssec-keygen"/> and
|
||||
<xref linkend="man.dnssec-settime"/>).
|
||||
(see <xref linkend="man.dnyssec-keygen"/> and
|
||||
<xref linkend="man.dnssec-settime"/>). The command
|
||||
<command>rndc sign
|
||||
<replaceable>zonename</replaceable></command> causes
|
||||
<command>named</command> to load keys from the key
|
||||
repository and sign the zone with all keys that are
|
||||
active.
|
||||
<command>rndc loadkeys
|
||||
<replaceable>zonename</replaceable></command> causes
|
||||
<command>named</command> to load keys from the key
|
||||
repository and schedule key maintenance events to occur
|
||||
in the future, but it does not sign the full zone
|
||||
immediately.
|
||||
</para>
|
||||
<para>
|
||||
<command>auto-dnssec create;</command> includes the
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- $Id: dnssec.xml,v 1.3 2010/02/03 23:49:07 tbox Exp $ -->
|
||||
<!-- $Id: dnssec.xml,v 1.4 2010/08/16 22:21:06 marka Exp $ -->
|
||||
|
||||
<sect1 id="dnssec.dynamic.zones">
|
||||
<title>DNSSEC, Dynamic Zones, and Automatic Signing</title>
|
||||
|
|
@ -100,7 +100,8 @@
|
|||
<command>named</command> can search the key directory for keys
|
||||
matching the zone, insert them into the zone, and use them to
|
||||
sign the zone. It will do so only when it receives an
|
||||
<command>rndc sign <zonename></command> command.</para>
|
||||
<command>rndc sign <zonename></command> or
|
||||
<command>rndc loadkeys <zonename></command> command.</para>
|
||||
<para>
|
||||
<!-- TODO: this is repeated in the ARM -->
|
||||
<command>auto-dnssec maintain</command> includes the above
|
||||
|
|
@ -110,8 +111,10 @@
|
|||
<xref linkend="man.dnssec-settime"/> for more information.)
|
||||
If keys are present in the key directory the first time the zone
|
||||
is loaded, it will be signed immediately, without waiting for an
|
||||
<command>rndc sign</command> command. (This command can still be
|
||||
used for unscheduled key changes, however.)</para>
|
||||
<command>rndc sign</command> or <command>rndc loadkeys</command>
|
||||
command. (Those commands can still be used when there are unscheduled
|
||||
key changes, however.)
|
||||
</para>
|
||||
<para>Using the
|
||||
<command>auto-dnssec</command> option requires the zone to be
|
||||
configured to allow dynamic updates, by adding an
|
||||
|
|
@ -158,11 +161,16 @@
|
|||
</literallayout>
|
||||
</para>
|
||||
<sect2>
|
||||
<title>DNSKEY rollovers via UPDATE</title>
|
||||
<title>DNSKEY rollovers</title>
|
||||
</sect2>
|
||||
<para>It is possible to perform key rollovers via dynamic update.
|
||||
You need to add the
|
||||
<filename>K*</filename> files for the new keys so that
|
||||
<para>As with insecure-to-secure conversions, rolling DNSSEC
|
||||
keys can be done in two ways: using a dynamic DNS update, or the
|
||||
<command>auto-dnssec</command> zone option.</para>
|
||||
<sect2>
|
||||
<title>Dynamic DNS update method</title>
|
||||
</sect2>
|
||||
<para> To perform key rollovers via dynamic update, you need to add
|
||||
the <filename>K*</filename> files for the new keys so that
|
||||
<command>named</command> can find them. You can then add the new
|
||||
DNSKEY RRs via dynamic update.
|
||||
<command>named</command> will then cause the zone to be signed
|
||||
|
|
@ -181,6 +189,22 @@
|
|||
specify the correct key.
|
||||
<command>named</command> will clean out any signatures generated
|
||||
by the old key after the update completes.</para>
|
||||
<sect2>
|
||||
<title>Automatic key rollovers</title>
|
||||
</sect2>
|
||||
<para>When a new key reaches its activation date (as set by
|
||||
<command>dnssec-keygen</command> or <command>dnssec-settime</command>),
|
||||
if the <command>auto-dnssec</command> zone option is set to
|
||||
<constant>maintain</constant>, <command>named</command> will
|
||||
automatically carry out the key rollover. If the key's algorithm
|
||||
has not previously been used to sign the zone, then the zone will
|
||||
be fully signed as quickly as possible. However, if the new key
|
||||
is replacing an existing key of the same algorithm, then the
|
||||
zone will be re-signed incrementally, with signatures from the
|
||||
old key being replaced with signatures from the new key as their
|
||||
signature validity periods expire. By default, this rollover
|
||||
completes in 30 days, after which it will be safe to remove the
|
||||
old key from the DNSKEY RRset.</para>
|
||||
<sect2>
|
||||
<title>NSEC3PARAM rollovers via UPDATE</title>
|
||||
</sect2>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zone.h,v 1.177 2010/08/13 23:47:03 tbox Exp $ */
|
||||
/* $Id: zone.h,v 1.178 2010/08/16 22:21:07 marka Exp $ */
|
||||
|
||||
#ifndef DNS_ZONE_H
|
||||
#define DNS_ZONE_H 1
|
||||
|
|
@ -89,6 +89,7 @@ typedef enum {
|
|||
#define DNS_ZONEKEY_ALLOW 0x00000001U /*%< fetch keys on command */
|
||||
#define DNS_ZONEKEY_MAINTAIN 0x00000002U /*%< publish/sign on schedule */
|
||||
#define DNS_ZONEKEY_CREATE 0x00000004U /*%< make keys when needed */
|
||||
#define DNS_ZONEKEY_FULLSIGN 0x00000008U /*%< roll to new keys immediately */
|
||||
|
||||
#ifndef DNS_ZONE_MINREFRESH
|
||||
#define DNS_ZONE_MINREFRESH 300 /*%< 5 minutes */
|
||||
|
|
@ -1779,9 +1780,14 @@ dns_zone_getprivatetype(dns_zone_t *zone);
|
|||
*/
|
||||
|
||||
void
|
||||
dns_zone_rekey(dns_zone_t *zone);
|
||||
dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign);
|
||||
/*%<
|
||||
* Update the zone's DNSKEY set from the key repository.
|
||||
*
|
||||
* If 'fullsign' is true, trigger an immediate full signing of
|
||||
* the zone with the new key. Otherwise, if there are no keys or
|
||||
* if the new keys are for algorithms that have already signed the
|
||||
* zone, then the zone can be re-signed incrementally.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
|
|
|
|||
184
lib/dns/zone.c
184
lib/dns/zone.c
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zone.c,v 1.570 2010/08/11 18:14:19 each Exp $ */
|
||||
/* $Id: zone.c,v 1.571 2010/08/16 22:21:07 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
|
|
@ -13730,6 +13730,36 @@ clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
|
|||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an RRSIG rdataset and an algorithm, determine whether there
|
||||
* are any signatures using that algorithm.
|
||||
*/
|
||||
static isc_boolean_t
|
||||
signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_rrsig_t rrsig;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
|
||||
if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
for (result = dns_rdataset_first(rdataset);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_rdataset_next(rdataset))
|
||||
{
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_rdata_reset(&rdata);
|
||||
if (rrsig.algorithm == alg)
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
zone_rekey(dns_zone_t *zone) {
|
||||
isc_result_t result;
|
||||
|
|
@ -13741,12 +13771,14 @@ zone_rekey(dns_zone_t *zone) {
|
|||
dns_dnsseckey_t *key;
|
||||
dns_diff_t diff;
|
||||
isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
|
||||
isc_boolean_t fullsign;
|
||||
dns_ttl_t ttl = 3600;
|
||||
const char *dir;
|
||||
isc_mem_t *mctx;
|
||||
isc_stdtime_t now;
|
||||
isc_time_t timenow;
|
||||
isc_interval_t ival;
|
||||
char timebuf[80];
|
||||
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
|
|
@ -13789,6 +13821,12 @@ zone_rekey(dns_zone_t *zone) {
|
|||
} else if (result != ISC_R_NOTFOUND)
|
||||
goto failure;
|
||||
|
||||
/*
|
||||
* True when called from "rndc sign". Indicates the zone should be
|
||||
* fully signed now.
|
||||
*/
|
||||
fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
|
||||
|
||||
result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_boolean_t check_ksk;
|
||||
|
|
@ -13818,7 +13856,7 @@ zone_rekey(dns_zone_t *zone) {
|
|||
}
|
||||
}
|
||||
|
||||
if ((newactive || !ISC_LIST_EMPTY(diff.tuples)) &&
|
||||
if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
|
||||
dnskey_sane(zone, db, ver, &diff)) {
|
||||
CHECK(dns_diff_apply(&diff, db, ver));
|
||||
CHECK(clean_nsec3param(zone, db, ver, &diff));
|
||||
|
|
@ -13839,6 +13877,8 @@ zone_rekey(dns_zone_t *zone) {
|
|||
if (commit) {
|
||||
isc_time_t timenow;
|
||||
dns_difftuple_t *tuple;
|
||||
isc_boolean_t newkey = ISC_FALSE;
|
||||
isc_boolean_t newalg = ISC_FALSE;
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
|
||||
|
|
@ -13848,33 +13888,126 @@ zone_rekey(dns_zone_t *zone) {
|
|||
TIME_NOW(&timenow);
|
||||
zone_settimer(zone, &timenow);
|
||||
|
||||
/*
|
||||
* Has a new key become active? If so, is it for
|
||||
* a new algorithm?
|
||||
*/
|
||||
for (tuple = ISC_LIST_HEAD(diff.tuples);
|
||||
tuple != NULL;
|
||||
tuple = ISC_LIST_NEXT(tuple, link)) {
|
||||
dns_rdata_dnskey_t dnskey;
|
||||
dns_secalg_t algorithm;
|
||||
isc_region_t r;
|
||||
isc_uint16_t keyid;
|
||||
|
||||
if (tuple->rdata.type != dns_rdatatype_dnskey)
|
||||
continue;
|
||||
|
||||
result = dns_rdata_tostruct(&tuple->rdata, &dnskey,
|
||||
NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_rdata_toregion(&tuple->rdata, &r);
|
||||
algorithm = dnskey.algorithm;
|
||||
keyid = dst_region_computeid(&r, algorithm);
|
||||
newkey = ISC_TRUE;
|
||||
if (!dns_rdataset_isassociated(&keysigs)) {
|
||||
newalg = ISC_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
result = zone_signwithkey(zone, algorithm, keyid,
|
||||
ISC_TF(tuple->op == DNS_DIFFOP_DEL));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"zone_signwithkey failed: %s",
|
||||
dns_result_totext(result));
|
||||
result = dns_rdata_tostruct(&tuple->rdata,
|
||||
&dnskey, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
if (!signed_with_alg(&keysigs,
|
||||
dnskey.algorithm)) {
|
||||
newalg = ISC_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found a new algorithm, we need to sign the
|
||||
* zone fully. If there's a new key, but it's for an
|
||||
* already-existing algorithm, then the zone signing
|
||||
* can be handled incrementally.
|
||||
*/
|
||||
if (newkey && !newalg)
|
||||
set_resigntime(zone);
|
||||
|
||||
/* Remove any signatures from removed keys. */
|
||||
if (!ISC_LIST_EMPTY(rmkeys)) {
|
||||
for (key = ISC_LIST_HEAD(rmkeys);
|
||||
key != NULL;
|
||||
key = ISC_LIST_NEXT(key, link)) {
|
||||
result = zone_signwithkey(zone,
|
||||
dst_key_alg(key->key),
|
||||
dst_key_id(key->key),
|
||||
ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"zone_signwithkey failed: %s",
|
||||
dns_result_totext(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fullsign) {
|
||||
/*
|
||||
* "rndc sign" was called, so we now sign the zone
|
||||
* with all active keys, whether they're new or not.
|
||||
*/
|
||||
for (key = ISC_LIST_HEAD(dnskeys);
|
||||
key != NULL;
|
||||
key = ISC_LIST_NEXT(key, link)) {
|
||||
if (!key->force_sign && !key->hint_sign)
|
||||
continue;
|
||||
|
||||
result = zone_signwithkey(zone,
|
||||
dst_key_alg(key->key),
|
||||
dst_key_id(key->key),
|
||||
ISC_FALSE);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"zone_signwithkey failed: %s",
|
||||
dns_result_totext(result));
|
||||
}
|
||||
}
|
||||
} else if (newalg) {
|
||||
/*
|
||||
* We haven't been told to sign fully, but a new
|
||||
* algorithm was added to the DNSKEY. We sign
|
||||
* the full zone, but only with the newly-added
|
||||
* keys.
|
||||
*/
|
||||
for (tuple = ISC_LIST_HEAD(diff.tuples);
|
||||
tuple != NULL;
|
||||
tuple = ISC_LIST_NEXT(tuple, link)) {
|
||||
dns_rdata_dnskey_t dnskey;
|
||||
dns_secalg_t algorithm;
|
||||
isc_region_t r;
|
||||
isc_uint16_t keyid;
|
||||
|
||||
if (tuple->rdata.type != dns_rdatatype_dnskey ||
|
||||
tuple->op == DNS_DIFFOP_DEL)
|
||||
continue;
|
||||
|
||||
result = dns_rdata_tostruct(&tuple->rdata,
|
||||
&dnskey, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_rdata_toregion(&tuple->rdata, &r);
|
||||
algorithm = dnskey.algorithm;
|
||||
keyid = dst_region_computeid(&r, algorithm);
|
||||
|
||||
result = zone_signwithkey(zone, algorithm,
|
||||
keyid,
|
||||
ISC_TF(tuple->op ==
|
||||
DNS_DIFFOP_DEL));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"zone_signwithkey failed: %s",
|
||||
dns_result_totext(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear fullsign flag, if it was set, so we don't do
|
||||
* another full signing next time
|
||||
*/
|
||||
zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
|
||||
|
||||
/*
|
||||
* Cause the zone to add/delete NSEC3 chains for the
|
||||
* deferred NSEC3PARAM changes.
|
||||
|
|
@ -13939,6 +14072,17 @@ zone_rekey(dns_zone_t *zone) {
|
|||
UNLOCK_ZONE(zone);
|
||||
}
|
||||
|
||||
/*
|
||||
* If no key event is scheduled, we should still check the key
|
||||
* repository for updates every so often. (Currently this is
|
||||
* hard-coded to 12 hours, but it could be configurable.)
|
||||
*/
|
||||
if (isc_time_isepoch(&zone->refreshkeytime))
|
||||
DNS_ZONE_TIME_ADD(&timenow, (3600 * 12), &zone->refreshkeytime);
|
||||
|
||||
isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
|
||||
dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
|
||||
|
||||
failure:
|
||||
dns_diff_clear(&diff);
|
||||
|
||||
|
|
@ -13967,15 +14111,19 @@ zone_rekey(dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
void
|
||||
dns_zone_rekey(dns_zone_t *zone) {
|
||||
dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
|
||||
isc_time_t now;
|
||||
|
||||
if (zone->type == dns_zone_master && zone->task != NULL) {
|
||||
LOCK_ZONE(zone);
|
||||
|
||||
if (fullsign)
|
||||
zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
|
||||
|
||||
TIME_NOW(&now);
|
||||
zone->refreshkeytime = now;
|
||||
zone_settimer(zone, &now);
|
||||
|
||||
UNLOCK_ZONE(zone);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue