commit
6f48d8b947
17 changed files with 854 additions and 0 deletions
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code |
||||
|
||||
CC0 1.0 Universal |
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE |
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN |
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS |
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES |
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS |
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM |
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED |
||||
HEREUNDER. |
||||
|
||||
Statement of Purpose |
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer |
||||
exclusive Copyright and Related Rights (defined below) upon the creator |
||||
and subsequent owner(s) (each and all, an "owner") of an original work of |
||||
authorship and/or a database (each, a "Work"). |
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for |
||||
the purpose of contributing to a commons of creative, cultural and |
||||
scientific works ("Commons") that the public can reliably and without fear |
||||
of later claims of infringement build upon, modify, incorporate in other |
||||
works, reuse and redistribute as freely as possible in any form whatsoever |
||||
and for any purposes, including without limitation commercial purposes. |
||||
These owners may contribute to the Commons to promote the ideal of a free |
||||
culture and the further production of creative, cultural and scientific |
||||
works, or to gain reputation or greater distribution for their Work in |
||||
part through the use and efforts of others. |
||||
|
||||
For these and/or other purposes and motivations, and without any |
||||
expectation of additional consideration or compensation, the person |
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she |
||||
is an owner of Copyright and Related Rights in the Work, voluntarily |
||||
elects to apply CC0 to the Work and publicly distribute the Work under its |
||||
terms, with knowledge of his or her Copyright and Related Rights in the |
||||
Work and the meaning and intended legal effect of CC0 on those rights. |
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be |
||||
protected by copyright and related or neighboring rights ("Copyright and |
||||
Related Rights"). Copyright and Related Rights include, but are not |
||||
limited to, the following: |
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, |
||||
communicate, and translate a Work; |
||||
ii. moral rights retained by the original author(s) and/or performer(s); |
||||
iii. publicity and privacy rights pertaining to a person's image or |
||||
likeness depicted in a Work; |
||||
iv. rights protecting against unfair competition in regards to a Work, |
||||
subject to the limitations in paragraph 4(a), below; |
||||
v. rights protecting the extraction, dissemination, use and reuse of data |
||||
in a Work; |
||||
vi. database rights (such as those arising under Directive 96/9/EC of the |
||||
European Parliament and of the Council of 11 March 1996 on the legal |
||||
protection of databases, and under any national implementation |
||||
thereof, including any amended or successor version of such |
||||
directive); and |
||||
vii. other similar, equivalent or corresponding rights throughout the |
||||
world based on applicable law or treaty, and any national |
||||
implementations thereof. |
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention |
||||
of, applicable law, Affirmer hereby overtly, fully, permanently, |
||||
irrevocably and unconditionally waives, abandons, and surrenders all of |
||||
Affirmer's Copyright and Related Rights and associated claims and causes |
||||
of action, whether now known or unknown (including existing as well as |
||||
future claims and causes of action), in the Work (i) in all territories |
||||
worldwide, (ii) for the maximum duration provided by applicable law or |
||||
treaty (including future time extensions), (iii) in any current or future |
||||
medium and for any number of copies, and (iv) for any purpose whatsoever, |
||||
including without limitation commercial, advertising or promotional |
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each |
||||
member of the public at large and to the detriment of Affirmer's heirs and |
||||
successors, fully intending that such Waiver shall not be subject to |
||||
revocation, rescission, cancellation, termination, or any other legal or |
||||
equitable action to disrupt the quiet enjoyment of the Work by the public |
||||
as contemplated by Affirmer's express Statement of Purpose. |
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason |
||||
be judged legally invalid or ineffective under applicable law, then the |
||||
Waiver shall be preserved to the maximum extent permitted taking into |
||||
account Affirmer's express Statement of Purpose. In addition, to the |
||||
extent the Waiver is so judged Affirmer hereby grants to each affected |
||||
person a royalty-free, non transferable, non sublicensable, non exclusive, |
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and |
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the |
||||
maximum duration provided by applicable law or treaty (including future |
||||
time extensions), (iii) in any current or future medium and for any number |
||||
of copies, and (iv) for any purpose whatsoever, including without |
||||
limitation commercial, advertising or promotional purposes (the |
||||
"License"). The License shall be deemed effective as of the date CC0 was |
||||
applied by Affirmer to the Work. Should any part of the License for any |
||||
reason be judged legally invalid or ineffective under applicable law, such |
||||
partial invalidity or ineffectiveness shall not invalidate the remainder |
||||
of the License, and in such case Affirmer hereby affirms that he or she |
||||
will not (i) exercise any of his or her remaining Copyright and Related |
||||
Rights in the Work or (ii) assert any associated claims and causes of |
||||
action with respect to the Work, in either case contrary to Affirmer's |
||||
express Statement of Purpose. |
||||
|
||||
4. Limitations and Disclaimers. |
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned, |
||||
surrendered, licensed or otherwise affected by this document. |
||||
b. Affirmer offers the Work as-is and makes no representations or |
||||
warranties of any kind concerning the Work, express, implied, |
||||
statutory or otherwise, including without limitation warranties of |
||||
title, merchantability, fitness for a particular purpose, non |
||||
infringement, or the absence of latent or other defects, accuracy, or |
||||
the present or absence of errors, whether or not discoverable, all to |
||||
the greatest extent permissible under applicable law. |
||||
c. Affirmer disclaims responsibility for clearing rights of other persons |
||||
that may apply to the Work or any use thereof, including without |
||||
limitation any person's Copyright and Related Rights in the Work. |
||||
Further, Affirmer disclaims responsibility for obtaining any necessary |
||||
consents, permissions or other rights required for any use of the |
||||
Work. |
||||
d. Affirmer understands and acknowledges that Creative Commons is not a |
||||
party to this document and has no duty or obligation with respect to |
||||
this CC0 or use of the Work. |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
# 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
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
.POSIX: |
||||
.SUFFIXES: |
||||
.SUFFIXES: .o .c |
||||
|
||||
P = ldnssec-utils |
||||
V = 0.0 |
||||
|
||||
LIBHDR = util.h |
||||
LIBOBJ = util.o |
||||
|
||||
BIN = ldnssec-keygen ldnssec-sign-dnskey |
||||
BINEX = ex-print-zone |
||||
OBJ = ${BIN:=.o} ${BINEX:=.o} ${LIBOBJ} |
||||
SRC = ${OBJ:.o=.c} |
||||
DIST = COPYING Makefile ${LIBHDR} ${SRC} |
||||
|
||||
LDNS_INCS = -I/usr/local/include |
||||
LDNS_LIBS = -L/usr/local/lib -lldns |
||||
|
||||
.o: |
||||
${CC} ${LDFLAGS} -o $@ $@.o ${LIBOBJ} ${LDNS_LIBS} |
||||
|
||||
.c.o: |
||||
${CC} ${CFLAGS} ${LDNS_INCS} -c $< |
||||
|
||||
all: ${BINEX} ${BIN} |
||||
|
||||
clean: |
||||
rm -f ${BIN} ${BINEX} ${OBJ} ${P}-${V}.tgz |
||||
|
||||
dist: clean |
||||
pax -ws ',^,${P}-${V}/,' ${DIST} | gzip >${P}-${V}.tgz |
||||
|
||||
install: all |
||||
mkdir -p ${PREFIX}/bin |
||||
cp -f ${BIN} ${PREFIX}/bin |
||||
cd ${PREFIX}/bin && chmod 555 ${BIN} |
||||
|
||||
uninstall: |
||||
cd ${PREFIX}/bin && rm -f ${BIN} |
||||
|
||||
util.o: util.h |
||||
|
||||
ldnssec-keygen: ldnssec-keygen.o ${LIBOBJ} |
||||
ldnssec-sign-dnskey: ldnssec-sign-dnskey.o ${LIBOBJ} |
||||
ex-print-zone: ex-print-zone.o ${LIBOBJ} |
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
ldnssec-utils |
||||
============= |
||||
|
||||
Lucas' DNSSEC utils, built around LDNS[0]. |
||||
|
||||
[0]: https://nlnetlabs.nl/projects/ldns/about/ |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
example. IN DS 38127 13 2 45e1fdf3338cedce4676be9014a6b46604e00688be95f7a8854f541930be65b4 |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
example. IN DNSKEY 257 3 13 r84HU+lP18H53xF6ZsOUGCGmvon0Gfkr5BgIof4KBFQ7hluFqnf0gF45xEzxr/o+NxksGmOeOKRVzNEABP3mLw== ;{id = 38127 (ksk), size = 256b} |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
Private-key-format: v1.2 |
||||
Algorithm: 13 (ECDSAP256SHA256) |
||||
PrivateKey: lM2XFN/WiR0wWTrpC7oDAYbQoDV8DGcA/w/kHq9F5pw= |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
example. IN DS 57357 13 2 d65b3fd9c6a5d30eb9a5ab83149216116de9ab9e1f1c15255b37d79a8d64b8a9 |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
example. IN DNSKEY 257 3 13 1egQYIooCJBCelV2nEvGGn+YnSQlb4Hv6vdahRgsnnFTRlOCDk8YHN01E86tT+Q3weB4wmjiSlvu6hRfPC4rWA== ;{id = 57357 (ksk), size = 256b} |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
Private-key-format: v1.2 |
||||
Algorithm: 13 (ECDSAP256SHA256) |
||||
PrivateKey: GuF9VrZ71HDIlLIEyeGthrab8q1rlm4A5cMMPPMAQwk= |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
example. IN DNSKEY 256 3 13 t5+0WPq6TFtVmrmvLH6EOYftEFPyz1/M+gRA8NGwlqKzoCSjQ66TuM73c5DohVql/KUqdqfiVm/Hw7sT12Ypew== ;{id = 58312 (zsk), size = 256b} |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
Private-key-format: v1.2 |
||||
Algorithm: 13 (ECDSAP256SHA256) |
||||
PrivateKey: ECpe5kwRfHNVeiTLl+VbFMnOiQqW65LgVNwv7N3qu/g= |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
$ORIGIN example. |
||||
@ 86400 IN SOA ns1.example. hostmaster.example. 2021120701 2h 15m 1w 30m |
||||
86400 IN NS ns1.example. |
||||
86400 IN NS ns2.example. |
||||
86400 IN MX 0 . |
||||
86400 IN TXT "v=spf1 -all" |
||||
86400 IN DNSKEY 257 3 13 1egQYIooCJBCelV2nEvGGn+YnSQlb4Hv6vdahRgsnnFTRlOCDk8YHN01E86tT+Q3weB4wmjiSlvu6hRfPC4rWA== ;{id = 57357 (ksk), size = 256b} |
||||
86400 IN DNSKEY 257 3 13 r84HU+lP18H53xF6ZsOUGCGmvon0Gfkr5BgIof4KBFQ7hluFqnf0gF45xEzxr/o+NxksGmOeOKRVzNEABP3mLw== ;{id = 38127 (ksk), size = 256b} |
||||
86400 IN DNSKEY 256 3 13 t5+0WPq6TFtVmrmvLH6EOYftEFPyz1/M+gRA8NGwlqKzoCSjQ66TuM73c5DohVql/KUqdqfiVm/Hw7sT12Ypew== ;{id = 58312 (zsk), size = 256b} |
||||
|
||||
ns1 86400 IN A 192.0.2.1 |
||||
86400 IN AAAA 2001:db8::6af:4864:a096:eb76 |
||||
ns2 86400 IN A 198.51.100.1 |
||||
86400 IN AAAA 2001:db8::5e7f:b183:4f08:217f |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 |
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/ |
||||
|
||||
#include <err.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
|
||||
#include <ldns/ldns.h> |
||||
|
||||
#include "util.h" |
||||
|
||||
static void |
||||
usage(void) |
||||
{ |
||||
fprintf(stderr, "usage: %s [-f zone]\n", getprogname()); |
||||
exit(1); |
||||
} |
||||
|
||||
int |
||||
main(int argc, char *argv[]) |
||||
{ |
||||
ldns_zone *zone; |
||||
ldns_status s; |
||||
FILE *fp; |
||||
char *filename; |
||||
int ch, line_nr; |
||||
|
||||
fp = NULL; |
||||
filename = NULL; |
||||
while ((ch = getopt(argc, argv, "f:")) != -1) { |
||||
switch (ch) { |
||||
case 'f': |
||||
if (fp != NULL) |
||||
errx(1, "-f can be used only once"); |
||||
filename = optarg; |
||||
fp = fopen(filename, "r"); |
||||
if (fp == NULL) |
||||
err(1, "fopen"); |
||||
break; |
||||
default: |
||||
usage(); |
||||
} |
||||
} |
||||
argc -= optind; |
||||
argv += optind; |
||||
|
||||
if (fp == NULL) { |
||||
filename = "(stdin)"; |
||||
fp = stdin; |
||||
} |
||||
|
||||
fatal_check_minimum_ldns_revision(); |
||||
|
||||
s = ldns_zone_new_frm_fp_l(&zone, fp, NULL, LDNS_DEFAULT_TTL, |
||||
LDNS_RR_CLASS_IN, &line_nr); |
||||
if (s != LDNS_STATUS_OK) |
||||
errx(1, "ldns_zone_new_frm_fp_l: file %s line %d: %s", |
||||
filename, line_nr, ldns_get_errorstr_by_id(s)); |
||||
if (fp != stdin) |
||||
(void)fclose(fp); |
||||
|
||||
ldns_zone_print(stdout, zone); |
||||
|
||||
ldns_zone_deep_free(zone); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,198 @@
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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 |
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/ |
||||
|
||||
#include <err.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
|
||||
#include <ldns/ldns.h> |
||||
|
||||
#include "util.h" |
||||
|
||||
static void |
||||
usage(void) |
||||
{ |
||||
const char *p = getprogname(); |
||||
|
||||
fprintf(stderr, "Usage:\n" |
||||
"\t%s [-b bits] algorithm\n" |
||||
"\t%s [-a algorithm] [-d domain] [-k] -r ds|dnskey\n", |
||||
p, p); |
||||
exit(1); |
||||
} |
||||
|
||||
static int |
||||
print_record_main(ldns_hash hash, int ksk, const char *domain, int argc, |
||||
char *argv[]) |
||||
{ |
||||
ldns_key *key; |
||||
ldns_rr *dnskey_rr, *ds_rr; |
||||
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); |
||||
|
||||
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)); |
||||
|
||||
flags = LDNS_KEY_ZONE_KEY; |
||||
if (ksk) |
||||
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"); |
||||
|
||||
ds_rr = NULL; |
||||
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); |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
static int |
||||
keygen_main(uint16_t bits, int argc, char *argv[]) |
||||
{ |
||||
ldns_key *key; |
||||
ldns_signing_algorithm alg; |
||||
char *str; |
||||
|
||||
if (argc != 1) |
||||
usage(); |
||||
|
||||
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]); |
||||
|
||||
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); |
||||
|
||||
ldns_key_deep_free(key); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
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, rflag; |
||||
uint16_t bits; |
||||
|
||||
aflag = bflag = dflag = kflag = rflag = 0; |
||||
hash_alg = LDNS_SHA256; |
||||
bits = 0; |
||||
domain = "."; |
||||
while ((ch = getopt(argc, argv, "a:b:d:kr")) != -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 'r': |
||||
rflag = 1; |
||||
break; |
||||
default: |
||||
usage(); |
||||
} |
||||
} |
||||
argc -= optind; |
||||
argv += optind; |
||||
|
||||
if (bflag && (aflag || dflag || rflag || kflag)) |
||||
errx(1, "-b is mutually exclusive with -d, -k and -r"); |
||||
if (aflag && !rflag) |
||||
errx(1, "can't use -a without -r"); |
||||
if (dflag && !rflag) |
||||
errx(1, "can't use -d without -r"); |
||||
if (kflag && !rflag) |
||||
errx(1, "can't use -k without -r"); |
||||
|
||||
rc = 1; |
||||
if (rflag) |
||||
rc = print_record_main(hash_alg, kflag, domain, argc, argv); |
||||
else |
||||
rc = keygen_main(bits, argc, argv); |
||||
|
||||
return rc; |
||||
} |
@ -0,0 +1,272 @@
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* 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 |
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/ |
||||
|
||||
#include <err.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
|
||||
#include <ldns/ldns.h> |
||||
|
||||
#include "util.h" |
||||
|
||||
#define DEFAULT_DURATION (30 * 86400) /* 30 days */ |
||||
|
||||
static int |
||||
extend_key_from_zone(ldns_key *k, const ldns_zone *z) |
||||
{ |
||||
ldns_rr_list *rrs; |
||||
ldns_rr *soa, *key_rr; |
||||
size_t i; |
||||
int match = 0; |
||||
|
||||
soa = ldns_zone_soa(z); |
||||
rrs = ldns_zone_rrs(z); |
||||
key_rr = ldns_key2rr(k); |
||||
if (key_rr == NULL) |
||||
errx(1, "ldns_key2rr"); |
||||
for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { |
||||
ldns_rr *rr; |
||||
ldns_rdf *owner_rdf; |
||||
|
||||
rr = ldns_rr_list_rr(rrs, i); |
||||
if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY || |
||||
ldns_rdf_compare(ldns_rr_dnskey_protocol(rr), |
||||
ldns_rr_dnskey_protocol(key_rr)) != 0 || |
||||
ldns_rdf_compare(ldns_rr_dnskey_algorithm(rr), |
||||
ldns_rr_dnskey_algorithm(key_rr)) != 0 || |
||||
ldns_rdf_compare(ldns_rr_dnskey_key(rr), |
||||
ldns_rr_dnskey_key(key_rr)) != 0) |
||||
continue; |
||||
|
||||
/* key and DNSKEY have the same pubkey and algorithm */ |
||||
owner_rdf = ldns_rdf_clone(ldns_rr_owner(rr)); |
||||
if (owner_rdf == NULL) |
||||
errx(1, "ldns_rdf_clone"); |
||||
ldns_key_set_pubkey_owner(k, owner_rdf); |
||||
ldns_key_set_origttl(k, ldns_rr_ttl(rr)); |
||||
ldns_key_set_keytag(k, ldns_calc_keytag(rr)); |
||||
ldns_key_set_flags(k, |
||||
ldns_rdf2native_int16(ldns_rr_dnskey_flags(rr))); |
||||
match = 1; |
||||
break; |
||||
} |
||||
ldns_rr_free(key_rr); |
||||
|
||||
return match; |
||||
} |
||||
|
||||
static int |
||||
parse_datetime(const char *buf, struct tm *tm) |
||||
{ |
||||
char *s; |
||||
time_t t; |
||||
|
||||
t = time(NULL); |
||||
if (t == (time_t)-1) |
||||
err(1, "time"); |
||||
if (gmtime_r(&t, tm) == NULL) |
||||
errx(1, "gmtime_r"); |
||||
|
||||
/* attempt to parse as YYYYMMDDhhmmss */ |
||||
s = strptime(buf, "%Y %m %d %H %M %S", tm); |
||||
if (s != NULL && *s == '\0') |
||||
return 1; |
||||
|
||||
/* failed; attemp to parse as YYYYMMDD */ |
||||
s = strptime(buf, "%Y %m %d", tm); |
||||
if (s != NULL && *s == '\0') |
||||
return 1; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static void |
||||
usage(void) |
||||
{ |
||||
const char *p = getprogname(); |
||||
|
||||
fprintf(stderr, "Usage:\n" |
||||
"\t%s [-d duration] [-i inception] key [key ...]\n" |
||||
"\t%s [-e expiration] [-i inception] key [key ...]\n", |
||||
p, p); |
||||
exit(1); |
||||
} |
||||
|
||||
int |
||||
main(int argc, char *argv[]) |
||||
{ |
||||
ldns_zone *zone = NULL; |
||||
ldns_dnssec_zone *dnssec_zone; |
||||
ldns_key_list *keys; |
||||
ldns_rr_list *added_rrs, *origin_rrs; |
||||
ldns_rr *origin_soa; |
||||
ldns_status s; |
||||
const char *errstr; |
||||
struct tm tm; |
||||
time_t t; |
||||
size_t i; |
||||
long long n; |
||||
uint32_t expiration, inception, duration; |
||||
int ch, line_nr; |
||||
int dflag, eflag, iflag; |
||||
|
||||
dflag = eflag = iflag = 0; |
||||
duration = DEFAULT_DURATION; |
||||
while ((ch = getopt(argc, argv, "d:e:i:")) != -1) { |
||||
switch (ch) { |
||||
case 'd': |
||||
dflag = 1; |
||||
n = strtonum(optarg, 0, UINT32_MAX, &errstr); |
||||
if (errstr != NULL) |
||||
errx(1, "-d: duration is %s: %s", errstr, |
||||
optarg); |
||||
duration = n; |
||||
break; |
||||
case 'e': |
||||
eflag = 1; |
||||
if (!parse_datetime(optarg, &tm)) |
||||
errx(1, "-e: not in YYYYMMDDhhmmss or " |
||||
"YYYYMMDD format"); |
||||
t = mktime(&tm); |
||||
if (t == (time_t)-1) |
||||
errx(1, "mktime"); |
||||
expiration = t & 0xffffffff; |
||||
break; |
||||
case 'i': |
||||
iflag = 1; |
||||
if (!parse_datetime(optarg, &tm)) |
||||
errx(1, "-i: not in YYYYMMDDhhmmss or " |
||||
"YYYYMMDD format"); |
||||
t = mktime(&tm); |
||||
if (t == (time_t)-1) |
||||
errx(1, "mktime"); |
||||
inception = t & 0xffffffff; |
||||
break; |
||||
default: |
||||
usage(); |
||||
} |
||||
} |
||||
argc -= optind; |
||||
argv += optind; |
||||
|
||||
if (dflag && eflag) |
||||
errx(1, "-d and -e are mutually exclusive"); |
||||
if (argc == 0) |
||||
usage(); |
||||
|
||||
if (!iflag) { |
||||
t = time(NULL); |
||||
if (t == (time_t)-1) |
||||
err(1, "time"); |
||||
inception = t & 0xffffffff; |
||||
} |
||||
if (!eflag) |
||||
expiration = inception + duration; |
||||
|
||||
fatal_check_minimum_ldns_revision(); |
||||
|
||||
s = ldns_zone_new_frm_fp_l(&zone, stdin, NULL, LDNS_DEFAULT_TTL, |
||||
LDNS_RR_CLASS_IN, &line_nr); |
||||
if (s != LDNS_STATUS_OK) |
||||
errx(1, "ldns_zone_new_frm_fp_l: (stdin) line %d: %s", |
||||
line_nr, ldns_get_errorstr_by_id(s)); |
||||
|
||||
origin_soa = ldns_zone_soa(zone); |
||||
if (origin_soa == NULL) |
||||
errx(1, "no SOA in zone"); |
||||
origin_rrs = ldns_zone_rrs(zone); |
||||
|
||||
dnssec_zone = ldns_dnssec_zone_new(); |
||||
if (dnssec_zone == NULL) |
||||
err(1, "ldns_dnssec_zone_new"); |
||||
s = ldns_dnssec_zone_add_rr(dnssec_zone, origin_soa); |
||||
if (s != LDNS_STATUS_OK) |
||||
errx(1, "ldns_dnssec_zone_add_rr: %s", |
||||
ldns_get_errorstr_by_id(s)); |
||||
for (i = 0; i < ldns_rr_list_rr_count(origin_rrs); i++) { |
||||
ldns_rr *rr; |
||||
|
||||
rr = ldns_rr_list_rr(origin_rrs, i); |
||||
if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY || |
||||
ldns_rdf_compare(ldns_rr_owner(rr), |
||||
ldns_rr_owner(origin_soa)) != 0) |
||||
continue; |
||||
|
||||
s = ldns_dnssec_zone_add_rr(dnssec_zone, rr); |
||||
if (s != LDNS_STATUS_OK) |
||||
errx(1, "ldns_dnssec_zone_add_rr: %s", |
||||
ldns_get_errorstr_by_id(s)); |
||||
} |
||||
|
||||
keys = ldns_key_list_new(); |
||||
if (keys == NULL) |
||||
err(1, "ldns_key_list_new"); |
||||
for (; *argv != NULL; argv++) { |
||||
ldns_key *k = NULL; |
||||
FILE *fp; |
||||
|
||||
fp = fopen(*argv, "r"); |
||||
if (fp == NULL) |
||||
err(1, "fopen: %s", *argv); |
||||
s = ldns_key_new_frm_fp_l(&k, fp, &line_nr); |
||||
(void)fclose(fp); |
||||
if (s != LDNS_STATUS_OK) |
||||
errx(1, "ldns_key_new_frm_fp_l: %s line %d: %s", |
||||
*argv, line_nr, ldns_get_errorstr_by_id(s)); |
||||
|
||||
if (!extend_key_from_zone(k, zone)) |
||||
errx(1, "no DNSKEY in zone for private key \"%s\"", |
||||
*argv); |
||||
ldns_key_set_expiration(k, expiration); |
||||
ldns_key_set_inception(k, inception); |
||||
|
||||
if (!ldns_key_list_push_key(keys, k)) |
||||
err(1, "ldns_key_list_push_key"); |
||||
} |
||||
|
||||
added_rrs = ldns_rr_list_new(); |
||||
if (added_rrs == NULL) |
||||
err(1, "ldns_rr_list_new"); |
||||
s = ldns_dnssec_zone_create_rrsigs_flg(dnssec_zone, added_rrs, keys, |
||||
ldns_dnssec_default_replace_signatures, NULL, 0); |
||||
if (s != LDNS_STATUS_OK) |
||||
errx(1, "ldns_dnssec_zone_create_rrsigs_flg: %s", |
||||
ldns_get_errorstr_by_id(s)); |
||||
|
||||
for (i = 0; i < ldns_rr_list_rr_count(added_rrs); i++) { |
||||
ldns_rr *rr; |
||||
char *str; |
||||
|
||||
rr = ldns_rr_list_rr(added_rrs, i); |
||||
if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG || |
||||
ldns_rdf2native_int16(ldns_rr_rrsig_typecovered(rr)) != |
||||
LDNS_RR_TYPE_DNSKEY) |
||||
continue; |
||||
|
||||
str = ldns_rr2str(rr); |
||||
if (str == NULL) |
||||
errx(1, "ldns_rr2str"); |
||||
fputs(str, stdout); |
||||
free(str); |
||||
} |
||||
|
||||
ldns_key_list_free(keys); |
||||
ldns_dnssec_zone_free(dnssec_zone); |
||||
ldns_zone_deep_free(zone); |
||||
ldns_rr_list_deep_free(added_rrs); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 |
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/ |
||||
|
||||
#include <err.h> |
||||
|
||||
#include <ldns/ldns.h> |
||||
|
||||
#include "util.h" |
||||
|
||||
#define MINIMUM_LDNS_VERSION "1.7.1" |
||||
#define MINIMUM_LDNS_REVISION ((1<<16)|(7<<8)|(1)) |
||||
|
||||
ldns_lookup_table ldnssec_hashes[] = { |
||||
{ LDNS_SHA1, "SHA1" }, |
||||
{ LDNS_SHA256, "SHA256" }, |
||||
{ LDNS_HASH_GOST, "GOST" }, |
||||
{ LDNS_SHA384, "SHA384" }, |
||||
{ 0, NULL }, |
||||
}; |
||||
|
||||
ldns_hash |
||||
ldnssec_get_hash_algorithm_by_name(const char *name) |
||||
{ |
||||
static ldns_lookup_table aliases[] = { |
||||
{ LDNS_SHA1, "SHA-1" }, |
||||
{ LDNS_SHA256, "SHA-256" }, |
||||
{ LDNS_SHA384, "SHA-384" }, |
||||
{ 0, NULL }, |
||||
}; |
||||
ldns_lookup_table *lt; |
||||
const char *errstr; |
||||
long long n; |
||||
|
||||
lt = ldns_lookup_by_name(ldnssec_hashes, name); |
||||
if (lt != NULL) |
||||
return lt->id; |
||||
lt = ldns_lookup_by_name(aliases, name); |
||||
if (lt != NULL) |
||||
return lt->id; |
||||
|
||||
n = strtonum(name, 0, UINT8_MAX, &errstr); |
||||
if (errstr == NULL) |
||||
return n; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void |
||||
fatal_check_minimum_ldns_revision(void) |
||||
{ |
||||
if (MINIMUM_LDNS_REVISION > LDNS_REVISION) |
||||
errx(1, "ldns version should be greater or equal than " |
||||
MINIMUM_LDNS_VERSION "; got %s instead\n", ldns_version()); |
||||
} |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 |
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/ |
||||
|
||||
#ifndef _UTIL_H_INCLUDED |
||||
#define _UTIL_H_INCLUDED |
||||
|
||||
extern ldns_lookup_table ldnssec_hashes[]; |
||||
|
||||
ldns_hash ldnssec_get_hash_algorithm_by_name(const char *); |
||||
|
||||
void fatal_check_minimum_ldns_revision(void); |
||||
|
||||
#endif /* !_UTIL_H_INCLUDED */ |
Loading…
Reference in new issue