ldns-signzone.c
Go to the documentation of this file.
1 /*
2  * ldns-signzone signs a zone file
3  *
4  * (c) NLnet Labs, 2005 - 2008
5  * See the file LICENSE for the license
6  */
7 
8 #include "config.h"
9 #include <stdlib.h>
10 #include <unistd.h>
11 
12 #include <errno.h>
13 
14 #include <time.h>
15 
16 #include <ldns/ldns.h>
17 #include <ldns/keys.h>
18 
19 #ifdef HAVE_SSL
20 #include <openssl/conf.h>
21 #include <openssl/engine.h>
22 #endif /* HAVE_SSL */
23 
24 #define MAX_FILENAME_LEN 250
25 int verbosity = 1;
26 
27 #ifdef HAVE_SSL
28 #include <openssl/err.h>
29 
30 static void
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");
53  fprintf(fp, "\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");
60 }
61 
62 static void check_tm(struct tm tm)
63 {
64  if (tm.tm_year < 70) {
65  fprintf(stderr, "You cannot specify dates before 1970\n");
66  exit(EXIT_FAILURE);
67  }
68  if (tm.tm_mon < 0 || tm.tm_mon > 11) {
69  fprintf(stderr, "The month must be in the range 1 to 12\n");
70  exit(EXIT_FAILURE);
71  }
72  if (tm.tm_mday < 1 || tm.tm_mday > 31) {
73  fprintf(stderr, "The day must be in the range 1 to 31\n");
74  exit(EXIT_FAILURE);
75  }
76 
77  if (tm.tm_hour < 0 || tm.tm_hour > 23) {
78  fprintf(stderr, "The hour must be in the range 0-23\n");
79  exit(EXIT_FAILURE);
80  }
81 
82  if (tm.tm_min < 0 || tm.tm_min > 59) {
83  fprintf(stderr, "The minute must be in the range 0-59\n");
84  exit(EXIT_FAILURE);
85  }
86 
87  if (tm.tm_sec < 0 || tm.tm_sec > 59) {
88  fprintf(stderr, "The second must be in the range 0-59\n");
89  exit(EXIT_FAILURE);
90  }
91 
92 }
93 
94 /*
95  * if the ttls are different, make them equal
96  * if one of the ttls equals LDNS_DEFAULT_TTL, that one is changed
97  * otherwise, rr2 will get the ttl of rr1
98  *
99  * prints a warning if a non-default TTL is changed
100  */
101 static void
102 equalize_ttls(ldns_rr *rr1, ldns_rr *rr2, uint32_t default_ttl)
103 {
104  uint32_t ttl1, ttl2;
105 
106  ttl1 = ldns_rr_ttl(rr1);
107  ttl2 = ldns_rr_ttl(rr2);
108 
109  if (ttl1 != ttl2) {
110  if (ttl1 == default_ttl) {
111  ldns_rr_set_ttl(rr1, ttl2);
112  } else if (ttl2 == default_ttl) {
113  ldns_rr_set_ttl(rr2, ttl1);
114  } else {
115  ldns_rr_set_ttl(rr2, ttl1);
116  fprintf(stderr,
117  "warning: changing non-default TTL %u to %u\n",
118  (unsigned int) ttl2, (unsigned int) ttl1);
119  }
120  }
121 }
122 
123 static void
124 equalize_ttls_rr_list(ldns_rr_list *rr_list, ldns_rr *rr, uint32_t default_ttl)
125 {
126  size_t i;
127  ldns_rr *cur_rr;
128 
129  for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
130  cur_rr = ldns_rr_list_rr(rr_list, i);
131  if (ldns_rr_compare_no_rdata(cur_rr, rr) == 0) {
132  equalize_ttls(cur_rr, rr, default_ttl);
133  }
134  }
135 }
136 
137 static ldns_rr *
138 find_key_in_zone(ldns_rr *pubkey_gen, ldns_zone *zone) {
139  size_t key_i;
140  ldns_rr *pubkey;
141 
142  for (key_i = 0;
143  key_i < ldns_rr_list_rr_count(ldns_zone_rrs(zone));
144  key_i++) {
145  pubkey = ldns_rr_list_rr(ldns_zone_rrs(zone), key_i);
146  if (ldns_rr_get_type(pubkey) == LDNS_RR_TYPE_DNSKEY &&
147  (ldns_calc_keytag(pubkey)
148  ==
149  ldns_calc_keytag(pubkey_gen) ||
150  /* KSK has gen-keytag + 1 */
151  ldns_calc_keytag(pubkey)
152  ==
153  ldns_calc_keytag(pubkey_gen) + 1)
154  ) {
155  if (verbosity >= 2) {
156  fprintf(stderr, "Found it in the zone!\n");
157  }
158  return pubkey;
159  }
160  }
161  return NULL;
162 }
163 
164 static ldns_rr *
165 find_key_in_file(const char *keyfile_name_base, ldns_key* ATTR_UNUSED(key),
166  uint32_t zone_ttl)
167 {
168  char *keyfile_name;
169  FILE *keyfile;
170  int line_nr;
171  uint32_t default_ttl = zone_ttl;
172 
173  ldns_rr *pubkey = NULL;
174  keyfile_name = LDNS_XMALLOC(char,
175  strlen(keyfile_name_base) + 5);
176  snprintf(keyfile_name,
177  strlen(keyfile_name_base) + 5,
178  "%s.key",
179  keyfile_name_base);
180  if (verbosity >= 2) {
181  fprintf(stderr, "Trying to read %s\n", keyfile_name);
182  }
183  keyfile = fopen(keyfile_name, "r");
184  line_nr = 0;
185  if (keyfile) {
186  if (ldns_rr_new_frm_fp_l(&pubkey,
187  keyfile,
188  &default_ttl,
189  NULL,
190  NULL,
191  &line_nr) ==
192  LDNS_STATUS_OK) {
193  if (verbosity >= 2) {
194  printf("Key found in file: %s\n", keyfile_name);
195  }
196  }
197  fclose(keyfile);
198  }
199  LDNS_FREE(keyfile_name);
200  return pubkey;
201 }
202 
203 /* this function tries to find the specified keys either in the zone that
204  * has been read, or in a <basename>.key file. If the key is not found,
205  * a public key is generated, and it is assumed the key is a ZSK
206  *
207  * if add_keys is true; the DNSKEYs are added to the zone prior to signing
208  * if it is false, they are not added.
209  * Even if keys are not added, the function is still needed, to check
210  * whether keys of which we only have key data are KSKs or ZSKS
211  */
212 static void
213 find_or_create_pubkey(const char *keyfile_name_base, ldns_key *key, ldns_zone *orig_zone, bool add_keys, uint32_t default_ttl) {
214  ldns_rr *pubkey_gen, *pubkey;
215  int key_in_zone;
216 
217  if (default_ttl == LDNS_DEFAULT_TTL) {
218  default_ttl = ldns_rr_ttl(ldns_zone_soa(orig_zone));
219  }
220 
221  if (!ldns_key_pubkey_owner(key)) {
223  }
224 
225  /* find the public key in the zone, or in a
226  * seperate file
227  * we 'generate' one anyway,
228  * then match that to any present in the zone,
229  * if it matches, we drop our own. If not,
230  * we try to see if there is a .key file present.
231  * If not, we use our own generated one, with
232  * some default values
233  *
234  * Even if -d (do-not-add-keys) is specified,
235  * we still need to do this, because we need
236  * to have any key flags that are set this way
237  */
238  pubkey_gen = ldns_key2rr(key);
239  ldns_rr_set_ttl(pubkey_gen, default_ttl);
240 
241  if (verbosity >= 2) {
242  fprintf(stderr,
243  "Looking for key with keytag %u or %u\n",
244  (unsigned int) ldns_calc_keytag(pubkey_gen),
245  (unsigned int) ldns_calc_keytag(pubkey_gen)+1
246  );
247  }
248 
249  pubkey = find_key_in_zone(pubkey_gen, orig_zone);
250  key_in_zone = 1;
251  if (!pubkey) {
252  key_in_zone = 0;
253  /* it was not in the zone, try to read a .key file */
254  pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
255  if (!pubkey && !(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
256  /* maybe it is a ksk? */
257  ldns_key_set_keytag(key, ldns_key_keytag(key) + 1);
258  pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
259  if (!pubkey) {
260  /* ok, no file, set back to ZSK */
261  ldns_key_set_keytag(key, ldns_key_keytag(key) - 1);
262  }
263  }
264  if(pubkey && ldns_dname_compare(ldns_rr_owner(pubkey), ldns_rr_owner(ldns_zone_soa(orig_zone))) != 0) {
265  fprintf(stderr, "Error %s.key has wrong name: %s\n",
266  keyfile_name_base, ldns_rdf2str(ldns_rr_owner(pubkey)));
267  exit(EXIT_FAILURE); /* leak rdf2str, but we exit */
268  }
269  }
270 
271  if (!pubkey) {
272  /* okay, no public key found,
273  just use our generated one */
274  pubkey = pubkey_gen;
275  if (verbosity >= 2) {
276  fprintf(stderr, "Not in zone, no .key file, generating ZSK DNSKEY from private key data\n");
277  }
278  } else {
279  ldns_rr_free(pubkey_gen);
280  }
283 
284  if (add_keys && !key_in_zone) {
285  equalize_ttls_rr_list(ldns_zone_rrs(orig_zone), pubkey, default_ttl);
286  ldns_zone_push_rr(orig_zone, pubkey);
287  }
288 }
289 
290 void
292 {
293  ldns_rr_list *new_list;
294  ldns_rr *cur_rr;
295 
296  new_list = ldns_rr_list_new();
297 
298  while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(zone)))) {
299  if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG ||
300  ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC ||
302  ) {
303 
304  ldns_rr_free(cur_rr);
305  } else {
306  ldns_rr_list_push_rr(new_list, cur_rr);
307  }
308  }
310  ldns_zone_set_rrs(zone, new_list);
311 }
312 
313 int
314 main(int argc, char *argv[])
315 {
316  const char *zonefile_name;
317  FILE *zonefile = NULL;
318  int line_nr = 0;
319  int c;
320  int argi;
321  ENGINE *engine = NULL;
322 
323  ldns_zone *orig_zone;
324  ldns_rr_list *orig_rrs = NULL;
325  ldns_rr *orig_soa = NULL;
326  ldns_dnssec_zone *signed_zone;
327 
328  char *keyfile_name_base;
329  char *keyfile_name = NULL;
330  FILE *keyfile = NULL;
331  ldns_key *key = NULL;
332  ldns_key_list *keys;
333  ldns_status s;
334  size_t i;
335  ldns_rr_list *added_rrs;
336 
337  char *outputfile_name = NULL;
338  FILE *outputfile;
339 
340  /* tmp vars for engine keys */
341  char *eng_key_l;
342  size_t eng_key_id_len;
343  char *eng_key_id;
344  int eng_key_algo;
345 
346  bool use_nsec3 = false;
347  int signflags = 0;
348 
349  /* Add the given keys to the zone if they are not yet present */
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;
357 
358  /* we need to know the origin before reading ksk's,
359  * so keep an array of filenames until we know it
360  */
361  struct tm tm;
362  uint32_t inception;
363  uint32_t expiration;
364  ldns_rdf *origin = NULL;
365  uint32_t ttl = LDNS_DEFAULT_TTL;
367 
368  char *prog = strdup(argv[0]);
369  ldns_status result;
370 
372  void **hashmap = NULL;
373 
374 
375  inception = 0;
376  expiration = 0;
377 
378  keys = ldns_key_list_new();
379 
380  OPENSSL_config(NULL);
381 
382  while ((c = getopt(argc, argv, "a:bde:f:i:k:no:ps:t:vAE:K:")) != -1) {
383  switch (c) {
384  case 'a':
385  nsec3_algorithm = (uint8_t) atoi(optarg);
386  if (nsec3_algorithm != 1) {
387  fprintf(stderr, "Bad NSEC3 algorithm, only RSASHA1 allowed\n");
388  exit(EXIT_FAILURE);
389  }
390  break;
391  case 'b':
393  fmt.flags |= LDNS_COMMENT_FLAGS;
395  fmt.flags |= LDNS_COMMENT_LAYOUT;
396  hashmap = &fmt.data;
397  break;
398  case 'd':
399  add_keys = false;
400  break;
401  case 'e':
402  /* try to parse YYYYMMDD first,
403  * if that doesn't work, it
404  * should be a timestamp (seconds since epoch)
405  */
406  memset(&tm, 0, sizeof(tm));
407 
408  if (strlen(optarg) == 8 &&
409  sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
410  ) {
411  tm.tm_year -= 1900;
412  tm.tm_mon--;
413  check_tm(tm);
414  expiration =
415  (uint32_t) ldns_mktime_from_utc(&tm);
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)
418  ) {
419  tm.tm_year -= 1900;
420  tm.tm_mon--;
421  check_tm(tm);
422  expiration =
423  (uint32_t) ldns_mktime_from_utc(&tm);
424  } else {
425  expiration = (uint32_t) atol(optarg);
426  }
427  break;
428  case 'f':
429  outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
430  strncpy(outputfile_name, optarg, MAX_FILENAME_LEN);
431  break;
432  case 'i':
433  memset(&tm, 0, sizeof(tm));
434 
435  if (strlen(optarg) == 8 &&
436  sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
437  ) {
438  tm.tm_year -= 1900;
439  tm.tm_mon--;
440  check_tm(tm);
441  inception =
442  (uint32_t) ldns_mktime_from_utc(&tm);
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)
445  ) {
446  tm.tm_year -= 1900;
447  tm.tm_mon--;
448  check_tm(tm);
449  inception =
450  (uint32_t) ldns_mktime_from_utc(&tm);
451  } else {
452  inception = (uint32_t) atol(optarg);
453  }
454  break;
455  case 'n':
456  use_nsec3 = true;
457  break;
458  case 'o':
459  if (ldns_str2rdf_dname(&origin, optarg) != LDNS_STATUS_OK) {
460  fprintf(stderr, "Bad origin, not a correct domain name\n");
461  usage(stderr, prog);
462  exit(EXIT_FAILURE);
463  }
464  break;
465  case 'p':
466  nsec3_flags = nsec3_flags | LDNS_NSEC3_VARS_OPTOUT_MASK;
467  break;
468  case 'v':
469  printf("zone signer version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
470  exit(EXIT_SUCCESS);
471  break;
472  case 'A':
473  signflags |= LDNS_SIGN_DNSKEY_WITH_ZSK;
474  break;
475  case 'E':
476  ENGINE_load_builtin_engines();
477  ENGINE_load_dynamic();
478  ENGINE_load_cryptodev();
479  engine = ENGINE_by_id(optarg);
480  if (!engine) {
481  printf("No such engine: %s\n", optarg);
482  engine = ENGINE_get_first();
483  printf("Available engines:\n");
484  while (engine) {
485  printf("%s\n", ENGINE_get_id(engine));
486  engine = ENGINE_get_next(engine);
487  }
488  exit(EXIT_FAILURE);
489  } else {
490  if (!ENGINE_init(engine)) {
491  printf("The engine couldn't initialize\n");
492  exit(EXIT_FAILURE);
493  }
494  ENGINE_set_default_RSA(engine);
495  ENGINE_set_default_DSA(engine);
496  ENGINE_set_default(engine, 0);
497  }
498  break;
499  case 'k':
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';
507  } else {
508  /* no id given, use default from engine */
509  eng_key_id = NULL;
510  }
511 
512  eng_key_algo = atoi(eng_key_l + 1);
513 
514  printf("Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo);
515 
516  s = ldns_key_new_frm_engine(&key, engine, eng_key_id, eng_key_algo);
517  if (s == LDNS_STATUS_OK) {
518  /* must be dnssec key */
519  switch (ldns_key_algorithm(key)) {
520  case LDNS_SIGN_RSAMD5:
521  case LDNS_SIGN_RSASHA1:
523  case LDNS_SIGN_RSASHA256:
524  case LDNS_SIGN_RSASHA512:
525  case LDNS_SIGN_DSA:
526  case LDNS_SIGN_DSA_NSEC3:
527  case LDNS_SIGN_ECC_GOST:
528 #ifdef USE_ECDSA
531 #endif
532  ldns_key_list_push_key(keys, key);
533  /*printf("Added key at %p:\n", key);*/
534  /*ldns_key_print(stdout, key);*/
535  break;
536  default:
537  fprintf(stderr, "Warning, key not suitable for signing, ignoring key with algorithm %u\n", ldns_key_algorithm(key));
538  break;
539  }
540  if (expiration != 0) {
542  expiration);
543  }
544  if (inception != 0) {
546  inception);
547  }
548  } else {
549  printf("Error reading key '%s' from engine: %s\n", eng_key_id, ldns_get_errorstr_by_id(s));
550  #ifdef HAVE_SSL
551  if (ERR_peek_error()) {
552  ERR_load_crypto_strings();
553  ERR_print_errors_fp(stderr);
554  ERR_free_strings();
555  }
556  #endif
557  exit(EXIT_FAILURE);
558  }
559 
560  if (eng_key_id) {
561  free(eng_key_id);
562  }
563  } else {
564  printf("Error: bad engine key specification (should be: -k <id>,<algorithm>)).\n");
565  exit(EXIT_FAILURE);
566  }
567  break;
568  case 'K':
569  printf("Not implemented yet\n");
570  exit(EXIT_FAILURE);
571  break;
572  case 's':
573  if (strlen(optarg) % 2 != 0) {
574  fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
575  exit(EXIT_FAILURE);
576  }
577  nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
578  nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length);
579  for (c = 0; c < (int) strlen(optarg); c += 2) {
580  if (isxdigit((int) optarg[c]) && isxdigit((int) optarg[c+1])) {
581  nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
582  ldns_hexdigit_to_int(optarg[c+1]);
583  } else {
584  fprintf(stderr, "Salt value is not valid hex data.\n");
585  exit(EXIT_FAILURE);
586  }
587  }
588 
589  break;
590  case 't':
591  nsec3_iterations_cmd = (size_t) atol(optarg);
592  if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) {
593  fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
594  exit(EXIT_FAILURE);
595  }
596  nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
597  break;
598  default:
599  usage(stderr, prog);
600  exit(EXIT_SUCCESS);
601  }
602  }
603 
604  argc -= optind;
605  argv += optind;
606 
607  if (argc < 1) {
608  printf("Error: not enough arguments\n");
609  usage(stdout, prog);
610  exit(EXIT_FAILURE);
611  } else {
612  zonefile_name = argv[0];
613  }
614 
615  /* read zonefile first to find origin if not specified */
616 
617  if (strncmp(zonefile_name, "-", 2) == 0) {
618  s = ldns_zone_new_frm_fp_l(&orig_zone,
619  stdin,
620  origin,
621  ttl,
622  class,
623  &line_nr);
624  if (s != LDNS_STATUS_OK) {
625  fprintf(stderr, "Zone not read, error: %s at stdin line %d\n",
627  line_nr);
628  exit(EXIT_FAILURE);
629  } else {
630  orig_soa = ldns_zone_soa(orig_zone);
631  if (!orig_soa) {
632  fprintf(stderr,
633  "Error reading zonefile: missing SOA record\n");
634  exit(EXIT_FAILURE);
635  }
636  orig_rrs = ldns_zone_rrs(orig_zone);
637  if (!orig_rrs) {
638  fprintf(stderr,
639  "Error reading zonefile: no resource records\n");
640  exit(EXIT_FAILURE);
641  }
642  }
643  } else {
644  zonefile = fopen(zonefile_name, "r");
645 
646  if (!zonefile) {
647  fprintf(stderr,
648  "Error: unable to read %s (%s)\n",
649  zonefile_name,
650  strerror(errno));
651  exit(EXIT_FAILURE);
652  } else {
653  s = ldns_zone_new_frm_fp_l(&orig_zone,
654  zonefile,
655  origin,
656  ttl,
657  class,
658  &line_nr);
659  if (s != LDNS_STATUS_OK) {
660  fprintf(stderr, "Zone not read, error: %s at %s line %d\n",
662  zonefile_name, line_nr);
663  exit(EXIT_FAILURE);
664  } else {
665  orig_soa = ldns_zone_soa(orig_zone);
666  if (!orig_soa) {
667  fprintf(stderr,
668  "Error reading zonefile: missing SOA record\n");
669  exit(EXIT_FAILURE);
670  }
671  orig_rrs = ldns_zone_rrs(orig_zone);
672  if (!orig_rrs) {
673  fprintf(stderr,
674  "Error reading zonefile: no resource records\n");
675  exit(EXIT_FAILURE);
676  }
677  }
678  fclose(zonefile);
679  }
680  }
681 
682  /* read the ZSKs */
683  argi = 1;
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,
689  "%s.private",
690  keyfile_name_base);
691  keyfile = fopen(keyfile_name, "r");
692  line_nr = 0;
693  if (!keyfile) {
694  fprintf(stderr,
695  "Error: unable to read %s: %s\n",
696  keyfile_name,
697  strerror(errno));
698  } else {
699  s = ldns_key_new_frm_fp_l(&key, keyfile, &line_nr);
700  fclose(keyfile);
701  if (s == LDNS_STATUS_OK) {
702  /* set times in key? they will end up
703  in the rrsigs
704  */
705  if (expiration != 0) {
706  ldns_key_set_expiration(key, expiration);
707  }
708  if (inception != 0) {
709  ldns_key_set_inception(key, inception);
710  }
711 
712  LDNS_FREE(keyfile_name);
713 
714  ldns_key_list_push_key(keys, key);
715  } else {
716  fprintf(stderr, "Error reading key from %s at line %d: %s\n", argv[argi], line_nr, ldns_get_errorstr_by_id(s));
717  }
718  }
719  /* and, if not unset by -p, find or create the corresponding DNSKEY record */
720  if (key) {
721  find_or_create_pubkey(keyfile_name_base, key,
722  orig_zone, add_keys, ttl);
723  }
724  argi++;
725  }
726 
727  if (ldns_key_list_key_count(keys) < 1) {
728  fprintf(stderr, "Error: no keys to sign with. Aborting.\n\n");
729  usage(stderr, prog);
730  exit(EXIT_FAILURE);
731  }
732 
733  signed_zone = ldns_dnssec_zone_new();
734  if (ldns_dnssec_zone_add_rr(signed_zone, ldns_zone_soa(orig_zone)) !=
735  LDNS_STATUS_OK) {
736  fprintf(stderr,
737  "Error adding SOA to dnssec zone, skipping record\n");
738  }
739 
740  for (i = 0;
741  i < ldns_rr_list_rr_count(ldns_zone_rrs(orig_zone));
742  i++) {
743  if (ldns_dnssec_zone_add_rr(signed_zone,
744  ldns_rr_list_rr(ldns_zone_rrs(orig_zone),
745  i)) !=
746  LDNS_STATUS_OK) {
747  fprintf(stderr,
748  "Error adding RR to dnssec zone");
749  fprintf(stderr, ", skipping record:\n");
750  ldns_rr_print(stderr,
751  ldns_rr_list_rr(ldns_zone_rrs(orig_zone), i));
752  }
753  }
754 
755  /* list to store newly created rrs, so we can free them later */
756  added_rrs = ldns_rr_list_new();
757 
758  if (use_nsec3) {
759  result = ldns_dnssec_zone_sign_nsec3_flg_mkmap(signed_zone,
760  added_rrs,
761  keys,
763  NULL,
764  nsec3_algorithm,
765  nsec3_flags,
766  nsec3_iterations,
767  nsec3_salt_length,
768  nsec3_salt,
769  signflags,
770  (ldns_rbtree_t**) hashmap);
771  } else {
772  result = ldns_dnssec_zone_sign_flg(signed_zone,
773  added_rrs,
774  keys,
776  NULL,
777  signflags);
778  }
779  if (result != LDNS_STATUS_OK) {
780  fprintf(stderr, "Error signing zone: %s\n",
781  ldns_get_errorstr_by_id(result));
782  }
783 
784  if (!outputfile_name) {
785  outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
786  snprintf(outputfile_name, MAX_FILENAME_LEN, "%s.signed", zonefile_name);
787  }
788 
789  if (signed_zone) {
790  if (strncmp(outputfile_name, "-", 2) == 0) {
791  ldns_dnssec_zone_print(stdout, signed_zone);
792  } else {
793  outputfile = fopen(outputfile_name, "w");
794  if (!outputfile) {
795  fprintf(stderr, "Unable to open %s for writing: %s\n",
796  outputfile_name, strerror(errno));
797  } else {
799  outputfile, &fmt, signed_zone);
800  fclose(outputfile);
801  }
802  }
803  } else {
804  fprintf(stderr, "Error signing zone.\n");
805 
806 #ifdef HAVE_SSL
807  if (ERR_peek_error()) {
808  ERR_load_crypto_strings();
809  ERR_print_errors_fp(stderr);
810  ERR_free_strings();
811  }
812 #endif
813  exit(EXIT_FAILURE);
814  }
815 
816  ldns_key_list_free(keys);
817  /* since the ldns_rr records are pointed to in both the ldns_zone
818  * and the ldns_dnssec_zone, we can either deep_free the
819  * dnssec_zone and 'shallow' free the original zone and added
820  * records, or the other way around
821  */
822  ldns_dnssec_zone_free(signed_zone);
823  ldns_zone_deep_free(orig_zone);
824  ldns_rr_list_deep_free(added_rrs);
825 
826  LDNS_FREE(outputfile_name);
827 
828  CRYPTO_cleanup_all_ex_data();
829 
830  free(prog);
831  exit(EXIT_SUCCESS);
832 }
833 #else
834 int
835 main(int argc, char **argv)
836 {
837  fprintf(stderr, "ldns-signzone needs OpenSSL support, which has not been compiled in\n");
838  return 1;
839 }
840 #endif /* HAVE_SSL */
ldns_rdf * ldns_rr_rdf(const ldns_rr *rr, size_t nr)
returns the rdata field member counter.
Definition: rr.c:848
ldns_rr_list * ldns_rr_list_new()
creates a new rr_list structure.
Definition: rr.c:939
void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist)
Set the zone&#39;s contents.
Definition: zone.c:41
ldns_rr * ldns_zone_soa(const ldns_zone *z)
Return the soa record of a zone.
Definition: zone.c:17
ldns_dnssec_zone * ldns_dnssec_zone_new()
Creates a new dnssec_zone structure.
Definition: dnssec_zone.c:614
ldns_rdf * ldns_key_pubkey_owner(const ldns_key *k)
return the public key&#39;s owner
Definition: keys.c:1196
#define LDNS_COMMENT_BUBBLEBABBLE
Provide bubblebabble representation for DS RR&#39;s as comment.
Definition: host2str.h:58
#define LDNS_DEFAULT_TTL
Definition: ldns.h:134
DNSSEC.
Definition: rr.h:173
int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
Compares the two dname rdf&#39;s according to the algorithm for ordering in RFC4034 Section 6...
Definition: dname.c:356
enum ldns_enum_rr_class ldns_rr_class
Definition: rr.h:64
bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr)
pushes an rr to an rrlist.
Definition: rr.c:1071
List or Set of Resource Records.
Definition: rr.h:306
ldns_status ldns_str2rdf_dname(ldns_rdf **d, const char *str)
convert a dname string into wireformat
Definition: str2host.c:296
Output format specifier.
Definition: host2str.h:80
void ldns_key_set_flags(ldns_key *k, uint16_t f)
Set the key&#39;s flags.
Definition: keys.c:974
time_t ldns_mktime_from_utc(const struct tm *tm)
Convert TM to seconds since epoch (midnight, January 1st, 1970).
Definition: util.c:230
#define LDNS_SIGN_DNSKEY_WITH_ZSK
dnssec_verify
Definition: dnssec_sign.h:15
void strip_dnssec_records(ldns_zone *zone)
ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c __attribute__((unused)), int *line_nr)
Definition: zone.c:292
#define LDNS_XMALLOC(type, count)
Definition: util.h:51
void ldns_rr_list_deep_free(ldns_rr_list *rr_list)
frees an rr_list structure and all rrs contained therein.
Definition: rr.c:959
DNS Zone.
Definition: zone.h:42
ldns_rdf * ldns_rdf_clone(const ldns_rdf *rd)
clones a rdf structure.
Definition: rdata.c:222
void ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
Definition: dnssec_zone.c:946
int main(void)
Definition: linktest.c:6
void ldns_rr_free(ldns_rr *rr)
frees an RR structure
Definition: rr.c:75
Structure containing a dnssec zone.
Definition: dnssec_zone.h:91
int ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n)
Default callback function to always leave present signatures, and add new ones.
void ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r)
Set the key&#39;s pubkey owner.
Definition: keys.c:1058
void ldns_rr_list_free(ldns_rr_list *rr_list)
frees an rr_list structure.
Definition: rr.c:950
const ldns_output_format * ldns_output_format_default
The default output format record.
Definition: host2str.c:125
Resource Record.
Definition: rr.h:278
ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm alg)
Read the key with the given id from the given engine and store it in the given ldns_key structure...
Definition: keys.c:93
Including this file will include all ldns files, and define some lookup tables.
ldns_status ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, ldns_key_list *key_list, int(*func)(ldns_rr *, void *), void *arg, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt, int signflags, ldns_rbtree_t **map)
signs the given zone with the given new zone, with NSEC3
Definition: dnssec_sign.c:1235
int verbosity
Definition: ldns-signzone.c:25
General key structure, can contain all types of keys that are used in DNSSEC.
Definition: keys.h:107
ldns_rr * ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr)
returns a specific rr of an rrlist.
Definition: rr.c:929
const char * ldns_version(void)
Show the internal library version.
Definition: util.c:196
ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
Adds the given RR to the zone.
Definition: dnssec_zone.c:858
#define LDNS_VERSION
Definition: util.h:30
bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr)
push an single rr to a zone structure.
Definition: zone.c:54
#define ATTR_UNUSED(x)
Definition: common.h:64
ldns_rr * ldns_rr_list_pop_rr(ldns_rr_list *rr_list)
pops the last rr from an rrlist.
Definition: rr.c:1116
uint16_t ldns_rdf2native_int16(const ldns_rdf *rd)
returns the native uint16_t representation from the rdf.
Definition: rdata.c:84
void * data
Potential extra data to be used with formatting RR&#39;s in text.
Definition: host2str.h:85
void ldns_key_set_expiration(ldns_key *k, uint32_t e)
Set the key&#39;s expiration date (seconds after epoch)
Definition: keys.c:1052
#define LDNS_NSEC3_VARS_OPTOUT_MASK
Definition: rdata.h:39
int flags
Specification of how RR&#39;s should be formatted in text.
Definition: host2str.h:83
return NULL
Definition: keys.c:738
the Internet
Definition: rr.h:50
Same as rr_list, but now for keys.
Definition: keys.h:157
ldns_status ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
Creates a new private key based on the contents of the file pointed by fp.
Definition: keys.c:291
uint16_t ldns_calc_keytag(const ldns_rr *key)
calculates a keytag of a key for use in DNSSEC.
Definition: dnssec.c:271
#define MAX_FILENAME_LEN
Definition: ldns-signzone.c:24
void ldns_key_list_free(ldns_key_list *key_list)
Frees a key list structure.
Definition: keys.c:1582
bool ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key)
pushes a key to a keylist
Definition: keys.c:1219
definition for tree struct
Definition: rbtree.h:83
#define LDNS_KEY_SEP_KEY
Definition: keys.h:38
void ldns_zone_deep_free(ldns_zone *zone)
Frees the allocated memory for the zone, the soa rr in it, and the rr_list structure in it...
Definition: zone.c:426
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
Definition: rr.c:882
int ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2)
compares two rrs, up to the rdata.
Definition: rr.c:1515
void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
sets the ttl in the rr structure.
Definition: rr.c:755
enum ldns_enum_status ldns_status
Definition: error.h:122
void ldns_key_set_inception(ldns_key *k, uint32_t i)
Set the key&#39;s inception date (seconds after epoch)
Definition: keys.c:1046
ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k)
return the signing alg of the key
Definition: keys.c:1087
void ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
Frees the given zone structure, and its rbtree of dnssec_names Individual ldns_rr RRs within those na...
Definition: dnssec_zone.c:795
ldns_status ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr)
creates a new rr from a file containing a string.
Definition: rr.c:655
void ldns_rr_print(FILE *output, const ldns_rr *rr)
Prints the data in the resource record to the given file stream (in presentation format) ...
Definition: host2str.c:2241
void ldns_key_set_keytag(ldns_key *k, uint16_t tag)
Set the key&#39;s key tag.
Definition: keys.c:1064
Addendum to dnssec.h, this module contains key and algorithm definitions and functions.
#define LDNS_COMMENT_FLAGS
Show when a NSEC3 RR has the optout flag set as comment.
Definition: host2str.h:60
char * ldns_rdf2str(const ldns_rdf *rdf)
Converts the data in the rdata field to presentation format and returns that as a char *...
Definition: host2str.c:2098
ldns_rr_list * ldns_zone_rrs(const ldns_zone *z)
Get a list of a zone&#39;s content.
Definition: zone.c:35
int ldns_hexdigit_to_int(char ch)
Returns the int value of the given (hex) digit.
Definition: util.c:124
void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
Definition: dnssec_zone.c:974
ldns_rr * ldns_key2rr(const ldns_key *k)
converts a ldns_key to a public key rr If the key data exists at an external point, the corresponding rdata field must still be added with ldns_rr_rdf_push() to the result rr of this function
Definition: keys.c:1358
Resource record data field.
Definition: rdata.h:138
size_t ldns_key_list_key_count(const ldns_key_list *key_list)
returns the number of keys in the key list
Definition: keys.c:1071
ldns_rdf * ldns_rr_owner(const ldns_rr *rr)
returns the owner name of an rr structure.
Definition: rr.c:858
size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
returns the number of rr&#39;s in an rr_list.
Definition: rr.c:896
#define LDNS_COMMENT_NSEC3_CHAIN
Show the unhashed owner and next owner names for NSEC3 RR&#39;s as comment.
Definition: host2str.h:62
#define LDNS_FREE(ptr)
Definition: util.h:60
uint16_t ldns_key_keytag(const ldns_key *k)
return the keytag
Definition: keys.c:1190
ldns_key_list * ldns_key_list_new()
Creates a new empty key list.
Definition: keys.c:47
#define LDNS_COMMENT_LAYOUT
Print mark up.
Definition: host2str.h:64
const char * ldns_get_errorstr_by_id(ldns_status err)
look up a descriptive text by each error.
Definition: error.c:131
uint32_t ldns_rr_ttl(const ldns_rr *rr)
returns the ttl of an rr structure.
Definition: rr.c:870
uint16_t ldns_key_flags(const ldns_key *k)
return the flag of the key
Definition: keys.c:1172
ldns_status ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, ldns_key_list *key_list, int(*func)(ldns_rr *, void *), void *arg, int flags)
signs the given zone with the given keys
Definition: dnssec_sign.c:1180
#define LDNS_NSEC3_MAX_ITERATIONS
Definition: dnssec.h:87
int
Definition: dnssec.c:1575
i
Definition: keys.c:681