summaryrefslogtreecommitdiffstats
path: root/lib/dns/tsig.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/tsig.c')
-rw-r--r--lib/dns/tsig.c85
1 files changed, 73 insertions, 12 deletions
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
index 74a7af3..65d32dc 100644
--- a/lib/dns/tsig.c
+++ b/lib/dns/tsig.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +16,7 @@
*/
/*
- * $Id: tsig.c,v 1.136 2008/11/04 21:23:14 marka Exp $
+ * $Id: tsig.c,v 1.136.18.5 2010-12-09 01:12:55 marka Exp $
*/
/*! \file */
#include <config.h>
@@ -26,6 +26,7 @@
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/refcount.h>
+#include <isc/serial.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/util.h>
#include <isc/time.h>
@@ -47,6 +48,10 @@
#define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
#define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
+#ifndef DNS_TSIG_MAXGENERATEDKEYS
+#define DNS_TSIG_MAXGENERATEDKEYS 4096
+#endif
+
#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
#define algname_is_allocated(algname) \
((algname) != dns_tsig_hmacmd5_name && \
@@ -86,6 +91,31 @@ static dns_name_t gsstsig = {
};
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
+static void
+remove_fromring(dns_tsigkey_t *tkey) {
+ if (tkey->generated) {
+ ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
+ tkey->ring->generated--;
+ }
+ (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
+}
+
+static void
+adjust_lru(dns_tsigkey_t *tkey) {
+ if (tkey->generated) {
+ RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
+ /*
+ * We may have been removed from the LRU list between
+ * removing the read lock and aquiring the write lock.
+ */
+ if (ISC_LINK_LINKED(tkey, link)) {
+ ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
+ ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
+ }
+ RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
+ }
+}
+
/*
* Since Microsoft doesn't follow its own standard, we will use this
* alternate name as a second guess.
@@ -327,7 +357,9 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
} else
tkey->creator = NULL;
- tkey->key = dstkey;
+ tkey->key = NULL;
+ if (dstkey != NULL)
+ dst_key_attach(dstkey, &tkey->key);
tkey->ring = ring;
if (key != NULL)
@@ -358,11 +390,24 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
cleanup_ring(ring);
ring->writecount = 0;
}
+
ret = dns_rbt_addname(ring->keys, name, tkey);
if (ret != ISC_R_SUCCESS) {
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
goto cleanup_refs;
}
+
+ if (tkey->generated) {
+ /*
+ * Add the new key to the LRU list and remove the
+ * least recently used key if there are too many
+ * keys on the list.
+ */
+ ISC_LIST_INITANDAPPEND(ring->lru, tkey, link);
+ if (ring->generated++ > ring->maxgenerated)
+ remove_fromring(ISC_LIST_HEAD(ring->lru));
+ }
+
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
}
@@ -390,6 +435,8 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
isc_refcount_decrement(&tkey->refs, NULL);
isc_refcount_destroy(&tkey->refs);
cleanup_creator:
+ if (tkey->key != NULL)
+ dst_key_free(&tkey->key);
if (tkey->creator != NULL) {
dns_name_free(tkey->creator, mctx);
isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
@@ -452,9 +499,7 @@ cleanup_ring(dns_tsig_keyring_t *ring)
tsig_log(tkey, 2, "tsig expire: deleting");
/* delete the key */
dns_rbtnodechain_invalidate(&chain);
- (void)dns_rbt_deletename(ring->keys,
- &tkey->name,
- ISC_FALSE);
+ remove_fromring(tkey);
goto again;
}
}
@@ -464,7 +509,6 @@ cleanup_ring(dns_tsig_keyring_t *ring)
dns_rbtnodechain_invalidate(&chain);
return;
}
-
}
}
@@ -572,7 +616,7 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
generated, creator,
inception, expire, mctx, ring, key);
- if (result != ISC_R_SUCCESS && dstkey != NULL)
+ if (dstkey != NULL)
dst_key_free(&dstkey);
return (result);
}
@@ -629,7 +673,7 @@ dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
REQUIRE(key->ring != NULL);
RWLOCK(&key->ring->lock, isc_rwlocktype_write);
- (void)dns_rbt_deletename(key->ring->keys, &key->name, ISC_FALSE);
+ remove_fromring(key);
RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
}
@@ -889,6 +933,9 @@ dns_tsig_sign(dns_message_t *msg) {
msg->tsig = dataset;
msg->tsigname = owner;
+ /* Windows does not like the tsig name being compressed. */
+ msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
+
return (ISC_R_SUCCESS);
cleanup_rdatalist:
@@ -1469,19 +1516,30 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
return (ISC_R_NOTFOUND);
}
- if (key->inception != key->expire && key->expire < now) {
+ if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
/*
* The key has expired.
*/
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
RWLOCK(&ring->lock, isc_rwlocktype_write);
- (void)dns_rbt_deletename(ring->keys, name, ISC_FALSE);
+ remove_fromring(key);
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
return (ISC_R_NOTFOUND);
}
-
+#if 0
+ /*
+ * MPAXXX We really should look at the inception time.
+ */
+ if (key->inception != key->expire &&
+ isc_serial_lt(key->inception, now)) {
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ adjust_lru(key);
+ return (ISC_R_NOTFOUND);
+ }
+#endif
isc_refcount_increment(&key->refs, NULL);
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ adjust_lru(key);
*tsigkey = key;
return (ISC_R_SUCCESS);
}
@@ -1527,6 +1585,9 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
ring->writecount = 0;
ring->mctx = NULL;
+ ring->generated = 0;
+ ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
+ ISC_LIST_INIT(ring->lru);
isc_mem_attach(mctx, &ring->mctx);
*ringp = ring;
OpenPOWER on IntegriCloud