mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-28 21:17:54 +00:00
dnssec-settime: Allow manipulating state files
Introduce a new option '-s' for dnssec-settime that when manipulating timing metadata, it also updates the key state file. For testing purposes, add options to dnssec-settime to set key states and when they last changed. The dst code adds ways to write and read the new key states and timing metadata. It updates the parsing code for private key files to not parse the newly introduced metadata (these are for state files only). Introduce key goal (the state the key wants to be in).
This commit is contained in:
parent
c55625b035
commit
72042a06d6
@ -88,6 +88,15 @@ usage(void) {
|
|||||||
fprintf(stderr, " -i <interval>: prepublication interval for "
|
fprintf(stderr, " -i <interval>: prepublication interval for "
|
||||||
"successor key "
|
"successor key "
|
||||||
"(default: 30 days)\n");
|
"(default: 30 days)\n");
|
||||||
|
fprintf(stderr, "Key state options:\n");
|
||||||
|
fprintf(stderr, " -s: update key state file (default no)\n");
|
||||||
|
fprintf(stderr, " -g state: set the goal state for this key\n");
|
||||||
|
fprintf(stderr, " -d state date/[+-]offset: set the DS state\n");
|
||||||
|
fprintf(stderr, " -k state date/[+-]offset: set the DNSKEY state\n");
|
||||||
|
fprintf(stderr, " -r state date/[+-]offset: set the RRSIG (KSK) "
|
||||||
|
"state\n");
|
||||||
|
fprintf(stderr, " -z state date/[+-]offset: set the RRSIG (ZSK) "
|
||||||
|
"state\n");
|
||||||
fprintf(stderr, "Printing options:\n");
|
fprintf(stderr, "Printing options:\n");
|
||||||
fprintf(stderr, " -p C/P/Psync/A/R/I/D/Dsync/all: print a "
|
fprintf(stderr, " -p C/P/Psync/A/R/I/D/Dsync/all: print a "
|
||||||
"particular time value or values\n");
|
"particular time value or values\n");
|
||||||
@ -123,29 +132,87 @@ printtime(dst_key_t *key, int type, const char *tag, bool epoch,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
writekey(dst_key_t *key, const char *directory, bool write_state)
|
||||||
|
{
|
||||||
|
char newname[1024];
|
||||||
|
char keystr[DST_KEY_FORMATSIZE];
|
||||||
|
isc_buffer_t buf;
|
||||||
|
isc_result_t result;
|
||||||
|
int options = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE;
|
||||||
|
|
||||||
|
if (write_state) {
|
||||||
|
options |= DST_TYPE_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_buffer_init(&buf, newname, sizeof(newname));
|
||||||
|
result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
fatal("Failed to build public key filename: %s",
|
||||||
|
isc_result_totext(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dst_key_tofile(key, options, directory);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
dst_key_format(key, keystr, sizeof(keystr));
|
||||||
|
fatal("Failed to write key %s: %s", keystr,
|
||||||
|
isc_result_totext(result));
|
||||||
|
}
|
||||||
|
printf("%s\n", newname);
|
||||||
|
|
||||||
|
isc_buffer_clear(&buf);
|
||||||
|
result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
fatal("Failed to build private key filename: %s",
|
||||||
|
isc_result_totext(result));
|
||||||
|
}
|
||||||
|
printf("%s\n", newname);
|
||||||
|
|
||||||
|
if (write_state) {
|
||||||
|
isc_buffer_clear(&buf);
|
||||||
|
result = dst_key_buildfilename(key, DST_TYPE_STATE, directory,
|
||||||
|
&buf);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
fatal("Failed to build key state filename: %s",
|
||||||
|
isc_result_totext(result));
|
||||||
|
}
|
||||||
|
printf("%s\n", newname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv) {
|
main(int argc, char **argv) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
const char *engine = NULL;
|
const char *engine = NULL;
|
||||||
const char *filename = NULL;
|
const char *filename = NULL;
|
||||||
char *directory = NULL;
|
char *directory = NULL;
|
||||||
char newname[1024];
|
|
||||||
char keystr[DST_KEY_FORMATSIZE];
|
char keystr[DST_KEY_FORMATSIZE];
|
||||||
char *endp, *p;
|
char *endp, *p;
|
||||||
int ch;
|
int ch;
|
||||||
const char *predecessor = NULL;
|
const char *predecessor = NULL;
|
||||||
dst_key_t *prevkey = NULL;
|
dst_key_t *prevkey = NULL;
|
||||||
dst_key_t *key = NULL;
|
dst_key_t *key = NULL;
|
||||||
isc_buffer_t buf;
|
|
||||||
dns_name_t *name = NULL;
|
dns_name_t *name = NULL;
|
||||||
dns_secalg_t alg = 0;
|
dns_secalg_t alg = 0;
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
uint16_t flags = 0;
|
uint16_t flags = 0;
|
||||||
int prepub = -1;
|
int prepub = -1;
|
||||||
|
int options;
|
||||||
dns_ttl_t ttl = 0;
|
dns_ttl_t ttl = 0;
|
||||||
isc_stdtime_t now;
|
isc_stdtime_t now;
|
||||||
|
isc_stdtime_t dstime = 0, dnskeytime = 0;
|
||||||
|
isc_stdtime_t krrsigtime = 0, zrrsigtime = 0;
|
||||||
isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0;
|
isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0;
|
||||||
isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0;
|
isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0;
|
||||||
|
dst_key_state_t goal = DST_KEY_STATE_NA;
|
||||||
|
dst_key_state_t ds = DST_KEY_STATE_NA;
|
||||||
|
dst_key_state_t dnskey = DST_KEY_STATE_NA;
|
||||||
|
dst_key_state_t krrsig = DST_KEY_STATE_NA;
|
||||||
|
dst_key_state_t zrrsig = DST_KEY_STATE_NA;
|
||||||
|
bool setgoal = false, setds = false, setdnskey = false;
|
||||||
|
bool setkrrsig = false, setzrrsig = false;
|
||||||
|
bool setdstime = false, setdnskeytime = false;
|
||||||
|
bool setkrrsigtime = false, setzrrsigtime = false;
|
||||||
bool setpub = false, setact = false;
|
bool setpub = false, setact = false;
|
||||||
bool setrev = false, setinact = false;
|
bool setrev = false, setinact = false;
|
||||||
bool setdel = false, setttl = false;
|
bool setdel = false, setttl = false;
|
||||||
@ -156,14 +223,17 @@ main(int argc, char **argv) {
|
|||||||
bool printact = false, printrev = false;
|
bool printact = false, printrev = false;
|
||||||
bool printinact = false, printdel = false;
|
bool printinact = false, printdel = false;
|
||||||
bool force = false;
|
bool force = false;
|
||||||
bool epoch = false;
|
bool epoch = false;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
bool write_state = false;
|
||||||
isc_log_t *log = NULL;
|
isc_log_t *log = NULL;
|
||||||
isc_stdtime_t syncadd = 0, syncdel = 0;
|
isc_stdtime_t syncadd = 0, syncdel = 0;
|
||||||
bool unsetsyncadd = false, setsyncadd = false;
|
bool unsetsyncadd = false, setsyncadd = false;
|
||||||
bool unsetsyncdel = false, setsyncdel = false;
|
bool unsetsyncdel = false, setsyncdel = false;
|
||||||
bool printsyncadd = false, printsyncdel = false;
|
bool printsyncadd = false, printsyncdel = false;
|
||||||
|
|
||||||
|
options = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_STATE;
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
@ -180,7 +250,7 @@ main(int argc, char **argv) {
|
|||||||
|
|
||||||
isc_stdtime_get(&now);
|
isc_stdtime_get(&now);
|
||||||
|
|
||||||
#define CMDLINE_FLAGS "A:D:E:fhI:i:K:L:P:p:R:S:uv:V"
|
#define CMDLINE_FLAGS "A:D:d:E:fg:hI:i:K:k:L:P:p:R:r:S:suv:Vz:"
|
||||||
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
|
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'E':
|
case 'E':
|
||||||
@ -339,6 +409,70 @@ main(int argc, char **argv) {
|
|||||||
case 'i':
|
case 'i':
|
||||||
prepub = strtottl(isc_commandline_argument);
|
prepub = strtottl(isc_commandline_argument);
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
write_state = true;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
if (setgoal) {
|
||||||
|
fatal("-g specified more than once");
|
||||||
|
}
|
||||||
|
|
||||||
|
goal = strtokeystate(isc_commandline_argument);
|
||||||
|
if (goal != DST_KEY_STATE_NA &&
|
||||||
|
goal != DST_KEY_STATE_HIDDEN &&
|
||||||
|
goal != DST_KEY_STATE_OMNIPRESENT) {
|
||||||
|
fatal("-g must be either none, hidden, or "
|
||||||
|
"omnipresent");
|
||||||
|
}
|
||||||
|
setgoal = true;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (setds) {
|
||||||
|
fatal("-d specified more than once");
|
||||||
|
}
|
||||||
|
|
||||||
|
ds = strtokeystate(isc_commandline_argument);
|
||||||
|
setds = true;
|
||||||
|
/* time */
|
||||||
|
(void)isoptarg(isc_commandline_argument, argv, usage);
|
||||||
|
dstime = strtotime(isc_commandline_argument,
|
||||||
|
now, now, &setdstime);
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
if (setdnskey) {
|
||||||
|
fatal("-k specified more than once");
|
||||||
|
}
|
||||||
|
|
||||||
|
dnskey = strtokeystate(isc_commandline_argument);
|
||||||
|
setdnskey = true;
|
||||||
|
/* time */
|
||||||
|
(void)isoptarg(isc_commandline_argument, argv, usage);
|
||||||
|
dnskeytime = strtotime(isc_commandline_argument,
|
||||||
|
now, now, &setdnskeytime);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (setkrrsig) {
|
||||||
|
fatal("-r specified more than once");
|
||||||
|
}
|
||||||
|
|
||||||
|
krrsig = strtokeystate(isc_commandline_argument);
|
||||||
|
setkrrsig = true;
|
||||||
|
/* time */
|
||||||
|
(void)isoptarg(isc_commandline_argument, argv, usage);
|
||||||
|
krrsigtime = strtotime(isc_commandline_argument,
|
||||||
|
now, now, &setkrrsigtime);
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
if (setzrrsig) {
|
||||||
|
fatal("-z specified more than once");
|
||||||
|
}
|
||||||
|
|
||||||
|
zrrsig = strtokeystate(isc_commandline_argument);
|
||||||
|
setzrrsig = true;
|
||||||
|
(void)isoptarg(isc_commandline_argument, argv, usage);
|
||||||
|
zrrsigtime = strtotime(isc_commandline_argument,
|
||||||
|
now, now, &setzrrsigtime);
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
if (isc_commandline_option != '?')
|
if (isc_commandline_option != '?')
|
||||||
fprintf(stderr, "%s: invalid argument -%c\n",
|
fprintf(stderr, "%s: invalid argument -%c\n",
|
||||||
@ -365,6 +499,12 @@ main(int argc, char **argv) {
|
|||||||
if (argc > isc_commandline_index + 1)
|
if (argc > isc_commandline_index + 1)
|
||||||
fatal("Extraneous arguments");
|
fatal("Extraneous arguments");
|
||||||
|
|
||||||
|
if ((setgoal || setds || setdnskey || setkrrsig || setzrrsig) &&
|
||||||
|
!write_state)
|
||||||
|
{
|
||||||
|
fatal("Options -g, -d, -k, -r and -z require -s to be set");
|
||||||
|
}
|
||||||
|
|
||||||
result = dst_lib_init(mctx, engine);
|
result = dst_lib_init(mctx, engine);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
fatal("Could not initialize dst: %s",
|
fatal("Could not initialize dst: %s",
|
||||||
@ -381,9 +521,7 @@ main(int argc, char **argv) {
|
|||||||
if (setact || unsetact)
|
if (setact || unsetact)
|
||||||
fatal("-S and -A cannot be used together");
|
fatal("-S and -A cannot be used together");
|
||||||
|
|
||||||
result = dst_key_fromnamedfile(predecessor, directory,
|
result = dst_key_fromnamedfile(predecessor, directory, options,
|
||||||
DST_TYPE_PUBLIC |
|
|
||||||
DST_TYPE_PRIVATE,
|
|
||||||
mctx, &prevkey);
|
mctx, &prevkey);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
fatal("Invalid keyfile %s: %s",
|
fatal("Invalid keyfile %s: %s",
|
||||||
@ -475,9 +613,8 @@ main(int argc, char **argv) {
|
|||||||
isc_result_totext(result));
|
isc_result_totext(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dst_key_fromnamedfile(filename, directory,
|
result = dst_key_fromnamedfile(filename, directory, options, mctx,
|
||||||
DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
|
&key);
|
||||||
mctx, &key);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
fatal("Invalid keyfile %s: %s",
|
fatal("Invalid keyfile %s: %s",
|
||||||
filename, isc_result_totext(result));
|
filename, isc_result_totext(result));
|
||||||
@ -588,6 +725,63 @@ main(int argc, char **argv) {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the key state goals are written.
|
||||||
|
*/
|
||||||
|
if (write_state) {
|
||||||
|
if (setgoal) {
|
||||||
|
if (goal == DST_KEY_STATE_NA) {
|
||||||
|
dst_key_unsetstate(key, DST_KEY_GOAL);
|
||||||
|
} else {
|
||||||
|
dst_key_setstate(key, DST_KEY_GOAL, goal);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (setds) {
|
||||||
|
if (ds == DST_KEY_STATE_NA) {
|
||||||
|
dst_key_unsetstate(key, DST_KEY_DS);
|
||||||
|
dst_key_unsettime(key, DST_TIME_DS);
|
||||||
|
} else {
|
||||||
|
dst_key_setstate(key, DST_KEY_DS, ds);
|
||||||
|
dst_key_settime(key, DST_TIME_DS, dstime);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (setdnskey) {
|
||||||
|
if (dnskey == DST_KEY_STATE_NA) {
|
||||||
|
dst_key_unsetstate(key, DST_KEY_DNSKEY);
|
||||||
|
dst_key_unsettime(key, DST_TIME_DNSKEY);
|
||||||
|
} else {
|
||||||
|
dst_key_setstate(key, DST_KEY_DNSKEY, dnskey);
|
||||||
|
dst_key_settime(key, DST_TIME_DNSKEY,
|
||||||
|
dnskeytime);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (setkrrsig) {
|
||||||
|
if (krrsig == DST_KEY_STATE_NA) {
|
||||||
|
dst_key_unsetstate(key, DST_KEY_KRRSIG);
|
||||||
|
dst_key_unsettime(key, DST_TIME_KRRSIG);
|
||||||
|
} else {
|
||||||
|
dst_key_setstate(key, DST_KEY_KRRSIG, krrsig);
|
||||||
|
dst_key_settime(key, DST_TIME_KRRSIG,
|
||||||
|
krrsigtime);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (setzrrsig) {
|
||||||
|
if (zrrsig == DST_KEY_STATE_NA) {
|
||||||
|
dst_key_unsetstate(key, DST_KEY_ZRRSIG);
|
||||||
|
dst_key_unsettime(key, DST_TIME_ZRRSIG);
|
||||||
|
} else {
|
||||||
|
dst_key_setstate(key, DST_KEY_ZRRSIG, zrrsig);
|
||||||
|
dst_key_settime(key, DST_TIME_ZRRSIG,
|
||||||
|
zrrsigtime);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!changed && setttl)
|
if (!changed && setttl)
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
@ -621,32 +815,7 @@ main(int argc, char **argv) {
|
|||||||
epoch, stdout);
|
epoch, stdout);
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
isc_buffer_init(&buf, newname, sizeof(newname));
|
writekey(key, directory, write_state);
|
||||||
result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory,
|
|
||||||
&buf);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
fatal("Failed to build public key filename: %s",
|
|
||||||
isc_result_totext(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
|
|
||||||
directory);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
dst_key_format(key, keystr, sizeof(keystr));
|
|
||||||
fatal("Failed to write key %s: %s", keystr,
|
|
||||||
isc_result_totext(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n", newname);
|
|
||||||
|
|
||||||
isc_buffer_clear(&buf);
|
|
||||||
result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory,
|
|
||||||
&buf);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
fatal("Failed to build private key filename: %s",
|
|
||||||
isc_result_totext(result));
|
|
||||||
}
|
|
||||||
printf("%s\n", newname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevkey != NULL)
|
if (prevkey != NULL)
|
||||||
|
@ -64,6 +64,12 @@
|
|||||||
<arg choice="opt" rep="norepeat"><option>-V</option></arg>
|
<arg choice="opt" rep="norepeat"><option>-V</option></arg>
|
||||||
<arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
|
<arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
|
||||||
<arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
|
<arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
|
||||||
|
<arg choice="opt" rep="norepeat"><option>-s</option></arg>
|
||||||
|
<arg choice="opt" rep="norepeat"><option>-g <replaceable class="parameter">state</replaceable></option></arg>
|
||||||
|
<arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">state</replaceable> <replaceable class="parameter">date/offset</replaceable></option></arg>
|
||||||
|
<arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">state</replaceable> <replaceable class="parameter">date/offset</replaceable></option></arg>
|
||||||
|
<arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">state</replaceable> <replaceable class="parameter">date/offset</replaceable></option></arg>
|
||||||
|
<arg choice="opt" rep="norepeat"><option>-z <replaceable class="parameter">state</replaceable> <replaceable class="parameter">date/offset</replaceable></option></arg>
|
||||||
<arg choice="req" rep="norepeat">keyfile</arg>
|
<arg choice="req" rep="norepeat">keyfile</arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
@ -88,11 +94,30 @@
|
|||||||
When key metadata fields are changed, both files of a key
|
When key metadata fields are changed, both files of a key
|
||||||
pair (<filename>Knnnn.+aaa+iiiii.key</filename> and
|
pair (<filename>Knnnn.+aaa+iiiii.key</filename> and
|
||||||
<filename>Knnnn.+aaa+iiiii.private</filename>) are regenerated.
|
<filename>Knnnn.+aaa+iiiii.private</filename>) are regenerated.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
Metadata fields are stored in the private file. A human-readable
|
Metadata fields are stored in the private file. A human-readable
|
||||||
description of the metadata is also placed in comments in the key
|
description of the metadata is also placed in comments in the key
|
||||||
file. The private file's permissions are always set to be
|
file. The private file's permissions are always set to be
|
||||||
inaccessible to anyone other than the owner (mode 0600).
|
inaccessible to anyone other than the owner (mode 0600).
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
When working with state files, it is possible to update the timing
|
||||||
|
metadata in those files as well with <option>-s</option>. If this
|
||||||
|
option is used you can also update key states with <option>-d</option>
|
||||||
|
(DS), <option>-k</option> (DNSKEY), <option>-r</option> (RRSIG of KSK),
|
||||||
|
or <option>-z</option> (RRSIG of ZSK). Allowed states are HIDDEN,
|
||||||
|
RUMOURED, OMNIPRESENT, and UNRETENTIVE.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
You can also set the goal state of the key with <option>-g</option>.
|
||||||
|
This should be either HIDDEN or OMNIPRESENT (representing whether the
|
||||||
|
key should be removed from the zone, or published).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It is NOT RECOMMENDED to manipulate state files manually except for
|
||||||
|
testing purposes.
|
||||||
|
</para>
|
||||||
</refsection>
|
</refsection>
|
||||||
|
|
||||||
<refsection><info><title>OPTIONS</title></info>
|
<refsection><info><title>OPTIONS</title></info>
|
||||||
@ -319,6 +344,74 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsection>
|
</refsection>
|
||||||
|
|
||||||
|
<refsection><info><title>KEY STATE OPTIONS</title></info>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Known key states are HIDDEN, RUMOURED, OMNIPRESENT and UNRETENTIVE.
|
||||||
|
These should not be set manually except for testing purposes.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>-s</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
When setting key timing data, also update the state file.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>-g</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Set the goal state for this key. Must be HIDDEN or OMNIPRESENT.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>-d</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Set the DS state for this key, and when it was last changed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>-k</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Set the DNSKEY state for this key, and when it was last changed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>-r</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Set the RRSIG (KSK) state for this key, and when it was last
|
||||||
|
changed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>-z</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Set the RRSIG (ZSK) state for this key, and when it was last
|
||||||
|
changed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsection>
|
||||||
|
|
||||||
<refsection><info><title>PRINTING OPTIONS</title></info>
|
<refsection><info><title>PRINTING OPTIONS</title></info>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -57,6 +57,11 @@
|
|||||||
|
|
||||||
#include "dnssectool.h"
|
#include "dnssectool.h"
|
||||||
|
|
||||||
|
#define KEYSTATES_NVALUES 4
|
||||||
|
static const char *keystates[KEYSTATES_NVALUES] = {
|
||||||
|
"hidden", "rumoured", "omnipresent", "unretentive",
|
||||||
|
};
|
||||||
|
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
uint8_t dtype[8];
|
uint8_t dtype[8];
|
||||||
@ -244,6 +249,21 @@ strtottl(const char *str) {
|
|||||||
return (ttl);
|
return (ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dst_key_state_t
|
||||||
|
strtokeystate(const char *str) {
|
||||||
|
if (isnone(str)) {
|
||||||
|
return (DST_KEY_STATE_NA);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < KEYSTATES_NVALUES; i++) {
|
||||||
|
if (keystates[i] != NULL &&
|
||||||
|
strcasecmp(str, keystates[i]) == 0) {
|
||||||
|
return (dst_key_state_t) i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fatal("unknown key state");
|
||||||
|
}
|
||||||
|
|
||||||
isc_stdtime_t
|
isc_stdtime_t
|
||||||
strtotime(const char *str, int64_t now, int64_t base,
|
strtotime(const char *str, int64_t now, int64_t base,
|
||||||
bool *setp)
|
bool *setp)
|
||||||
|
@ -71,6 +71,8 @@ cleanup_logging(isc_log_t **logp);
|
|||||||
|
|
||||||
dns_ttl_t strtottl(const char *str);
|
dns_ttl_t strtottl(const char *str);
|
||||||
|
|
||||||
|
dst_key_state_t strtokeystate(const char *str);
|
||||||
|
|
||||||
isc_stdtime_t
|
isc_stdtime_t
|
||||||
strtotime(const char *str, int64_t now, int64_t base,
|
strtotime(const char *str, int64_t now, int64_t base,
|
||||||
bool *setp);
|
bool *setp);
|
||||||
|
@ -17,7 +17,6 @@ set -e
|
|||||||
|
|
||||||
status=0
|
status=0
|
||||||
n=0
|
n=0
|
||||||
log=1
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Utilities #
|
# Utilities #
|
||||||
@ -35,9 +34,14 @@ get_keyids() {
|
|||||||
ls ${start}*${end} | sed "s/$dir\/K${zone}.+${algorithm}+\([0-9]\{5\}\)${end}/\1/"
|
ls ${start}*${end} | sed "s/$dir\/K${zone}.+${algorithm}+\([0-9]\{5\}\)${end}/\1/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# By default log errors and don't quit immediately.
|
||||||
|
_log=1
|
||||||
|
_continue=1
|
||||||
log_error() {
|
log_error() {
|
||||||
test $log -eq 1 && echo_i "error: $1"
|
test $_log -eq 1 && echo_i "error: $1"
|
||||||
ret=$((ret+1))
|
ret=$((ret+1))
|
||||||
|
|
||||||
|
test $_continue -eq 1 || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check the created key in directory $1 for zone $2.
|
# Check the created key in directory $1 for zone $2.
|
||||||
@ -115,18 +119,6 @@ check_created_key() {
|
|||||||
#
|
#
|
||||||
# dnssec-keygen
|
# dnssec-keygen
|
||||||
#
|
#
|
||||||
n=$((n+1))
|
|
||||||
echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
|
|
||||||
ret=0
|
|
||||||
$KEYGEN -k _default kasp > keygen.out._default.test$n 2>/dev/null || ret=1
|
|
||||||
lines=$(cat keygen.out._default.test$n | wc -l)
|
|
||||||
test "$lines" -eq 1 || log_error "wrong number of keys created for policy _default"
|
|
||||||
KEY_ID=$(get_keyids "." "kasp" "13")
|
|
||||||
echo_i "check key $KEY_ID..."
|
|
||||||
check_created_key "." "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "3600" "0"
|
|
||||||
test "$ret" -eq 0 || echo_i "failed"
|
|
||||||
status=$((status+ret))
|
|
||||||
|
|
||||||
n=$((n+1))
|
n=$((n+1))
|
||||||
echo_i "check that 'dnssec-keygen -k' (configured policy) creates valid files ($n)"
|
echo_i "check that 'dnssec-keygen -k' (configured policy) creates valid files ($n)"
|
||||||
ret=0
|
ret=0
|
||||||
@ -138,7 +130,7 @@ KEY_ID=$(get_keyids "keys" "kasp" "13")
|
|||||||
echo_i "check key $KEY_ID..."
|
echo_i "check key $KEY_ID..."
|
||||||
check_created_key "keys" "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "200" "31536000"
|
check_created_key "keys" "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "200" "31536000"
|
||||||
# Temporarily don't log errors because we are searching multiple files.
|
# Temporarily don't log errors because we are searching multiple files.
|
||||||
log=0
|
_log=0
|
||||||
# Check the other algorithm.
|
# Check the other algorithm.
|
||||||
KEY_IDS=$(get_keyids "keys" "kasp" "8")
|
KEY_IDS=$(get_keyids "keys" "kasp" "8")
|
||||||
for KEY_ID in $KEY_IDS; do
|
for KEY_ID in $KEY_IDS; do
|
||||||
@ -151,10 +143,21 @@ for KEY_ID in $KEY_IDS; do
|
|||||||
# If ret is non-zero, non of the files matched.
|
# If ret is non-zero, non of the files matched.
|
||||||
test "$ret" -eq 0 || echo_i "failed"
|
test "$ret" -eq 0 || echo_i "failed"
|
||||||
status=$((status+ret))
|
status=$((status+ret))
|
||||||
|
|
||||||
done
|
done
|
||||||
# Turn error logs on again.
|
# Turn error logs on again.
|
||||||
log=1
|
_log=1
|
||||||
|
|
||||||
|
n=$((n+1))
|
||||||
|
echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
|
||||||
|
ret=0
|
||||||
|
$KEYGEN -k _default kasp > keygen.out._default.test$n 2>/dev/null || ret=1
|
||||||
|
lines=$(cat keygen.out._default.test$n | wc -l)
|
||||||
|
test "$lines" -eq 1 || log_error "wrong number of keys created for policy _default"
|
||||||
|
KEY_ID=$(get_keyids "." "kasp" "13")
|
||||||
|
echo_i "check key $KEY_ID..."
|
||||||
|
check_created_key "." "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "3600" "0"
|
||||||
|
test "$ret" -eq 0 || echo_i "failed"
|
||||||
|
status=$((status+ret))
|
||||||
|
|
||||||
n=$((n+1))
|
n=$((n+1))
|
||||||
echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
|
echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
|
||||||
@ -171,6 +174,45 @@ status=$((status+ret))
|
|||||||
#
|
#
|
||||||
# dnssec-settime
|
# dnssec-settime
|
||||||
#
|
#
|
||||||
|
BASE_FILE="K${zone}.+${alg_numpad}+${key_idpad}"
|
||||||
|
KEY_FILE="${BASE_FILE}.key"
|
||||||
|
PRIVATE_FILE="${BASE_FILE}.private"
|
||||||
|
STATE_FILE="${BASE_FILE}.state"
|
||||||
|
CMP_FILE="${BASE_FILE}.cmp"
|
||||||
|
|
||||||
|
n=$((n+1))
|
||||||
|
echo_i "check that 'dnssec-settime' by default does not edit key state file ($n)"
|
||||||
|
ret=0
|
||||||
|
cp $STATE_FILE $CMP_FILE
|
||||||
|
$SETTIME -P +3600 $BASE_FILE >/dev/null || log_error "settime failed"
|
||||||
|
grep "; Publish: " $KEY_FILE > /dev/null || log_error "mismatch published in $KEY_FILE"
|
||||||
|
grep "Publish: " $PRIVATE_FILE > /dev/null || log_error "mismatch published in $PRIVATE_FILE"
|
||||||
|
$DIFF $CMP_FILE $STATE_FILE || log_error "unexpected file change in $STATE_FILE"
|
||||||
|
test "$ret" -eq 0 || echo_i "failed"
|
||||||
|
status=$((status+ret))
|
||||||
|
|
||||||
|
n=$((n+1))
|
||||||
|
echo_i "check that 'dnssec-settime -s' also sets time metadata in key state file ($n)"
|
||||||
|
ret=0
|
||||||
|
cp $STATE_FILE $CMP_FILE
|
||||||
|
now=$(date +%Y%m%d%H%M%S)
|
||||||
|
$SETTIME -s -P $now $BASE_FILE >/dev/null || log_error "settime failed"
|
||||||
|
grep "; Publish: $now" $KEY_FILE > /dev/null || log_error "mismatch published in $KEY_FILE"
|
||||||
|
grep "Publish: $now" $PRIVATE_FILE > /dev/null || log_error "mismatch published in $PRIVATE_FILE"
|
||||||
|
grep "Published: $now" $STATE_FILE > /dev/null || log_error "mismatch published in $STATE_FILE"
|
||||||
|
test "$ret" -eq 0 || echo_i "failed"
|
||||||
|
status=$((status+ret))
|
||||||
|
|
||||||
|
n=$((n+1))
|
||||||
|
echo_i "check that 'dnssec-settime -s' also unsets time metadata in key state file ($n)"
|
||||||
|
ret=0
|
||||||
|
cp $STATE_FILE $CMP_FILE
|
||||||
|
$SETTIME -s -P none $BASE_FILE >/dev/null || log_error "settime failed"
|
||||||
|
grep "; Publish:" $KEY_FILE > /dev/null && log_error "unexpected published in $KEY_FILE"
|
||||||
|
grep "Publish:" $PRIVATE_FILE > /dev/null && log_error "unexpected published in $PRIVATE_FILE"
|
||||||
|
grep "Published:" $STATE_FILE > /dev/null && log_error "unexpected published in $STATE_FILE"
|
||||||
|
test "$ret" -eq 0 || echo_i "failed"
|
||||||
|
status=$((status+ret))
|
||||||
|
|
||||||
#
|
#
|
||||||
# named
|
# named
|
||||||
|
@ -70,20 +70,21 @@
|
|||||||
goto cleanup; \
|
goto cleanup; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NEXTTOKEN_OR_EOF(lex, opt, token) { \
|
#define NEXTTOKEN_OR_EOF(lex, opt, token) \
|
||||||
ret = isc_lex_gettoken(lex, opt, token); \
|
do { \
|
||||||
if (ret == ISC_R_EOF) \
|
ret = isc_lex_gettoken(lex, opt, token); \
|
||||||
break; \
|
if (ret == ISC_R_EOF) \
|
||||||
if (ret != ISC_R_SUCCESS) \
|
break; \
|
||||||
goto cleanup; \
|
if (ret != ISC_R_SUCCESS) \
|
||||||
}
|
goto cleanup; \
|
||||||
|
} while ((*token).type == isc_tokentype_eol); \
|
||||||
|
|
||||||
#define READLINE(lex, opt, token) \
|
#define READLINE(lex, opt, token) \
|
||||||
do { \
|
do { \
|
||||||
ret = isc_lex_gettoken(lex, opt, token); \
|
ret = isc_lex_gettoken(lex, opt, token); \
|
||||||
if (ret == ISC_R_EOF) \
|
if (ret == ISC_R_EOF) \
|
||||||
break; \
|
break; \
|
||||||
else if (ret != ISC_R_SUCCESS) \
|
if (ret != ISC_R_SUCCESS) \
|
||||||
goto cleanup; \
|
goto cleanup; \
|
||||||
} while ((*token).type != isc_tokentype_eol)
|
} while ((*token).type != isc_tokentype_eol)
|
||||||
|
|
||||||
@ -94,6 +95,10 @@
|
|||||||
|
|
||||||
#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
|
#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
|
||||||
static const char *numerictags[NUMERIC_NTAGS] = {
|
static const char *numerictags[NUMERIC_NTAGS] = {
|
||||||
|
"Predecessor:",
|
||||||
|
"Successor:",
|
||||||
|
"MaxTTL:",
|
||||||
|
"RollPeriod:",
|
||||||
"Lifetime:"
|
"Lifetime:"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,18 +113,38 @@ static const char *timingtags[TIMING_NTAGS] = {
|
|||||||
"Generated:",
|
"Generated:",
|
||||||
"Published:",
|
"Published:",
|
||||||
"Active:",
|
"Active:",
|
||||||
"Retired:",
|
|
||||||
"Revoked:",
|
"Revoked:",
|
||||||
|
"Retired:",
|
||||||
"Removed:",
|
"Removed:",
|
||||||
|
|
||||||
"DSPublish:",
|
"DSPublish:",
|
||||||
"SyncPublish:",
|
"SyncPublish:",
|
||||||
"SyncDelete:"
|
"SyncDelete:",
|
||||||
|
|
||||||
|
"DNSKEYChange:",
|
||||||
|
"ZRRSIGChange:",
|
||||||
|
"KRRSIGChange:",
|
||||||
|
"DSChange:"
|
||||||
|
};
|
||||||
|
|
||||||
|
#define KEYSTATES_NTAGS (DST_MAX_KEYSTATES + 1)
|
||||||
|
static const char *keystatestags[KEYSTATES_NTAGS] = {
|
||||||
|
"DNSKEYState:",
|
||||||
|
"ZRRSIGState:",
|
||||||
|
"KRRSIGState:",
|
||||||
|
"DSState:",
|
||||||
|
"GoalState:"
|
||||||
|
};
|
||||||
|
|
||||||
|
#define KEYSTATES_NVALUES 4
|
||||||
|
static const char *keystates[KEYSTATES_NVALUES] = {
|
||||||
|
"hidden", "rumoured", "omnipresent", "unretentive",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define STATE_ALGORITHM_STR "Algorithm:"
|
#define STATE_ALGORITHM_STR "Algorithm:"
|
||||||
#define STATE_LENGTH_STR "Length:"
|
#define STATE_LENGTH_STR "Length:"
|
||||||
#define MAX_NTAGS (DST_MAX_NUMERIC + DST_MAX_BOOLEAN + DST_MAX_TIMES)
|
#define MAX_NTAGS (DST_MAX_NUMERIC + DST_MAX_BOOLEAN + \
|
||||||
|
DST_MAX_TIMES + DST_MAX_KEYSTATES)
|
||||||
|
|
||||||
static dst_func_t *dst_t_func[DST_MAX_ALGS];
|
static dst_func_t *dst_t_func[DST_MAX_ALGS];
|
||||||
|
|
||||||
@ -604,10 +629,23 @@ dst_key_fromnamedfile(const char *filename, const char *dirname,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key = get_key_struct(pubkey->key_name, pubkey->key_alg,
|
||||||
|
pubkey->key_flags, pubkey->key_proto,
|
||||||
|
pubkey->key_size, pubkey->key_class,
|
||||||
|
pubkey->key_ttl, mctx);
|
||||||
|
if (key == NULL) {
|
||||||
|
dst_key_free(&pubkey);
|
||||||
|
return (ISC_R_NOMEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key->func->parse == NULL)
|
||||||
|
RETERR(DST_R_UNSUPPORTEDALG);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the state file, if requested by type.
|
* Read the state file, if requested by type.
|
||||||
*/
|
*/
|
||||||
if ((type & DST_TYPE_STATE) != 0) {
|
if ((type & DST_TYPE_STATE) != 0) {
|
||||||
|
|
||||||
newfilenamelen = strlen(filename) + 7;
|
newfilenamelen = strlen(filename) + 7;
|
||||||
if (dirname != NULL) {
|
if (dirname != NULL) {
|
||||||
newfilenamelen += strlen(dirname) + 1;
|
newfilenamelen += strlen(dirname) + 1;
|
||||||
@ -617,23 +655,17 @@ dst_key_fromnamedfile(const char *filename, const char *dirname,
|
|||||||
dirname, filename, ".state");
|
dirname, filename, ".state");
|
||||||
INSIST(result == ISC_R_SUCCESS);
|
INSIST(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = dst_key_read_state(newfilename, mctx, pubkey);
|
result = dst_key_read_state(newfilename, mctx, &key);
|
||||||
|
if (result == ISC_R_FILENOTFOUND) {
|
||||||
|
/* Having no state is valid. */
|
||||||
|
result = ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
isc_mem_put(mctx, newfilename, newfilenamelen);
|
isc_mem_put(mctx, newfilename, newfilenamelen);
|
||||||
newfilename = NULL;
|
newfilename = NULL;
|
||||||
RETERR(result);
|
RETERR(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
key = get_key_struct(pubkey->key_name, pubkey->key_alg,
|
|
||||||
pubkey->key_flags, pubkey->key_proto, 0,
|
|
||||||
pubkey->key_class, pubkey->key_ttl, mctx);
|
|
||||||
if (key == NULL) {
|
|
||||||
dst_key_free(&pubkey);
|
|
||||||
return (ISC_R_NOMEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key->func->parse == NULL)
|
|
||||||
RETERR(DST_R_UNSUPPORTEDALG);
|
|
||||||
|
|
||||||
newfilenamelen = strlen(filename) + 9;
|
newfilenamelen = strlen(filename) + 9;
|
||||||
if (dirname != NULL)
|
if (dirname != NULL)
|
||||||
newfilenamelen += strlen(dirname) + 1;
|
newfilenamelen += strlen(dirname) + 1;
|
||||||
@ -1611,17 +1643,32 @@ find_timingdata(const char *s) {
|
|||||||
return (find_metadata(s, timingtags, TIMING_NTAGS));
|
return (find_metadata(s, timingtags, TIMING_NTAGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
find_keystatedata(const char *s) {
|
||||||
|
return (find_metadata(s, keystatestags, KEYSTATES_NTAGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
keystate_fromtext(const char *s, dst_key_state_t *state) {
|
||||||
|
for (int i = 0; i < KEYSTATES_NVALUES; i++) {
|
||||||
|
if (keystates[i] != NULL && strcasecmp(s, keystates[i]) == 0) {
|
||||||
|
*state = (dst_key_state_t) i;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* Reads a key state from disk.
|
* Reads a key state from disk.
|
||||||
*/
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t **keyp)
|
||||||
{
|
{
|
||||||
isc_lex_t *lex = NULL;
|
isc_lex_t *lex = NULL;
|
||||||
isc_token_t token;
|
isc_token_t token;
|
||||||
isc_result_t ret;
|
isc_result_t ret;
|
||||||
unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
|
unsigned int opt = ISC_LEXOPT_EOL;
|
||||||
|
|
||||||
ret = isc_lex_create(mctx, 1500, &lex);
|
ret = isc_lex_create(mctx, 1500, &lex);
|
||||||
if (ret != ISC_R_SUCCESS) {
|
if (ret != ISC_R_SUCCESS) {
|
||||||
@ -1634,6 +1681,11 @@ dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the comment line.
|
||||||
|
*/
|
||||||
|
READLINE(lex, opt, &token);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the algorithm line.
|
* Read the algorithm line.
|
||||||
*/
|
*/
|
||||||
@ -1646,11 +1698,13 @@ dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
|||||||
|
|
||||||
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
||||||
if (token.type != isc_tokentype_number ||
|
if (token.type != isc_tokentype_number ||
|
||||||
token.value.as_ulong != (unsigned long) dst_key_alg(key))
|
token.value.as_ulong != (unsigned long) dst_key_alg(*keyp))
|
||||||
{
|
{
|
||||||
BADTOKEN();
|
BADTOKEN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
READLINE(lex, opt, &token);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the length line.
|
* Read the length line.
|
||||||
*/
|
*/
|
||||||
@ -1663,11 +1717,13 @@ dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
|||||||
|
|
||||||
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
||||||
if (token.type != isc_tokentype_number ||
|
if (token.type != isc_tokentype_number ||
|
||||||
token.value.as_ulong != (unsigned long) dst_key_size(key))
|
token.value.as_ulong != (unsigned long) dst_key_size(*keyp))
|
||||||
{
|
{
|
||||||
BADTOKEN();
|
BADTOKEN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
READLINE(lex, opt, &token);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the metadata.
|
* Read the metadata.
|
||||||
*/
|
*/
|
||||||
@ -1675,6 +1731,9 @@ dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
|||||||
int tag;
|
int tag;
|
||||||
|
|
||||||
NEXTTOKEN_OR_EOF(lex, opt, &token);
|
NEXTTOKEN_OR_EOF(lex, opt, &token);
|
||||||
|
if (ret == ISC_R_EOF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (token.type != isc_tokentype_string) {
|
if (token.type != isc_tokentype_string) {
|
||||||
BADTOKEN();
|
BADTOKEN();
|
||||||
}
|
}
|
||||||
@ -1682,12 +1741,14 @@ dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
|||||||
/* Numeric metadata */
|
/* Numeric metadata */
|
||||||
tag = find_numericdata(DST_AS_STR(token));
|
tag = find_numericdata(DST_AS_STR(token));
|
||||||
if (tag >= 0) {
|
if (tag >= 0) {
|
||||||
|
INSIST(tag < NUMERIC_NTAGS);
|
||||||
|
|
||||||
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
||||||
if (token.type != isc_tokentype_number) {
|
if (token.type != isc_tokentype_number) {
|
||||||
BADTOKEN();
|
BADTOKEN();
|
||||||
}
|
}
|
||||||
dst_key_setnum(key, tag, token.value.as_ulong);
|
|
||||||
|
|
||||||
|
dst_key_setnum(*keyp, tag, token.value.as_ulong);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1700,14 +1761,14 @@ dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
|||||||
if (token.type != isc_tokentype_string) {
|
if (token.type != isc_tokentype_string) {
|
||||||
BADTOKEN();
|
BADTOKEN();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(DST_AS_STR(token), "yes") == 0) {
|
if (strcmp(DST_AS_STR(token), "yes") == 0) {
|
||||||
dst_key_setbool(key, tag, true);
|
dst_key_setbool(*keyp, tag, true);
|
||||||
} else if (strcmp(DST_AS_STR(token), "no") == 0) {
|
} else if (strcmp(DST_AS_STR(token), "no") == 0) {
|
||||||
dst_key_setbool(key, tag, false);
|
dst_key_setbool(*keyp, tag, false);
|
||||||
} else {
|
} else {
|
||||||
BADTOKEN();
|
BADTOKEN();
|
||||||
}
|
}
|
||||||
|
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1727,13 +1788,35 @@ dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *key)
|
|||||||
if (ret != ISC_R_SUCCESS) {
|
if (ret != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
dst_key_settime(key, tag, when);
|
|
||||||
|
|
||||||
|
dst_key_settime(*keyp, tag, when);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keystate metadata */
|
||||||
|
tag = find_keystatedata(DST_AS_STR(token));
|
||||||
|
if (tag >= 0) {
|
||||||
|
dst_key_state_t state;
|
||||||
|
|
||||||
|
INSIST(tag < KEYSTATES_NTAGS);
|
||||||
|
|
||||||
|
NEXTTOKEN(lex, opt, &token);
|
||||||
|
if (token.type != isc_tokentype_string) {
|
||||||
|
BADTOKEN();
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = keystate_fromtext(DST_AS_STR(token), &state);
|
||||||
|
if (ret != ISC_R_SUCCESS) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst_key_setstate(*keyp, tag, state);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
READLINE(lex, opt, &token);
|
READLINE(lex, opt, &token);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done, successfully parsed the whole file. */
|
/* Done, successfully parsed the whole file. */
|
||||||
@ -1847,6 +1930,21 @@ printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
|
|||||||
fprintf(stream, "%s: (set, unable to display)\n", tag);
|
fprintf(stream, "%s: (set, unable to display)\n", tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*%
|
||||||
|
* Write key state metadata to a file pointer, preceded by 'tag'
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
printstate(const dst_key_t *key, int type, const char *tag, FILE *stream) {
|
||||||
|
isc_result_t result;
|
||||||
|
dst_key_state_t value = 0;
|
||||||
|
|
||||||
|
result = dst_key_getstate(key, type, &value);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(stream, "%s: %s\n", tag, keystates[value]);
|
||||||
|
}
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* Writes a key state to disk.
|
* Writes a key state to disk.
|
||||||
*/
|
*/
|
||||||
@ -1898,6 +1996,11 @@ write_key_state(const dst_key_t *key, int type, const char *directory) {
|
|||||||
fprintf(fp, "Algorithm: %u\n", key->key_alg);
|
fprintf(fp, "Algorithm: %u\n", key->key_alg);
|
||||||
fprintf(fp, "Length: %u\n", key->key_size);
|
fprintf(fp, "Length: %u\n", key->key_size);
|
||||||
|
|
||||||
|
printnum(key, DST_NUM_LIFETIME, "Lifetime", fp);
|
||||||
|
|
||||||
|
printbool(key, DST_BOOL_KSK, "KSK", fp);
|
||||||
|
printbool(key, DST_BOOL_ZSK, "ZSK", fp);
|
||||||
|
|
||||||
printtime(key, DST_TIME_CREATED, "Generated", fp);
|
printtime(key, DST_TIME_CREATED, "Generated", fp);
|
||||||
printtime(key, DST_TIME_PUBLISH, "Published", fp);
|
printtime(key, DST_TIME_PUBLISH, "Published", fp);
|
||||||
printtime(key, DST_TIME_ACTIVATE, "Active", fp);
|
printtime(key, DST_TIME_ACTIVATE, "Active", fp);
|
||||||
@ -1905,10 +2008,16 @@ write_key_state(const dst_key_t *key, int type, const char *directory) {
|
|||||||
printtime(key, DST_TIME_REVOKE, "Revoked", fp);
|
printtime(key, DST_TIME_REVOKE, "Revoked", fp);
|
||||||
printtime(key, DST_TIME_DELETE, "Removed", fp);
|
printtime(key, DST_TIME_DELETE, "Removed", fp);
|
||||||
|
|
||||||
printnum(key, DST_NUM_LIFETIME, "Lifetime", fp);
|
printtime(key, DST_TIME_DNSKEY, "DNSKEYChange", fp);
|
||||||
|
printtime(key, DST_TIME_ZRRSIG, "ZRRSIGChange", fp);
|
||||||
|
printtime(key, DST_TIME_KRRSIG, "KRRSIGChange", fp);
|
||||||
|
printtime(key, DST_TIME_DS, "DSChange", fp);
|
||||||
|
|
||||||
printbool(key, DST_BOOL_KSK, "KSK", fp);
|
printstate(key, DST_KEY_DNSKEY, "DNSKEYState", fp);
|
||||||
printbool(key, DST_BOOL_ZSK, "ZSK", fp);
|
printstate(key, DST_KEY_ZRRSIG, "ZRRSIGState", fp);
|
||||||
|
printstate(key, DST_KEY_KRRSIG, "KRRSIGState", fp);
|
||||||
|
printstate(key, DST_KEY_DS, "DSState", fp);
|
||||||
|
printstate(key, DST_KEY_GOAL, "GoalState", fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
|
@ -108,11 +108,16 @@ struct dst_key {
|
|||||||
|
|
||||||
isc_stdtime_t times[DST_MAX_TIMES + 1]; /*%< timing metadata */
|
isc_stdtime_t times[DST_MAX_TIMES + 1]; /*%< timing metadata */
|
||||||
bool timeset[DST_MAX_TIMES + 1]; /*%< data set? */
|
bool timeset[DST_MAX_TIMES + 1]; /*%< data set? */
|
||||||
|
|
||||||
uint32_t nums[DST_MAX_NUMERIC + 1]; /*%< numeric metadata */
|
uint32_t nums[DST_MAX_NUMERIC + 1]; /*%< numeric metadata */
|
||||||
bool numset[DST_MAX_NUMERIC + 1]; /*%< data set? */
|
bool numset[DST_MAX_NUMERIC + 1]; /*%< data set? */
|
||||||
|
|
||||||
bool bools[DST_MAX_BOOLEAN + 1]; /*%< boolean metadata */
|
bool bools[DST_MAX_BOOLEAN + 1]; /*%< boolean metadata */
|
||||||
bool boolset[DST_MAX_BOOLEAN + 1]; /*%< data set? */
|
bool boolset[DST_MAX_BOOLEAN + 1]; /*%< data set? */
|
||||||
|
|
||||||
|
dst_key_state_t keystates[DST_MAX_KEYSTATES + 1]; /*%< key states */
|
||||||
|
bool keystateset[DST_MAX_KEYSTATES + 1]; /*%< data set? */
|
||||||
|
|
||||||
bool inactive; /*%< private key not present as it is inactive */
|
bool inactive; /*%< private key not present as it is inactive */
|
||||||
bool external; /*%< external key */
|
bool external; /*%< external key */
|
||||||
|
|
||||||
|
@ -61,7 +61,11 @@ static const char *timetags[TIMING_NTAGS] = {
|
|||||||
"Delete:",
|
"Delete:",
|
||||||
"DSPublish:",
|
"DSPublish:",
|
||||||
"SyncPublish:",
|
"SyncPublish:",
|
||||||
"SyncDelete:"
|
"SyncDelete:",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
|
#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
|
||||||
@ -69,7 +73,8 @@ static const char *numerictags[NUMERIC_NTAGS] = {
|
|||||||
"Predecessor:",
|
"Predecessor:",
|
||||||
"Successor:",
|
"Successor:",
|
||||||
"MaxTTL:",
|
"MaxTTL:",
|
||||||
"RollPeriod:"
|
"RollPeriod:",
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct parse_map {
|
struct parse_map {
|
||||||
@ -754,7 +759,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
|
|||||||
|
|
||||||
if (timetags[i] != NULL) {
|
if (timetags[i] != NULL) {
|
||||||
fprintf(fp, "%s %.*s\n", timetags[i],
|
fprintf(fp, "%s %.*s\n", timetags[i],
|
||||||
(int)r.length, r.base);
|
(int)r.length, r.base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,38 @@ ISC_LANG_BEGINDECLS
|
|||||||
typedef struct dst_key dst_key_t;
|
typedef struct dst_key dst_key_t;
|
||||||
typedef struct dst_context dst_context_t;
|
typedef struct dst_context dst_context_t;
|
||||||
|
|
||||||
|
/*%
|
||||||
|
* Key states for the DNSSEC records related to a key: DNSKEY, RRSIG (ksk),
|
||||||
|
* RRSIG (zsk), and DS.
|
||||||
|
*
|
||||||
|
* DST_KEY_STATE_HIDDEN: Records of this type are not published in zone.
|
||||||
|
* This may be because the key parts were never
|
||||||
|
* introduced in the zone, or because the key has
|
||||||
|
* retired and has no records of this type left in
|
||||||
|
* the zone.
|
||||||
|
* DST_KEY_STATE_RUMOURED: Records of this type are published in zone, but
|
||||||
|
* not long enough to ensure all resolvers know
|
||||||
|
* about it.
|
||||||
|
* DST_KEY_STATE_OMNIPRESENT: Records of this type are published in zone long
|
||||||
|
* enough so that all resolvers that know about
|
||||||
|
* these records, no longer have outdated data.
|
||||||
|
* DST_KEY_STATE_UNRETENTIVE: Records of this type have been removed from the
|
||||||
|
* zone, but there may be resolvers that still have
|
||||||
|
* have predecessor records cached. Note that RRSIG
|
||||||
|
* records in this state may actually still be in the
|
||||||
|
* zone because they are reused, but retired RRSIG
|
||||||
|
* records will never be refreshed: A successor key
|
||||||
|
* is used to create signatures.
|
||||||
|
* DST_KEY_STATE_NA: The state is not applicable for this record type.
|
||||||
|
*/
|
||||||
|
typedef enum dst_key_state {
|
||||||
|
DST_KEY_STATE_HIDDEN = 0,
|
||||||
|
DST_KEY_STATE_RUMOURED = 1,
|
||||||
|
DST_KEY_STATE_OMNIPRESENT = 2,
|
||||||
|
DST_KEY_STATE_UNRETENTIVE = 3,
|
||||||
|
DST_KEY_STATE_NA = 4
|
||||||
|
} dst_key_state_t;
|
||||||
|
|
||||||
/* DST algorithm codes */
|
/* DST algorithm codes */
|
||||||
#define DST_ALG_UNKNOWN 0
|
#define DST_ALG_UNKNOWN 0
|
||||||
#define DST_ALG_RSA 1 /* Used for parsing RSASHA1, RSASHA256 and RSASHA512 */
|
#define DST_ALG_RSA 1 /* Used for parsing RSASHA1, RSASHA256 and RSASHA512 */
|
||||||
@ -97,7 +129,11 @@ typedef struct dst_context dst_context_t;
|
|||||||
#define DST_TIME_DSPUBLISH 6
|
#define DST_TIME_DSPUBLISH 6
|
||||||
#define DST_TIME_SYNCPUBLISH 7
|
#define DST_TIME_SYNCPUBLISH 7
|
||||||
#define DST_TIME_SYNCDELETE 8
|
#define DST_TIME_SYNCDELETE 8
|
||||||
#define DST_MAX_TIMES 8
|
#define DST_TIME_DNSKEY 9
|
||||||
|
#define DST_TIME_ZRRSIG 10
|
||||||
|
#define DST_TIME_KRRSIG 11
|
||||||
|
#define DST_TIME_DS 12
|
||||||
|
#define DST_MAX_TIMES 12
|
||||||
|
|
||||||
/* Numeric metadata definitions */
|
/* Numeric metadata definitions */
|
||||||
#define DST_NUM_PREDECESSOR 0
|
#define DST_NUM_PREDECESSOR 0
|
||||||
@ -112,6 +148,14 @@ typedef struct dst_context dst_context_t;
|
|||||||
#define DST_BOOL_ZSK 1
|
#define DST_BOOL_ZSK 1
|
||||||
#define DST_MAX_BOOLEAN 1
|
#define DST_MAX_BOOLEAN 1
|
||||||
|
|
||||||
|
/* Key state metadata definitions */
|
||||||
|
#define DST_KEY_DNSKEY 0
|
||||||
|
#define DST_KEY_ZRRSIG 1
|
||||||
|
#define DST_KEY_KRRSIG 2
|
||||||
|
#define DST_KEY_DS 3
|
||||||
|
#define DST_KEY_GOAL 4
|
||||||
|
#define DST_MAX_KEYSTATES 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Current format version number of the private key parser.
|
* Current format version number of the private key parser.
|
||||||
*
|
*
|
||||||
@ -391,7 +435,7 @@ dst_key_read_public(const char *filename, int type,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t *keyp);
|
dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t **keyp);
|
||||||
/*%<
|
/*%<
|
||||||
* Reads a key state from permanent storage.
|
* Reads a key state from permanent storage.
|
||||||
*
|
*
|
||||||
@ -929,6 +973,38 @@ dst_key_unsettime(dst_key_t *key, int type);
|
|||||||
* "type" is no larger than DST_MAX_TIMES
|
* "type" is no larger than DST_MAX_TIMES
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dst_key_getstate(const dst_key_t *key, int type, dst_key_state_t *statep);
|
||||||
|
/*%<
|
||||||
|
* Get a member of the keystate metadata array and place it in '*statep'.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* "key" is a valid key.
|
||||||
|
* "type" is no larger than DST_MAX_KEYSTATES
|
||||||
|
* "statep" is not null.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state);
|
||||||
|
/*%<
|
||||||
|
* Set a member of the keystate metadata array.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* "key" is a valid key.
|
||||||
|
* "state" is a valid state.
|
||||||
|
* "type" is no larger than DST_MAX_KEYSTATES
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dst_key_unsetstate(dst_key_t *key, int type);
|
||||||
|
/*%<
|
||||||
|
* Flag a member of the keystate metadata array as "not set".
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* "key" is a valid key.
|
||||||
|
* "type" is no larger than DST_MAX_KEYSTATES
|
||||||
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp);
|
dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp);
|
||||||
/*%<
|
/*%<
|
||||||
|
@ -1411,6 +1411,7 @@ dst_key_getfilename
|
|||||||
dst_key_getgssctx
|
dst_key_getgssctx
|
||||||
dst_key_getnum
|
dst_key_getnum
|
||||||
dst_key_getprivateformat
|
dst_key_getprivateformat
|
||||||
|
dst_key_getstate
|
||||||
dst_key_gettime
|
dst_key_gettime
|
||||||
dst_key_getttl
|
dst_key_getttl
|
||||||
dst_key_id
|
dst_key_id
|
||||||
@ -1436,6 +1437,7 @@ dst_key_setflags
|
|||||||
dst_key_setinactive
|
dst_key_setinactive
|
||||||
dst_key_setnum
|
dst_key_setnum
|
||||||
dst_key_setprivateformat
|
dst_key_setprivateformat
|
||||||
|
dst_key_setstate
|
||||||
dst_key_settime
|
dst_key_settime
|
||||||
dst_key_setttl
|
dst_key_setttl
|
||||||
dst_key_sigsize
|
dst_key_sigsize
|
||||||
@ -1446,6 +1448,7 @@ dst_key_todns
|
|||||||
dst_key_tofile
|
dst_key_tofile
|
||||||
dst_key_unsetbool
|
dst_key_unsetbool
|
||||||
dst_key_unsetnum
|
dst_key_unsetnum
|
||||||
|
dst_key_unsetstate
|
||||||
dst_key_unsettime
|
dst_key_unsettime
|
||||||
dst_lib_destroy
|
dst_lib_destroy
|
||||||
dst_lib_init
|
dst_lib_init
|
||||||
|
Loading…
x
Reference in New Issue
Block a user