major TSIG/TKEY cleanup

This commit is contained in:
Brian Wellington 2000-01-21 20:18:41 +00:00
parent 4380033dc4
commit b984520acc
9 changed files with 387 additions and 193 deletions

View file

@ -190,6 +190,7 @@ struct dns_message {
ISC_LIST(dns_rdata_t) freerdata;
ISC_LIST(dns_rdatalist_t) freerdatalist;
dns_tsig_keyring_t *ring;
dns_rcode_t tsigstatus;
dns_rcode_t querytsigstatus;
dns_rdata_any_tsig_t *tsig;
@ -272,9 +273,7 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
* DNS message.
*
* OPT records are detected and stored in the pseudo-section "opt".
* TSIGs are detected and stored in the pseudo-section "tsig". At detection
* time, the TSIG is verified (XXX) and the message fails if the TSIG fails
* to verify.
* TSIGs are detected and stored in the pseudo-section "tsig".
*
* If 'preserve_order' is true, or if the opcode of the message is UPDATE,
* a separate dns_name_t object will be created for each RR in the message.
@ -887,6 +886,26 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer);
* the signature has not been verified yet
*/
isc_result_t
dns_message_checksig(dns_message_t *msg, dns_view_t *view);
/*
* If this message was signed, verify the signature.
*
* Requires:
*
* msg is a valid parsed message.
* view is a valid view
*
* Returns:
*
* ISC_R_SUCCESS - the message was unsigned, or the message
* was signed correctly.
*
* DNS_R_EXPECTEDTSIG - A TSIG was expected, but not seen
* DNS_R_UNEXPECTEDTSIG - A TSIG was seen but not expected
* DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify
*/
ISC_LANG_ENDDECLS
#endif /* DNS_MESSAGE_H */

View file

@ -36,15 +36,22 @@ ISC_LANG_BEGINDECLS
#define DNS_TKEYMODE_RESOLVERASSIGNED 4
#define DNS_TKEYMODE_DELETE 5
struct dns_tkey_ctx {
dst_key_t *dhkey;
dns_name_t *domain;
isc_mem_t *mctx;
};
isc_result_t
dns_tkey_init(isc_log_t *lctx, dns_c_ctx_t *cfg, isc_mem_t *mctx);
dns_tkey_init(dns_c_ctx_t *cfg, isc_mem_t *mctx, dns_tkey_ctx_t **tctx);
/*
* Obtains TKEY configuration information, including default DH key
* and default domain from the configuration, if it's not NULL.
*
* Requires:
* 'lctx' is not NULL
* 'mctx' is not NULL
* 'tctx' is not NULL
* '*tctx' is NULL
*
* Returns
* ISC_R_SUCCESS
@ -53,19 +60,26 @@ dns_tkey_init(isc_log_t *lctx, dns_c_ctx_t *cfg, isc_mem_t *mctx);
*/
void
dns_tkey_destroy(void);
dns_tkey_destroy(dns_tkey_ctx_t **tctx);
/*
* Frees all data associated with the TKEY subsystem
* Frees all data associated with the TKEY context
*
* Requires:
* 'tctx' is not NULL
* '*tctx' is not NULL
*/
isc_result_t
dns_tkey_processquery(dns_message_t *msg);
dns_tkey_processquery(dns_message_t *msg, dns_tkey_ctx_t *tctx,
dns_tsig_keyring_t *ring);
/*
* Processes a query containing a TKEY record, adding or deleting TSIG
* keys if necessary, and modifies the message to contain the response.
*
* Requires:
* 'msg' is a valid message
* 'tctx' is a valid TKEY context
* 'ring' is a valid TSIG keyring
*
* Returns
* ISC_R_SUCCESS msg was updated (the TKEY operation succeeded,
@ -117,7 +131,8 @@ dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key);
isc_result_t
dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dst_key_t *key, dns_tsigkey_t **outkey);
dst_key_t *key, isc_buffer_t *nonce,
dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring);
/*
* Processes a response to a query containing a TKEY that was
* designed to generate a shared secret using a Diffie-Hellman key
@ -129,6 +144,7 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
* 'rmsg' is a valid message (the response)
* 'key' is a valid Diffie Hellman dst key
* 'outkey' is either NULL or a pointer to NULL
* 'ring' is not NULL
*
* Returns:
* ISC_R_SUCCESS the shared key was successfully added
@ -137,7 +153,8 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
*/
isc_result_t
dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg);
dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dns_tsig_keyring_t *ring);
/*
* Processes a response to a query containing a TKEY that was
* designed to delete a shared secret. If the query was successful,
@ -146,6 +163,7 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg);
* Requires:
* 'qmsg' is a valid message (the query)
* 'rmsg' is a valid message (the response)
* 'ring' is not NULL
*
* Returns:
* ISC_R_SUCCESS the shared key was successfully deleted

View file

@ -20,7 +20,7 @@
#include <isc/types.h>
#include <isc/lang.h>
#include <isc/log.h>
#include <isc/rwlock.h>
#include <dns/types.h>
#include <dns/name.h>
@ -38,6 +38,12 @@ extern dns_name_t *dns_tsig_hmacmd5_name;
/* Default fudge value. */
#define DNS_TSIG_FUDGE 300
struct dns_tsig_keyring {
ISC_LIST(dns_tsigkey_t) keys;
isc_rwlock_t lock;
isc_mem_t *mctx;
};
struct dns_tsigkey {
/* Unlocked */
unsigned int magic; /* Magic number. */
@ -62,10 +68,11 @@ struct dns_tsigkey {
isc_result_t
dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
unsigned char *secret, int length, isc_boolean_t generated,
dns_name_t *creator, isc_mem_t *mctx, dns_tsigkey_t **key);
dns_name_t *creator, isc_mem_t *mctx,
dns_tsig_keyring_t *ring, dns_tsigkey_t **key);
/*
* Creates and saves a tsig key structure. If key is not NULL, *key
* will contain a copy of the key.
* Creates a tsig key structure and saves it in the keyring. If key is
* not NULL, *key * will contain a copy of the key.
*
* Requires:
* 'name' is a valid dns_name_t
@ -74,6 +81,7 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
* 'length' is an integer greater than 0
* 'creator' points to a valid dns_name_t or is NULL
* 'mctx' is a valid memory context
* 'ring' is a valid TSIG keyring
* 'key' or '*key' must be NULL
*
* Returns:
@ -84,12 +92,13 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
*/
void
dns_tsigkey_free(dns_tsigkey_t **key);
dns_tsigkey_free(dns_tsigkey_t **key, dns_tsig_keyring_t *ring);
/*
* Frees the tsig key structure pointed to by 'key'.
*
* Requires:
* 'key' is a valid TSIG key
* 'ring' is a valid TSIG keyring containing the key
*/
void
@ -119,7 +128,8 @@ dns_tsig_sign(dns_message_t *msg);
*/
isc_result_t
dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg);
dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
dns_tsig_keyring_t *sring, dns_tsig_keyring_t *dring);
/*
* Verifies the TSIG record in this message
*
@ -129,6 +139,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg);
* 'msg->tsigkey' is a valid TSIG key if this is a response
* 'msg->tsig' is NULL
* 'msg->querytsig' is not NULL if this is a response
* 'sring' is a valid keyring or NULL
* 'dring' is a valid keyring or NULL
*
* Returns:
* DNS_R_SUCCESS
@ -140,28 +152,9 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg);
* DNS_R_TSIGVERIFYFAILURE - the TSIG failed to verify
*/
isc_result_t
dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
/*
* Verifies the TSIG record in this continuation of a TCP response,
* if there is one.
*
* Requires:
* 'source' is a valid buffer containing the unparsed message
* 'msg' is a valid message
* 'msg->tsigkey' is a valid TSIG key
* 'msg->tsig' is NULL
* 'msg->querytsig' is not NULL
*
* Returns:
* DNS_R_SUCCESS
* ISC_R_NOMEMORY
* DNS_R_TSIGVERIFYFAILURE - the TSIG failed to verify
*/
isc_result_t
dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
dns_name_t *algorithm);
dns_name_t *algorithm, dns_tsig_keyring_t *ring);
/*
* Returns the TSIG key corresponding to this name and (possibly)
* algorithm. Also increments the key's reference counter.
@ -171,6 +164,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
* '*tsigkey' is NULL
* 'name' is a valid dns_name_t
* 'algorithm' is a valid dns_name_t or NULL
* 'ring' is a valid keyring
*
* Returns:
* ISC_R_SUCCESS
@ -179,15 +173,15 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
isc_result_t
dns_tsig_init(isc_log_t *lctx, dns_c_ctx_t *confctx, isc_mem_t *mctx);
dns_tsig_init(dns_c_ctx_t *confctx, isc_mem_t *mctx, dns_tsig_keyring_t **ring);
/*
* Initializes the TSIG subsystem. If confctx is not NULL, any
* specified keys are loaded.
*
* Requires:
* 'lctx' is not NULL
* 'mctx' is not NULL
* 'ring' is not NULL, and '*ring' is NULL
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
@ -195,9 +189,12 @@ dns_tsig_init(isc_log_t *lctx, dns_c_ctx_t *confctx, isc_mem_t *mctx);
void
dns_tsig_destroy(void);
dns_tsig_destroy(dns_tsig_keyring_t **ring);
/*
* Frees all data associated with the TSIG subsystem
*
* Requires:
* 'ring' is not NULL
*/
ISC_LANG_ENDDECLS

