mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-08 20:12:06 -04:00
Support for DST_ALG_PRIVATEDNS and DST_ALG_PRIVATEOID
The algorithm values PRIVATEDNS and PRIVATEOID are placeholders,
signifying that the actual algorithm identifier is encoded into the
key data. Keys using this mechanism are now supported.
- The algorithm values PRIVATEDNS and PRIVATEOID cannot be used to
build a key file name; dst_key_buildfilename() will assert if
they are used.
- The DST key values for private algorithms are higher than 255.
Since DST_ALG_MAXALG now exceeds 256, algorithm arrays that were
previously hardcoded to size 256 have been resized.
- New mnemonic/text conversion functions have been added.
dst_algorithm_{fromtext,totext,format} can handle algorithm
identifiers encoded in PRIVATEDNS and PRIVATEOID keys, as well
as the traditional algorithm identifiers. (Note: The existing
dns_secalg_{fromtext,totext,format} functions are similar, but
do *not* support PRIVATEDNS and PRIVATEOID. In most cases, the
new functions have taken the place of the old ones, but in a few
cases the old version is still appropriate.)
- dns_private{oid,dns}_{fromtext,totext,format} converts between
DST algorithm values and the mnemonic strings for algorithms
implemented using PRIVATEDNS or PRIVATEOID. (E.g., "RSASHA256OID").
- dst_algorithm_tosecalg() returns the DNSSEC algorithm identifier
that applies for a given DST algorithm. For PRIVATEDNS- or
PRIVATEOID- based algorithms, the result will be PRIVATEDNS or
PRIVATEOID, respectively.
- dst_algorithm_fromprivatedns() and dst_algorithm_fromprivateoid()
return the DST algorithm identifier for an encoded algorithm in
wire format, represented as in DNS name or an object identifier,
respectively.
- dst_algorithm_fromdata() is a front-end for the above; it extracts
the private algorithm identifier encoded at the begining of a
block of key or signature data, and returns the matching DST
algorithm number.
- dst_key_fromdns() and dst_key_frombuffer() now work with keys
that have PRIVATEDNS and PRIVATEOID algorithm identifiers at the
beginning.
This commit is contained in:
parent
e6f1363964
commit
6fe09d85ab
8 changed files with 303 additions and 15 deletions
|
|
@ -2107,6 +2107,8 @@ buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
|
|||
isc_result_t result;
|
||||
|
||||
REQUIRE(out != NULL);
|
||||
REQUIRE(alg != 0 && alg != DST_ALG_PRIVATEOID &&
|
||||
alg != DST_ALG_PRIVATEDNS);
|
||||
|
||||
if ((type & DST_TYPE_PRIVATE) != 0) {
|
||||
suffix = ".private";
|
||||
|
|
@ -2172,6 +2174,22 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
|||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(keyp != NULL && *keyp == NULL);
|
||||
|
||||
if (alg == DNS_KEYALG_PRIVATEDNS) {
|
||||
isc_buffer_t b = *source;
|
||||
alg = dst_algorithm_fromprivatedns(&b);
|
||||
if (alg == 0) {
|
||||
return DST_R_UNSUPPORTEDALG;
|
||||
}
|
||||
}
|
||||
|
||||
if (alg == DNS_KEYALG_PRIVATEOID) {
|
||||
isc_buffer_t b = *source;
|
||||
alg = dst_algorithm_fromprivateoid(&b);
|
||||
if (alg == 0) {
|
||||
return DST_R_UNSUPPORTEDALG;
|
||||
}
|
||||
}
|
||||
|
||||
key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
|
||||
|
||||
if (isc_buffer_remaininglength(source) > 0) {
|
||||
|
|
@ -2636,3 +2654,67 @@ dst_hmac_algorithm_totext(dst_algorithm_t alg) {
|
|||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
dns_secalg_t
|
||||
dst_algorithm_tosecalg(dst_algorithm_t dst_alg) {
|
||||
static dns_secalg_t dns_alg[DST_MAX_ALGS] = { 0 };
|
||||
|
||||
if (dst_alg < 256) {
|
||||
return dst_alg;
|
||||
}
|
||||
if (dst_alg < DST_MAX_ALGS) {
|
||||
return dns_alg[dst_alg];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivatedns(isc_buffer_t *buffer) {
|
||||
dns_fixedname_t fixed;
|
||||
dns_name_t *name = dns_fixedname_initname(&fixed);
|
||||
isc_result_t result;
|
||||
|
||||
result = dns_name_fromwire(name, buffer, DNS_DECOMPRESS_DEFAULT, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do name to dst_algorithm number mapping here.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivateoid(isc_buffer_t *buffer) {
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_remainingregion(buffer, &r);
|
||||
|
||||
/*
|
||||
* Do OID to dst_algorithm number mapping here. There is a
|
||||
* length byte followed by the OID of that length.
|
||||
*/
|
||||
if (r.length > 0 && ((unsigned int)r.base[0] + 1) <= r.length) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromdata(dns_secalg_t algorithm, unsigned char *data,
|
||||
unsigned int length) {
|
||||
isc_buffer_t b;
|
||||
switch (algorithm) {
|
||||
case DNS_KEYALG_PRIVATEDNS:
|
||||
isc_buffer_init(&b, data, length);
|
||||
isc_buffer_add(&b, length);
|
||||
return dst_algorithm_fromprivatedns(&b);
|
||||
case DNS_KEYALG_PRIVATEOID:
|
||||
isc_buffer_init(&b, data, length);
|
||||
isc_buffer_add(&b, length);
|
||||
return dst_algorithm_fromprivateoid(&b);
|
||||
default:
|
||||
return algorithm;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,12 @@ typedef enum dst_algorithm {
|
|||
DST_ALG_HMAC_LAST = DST_ALG_HMACSHA512,
|
||||
|
||||
DST_ALG_INDIRECT = 252,
|
||||
DST_ALG_PRIVATE = 254,
|
||||
DST_ALG_PRIVATEDNS = 253,
|
||||
DST_ALG_PRIVATEOID = 254,
|
||||
DST_ALG_RESERVED = 255,
|
||||
/*
|
||||
* Put PRIVATE DNS and PRIVATE OID identifiers here.
|
||||
*/
|
||||
DST_MAX_ALGS = 256,
|
||||
} dst_algorithm_t;
|
||||
|
||||
|
|
@ -206,6 +211,20 @@ dst_algorithm_supported(unsigned int alg);
|
|||
* \li false
|
||||
*/
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivateoid(isc_buffer_t *buffer);
|
||||
/*
|
||||
* Extract the dst algorithm identifier that matches
|
||||
* the OID value found at the start of 'buffer'.
|
||||
*/
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivatedns(isc_buffer_t *buf);
|
||||
/*
|
||||
* Extract the dst algorithm identifier that matches
|
||||
* the DNS name found at the start of 'buffer'.
|
||||
*/
|
||||
|
||||
bool
|
||||
dst_ds_digest_supported(unsigned int digest_type);
|
||||
/*%<
|
||||
|
|
@ -1160,3 +1179,89 @@ dst_hmac_algorithm_totext(dst_algorithm_t alg);
|
|||
* Return the name associtated with the HMAC algorithm 'alg'
|
||||
* or return "unknown".
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_fromtext(dst_algorithm_t *algp, isc_textregion_t *source);
|
||||
/*%<
|
||||
* Convert the text 'source' refers to into a DST security algorithm value.
|
||||
* The text may contain either a mnemonic algorithm name or a decimal algorithm
|
||||
* number. This supports more algorithms than 'dns_secalg_fromtext' as it
|
||||
* supports private algorithms used with PRIVATEDNS and PRIVATEOID.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'algp' is a valid pointer.
|
||||
*
|
||||
*\li 'source' is a valid text region.
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS on success
|
||||
*\li ISC_R_RANGE numeric type is out of range
|
||||
*\li DNS_R_UNKNOWN mnemonic type is unknown
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_totext(dst_algorithm_t alg, isc_buffer_t *target);
|
||||
/*%<
|
||||
* Put a textual representation of DST security algorithm 'alg'
|
||||
* into 'target'. This supports a superset of dns_secalg_totext.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'alg' is a valid dst_algorithm_t.
|
||||
*
|
||||
*\li 'target' is a valid text buffer.
|
||||
*
|
||||
* Ensures,
|
||||
* if the result is success:
|
||||
*\li The used space in 'target' is updated.
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS on success
|
||||
*\li ISC_R_NOSPACE target buffer is too small
|
||||
*/
|
||||
|
||||
#define DST_ALGORITHM_FORMATSIZE 20
|
||||
void
|
||||
dst_algorithm_format(dst_algorithm_t dst_alg, char *data, unsigned int length);
|
||||
/*%<
|
||||
* Wrapper for dst_algorithm_totext(), writing text into 'cp'
|
||||
*/
|
||||
|
||||
dns_secalg_t
|
||||
dst_algorithm_tosecalg(dst_algorithm_t dst_alg);
|
||||
/*%<
|
||||
* Return the DNSSEC algorithm identifier that applies for the DST
|
||||
* algorithm. For PRIVATEDNS and PRIVATEOID based algorithms, this
|
||||
* is PRIVATEDNS and PRIVATEOID respectively.
|
||||
*
|
||||
* Zero is returned when there is no mapping.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dst_privatedns_fromtext(dst_algorithm_t *algp, isc_textregion_t *source);
|
||||
|
||||
isc_result_t
|
||||
dns_privatedns_totext(dst_algorithm_t alg, isc_buffer_t *b);
|
||||
|
||||
void
|
||||
dns_privatedns_format(dst_algorithm_t alg, char *buf, unsigned int size);
|
||||
|
||||
isc_result_t
|
||||
dst_privateoid_fromtext(dst_algorithm_t *algp, isc_textregion_t *source);
|
||||
|
||||
isc_result_t
|
||||
dns_privateoid_totext(dst_algorithm_t alg, isc_buffer_t *b);
|
||||
|
||||
void
|
||||
dns_privateoid_format(dst_algorithm_t alg, char *buf, unsigned int size);
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromdata(dns_secalg_t algorithm, unsigned char *data,
|
||||
unsigned int length);
|
||||
/*%<
|
||||
* If 'algorithm' is PRIVATEOID or PRIVATEDNS, extract the DNSSEC private
|
||||
* algorithm encoded at the begining of data and return the DST algorithm
|
||||
* number that corresponds to it; if the algorithm is unknown to DST,
|
||||
* return 0.
|
||||
*
|
||||
* If 'algorithm' is any other value, return it directly.
|
||||
*/
|
||||
|
|
|
|||
102
lib/dns/rcode.c
102
lib/dns/rcode.c
|
|
@ -36,6 +36,8 @@
|
|||
#include <dns/secalg.h>
|
||||
#include <dns/secproto.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#define RETERR(x) \
|
||||
do { \
|
||||
isc_result_t _r = (x); \
|
||||
|
|
@ -115,6 +117,16 @@
|
|||
{ DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \
|
||||
{ DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, SENTINEL
|
||||
|
||||
/*
|
||||
* PRIVATEDNS subtypes we support.
|
||||
*/
|
||||
#define PRIVATEDNSS /* currently empty */
|
||||
|
||||
/*
|
||||
* PRIVATEOID subtypes we support.
|
||||
*/
|
||||
#define PRIVATEOIDS /* currently empty */
|
||||
|
||||
/* RFC2535 section 7.1 */
|
||||
|
||||
#define SECPROTONAMES \
|
||||
|
|
@ -150,6 +162,9 @@ static struct tbl secalgs[] = { SECALGNAMES };
|
|||
static struct tbl secprotos[] = { SECPROTONAMES };
|
||||
static struct tbl hashalgs[] = { HASHALGNAMES };
|
||||
static struct tbl dsdigests[] = { DSDIGESTNAMES };
|
||||
static struct tbl privatednss[] = { PRIVATEDNSS SENTINEL };
|
||||
static struct tbl privateoids[] = { PRIVATEOIDS SENTINEL };
|
||||
static struct tbl dstalgorithms[] = { PRIVATEDNSS PRIVATEOIDS SECALGNAMES };
|
||||
|
||||
static struct keyflag {
|
||||
const char *name;
|
||||
|
|
@ -353,6 +368,64 @@ dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) {
|
|||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_privatedns_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
RETERR(dns_mnemonic_fromtext(&value, source, privatednss, 0));
|
||||
*dstalgp = value;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_privatedns_totext(dst_algorithm_t alg, isc_buffer_t *target) {
|
||||
return dns_mnemonic_totext(alg, target, privatednss);
|
||||
}
|
||||
|
||||
void
|
||||
dns_privatedns_format(dst_algorithm_t alg, char *cp, unsigned int size) {
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(cp != NULL && size > 0);
|
||||
isc_buffer_init(&b, cp, size - 1);
|
||||
result = dns_privatedns_totext(alg, &b);
|
||||
isc_buffer_usedregion(&b, &r);
|
||||
r.base[r.length] = 0;
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
r.base[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_privateoid_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
RETERR(dns_mnemonic_fromtext(&value, source, privateoids, 0));
|
||||
*dstalgp = value;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_privateoid_totext(dst_algorithm_t alg, isc_buffer_t *target) {
|
||||
return dns_mnemonic_totext(alg, target, privateoids);
|
||||
}
|
||||
|
||||
void
|
||||
dns_privateoid_format(dst_algorithm_t alg, char *cp, unsigned int size) {
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(cp != NULL && size > 0);
|
||||
isc_buffer_init(&b, cp, size - 1);
|
||||
result = dns_privateoid_totext(alg, &b);
|
||||
isc_buffer_usedregion(&b, &r);
|
||||
r.base[r.length] = 0;
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
r.base[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
|
|
@ -579,3 +652,32 @@ dns_rdataclass_format(dns_rdataclass_t rdclass, char *array,
|
|||
strlcpy(array, "<unknown>", size);
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
RETERR(dns_mnemonic_fromtext(&value, source, dstalgorithms, 255));
|
||||
*dstalgp = value;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_totext(dst_algorithm_t alg, isc_buffer_t *target) {
|
||||
return dns_mnemonic_totext(alg, target, dstalgorithms);
|
||||
}
|
||||
|
||||
void
|
||||
dst_algorithm_format(dst_algorithm_t alg, char *cp, unsigned int size) {
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(cp != NULL && size > 0);
|
||||
isc_buffer_init(&b, cp, size - 1);
|
||||
result = dst_algorithm_totext(alg, &b);
|
||||
isc_buffer_usedregion(&b, &r);
|
||||
r.base[r.length] = 0;
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
r.base[0] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10593,7 +10593,7 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, const dns_name_t *name,
|
|||
unsigned int alg) {
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
if (alg > 255) {
|
||||
if (alg >= DST_MAX_ALGS) {
|
||||
return ISC_R_RANGE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2910,7 +2910,6 @@ check_ds_algs(dns_validator_t *val, dns_name_t *name,
|
|||
isc_result_t result;
|
||||
dns_rdata_t dsrdata = DNS_RDATA_INIT;
|
||||
dns_rdataset_current(rdataset, &dsrdata);
|
||||
|
||||
result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
|
|
|
|||
|
|
@ -22804,7 +22804,7 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
|
|||
isc_result_t result;
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_rdataset_t dnskey, cds, cdnskey;
|
||||
unsigned char algorithms[256];
|
||||
unsigned char algorithms[DST_MAX_ALGS];
|
||||
unsigned int i;
|
||||
bool empty = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -68,14 +68,14 @@ typedef struct vctx {
|
|||
dns_rdataset_t nsecsigs;
|
||||
dns_rdataset_t nsec3paramset;
|
||||
dns_rdataset_t nsec3paramsigs;
|
||||
unsigned char revoked_ksk[256];
|
||||
unsigned char revoked_zsk[256];
|
||||
unsigned char standby_ksk[256];
|
||||
unsigned char standby_zsk[256];
|
||||
unsigned char ksk_algorithms[256];
|
||||
unsigned char zsk_algorithms[256];
|
||||
unsigned char bad_algorithms[256];
|
||||
unsigned char act_algorithms[256];
|
||||
unsigned char revoked_ksk[DST_MAX_ALGS];
|
||||
unsigned char revoked_zsk[DST_MAX_ALGS];
|
||||
unsigned char standby_ksk[DST_MAX_ALGS];
|
||||
unsigned char standby_zsk[DST_MAX_ALGS];
|
||||
unsigned char ksk_algorithms[DST_MAX_ALGS];
|
||||
unsigned char zsk_algorithms[DST_MAX_ALGS];
|
||||
unsigned char bad_algorithms[DST_MAX_ALGS];
|
||||
unsigned char act_algorithms[DST_MAX_ALGS];
|
||||
isc_heap_t *expected_chains;
|
||||
isc_heap_t *found_chains;
|
||||
} vctx_t;
|
||||
|
|
@ -792,7 +792,7 @@ verifynsec3s(const vctx_t *vctx, const dns_name_t *name,
|
|||
static isc_result_t
|
||||
verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
|
||||
dns_dbnode_t *node, dst_key_t **dstkeys, size_t nkeys) {
|
||||
unsigned char set_algorithms[256] = { 0 };
|
||||
unsigned char set_algorithms[DST_MAX_ALGS] = { 0 };
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
char algbuf[DNS_SECALG_FORMATSIZE];
|
||||
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
||||
|
|
|
|||
|
|
@ -624,8 +624,8 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
|
|||
|
||||
(void)confget(maps, "keys", &keys);
|
||||
if (keys != NULL) {
|
||||
char role[256] = { 0 };
|
||||
bool warn[256][2] = { { false } };
|
||||
char role[DST_MAX_ALGS] = { 0 };
|
||||
bool warn[DST_MAX_ALGS][2] = { { false } };
|
||||
|
||||
CFG_LIST_FOREACH (keys, element) {
|
||||
cfg_obj_t *kobj = cfg_listelt_value(element);
|
||||
|
|
|
|||
Loading…
Reference in a new issue