20 #include <openssl/conf.h>
21 #include <openssl/engine.h>
24 #define MAX_FILENAME_LEN 250
28 #include <openssl/err.h>
31 usage(FILE *fp,
const char *prog) {
32 fprintf(fp,
"%s [OPTIONS] zonefile key [key [key]]\n", prog);
33 fprintf(fp,
" signs the zone with the given key(s)\n");
34 fprintf(fp,
" -b\t\tuse layout in signed zone and print comments DNSSEC records\n");
35 fprintf(fp,
" -d\t\tused keys are not added to the zone\n");
36 fprintf(fp,
" -e <date>\texpiration date\n");
37 fprintf(fp,
" -f <file>\toutput zone to file (default <name>.signed)\n");
38 fprintf(fp,
" -i <date>\tinception date\n");
39 fprintf(fp,
" -o <domain>\torigin for the zone\n");
40 fprintf(fp,
" -v\t\tprint version and exit\n");
41 fprintf(fp,
" -A\t\tsign DNSKEY with all keys instead of minimal\n");
42 fprintf(fp,
" -E <name>\tuse <name> as the crypto engine for signing\n");
43 fprintf(fp,
" \tThis can have a lot of extra options, see the manual page for more info\n");
44 fprintf(fp,
" -k <id>,<int>\tuse key id with algorithm int from engine\n");
45 fprintf(fp,
" -K <id>,<int>\tuse key id with algorithm int from engine as KSK\n");
46 fprintf(fp,
"\t\tif no key is given (but an external one is used through the engine support, it might be necessary to provide the right algorithm number.\n");
47 fprintf(fp,
" -n\t\tuse NSEC3 instead of NSEC.\n");
48 fprintf(fp,
"\t\tIf you use NSEC3, you can specify the following extra options:\n");
49 fprintf(fp,
"\t\t-a [algorithm] hashing algorithm\n");
50 fprintf(fp,
"\t\t-t [number] number of hash iterations\n");
51 fprintf(fp,
"\t\t-s [string] salt\n");
52 fprintf(fp,
"\t\t-p set the opt-out flag on all nsec3 rrs\n");
54 fprintf(fp,
" keys must be specified by their base name (usually K<name>+<alg>+<id>),\n");
55 fprintf(fp,
" i.e. WITHOUT the .private extension.\n");
56 fprintf(fp,
" If the public part of the key is not present in the zone, the DNSKEY RR\n");
57 fprintf(fp,
" will be read from the file called <base name>.key. If that does not exist,\n");
58 fprintf(fp,
" a default DNSKEY will be generated from the private key and added to the zone.\n");
59 fprintf(fp,
" A date can be a timestamp (seconds since the epoch), or of\n the form <YYYYMMdd[hhmmss]>\n");
62 static void check_tm(
struct tm tm)
64 if (tm.tm_year < 70) {
65 fprintf(stderr,
"You cannot specify dates before 1970\n");
68 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
69 fprintf(stderr,
"The month must be in the range 1 to 12\n");
72 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
73 fprintf(stderr,
"The day must be in the range 1 to 31\n");
77 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
78 fprintf(stderr,
"The hour must be in the range 0-23\n");
82 if (tm.tm_min < 0 || tm.tm_min > 59) {
83 fprintf(stderr,
"The minute must be in the range 0-59\n");
87 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
88 fprintf(stderr,
"The second must be in the range 0-59\n");
110 if (ttl1 == default_ttl) {
112 }
else if (ttl2 == default_ttl) {
117 "warning: changing non-default TTL %u to %u\n",
118 (
unsigned int) ttl2, (
unsigned int) ttl1);
132 equalize_ttls(cur_rr, rr, default_ttl);
156 fprintf(stderr,
"Found it in the zone!\n");
171 uint32_t default_ttl = zone_ttl;
175 strlen(keyfile_name_base) + 5);
176 snprintf(keyfile_name,
177 strlen(keyfile_name_base) + 5,
181 fprintf(stderr,
"Trying to read %s\n", keyfile_name);
183 keyfile = fopen(keyfile_name,
"r");
194 printf(
"Key found in file: %s\n", keyfile_name);
213 find_or_create_pubkey(
const char *keyfile_name_base,
ldns_key *key,
ldns_zone *orig_zone,
bool add_keys, uint32_t default_ttl) {
243 "Looking for key with keytag %u or %u\n",
249 pubkey = find_key_in_zone(pubkey_gen, orig_zone);
254 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
258 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
265 fprintf(stderr,
"Error %s.key has wrong name: %s\n",
276 fprintf(stderr,
"Not in zone, no .key file, generating ZSK DNSKEY from private key data\n");
284 if (add_keys && !key_in_zone) {
285 equalize_ttls_rr_list(
ldns_zone_rrs(orig_zone), pubkey, default_ttl);
316 const char *zonefile_name;
317 FILE *zonefile = NULL;
321 ENGINE *engine = NULL;
328 char *keyfile_name_base;
329 char *keyfile_name = NULL;
330 FILE *keyfile = NULL;
337 char *outputfile_name = NULL;
342 size_t eng_key_id_len;
346 bool use_nsec3 =
false;
350 bool add_keys =
true;
351 uint8_t nsec3_algorithm = 1;
352 uint8_t nsec3_flags = 0;
353 size_t nsec3_iterations_cmd = 1;
354 uint16_t nsec3_iterations = 1;
355 uint8_t nsec3_salt_length = 0;
356 uint8_t *nsec3_salt = NULL;
368 char *prog = strdup(argv[0]);
372 void **hashmap = NULL;
380 OPENSSL_config(NULL);
382 while ((c = getopt(argc, argv,
"a:bde:f:i:k:lno:ps:t:vAE:K:")) != -1) {
385 nsec3_algorithm = (uint8_t) atoi(optarg);
386 if (nsec3_algorithm != 1) {
387 fprintf(stderr,
"Bad NSEC3 algorithm, only RSASHA1 allowed\n");
406 memset(&tm, 0,
sizeof(tm));
408 if (strlen(optarg) == 8 &&
409 sscanf(optarg,
"%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
416 }
else if (strlen(optarg) == 14 &&
417 sscanf(optarg,
"%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
425 expiration = (uint32_t) atol(optarg);
433 memset(&tm, 0,
sizeof(tm));
435 if (strlen(optarg) == 8 &&
436 sscanf(optarg,
"%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
443 }
else if (strlen(optarg) == 14 &&
444 sscanf(optarg,
"%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
452 inception = (uint32_t) atol(optarg);
460 fprintf(stderr,
"Bad origin, not a correct domain name\n");
476 ENGINE_load_builtin_engines();
477 ENGINE_load_dynamic();
478 ENGINE_load_cryptodev();
479 engine = ENGINE_by_id(optarg);
481 printf(
"No such engine: %s\n", optarg);
482 engine = ENGINE_get_first();
483 printf(
"Available engines:\n");
485 printf(
"%s\n", ENGINE_get_id(engine));
486 engine = ENGINE_get_next(engine);
490 if (!ENGINE_init(engine)) {
491 printf(
"The engine couldn't initialize\n");
494 ENGINE_set_default_RSA(engine);
495 ENGINE_set_default_DSA(engine);
496 ENGINE_set_default(engine, 0);
500 eng_key_l = strchr(optarg,
',');
501 if (eng_key_l && strlen(eng_key_l) > 1) {
502 if (eng_key_l > optarg) {
503 eng_key_id_len = (size_t) (eng_key_l - optarg);
504 eng_key_id = malloc(eng_key_id_len + 1);
505 memcpy(eng_key_id, optarg, eng_key_id_len);
506 eng_key_id[eng_key_id_len] =
'\0';
512 eng_key_algo = atoi(eng_key_l + 1);
514 printf(
"Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo);
537 fprintf(stderr,
"Warning, key not suitable for signing, ignoring key with algorithm %u\n",
ldns_key_algorithm(key));
540 if (expiration != 0) {
544 if (inception != 0) {
551 if (ERR_peek_error()) {
552 ERR_load_crypto_strings();
553 ERR_print_errors_fp(stderr);
564 printf(
"Error: bad engine key specification (should be: -k <id>,<algorithm>)).\n");
569 printf(
"Not implemented yet\n");
573 if (strlen(optarg) % 2 != 0) {
574 fprintf(stderr,
"Salt value is not valid hex data, not a multiple of 2 characters\n");
577 nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
579 for (c = 0; c < (int) strlen(optarg); c += 2) {
580 if (isxdigit((
int) optarg[c]) && isxdigit((
int) optarg[c+1])) {
584 fprintf(stderr,
"Salt value is not valid hex data.\n");
591 nsec3_iterations_cmd = (size_t) atol(optarg);
596 nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
608 printf(
"Error: not enough arguments\n");
612 zonefile_name = argv[0];
617 if (strncmp(zonefile_name,
"-", 2) == 0) {
625 fprintf(stderr,
"Zone not read, error: %s at stdin line %d\n",
633 "Error reading zonefile: missing SOA record\n");
639 "Error reading zonefile: no resource records\n");
644 zonefile = fopen(zonefile_name,
"r");
648 "Error: unable to read %s (%s)\n",
660 fprintf(stderr,
"Zone not read, error: %s at %s line %d\n",
662 zonefile_name, line_nr);
668 "Error reading zonefile: missing SOA record\n");
674 "Error reading zonefile: no resource records\n");
684 while (argi < argc) {
685 keyfile_name_base = argv[argi];
686 keyfile_name =
LDNS_XMALLOC(
char, strlen(keyfile_name_base) + 9);
687 snprintf(keyfile_name,
688 strlen(keyfile_name_base) + 9,
691 keyfile = fopen(keyfile_name,
"r");
695 "Error: unable to read %s: %s\n",
705 if (expiration != 0) {
708 if (inception != 0) {
716 fprintf(stderr,
"Error reading key from %s at line %d: %s\n", argv[argi], line_nr,
ldns_get_errorstr_by_id(s));
721 find_or_create_pubkey(keyfile_name_base, key,
722 orig_zone, add_keys, ttl);
728 fprintf(stderr,
"Error: no keys to sign with. Aborting.\n\n");
737 "Error adding SOA to dnssec zone, skipping record\n");
748 "Error adding RR to dnssec zone");
749 fprintf(stderr,
", skipping record:\n");
780 fprintf(stderr,
"Error signing zone: %s\n",
784 if (!outputfile_name) {
790 if (strncmp(outputfile_name,
"-", 2) == 0) {
793 outputfile = fopen(outputfile_name,
"w");
795 fprintf(stderr,
"Unable to open %s for writing: %s\n",
796 outputfile_name, strerror(errno));
799 outputfile, &fmt, signed_zone);
804 fprintf(stderr,
"Error signing zone.\n");
807 if (ERR_peek_error()) {
808 ERR_load_crypto_strings();
809 ERR_print_errors_fp(stderr);
828 CRYPTO_cleanup_all_ex_data();
835 main(
int argc,
char **argv)
837 fprintf(stderr,
"ldns-signzone needs OpenSSL support, which has not been compiled in\n");