View file

@ -78,6 +78,8 @@ typedef struct dns_dispatch dns_dispatch_t;
typedef struct dns_dispentry dns_dispentry_t;
typedef struct dns_dispatchevent dns_dispatchevent_t;
typedef struct dns_tsigkey dns_tsigkey_t;
typedef struct dns_tsig_keyring dns_tsig_keyring_t;
typedef struct dns_tkey_ctx dns_tkey_ctx_t;
typedef struct dns_view dns_view_t;
typedef ISC_LIST(dns_view_t) dns_viewlist_t;
typedef struct dns_zone dns_zone_t;

View file

@ -88,6 +88,8 @@ struct dns_view {
isc_task_t * task;
isc_event_t resevent;
isc_event_t adbevent;
dns_tsig_keyring_t * statickeys;
dns_tsig_keyring_t * dynamickeys;
/* Locked by lock. */
unsigned int references;
unsigned int attributes;
@ -226,6 +228,26 @@ dns_view_sethints(dns_view_t *view, dns_db_t *hints);
* The hints database of 'view' is 'hints'.
*/
void
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring);
/*
* Set the view's static TSIG keys
*
* Requires:
*
* 'view' is a valid, unfrozen view, whose static TSIG keyring has not
* been set.
*
* 'ring' is a valid TSIG keyring
*
* Ensures:
*
* The static TSIG keyring of 'view' is 'ring'.
*/
isc_result_t
dns_view_addzone(dns_view_t *view, dns_zone_t *zone);
/*
@ -421,6 +443,21 @@ dns_view_load(dns_view_t *view);
* 'view' is a valid.
*/
isc_result_t
dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg);
/*
* Verifies the signature of a message.
*
* Requires:
*
* 'view' is a valid view.
* 'source' is a valid buffer containing the message
* 'msg' is a valid message
*
* Returns:
* see dns_tsig_verify()
*/
ISC_LANG_ENDDECLS
#endif /* DNS_VIEW_H */

View file

