mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
Store tsig keys in an rbt, not a list.
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: tsig.h,v 1.25 2000/07/18 00:46:03 bwelling Exp $ */
|
/* $Id: tsig.h,v 1.26 2000/07/21 20:53:59 bwelling Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_TSIG_H
|
#ifndef DNS_TSIG_H
|
||||||
#define DNS_TSIG_H 1
|
#define DNS_TSIG_H 1
|
||||||
@@ -42,7 +42,7 @@ extern dns_name_t *dns_tsig_hmacmd5_name;
|
|||||||
#define DNS_TSIG_FUDGE 300
|
#define DNS_TSIG_FUDGE 300
|
||||||
|
|
||||||
struct dns_tsig_keyring {
|
struct dns_tsig_keyring {
|
||||||
ISC_LIST(dns_tsigkey_t) keys;
|
dns_rbt_t *keys;
|
||||||
isc_rwlock_t lock;
|
isc_rwlock_t lock;
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
};
|
};
|
||||||
@@ -61,10 +61,8 @@ struct dns_tsigkey {
|
|||||||
dns_tsig_keyring_t *ring; /* the enclosing keyring */
|
dns_tsig_keyring_t *ring; /* the enclosing keyring */
|
||||||
isc_mutex_t lock;
|
isc_mutex_t lock;
|
||||||
/* Locked */
|
/* Locked */
|
||||||
isc_boolean_t deleted; /* has this been deleted? */
|
|
||||||
isc_uint32_t refs; /* reference counter */
|
isc_uint32_t refs; /* reference counter */
|
||||||
/* Unlocked */
|
/* Unlocked */
|
||||||
ISC_LINK(dns_tsigkey_t) link;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define dns_tsigkey_empty(tsigkey) ((tsigkey)->key == NULL)
|
#define dns_tsigkey_empty(tsigkey) ((tsigkey)->key == NULL)
|
||||||
@@ -116,25 +114,25 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_tsigkey_detach(dns_tsigkey_t **key);
|
dns_tsigkey_detach(dns_tsigkey_t **keyp);
|
||||||
/*
|
/*
|
||||||
* Detaches from the tsig key structure pointed to by '*key'.
|
* Detaches from the tsig key structure pointed to by '*key'.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'key' not NULL and '*key' is a valid TSIG key
|
* 'keyp' is not NULL and '*keyp' is a valid TSIG key
|
||||||
*
|
*
|
||||||
* Ensures:
|
* Ensures:
|
||||||
* 'key' points to NULL
|
* 'keyp' points to NULL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_tsigkey_setdeleted(dns_tsigkey_t *key);
|
dns_tsigkey_setdeleted(dns_tsigkey_t *key);
|
||||||
/*
|
/*
|
||||||
* Marks this key as deleted. It will be deleted when no references
|
* Prevents this key from being used again. It will be deleted when
|
||||||
* exist.
|
* no references * exist.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'key' is a valid TSIG key
|
* 'key' is a valid TSIG key on a keyring
|
||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -201,13 +199,13 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
|
|||||||
|
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring);
|
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp);
|
||||||
/*
|
/*
|
||||||
* Create an empty TSIG key ring.
|
* Create an empty TSIG key ring.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'mctx' is not NULL
|
* 'mctx' is not NULL
|
||||||
* 'ring' is not NULL, and '*ring' is NULL
|
* 'ringp' is not NULL, and '*ringp' is NULL
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* ISC_R_SUCCESS
|
* ISC_R_SUCCESS
|
||||||
@@ -216,12 +214,12 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring);
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_tsigkeyring_destroy(dns_tsig_keyring_t **ring);
|
dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp);
|
||||||
/*
|
/*
|
||||||
* Destroy a TSIG key ring.
|
* Destroy a TSIG key ring.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'ring' is not NULL
|
* 'ringp' is not NULL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ISC_LANG_ENDDECLS
|
ISC_LANG_ENDDECLS
|
||||||
|
194
lib/dns/tsig.c
194
lib/dns/tsig.c
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Id: tsig.c,v 1.75 2000/07/21 20:32:12 bwelling Exp $
|
* $Id: tsig.c,v 1.76 2000/07/21 20:53:58 bwelling Exp $
|
||||||
* Principal Author: Brian Wellington
|
* Principal Author: Brian Wellington
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <dns/keyvalues.h>
|
#include <dns/keyvalues.h>
|
||||||
#include <dns/log.h>
|
#include <dns/log.h>
|
||||||
#include <dns/message.h>
|
#include <dns/message.h>
|
||||||
|
#include <dns/rbt.h>
|
||||||
#include <dns/rdata.h>
|
#include <dns/rdata.h>
|
||||||
#include <dns/rdatalist.h>
|
#include <dns/rdatalist.h>
|
||||||
#include <dns/rdataset.h>
|
#include <dns/rdataset.h>
|
||||||
@@ -123,12 +124,12 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
|
|||||||
else
|
else
|
||||||
tkey->creator = NULL;
|
tkey->creator = NULL;
|
||||||
|
|
||||||
ISC_LINK_INIT(tkey, link);
|
|
||||||
tkey->key = NULL;
|
tkey->key = NULL;
|
||||||
tkey->ring = ring;
|
tkey->ring = ring;
|
||||||
|
tkey->refs = 0;
|
||||||
|
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
dns_tsigkey_t *tmp;
|
dns_tsigkey_t *tmp = NULL;
|
||||||
|
|
||||||
isc_buffer_init(&b, secret, length);
|
isc_buffer_init(&b, secret, length);
|
||||||
isc_buffer_add(&b, length);
|
isc_buffer_add(&b, length);
|
||||||
@@ -141,30 +142,31 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
|
|||||||
|
|
||||||
if (ring != NULL) {
|
if (ring != NULL) {
|
||||||
RWLOCK(&ring->lock, isc_rwlocktype_write);
|
RWLOCK(&ring->lock, isc_rwlocktype_write);
|
||||||
tmp = ISC_LIST_HEAD(ring->keys);
|
ret = dns_rbt_findname(ring->keys, name, 0, NULL,
|
||||||
while (tmp != NULL) {
|
(void *)&tmp);
|
||||||
if (dns_name_equal(&tkey->name, &tmp->name) &&
|
if (ret == ISC_R_SUCCESS) {
|
||||||
!tmp->deleted)
|
ret = ISC_R_EXISTS;
|
||||||
{
|
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
||||||
ret = ISC_R_EXISTS;
|
goto cleanup_algorithm;
|
||||||
RWUNLOCK(&ring->lock,
|
|
||||||
isc_rwlocktype_write);
|
|
||||||
goto cleanup_algorithm;
|
|
||||||
}
|
|
||||||
tmp = ISC_LIST_NEXT(tmp, link);
|
|
||||||
}
|
}
|
||||||
ISC_LIST_APPEND(ring->keys, tkey, link);
|
INSIST(ret == ISC_R_NOTFOUND ||
|
||||||
|
ret == DNS_R_PARTIALMATCH);
|
||||||
|
ret = dns_rbt_addname(ring->keys, name, tkey);
|
||||||
|
if (ret != ISC_R_SUCCESS) {
|
||||||
|
ret = ISC_R_EXISTS;
|
||||||
|
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
||||||
|
goto cleanup_algorithm;
|
||||||
|
}
|
||||||
|
tkey->refs++;
|
||||||
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tkey->refs = 0;
|
|
||||||
if (key != NULL)
|
if (key != NULL)
|
||||||
tkey->refs++;
|
tkey->refs++;
|
||||||
tkey->generated = generated;
|
tkey->generated = generated;
|
||||||
tkey->inception = inception;
|
tkey->inception = inception;
|
||||||
tkey->expire = expire;
|
tkey->expire = expire;
|
||||||
tkey->deleted = ISC_FALSE;
|
|
||||||
tkey->mctx = mctx;
|
tkey->mctx = mctx;
|
||||||
ret = isc_mutex_init(&tkey->lock);
|
ret = isc_mutex_init(&tkey->lock);
|
||||||
if (ret != ISC_R_SUCCESS) {
|
if (ret != ISC_R_SUCCESS) {
|
||||||
@@ -204,17 +206,9 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
tsigkey_free(dns_tsigkey_t *key) {
|
tsigkey_free(dns_tsigkey_t *key) {
|
||||||
dns_tsig_keyring_t *ring;
|
|
||||||
|
|
||||||
REQUIRE(VALID_TSIG_KEY(key));
|
REQUIRE(VALID_TSIG_KEY(key));
|
||||||
ring = key->ring;
|
|
||||||
|
|
||||||
key->magic = 0;
|
key->magic = 0;
|
||||||
if (ring != NULL) {
|
|
||||||
RWLOCK(&ring->lock, isc_rwlocktype_write);
|
|
||||||
ISC_LIST_UNLINK(ring->keys, key, link);
|
|
||||||
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
|
||||||
}
|
|
||||||
dns_name_free(&key->name, key->mctx);
|
dns_name_free(&key->name, key->mctx);
|
||||||
dns_name_free(&key->algorithm, key->mctx);
|
dns_name_free(&key->algorithm, key->mctx);
|
||||||
if (key->key != NULL)
|
if (key->key != NULL)
|
||||||
@@ -227,30 +221,32 @@ tsigkey_free(dns_tsigkey_t *key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_tsigkey_detach(dns_tsigkey_t **key) {
|
dns_tsigkey_detach(dns_tsigkey_t **keyp) {
|
||||||
dns_tsigkey_t *tkey;
|
dns_tsigkey_t *key;
|
||||||
isc_boolean_t should_free = ISC_FALSE;
|
isc_boolean_t should_free = ISC_FALSE;
|
||||||
|
|
||||||
REQUIRE(key != NULL);
|
REQUIRE(keyp != NULL);
|
||||||
REQUIRE(VALID_TSIG_KEY(*key));
|
REQUIRE(VALID_TSIG_KEY(*keyp));
|
||||||
tkey = *key;
|
key = *keyp;
|
||||||
*key = NULL;
|
*keyp = NULL;
|
||||||
|
|
||||||
LOCK(&tkey->lock);
|
LOCK(&key->lock);
|
||||||
tkey->refs--;
|
key->refs--;
|
||||||
if (tkey->refs == 0 && (tkey->deleted || tkey->key == NULL))
|
if (key->refs == 0)
|
||||||
should_free = ISC_TRUE;
|
should_free = ISC_TRUE;
|
||||||
UNLOCK(&tkey->lock);
|
UNLOCK(&key->lock);
|
||||||
if (should_free)
|
if (should_free)
|
||||||
tsigkey_free(tkey);
|
tsigkey_free(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
|
dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
|
||||||
INSIST(VALID_TSIG_KEY(key));
|
REQUIRE(VALID_TSIG_KEY(key));
|
||||||
LOCK(&key->lock);
|
REQUIRE(key->ring != NULL);
|
||||||
key->deleted = ISC_TRUE;
|
|
||||||
UNLOCK(&key->lock);
|
RWLOCK(&key->ring->lock, isc_rwlocktype_write);
|
||||||
|
(void)dns_rbt_deletename(key->ring->keys, &key->name, ISC_FALSE);
|
||||||
|
RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -1024,6 +1020,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
|
|||||||
{
|
{
|
||||||
dns_tsigkey_t *key;
|
dns_tsigkey_t *key;
|
||||||
isc_stdtime_t now;
|
isc_stdtime_t now;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
REQUIRE(tsigkey != NULL);
|
REQUIRE(tsigkey != NULL);
|
||||||
REQUIRE(*tsigkey == NULL);
|
REQUIRE(*tsigkey == NULL);
|
||||||
@@ -1032,79 +1029,96 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
|
|||||||
|
|
||||||
isc_stdtime_get(&now);
|
isc_stdtime_get(&now);
|
||||||
RWLOCK(&ring->lock, isc_rwlocktype_read);
|
RWLOCK(&ring->lock, isc_rwlocktype_read);
|
||||||
key = ISC_LIST_HEAD(ring->keys);
|
key = NULL;
|
||||||
while (key != NULL) {
|
result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
|
||||||
if (dns_name_equal(&key->name, name) &&
|
if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
|
||||||
(algorithm == NULL ||
|
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||||
dns_name_equal(&key->algorithm, algorithm)) &&
|
return (ISC_R_NOTFOUND);
|
||||||
!key->deleted)
|
|
||||||
{
|
|
||||||
if (key->inception != key->expire &&
|
|
||||||
key->expire < now)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The key has expired.
|
|
||||||
*/
|
|
||||||
key->deleted = ISC_TRUE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
LOCK(&key->lock);
|
|
||||||
key->refs++;
|
|
||||||
UNLOCK(&key->lock);
|
|
||||||
*tsigkey = key;
|
|
||||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
key = ISC_LIST_NEXT(key, link);
|
|
||||||
}
|
}
|
||||||
|
if (algorithm != NULL && !dns_name_equal(&key->algorithm, algorithm)) {
|
||||||
|
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
if (key->inception != key->expire && key->expire < now) {
|
||||||
|
/*
|
||||||
|
* The key has expired.
|
||||||
|
*/
|
||||||
|
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||||
|
LOCK(&key->lock);
|
||||||
|
key->refs--;
|
||||||
|
UNLOCK(&key->lock);
|
||||||
|
RWLOCK(&ring->lock, isc_rwlocktype_write);
|
||||||
|
(void) dns_rbt_deletename(ring->keys, name, ISC_FALSE);
|
||||||
|
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCK(&key->lock);
|
||||||
|
key->refs++;
|
||||||
|
UNLOCK(&key->lock);
|
||||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||||
*tsigkey = NULL;
|
*tsigkey = key;
|
||||||
return (ISC_R_NOTFOUND);
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_tsignode(void *node, void *_unused) {
|
||||||
|
dns_tsigkey_t *key;
|
||||||
|
|
||||||
|
UNUSED(_unused);
|
||||||
|
|
||||||
|
REQUIRE(node != NULL);
|
||||||
|
|
||||||
|
key = node;
|
||||||
|
dns_tsigkey_detach(&key);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring) {
|
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
|
||||||
isc_result_t ret;
|
isc_result_t result;
|
||||||
|
dns_tsig_keyring_t *ring;
|
||||||
|
|
||||||
REQUIRE(mctx != NULL);
|
REQUIRE(mctx != NULL);
|
||||||
REQUIRE(ring != NULL);
|
REQUIRE(ringp != NULL);
|
||||||
REQUIRE(*ring == NULL);
|
REQUIRE(*ringp == NULL);
|
||||||
|
|
||||||
*ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
|
ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
|
||||||
if (ring == NULL)
|
if (ring == NULL)
|
||||||
return (ISC_R_NOMEMORY);
|
return (ISC_R_NOMEMORY);
|
||||||
|
|
||||||
ret = isc_rwlock_init(&(*ring)->lock, 0, 0);
|
result = isc_rwlock_init(&ring->lock, 0, 0);
|
||||||
if (ret != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
"isc_rwlock_init() failed: %s",
|
"isc_rwlock_init() failed: %s",
|
||||||
isc_result_totext(ret));
|
isc_result_totext(result));
|
||||||
return (ISC_R_UNEXPECTED);
|
return (ISC_R_UNEXPECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
ISC_LIST_INIT((*ring)->keys);
|
ring->keys = NULL;
|
||||||
|
result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
isc_rwlock_destroy(&ring->lock);
|
||||||
|
isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
(*ring)->mctx = mctx;
|
ring->mctx = mctx;
|
||||||
|
|
||||||
|
*ringp = ring;
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_tsigkeyring_destroy(dns_tsig_keyring_t **ring) {
|
dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) {
|
||||||
isc_mem_t *mctx;
|
dns_tsig_keyring_t *ring;
|
||||||
|
|
||||||
REQUIRE(ring != NULL);
|
REQUIRE(ringp != NULL);
|
||||||
REQUIRE(*ring != NULL);
|
REQUIRE(*ringp != NULL);
|
||||||
|
|
||||||
while (!ISC_LIST_EMPTY((*ring)->keys)) {
|
ring = *ringp;
|
||||||
dns_tsigkey_t *key = ISC_LIST_HEAD((*ring)->keys);
|
*ringp = NULL;
|
||||||
key->refs = 0;
|
|
||||||
key->deleted = ISC_TRUE;
|
|
||||||
tsigkey_free(key);
|
|
||||||
}
|
|
||||||
isc_rwlock_destroy(&(*ring)->lock);
|
|
||||||
mctx = (*ring)->mctx;
|
|
||||||
isc_mem_put(mctx, *ring, sizeof(dns_tsig_keyring_t));
|
|
||||||
|
|
||||||
*ring = NULL;
|
dns_rbt_destroy(&ring->keys);
|
||||||
|
isc_rwlock_destroy(&ring->lock);
|
||||||
|
isc_mem_put(ring->mctx, ring, sizeof(dns_tsig_keyring_t));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user