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 #include <openssl/conf.h>
00020 #include <openssl/engine.h>
00021
00022
00023 #define MAX_FILENAME_LEN 250
00024 int verbosity = 0;
00025
00026 #ifdef HAVE_SSL
00027 #include <openssl/err.h>
00028 #endif
00029
00030 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, " -e <date>\texpiration date\n");
00035 fprintf(fp, " -f <file>\toutput zone to file (default <name>.signed)\n");
00036 fprintf(fp, " -i <date>\tinception date\n");
00037 fprintf(fp, " -l\t\tLeave old DNSSEC RRSIGS and NSEC records intact\n");
00038 fprintf(fp, " -o <domain>\torigin for the zone\n");
00039 fprintf(fp, " -v\t\tprint version and exit\n");
00040 fprintf(fp, " -E <name>\tuse <name> as the crypto engine for signing\n");
00041 fprintf(fp, " \tThis can have a lot of extra options, see -E help for more info\n");
00042 fprintf(fp, " -k <id>,<int>\tuse key id with algorithm int from engine\n");
00043 fprintf(fp, " -K <id>,<int>\tuse key id with algorithm int from engine as KSK\n");
00044 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");
00045 fprintf(fp, " -n\t\tuse NSEC3 instead of NSEC.\n");
00046 fprintf(fp, "\t\tIf you use NSEC3, you can specify the following extra options:\n");
00047 fprintf(fp, "\t\t-a [algorithm] hashing algorithm\n");
00048 fprintf(fp, "\t\t-t [number] number of hash iterations\n");
00049 fprintf(fp, "\t\t-s [string] salt\n");
00050 fprintf(fp, "\n");
00051 fprintf(fp, " keys must be specified by their base name: K<name>+<alg>+<id>\n");
00052 fprintf(fp, " if the public part of the key is not present in the zone, \n");
00053 fprintf(fp, " both a .key and .private file must be present\n");
00054 fprintf(fp, " A date can be a timestamp (seconds since the epoch), or of\n the form <YYYYMMdd[hhmmss]>\n");
00055 }
00056
00057 void
00058 usage_openssl(FILE *fp, const char *prog) {
00059 fprintf(fp, "Special commands for openssl engines:\n");
00060 fprintf(fp, "-c <file>\tOpenSSL config file\n");
00061 }
00062
00063 void check_tm(struct tm tm)
00064 {
00065 if (tm.tm_year < 70) {
00066 fprintf(stderr, "You cannot specify dates before 1970\n");
00067 exit(EXIT_FAILURE);
00068 }
00069 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
00070 fprintf(stderr, "The month must be in the range 1 to 12\n");
00071 exit(EXIT_FAILURE);
00072 }
00073 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
00074 fprintf(stderr, "The day must be in the range 1 to 31\n");
00075 exit(EXIT_FAILURE);
00076 }
00077
00078 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
00079 fprintf(stderr, "The hour must be in the range 0-23\n");
00080 exit(EXIT_FAILURE);
00081 }
00082
00083 if (tm.tm_min < 0 || tm.tm_min > 59) {
00084 fprintf(stderr, "The minute must be in the range 0-59\n");
00085 exit(EXIT_FAILURE);
00086 }
00087
00088 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
00089 fprintf(stderr, "The second must be in the range 0-59\n");
00090 exit(EXIT_FAILURE);
00091 }
00092
00093 }
00094
00095 void
00096 strip_dnssec_records(ldns_zone *zone)
00097 {
00098 ldns_rr_list *new_list;
00099 ldns_rr *cur_rr;
00100
00101 new_list = ldns_rr_list_new();
00102
00103 while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(zone)))) {
00104 if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG ||
00105 ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC
00106 ) {
00107
00108 ldns_rr_free(cur_rr);
00109 } else {
00110 ldns_rr_list_push_rr(new_list, cur_rr);
00111 }
00112 }
00113 ldns_rr_list_free(ldns_zone_rrs(zone));
00114 ldns_zone_set_rrs(zone, new_list);
00115 }
00116
00117 int
00118 main(int argc, char *argv[])
00119 {
00120 const char *zonefile_name;
00121 FILE *zonefile = NULL;
00122 uint32_t default_ttl = LDNS_DEFAULT_TTL;
00123 int line_nr = 0;
00124 int c;
00125 int argi;
00126 ENGINE *engine = NULL;
00127
00128 ldns_zone *orig_zone;
00129 ldns_rr_list *orig_rrs = NULL;
00130 ldns_rr *orig_soa = NULL;
00131 ldns_dnssec_zone *signed_zone;
00132
00133 const char *keyfile_name_base;
00134 char *keyfile_name;
00135 FILE *keyfile = NULL;
00136 ldns_key *key = NULL;
00137 ldns_rr *pubkey, *pubkey_gen;
00138 ldns_key_list *keys;
00139 size_t key_i;
00140 ldns_status s;
00141 size_t i;
00142 ldns_rr_list *added_rrs;
00143
00144 bool leave_old_dnssec_data = false;
00145
00146 char *outputfile_name = NULL;
00147 FILE *outputfile;
00148
00149
00150 char *eng_key_l;
00151 size_t eng_key_id_len;
00152 char *eng_key_id;
00153 int eng_key_algo;
00154
00155 bool use_nsec3 = false;
00156
00157 uint8_t nsec3_algorithm = 1;
00158
00159 size_t nsec3_iterations_cmd = 1;
00160 uint16_t nsec3_iterations = 1;
00161 uint8_t nsec3_salt_length = 0;
00162 uint8_t *nsec3_salt = NULL;
00163
00164
00165
00166
00167 struct tm tm;
00168 uint32_t inception;
00169 uint32_t expiration;
00170 ldns_rdf *origin = NULL;
00171 uint32_t ttl = 0;
00172 ldns_rr_class class = LDNS_RR_CLASS_IN;
00173
00174 char *prog = strdup(argv[0]);
00175 ldns_status result;
00176
00177 inception = 0;
00178 expiration = 0;
00179
00180 keys = ldns_key_list_new();
00181
00182 OPENSSL_config(NULL);
00183
00184 while ((c = getopt(argc, argv, "a:e:f:i:k:lno:s:t:v:E:K:")) != -1) {
00185 switch (c) {
00186 case 'a':
00187 nsec3_algorithm = (uint8_t) atoi(optarg);
00188 break;
00189 case 'e':
00190
00191
00192
00193
00194 memset(&tm, 0, sizeof(tm));
00195
00196 if (strlen(optarg) == 8 &&
00197 sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
00198 ) {
00199 tm.tm_year -= 1900;
00200 tm.tm_mon--;
00201 check_tm(tm);
00202 expiration = (uint32_t) mktime_from_utc(&tm);
00203 } else if (strlen(optarg) == 14 &&
00204 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)
00205 ) {
00206 tm.tm_year -= 1900;
00207 tm.tm_mon--;
00208 check_tm(tm);
00209 expiration = (uint32_t) mktime_from_utc(&tm);
00210 } else {
00211 expiration = (uint32_t) atol(optarg);
00212 }
00213 break;
00214 case 'f':
00215 outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
00216 strncpy(outputfile_name, optarg, MAX_FILENAME_LEN);
00217 break;
00218 case 'i':
00219 memset(&tm, 0, sizeof(tm));
00220
00221 if (strlen(optarg) == 8 &&
00222 sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
00223 ) {
00224 tm.tm_year -= 1900;
00225 tm.tm_mon--;
00226 check_tm(tm);
00227 inception = (uint32_t) mktime_from_utc(&tm);
00228 } else if (strlen(optarg) == 14 &&
00229 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)
00230 ) {
00231 tm.tm_year -= 1900;
00232 tm.tm_mon--;
00233 check_tm(tm);
00234 inception = (uint32_t) mktime_from_utc(&tm);
00235 } else {
00236 inception = (uint32_t) atol(optarg);
00237 }
00238 break;
00239 case 'l':
00240 leave_old_dnssec_data = true;
00241 break;
00242 case 'n':
00243 use_nsec3 = true;
00244 break;
00245 case 'o':
00246 if (ldns_str2rdf_dname(&origin, optarg) != LDNS_STATUS_OK) {
00247 fprintf(stderr, "Bad origin, not a correct domain name\n");
00248 usage(stderr, prog);
00249 exit(EXIT_FAILURE);
00250 }
00251
00252 break;
00253 case 'v':
00254 printf("zone signer version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
00255 exit(EXIT_SUCCESS);
00256 break;
00257 case 'E':
00258 if (strncmp("help", optarg, 5) == 0) {
00259 printf("help\n");
00260 exit(EXIT_SUCCESS);
00261 }
00262 ENGINE_load_openssl();
00263 ENGINE_load_builtin_engines();
00264 ENGINE_load_dynamic();
00265 ENGINE_load_cryptodev();
00266 engine = ENGINE_by_id(optarg);
00267 if (!engine) {
00268 printf("No such engine: %s\n", optarg);
00269 engine = ENGINE_get_first();
00270 printf("Available engines:\n");
00271 while (engine) {
00272 printf("%s\n", ENGINE_get_id(engine));
00273 engine = ENGINE_get_next(engine);
00274 }
00275 exit(EXIT_FAILURE);
00276 } else {
00277 if (!ENGINE_init(engine)) {
00278 printf("The engine couldn't initialize\n");
00279 exit(EXIT_FAILURE);
00280 }
00281 ENGINE_set_default_RSA(engine);
00282 ENGINE_set_default_DSA(engine);
00283 ENGINE_set_default(engine, 0);
00284 }
00285 break;
00286 case 'k':
00287 eng_key_l = index(optarg, ',');
00288 if (eng_key_l && strlen(eng_key_l) > 1) {
00289 if (eng_key_l > optarg) {
00290 eng_key_id_len = (size_t) (eng_key_l - optarg);
00291 eng_key_id = malloc(eng_key_id_len + 1);
00292 memcpy(eng_key_id, optarg, eng_key_id_len);
00293 eng_key_id[eng_key_id_len] = '\0';
00294 } else {
00295
00296 eng_key_id = NULL;
00297 }
00298
00299 eng_key_algo = atoi(eng_key_l + 1);
00300
00301 printf("Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo);
00302
00303 if (expiration != 0) {
00304 ldns_key_set_expiration(key, expiration);
00305 }
00306 if (inception != 0) {
00307 ldns_key_set_inception(key, inception);
00308 }
00309
00310 s = ldns_key_new_frm_engine(&key, engine, eng_key_id, eng_key_algo);
00311 if (s == LDNS_STATUS_OK) {
00312
00313 switch (ldns_key_algorithm(key)) {
00314 case LDNS_SIGN_RSAMD5:
00315 case LDNS_SIGN_RSASHA1:
00316 case LDNS_SIGN_RSASHA1_NSEC3:
00317 case LDNS_SIGN_RSASHA256:
00318 case LDNS_SIGN_RSASHA256_NSEC3:
00319 case LDNS_SIGN_RSASHA512:
00320 case LDNS_SIGN_RSASHA512_NSEC3:
00321 case LDNS_SIGN_DSA:
00322 case LDNS_SIGN_DSA_NSEC3:
00323 ldns_key_list_push_key(keys, key);
00324
00325
00326 break;
00327 default:
00328 fprintf(stderr, "Warning, key not suitable for signing, ignoring key with algorithm %u\n", ldns_key_algorithm(key));
00329 break;
00330 }
00331 } else {
00332 printf("Error reading key '%s' from engine: %s\n", eng_key_id, ldns_get_errorstr_by_id(s));
00333 printf("The available key id's are:\n");
00334 printf("TODO\n");
00335 exit(EXIT_FAILURE);
00336 }
00337
00338 if (eng_key_id) {
00339 free(eng_key_id);
00340 }
00341 } else {
00342 printf("Error: bad engine key specification (should be: -k <id>,<algorithm>)).\n");
00343 exit(EXIT_FAILURE);
00344 }
00345
00346 break;
00347 case 'K':
00348 printf("Not implemented yet\n");
00349 exit(EXIT_FAILURE);
00350 break;
00351 case 's':
00352 if (strlen(optarg) % 2 != 0) {
00353 fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
00354 exit(EXIT_FAILURE);
00355 }
00356 nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
00357 nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length);
00358 for (c = 0; c < (int) strlen(optarg); c += 2) {
00359 if (isxdigit(optarg[c]) && isxdigit(optarg[c+1])) {
00360 nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
00361 ldns_hexdigit_to_int(optarg[c+1]);
00362 } else {
00363 fprintf(stderr, "Salt value is not valid hex data.\n");
00364 exit(EXIT_FAILURE);
00365 }
00366 }
00367
00368 break;
00369 case 't':
00370 nsec3_iterations_cmd = (size_t) atol(optarg);
00371 if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) {
00372 fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
00373 exit(EXIT_FAILURE);
00374 }
00375 nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
00376 break;
00377 default:
00378 usage(stderr, prog);
00379 exit(EXIT_SUCCESS);
00380 }
00381 }
00382
00383 argc -= optind;
00384 argv += optind;
00385
00386 if (argc < 1) {
00387 printf("Error: not enough arguments\n");
00388 usage(stdout, prog);
00389 exit(EXIT_FAILURE);
00390 } else {
00391 zonefile_name = argv[0];
00392 }
00393
00394
00395
00396 zonefile = fopen(zonefile_name, "r");
00397
00398 printf("[XX] Reading zone file\n");
00399 if (!zonefile) {
00400 fprintf(stderr, "Error: unable to read %s (%s)\n", zonefile_name, strerror(errno));
00401 exit(EXIT_FAILURE);
00402 } else {
00403 s = ldns_zone_new_frm_fp_l(&orig_zone, zonefile, origin, ttl, class, &line_nr);
00404 if (s != LDNS_STATUS_OK) {
00405 fprintf(stderr, "Zone not read, error: %s at %s line %d\n",
00406 ldns_get_errorstr_by_id(s),
00407 zonefile_name, line_nr);
00408 exit(EXIT_FAILURE);
00409 } else {
00410 orig_soa = ldns_zone_soa(orig_zone);
00411 if (!orig_soa) {
00412 fprintf(stderr, "Error reading zonefile: missing SOA record\n");
00413 exit(EXIT_FAILURE);
00414 }
00415 orig_rrs = ldns_zone_rrs(orig_zone);
00416 if (!orig_rrs) {
00417 fprintf(stderr, "Error reading zonefile: no resource records\n");
00418 exit(EXIT_FAILURE);
00419 }
00420 }
00421 fclose(zonefile);
00422 }
00423
00424 if (!origin) {
00425 origin = ldns_rr_owner(orig_soa);
00426 }
00427
00428
00429 argi = 1;
00430 while (argi < argc) {
00431 keyfile_name_base = argv[argi];
00432 keyfile_name = LDNS_XMALLOC(char, strlen(keyfile_name_base) + 9);
00433 snprintf(keyfile_name,
00434 strlen(keyfile_name_base) + 9,
00435 "%s.private",
00436 keyfile_name_base);
00437 keyfile = fopen(keyfile_name, "r");
00438 line_nr = 0;
00439 if (!keyfile) {
00440 fprintf(stderr,
00441 "Error: unable to read %s: %s\n",
00442 keyfile_name,
00443 strerror(errno));
00444 } else {
00445 s = ldns_key_new_frm_fp_l(&key, keyfile, &line_nr);
00446 fclose(keyfile);
00447 if (s == LDNS_STATUS_OK) {
00448
00449
00450
00451 if (expiration != 0) {
00452 ldns_key_set_expiration(key, expiration);
00453 }
00454 if (inception != 0) {
00455 ldns_key_set_inception(key, inception);
00456 }
00457
00458 LDNS_FREE(keyfile_name);
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 pubkey_gen = ldns_key2rr(key);
00470
00471 if (verbosity >= 2) {
00472 fprintf(stderr,
00473 "Looking for key with keytag %u or %u\n",
00474 (unsigned int) ldns_calc_keytag(pubkey_gen),
00475 (unsigned int) ldns_calc_keytag(pubkey_gen)+1
00476 );
00477 }
00478 for (key_i = 0;
00479 key_i < ldns_rr_list_rr_count(orig_rrs);
00480 key_i++) {
00481 pubkey = ldns_rr_list_rr(orig_rrs, key_i);
00482 if (ldns_rr_get_type(pubkey) == LDNS_RR_TYPE_DNSKEY &&
00483 (ldns_calc_keytag(pubkey)
00484 ==
00485 ldns_calc_keytag(pubkey_gen) ||
00486
00487 ldns_calc_keytag(pubkey)
00488 ==
00489 ldns_calc_keytag(pubkey_gen) + 1)
00490 ) {
00491
00492 if (verbosity >= 2) {
00493 fprintf(stderr, "Found it in the zone!\n");
00494 }
00495 goto found;
00496 }
00497 }
00498
00499 keyfile_name = LDNS_XMALLOC(char,
00500 strlen(keyfile_name_base) + 5);
00501 snprintf(keyfile_name,
00502 strlen(keyfile_name_base) + 5,
00503 "%s.key",
00504 keyfile_name_base);
00505 if (verbosity >= 2) {
00506 fprintf(stderr, "Trying to read %s\n", keyfile_name);
00507 }
00508 keyfile = fopen(keyfile_name, "r");
00509 line_nr = 0;
00510 if (keyfile) {
00511 if (ldns_rr_new_frm_fp_l(&pubkey,
00512 keyfile,
00513 &default_ttl,
00514 NULL,
00515 NULL,
00516 &line_nr) ==
00517 LDNS_STATUS_OK) {
00518 ldns_key_set_pubkey_owner(key, ldns_rdf_clone(ldns_rr_owner(pubkey)));
00519 ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0)));
00520 ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
00521 }
00522 ldns_zone_push_rr(orig_zone, ldns_rr_clone(pubkey));
00523 ldns_rr_free(pubkey);
00524 fclose(keyfile);
00525 goto found;
00526 }
00527
00528
00529
00530 if (verbosity >= 2) {
00531 fprintf(stderr, "Not in zone, no .key file, generating DNSKEY from .private\n");
00532 }
00533 ldns_zone_push_rr(orig_zone, pubkey_gen);
00534
00535
00536 found:
00537 ldns_rr_free(pubkey_gen);
00538 switch (ldns_key_algorithm(key)) {
00539 case LDNS_SIGN_RSAMD5:
00540 case LDNS_SIGN_RSASHA1:
00541 case LDNS_SIGN_RSASHA1_NSEC3:
00542 case LDNS_SIGN_RSASHA256:
00543 case LDNS_SIGN_RSASHA256_NSEC3:
00544 case LDNS_SIGN_RSASHA512:
00545 case LDNS_SIGN_RSASHA512_NSEC3:
00546 case LDNS_SIGN_DSA:
00547 case LDNS_SIGN_DSA_NSEC3:
00548 ldns_key_list_push_key(keys, key);
00549
00550
00551 break;
00552 default:
00553 fprintf(stderr, "Warning, key not suitable for signing, ignoring key from %s with algorithm %u\n", keyfile_name, ldns_key_algorithm(key));
00554 break;
00555 }
00556 LDNS_FREE(keyfile_name);
00557 } else {
00558 fprintf(stderr, "Error reading key from %s at line %d\n", argv[argi], line_nr);
00559 }
00560 }
00561
00562 argi++;
00563 }
00564
00565 if (ldns_key_list_key_count(keys) < 1) {
00566 fprintf(stderr, "Error: no keys to sign with. Aborting.\n\n");
00567 usage(stderr, prog);
00568 exit(EXIT_FAILURE);
00569 }
00570
00571
00572 for (key_i = 0; key_i < ldns_key_list_key_count(keys); key_i++) {
00573 key = ldns_key_list_key(keys, key_i);
00574 if (!ldns_key_pubkey_owner(key)) {
00575 ldns_key_set_pubkey_owner(key, ldns_rdf_clone(origin));
00576 pubkey = ldns_key2rr(key);
00577 ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0)));
00578 ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
00579
00580 printf("Derived DNSKEY RR:\n");
00581 ldns_rr_print(stdout, pubkey);
00582 }
00583 }
00584
00585 printf("[XX] convert to dnssec zone\n");
00586 signed_zone = ldns_dnssec_zone_new();
00587 if (ldns_dnssec_zone_add_rr(signed_zone, ldns_zone_soa(orig_zone)) !=
00588 LDNS_STATUS_OK) {
00589 fprintf(stderr, "Error adding SOA to dnssec zone, skipping record\n");
00590 }
00591
00592 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(orig_zone)); i++) {
00593 if (ldns_dnssec_zone_add_rr(signed_zone,
00594 ldns_rr_list_rr(ldns_zone_rrs(orig_zone),
00595 i)) !=
00596 LDNS_STATUS_OK) {
00597 fprintf(stderr, "Error adding RR to dnssec zone");
00598 fprintf(stderr, ", skipping record:\n");
00599 ldns_rr_print(stderr,
00600 ldns_rr_list_rr(ldns_zone_rrs(orig_zone), i));
00601 }
00602 }
00603
00604
00605 added_rrs = ldns_rr_list_new();
00606
00607 if (use_nsec3) {
00608 result = ldns_dnssec_zone_sign_nsec3(signed_zone,
00609 added_rrs,
00610 keys,
00611 ldns_dnssec_default_replace_signatures,
00612 NULL,
00613 nsec3_algorithm,
00614 0,
00615 nsec3_iterations,
00616 nsec3_salt_length,
00617 nsec3_salt);
00618 } else {
00619 result = ldns_dnssec_zone_sign(signed_zone,
00620 added_rrs,
00621 keys,
00622 ldns_dnssec_default_replace_signatures,
00623 NULL);
00624 }
00625 if (result != LDNS_STATUS_OK) {
00626 fprintf(stderr, "Error signing zone: %s\n",
00627 ldns_get_errorstr_by_id(result));
00628 }
00629
00630 if (!outputfile_name) {
00631 outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
00632 snprintf(outputfile_name, MAX_FILENAME_LEN, "%s.signed", zonefile_name);
00633 }
00634
00635 if (signed_zone) {
00636 outputfile = fopen(outputfile_name, "w");
00637 if (!outputfile) {
00638 fprintf(stderr, "Unable to open %s for writing: %s\n", outputfile_name, strerror(errno));
00639 } else {
00640 ldns_dnssec_zone_print(outputfile, signed_zone);
00641 fclose(outputfile);
00642 }
00643
00644
00645
00646 } else {
00647 fprintf(stderr, "Error signing zone.\n");
00648
00649 #ifdef HAVE_SSL
00650 if (ERR_peek_error()) {
00651 ERR_load_crypto_strings();
00652 ERR_print_errors_fp(stderr);
00653 ERR_free_strings();
00654 }
00655 #endif
00656 exit(EXIT_FAILURE);
00657 }
00658
00659 ldns_dnssec_zone_free(signed_zone);
00660 ldns_key_list_free(keys);
00661 ldns_zone_deep_free(orig_zone);
00662 ldns_rr_list_deep_free(added_rrs);
00663
00664 LDNS_FREE(outputfile_name);
00665
00666 CRYPTO_cleanup_all_ex_data();
00667
00668 free(prog);
00669 exit(EXIT_SUCCESS);
00670 }