24 #include <openssl/conf.h> 25 #ifndef OPENSSL_NO_ENGINE 26 #include <openssl/engine.h> 28 #include <openssl/err.h> 30 #define MAX_FILENAME_LEN 250 36 usage(FILE *fp,
const char *
prog) {
37 fprintf(fp,
"%s [OPTIONS] zonefile key [key [key]]\n",
prog);
38 fprintf(fp,
" signs the zone with the given key(s)\n");
39 fprintf(fp,
" -b\t\tuse layout in signed zone and print comments DNSSEC records\n");
40 fprintf(fp,
" -d\t\tused keys are not added to the zone\n");
41 fprintf(fp,
" -e <date>\texpiration date\n");
42 fprintf(fp,
" -f <file>\toutput zone to file (default <name>.signed)\n");
43 fprintf(fp,
" -i <date>\tinception date\n");
44 fprintf(fp,
" -o <domain>\torigin for the zone\n");
45 fprintf(fp,
" -u\t\tset SOA serial to the number of seconds since 1-1-1970\n");
46 fprintf(fp,
" -v\t\tprint version and exit\n");
47 fprintf(fp,
" -A\t\tsign DNSKEY with all keys instead of minimal\n");
48 fprintf(fp,
" -U\t\tSign with every unique algorithm in the provided keys\n");
49 #ifndef OPENSSL_NO_ENGINE 50 fprintf(fp,
" -E <name>\tuse <name> as the crypto engine for signing\n");
51 fprintf(fp,
" \tThis can have a lot of extra options, see the manual page for more info\n");
52 fprintf(fp,
" -k <algorithm>,<key>\tuse `key' with `algorithm' from engine as ZSK\n");
53 fprintf(fp,
" -K <algorithm>,<key>\tuse `key' with `algorithm' from engine as KSK\n");
55 fprintf(fp,
" -n\t\tuse NSEC3 instead of NSEC.\n");
56 fprintf(fp,
"\t\tIf you use NSEC3, you can specify the following extra options:\n");
57 fprintf(fp,
"\t\t-a [algorithm] hashing algorithm\n");
58 fprintf(fp,
"\t\t-t [number] number of hash iterations\n");
59 fprintf(fp,
"\t\t-s [string] salt\n");
60 fprintf(fp,
"\t\t-p set the opt-out flag on all nsec3 rrs\n");
62 fprintf(fp,
" keys must be specified by their base name (usually K<name>+<alg>+<id>),\n");
63 fprintf(fp,
" i.e. WITHOUT the .private extension.\n");
64 fprintf(fp,
" If the public part of the key is not present in the zone, the DNSKEY RR\n");
65 fprintf(fp,
" will be read from the file called <base name>.key. If that does not exist,\n");
66 fprintf(fp,
" a default DNSKEY will be generated from the private key and added to the zone.\n");
67 fprintf(fp,
" A date can be a timestamp (seconds since the epoch), or of\n the form <YYYYMMdd[hhmmss]>\n");
68 #ifndef OPENSSL_NO_ENGINE 69 fprintf(fp,
" For -k or -K, the algorithm can be specified as an integer or a symbolic name:" );
71 #define __LIST(x) fprintf ( fp, " %3d: %-15s", LDNS_SIGN_ ## x, # x ) 73 fprintf ( fp,
"\n " );
77 fprintf ( fp,
"\n " );
81 fprintf ( fp,
"\n " );
84 __LIST ( ECDSAP256SHA256 );
85 fprintf ( fp,
"\n " );
86 __LIST ( ECDSAP384SHA384 );
101 static void check_tm(
struct tm tm)
103 if (tm.tm_year < 70) {
104 fprintf(stderr,
"You cannot specify dates before 1970\n");
107 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
108 fprintf(stderr,
"The month must be in the range 1 to 12\n");
111 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
112 fprintf(stderr,
"The day must be in the range 1 to 31\n");
116 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
117 fprintf(stderr,
"The hour must be in the range 0-23\n");
121 if (tm.tm_min < 0 || tm.tm_min > 59) {
122 fprintf(stderr,
"The minute must be in the range 0-59\n");
126 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
127 fprintf(stderr,
"The second must be in the range 0-59\n");
149 if (ttl1 == default_ttl) {
151 }
else if (ttl2 == default_ttl) {
156 "warning: changing non-default TTL %u to %u\n",
157 (
unsigned int) ttl2, (
unsigned int) ttl1);
171 equalize_ttls(cur_rr, rr, default_ttl);
195 fprintf(stderr,
"Found it in the zone!\n");
210 uint32_t default_ttl = zone_ttl;
214 strlen(keyfile_name_base) + 5);
215 snprintf(keyfile_name,
216 strlen(keyfile_name_base) + 5,
220 fprintf(stderr,
"Trying to read %s\n", keyfile_name);
222 keyfile = fopen(keyfile_name,
"r");
233 printf(
"Key found in file: %s\n", keyfile_name);
252 find_or_create_pubkey(
const char *keyfile_name_base,
ldns_key *key,
ldns_zone *orig_zone,
bool add_keys, uint32_t default_ttl) {
282 "Looking for key with keytag %u or %u\n",
288 pubkey = find_key_in_zone(pubkey_gen, orig_zone);
293 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
297 pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
304 fprintf(stderr,
"Error %s.key has wrong name: %s\n",
315 fprintf(stderr,
"Not in zone, no .key file, generating ZSK DNSKEY from private key data\n");
323 if (add_keys && !key_in_zone) {
324 equalize_ttls_rr_list(
ldns_zone_rrs(orig_zone), pubkey, default_ttl);
329 #ifndef OPENSSL_NO_ENGINE 334 parse_algspec (
const char *
const p )
339 if ( isdigit ( (
const unsigned char)*p ) ) {
340 const char *nptr = NULL;
341 const long id = strtol ( p, (
char **) &nptr, 10 );
342 return id > 0 && nptr != NULL && *nptr ==
',' ? id : 0;
346 if ( !memcmp ( # x, p, sizeof ( # x ) - 1 ) \ 347 && p [ sizeof ( # x ) - 1 ] == ',' ) { \ 348 return LDNS_SIGN_ ## x; \ 384 parse_keyspec (
const char *
const p,
386 const char **
const id )
388 const char *
const comma = strchr ( p,
',' );
390 if ( comma == NULL || !(*algorithm = parse_algspec ( p )) )
392 return comma [ 1 ] ? *
id = comma + 1 : NULL;
399 load_key (
const char *
const p, ENGINE *
const e )
402 const char *
id = NULL;
407 if ( parse_keyspec ( p, &alg, &
id ) == NULL ) {
409 "Failed to parse key specification `%s'.\n",
411 usage ( stderr,
prog );
412 exit ( EXIT_FAILURE );
432 "Algorithm %d cannot be used for signing.\n",
434 usage ( stderr,
prog );
435 exit ( EXIT_FAILURE );
438 printf (
"Engine key id: %s, algo %d\n",
id, alg );
444 ERR_print_errors_fp ( stderr );
445 exit ( EXIT_FAILURE );
461 const uint32_t inception,
462 const uint32_t expiration )
464 if ( key == NULL )
return;
471 find_or_create_pubkey (
"", key, zone, add_keys, ttl );
478 init_openssl_engine (
const char *
const id )
482 #ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS 483 ERR_load_crypto_strings();
485 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) || !defined(HAVE_OPENSSL_INIT_CRYPTO) 486 OpenSSL_add_all_algorithms();
488 if ( !OPENSSL_init_crypto ( OPENSSL_INIT_LOAD_CONFIG, NULL ) ) {
489 fprintf ( stderr,
"OPENSSL_init_crypto(3) failed.\n" );
490 ERR_print_errors_fp ( stderr );
491 exit ( EXIT_FAILURE );
495 if ( (e = ENGINE_by_id (
id )) == NULL ) {
496 fprintf ( stderr,
"ENGINE_by_id(3) failed.\n" );
497 ERR_print_errors_fp ( stderr );
498 exit ( EXIT_FAILURE );
501 if ( !ENGINE_set_default_DSA ( e ) ) {
502 fprintf ( stderr,
"ENGINE_set_default_DSA(3) failed.\n" );
503 ERR_print_errors_fp ( stderr );
504 exit ( EXIT_FAILURE );
507 if ( !ENGINE_set_default_RSA ( e ) ) {
508 fprintf ( stderr,
"ENGINE_set_default_RSA(3) failed.\n" );
509 ERR_print_errors_fp ( stderr );
510 exit ( EXIT_FAILURE );
526 shutdown_openssl ( ENGINE *
const e )
533 CONF_modules_unload ( 1 );
535 CRYPTO_cleanup_all_ex_data ();
543 const char *zonefile_name;
544 FILE *zonefile = NULL;
548 #ifndef OPENSSL_NO_ENGINE 549 ENGINE *engine = NULL;
556 char *keyfile_name_base;
557 char *keyfile_name = NULL;
558 FILE *keyfile = NULL;
560 #ifndef OPENSSL_NO_ENGINE 569 char *outputfile_name = NULL;
572 bool use_nsec3 =
false;
574 bool unixtime_serial =
false;
577 bool add_keys =
true;
578 uint8_t nsec3_algorithm = 1;
579 uint8_t nsec3_flags = 0;
580 size_t nsec3_iterations_cmd = 1;
581 uint16_t nsec3_iterations = 1;
582 uint8_t nsec3_salt_length = 0;
583 uint8_t *nsec3_salt = NULL;
600 prog = strdup(argv[0]);
606 while ((c = getopt(argc, argv,
"a:bde:f:i:k:no:ps:t:uvAUE:K:")) != -1) {
609 nsec3_algorithm = (uint8_t) atoi(optarg);
610 if (nsec3_algorithm != 1) {
611 fprintf(stderr,
"Bad NSEC3 algorithm, only RSASHA1 allowed\n");
629 memset(&tm, 0,
sizeof(tm));
631 if (strlen(optarg) == 8 &&
632 sscanf(optarg,
"%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
639 }
else if (strlen(optarg) == 14 &&
640 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)
648 expiration = (uint32_t) atol(optarg);
656 memset(&tm, 0,
sizeof(tm));
658 if (strlen(optarg) == 8 &&
659 sscanf(optarg,
"%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
666 }
else if (strlen(optarg) == 14 &&
667 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)
675 inception = (uint32_t) atol(optarg);
683 fprintf(stderr,
"Bad origin, not a correct domain name\n");
692 unixtime_serial =
true;
702 #ifndef OPENSSL_NO_ENGINE 703 engine = init_openssl_engine ( optarg );
709 #ifndef OPENSSL_NO_ENGINE 710 eng_zsk = load_key ( optarg, engine );
716 #ifndef OPENSSL_NO_ENGINE 717 eng_ksk = load_key ( optarg, engine );
721 fprintf(stderr,
"%s compiled without engine support\n" 730 if (strlen(optarg) % 2 != 0) {
731 fprintf(stderr,
"Salt value is not valid hex data, not a multiple of 2 characters\n");
734 nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
736 for (c = 0; c < (int) strlen(optarg); c += 2) {
737 if (isxdigit((
int) optarg[c]) && isxdigit((
int) optarg[c+1])) {
741 fprintf(stderr,
"Salt value is not valid hex data.\n");
748 nsec3_iterations_cmd = (size_t) atol(optarg);
753 nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
765 printf(
"Error: not enough arguments\n");
769 zonefile_name = argv[0];
774 if (strncmp(zonefile_name,
"-", 2) == 0) {
782 fprintf(stderr,
"Zone not read, error: %s at stdin line %d\n",
790 "Error reading zonefile: missing SOA record\n");
796 "Error reading zonefile: no resource records\n");
801 zonefile = fopen(zonefile_name,
"r");
805 "Error: unable to read %s (%s)\n",
817 fprintf(stderr,
"Zone not read, error: %s at %s line %d\n",
819 zonefile_name, line_nr);
825 "Error reading zonefile: missing SOA record\n");
831 "Error reading zonefile: no resource records\n");
841 while (argi < argc) {
842 keyfile_name_base = argv[argi];
843 keyfile_name =
LDNS_XMALLOC(
char, strlen(keyfile_name_base) + 9);
844 snprintf(keyfile_name,
845 strlen(keyfile_name_base) + 9,
848 keyfile = fopen(keyfile_name,
"r");
852 "Error: unable to read %s: %s\n",
862 if (expiration != 0) {
865 if (inception != 0) {
873 fprintf(stderr,
"Error reading key from %s at line %d: %s\n", argv[argi], line_nr,
ldns_get_errorstr_by_id(s));
878 find_or_create_pubkey(keyfile_name_base, key,
879 orig_zone, add_keys, ttl);
884 #ifndef OPENSSL_NO_ENGINE 895 post_process_engine_key ( keys,
904 post_process_engine_key ( keys,
914 fprintf(stderr,
"Error: no keys to sign with. Aborting.\n\n");
920 if (unixtime_serial) {
927 "Error adding SOA to dnssec zone, skipping record\n");
938 "Error adding RR to dnssec zone");
939 fprintf(stderr,
", skipping record:\n");
970 fprintf(stderr,
"Error signing zone: %s\n",
974 if (!outputfile_name) {
980 if (strncmp(outputfile_name,
"-", 2) == 0) {
983 outputfile = fopen(outputfile_name,
"w");
985 fprintf(stderr,
"Unable to open %s for writing: %s\n",
986 outputfile_name, strerror(errno));
989 outputfile, fmt, signed_zone);
994 fprintf(stderr,
"Error signing zone.\n");
997 if (ERR_peek_error()) {
998 ERR_load_crypto_strings();
999 ERR_print_errors_fp(stderr);
1018 #ifndef OPENSSL_NO_ENGINE 1019 shutdown_openssl ( engine );
1021 CRYPTO_cleanup_all_ex_data();
1030 main(
int argc __attribute__((unused)),
1031 char **argv __attribute__((unused)))
1033 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.
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
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_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
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
#define LDNS_XMALLOC(type, count)
#define LDNS_SIGN_WITH_ALL_ALGORITHMS
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_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.
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.
void ldns_rr_soa_increment_func_int(ldns_rr *soa, ldns_soa_serial_increment_func_t f, int data)
Increment the serial number of the given SOA with the given function using data as an argument for th...
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.
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)
struct ldns_struct_key::@1::@3 dnssec
Some values that influence generated signatures.
#define LDNS_NSEC3_VARS_OPTOUT_MASK
ldns_rr_list * ldns_rr_list_new(void)
creates a new rr_list structure.
ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t ttl, ldns_rr_class c __attribute__((unused)), int *line_nr)
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_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, const ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
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)
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.
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,...
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_enum_signing_algorithm
Algorithms used in dns for signing.
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
enum ldns_enum_algorithm ldns_algorithm
uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data)
Function to be used with ldns_rr_soa_increment_func or ldns_rr_soa_increment_func_int to set the soa ...