/* * ldnssec-utils * * Written in 2021 by Lucas * * To the extent possible under law, the author(s) have dedicated all * copyright and related and neighboring rights to this software to the * public domain worldwide. This software is distributed without any * warranty. * * You should have received a copy of the CC0 Public Domain Dedication * along with this software. If not, see * . */ #include #include #include #include #include #include #include "util.h" static void usage(void) { const char *p = getprogname(); fprintf(stderr, "usage:\n" "\t%s dnskey [-d domain] [-k]\n" "\t%s ds [-a algorithm] [-d domain]\n" "\t%s filename [-d domain] [-k]\n" "\t%s gen [-a algorithm] [-b bits]\n", p, p, p, p); exit(1); } static void cmd_dnskey_usage(void) { fprintf(stderr, "usage: %s dnskey [-d domain] [-k]\n", getprogname()); exit(1); } static void cmd_ds_usage(void) { fprintf(stderr, "usage: %s ds [-a algorithm] [-d domain]\n", getprogname()); exit(1); } static void cmd_filename_usage(void) { fprintf(stderr, "usage: %s filename [-d domain] [-k]\n", getprogname()); exit(1); } static void cmd_gen_usage(void) { fprintf(stderr, "usage: %s gen [-a algorithm] [-b bits]\n", getprogname()); exit(1); } static void ds_dnskey_rr_filename_print(const char *domain, int sep, ldns_hash hash, int do_filename) { ldns_key *key; ldns_rr *dnskey_rr, *ds_rr = NULL; ldns_rdf *rdf_dname; ldns_status s; char *str; uint16_t flags; int do_ds, line_nr; s = ldns_key_new_frm_fp_l(&key, stdin, &line_nr); if (s != LDNS_STATUS_OK) errx(1, "ldns_key_new_frm_fp_l: (stdin) line %d: %s", line_nr, ldns_get_errorstr_by_id(s)); s = ldns_str2rdf_dname(&rdf_dname, domain); if (s != LDNS_STATUS_OK) errx(1, "ldns_str2rdf_dname: %s: %s", domain, ldns_get_errorstr_by_id(s)); flags = LDNS_KEY_ZONE_KEY; if (sep) flags |= LDNS_KEY_SEP_KEY; ldns_key_set_pubkey_owner(key, rdf_dname); ldns_key_set_flags(key, flags); dnskey_rr = ldns_key2rr(key); if (dnskey_rr == NULL) errx(1, "ldns_key2rr"); if (do_filename) { ldns_key_set_keytag(key, ldns_calc_keytag(dnskey_rr)); str = ldns_key_get_file_base_name(key); if (str == NULL) errx(1, "ldns_key_get_file_base_name"); printf("%s\n", str); } else { do_ds = hash != 0; if (do_ds) { ds_rr = ldns_key_rr2ds(dnskey_rr, hash); if (ds_rr == NULL) errx(1, "ldns_key_rr2ds"); } str = ldns_rr2str(do_ds ? ds_rr : dnskey_rr); if (str == NULL) errx(1, "ldns_rr2str"); fputs(str, stdout); } free(str); ldns_rr_free(dnskey_rr); ldns_rr_free(ds_rr); ldns_key_deep_free(key); } static int cmd_dnskey_main(int argc, char *argv[]) { const char *domain; int ch, sep; domain = "."; sep = 0; while ((ch = getopt(argc, argv, "d:k")) != -1) { switch (ch) { case 'd': domain = optarg; break; case 'k': sep = 1; break; default: cmd_dnskey_usage(); } } argc -= optind; argv += optind; if (argc != 0) cmd_ds_usage(); ds_dnskey_rr_filename_print(domain, sep, 0, 0); return 0; } static int cmd_ds_main(int argc, char *argv[]) { ldns_hash alg; const char *domain; int ch; alg = LDNS_SHA256; domain = "."; while ((ch = getopt(argc, argv, "a:d:")) != -1) { switch (ch) { case 'a': alg = ldnssec_get_hash_algorithm_by_name(optarg); if (ldns_lookup_by_id(ldnssec_hashes, alg) == NULL) errx(1, "-a: unsupported algorithm %s", optarg); break; case 'd': domain = optarg; break; default: cmd_ds_usage(); } } argc -= optind; argv += optind; if (argc != 0) cmd_ds_usage(); ds_dnskey_rr_filename_print(domain, 1, alg, 0); return 0; } static int cmd_filename_main(int argc, char *argv[]) { const char *domain; int ch, sep; domain = "."; sep = 0; while ((ch = getopt(argc, argv, "d:k")) != -1) { switch (ch) { case 'd': domain = optarg; break; case 'k': sep = 1; break; default: cmd_filename_usage(); } } argc -= optind; argv += optind; if (argc != 0) cmd_filename_usage(); ds_dnskey_rr_filename_print(domain, sep, 0, 1); return 0; } static int cmd_gen_main(int argc, char *argv[]) { ldns_key *key; ldns_signing_algorithm alg; const char *errstr; char *str; long long n; int ch; uint16_t bits; alg = LDNS_SIGN_ECDSAP256SHA256; bits = 0; while ((ch = getopt(argc, argv, "a:b:")) != -1) { switch (ch) { case 'a': alg = ldns_get_signing_algorithm_by_name(optarg); /* * ldns_key_algo_supported can't be used here as * it uses ldns_signing_algorithms lookup table, which * includes algorithms for TSIG. */ if (ldns_lookup_by_id(ldns_algorithms, alg) == NULL) errx(1, "-a: unsupported algorithm %s", optarg); break; case 'b': n = strtonum(optarg, 0, UINT16_MAX, &errstr); if (errstr != NULL) errx(1, "-b: bits is %s: %s", errstr, optarg); bits = n; break; default: cmd_gen_usage(); } } argc -= optind; argv += optind; if (argc != 0) cmd_gen_usage(); key = ldns_key_new_frm_algorithm(alg, bits); if (key == NULL) errx(1, "error generating key of type %s", argv[0]); /* ldns_key_print uses stdout to signal errors */ str = ldns_key2str(key); if (str == NULL) errx(1, "ldns_key2str"); fputs(str, stdout); free(str); ldns_key_deep_free(key); return 0; } int main(int argc, char *argv[]) { const char *cmd; int rc; if (argc < 2) usage(); cmd = argv[1]; rc = 1; optind = 2; if (strcmp(cmd, "ds") == 0) rc = cmd_ds_main(argc, argv); else if (strcmp(cmd, "dnskey") == 0) rc = cmd_dnskey_main(argc, argv); else if (strcmp(cmd, "filename") == 0) rc = cmd_filename_main(argc, argv); else if (strcmp(cmd, "gen") == 0) rc = cmd_gen_main(argc, argv); else usage(); return rc; }