ldns-signzone.c

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

Generated on 5 Apr 2012 for ldns by  doxygen 1.6.1