@ -38,6 +38,7 @@
#include <dns/compress.h>
#include <dns/tsig.h>
#include <dns/dnssec.h>
#include <dns/view.h>
#define DNS_MESSAGE_OPCODE_MASK 0x7800U
#define DNS_MESSAGE_OPCODE_SHIFT 11
@ -287,6 +288,7 @@ msginitprivate(dns_message_t *m)
static inline void
msginittsig(dns_message_t *m)
{
m->ring = NULL;
m->tsigstatus = m->querytsigstatus = dns_rcode_noerror;
m->tsig = m->querytsig = NULL;
m->tsigkey = NULL;
@ -455,7 +457,7 @@ msgreset(dns_message_t *msg, isc_boolean_t everything)
}
if (msg->tsigkey != NULL) {
dns_tsigkey_free(&msg->tsigkey);
dns_tsigkey_free(&msg->tsigkey, msg->ring);
msg->tsigkey = NULL;
}
@ -1317,17 +1319,9 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
if (r.length != 0)
return (DNS_R_FORMERR);
if (msg->tsigkey != NULL ||
!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_TSIG]))
if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_TSIG]) ||
!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_SIG0]))
{
if (!msg->tcp_continuation)
ret = dns_tsig_verify(source, msg);
else
ret = dns_tsig_verify_tcp(source, msg);
if (ret != DNS_R_SUCCESS)
return ret;
}
else if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_SIG0])) {
msg->saved = isc_mem_get(msg->mctx, sizeof(isc_region_t));
if (msg->saved == NULL)
return (ISC_R_NOMEMORY);
@ -2148,3 +2142,21 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
return (result);
}
isc_result_t
dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
isc_buffer_t b;
REQUIRE(DNS_MESSAGE_VALID(msg));
REQUIRE(view != NULL);
if (msg->tsigkey == NULL &&
ISC_LIST_EMPTY(msg->sections[DNS_SECTION_TSIG]))
return (ISC_R_SUCCESS);
if (msg->saved == NULL)
return (DNS_R_EXPECTEDTSIG);
isc_buffer_init(&b, msg->saved->base, msg->saved->length,
ISC_BUFFERTYPE_BINARY);
isc_buffer_add(&b, msg->saved->length);
return dns_view_checksig(view, &b, msg);
}

View file

