00001
00002
00003
00004
00005
00006
00007
00008 #include "config.h"
00009 #include <stdlib.h>
00010 #include <unistd.h>
00011
00012 #include <errno.h>
00013
00014 #include <time.h>
00015
00016 #include <ldns/ldns.h>
00017 #include <ldns/keys.h>
00018
00019 #ifdef HAVE_SSL
00020 #include <openssl/conf.h>
00021 #include <openssl/engine.h>
00022 #endif
00023
00024 #define MAX_FILENAME_LEN 250
00025 int verbosity = 1;
00026
00027 #ifdef HAVE_SSL
00028 #include <openssl/err.h>
00029
00030 static void
00031 usage(FILE *fp, const char *prog) {
00032 fprintf(fp, "%s [OPTIONS] zonefile key [key [key]]\n", prog);
00033 fprintf(fp, " signs the zone with the given key(s)\n");
00034 fprintf(fp, " -b\t\tuse layout in signed zone and print comments DNSSEC records\n");
00035 fprintf(fp, " -d\t\tused keys are not added to the zone\n");
00036 fprintf(fp, " -e <date>\texpiration date\n");
00037 fprintf(fp, " -f <file>\toutput zone to file (default <name>.signed)\n");
00038 fprintf(fp, " -i <date>\tinception date\n");
00039 fprintf(fp, " -o <domain>\torigin for the zone\n");
00040 fprintf(fp, " -v\t\tprint version and exit\n");
00041 fprintf(fp, " -A\t\tsign DNSKEY with all keys instead of minimal\n");
00042 fprintf(fp, " -E <name>\tuse <name> as the crypto engine for signing\n");
00043 fprintf(fp, " \tThis can have a lot of extra options, see the manual page for more info\n");
00044 fprintf(fp, " -k <id>,<int>\tuse key id with algorithm int from engine\n");
00045 fprintf(fp, " -K <id>,<int>\tuse key id with algorithm int from engine as KSK\n");
00046 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");
00047 fprintf(fp, " -n\t\tuse NSEC3 instead of NSEC.\n");
00048 fprintf(fp, "\t\tIf you use NSEC3, you can specify the following extra options:\n");
00049 fprintf(fp, "\t\t-a [algorithm] hashing algorithm\n");
00050 fprintf(fp, "\t\t-t [number] number of hash iterations\n");
00051 fprintf(fp, "\t\t-s [string] salt\n");
00052 fprintf(fp, "\t\t-p set the opt-out flag on all nsec3 rrs\n");
00053 fprintf(fp, "\n");
00054 fprintf(fp, " keys must be specified by their base name (usually K<name>+<alg>+<id>),\n");
00055 fprintf(fp, " i.e. WITHOUT the .private extension.\n");
00056 fprintf(fp, " If the public part of the key is not present in the zone, the DNSKEY RR\n");
00057 fprintf(fp, " will be read from the file called <base name>.key. If that does not exist,\n");
00058 fprintf(fp, " a default DNSKEY will be generated from the private key and added to the zone.\n");
00059 fprintf(fp, " A date can be a timestamp (seconds since the epoch), or of\n the form <YYYYMMdd[hhmmss]>\n");
00060 }
00061
00062 static void check_tm(struct tm tm)
00063 {
00064 if (tm.tm_year < 70) {
00065 fprintf(stderr, "You cannot specify dates before 1970\n");
00066 exit(EXIT_FAILURE);
00067 }
00068 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
00069 fprintf(stderr, "The month must be in the range 1 to 12\n");
00070 exit(EXIT_FAILURE);
00071 }
00072 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
00073 fprintf(stderr, "The day must be in the range 1 to 31\n");
00074 exit(EXIT_FAILURE);
00075 }
00076
00077 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
00078 fprintf(stderr, "The hour must be in the range 0-23\n");
00079 exit(EXIT_FAILURE);
00080 }
00081
00082 if (tm.tm_min < 0 || tm.tm_min > 59) {
00083 fprintf(stderr, "The minute must be in the range 0-59\n");
00084 exit(EXIT_FAILURE);
00085 }
00086
00087 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
00088 fprintf(stderr, "The second must be in the range 0-59\n");
00089 exit(EXIT_FAILURE);
00090 }
00091
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101 static void
00102 equalize_ttls(ldns_rr *rr1, ldns_rr *rr2, uint32_t default_ttl)
00103 {
00104 uint32_t ttl1, ttl2;
00105
00106 ttl1 = ldns_rr_ttl(rr1);
00107 ttl2 = ldns_rr_ttl(rr2);
00108
00109 if (ttl1 != ttl2) {
00110 if (ttl1 == default_ttl) {
00111 ldns_rr_set_ttl(rr1, ttl2);
00112 } else if (ttl2 == default_ttl) {
00113 ldns_rr_set_ttl(rr2, ttl1);
00114 } else {
00115 ldns_rr_set_ttl(rr2, ttl1);
00116 fprintf(stderr,
00117 "warning: changing non-default TTL %u to %u\n",
00118 (unsigned int) ttl2, (unsigned int) ttl1);
00119 }
00120 }
00121 }
00122
00123 static void
00124 equalize_ttls_rr_list(ldns_rr_list *rr_list, ldns_rr *rr, uint32_t default_ttl)
00125 {
00126 size_t i;
00127 ldns_rr *cur_rr;
00128
00129 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
00130 cur_rr = ldns_rr_list_rr(rr_list, i);
00131 if (ldns_rr_compare_no_rdata(cur_rr, rr) == 0) {
00132 equalize_ttls(cur_rr, rr, default_ttl);
00133 }
00134 }
00135 }
00136
00137 static ldns_rr *
00138 find_key_in_zone(ldns_rr *pubkey_gen, ldns_zone *zone) {
00139 size_t key_i;
00140 ldns_rr *pubkey;
00141
00142 for (key_i = 0;
00143 key_i < ldns_rr_list_rr_count(ldns_zone_rrs(zone));
00144 key_i++) {
00145 pubkey = ldns_rr_list_rr(ldns_zone_rrs(zone), key_i);
00146 if (ldns_rr_get_type(pubkey) == LDNS_RR_TYPE_DNSKEY &&
00147 (ldns_calc_keytag(pubkey)
00148 ==
00149 ldns_calc_keytag(pubkey_gen) ||
00150
00151 ldns_calc_keytag(pubkey)
00152 ==
00153 ldns_calc_keytag(pubkey_gen) + 1)
00154 ) {
00155 if (verbosity >= 2) {
00156 fprintf(stderr, "Found it in the zone!\n");
00157 }
00158 return pubkey;
00159 }
00160 }
00161 return NULL;
00162 }
00163
00164 static ldns_rr *
00165 find_key_in_file(const char *keyfile_name_base, ldns_key* ATTR_UNUSED(key),
00166 uint32_t zone_ttl)
00167 {
00168 char *keyfile_name;
00169 FILE *keyfile;
00170 int line_nr;
00171 uint32_t default_ttl = zone_ttl;
00172
00173 ldns_rr *pubkey = NULL;
00174 keyfile_name = LDNS_XMALLOC(char,
00175 strlen(keyfile_name_base) + 5);
00176 snprintf(keyfile_name,
00177 strlen(keyfile_name_base) + 5,
00178 "%s.key",
00179 keyfile_name_base);
00180 if (verbosity >= 2) {
00181 fprintf(stderr, "Trying to read %s\n", keyfile_name);
00182 }
00183 keyfile = fopen(keyfile_name, "r");
00184 line_nr = 0;
00185 if (keyfile) {
00186 if (ldns_rr_new_frm_fp_l(&pubkey,
00187 keyfile,
00188 &default_ttl,
00189 NULL,
00190 NULL,
00191 &line_nr) ==
00192 LDNS_STATUS_OK) {
00193 if (verbosity >= 2) {
00194 printf("Key found in file: %s\n", keyfile_name);
00195 }
00196 }
00197 fclose(keyfile);
00198 }
00199 LDNS_FREE(keyfile_name);
00200 return pubkey;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 static void
00213 find_or_create_pubkey(const char *keyfile_name_base, ldns_key *key, ldns_zone *orig_zone, bool add_keys, uint32_t default_ttl) {
00214 ldns_rr *pubkey_gen, *pubkey;
00215 int key_in_zone;
00216
00217 if (default_ttl == LDNS_DEFAULT_TTL) {
00218 default_ttl = ldns_rr_ttl(ldns_zone_soa(orig_zone));
00219 }
00220
00221 if (!ldns_key_pubkey_owner(key)) {
00222 ldns_key_set_pubkey_owner(key, ldns_rdf_clone(ldns_rr_owner(ldns_zone_soa(orig_zone))));
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 pubkey_gen = ldns_key2rr(key);
00239 ldns_rr_set_ttl(pubkey_gen, default_ttl);
00240
00241 if (verbosity >= 2) {
00242 fprintf(stderr,
00243 "Looking for key with keytag %u or %u\n",
00244 (unsigned int) ldns_calc_keytag(pubkey_gen),
00245 (unsigned int) ldns_calc_keytag(pubkey_gen)+1
00246 );
00247 }
00248
00249 pubkey = find_key_in_zone(pubkey_gen, orig_zone);
00250 key_in_zone = 1;
00251 if (!pubkey) {
00252 key_in_zone = 0;
00253
00254 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
00255 if (!pubkey && !(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
00256
00257 ldns_key_set_keytag(key, ldns_key_keytag(key) + 1);
00258 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
00259 if (!pubkey) {
00260
00261 ldns_key_set_keytag(key, ldns_key_keytag(key) - 1);
00262 }
00263 }
00264 if(pubkey && ldns_dname_compare(ldns_rr_owner(pubkey), ldns_rr_owner(ldns_zone_soa(orig_zone))) != 0) {
00265 fprintf(stderr, "Error %s.key has wrong name: %s\n",
00266 keyfile_name_base, ldns_rdf2str(ldns_rr_owner(pubkey)));
00267 exit(EXIT_FAILURE);
00268 }
00269 }
00270
00271 if (!pubkey) {
00272
00273
00274 pubkey = pubkey_gen;
00275 if (verbosity >= 2) {
00276 fprintf(stderr, "Not in zone, no .key file, generating ZSK DNSKEY from private key data\n");
00277 }
00278 } else {
00279 ldns_rr_free(pubkey_gen);
00280 }
00281 ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0)));
00282 ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
00283
00284 if (add_keys && !key_in_zone) {
00285 equalize_ttls_rr_list(ldns_zone_rrs(orig_zone), pubkey, default_ttl);
00286 ldns_zone_push_rr(orig_zone, pubkey);
00287 }
00288 }
00289
00290 void
00291 strip_dnssec_records(ldns_zone *zone)
00292 {
00293 ldns_rr_list *new_list;
00294 ldns_rr *cur_rr;
00295
00296 new_list = ldns_rr_list_new();
00297
00298 while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(zone)))) {
00299 if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG ||
00300 ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC ||
00301 ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC3
00302 ) {
00303
00304 ldns_rr_free(cur_rr);
00305 } else {
00306 ldns_rr_list_push_rr(new_list, cur_rr);
00307 }
00308 }
00309 ldns_rr_list_free(ldns_zone_rrs(zone));
00310 ldns_zone_set_rrs(zone, new_list);
00311 }
00312
00313 int
00314 main(int argc, char *argv[])
00315 {
00316 const char *zonefile_name;
00317 FILE *zonefile = NULL;
00318 int line_nr = 0;
00319 int c;
00320 int argi;
00321 ENGINE *engine = NULL;
00322
00323 ldns_zone *orig_zone;
00324 ldns_rr_list *orig_rrs = NULL;
00325 ldns_rr *orig_soa = NULL;
00326 ldns_dnssec_zone *signed_zone;
00327
00328 char *keyfile_name_base;
00329 char *keyfile_name = NULL;
00330 FILE *keyfile = NULL;
00331 ldns_key *key = NULL;
00332 ldns_key_list *keys;
00333 ldns_status s;
00334 size_t i;
00335 ldns_rr_list *added_rrs;
00336
00337 char *outputfile_name = NULL;
00338 FILE *outputfile;
00339
00340
00341 char *eng_key_l;
00342 size_t eng_key_id_len;
00343 char *eng_key_id;
00344 int eng_key_algo;
00345
00346 bool use_nsec3 = false;
00347 int signflags = 0;
00348
00349
00350 bool add_keys = true;
00351 uint8_t nsec3_algorithm = 1;
00352 uint8_t nsec3_flags = 0;
00353 size_t nsec3_iterations_cmd = 1;
00354 uint16_t nsec3_iterations = 1;
00355 uint8_t nsec3_salt_length = 0;
00356 uint8_t *nsec3_salt = NULL;
00357
00358
00359
00360
00361 struct tm tm;
00362 uint32_t inception;
00363 uint32_t expiration;
00364 ldns_rdf *origin = NULL;
00365 uint32_t ttl = LDNS_DEFAULT_TTL;
00366 ldns_rr_class class = LDNS_RR_CLASS_IN;
00367
00368 char *prog = strdup(argv[0]);
00369 ldns_status result;
00370
00371 ldns_output_format fmt = { ldns_output_format_default->flags, NULL };
00372 void **hashmap = NULL;
00373
00374
00375 inception = 0;
00376 expiration = 0;
00377
00378 keys = ldns_key_list_new();
00379
00380 OPENSSL_config(NULL);
00381
00382 while ((c = getopt(argc, argv, "a:bde:f:i:k:lno:ps:t:vAE:K:")) != -1) {
00383 switch (c) {
00384 case 'a':
00385 nsec3_algorithm = (uint8_t) atoi(optarg);
00386 if (nsec3_algorithm != 1) {
00387 fprintf(stderr, "Bad NSEC3 algorithm, only RSASHA1 allowed\n");
00388 exit(EXIT_FAILURE);
00389 }
00390 break;
00391 case 'b':
00392 fmt.flags |= LDNS_COMMENT_BUBBLEBABBLE;
00393 fmt.flags |= LDNS_COMMENT_FLAGS;
00394 fmt.flags |= LDNS_COMMENT_NSEC3_CHAIN;
00395 fmt.flags |= LDNS_COMMENT_LAYOUT;
00396 hashmap = &fmt.data;
00397 break;
00398 case 'd':
00399 add_keys = false;
00400 break;
00401 case 'e':
00402
00403
00404
00405
00406 memset(&tm, 0, sizeof(tm));
00407
00408 if (strlen(optarg) == 8 &&
00409 sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
00410 ) {
00411 tm.tm_year -= 1900;
00412 tm.tm_mon--;
00413 check_tm(tm);
00414 expiration = (uint32_t) mktime_from_utc(&tm);
00415 } else if (strlen(optarg) == 14 &&
00416 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)
00417 ) {
00418 tm.tm_year -= 1900;
00419 tm.tm_mon--;
00420 check_tm(tm);
00421 expiration = (uint32_t) mktime_from_utc(&tm);
00422 } else {
00423 expiration = (uint32_t) atol(optarg);
00424 }
00425 break;
00426 case 'f':
00427 outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
00428 strncpy(outputfile_name, optarg, MAX_FILENAME_LEN);
00429 break;
00430 case 'i':
00431 memset(&tm, 0, sizeof(tm));
00432
00433 if (strlen(optarg) == 8 &&
00434 sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
00435 ) {
00436 tm.tm_year -= 1900;
00437 tm.tm_mon--;
00438 check_tm(tm);
00439 inception = (uint32_t) mktime_from_utc(&tm);
00440 } else if (strlen(optarg) == 14 &&
00441 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)
00442 ) {
00443 tm.tm_year -= 1900;
00444 tm.tm_mon--;
00445 check_tm(tm);
00446 inception = (uint32_t) mktime_from_utc(&tm);
00447 } else {
00448 inception = (uint32_t) atol(optarg);
00449 }
00450 break;
00451 case 'n':
00452 use_nsec3 = true;
00453 break;
00454 case 'o':
00455 if (ldns_str2rdf_dname(&origin, optarg) != LDNS_STATUS_OK) {
00456 fprintf(stderr, "Bad origin, not a correct domain name\n");
00457 usage(stderr, prog);
00458 exit(EXIT_FAILURE);
00459 }
00460 break;
00461 case 'p':
00462 nsec3_flags = nsec3_flags | LDNS_NSEC3_VARS_OPTOUT_MASK;
00463 break;
00464 case 'v':
00465 printf("zone signer version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
00466 exit(EXIT_SUCCESS);
00467 break;
00468 case 'A':
00469 signflags |= LDNS_SIGN_DNSKEY_WITH_ZSK;
00470 break;
00471 case 'E':
00472 ENGINE_load_builtin_engines();
00473 ENGINE_load_dynamic();
00474 ENGINE_load_cryptodev();
00475 engine = ENGINE_by_id(optarg);
00476 if (!engine) {
00477 printf("No such engine: %s\n", optarg);
00478 engine = ENGINE_get_first();
00479 printf("Available engines:\n");
00480 while (engine) {
00481 printf("%s\n", ENGINE_get_id(engine));
00482 engine = ENGINE_get_next(engine);
00483 }
00484 exit(EXIT_FAILURE);
00485 } else {
00486 if (!ENGINE_init(engine)) {
00487 printf("The engine couldn't initialize\n");
00488 exit(EXIT_FAILURE);
00489 }
00490 ENGINE_set_default_RSA(engine);
00491 ENGINE_set_default_DSA(engine);
00492 ENGINE_set_default(engine, 0);
00493 }
00494 break;
00495 case 'k':
00496 eng_key_l = strchr(optarg, ',');
00497 if (eng_key_l && strlen(eng_key_l) > 1) {
00498 if (eng_key_l > optarg) {
00499 eng_key_id_len = (size_t) (eng_key_l - optarg);
00500 eng_key_id = malloc(eng_key_id_len + 1);
00501 memcpy(eng_key_id, optarg, eng_key_id_len);
00502 eng_key_id[eng_key_id_len] = '\0';
00503 } else {
00504
00505 eng_key_id = NULL;
00506 }
00507
00508 eng_key_algo = atoi(eng_key_l + 1);
00509
00510 printf("Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo);
00511
00512 if (expiration != 0) {
00513 ldns_key_set_expiration(key, expiration);
00514 }
00515 if (inception != 0) {
00516 ldns_key_set_inception(key, inception);
00517 }
00518
00519 s = ldns_key_new_frm_engine(&key, engine, eng_key_id, eng_key_algo);
00520 if (s == LDNS_STATUS_OK) {
00521
00522 switch (ldns_key_algorithm(key)) {
00523 case LDNS_SIGN_RSAMD5:
00524 case LDNS_SIGN_RSASHA1:
00525 case LDNS_SIGN_RSASHA1_NSEC3:
00526 case LDNS_SIGN_RSASHA256:
00527 case LDNS_SIGN_RSASHA512:
00528 case LDNS_SIGN_DSA:
00529 case LDNS_SIGN_DSA_NSEC3:
00530 case LDNS_SIGN_ECC_GOST:
00531 #ifdef USE_ECDSA
00532 case LDNS_SIGN_ECDSAP256SHA256:
00533 case LDNS_SIGN_ECDSAP384SHA384:
00534 #endif
00535 ldns_key_list_push_key(keys, key);
00536
00537
00538 break;
00539 default:
00540 fprintf(stderr, "Warning, key not suitable for signing, ignoring key with algorithm %u\n", ldns_key_algorithm(key));
00541 break;
00542 }
00543 } else {
00544 printf("Error reading key '%s' from engine: %s\n", eng_key_id, ldns_get_errorstr_by_id(s));
00545 #ifdef HAVE_SSL
00546 if (ERR_peek_error()) {
00547 ERR_load_crypto_strings();
00548 ERR_print_errors_fp(stderr);
00549 ERR_free_strings();
00550 }
00551 #endif
00552 exit(EXIT_FAILURE);
00553 }
00554
00555 if (eng_key_id) {
00556 free(eng_key_id);
00557 }
00558 } else {
00559 printf("Error: bad engine key specification (should be: -k <id>,<algorithm>)).\n");
00560 exit(EXIT_FAILURE);
00561 }
00562 break;
00563 case 'K':
00564 printf("Not implemented yet\n");
00565 exit(EXIT_FAILURE);
00566 break;
00567 case 's':
00568 if (strlen(optarg) % 2 != 0) {
00569 fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
00570 exit(EXIT_FAILURE);
00571 }
00572 nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
00573 nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length);
00574 for (c = 0; c < (int) strlen(optarg); c += 2) {
00575 if (isxdigit((int) optarg[c]) && isxdigit((int) optarg[c+1])) {
00576 nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
00577 ldns_hexdigit_to_int(optarg[c+1]);
00578 } else {
00579 fprintf(stderr, "Salt value is not valid hex data.\n");
00580 exit(EXIT_FAILURE);
00581 }
00582 }
00583
00584 break;
00585 case 't':
00586 nsec3_iterations_cmd = (size_t) atol(optarg);
00587 if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) {
00588 fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
00589 exit(EXIT_FAILURE);
00590 }
00591 nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
00592 break;
00593 default:
00594 usage(stderr, prog);
00595 exit(EXIT_SUCCESS);
00596 }
00597 }
00598
00599 argc -= optind;
00600 argv += optind;
00601
00602 if (argc < 1) {
00603 printf("Error: not enough arguments\n");
00604 usage(stdout, prog);
00605 exit(EXIT_FAILURE);
00606 } else {
00607 zonefile_name = argv[0];
00608 }
00609
00610
00611
00612 if (strncmp(zonefile_name, "-", 2) == 0) {
00613 s = ldns_zone_new_frm_fp_l(&orig_zone,
00614 stdin,
00615 origin,
00616 ttl,
00617 class,
00618 &line_nr);
00619 if (s != LDNS_STATUS_OK) {
00620 fprintf(stderr, "Zone not read, error: %s at stdin line %d\n",
00621 ldns_get_errorstr_by_id(s),
00622 line_nr);
00623 exit(EXIT_FAILURE);
00624 } else {
00625 orig_soa = ldns_zone_soa(orig_zone);
00626 if (!orig_soa) {
00627 fprintf(stderr,
00628 "Error reading zonefile: missing SOA record\n");
00629 exit(EXIT_FAILURE);
00630 }
00631 orig_rrs = ldns_zone_rrs(orig_zone);
00632 if (!orig_rrs) {
00633 fprintf(stderr,
00634 "Error reading zonefile: no resource records\n");
00635 exit(EXIT_FAILURE);
00636 }
00637 }
00638 } else {
00639 zonefile = fopen(zonefile_name, "r");
00640
00641 if (!zonefile) {
00642 fprintf(stderr,
00643 "Error: unable to read %s (%s)\n",
00644 zonefile_name,
00645 strerror(errno));
00646 exit(EXIT_FAILURE);
00647 } else {
00648 s = ldns_zone_new_frm_fp_l(&orig_zone,
00649 zonefile,
00650 origin,
00651 ttl,
00652 class,
00653 &line_nr);
00654 if (s != LDNS_STATUS_OK) {
00655 fprintf(stderr, "Zone not read, error: %s at %s line %d\n",
00656 ldns_get_errorstr_by_id(s),
00657 zonefile_name, line_nr);
00658 exit(EXIT_FAILURE);
00659 } else {
00660 orig_soa = ldns_zone_soa(orig_zone);
00661 if (!orig_soa) {
00662 fprintf(stderr,
00663 "Error reading zonefile: missing SOA record\n");
00664 exit(EXIT_FAILURE);
00665 }
00666 orig_rrs = ldns_zone_rrs(orig_zone);
00667 if (!orig_rrs) {
00668 fprintf(stderr,
00669 "Error reading zonefile: no resource records\n");
00670 exit(EXIT_FAILURE);
00671 }
00672 }
00673 fclose(zonefile);
00674 }
00675 }
00676
00677 if (!origin) {
00678 origin = ldns_rr_owner(orig_soa);
00679 }
00680
00681
00682 argi = 1;
00683 while (argi < argc) {
00684 keyfile_name_base = argv[argi];
00685 keyfile_name = LDNS_XMALLOC(char, strlen(keyfile_name_base) + 9);
00686 snprintf(keyfile_name,
00687 strlen(keyfile_name_base) + 9,
00688 "%s.private",
00689 keyfile_name_base);
00690 keyfile = fopen(keyfile_name, "r");
00691 line_nr = 0;
00692 if (!keyfile) {
00693 fprintf(stderr,
00694 "Error: unable to read %s: %s\n",
00695 keyfile_name,
00696 strerror(errno));
00697 } else {
00698 s = ldns_key_new_frm_fp_l(&key, keyfile, &line_nr);
00699 fclose(keyfile);
00700 if (s == LDNS_STATUS_OK) {
00701
00702
00703
00704 if (expiration != 0) {
00705 ldns_key_set_expiration(key, expiration);
00706 }
00707 if (inception != 0) {
00708 ldns_key_set_inception(key, inception);
00709 }
00710
00711 LDNS_FREE(keyfile_name);
00712
00713 ldns_key_list_push_key(keys, key);
00714 } else {
00715 fprintf(stderr, "Error reading key from %s at line %d: %s\n", argv[argi], line_nr, ldns_get_errorstr_by_id(s));
00716 }
00717 }
00718
00719 if (key) {
00720 find_or_create_pubkey(keyfile_name_base, key,
00721 orig_zone, add_keys, ttl);
00722 }
00723 argi++;
00724 }
00725
00726 if (ldns_key_list_key_count(keys) < 1) {
00727 fprintf(stderr, "Error: no keys to sign with. Aborting.\n\n");
00728 usage(stderr, prog);
00729 exit(EXIT_FAILURE);
00730 }
00731
00732 signed_zone = ldns_dnssec_zone_new();
00733 if (ldns_dnssec_zone_add_rr(signed_zone, ldns_zone_soa(orig_zone)) !=
00734 LDNS_STATUS_OK) {
00735 fprintf(stderr,
00736 "Error adding SOA to dnssec zone, skipping record\n");
00737 }
00738
00739 for (i = 0;
00740 i < ldns_rr_list_rr_count(ldns_zone_rrs(orig_zone));
00741 i++) {
00742 if (ldns_dnssec_zone_add_rr(signed_zone,
00743 ldns_rr_list_rr(ldns_zone_rrs(orig_zone),
00744 i)) !=
00745 LDNS_STATUS_OK) {
00746 fprintf(stderr,
00747 "Error adding RR to dnssec zone");
00748 fprintf(stderr, ", skipping record:\n");
00749 ldns_rr_print(stderr,
00750 ldns_rr_list_rr(ldns_zone_rrs(orig_zone), i));
00751 }
00752 }
00753
00754
00755 added_rrs = ldns_rr_list_new();
00756
00757 if (use_nsec3) {
00758 result = ldns_dnssec_zone_sign_nsec3_flg_mkmap(signed_zone,
00759 added_rrs,
00760 keys,
00761 ldns_dnssec_default_replace_signatures,
00762 NULL,
00763 nsec3_algorithm,
00764 nsec3_flags,
00765 nsec3_iterations,
00766 nsec3_salt_length,
00767 nsec3_salt,
00768 signflags,
00769 (ldns_rbtree_t**) hashmap);
00770 } else {
00771 result = ldns_dnssec_zone_sign_flg(signed_zone,
00772 added_rrs,
00773 keys,
00774 ldns_dnssec_default_replace_signatures,
00775 NULL,
00776 signflags);
00777 }
00778 if (result != LDNS_STATUS_OK) {
00779 fprintf(stderr, "Error signing zone: %s\n",
00780 ldns_get_errorstr_by_id(result));
00781 }
00782
00783 if (!outputfile_name) {
00784 outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
00785 snprintf(outputfile_name, MAX_FILENAME_LEN, "%s.signed", zonefile_name);
00786 }
00787
00788 if (signed_zone) {
00789 if (strncmp(outputfile_name, "-", 2) == 0) {
00790 ldns_dnssec_zone_print(stdout, signed_zone);
00791 } else {
00792 outputfile = fopen(outputfile_name, "w");
00793 if (!outputfile) {
00794 fprintf(stderr, "Unable to open %s for writing: %s\n",
00795 outputfile_name, strerror(errno));
00796 } else {
00797 ldns_dnssec_zone_print_fmt(
00798 outputfile, &fmt, signed_zone);
00799 fclose(outputfile);
00800 }
00801 }
00802 } else {
00803 fprintf(stderr, "Error signing zone.\n");
00804
00805 #ifdef HAVE_SSL
00806 if (ERR_peek_error()) {
00807 ERR_load_crypto_strings();
00808 ERR_print_errors_fp(stderr);
00809 ERR_free_strings();
00810 }
00811 #endif
00812 exit(EXIT_FAILURE);
00813 }
00814
00815 ldns_key_list_free(keys);
00816
00817
00818
00819
00820
00821 ldns_dnssec_zone_free(signed_zone);
00822 ldns_zone_deep_free(orig_zone);
00823 ldns_rr_list_deep_free(added_rrs);
00824
00825 LDNS_FREE(outputfile_name);
00826
00827 CRYPTO_cleanup_all_ex_data();
00828
00829 free(prog);
00830 exit(EXIT_SUCCESS);
00831 }
00832 #else
00833 int
00834 main(int argc, char **argv)
00835 {
00836 fprintf(stderr, "ldns-signzone needs OpenSSL support, which has not been compiled in\n");
00837 return 1;
00838 }
00839 #endif