From 46ff06341bc9aca85fb9fe2aa7060c782734cdbf Mon Sep 17 00:00:00 2001 From: Lucas Date: Tue, 14 Dec 2021 13:14:08 +0000 Subject: [PATCH] ldnssec-keygen: rewrite and refactor to use subcommands instead of flags --- ldnssec-keygen.c | 347 ++++++++++++++++++++++++++++------------------- 1 file changed, 206 insertions(+), 141 deletions(-) diff --git a/ldnssec-keygen.c b/ldnssec-keygen.c index 7c95c59..b54b09f 100644 --- a/ldnssec-keygen.c +++ b/ldnssec-keygen.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -27,68 +28,57 @@ usage(void) { const char *p = getprogname(); - fprintf(stderr, "Usage:\n" - "\t%s [-b bits] algorithm\n" - "\t%s -n [-d domain]\n" - "\t%s -r [-a algorithm] [-d domain] [-k] ds|dnskey\n", - p, p, p); + 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 int -print_filename_main(const char *domain, int argc, char *argv[]) +static void +cmd_dnskey_usage(void) { - ldns_key *key; - ldns_rdf *rdf_dname; - ldns_status s; - char *str; - int line_nr; - - if (argc != 0) - usage(); - - 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", ldns_get_errorstr_by_id(s)); - - ldns_key_set_pubkey_owner(key, rdf_dname); - - str = ldns_key_get_file_base_name(key); - if (str == NULL) - errx(1, "ldns_key_get_file_base_name"); - printf("%s\n", str); - - free(str); - ldns_key_deep_free(key); - - return 0; + fprintf(stderr, "usage: %s dnskey [-d domain] [-k]\n", getprogname()); + exit(1); } -static int -print_record_main(ldns_hash hash, int ksk, const char *domain, int argc, - char *argv[]) +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; + ldns_rr *dnskey_rr, *ds_rr = NULL; ldns_rdf *rdf_dname; ldns_status s; - const char *type; char *str; uint16_t flags; - int line_nr, do_ds; - - if (argc != 1) - usage(); - type = argv[0]; - - do_ds = strcasecmp(type, "DS") == 0; - if (strcasecmp(type, "DNSKEY") != 0 && !do_ds) - errx(1, "unsupport RR type %s", type); + int do_ds, line_nr; s = ldns_key_new_frm_fp_l(&key, stdin, &line_nr); if (s != LDNS_STATUS_OK) @@ -97,10 +87,11 @@ print_record_main(ldns_hash hash, int ksk, const char *domain, int argc, s = ldns_str2rdf_dname(&rdf_dname, domain); if (s != LDNS_STATUS_OK) - errx(1, "ldns_str2rdf_dname: %s", ldns_get_errorstr_by_id(s)); + errx(1, "ldns_str2rdf_dname: %s: %s", domain, + ldns_get_errorstr_by_id(s)); flags = LDNS_KEY_ZONE_KEY; - if (ksk) + if (sep) flags |= LDNS_KEY_SEP_KEY; ldns_key_set_pubkey_owner(key, rdf_dname); @@ -110,44 +101,170 @@ print_record_main(ldns_hash hash, int ksk, const char *domain, int argc, if (dnskey_rr == NULL) errx(1, "ldns_key2rr"); - ds_rr = NULL; - if (do_ds) { - ds_rr = ldns_key_rr2ds(dnskey_rr, hash); - if (ds_rr == NULL) - errx(1, "ldns_key_rr2ds"); - } + 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); + 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 -keygen_main(uint16_t bits, int argc, char *argv[]) +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; - if (argc != 1) - usage(); + 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; - alg = ldns_get_signing_algorithm_by_name(argv[0]); - /* - * 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, "unsupported algorithm %s", argv[0]); + if (argc != 0) + cmd_gen_usage(); key = ldns_key_new_frm_algorithm(alg, bits); if (key == NULL) @@ -159,6 +276,7 @@ keygen_main(uint16_t bits, int argc, char *argv[]) errx(1, "ldns_key2str"); fputs(str, stdout); + free(str); ldns_key_deep_free(key); return 0; @@ -167,78 +285,25 @@ keygen_main(uint16_t bits, int argc, char *argv[]) int main(int argc, char *argv[]) { - const ldns_lookup_table *lt; - ldns_key *key; - ldns_signing_algorithm alg; - ldns_hash hash_alg; - const char *errstr, *domain; - long long n; - int ch, rc; - int aflag, bflag, dflag, kflag, nflag, rflag; - uint16_t bits; + const char *cmd; + int rc; - aflag = bflag = dflag = kflag = nflag = rflag = 0; - hash_alg = LDNS_SHA256; - bits = 0; - domain = "."; - while ((ch = getopt(argc, argv, "a:b:d:knr")) != -1) { - switch (ch) { - case 'a': - aflag = 1; - hash_alg = ldnssec_get_hash_algorithm_by_name(optarg); - if (!ldns_lookup_by_id(ldnssec_hashes, hash_alg)) - errx(1, "-a: unsupported algorithm: %s", - optarg); - break; - case 'b': - bflag = 1; - n = strtonum(optarg, 0, UINT16_MAX, &errstr); - if (errstr != NULL) - errx(1, "-b: bits is %s: %s", errstr, optarg); - bits = n; - break; - case 'd': - dflag = 1; - domain = optarg; - break; - case 'k': - kflag = 1; - break; - case 'n': - nflag = 1; - break; - case 'r': - rflag = 1; - break; - default: - usage(); - } - } - argc -= optind; - argv += optind; - - if (bflag && (aflag || dflag || kflag || nflag || rflag)) - errx(1, "-b is mutually exclusive with -d, -k, -n and -r"); - if (aflag && !rflag) - errx(1, "can't use -a without -r"); - if (aflag && nflag) - errx(1, "-a and -n are mutually exclusive"); - if (dflag && !(nflag || rflag)) - errx(1, "can't use -d without -n or -r"); - if (kflag && !rflag) - errx(1, "can't use -k without -r"); - if (kflag && nflag) - errx(1, "-k and -n are mutually exclusive"); - if (nflag && rflag) - errx(1, "-n and -r are mutually exclusive"); + if (argc < 2) + usage(); + cmd = argv[1]; rc = 1; - if (nflag) - rc = print_filename_main(domain, argc, argv); - else if (rflag) - rc = print_record_main(hash_alg, kflag, domain, argc, argv); + 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 - rc = keygen_main(bits, argc, argv); + usage(); return rc; }