@ -16,7 +16,7 @@
*/
/*
* $Id: tkey.c,v 1.15 1999/12/06 12:40:30 brister Exp $
* $Id: tkey.c,v 1.16 2000/01/21 20:18:36 bwelling Exp $
* Principal Author: Brian Wellington
*/
@ -31,6 +31,7 @@
#include <isc/error.h>
#include <isc/list.h>
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/result.h>
#include <isc/rwlock.h>
@ -63,12 +64,8 @@
} while (0)
static dst_key_t *tkey_dhkey = NULL;
static dns_name_t *tkey_domain = NULL;
static isc_mem_t *tkey_mctx = NULL;
isc_result_t
dns_tkey_init(isc_log_t *lctx, dns_c_ctx_t *cfg, isc_mem_t *mctx) {
dns_tkey_init(dns_c_ctx_t *cfg, isc_mem_t *mctx, dns_tkey_ctx_t **tctx) {
isc_result_t result;
char *s;
int n;
@ -76,11 +73,16 @@ dns_tkey_init(isc_log_t *lctx, dns_c_ctx_t *cfg, isc_mem_t *mctx) {
unsigned char data[1024];
dns_name_t domain;
RUNTIME_CHECK(tkey_domain == NULL);
RUNTIME_CHECK(tkey_dhkey == NULL);
REQUIRE(lctx != NULL); /* XXX lctx is now unused. */
REQUIRE(mctx != NULL);
REQUIRE(tctx != NULL);
REQUIRE(*tctx == NULL);
*tctx = isc_mem_get(mctx, sizeof(dns_tkey_ctx_t));
if (*tctx == NULL)
return (ISC_R_NOMEMORY);
(*tctx)->mctx = mctx;
(*tctx)->dhkey = NULL;
(*tctx)->domain = NULL;
if (cfg == NULL)
return (ISC_R_SUCCESS);
@ -91,47 +93,50 @@ dns_tkey_init(isc_log_t *lctx, dns_c_ctx_t *cfg, isc_mem_t *mctx) {
return (ISC_R_SUCCESS);
RETERR(dst_key_fromfile(s, n, DNS_KEYALG_DH,
DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
mctx, &tkey_dhkey));
mctx, &(*tctx)->dhkey));
s = NULL;
RETERR(dns_c_ctx_gettkeydomain(cfg, &s));
dns_name_init(&domain, NULL);
tkey_domain = (dns_name_t *) isc_mem_get(mctx, sizeof(dns_name_t));
if (tkey_domain == NULL)
(*tctx)->domain = (dns_name_t *) isc_mem_get(mctx, sizeof(dns_name_t));
if ((*tctx)->domain == NULL)
return (ISC_R_NOMEMORY);
dns_name_init(tkey_domain, NULL);
dns_name_init((*tctx)->domain, NULL);
isc_buffer_init(&b, s, strlen(s), ISC_BUFFERTYPE_TEXT);
isc_buffer_add(&b, strlen(s));
isc_buffer_init(&namebuf, data, sizeof(data), ISC_BUFFERTYPE_BINARY);
RETERR(dns_name_fromtext(&domain, &b, dns_rootname, ISC_FALSE,
&namebuf));
RETERR(dns_name_dup(&domain, mctx, tkey_domain));
tkey_mctx = mctx;
RETERR(dns_name_dup(&domain, mctx, (*tctx)->domain));
return (ISC_R_SUCCESS);
failure:
if (tkey_dhkey != NULL) {
dst_key_free(tkey_dhkey);
tkey_dhkey = NULL;
if ((*tctx)->dhkey != NULL) {
dst_key_free((*tctx)->dhkey);
(*tctx)->dhkey = NULL;
}
if (tkey_domain != NULL) {
dns_name_free(tkey_domain, mctx);
isc_mem_put(mctx, tkey_domain, sizeof(dns_name_t));
tkey_domain = NULL;
if ((*tctx)->domain != NULL) {
dns_name_free((*tctx)->domain, mctx);
isc_mem_put(mctx, (*tctx)->domain, sizeof(dns_name_t));
(*tctx)->domain = NULL;
}
return (result);
}
void
dns_tkey_destroy(void) {
if (tkey_mctx == NULL)
return;
if (tkey_dhkey != NULL)
dst_key_free(tkey_dhkey);
if (tkey_domain != NULL)
isc_mem_put(tkey_mctx, tkey_domain, sizeof(dns_name_t));
tkey_mctx = NULL;
dns_tkey_destroy(dns_tkey_ctx_t **tctx) {
isc_mem_t *mctx;
REQUIRE(tctx != NULL);
REQUIRE(*tctx != NULL);
if ((*tctx)->dhkey != NULL)
dst_key_free((*tctx)->dhkey);
if ((*tctx)->domain != NULL)
isc_mem_put((*tctx)->mctx, (*tctx)->domain, sizeof(dns_name_t));
mctx = (*tctx)->mctx;
isc_mem_put(mctx, *tctx, sizeof(dns_tkey_ctx_t));
}
static isc_result_t
@ -169,6 +174,7 @@ add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
RETERR(dns_message_gettemprdatalist(msg, &newlist));
newlist->rdclass = newrdata->rdclass;
newlist->type = newrdata->type;
newlist->covers = 0;
newlist->ttl = ttl;
ISC_LIST_INIT(newlist->rdata);
ISC_LIST_APPEND(newlist->rdata, newrdata, link);
@ -191,27 +197,59 @@ add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
dns_message_puttempname(msg, &newname);
if (newlist != NULL)
dns_message_puttemprdatalist(msg, &newlist);
if (newset != NULL)
if (newset != NULL) {
dns_rdataset_disassociate(newset);
dns_message_puttemprdataset(msg, &newset);
}
return (result);
}
static isc_result_t
compute_secret(isc_buffer_t *shared, isc_region_t *randomness,
isc_buffer_t *secret)
compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness,
isc_region_t *serverrandomness, isc_buffer_t *secret)
{
dst_context_t ctx;
isc_result_t result;
isc_region_t r;
isc_region_t r, r2;
char digests[32];
isc_buffer_t b;
unsigned int i;
isc_buffer_init(&b, digests, sizeof(digests), ISC_BUFFERTYPE_BINARY);
isc_buffer_used(shared, &r);
/* MD5 ( query data | DH value ) */
RETERR(dst_digest(DST_SIGMODE_INIT, DST_DIGEST_MD5, &ctx, NULL, NULL));
RETERR(dst_digest(DST_SIGMODE_UPDATE, DST_DIGEST_MD5, &ctx,
queryrandomness, NULL));
RETERR(dst_digest(DST_SIGMODE_UPDATE, DST_DIGEST_MD5, &ctx, &r, NULL));
if (randomness->length != 0)
RETERR(dst_digest(DST_SIGMODE_UPDATE, DST_DIGEST_MD5,
&ctx, randomness, secret));
RETERR(dst_digest(DST_SIGMODE_FINAL, DST_DIGEST_MD5, &ctx, NULL,
secret));
RETERR(dst_digest(DST_SIGMODE_FINAL, DST_DIGEST_MD5, &ctx, NULL, &b));
/* MD5 ( server data | DH value ) */
RETERR(dst_digest(DST_SIGMODE_INIT, DST_DIGEST_MD5, &ctx, NULL, NULL));
RETERR(dst_digest(DST_SIGMODE_UPDATE, DST_DIGEST_MD5, &ctx,
serverrandomness, NULL));
RETERR(dst_digest(DST_SIGMODE_UPDATE, DST_DIGEST_MD5, &ctx, &r, NULL));
RETERR(dst_digest(DST_SIGMODE_FINAL, DST_DIGEST_MD5, &ctx, NULL, &b));
/* XOR ( DH value, MD5-1 | MD5-2) */
isc_buffer_available(secret, &r);
isc_buffer_used(shared, &r2);
if (r.length < sizeof(digests) || r.length < r2.length)
return (ISC_R_NOSPACE);
if (r2.length > sizeof(digests)) {
memcpy(r.base, r2.base, r2.length);
for (i = 0; i < sizeof(digests); i++)
r.base[i] ^= digests[i];
isc_buffer_add(secret, r2.length);
}
else {
memcpy(r.base, digests, sizeof(digests));
for (i = 0; i < r2.length; i++)
r.base[i] ^= r2.base[i];
isc_buffer_add(secret, sizeof(digests));
}
failure:
return result;
@ -219,8 +257,9 @@ compute_secret(isc_buffer_t *shared, isc_region_t *randomness,
static isc_result_t
process_dhtkey(dns_message_t *msg, dns_name_t *name,
dns_rdata_generic_tkey_t *tkeyin,
dns_rdata_generic_tkey_t *tkeyout, dns_namelist_t *namelist)
dns_rdata_generic_tkey_t *tkeyin, dns_tkey_ctx_t *tctx,
dns_rdata_generic_tkey_t *tkeyout,
dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
{
isc_result_t result = ISC_R_SUCCESS;
dns_name_t *keyname, ourname, signer, *creator;
@ -229,14 +268,14 @@ process_dhtkey(dns_message_t *msg, dns_name_t *name,
isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
dst_key_t *pubkey = NULL;
isc_buffer_t ourkeybuf, ournamein, ournameout, *shared = NULL;
isc_region_t r, ourkeyr;
isc_region_t r, r2, ourkeyr;
isc_uint32_t ourttl;
unsigned char keydata[DST_KEY_MAXSIZE];
unsigned char namedata[1024];
dns_tsigkey_t *tsigkey;
unsigned int sharedsize;
isc_buffer_t randombuf, secret;
unsigned char *randomdata = NULL, secretdata[TKEY_RANDOM_AMOUNT];
unsigned char *randomdata = NULL, secretdata[256];
/* Look for a DH KEY record that will work with ours */
result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
@ -261,7 +300,7 @@ process_dhtkey(dns_message_t *msg, dns_name_t *name,
}
if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
if (dst_key_paramcompare(pubkey,
tkey_dhkey))
tctx->dhkey))
{
found_key = ISC_TRUE;
goto got_key;
@ -290,13 +329,13 @@ process_dhtkey(dns_message_t *msg, dns_name_t *name,
isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata),
ISC_BUFFERTYPE_BINARY);
RETERR(dst_key_todns(tkey_dhkey, &ourkeybuf));
RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf));
isc_buffer_used(&ourkeybuf, &ourkeyr);
dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_in,
dns_rdatatype_key, &ourkeyr);
isc_buffer_init(&ournamein, dst_key_name(tkey_dhkey),
strlen(dst_key_name(tkey_dhkey)), ISC_BUFFERTYPE_TEXT);
isc_buffer_add(&ournamein, strlen(dst_key_name(tkey_dhkey)));
isc_buffer_init(&ournamein, dst_key_name(tctx->dhkey),
strlen(dst_key_name(tctx->dhkey)), ISC_BUFFERTYPE_TEXT);
isc_buffer_add(&ournamein, strlen(dst_key_name(tctx->dhkey)));
isc_buffer_init(&ournameout, namedata, sizeof(namedata),
ISC_BUFFERTYPE_BINARY);
dns_name_init(&ourname, NULL);
@ -326,11 +365,11 @@ process_dhtkey(dns_message_t *msg, dns_name_t *name,
RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, ourttl,
namelist));
RETERR(dst_secret_size(tkey_dhkey, &sharedsize));
RETERR(dst_secret_size(tctx->dhkey, &sharedsize));
RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize,
ISC_BUFFERTYPE_BINARY));
RETERR(dst_computesecret(pubkey, tkey_dhkey, shared));
RETERR(dst_computesecret(pubkey, tctx->dhkey, shared));
isc_buffer_init(&secret, secretdata, sizeof(secretdata),
ISC_BUFFERTYPE_BINARY);
@ -345,7 +384,9 @@ process_dhtkey(dns_message_t *msg, dns_name_t *name,
RETERR(dst_random_get(TKEY_RANDOM_AMOUNT, &randombuf));
isc_buffer_used(&randombuf, &r);
RETERR(compute_secret(shared, &r, &secret));
r2.base = tkeyin->key;
r2.length = tkeyin->keylen;
RETERR(compute_secret(shared, &r2, &r, &secret));
dns_name_init(&signer, NULL);
result = dns_message_signer(msg, &signer);
@ -359,7 +400,8 @@ process_dhtkey(dns_message_t *msg, dns_name_t *name,
isc_buffer_used(&secret, &r);
tsigkey = NULL;
result = dns_tsigkey_create(name, &tkeyin->algorithm, r.base, r.length,
ISC_TRUE, creator, msg->mctx, &tsigkey);
ISC_TRUE, creator, msg->mctx, ring,
&tsigkey);
isc_buffer_free(&shared);
shared = NULL;
if (result == ISC_R_NOTFOUND) {
@ -387,6 +429,7 @@ process_dhtkey(dns_message_t *msg, dns_name_t *name,
ISC_LIST_UNLINK(*namelist, tname, link);
tset = ISC_LIST_HEAD(tname->list);
dns_rdataset_disassociate(tset);
dns_message_puttemprdataset(msg, &tset);
dns_message_puttempname(msg, &tname);
tname = next;
@ -401,6 +444,7 @@ static isc_result_t
process_deletetkey(dns_message_t *msg, dns_name_t *name,
dns_rdata_generic_tkey_t *tkeyin,
dns_rdata_generic_tkey_t *tkeyout,
dns_tsig_keyring_t *ring,
dns_namelist_t *namelist)
{
isc_result_t result;
@ -412,7 +456,7 @@ process_deletetkey(dns_message_t *msg, dns_name_t *name,
tkeyout = tkeyout;
namelist = namelist;
result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm);
result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
if (result != ISC_R_SUCCESS)
tkeyout->error = dns_tsigerror_badname;
@ -448,13 +492,15 @@ process_deletetkey(dns_message_t *msg, dns_name_t *name,
*/
dns_tsigkey_setdeleted(tsigkey);
/* Release the reference */
dns_tsigkey_free(&tsigkey);
dns_tsigkey_free(&tsigkey, ring);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_tkey_processquery(dns_message_t *msg) {
dns_tkey_processquery(dns_message_t *msg, dns_tkey_ctx_t *tctx,
dns_tsig_keyring_t *ring)
{
isc_result_t result = ISC_R_SUCCESS;
dns_rdata_generic_tkey_t tkeyin, tkeyout;
dns_name_t *qname, *name, *keyname;
@ -463,6 +509,10 @@ dns_tkey_processquery(dns_message_t *msg) {
isc_buffer_t *dynbuf = NULL;
dns_namelist_t namelist;
REQUIRE(msg != NULL);
REQUIRE(tctx != NULL);
REQUIRE(ring != NULL);
/* Need to do this to determine if this should be freed later */
memset(&tkeyin, 0, sizeof(dns_rdata_generic_tkey_t));
@ -570,16 +620,16 @@ dns_tkey_processquery(dns_message_t *msg) {
goto failure;
}
}
result = dns_name_concatenate(&prefix, tkey_domain,
result = dns_name_concatenate(&prefix, tctx->domain,
keyname, buf);
dns_message_takebuffer(msg, &buf);
if (result != ISC_R_SUCCESS)
goto failure;
result = dns_tsigkey_find(&tsigkey, keyname, NULL);
result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
if (result == ISC_R_SUCCESS) {
tkeyout.error = dns_tsigerror_badname;
dns_tsigkey_free(&tsigkey);
dns_tsigkey_free(&tsigkey, ring);
goto failure_with_tkey;
}
else if (result != ISC_R_NOTFOUND)
@ -595,13 +645,13 @@ dns_tkey_processquery(dns_message_t *msg) {
switch (tkeyin.mode) {
case DNS_TKEYMODE_DIFFIEHELLMAN:
RETERR(process_dhtkey(msg, keyname, &tkeyin,
&tkeyout, &namelist));
RETERR(process_dhtkey(msg, keyname, &tkeyin, tctx,
&tkeyout, ring, &namelist));
tkeyout.error = dns_rcode_noerror;
break;
case DNS_TKEYMODE_DELETE:
RETERR(process_deletetkey(msg, keyname, &tkeyin,
&tkeyout, &namelist));
&tkeyout, ring, &namelist));
tkeyout.error = dns_rcode_noerror;
break;
case DNS_TKEYMODE_SERVERASSIGNED:
@ -712,8 +762,10 @@ buildquery(dns_message_t *msg, dns_name_t *name,
dns_message_puttempname(msg, &qname);
if (aname != NULL)
dns_message_puttempname(msg, &aname);
if (question != NULL)
if (question != NULL) {
dns_rdataset_disassociate(question);
dns_message_puttemprdataset(msg, &question);
}
if (dynbuf != NULL)
isc_buffer_free(&dynbuf);
return (result);
@ -738,8 +790,6 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
REQUIRE(name != NULL);
REQUIRE(algorithm != NULL);
nonce = nonce; /* until the new spec is done */
tkey.common.rdclass = dns_rdataclass_in /**/;
tkey.common.rdtype = dns_rdatatype_tkey;
ISC_LINK_INIT(&tkey.common, link);
@ -748,9 +798,12 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
dns_name_clone(algorithm, &tkey.algorithm);
tkey.inception = tkey.expire = 0;
tkey.mode = DNS_TKEYMODE_DIFFIEHELLMAN;
isc_buffer_region(nonce, &r);
tkey.error = 0;
tkey.keylen = tkey.otherlen = 0;
tkey.key = tkey.other = NULL;
tkey.key = r.base;
tkey.keylen = r.length;
tkey.other = NULL;
tkey.otherlen = 0;
RETERR(buildquery(msg, name, &tkey));
@ -836,7 +889,8 @@ find_tkey(dns_message_t *msg, dns_name_t **name, dns_rdata_t *rdata) {
isc_result_t
dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dst_key_t *key, dns_tsigkey_t **outkey)
dst_key_t *key, isc_buffer_t *nonce,
dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring)
{
dns_rdata_t qtkeyrdata, rtkeyrdata;
dns_name_t keyname, *tkeyname, *theirkeyname, *ourkeyname, *tempname;
@ -845,10 +899,10 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dst_key_t *theirkey;
dns_tsigkey_t *tsigkey;
dns_rdata_generic_tkey_t qtkey, rtkey;
unsigned char keydata[1024], secretdata[16];
unsigned char keydata[1024], secretdata[256];
unsigned int sharedsize;
isc_buffer_t keysrc, keybuf, *shared = NULL, secret;
isc_region_t r;
isc_region_t r, r2;
isc_result_t result;
REQUIRE(qmsg != NULL);
@ -858,6 +912,7 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
REQUIRE(dst_key_isprivate(key));
if (outkey != NULL)
REQUIRE(*outkey == NULL);
REQUIRE(ring != NULL);
RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata));
RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, rmsg->mctx));
@ -930,13 +985,14 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
r.base = rtkey.key;
r.length = rtkey.keylen;
RETERR(compute_secret(shared, &r, &secret));
isc_buffer_region(nonce, &r2);
RETERR(compute_secret(shared, &r2, &r, &secret));
isc_buffer_used(&secret, &r);
tsigkey = NULL;
result = dns_tsigkey_create(tkeyname, &rtkey.algorithm,
r.base, r.length, ISC_TRUE,
NULL, rmsg->mctx, outkey);
NULL, rmsg->mctx, ring, outkey);
isc_buffer_free(&shared);
return (result);
@ -948,7 +1004,9 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
}
isc_result_t
dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg) {
dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dns_tsig_keyring_t *ring)
{
dns_rdata_t qtkeyrdata, rtkeyrdata;
dns_name_t *tkeyname, *tempname;
dns_rdata_generic_tkey_t qtkey, rtkey;
@ -975,12 +1033,12 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg) {
goto failure;
}
RETERR(dns_tsigkey_find(&tsigkey, tkeyname, &rtkey.algorithm));
RETERR(dns_tsigkey_find(&tsigkey, tkeyname, &rtkey.algorithm,ring));
/* Mark the key as deleted */
dns_tsigkey_setdeleted(tsigkey);
/* Release the reference */
dns_tsigkey_free(&tsigkey);
dns_tsigkey_free(&tsigkey, ring);
failure:
return (result);

View file

@ -16,7 +16,7 @@
*/
/*
* $Id: tsig.c,v 1.36 1999/12/17 21:09:34 bwelling Exp $
* $Id: tsig.c,v 1.37 2000/01/21 20:18:37 bwelling Exp $
* Principal Author: Brian Wellington
*/
@ -32,6 +32,7 @@
#include <isc/error.h>
#include <isc/list.h>
#include <isc/net.h>
#include <isc/once.h>
#include <isc/result.h>
#include <isc/rwlock.h>
#include <isc/stdtime.h>
@ -54,19 +55,20 @@
#define TSIG_MAGIC 0x54534947 /* TSIG */
#define VALID_TSIG_KEY(x) ((x) != NULL && (x)->magic == TSIG_MAGIC)
/* XXXBEW If an unsorted list isn't good enough, this can be updated */
static ISC_LIST(dns_tsigkey_t) tsigkeys;
static isc_rwlock_t tsiglock;
static isc_mem_t *tsig_mctx = NULL;
#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
static isc_once_t once = ISC_ONCE_INIT;
static dns_name_t hmacmd5_name;
dns_name_t *dns_tsig_hmacmd5_name = NULL;
#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
static isc_result_t
dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
isc_result_t
dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
unsigned char *secret, int length, isc_boolean_t generated,
dns_name_t *creator, isc_mem_t *mctx, dns_tsigkey_t **key)
dns_name_t *creator, isc_mem_t *mctx,
dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
{
isc_buffer_t b, nameb;
char namestr[1025];
@ -144,19 +146,19 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
goto cleanup_algorithm;
ISC_LINK_INIT(tkey, link);
isc_rwlock_lock(&tsiglock, isc_rwlocktype_write);
tmp = ISC_LIST_HEAD(tsigkeys);
isc_rwlock_lock(&ring->lock, isc_rwlocktype_write);
tmp = ISC_LIST_HEAD(ring->keys);
while (tmp != NULL) {
if (dns_name_equal(&tkey->name, &tmp->name)) {
ret = ISC_R_EXISTS;
isc_rwlock_unlock(&tsiglock,
isc_rwlock_unlock(&ring->lock,
isc_rwlocktype_write);
goto cleanup_algorithm;
}
tmp = ISC_LIST_NEXT(tmp, link);
}
ISC_LIST_APPEND(tsigkeys, tkey, link);
isc_rwlock_unlock(&tsiglock, isc_rwlocktype_write);
ISC_LIST_APPEND(ring->keys, tkey, link);
isc_rwlock_unlock(&ring->lock, isc_rwlocktype_write);
}
else
tkey->key = NULL;
@ -189,7 +191,7 @@ cleanup_key:
}
static void
tsigkey_free(dns_tsigkey_t **key) {
tsigkey_free(dns_tsigkey_t **key, dns_tsig_keyring_t *ring) {
dns_tsigkey_t *tkey;
REQUIRE(key != NULL);
@ -199,9 +201,9 @@ tsigkey_free(dns_tsigkey_t **key) {
tkey->magic = 0;
if (tkey->key != NULL) {
isc_rwlock_lock(&tsiglock, isc_rwlocktype_write);
ISC_LIST_UNLINK(tsigkeys, tkey, link);
isc_rwlock_unlock(&tsiglock, isc_rwlocktype_write);
isc_rwlock_lock(&ring->lock, isc_rwlocktype_write);
ISC_LIST_UNLINK(ring->keys, tkey, link);
isc_rwlock_unlock(&ring->lock, isc_rwlocktype_write);
}
dns_name_free(&tkey->name, tkey->mctx);
dns_name_free(&tkey->algorithm, tkey->mctx);
@ -215,7 +217,7 @@ tsigkey_free(dns_tsigkey_t **key) {
}
void
dns_tsigkey_free(dns_tsigkey_t **key) {
dns_tsigkey_free(dns_tsigkey_t **key, dns_tsig_keyring_t *ring) {
dns_tsigkey_t *tkey;
REQUIRE(key != NULL);
@ -230,7 +232,7 @@ dns_tsigkey_free(dns_tsigkey_t **key) {
return;
}
isc_mutex_unlock(&tkey->lock);
tsigkey_free(key);
tsigkey_free(key, ring);
}
void
@ -526,7 +528,9 @@ cleanup_struct:
}
isc_result_t
dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg) {
dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
dns_tsig_keyring_t *sring, dns_tsig_keyring_t *dring)
{
dns_rdata_any_tsig_t *tsig;
isc_region_t r, source_r, header_r, sig_r;
isc_buffer_t databuf;
@ -549,6 +553,9 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg) {
if (msg->tsigkey != NULL)
REQUIRE(VALID_TSIG_KEY(msg->tsigkey));
if (msg->tcp_continuation)
return(dns_tsig_verify_tcp(source, msg));
/* There should be a TSIG record... */
if (ISC_LIST_EMPTY(msg->sections[DNS_SECTION_TSIG]))
return (DNS_R_EXPECTEDTSIG);
@ -598,13 +605,23 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg) {
/* Find dns_tsigkey_t based on keyname */
if (msg->tsigkey == NULL) {
ret = dns_tsigkey_find(&tsigkey, keyname, &tsig->algorithm);
ret = ISC_R_NOTFOUND;
if (sring != NULL)
ret = dns_tsigkey_find(&tsigkey, keyname,
&tsig->algorithm, sring);
if (ret == ISC_R_NOTFOUND && dring != NULL)
ret = dns_tsigkey_find(&tsigkey, keyname,
&tsig->algorithm, dring);
if (ret != ISC_R_SUCCESS) {
if (dring == NULL) {
ret = DNS_R_TSIGVERIFYFAILURE;
goto cleanup_struct;
}
msg->tsigstatus = dns_tsigerror_badkey;
msg->tsigkey = NULL;
ret = dns_tsigkey_create(keyname, &tsig->algorithm,
NULL, 0, ISC_FALSE, NULL,
mctx, &msg->tsigkey);
mctx, dring, &msg->tsigkey);
if (ret != ISC_R_SUCCESS)
goto cleanup_struct;
return (DNS_R_TSIGVERIFYFAILURE);
@ -751,7 +768,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg) {
cleanup_key:
if (dns_tsigkey_empty(msg->tsigkey)) {
dns_tsigkey_free(&msg->tsigkey);
dns_tsigkey_free(&msg->tsigkey, dring);
msg->tsigkey = NULL;
}
cleanup_struct:
@ -762,7 +779,7 @@ cleanup_emptystruct:
return (ret);
}
isc_result_t
static isc_result_t
dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
dns_rdata_any_tsig_t *tsig = NULL;
isc_region_t r, source_r, header_r, sig_r;
@ -928,16 +945,17 @@ cleanup_emptystruct:
isc_result_t
dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
dns_name_t *algorithm)
dns_name_t *algorithm, dns_tsig_keyring_t *ring)
{
dns_tsigkey_t *key;
REQUIRE(tsigkey != NULL);
REQUIRE(*tsigkey == NULL);
REQUIRE(name != NULL);
REQUIRE(ring != NULL);
isc_rwlock_lock(&tsiglock, isc_rwlocktype_read);
key = ISC_LIST_HEAD(tsigkeys);
isc_rwlock_lock(&ring->lock, isc_rwlocktype_read);
key = ISC_LIST_HEAD(ring->keys);
while (key != NULL) {
if (dns_name_equal(&key->name, name) &&
(algorithm == NULL ||
@ -948,21 +966,24 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
key->refs++;
isc_mutex_unlock(&key->lock);
*tsigkey = key;
isc_rwlock_unlock(&tsiglock, isc_rwlocktype_read);
isc_rwlock_unlock(&ring->lock, isc_rwlocktype_read);
return (ISC_R_SUCCESS);
}
key = ISC_LIST_NEXT(key, link);
}
isc_rwlock_unlock(&tsiglock, isc_rwlocktype_read);
isc_rwlock_unlock(&ring->lock, isc_rwlocktype_read);
*tsigkey = NULL;
return (ISC_R_NOTFOUND);
}
static isc_result_t
add_initial_keys(dns_c_kdeflist_t *list, isc_mem_t *mctx) {
add_initial_keys(dns_c_kdeflist_t *list, dns_tsig_keyring_t *ring,
isc_mem_t *mctx)
{
isc_lex_t *lex = NULL;
dns_c_kdef_t *key;
unsigned char *secret = NULL;
int secretalloc = 0;
int secretlen = 0;
isc_result_t ret;
@ -1008,7 +1029,7 @@ add_initial_keys(dns_c_kdeflist_t *list, isc_mem_t *mctx) {
ret = ISC_R_BADBASE64;
goto failure;
}
secretlen = strlen(key->secret) * 3 / 4;
secretalloc = secretlen = strlen(key->secret) * 3 / 4;
secret = isc_mem_get(mctx, secretlen);
if (secret == NULL) {
ret = ISC_R_NOMEMORY;
@ -1028,12 +1049,13 @@ add_initial_keys(dns_c_kdeflist_t *list, isc_mem_t *mctx) {
ret = isc_base64_tobuffer(lex, &secretbuf, -1);
if (ret != ISC_R_SUCCESS)
goto failure;
secretlen = ISC_BUFFER_USEDCOUNT(&secretbuf);
isc_lex_close(lex);
isc_lex_destroy(&lex);
ret = dns_tsigkey_create(&keyname, &alg, secret, secretlen,
ISC_FALSE, NULL, mctx, NULL);
isc_mem_put(mctx, secret, secretlen);
ISC_FALSE, NULL, mctx, ring, NULL);
isc_mem_put(mctx, secret, secretalloc);
secret = NULL;
if (ret != ISC_R_SUCCESS)
goto failure;
@ -1050,18 +1072,33 @@ add_initial_keys(dns_c_kdeflist_t *list, isc_mem_t *mctx) {
}
static void
dns_tsig_inithmac() {
isc_region_t r;
char *str = "\010HMAC-MD5\007SIG-ALG\003REG\003INT";
dns_name_init(&hmacmd5_name, NULL);
r.base = str;
r.length = strlen(str) + 1;
dns_name_fromregion(&hmacmd5_name, &r);
dns_tsig_hmacmd5_name = &hmacmd5_name;
}
isc_result_t
dns_tsig_init(isc_log_t *lctx, dns_c_ctx_t *confctx, isc_mem_t *mctx) {
isc_buffer_t hmacsrc, namebuf;
dns_tsig_init(dns_c_ctx_t *confctx, isc_mem_t *mctx, dns_tsig_keyring_t **ring)
{
isc_result_t ret;
dns_name_t hmac_name;
unsigned char data[32];
dns_c_kdeflist_t *keylist = NULL;
REQUIRE(lctx != NULL); /* XXX lctx is now unused. */
REQUIRE(mctx != NULL);
REQUIRE(ring != NULL);
REQUIRE(*ring == NULL);
ret = isc_rwlock_init(&tsiglock, 0, 0);
RUNTIME_CHECK(isc_once_do(&once, dns_tsig_inithmac) == ISC_R_SUCCESS);
*ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
if (ring == NULL)
return (ISC_R_NOMEMORY);
ret = isc_rwlock_init(&(*ring)->lock, 0, 0);
if (ret != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_rwlock_init() failed: %s",
@ -1069,34 +1106,17 @@ dns_tsig_init(isc_log_t *lctx, dns_c_ctx_t *confctx, isc_mem_t *mctx) {
return (DNS_R_UNEXPECTED);
}
ISC_LIST_INIT(tsigkeys);
isc_buffer_init(&hmacsrc, DNS_TSIG_HMACMD5,
strlen(DNS_TSIG_HMACMD5), ISC_BUFFERTYPE_TEXT);
isc_buffer_add(&hmacsrc, strlen(DNS_TSIG_HMACMD5));
isc_buffer_init(&namebuf, data, sizeof(data), ISC_BUFFERTYPE_BINARY);
dns_name_init(&hmac_name, NULL);
ret = dns_name_fromtext(&hmac_name, &hmacsrc, NULL, ISC_TRUE, &namebuf);
if (ret != ISC_R_SUCCESS)
return (ret);
dns_tsig_hmacmd5_name = isc_mem_get(mctx, sizeof(dns_name_t));
if (dns_tsig_hmacmd5_name == NULL)
return (ISC_R_NOMEMORY);
dns_name_init(dns_tsig_hmacmd5_name, NULL);
ret = dns_name_dup(&hmac_name, mctx, dns_tsig_hmacmd5_name);
if (ret != ISC_R_SUCCESS)
goto failure;
ISC_LIST_INIT((*ring)->keys);
if (confctx != NULL) {
ret = dns_c_ctx_getkdeflist(confctx, &keylist);
if (ret == ISC_R_SUCCESS)
ret = add_initial_keys(keylist, mctx);
ret = add_initial_keys(keylist, *ring, mctx);
else if (ret != ISC_R_NOTFOUND)
goto failure;
}
tsig_mctx = mctx;
(*ring)->mctx = mctx;
return (ISC_R_SUCCESS);
@ -1106,15 +1126,16 @@ dns_tsig_init(isc_log_t *lctx, dns_c_ctx_t *confctx, isc_mem_t *mctx) {
}
void
dns_tsig_destroy() {
if (tsig_mctx == NULL)
return;
while (!ISC_LIST_EMPTY(tsigkeys)) {
dns_tsigkey_t *key = ISC_LIST_HEAD(tsigkeys);
dns_tsig_destroy(dns_tsig_keyring_t **ring) {
REQUIRE(ring != NULL);
REQUIRE(*ring != NULL);
while (!ISC_LIST_EMPTY((*ring)->keys)) {
dns_tsigkey_t *key = ISC_LIST_HEAD((*ring)->keys);
key->refs = 0;
key->deleted = ISC_TRUE;
tsigkey_free(&key);
tsigkey_free(&key, *ring);
}
dns_name_free(dns_tsig_hmacmd5_name, tsig_mctx);
isc_mem_put(tsig_mctx, dns_tsig_hmacmd5_name, sizeof(dns_name_t));
*ring = NULL;
}

View file

@ -33,9 +33,11 @@
#include <dns/db.h>
#include <dns/events.h>
#include <dns/fixedname.h>
#include <dns/message.h>
#include <dns/rbt.h>
#include <dns/rdataset.h>
#include <dns/resolver.h>
#include <dns/tsig.h>
#include <dns/view.h>
#include <dns/zone.h>
#include <dns/zt.h>
@ -106,6 +108,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->task = NULL;
view->references = 1;
view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN);
view->statickeys = NULL;
view->dynamickeys = NULL;
result = dns_tsig_init(NULL, view->mctx, &view->dynamickeys);
ISC_LINK_INIT(view, link);
ISC_EVENT_INIT(&view->resevent, sizeof view->resevent, 0, NULL,
DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
@ -348,6 +353,20 @@ dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
dns_db_attach(hints, &view->hints);
}
void
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
/*
* Set the view's static TSIG keyring
*/
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->statickeys == NULL);
REQUIRE(ring != NULL);
view->statickeys = ring;
}
isc_result_t
dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
isc_result_t result;
@ -783,3 +802,14 @@ dns_view_load(dns_view_t *view) {
dns_zt_load(view->zonetable);
}
isc_result_t
dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(source != NULL);
REQUIRE(DNS_MESSAGE_VALID(msg));
return dns_tsig_verify(source, msg, view->statickeys,
view->dynamickeys);
}