20 #include <openssl/conf.h> 21 #include <openssl/engine.h> 24 #define MAX_FILENAME_LEN 250 28 #include <openssl/err.h> 31 usage(FILE *fp,
const char *prog) {
32 fprintf(fp,
"%s [OPTIONS] zonefile key [key [key]]\n", prog);
33 fprintf(fp,
" signs the zone with the given key(s)\n");
34 fprintf(fp,
" -b\t\tuse layout in signed zone and print comments DNSSEC records\n");
35 fprintf(fp,
" -d\t\tused keys are not added to the zone\n");
36 fprintf(fp,
" -e <date>\texpiration date\n");
37 fprintf(fp,
" -f <file>\toutput zone to file (default <name>.signed)\n");
38 fprintf(fp,
" -i <date>\tinception date\n");
39 fprintf(fp,
" -o <domain>\torigin for the zone\n");
40 fprintf(fp,
" -v\t\tprint version and exit\n");
41 fprintf(fp,
" -A\t\tsign DNSKEY with all keys instead of minimal\n");
42 fprintf(fp,
" -E <name>\tuse <name> as the crypto engine for signing\n");
43 fprintf(fp,
" \tThis can have a lot of extra options, see the manual page for more info\n");
44 fprintf(fp,
" -k <id>,<int>\tuse key id with algorithm int from engine\n");
45 fprintf(fp,
" -K <id>,<int>\tuse key id with algorithm int from engine as KSK\n");
46 fprintf(fp,
"\t\tif no key is given (but an external one is used through the engine support, it might be necessary to provide the right algorithm number.\n");
47 fprintf(fp,
" -n\t\tuse NSEC3 instead of NSEC.\n");
48 fprintf(fp,
"\t\tIf you use NSEC3, you can specify the following extra options:\n");
49 fprintf(fp,
"\t\t-a [algorithm] hashing algorithm\n");
50 fprintf(fp,
"\t\t-t [number] number of hash iterations\n");
51 fprintf(fp,
"\t\t-s [string] salt\n");
52 fprintf(fp,
"\t\t-p set the opt-out flag on all nsec3 rrs\n");
54 fprintf(fp,
" keys must be specified by their base name (usually K<name>+<alg>+<id>),\n");
55 fprintf(fp,
" i.e. WITHOUT the .private extension.\n");
56 fprintf(fp,
" If the public part of the key is not present in the zone, the DNSKEY RR\n");
57 fprintf(fp,
" will be read from the file called <base name>.key. If that does not exist,\n");
58 fprintf(fp,
" a default DNSKEY will be generated from the private key and added to the zone.\n");
59 fprintf(fp,
" A date can be a timestamp (seconds since the epoch), or of\n the form <YYYYMMdd[hhmmss]>\n");
62 static void check_tm(
struct tm tm)
64 if (tm.tm_year < 70) {
65 fprintf(stderr,
"You cannot specify dates before 1970\n");
68 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
69 fprintf(stderr,
"The month must be in the range 1 to 12\n");
72 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
73 fprintf(stderr,
"The day must be in the range 1 to 31\n");
77 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
78 fprintf(stderr,
"The hour must be in the range 0-23\n");
82 if (tm.tm_min < 0 || tm.tm_min > 59) {
83 fprintf(stderr,
"The minute must be in the range 0-59\n");
87 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
88 fprintf(stderr,
"The second must be in the range 0-59\n");
110 if (ttl1 == default_ttl) {
112 }
else if (ttl2 == default_ttl) {
117 "warning: changing non-default TTL %u to %u\n",
118 (
unsigned int) ttl2, (
unsigned int) ttl1);
132 equalize_ttls(cur_rr, rr, default_ttl);
156 fprintf(stderr,
"Found it in the zone!\n");
171 uint32_t default_ttl = zone_ttl;
175 strlen(keyfile_name_base) + 5);
176 snprintf(keyfile_name,
177 strlen(keyfile_name_base) + 5,
181 fprintf(stderr,
"Trying to read %s\n", keyfile_name);
183 keyfile = fopen(keyfile_name,
"r");
194 printf(
"Key found in file: %s\n", keyfile_name);
213 find_or_create_pubkey(
const char *keyfile_name_base,
ldns_key *key,
ldns_zone *orig_zone,
bool add_keys, uint32_t default_ttl) {
243 "Looking for key with keytag %u or %u\n",
249 pubkey = find_key_in_zone(pubkey_gen, orig_zone);
254 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
258 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
265 fprintf(stderr,
"Error %s.key has wrong name: %s\n",
276 fprintf(stderr,
"Not in zone, no .key file, generating ZSK DNSKEY from private key data\n");
284 if (add_keys && !key_in_zone) {
285 equalize_ttls_rr_list(
ldns_zone_rrs(orig_zone), pubkey, default_ttl);
316 const char *zonefile_name;
317 FILE *zonefile = NULL;
321 ENGINE *engine = NULL;
328 char *keyfile_name_base;
329 char *keyfile_name = NULL;
330 FILE *keyfile = NULL;
337 char *outputfile_name = NULL;
342 size_t eng_key_id_len;
346 bool use_nsec3 =
false;
350 bool add_keys =
true;
351 uint8_t nsec3_algorithm = 1;
352 uint8_t nsec3_flags = 0;
353 size_t nsec3_iterations_cmd = 1;
354 uint16_t nsec3_iterations = 1;
355 uint8_t nsec3_salt_length = 0;
356 uint8_t *nsec3_salt = NULL;
368 char *prog = strdup(argv[0]);
379 OPENSSL_config(NULL);
381 while ((c = getopt(argc, argv,
"a:bde:f:i:k:no:ps:t:vAE:K:")) != -1) {
384 nsec3_algorithm = (uint8_t) atoi(optarg);
385 if (nsec3_algorithm != 1) {
386 fprintf(stderr,
"Bad NSEC3 algorithm, only RSASHA1 allowed\n");
404 memset(&tm, 0,
sizeof(tm));
406 if (strlen(optarg) == 8 &&
407 sscanf(optarg,
"%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
414 }
else if (strlen(optarg) == 14 &&
415 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)
423 expiration = (uint32_t) atol(optarg);
431 memset(&tm, 0,
sizeof(tm));
433 if (strlen(optarg) == 8 &&
434 sscanf(optarg,
"%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
441 }
else if (strlen(optarg) == 14 &&
442 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)
450 inception = (uint32_t) atol(optarg);
458 fprintf(stderr,
"Bad origin, not a correct domain name\n");
474 ENGINE_load_builtin_engines();
475 ENGINE_load_dynamic();
476 ENGINE_load_cryptodev();
477 engine = ENGINE_by_id(optarg);
479 printf(
"No such engine: %s\n", optarg);
480 engine = ENGINE_get_first();
481 printf(
"Available engines:\n");
483 printf(
"%s\n", ENGINE_get_id(engine));
484 engine = ENGINE_get_next(engine);
488 if (!ENGINE_init(engine)) {
489 printf(
"The engine couldn't initialize\n");
492 ENGINE_set_default_RSA(engine);
493 ENGINE_set_default_DSA(engine);
494 ENGINE_set_default(engine, 0);
498 eng_key_l = strchr(optarg,
',');
499 if (eng_key_l && strlen(eng_key_l) > 1) {
500 if (eng_key_l > optarg) {
501 eng_key_id_len = (size_t) (eng_key_l - optarg);
502 eng_key_id = malloc(eng_key_id_len + 1);
503 memcpy(eng_key_id, optarg, eng_key_id_len);
504 eng_key_id[eng_key_id_len] =
'\0';
510 eng_key_algo = atoi(eng_key_l + 1);
512 printf(
"Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo);
535 fprintf(stderr,
"Warning, key not suitable for signing, ignoring key with algorithm %u\n",
ldns_key_algorithm(key));
538 if (expiration != 0) {
542 if (inception != 0) {
549 if (ERR_peek_error()) {
550 ERR_load_crypto_strings();
551 ERR_print_errors_fp(stderr);
562 printf(
"Error: bad engine key specification (should be: -k <id>,<algorithm>)).\n");
567 printf(
"Not implemented yet\n");
571 if (strlen(optarg) % 2 != 0) {
572 fprintf(stderr,
"Salt value is not valid hex data, not a multiple of 2 characters\n");
575 nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
577 for (c = 0; c < (int) strlen(optarg); c += 2) {
578 if (isxdigit((
int) optarg[c]) && isxdigit((
int) optarg[c+1])) {
582 fprintf(stderr,
"Salt value is not valid hex data.\n");
589 nsec3_iterations_cmd = (size_t) atol(optarg);
594 nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
606 printf(
"Error: not enough arguments\n");
610 zonefile_name = argv[0];
615 if (strncmp(zonefile_name,
"-", 2) == 0) {
623 fprintf(stderr,
"Zone not read, error: %s at stdin line %d\n",
631 "Error reading zonefile: missing SOA record\n");
637 "Error reading zonefile: no resource records\n");
642 zonefile = fopen(zonefile_name,
"r");
646 "Error: unable to read %s (%s)\n",
658 fprintf(stderr,
"Zone not read, error: %s at %s line %d\n",
660 zonefile_name, line_nr);
666 "Error reading zonefile: missing SOA record\n");
672 "Error reading zonefile: no resource records\n");
682 while (argi < argc) {
683 keyfile_name_base = argv[argi];
684 keyfile_name =
LDNS_XMALLOC(
char, strlen(keyfile_name_base) + 9);
685 snprintf(keyfile_name,
686 strlen(keyfile_name_base) + 9,
689 keyfile = fopen(keyfile_name,
"r");
693 "Error: unable to read %s: %s\n",
703 if (expiration != 0) {
706 if (inception != 0) {
714 fprintf(stderr,
"Error reading key from %s at line %d: %s\n", argv[argi], line_nr,
ldns_get_errorstr_by_id(s));
719 find_or_create_pubkey(keyfile_name_base, key,
720 orig_zone, add_keys, ttl);
726 fprintf(stderr,
"Error: no keys to sign with. Aborting.\n\n");
735 "Error adding SOA to dnssec zone, skipping record\n");
746 "Error adding RR to dnssec zone");
747 fprintf(stderr,
", skipping record:\n");
778 fprintf(stderr,
"Error signing zone: %s\n",
782 if (!outputfile_name) {
788 if (strncmp(outputfile_name,
"-", 2) == 0) {
791 outputfile = fopen(outputfile_name,
"w");
793 fprintf(stderr,
"Unable to open %s for writing: %s\n",
794 outputfile_name, strerror(errno));
797 outputfile, fmt, signed_zone);
802 fprintf(stderr,
"Error signing zone.\n");
805 if (ERR_peek_error()) {
806 ERR_load_crypto_strings();
807 ERR_print_errors_fp(stderr);
826 CRYPTO_cleanup_all_ex_data();
833 main(
int argc,
char **argv)
835 fprintf(stderr,
"ldns-signzone needs OpenSSL support, which has not been compiled in\n");
ldns_rdf * ldns_rr_rdf(const ldns_rr *rr, size_t nr)
returns the rdata field member counter.
void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist)
Set the zone's contents.
ldns_rr * ldns_zone_soa(const ldns_zone *z)
Return the soa record of a zone.
ldns_rdf * ldns_key_pubkey_owner(const ldns_key *k)
return the public key's owner
#define LDNS_COMMENT_BUBBLEBABBLE
Provide bubblebabble representation for DS RR's as comment.
int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
Compares the two dname rdf's according to the algorithm for ordering in RFC4034 Section 6...
enum ldns_enum_rr_class ldns_rr_class
bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr)
pushes an rr to an rrlist.
List or Set of Resource Records.
ldns_status ldns_str2rdf_dname(ldns_rdf **d, const char *str)
convert a dname string into wireformat
void ldns_key_set_flags(ldns_key *k, uint16_t f)
Set the key's flags.
time_t ldns_mktime_from_utc(const struct tm *tm)
Convert TM to seconds since epoch (midnight, January 1st, 1970).
#define LDNS_SIGN_DNSKEY_WITH_ZSK
dnssec_verify
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)
#define LDNS_XMALLOC(type, count)
void ldns_rr_list_deep_free(ldns_rr_list *rr_list)
frees an rr_list structure and all rrs contained therein.
ldns_rdf * ldns_rdf_clone(const ldns_rdf *rd)
clones a rdf structure.
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.
void ldns_rr_free(ldns_rr *rr)
frees an RR structure
Structure containing a dnssec zone.
void ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r)
Set the key's pubkey owner.
void ldns_rr_list_free(ldns_rr_list *rr_list)
frees an rr_list structure.
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...
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
General key structure, can contain all types of keys that are used in DNSSEC.
ldns_rr * ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr)
returns a specific rr of an rrlist.
const char * ldns_version(void)
Show the internal library version.
ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
Adds the given RR to the zone.
bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr)
push an single rr to a zone structure.
ldns_rr * ldns_rr_list_pop_rr(ldns_rr_list *rr_list)
pops the last rr from an rrlist.
uint16_t ldns_rdf2native_int16(const ldns_rdf *rd)
returns the native uint16_t representation from the rdf.
void ldns_key_set_expiration(ldns_key *k, uint32_t e)
Set the key's expiration date (seconds after epoch)
#define LDNS_NSEC3_VARS_OPTOUT_MASK
ldns_rr_list * ldns_rr_list_new(void)
creates a new rr_list structure.
Same as rr_list, but now for keys.
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.
uint16_t ldns_calc_keytag(const ldns_rr *key)
calculates a keytag of a key for use in DNSSEC.
int main(int argc, char *argv[])
void ldns_key_list_free(ldns_key_list *key_list)
Frees a key list structure.
bool ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key)
pushes a key to a keylist
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...
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
int ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2)
compares two rrs, up to the rdata.
void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
sets the ttl in the rr structure.
enum ldns_enum_status ldns_status
void ldns_key_set_inception(ldns_key *k, uint32_t i)
Set the key's inception date (seconds after epoch)
ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k)
return the signing alg of the key
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...
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.
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) ...
void ldns_key_set_keytag(ldns_key *k, uint16_t tag)
Set the key's key tag.
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.
char * ldns_rdf2str(const ldns_rdf *rdf)
Converts the data in the rdata field to presentation format and returns that as a char *...
ldns_rr_list * ldns_zone_rrs(const ldns_zone *z)
Get a list of a zone's content.
int ldns_hexdigit_to_int(char ch)
Returns the int value of the given (hex) digit.
void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
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
Resource record data field.
ldns_dnssec_zone * ldns_dnssec_zone_new(void)
Creates a new dnssec_zone structure.
size_t ldns_key_list_key_count(const ldns_key_list *key_list)
returns the number of keys in the key list
ldns_rdf * ldns_rr_owner(const ldns_rr *rr)
returns the owner name of an rr structure.
size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
returns the number of rr's in an rr_list.
#define LDNS_COMMENT_NSEC3_CHAIN
Show the unhashed owner and next owner names for NSEC3 RR's as comment.
uint16_t ldns_key_keytag(const ldns_key *k)
return the keytag
#define LDNS_COMMENT_LAYOUT
Print mark up.
const char * ldns_get_errorstr_by_id(ldns_status err)
look up a descriptive text by each error.
uint32_t ldns_rr_ttl(const ldns_rr *rr)
returns the ttl of an rr structure.
uint16_t ldns_key_flags(const ldns_key *k)
return the flag of the key
int ldns_dnssec_default_replace_signatures(ldns_rr *sig __attribute__((unused)), void *n __attribute__((unused)))
ldns_key_list * ldns_key_list_new(void)
Creates a new empty key list.
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
#define LDNS_NSEC3_MAX_ITERATIONS