"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/bin/dnssec/dnssec-settime.c" (4 Sep 2020, 25109 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dnssec-settime.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.17.4_vs_9.17.5.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <errno.h>
   15 #include <inttypes.h>
   16 #include <stdbool.h>
   17 #include <stdlib.h>
   18 #include <time.h>
   19 #include <unistd.h>
   20 
   21 #include <isc/attributes.h>
   22 #include <isc/buffer.h>
   23 #include <isc/commandline.h>
   24 #include <isc/file.h>
   25 #include <isc/hash.h>
   26 #include <isc/mem.h>
   27 #include <isc/print.h>
   28 #include <isc/string.h>
   29 #include <isc/time.h>
   30 #include <isc/util.h>
   31 
   32 #include <dns/keyvalues.h>
   33 #include <dns/log.h>
   34 #include <dns/result.h>
   35 
   36 #include <dst/dst.h>
   37 
   38 #if USE_PKCS11
   39 #include <pk11/result.h>
   40 #endif /* if USE_PKCS11 */
   41 
   42 #include "dnssectool.h"
   43 
   44 const char *program = "dnssec-settime";
   45 
   46 static isc_mem_t *mctx = NULL;
   47 
   48 ISC_NORETURN static void
   49 usage(void);
   50 
   51 static void
   52 usage(void) {
   53     fprintf(stderr, "Usage:\n");
   54     fprintf(stderr, "    %s [options] keyfile\n\n", program);
   55     fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
   56     fprintf(stderr, "General options:\n");
   57 #if USE_PKCS11
   58     fprintf(stderr,
   59         "    -E engine:          specify PKCS#11 provider "
   60         "(default: %s)\n",
   61         PK11_LIB_LOCATION);
   62 #elif defined(USE_PKCS11)
   63     fprintf(stderr, "    -E engine:          specify OpenSSL engine "
   64             "(default \"pkcs11\")\n");
   65 #else  /* if USE_PKCS11 */
   66     fprintf(stderr, "    -E engine:          specify OpenSSL engine\n");
   67 #endif /* if USE_PKCS11 */
   68     fprintf(stderr, "    -f:                 force update of old-style "
   69             "keys\n");
   70     fprintf(stderr, "    -K directory:       set key file location\n");
   71     fprintf(stderr, "    -L ttl:             set default key TTL\n");
   72     fprintf(stderr, "    -v level:           set level of verbosity\n");
   73     fprintf(stderr, "    -V:                 print version information\n");
   74     fprintf(stderr, "    -h:                 help\n");
   75     fprintf(stderr, "Timing options:\n");
   76     fprintf(stderr, "    -P date/[+-]offset/none: set/unset key "
   77             "publication date\n");
   78     fprintf(stderr, "    -P ds date/[+-]offset/none: set/unset "
   79             "DS publication date\n");
   80     fprintf(stderr, "    -P sync date/[+-]offset/none: set/unset "
   81             "CDS and CDNSKEY publication date\n");
   82     fprintf(stderr, "    -A date/[+-]offset/none: set/unset key "
   83             "activation date\n");
   84     fprintf(stderr, "    -R date/[+-]offset/none: set/unset key "
   85             "revocation date\n");
   86     fprintf(stderr, "    -I date/[+-]offset/none: set/unset key "
   87             "inactivation date\n");
   88     fprintf(stderr, "    -D date/[+-]offset/none: set/unset key "
   89             "deletion date\n");
   90     fprintf(stderr, "    -D ds date/[+-]offset/none: set/unset "
   91             "DS deletion date\n");
   92     fprintf(stderr, "    -D sync date/[+-]offset/none: set/unset "
   93             "CDS and CDNSKEY deletion date\n");
   94     fprintf(stderr, "    -S <key>: generate a successor to an existing "
   95             "key\n");
   96     fprintf(stderr, "    -i <interval>: prepublication interval for "
   97             "successor key "
   98             "(default: 30 days)\n");
   99     fprintf(stderr, "Key state options:\n");
  100     fprintf(stderr, "    -s: update key state file (default no)\n");
  101     fprintf(stderr, "    -g state: set the goal state for this key\n");
  102     fprintf(stderr, "    -d state date/[+-]offset: set the DS state\n");
  103     fprintf(stderr, "    -k state date/[+-]offset: set the DNSKEY state\n");
  104     fprintf(stderr, "    -r state date/[+-]offset: set the RRSIG (KSK) "
  105             "state\n");
  106     fprintf(stderr, "    -z state date/[+-]offset: set the RRSIG (ZSK) "
  107             "state\n");
  108     fprintf(stderr, "Printing options:\n");
  109     fprintf(stderr, "    -p C/P/Psync/A/R/I/D/Dsync/all: print a "
  110             "particular time value or values\n");
  111     fprintf(stderr, "    -u:                 print times in unix epoch "
  112             "format\n");
  113     fprintf(stderr, "Output:\n");
  114     fprintf(stderr, "     K<name>+<alg>+<new id>.key, "
  115             "K<name>+<alg>+<new id>.private\n");
  116 
  117     exit(-1);
  118 }
  119 
  120 static void
  121 printtime(dst_key_t *key, int type, const char *tag, bool epoch, FILE *stream) {
  122     isc_result_t result;
  123     isc_stdtime_t when;
  124 
  125     if (tag != NULL) {
  126         fprintf(stream, "%s: ", tag);
  127     }
  128 
  129     result = dst_key_gettime(key, type, &when);
  130     if (result == ISC_R_NOTFOUND) {
  131         fprintf(stream, "UNSET\n");
  132     } else if (epoch) {
  133         fprintf(stream, "%d\n", (int)when);
  134     } else {
  135         time_t now = when;
  136         struct tm t, *tm = localtime_r(&now, &t);
  137         unsigned int flen;
  138         char timebuf[80];
  139 
  140         if (tm == NULL) {
  141             fprintf(stream, "INVALID\n");
  142             return;
  143         }
  144 
  145         flen = strftime(timebuf, sizeof(timebuf),
  146                 "%a %b %e %H:%M:%S %Y", tm);
  147         INSIST(flen > 0U && flen < sizeof(timebuf));
  148         fprintf(stream, "%s\n", timebuf);
  149     }
  150 }
  151 
  152 static void
  153 writekey(dst_key_t *key, const char *directory, bool write_state) {
  154     char newname[1024];
  155     char keystr[DST_KEY_FORMATSIZE];
  156     isc_buffer_t buf;
  157     isc_result_t result;
  158     int options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE;
  159 
  160     if (write_state) {
  161         options |= DST_TYPE_STATE;
  162     }
  163 
  164     isc_buffer_init(&buf, newname, sizeof(newname));
  165     result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf);
  166     if (result != ISC_R_SUCCESS) {
  167         fatal("Failed to build public key filename: %s",
  168               isc_result_totext(result));
  169     }
  170 
  171     result = dst_key_tofile(key, options, directory);
  172     if (result != ISC_R_SUCCESS) {
  173         dst_key_format(key, keystr, sizeof(keystr));
  174         fatal("Failed to write key %s: %s", keystr,
  175               isc_result_totext(result));
  176     }
  177     printf("%s\n", newname);
  178 
  179     isc_buffer_clear(&buf);
  180     result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf);
  181     if (result != ISC_R_SUCCESS) {
  182         fatal("Failed to build private key filename: %s",
  183               isc_result_totext(result));
  184     }
  185     printf("%s\n", newname);
  186 
  187     if (write_state) {
  188         isc_buffer_clear(&buf);
  189         result = dst_key_buildfilename(key, DST_TYPE_STATE, directory,
  190                            &buf);
  191         if (result != ISC_R_SUCCESS) {
  192             fatal("Failed to build key state filename: %s",
  193                   isc_result_totext(result));
  194         }
  195         printf("%s\n", newname);
  196     }
  197 }
  198 
  199 int
  200 main(int argc, char **argv) {
  201     isc_result_t result;
  202     const char *engine = NULL;
  203     const char *filename = NULL;
  204     char *directory = NULL;
  205     char keystr[DST_KEY_FORMATSIZE];
  206     char *endp, *p;
  207     int ch;
  208     const char *predecessor = NULL;
  209     dst_key_t *prevkey = NULL;
  210     dst_key_t *key = NULL;
  211     dns_name_t *name = NULL;
  212     dns_secalg_t alg = 0;
  213     unsigned int size = 0;
  214     uint16_t flags = 0;
  215     int prepub = -1;
  216     int options;
  217     dns_ttl_t ttl = 0;
  218     isc_stdtime_t now;
  219     isc_stdtime_t dstime = 0, dnskeytime = 0;
  220     isc_stdtime_t krrsigtime = 0, zrrsigtime = 0;
  221     isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0;
  222     isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0;
  223     dst_key_state_t goal = DST_KEY_STATE_NA;
  224     dst_key_state_t ds = DST_KEY_STATE_NA;
  225     dst_key_state_t dnskey = DST_KEY_STATE_NA;
  226     dst_key_state_t krrsig = DST_KEY_STATE_NA;
  227     dst_key_state_t zrrsig = DST_KEY_STATE_NA;
  228     bool setgoal = false, setds = false, setdnskey = false;
  229     bool setkrrsig = false, setzrrsig = false;
  230     bool setdstime = false, setdnskeytime = false;
  231     bool setkrrsigtime = false, setzrrsigtime = false;
  232     bool setpub = false, setact = false;
  233     bool setrev = false, setinact = false;
  234     bool setdel = false, setttl = false;
  235     bool unsetpub = false, unsetact = false;
  236     bool unsetrev = false, unsetinact = false;
  237     bool unsetdel = false;
  238     bool printcreate = false, printpub = false;
  239     bool printact = false, printrev = false;
  240     bool printinact = false, printdel = false;
  241     bool force = false;
  242     bool epoch = false;
  243     bool changed = false;
  244     bool write_state = false;
  245     isc_log_t *log = NULL;
  246     isc_stdtime_t syncadd = 0, syncdel = 0;
  247     bool unsetsyncadd = false, setsyncadd = false;
  248     bool unsetsyncdel = false, setsyncdel = false;
  249     bool printsyncadd = false, printsyncdel = false;
  250     isc_stdtime_t dsadd = 0, dsdel = 0;
  251     bool unsetdsadd = false, setdsadd = false;
  252     bool unsetdsdel = false, setdsdel = false;
  253     bool printdsadd = false, printdsdel = false;
  254 
  255     options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE;
  256 
  257     if (argc == 1) {
  258         usage();
  259     }
  260 
  261     isc_mem_create(&mctx);
  262 
  263     setup_logging(mctx, &log);
  264 
  265 #if USE_PKCS11
  266     pk11_result_register();
  267 #endif /* if USE_PKCS11 */
  268     dns_result_register();
  269 
  270     isc_commandline_errprint = false;
  271 
  272     isc_stdtime_get(&now);
  273 
  274 #define CMDLINE_FLAGS "A:D:d:E:fg:hI:i:K:k:L:P:p:R:r:S:suv:Vz:"
  275     while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
  276         switch (ch) {
  277         case 'A':
  278             if (setact || unsetact) {
  279                 fatal("-A specified more than once");
  280             }
  281 
  282             changed = true;
  283             act = strtotime(isc_commandline_argument, now, now,
  284                     &setact);
  285             unsetact = !setact;
  286             break;
  287         case 'D':
  288             /* -Dsync ? */
  289             if (isoptarg("sync", argv, usage)) {
  290                 if (unsetsyncdel || setsyncdel) {
  291                     fatal("-D sync specified more than "
  292                           "once");
  293                 }
  294 
  295                 changed = true;
  296                 syncdel = strtotime(isc_commandline_argument,
  297                             now, now, &setsyncdel);
  298                 unsetsyncdel = !setsyncdel;
  299                 break;
  300             }
  301             /* -Dds ? */
  302             if (isoptarg("ds", argv, usage)) {
  303                 if (unsetdsdel || setdsdel) {
  304                     fatal("-D ds specified more than once");
  305                 }
  306 
  307                 changed = true;
  308                 dsdel = strtotime(isc_commandline_argument, now,
  309                           now, &setdsdel);
  310                 unsetdsdel = !setdsdel;
  311                 break;
  312             }
  313             /* -Ddnskey ? */
  314             (void)isoptarg("dnskey", argv, usage);
  315             if (setdel || unsetdel) {
  316                 fatal("-D specified more than once");
  317             }
  318 
  319             changed = true;
  320             del = strtotime(isc_commandline_argument, now, now,
  321                     &setdel);
  322             unsetdel = !setdel;
  323             break;
  324         case 'd':
  325             if (setds) {
  326                 fatal("-d specified more than once");
  327             }
  328 
  329             ds = strtokeystate(isc_commandline_argument);
  330             setds = true;
  331             /* time */
  332             (void)isoptarg(isc_commandline_argument, argv, usage);
  333             dstime = strtotime(isc_commandline_argument, now, now,
  334                        &setdstime);
  335             break;
  336         case 'E':
  337             engine = isc_commandline_argument;
  338             break;
  339         case 'f':
  340             force = true;
  341             break;
  342         case 'g':
  343             if (setgoal) {
  344                 fatal("-g specified more than once");
  345             }
  346 
  347             goal = strtokeystate(isc_commandline_argument);
  348             if (goal != DST_KEY_STATE_NA &&
  349                 goal != DST_KEY_STATE_HIDDEN &&
  350                 goal != DST_KEY_STATE_OMNIPRESENT)
  351             {
  352                 fatal("-g must be either none, hidden, or "
  353                       "omnipresent");
  354             }
  355             setgoal = true;
  356             break;
  357         case '?':
  358             if (isc_commandline_option != '?') {
  359                 fprintf(stderr, "%s: invalid argument -%c\n",
  360                     program, isc_commandline_option);
  361             }
  362         /* FALLTHROUGH */
  363         case 'h':
  364             /* Does not return. */
  365             usage();
  366         case 'I':
  367             if (setinact || unsetinact) {
  368                 fatal("-I specified more than once");
  369             }
  370 
  371             changed = true;
  372             inact = strtotime(isc_commandline_argument, now, now,
  373                       &setinact);
  374             unsetinact = !setinact;
  375             break;
  376         case 'i':
  377             prepub = strtottl(isc_commandline_argument);
  378             break;
  379         case 'K':
  380             /*
  381              * We don't have to copy it here, but do it to
  382              * simplify cleanup later
  383              */
  384             directory = isc_mem_strdup(mctx,
  385                            isc_commandline_argument);
  386             break;
  387         case 'k':
  388             if (setdnskey) {
  389                 fatal("-k specified more than once");
  390             }
  391 
  392             dnskey = strtokeystate(isc_commandline_argument);
  393             setdnskey = true;
  394             /* time */
  395             (void)isoptarg(isc_commandline_argument, argv, usage);
  396             dnskeytime = strtotime(isc_commandline_argument, now,
  397                            now, &setdnskeytime);
  398             break;
  399         case 'L':
  400             ttl = strtottl(isc_commandline_argument);
  401             setttl = true;
  402             break;
  403         case 'P':
  404             /* -Psync ? */
  405             if (isoptarg("sync", argv, usage)) {
  406                 if (unsetsyncadd || setsyncadd) {
  407                     fatal("-P sync specified more than "
  408                           "once");
  409                 }
  410 
  411                 changed = true;
  412                 syncadd = strtotime(isc_commandline_argument,
  413                             now, now, &setsyncadd);
  414                 unsetsyncadd = !setsyncadd;
  415                 break;
  416             }
  417             /* -Pds ? */
  418             if (isoptarg("ds", argv, usage)) {
  419                 if (unsetdsadd || setdsadd) {
  420                     fatal("-P ds specified more than once");
  421                 }
  422 
  423                 changed = true;
  424                 dsadd = strtotime(isc_commandline_argument, now,
  425                           now, &setdsadd);
  426                 unsetdsadd = !setdsadd;
  427                 break;
  428             }
  429             /* -Pdnskey ? */
  430             (void)isoptarg("dnskey", argv, usage);
  431             if (setpub || unsetpub) {
  432                 fatal("-P specified more than once");
  433             }
  434 
  435             changed = true;
  436             pub = strtotime(isc_commandline_argument, now, now,
  437                     &setpub);
  438             unsetpub = !setpub;
  439             break;
  440         case 'p':
  441             p = isc_commandline_argument;
  442             if (!strcasecmp(p, "all")) {
  443                 printcreate = true;
  444                 printpub = true;
  445                 printact = true;
  446                 printrev = true;
  447                 printinact = true;
  448                 printdel = true;
  449                 printsyncadd = true;
  450                 printsyncdel = true;
  451                 printdsadd = true;
  452                 printdsdel = true;
  453                 break;
  454             }
  455 
  456             do {
  457                 switch (*p++) {
  458                 case 'A':
  459                     printact = true;
  460                     break;
  461                 case 'C':
  462                     printcreate = true;
  463                     break;
  464                 case 'D':
  465                     if (!strncmp(p, "sync", 4)) {
  466                         p += 4;
  467                         printsyncdel = true;
  468                         break;
  469                     }
  470                     if (!strncmp(p, "ds", 2)) {
  471                         p += 2;
  472                         printdsdel = true;
  473                         break;
  474                     }
  475                     printdel = true;
  476                     break;
  477                 case 'I':
  478                     printinact = true;
  479                     break;
  480                 case 'P':
  481                     if (!strncmp(p, "sync", 4)) {
  482                         p += 4;
  483                         printsyncadd = true;
  484                         break;
  485                     }
  486                     if (!strncmp(p, "ds", 2)) {
  487                         p += 2;
  488                         printdsadd = true;
  489                         break;
  490                     }
  491                     printpub = true;
  492                     break;
  493                 case 'R':
  494                     printrev = true;
  495                     break;
  496                 case ' ':
  497                     break;
  498                 default:
  499                     usage();
  500                     break;
  501                 }
  502             } while (*p != '\0');
  503             break;
  504         case 'R':
  505             if (setrev || unsetrev) {
  506                 fatal("-R specified more than once");
  507             }
  508 
  509             changed = true;
  510             rev = strtotime(isc_commandline_argument, now, now,
  511                     &setrev);
  512             unsetrev = !setrev;
  513             break;
  514         case 'r':
  515             if (setkrrsig) {
  516                 fatal("-r specified more than once");
  517             }
  518 
  519             krrsig = strtokeystate(isc_commandline_argument);
  520             setkrrsig = true;
  521             /* time */
  522             (void)isoptarg(isc_commandline_argument, argv, usage);
  523             krrsigtime = strtotime(isc_commandline_argument, now,
  524                            now, &setkrrsigtime);
  525             break;
  526         case 'S':
  527             predecessor = isc_commandline_argument;
  528             break;
  529         case 's':
  530             write_state = true;
  531             break;
  532         case 'u':
  533             epoch = true;
  534             break;
  535         case 'V':
  536             /* Does not return. */
  537             version(program);
  538         case 'v':
  539             verbose = strtol(isc_commandline_argument, &endp, 0);
  540             if (*endp != '\0') {
  541                 fatal("-v must be followed by a number");
  542             }
  543             break;
  544         case 'z':
  545             if (setzrrsig) {
  546                 fatal("-z specified more than once");
  547             }
  548 
  549             zrrsig = strtokeystate(isc_commandline_argument);
  550             setzrrsig = true;
  551             (void)isoptarg(isc_commandline_argument, argv, usage);
  552             zrrsigtime = strtotime(isc_commandline_argument, now,
  553                            now, &setzrrsigtime);
  554             break;
  555 
  556         default:
  557             fprintf(stderr, "%s: unhandled option -%c\n", program,
  558                 isc_commandline_option);
  559             exit(1);
  560         }
  561     }
  562 
  563     if (argc < isc_commandline_index + 1 ||
  564         argv[isc_commandline_index] == NULL) {
  565         fatal("The key file name was not specified");
  566     }
  567     if (argc > isc_commandline_index + 1) {
  568         fatal("Extraneous arguments");
  569     }
  570 
  571     if ((setgoal || setds || setdnskey || setkrrsig || setzrrsig) &&
  572         !write_state) {
  573         fatal("Options -g, -d, -k, -r and -z require -s to be set");
  574     }
  575 
  576     result = dst_lib_init(mctx, engine);
  577     if (result != ISC_R_SUCCESS) {
  578         fatal("Could not initialize dst: %s",
  579               isc_result_totext(result));
  580     }
  581 
  582     if (predecessor != NULL) {
  583         int major, minor;
  584 
  585         if (prepub == -1) {
  586             prepub = (30 * 86400);
  587         }
  588 
  589         if (setpub || unsetpub) {
  590             fatal("-S and -P cannot be used together");
  591         }
  592         if (setact || unsetact) {
  593             fatal("-S and -A cannot be used together");
  594         }
  595 
  596         result = dst_key_fromnamedfile(predecessor, directory, options,
  597                            mctx, &prevkey);
  598         if (result != ISC_R_SUCCESS) {
  599             fatal("Invalid keyfile %s: %s", filename,
  600                   isc_result_totext(result));
  601         }
  602         if (!dst_key_isprivate(prevkey) && !dst_key_isexternal(prevkey))
  603         {
  604             fatal("%s is not a private key", filename);
  605         }
  606 
  607         name = dst_key_name(prevkey);
  608         alg = dst_key_alg(prevkey);
  609         size = dst_key_size(prevkey);
  610         flags = dst_key_flags(prevkey);
  611 
  612         dst_key_format(prevkey, keystr, sizeof(keystr));
  613         dst_key_getprivateformat(prevkey, &major, &minor);
  614         if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
  615             fatal("Predecessor has incompatible format "
  616                   "version %d.%d\n\t",
  617                   major, minor);
  618         }
  619 
  620         result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &prevact);
  621         if (result != ISC_R_SUCCESS) {
  622             fatal("Predecessor has no activation date. "
  623                   "You must set one before\n\t"
  624                   "generating a successor.");
  625         }
  626 
  627         result = dst_key_gettime(prevkey, DST_TIME_INACTIVE,
  628                      &previnact);
  629         if (result != ISC_R_SUCCESS) {
  630             fatal("Predecessor has no inactivation date. "
  631                   "You must set one before\n\t"
  632                   "generating a successor.");
  633         }
  634 
  635         pub = previnact - prepub;
  636         act = previnact;
  637 
  638         if ((previnact - prepub) < now && prepub != 0) {
  639             fatal("Time until predecessor inactivation is\n\t"
  640                   "shorter than the prepublication interval.  "
  641                   "Either change\n\t"
  642                   "predecessor inactivation date, or use the -i "
  643                   "option to set\n\t"
  644                   "a shorter prepublication interval.");
  645         }
  646 
  647         result = dst_key_gettime(prevkey, DST_TIME_DELETE, &prevdel);
  648         if (result != ISC_R_SUCCESS) {
  649             fprintf(stderr,
  650                 "%s: warning: Predecessor has no "
  651                 "removal date;\n\t"
  652                 "it will remain in the zone "
  653                 "indefinitely after rollover.\n",
  654                 program);
  655         } else if (prevdel < previnact) {
  656             fprintf(stderr,
  657                 "%s: warning: Predecessor is "
  658                 "scheduled to be deleted\n\t"
  659                 "before it is scheduled to be "
  660                 "inactive.\n",
  661                 program);
  662         }
  663 
  664         changed = setpub = setact = true;
  665     } else {
  666         if (prepub < 0) {
  667             prepub = 0;
  668         }
  669 
  670         if (prepub > 0) {
  671             if (setpub && setact && (act - prepub) < pub) {
  672                 fatal("Activation and publication dates "
  673                       "are closer together than the\n\t"
  674                       "prepublication interval.");
  675             }
  676 
  677             if (setpub && !setact) {
  678                 setact = true;
  679                 act = pub + prepub;
  680             } else if (setact && !setpub) {
  681                 setpub = true;
  682                 pub = act - prepub;
  683             }
  684 
  685             if ((act - prepub) < now) {
  686                 fatal("Time until activation is shorter "
  687                       "than the\n\tprepublication interval.");
  688             }
  689         }
  690     }
  691 
  692     if (directory != NULL) {
  693         filename = argv[isc_commandline_index];
  694     } else {
  695         result = isc_file_splitpath(mctx, argv[isc_commandline_index],
  696                         &directory, &filename);
  697         if (result != ISC_R_SUCCESS) {
  698             fatal("cannot process filename %s: %s",
  699                   argv[isc_commandline_index],
  700                   isc_result_totext(result));
  701         }
  702     }
  703 
  704     result = dst_key_fromnamedfile(filename, directory, options, mctx,
  705                        &key);
  706     if (result != ISC_R_SUCCESS) {
  707         fatal("Invalid keyfile %s: %s", filename,
  708               isc_result_totext(result));
  709     }
  710 
  711     if (!dst_key_isprivate(key) && !dst_key_isexternal(key)) {
  712         fatal("%s is not a private key", filename);
  713     }
  714 
  715     dst_key_format(key, keystr, sizeof(keystr));
  716 
  717     if (predecessor != NULL) {
  718         if (!dns_name_equal(name, dst_key_name(key))) {
  719             fatal("Key name mismatch");
  720         }
  721         if (alg != dst_key_alg(key)) {
  722             fatal("Key algorithm mismatch");
  723         }
  724         if (size != dst_key_size(key)) {
  725             fatal("Key size mismatch");
  726         }
  727         if (flags != dst_key_flags(key)) {
  728             fatal("Key flags mismatch");
  729         }
  730     }
  731 
  732     prevdel = previnact = 0;
  733     if ((setdel && setinact && del < inact) ||
  734         (dst_key_gettime(key, DST_TIME_INACTIVE, &previnact) ==
  735              ISC_R_SUCCESS &&
  736          setdel && !setinact && !unsetinact && del < previnact) ||
  737         (dst_key_gettime(key, DST_TIME_DELETE, &prevdel) == ISC_R_SUCCESS &&
  738          setinact && !setdel && !unsetdel && prevdel < inact) ||
  739         (!setdel && !unsetdel && !setinact && !unsetinact && prevdel != 0 &&
  740          prevdel < previnact))
  741     {
  742         fprintf(stderr,
  743             "%s: warning: Key is scheduled to "
  744             "be deleted before it is\n\t"
  745             "scheduled to be inactive.\n",
  746             program);
  747     }
  748 
  749     if (force) {
  750         set_keyversion(key);
  751     } else {
  752         check_keyversion(key, keystr);
  753     }
  754 
  755     if (verbose > 2) {
  756         fprintf(stderr, "%s: %s\n", program, keystr);
  757     }
  758 
  759     /*
  760      * Set time values.
  761      */
  762     if (setpub) {
  763         dst_key_settime(key, DST_TIME_PUBLISH, pub);
  764     } else if (unsetpub) {
  765         dst_key_unsettime(key, DST_TIME_PUBLISH);
  766     }
  767 
  768     if (setact) {
  769         dst_key_settime(key, DST_TIME_ACTIVATE, act);
  770     } else if (unsetact) {
  771         dst_key_unsettime(key, DST_TIME_ACTIVATE);
  772     }
  773 
  774     if (setrev) {
  775         if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) {
  776             fprintf(stderr,
  777                 "%s: warning: Key %s is already "
  778                 "revoked; changing the revocation date "
  779                 "will not affect this.\n",
  780                 program, keystr);
  781         }
  782         if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) {
  783             fprintf(stderr,
  784                 "%s: warning: Key %s is not flagged as "
  785                 "a KSK, but -R was used.  Revoking a "
  786                 "ZSK is legal, but undefined.\n",
  787                 program, keystr);
  788         }
  789         dst_key_settime(key, DST_TIME_REVOKE, rev);
  790     } else if (unsetrev) {
  791         if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) {
  792             fprintf(stderr,
  793                 "%s: warning: Key %s is already "
  794                 "revoked; removing the revocation date "
  795                 "will not affect this.\n",
  796                 program, keystr);
  797         }
  798         dst_key_unsettime(key, DST_TIME_REVOKE);
  799     }
  800 
  801     if (setinact) {
  802         dst_key_settime(key, DST_TIME_INACTIVE, inact);
  803     } else if (unsetinact) {
  804         dst_key_unsettime(key, DST_TIME_INACTIVE);
  805     }
  806 
  807     if (setdel) {
  808         dst_key_settime(key, DST_TIME_DELETE, del);
  809     } else if (unsetdel) {
  810         dst_key_unsettime(key, DST_TIME_DELETE);
  811     }
  812 
  813     if (setsyncadd) {
  814         dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd);
  815     } else if (unsetsyncadd) {
  816         dst_key_unsettime(key, DST_TIME_SYNCPUBLISH);
  817     }
  818 
  819     if (setsyncdel) {
  820         dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel);
  821     } else if (unsetsyncdel) {
  822         dst_key_unsettime(key, DST_TIME_SYNCDELETE);
  823     }
  824 
  825     if (setdsadd) {
  826         dst_key_settime(key, DST_TIME_DSPUBLISH, dsadd);
  827     } else if (unsetdsadd) {
  828         dst_key_unsettime(key, DST_TIME_DSPUBLISH);
  829     }
  830 
  831     if (setdsdel) {
  832         dst_key_settime(key, DST_TIME_DSDELETE, dsdel);
  833     } else if (unsetdsdel) {
  834         dst_key_unsettime(key, DST_TIME_DSDELETE);
  835     }
  836 
  837     if (setttl) {
  838         dst_key_setttl(key, ttl);
  839     }
  840 
  841     if (predecessor != NULL && prevkey != NULL) {
  842         dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key));
  843         dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey));
  844     }
  845 
  846     /*
  847      * No metadata changes were made but we're forcing an upgrade
  848      * to the new format anyway: use "-P now -A now" as the default
  849      */
  850     if (force && !changed) {
  851         dst_key_settime(key, DST_TIME_PUBLISH, now);
  852         dst_key_settime(key, DST_TIME_ACTIVATE, now);
  853         changed = true;
  854     }
  855 
  856     /*
  857      * Make sure the key state goals are written.
  858      */
  859     if (write_state) {
  860         if (setgoal) {
  861             if (goal == DST_KEY_STATE_NA) {
  862                 dst_key_unsetstate(key, DST_KEY_GOAL);
  863             } else {
  864                 dst_key_setstate(key, DST_KEY_GOAL, goal);
  865             }
  866             changed = true;
  867         }
  868         if (setds) {
  869             if (ds == DST_KEY_STATE_NA) {
  870                 dst_key_unsetstate(key, DST_KEY_DS);
  871                 dst_key_unsettime(key, DST_TIME_DS);
  872             } else {
  873                 dst_key_setstate(key, DST_KEY_DS, ds);
  874                 dst_key_settime(key, DST_TIME_DS, dstime);
  875             }
  876             changed = true;
  877         }
  878         if (setdnskey) {
  879             if (dnskey == DST_KEY_STATE_NA) {
  880                 dst_key_unsetstate(key, DST_KEY_DNSKEY);
  881                 dst_key_unsettime(key, DST_TIME_DNSKEY);
  882             } else {
  883                 dst_key_setstate(key, DST_KEY_DNSKEY, dnskey);
  884                 dst_key_settime(key, DST_TIME_DNSKEY,
  885                         dnskeytime);
  886             }
  887             changed = true;
  888         }
  889         if (setkrrsig) {
  890             if (krrsig == DST_KEY_STATE_NA) {
  891                 dst_key_unsetstate(key, DST_KEY_KRRSIG);
  892                 dst_key_unsettime(key, DST_TIME_KRRSIG);
  893             } else {
  894                 dst_key_setstate(key, DST_KEY_KRRSIG, krrsig);
  895                 dst_key_settime(key, DST_TIME_KRRSIG,
  896                         krrsigtime);
  897             }
  898             changed = true;
  899         }
  900         if (setzrrsig) {
  901             if (zrrsig == DST_KEY_STATE_NA) {
  902                 dst_key_unsetstate(key, DST_KEY_ZRRSIG);
  903                 dst_key_unsettime(key, DST_TIME_ZRRSIG);
  904             } else {
  905                 dst_key_setstate(key, DST_KEY_ZRRSIG, zrrsig);
  906                 dst_key_settime(key, DST_TIME_ZRRSIG,
  907                         zrrsigtime);
  908             }
  909             changed = true;
  910         }
  911     }
  912 
  913     if (!changed && setttl) {
  914         changed = true;
  915     }
  916 
  917     /*
  918      * Print out time values, if -p was used.
  919      */
  920     if (printcreate) {
  921         printtime(key, DST_TIME_CREATED, "Created", epoch, stdout);
  922     }
  923 
  924     if (printpub) {
  925         printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout);
  926     }
  927 
  928     if (printact) {
  929         printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout);
  930     }
  931 
  932     if (printrev) {
  933         printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout);
  934     }
  935 
  936     if (printinact) {
  937         printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout);
  938     }
  939 
  940     if (printdel) {
  941         printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout);
  942     }
  943 
  944     if (printsyncadd) {
  945         printtime(key, DST_TIME_SYNCPUBLISH, "SYNC Publish", epoch,
  946               stdout);
  947     }
  948 
  949     if (printsyncdel) {
  950         printtime(key, DST_TIME_SYNCDELETE, "SYNC Delete", epoch,
  951               stdout);
  952     }
  953 
  954     if (printdsadd) {
  955         printtime(key, DST_TIME_DSPUBLISH, "DS Publish", epoch, stdout);
  956     }
  957 
  958     if (printdsdel) {
  959         printtime(key, DST_TIME_DSDELETE, "DS Delete", epoch, stdout);
  960     }
  961 
  962     if (changed) {
  963         writekey(key, directory, write_state);
  964         if (predecessor != NULL && prevkey != NULL) {
  965             writekey(prevkey, directory, write_state);
  966         }
  967     }
  968 
  969     if (prevkey != NULL) {
  970         dst_key_free(&prevkey);
  971     }
  972     dst_key_free(&key);
  973     dst_lib_destroy();
  974     if (verbose > 10) {
  975         isc_mem_stats(mctx, stdout);
  976     }
  977     cleanup_logging(&log);
  978     isc_mem_free(mctx, directory);
  979     isc_mem_destroy(&mctx);
  980 
  981     return (0);
  982 }