diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 0cb12c1094..1b7bad2065 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -113,6 +113,7 @@ OBJS = callbacks.@O@ compress.@O@ db.@O@ dbiterator.@O@ \ rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \ resolver.@O@ result.@O@ version.@O@ masterdump.@O@ time.@O@ \ ttl.@O@ tcpmsg.@O@ tsig.@O@ view.@O@ journal.@O@ \ + dnssec.@O@ \ ${DSTOBJS} ${OPENSSLOBJS} ${DNSSAFEOBJS} SRCS = callbacks.c compress.c db.c dbiterator.c \ @@ -120,7 +121,7 @@ SRCS = callbacks.c compress.c db.c dbiterator.c \ name.c rbt.c rbtdb.c rbtdb64.c rdata.c \ rdatalist.c rdataset.c rdatasetiter.c rdataslab.c \ resolver.c result.c version.c masterdump.c time.c \ - ttl.c tcpmsg.c tsig.c view.c journal.c + ttl.c tcpmsg.c tsig.c view.c journal.c dnssec.c SUBDIRS = include sec TARGETS = include/dns/enumtype.h include/dns/enumclass.h \ diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c new file mode 100644 index 0000000000..317c7bd38f --- /dev/null +++ b/lib/dns/dnssec.c @@ -0,0 +1,497 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: dnssec.c,v 1.1 1999/09/01 20:50:49 bwelling Exp $ + * Principal Author: Brian Wellington + */ + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TRUSTED_KEY_MAGIC 0x54525354 /* TRST */ +#define VALID_TRUSTED_KEY(x) ((x) != NULL && (x)->magic == TRUSTED_KEY_MAGIC) + +typedef struct dns_trusted_key dns_trusted_key_t; + +struct dns_trusted_key { + unsigned int magic; /* Magic number. */ + isc_mem_t *mctx; + dst_key_t *key; /* Key */ + dns_name_t name; /* Key name */ + ISC_LINK(dns_trusted_key_t) link; +}; + +#define TYPE_SIGN 0 +#define TYPE_VERIFY 1 + +typedef struct digestctx { + dst_key_t *key; + dst_context_t context; + isc_uint8_t type; +} digestctx_t; + +/* XXXBEW If an unsorted list isn't good enough, this can be updated */ +static ISC_LIST(dns_trusted_key_t) trusted_keys; +static isc_rwlock_t trusted_key_lock; + + +static isc_result_t digest_callback(void *arg, isc_region_t *data); +static isc_result_t keyname_to_name(char *keyname, isc_mem_t *mctx, + dns_name_t *name); +static int rdata_compare_wrapper(const void *rdata1, const void *rdata2); +static isc_result_t rdataset_to_sortedarray(dns_rdataset_t *set, + isc_mem_t *mctx, + dns_rdata_t **rdata, int *nrdata); + + +static isc_result_t +digest_callback(void *arg, isc_region_t *data) { + digestctx_t *ctx = arg; + isc_result_t result; + + REQUIRE(ctx->type == TYPE_SIGN || ctx->type == TYPE_VERIFY); + + if (ctx->type == TYPE_SIGN) + result = dst_sign(DST_SIGMODE_UPDATE, ctx->key, &ctx->context, + data, NULL); + else + result = dst_verify(DST_SIGMODE_UPDATE, ctx->key, &ctx->context, + data, NULL); + return (result); +} + +/* converts the name of a key into a canonical isc_name_t */ +static isc_result_t +keyname_to_name(char *keyname, isc_mem_t *mctx, dns_name_t *name) { + isc_buffer_t src, dst; + unsigned char data[1024]; + isc_result_t ret; + dns_name_t tname; + + dns_name_init(name, NULL); + dns_name_init(&tname, NULL); + isc_buffer_init(&src, keyname, strlen(keyname), ISC_BUFFERTYPE_TEXT); + isc_buffer_add(&src, strlen(keyname)); + isc_buffer_init(&dst, data, sizeof(data), ISC_BUFFERTYPE_BINARY); + ret = dns_name_fromtext(&tname, &src, NULL, ISC_TRUE, &dst); + if (ret != ISC_R_SUCCESS) + return (ret); + + ret = dns_name_dup(&tname, mctx, name); + dns_name_downcase(name, name, NULL); + return (ret); +} + +/* make qsort happy */ +static int +rdata_compare_wrapper(const void *rdata1, const void *rdata2) { + return dns_rdata_compare((dns_rdata_t *)rdata1, (dns_rdata_t *)rdata2); +} + +/* sort the rdataset into an array */ +static isc_result_t +rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, + dns_rdata_t **rdata, int *nrdata) +{ + isc_result_t ret; + int i = 0, n = 1; + dns_rdata_t *data; + + ret = dns_rdataset_first(set); + if (ret != ISC_R_SUCCESS) + return (ret); + /* count the records */ + while (dns_rdataset_next(set) == ISC_R_SUCCESS) + n++; + + ret = dns_rdataset_first(set); + if (ret != ISC_R_SUCCESS) + return (ret); + + data = isc_mem_get(mctx, n * sizeof(dns_rdata_t)); + + /* put them in the array */ + do { + dns_rdataset_current(set, &data[i++]); + } while (dns_rdataset_next(set) == ISC_R_SUCCESS); + + /* This better not change. Should this be locked somehow? XXXBEW */ + INSIST(i == n); + + /* sort the array */ + qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); + *rdata = data; + *nrdata = n; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_dnssec_add_trusted_key(dst_key_t *key, isc_mem_t *mctx) { + dns_trusted_key_t *tkey; + isc_result_t ret; + + REQUIRE(key != NULL); + REQUIRE(mctx != NULL); + + tkey = isc_mem_get(mctx, sizeof(dns_trusted_key_t)); + if (tkey == NULL) + return (ISC_R_NOMEMORY); + + ret = keyname_to_name(dst_key_name(key), mctx, &tkey->name); + if (ret != ISC_R_SUCCESS) + goto cleanup; + + tkey->mctx = mctx; + ISC_LINK_INIT(tkey, link); + isc_rwlock_lock(&trusted_key_lock, isc_rwlocktype_write); + ISC_LIST_APPEND(trusted_keys, tkey, link); + isc_rwlock_unlock(&trusted_key_lock, isc_rwlocktype_write); + + tkey->mctx = mctx; + tkey->magic = TRUSTED_KEY_MAGIC; + return (ISC_R_SUCCESS); + +cleanup: + isc_mem_put(mctx, tkey, sizeof(dns_trusted_key_t)); + return (ret); +} + +isc_result_t +dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, + isc_stdtime_t *inception, isc_stdtime_t *expire, + isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) +{ + dns_rdata_generic_sig_t sig; + dns_rdata_t *rdatas; + int nrdatas, i; + isc_buffer_t b, sigbuf, envbuf; + isc_region_t r; + dst_context_t ctx = NULL; + isc_result_t ret; + unsigned char data[300]; + digestctx_t dctx; + u_int32_t flags; + + REQUIRE(name != NULL); + REQUIRE(set != NULL); + REQUIRE(key != NULL); + REQUIRE(inception != NULL); + REQUIRE(expire != NULL); + REQUIRE(mctx != NULL); + REQUIRE(sigrdata != NULL); + + if (*inception >= *expire) + return (DNS_R_INVALIDTIME); + + /* Is the key allowed to sign data? */ + flags = dst_key_flags(key); + if (flags & DNS_KEYTYPE_NOAUTH) + return (DNS_R_KEYUNAUTHORIZED); + if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) + return (DNS_R_KEYUNAUTHORIZED); + + sig.mctx = mctx; + sig.common.rdclass = set->rdclass; + sig.common.rdtype = dns_rdatatype_sig; + ISC_LINK_INIT(&sig.common, link); + + sig.signer = (dns_name_t *) isc_mem_get(mctx, sizeof(dns_name_t)); + if (sig.signer == NULL) { + ret = ISC_R_NOMEMORY; + } + ret = keyname_to_name(dst_key_name(key), mctx, sig.signer); + if (ret != ISC_R_SUCCESS) + goto cleanup_signer; + + sig.covered = set->type; + sig.algorithm = dst_key_alg(key); + sig.labels = dns_name_countlabels(name) - 1; + if (dns_name_iswildcard(name)) + sig.labels--; + sig.originalttl = set->ttl; + sig.timesigned = *inception; + sig.timeexpire = *expire; + sig.keyid = dst_key_id(key); + sig.siglen = dst_sig_size(key); + sig.signature = isc_mem_get(mctx, sig.siglen); + if (sig.signature == NULL) + goto cleanup_name; + + isc_buffer_init(&b, data, sizeof(data), ISC_BUFFERTYPE_BINARY); + ret = dns_rdata_fromstruct(NULL, sig.common.rdclass, + sig.common.rdtype, &sig, &b); + if (ret != ISC_R_SUCCESS) + goto cleanup_signature; + + isc_buffer_used(&b, &r); + + /* Digest the SIG rdata */ + r.length -= sig.siglen; + ret = dst_sign(DST_SIGMODE_INIT | DST_SIGMODE_UPDATE, + key, &ctx, &r, NULL); + + if (ret != ISC_R_SUCCESS) + goto cleanup_signature; + + dns_name_toregion(name, &r); + + /* create an envelope for each rdata: */ + isc_buffer_init(&envbuf, data, sizeof(data), ISC_BUFFERTYPE_BINARY); + memcpy(data, r.base, r.length); + isc_buffer_add(&envbuf, r.length); + isc_buffer_putuint16(&envbuf, set->type); + isc_buffer_putuint16(&envbuf, set->rdclass); + isc_buffer_putuint32(&envbuf, set->ttl); + + memset(&dctx, 0, sizeof(dctx)); + dctx.key = key; + dctx.context = ctx; + dctx.type = TYPE_SIGN; + + ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); + if (ret != ISC_R_SUCCESS) + goto cleanup_signature; + isc_buffer_used(&envbuf, &r); + + for (i = 0; i < nrdatas; i++) { + isc_uint16_t len; + isc_buffer_t lenbuf; + isc_region_t lenr; + + /* Digest the envelope */ + ret = dst_sign(DST_SIGMODE_UPDATE, key, &ctx, &r, NULL); + if (ret != ISC_R_SUCCESS) + goto cleanup_array; + + /* Digest the length of the rdata */ + isc_buffer_init(&lenbuf, &len, sizeof(len), + ISC_BUFFERTYPE_BINARY); + isc_buffer_putuint16(&lenbuf, rdatas[i].length); + isc_buffer_used(&lenbuf, &lenr); + ret = dst_sign(DST_SIGMODE_UPDATE, key, &ctx, &lenr, NULL); + if (ret != ISC_R_SUCCESS) + goto cleanup_array; + + /* Digest the rdata */ + ret = dns_rdata_digest(&rdatas[i], digest_callback, &dctx); + if (ret != ISC_R_SUCCESS) + goto cleanup_array; + } + + isc_buffer_init(&sigbuf, sig.signature, sig.siglen, + ISC_BUFFERTYPE_BINARY); + ret = dst_sign(DST_SIGMODE_FINAL, key, &ctx, NULL, &sigbuf); + if (ret != ISC_R_SUCCESS) + goto cleanup_array; + isc_buffer_used(&sigbuf, &r); + if (r.length != sig.siglen) { + ret = DNS_R_NOSPACE; + goto cleanup_array; + } + memcpy(sig.signature, r.base, sig.siglen); + + ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass, + sig.common.rdtype, &sig, buffer); + +cleanup_array: + isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); +cleanup_signature: + isc_mem_put(mctx, sig.signature, sig.siglen); +cleanup_name: + dns_name_free(sig.signer, mctx); +cleanup_signer: + isc_mem_put(mctx, sig.signer, sizeof(dns_name_t)); + + return (ret); +} + +isc_result_t +dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, + isc_mem_t *mctx, dns_rdata_t *sigrdata) +{ + dns_rdata_generic_sig_t sig; + dns_name_t newname; + isc_region_t r; + isc_buffer_t envbuf; + dns_rdata_t *rdatas; + int nrdatas, i; + isc_stdtime_t now; + isc_result_t ret; + unsigned char data[300]; + dst_context_t ctx; + digestctx_t dctx; + int labels; + u_int32_t flags; + + REQUIRE(name != NULL); + REQUIRE(set != NULL); + REQUIRE(key != NULL); + REQUIRE(mctx != NULL); + REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_sig); + + ret = dns_rdata_tostruct(sigrdata, &sig, mctx); + if (ret != ISC_R_SUCCESS) + return (ret); + + ret = isc_stdtime_get(&now); + if (ret != ISC_R_SUCCESS) + goto cleanup_struct; + + /* Is SIG temporally valid? */ + if (sig.timesigned > now) + return (DNS_R_SIGFUTURE); + else if (sig.timeexpire < now) + return (DNS_R_SIGEXPIRED); + + /* Is the key allowed to sign data? */ + flags = dst_key_flags(key); + if (flags & DNS_KEYTYPE_NOAUTH) + return (DNS_R_KEYUNAUTHORIZED); + if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) + return (DNS_R_KEYUNAUTHORIZED); + + /* Digest the SIG rdata (not including the signature) */ + dns_rdata_toregion(sigrdata, &r); + r.length -= sig.siglen; + if (r.length < 20) { + ret = DNS_R_RANGE; + goto cleanup_struct; + } + + ret = dst_verify(DST_SIGMODE_INIT | DST_SIGMODE_UPDATE, + key, &ctx, &r, NULL); + + /* if the name is an expanded wildcard, use the wildcard name */ + dns_name_init(&newname, NULL); + labels = dns_name_countlabels(name) - 1; + dns_name_getlabelsequence(name, labels - sig.labels, sig.labels + 1, + &newname); + dns_name_toregion(&newname, &r); + + /* create an envelope for each rdata: */ + isc_buffer_init(&envbuf, data, sizeof(data), ISC_BUFFERTYPE_BINARY); + if (labels - sig.labels > 0) { + isc_buffer_putuint8(&envbuf, 1); + isc_buffer_putuint8(&envbuf, '*'); + memcpy(data + 2, r.base, r.length); + } + else + memcpy(data, r.base, r.length); + isc_buffer_add(&envbuf, r.length); + isc_buffer_putuint16(&envbuf, set->type); + isc_buffer_putuint16(&envbuf, set->rdclass); + isc_buffer_putuint32(&envbuf, set->ttl); + + memset(&dctx, 0, sizeof(dctx)); + dctx.key = key; + dctx.context = ctx; + dctx.type = TYPE_VERIFY; + + ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); + if (ret != ISC_R_SUCCESS) + goto cleanup_struct; + isc_buffer_used(&envbuf, &r); + + for (i = 0; i < nrdatas; i++) { + isc_uint16_t len; + isc_buffer_t lenbuf; + isc_region_t lenr; + + /* Digest the envelope */ + ret = dst_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, NULL); + if (ret != ISC_R_SUCCESS) + goto cleanup_array; + + /* Digest the rdata length */ + isc_buffer_init(&lenbuf, &len, sizeof(len), + ISC_BUFFERTYPE_BINARY); + isc_buffer_putuint16(&lenbuf, rdatas[i].length); + isc_buffer_used(&lenbuf, &lenr); + + /* Digest the rdata */ + ret = dst_verify(DST_SIGMODE_UPDATE, key, &ctx, &lenr, NULL); + if (ret != ISC_R_SUCCESS) + goto cleanup_array; + ret = dns_rdata_digest(&rdatas[i], digest_callback, &dctx); + if (ret != ISC_R_SUCCESS) + goto cleanup_array; + } + + r.base = sig.signature; + r.length = sig.siglen; + ret = dst_verify(DST_SIGMODE_FINAL, key, &ctx, NULL, &r); + if (ret == DST_R_VERIFYFINALFAILURE) + ret = DNS_R_SIGINVALID; + +cleanup_array: + isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); +cleanup_struct: + dns_rdata_freestruct(&sig); + + return (ret); +} + +isc_result_t +dns_dnssec_init() { + isc_result_t ret; + + ret = isc_rwlock_init(&trusted_key_lock, 0, 0); + if (ret != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_rwlock_init() failed: %s", + isc_result_totext(ret)); + return (DNS_R_UNEXPECTED); + } + + ISC_LIST_INIT(trusted_keys); + + return (ISC_R_SUCCESS); +} + +void +dns_dnssec_destroy() { + while (!ISC_LIST_EMPTY(trusted_keys)) { + dns_trusted_key_t *key = ISC_LIST_HEAD(trusted_keys); + isc_mem_t *mctx = key->mctx; + dns_name_free(&key->name, mctx); + isc_mem_put(mctx, key, sizeof(dns_trusted_key_t)); + } +} diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h new file mode 100644 index 0000000000..aa22b8d008 --- /dev/null +++ b/lib/dns/include/dns/dnssec.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef DNS_DNSSEC_H +#define DNS_DNSSEC_H 1 + +#include +#include +#include + +#include + +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +dns_dnssec_add_trusted_key(dst_key_t *key, isc_mem_t *mctx); +/* + * Adds a key to the set of trusted keys. + * + * Requires: + * 'key' must be a valid DST_KEY * + * 'mctx' must be a valid isc_mem_t + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + */ + +isc_result_t +dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, + isc_stdtime_t *inception, isc_stdtime_t *expire, + isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata); +/* + * Generates a SIG record covering this rdataset. This has no effect + * on existing SIG records. + * + * Requires: + * 'name' (the owner name of the record) is a valid name + * 'set' is a valid rdataset + * 'key' is a valid key + * 'inception' is not NULL + * 'expire' is not NULL + * 'mctx' is not NULL + * 'buffer' is not NULL + * 'sigrdata' is not NULL + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + * ISC_R_NOSPACE + * DNS_R_INVALIDTIME - the expiration is before the inception + * DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either + * it is not a zone key or its flags prevent + * authentication) + * DST_R_* + */ + +isc_result_t +dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, + isc_mem_t *mctx, dns_rdata_t *sigrdata); +/* + * Verifies the SIG record covering this rdataset signed by a specific + * key. This does not determine if the key's owner is authorized to + * sign this record, as this requires a resolver or database. + * + * Requires: + * 'name' (the owner name of the record) is a valid name + * 'set' is a valid rdataset + * 'key' is a valid key + * 'mctx' is not NULL + * 'sigrdata' is a valid rdata containing a SIG record + * + * Returns: + * DNS_R_SUCCESS + * ISC_R_NOMEMORY + * DNS_R_RANGE - the SIG record has an invalid signature length + * DNS_R_SIGINVALID - the signature fails to verify + * DNS_R_SIGEXPIRED - the signature has expired + * DNS_R_SIGFUTURE - the signature's validity period has not begun + * DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either + * it is not a zone key or its flags prevent + * authentication) + * DST_R_* + */ + +isc_result_t +dns_dnssec_init(void); +/* + * Initializes the DNSSEC subsystem + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_UNEXPECTED + */ + +void +dns_dnssec_destroy(void); +/* + * Frees all data associated with the DNSSEC subsystem + */ + +ISC_LANG_ENDDECLS + +#endif /* DNS_DNSSEC_H */ diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index c900605670..44f2819f93 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -87,8 +87,13 @@ typedef isc_result_t dns_result_t; /* XXXRTH for legacy use only */ #define DNS_R_UPTODATE (ISC_RESULTCLASS_DNS + 37) #define DNS_R_TSIGVERIFYFAILURE (ISC_RESULTCLASS_DNS + 38) #define DNS_R_TSIGERRORSET (ISC_RESULTCLASS_DNS + 39) +#define DNS_R_SIGINVALID (ISC_RESULTCLASS_DNS + 40) +#define DNS_R_SIGEXPIRED (ISC_RESULTCLASS_DNS + 41) +#define DNS_R_SIGFUTURE (ISC_RESULTCLASS_DNS + 42) +#define DNS_R_KEYUNAUTHORIZED (ISC_RESULTCLASS_DNS + 43) +#define DNS_R_INVALIDTIME (ISC_RESULTCLASS_DNS + 44) -#define DNS_R_NRESULTS 40 /* Number of results */ +#define DNS_R_NRESULTS 45 /* Number of results */ /* * DNS wire format rcodes diff --git a/lib/dns/result.c b/lib/dns/result.c index b949feb4bf..db1417045c 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -67,6 +67,11 @@ static char *text[DNS_R_NRESULTS] = { "up to date", /* 37 */ "tsig verify failure", /* 38 */ "tsig error set in query", /* 39 */ + "SIG failed to verify", /* 40 */ + "SIG has expired", /* 41 */ + "SIG validity period has not begun", /* 42 */ + "key is unauthorized to sign data", /* 43 */ + "invalid time", /* 44 */ }; static char *rcode_text[DNS_R_NRCODERESULTS] = {