mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
2929. [bug] Improved handling of GSS security contexts:
- added LRU expiration for generated TSIGs - added the ability to use a non-default realm - added new "realm" keyword in nsupdate - limited lifetime of generated keys to 1 hour or the lifetime of the context (whichever is smaller) [RT #19737]
This commit is contained in:
9
CHANGES
9
CHANGES
@@ -1,3 +1,12 @@
|
||||
2929. [bug] Improved handling of GSS security contexts:
|
||||
- added LRU expiration for generated TSIGs
|
||||
- added the ability to use a non-default realm
|
||||
- added new "realm" keyword in nsupdate
|
||||
- limited lifetime of generated keys to 1 hour
|
||||
or the lifetime of the context (whichever is
|
||||
smaller)
|
||||
[RT #19737]
|
||||
|
||||
2928. [bug] Be more selective about the non-authoritative
|
||||
answer we apply change 2748 to. [RT #21594]
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: nsupdate.c,v 1.178 2010/05/18 06:18:23 marka Exp $ */
|
||||
/* $Id: nsupdate.c,v 1.179 2010/07/09 05:13:14 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -195,6 +195,7 @@ ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
|
||||
#ifdef GSSAPI
|
||||
static dns_fixedname_t fkname;
|
||||
static isc_sockaddr_t *kserver = NULL;
|
||||
static char *realm = NULL;
|
||||
static char servicename[DNS_NAME_FORMATSIZE];
|
||||
static dns_name_t *keyname;
|
||||
typedef struct nsu_gssinfo {
|
||||
@@ -548,7 +549,8 @@ setup_keystr(void) {
|
||||
|
||||
debug("keycreate");
|
||||
result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
|
||||
ISC_TRUE, NULL, 0, 0, mctx, NULL, &tsigkey);
|
||||
ISC_FALSE, NULL, 0, 0, mctx, NULL,
|
||||
&tsigkey);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fprintf(stderr, "could not create key from %s: %s\n",
|
||||
keystr, dns_result_totext(result));
|
||||
@@ -1462,7 +1464,7 @@ evaluate_key(char *cmdline) {
|
||||
if (tsigkey != NULL)
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
|
||||
ISC_TRUE, NULL, 0, 0, mctx, NULL,
|
||||
ISC_FALSE, NULL, 0, 0, mctx, NULL,
|
||||
&tsigkey);
|
||||
isc_mem_free(mctx, secret);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@@ -1500,6 +1502,31 @@ evaluate_zone(char *cmdline) {
|
||||
return (STATUS_MORE);
|
||||
}
|
||||
|
||||
static isc_uint16_t
|
||||
evaluate_realm(char *cmdline) {
|
||||
#ifdef GSSAPI
|
||||
char *word;
|
||||
char buf[1024];
|
||||
|
||||
word = nsu_strsep(&cmdline, " \t\r\n");
|
||||
if (*word == 0) {
|
||||
if (realm != NULL)
|
||||
isc_mem_free(mctx, realm);
|
||||
realm = NULL;
|
||||
return (STATUS_MORE);
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "@%s", word);
|
||||
realm = isc_mem_strdup(mctx, buf);
|
||||
if (realm == NULL)
|
||||
fatal("out of memory");
|
||||
return (STATUS_MORE);
|
||||
#else
|
||||
UNUSED(cmdline);
|
||||
return (STATUS_SYNTAX);
|
||||
#endif
|
||||
}
|
||||
|
||||
static isc_uint16_t
|
||||
evaluate_ttl(char *cmdline) {
|
||||
char *word;
|
||||
@@ -1891,6 +1918,8 @@ get_next_command(void) {
|
||||
usegsstsig = ISC_FALSE;
|
||||
return (evaluate_key(cmdline));
|
||||
}
|
||||
if (strcasecmp(word, "realm") == 0)
|
||||
return (evaluate_realm(cmdline));
|
||||
if (strcasecmp(word, "gsstsig") == 0) {
|
||||
#ifdef GSSAPI
|
||||
usegsstsig = ISC_TRUE;
|
||||
@@ -2423,7 +2452,7 @@ start_gssrequest(dns_name_t *master)
|
||||
servname = dns_fixedname_name(&fname);
|
||||
|
||||
result = isc_string_printf(servicename, sizeof(servicename),
|
||||
"DNS/%s", namestr);
|
||||
"DNS/%s%s", namestr, realm ? realm : "");
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("isc_string_printf(servicename) failed: %s",
|
||||
isc_result_totext(result));
|
||||
@@ -2461,7 +2490,6 @@ start_gssrequest(dns_name_t *master)
|
||||
isc_result_totext(result));
|
||||
|
||||
/* Build first request. */
|
||||
|
||||
context = GSS_C_NO_CONTEXT;
|
||||
result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
|
||||
&context, use_win2k_gsstsig);
|
||||
@@ -2763,6 +2791,10 @@ cleanup(void) {
|
||||
isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
|
||||
kserver = NULL;
|
||||
}
|
||||
if (realm != NULL) {
|
||||
isc_mem_free(mctx, realm);
|
||||
realm = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ddebug("Shutting down task manager");
|
||||
|
@@ -18,7 +18,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- $Id: nsupdate.docbook,v 1.42 2009/12/16 07:13:02 each Exp $ -->
|
||||
<!-- $Id: nsupdate.docbook,v 1.43 2010/07/09 05:13:14 each Exp $ -->
|
||||
<refentry id="man.nsupdate">
|
||||
<refentryinfo>
|
||||
<date>Aug 25, 2009</date>
|
||||
@@ -382,6 +382,45 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>gsstsig</command>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Use GSS-TSIG to sign the updated. This is equivalent to
|
||||
specifying <option>-g</option> on the commandline.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>oldgsstsig</command>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Use the Windows 2000 version of GSS-TSIG to sign the updated.
|
||||
This is equivalent to specifying <option>-o</option> on the
|
||||
commandline.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>realm</command>
|
||||
<arg choice="req"><optional>realm_name</optional></arg>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
When using GSS-TSIG use <parameter>realm_name</parameter> rather
|
||||
than the default realm in <filename>krb5.conf</filename>. If no
|
||||
realm is specified the saved realm is cleared.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>prereq nxdomain</command>
|
||||
|
@@ -18,7 +18,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.459 2010/06/25 03:24:05 marka Exp $ -->
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.460 2010/07/09 05:13:15 each Exp $ -->
|
||||
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>BIND 9 Administrator Reference Manual</title>
|
||||
|
||||
@@ -5243,7 +5243,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
||||
the server can acquire through the default system
|
||||
key file, normally <filename>/etc/krb5.keytab</filename>.
|
||||
Normally this principal is of the form
|
||||
"<userinput>dns/</userinput><varname>server.domain</varname>".
|
||||
"<userinput>DNS/</userinput><varname>server.domain</varname>".
|
||||
To use GSS-TSIG, <command>tkey-domain</command>
|
||||
must also be set.
|
||||
</para>
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: gssapictx.c,v 1.17 2010/06/03 02:27:11 marka Exp $ */
|
||||
/* $Id: gssapictx.c,v 1.18 2010/07/09 05:13:15 each Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -132,7 +132,7 @@ name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
|
||||
namep = &tname;
|
||||
}
|
||||
|
||||
result = dns_name_totext(namep, ISC_FALSE, buffer);
|
||||
result = dns_name_toprincipal(namep, buffer);
|
||||
isc_buffer_putuint8(buffer, 0);
|
||||
isc_buffer_usedregion(buffer, &r);
|
||||
REGION_TO_GBUFFER(r, *gbuffer);
|
||||
@@ -336,12 +336,15 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
|
||||
char rbuf[DNS_NAME_FORMATSIZE];
|
||||
char *sname;
|
||||
char *rname;
|
||||
isc_buffer_t buffer;
|
||||
|
||||
/*
|
||||
* It is far, far easier to write the names we are looking at into
|
||||
* a string, and do string operations on them.
|
||||
*/
|
||||
dns_name_format(signer, sbuf, sizeof(sbuf));
|
||||
isc_buffer_init(&buffer, sbuf, sizeof(sbuf));
|
||||
dns_name_toprincipal(signer, &buffer);
|
||||
isc_buffer_putuint8(&buffer, 0);
|
||||
if (name != NULL)
|
||||
dns_name_format(name, nbuf, sizeof(nbuf));
|
||||
dns_name_format(realm, rbuf, sizeof(rbuf));
|
||||
@@ -351,7 +354,7 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
|
||||
* does not exist, we don't have something we like, so we fail our
|
||||
* compare.
|
||||
*/
|
||||
rname = strstr(sbuf, "\\@");
|
||||
rname = strchr(sbuf, '@');
|
||||
if (rname == NULL)
|
||||
return (isc_boolean_false);
|
||||
*rname = '\0';
|
||||
@@ -405,12 +408,15 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
|
||||
char *sname;
|
||||
char *nname;
|
||||
char *rname;
|
||||
isc_buffer_t buffer;
|
||||
|
||||
/*
|
||||
* It is far, far easier to write the names we are looking at into
|
||||
* a string, and do string operations on them.
|
||||
*/
|
||||
dns_name_format(signer, sbuf, sizeof(sbuf));
|
||||
isc_buffer_init(&buffer, sbuf, sizeof(sbuf));
|
||||
dns_name_toprincipal(signer, &buffer);
|
||||
isc_buffer_putuint8(&buffer, 0);
|
||||
if (name != NULL)
|
||||
dns_name_format(name, nbuf, sizeof(nbuf));
|
||||
dns_name_format(realm, rbuf, sizeof(rbuf));
|
||||
@@ -420,17 +426,17 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
|
||||
* does not exist, we don't have something we like, so we fail our
|
||||
* compare.
|
||||
*/
|
||||
rname = strstr(sbuf, "\\@");
|
||||
rname = strchr(sbuf, '@');
|
||||
if (rname == NULL)
|
||||
return (isc_boolean_false);
|
||||
sname = strstr(sbuf, "\\$");
|
||||
sname = strchr(sbuf, '$');
|
||||
if (sname == NULL)
|
||||
return (isc_boolean_false);
|
||||
|
||||
/*
|
||||
* Verify that the $ and @ follow one another.
|
||||
*/
|
||||
if (rname - sname != 2)
|
||||
if (rname - sname != 1)
|
||||
return (isc_boolean_false);
|
||||
|
||||
/*
|
||||
@@ -442,8 +448,7 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
|
||||
* machinename$@EXAMPLE.COM
|
||||
* format.
|
||||
*/
|
||||
*rname = '\0';
|
||||
rname += 2;
|
||||
rname++;
|
||||
*sname = '\0';
|
||||
sname = sbuf;
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: name.h,v 1.133 2009/12/24 00:35:46 each Exp $ */
|
||||
/* $Id: name.h,v 1.134 2010/07/09 05:13:15 each Exp $ */
|
||||
|
||||
#ifndef DNS_NAME_H
|
||||
#define DNS_NAME_H 1
|
||||
@@ -802,9 +802,18 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
|
||||
*\li #ISC_R_UNEXPECTEDEND
|
||||
*/
|
||||
|
||||
#define DNS_NAME_OMITFINALDOT 0x01U
|
||||
#define DNS_NAME_MASTERFILE 0x02U /* escape $ and @ */
|
||||
|
||||
isc_result_t
|
||||
dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target);
|
||||
|
||||
isc_result_t
|
||||
dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
isc_buffer_t *target);
|
||||
|
||||
isc_result_t
|
||||
dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target);
|
||||
/*%<
|
||||
* Convert 'name' into text format, storing the result in 'target'.
|
||||
*
|
||||
@@ -812,6 +821,12 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
*\li If 'omit_final_dot' is true, then the final '.' in absolute
|
||||
* names other than the root name will be omitted.
|
||||
*
|
||||
*\li If DNS_NAME_OMITFINALDOT is set in options, then the final '.'
|
||||
* in absolute names other than the root name will be omitted.
|
||||
*
|
||||
*\li If DNS_NAME_MASTERFILE is set in options, '$' and '@' will also
|
||||
* be escaped.
|
||||
*
|
||||
*\li If dns_name_countlabels == 0, the name will be "@", representing the
|
||||
* current origin as described by RFC1035.
|
||||
*
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: tsig.h,v 1.53 2009/06/11 23:47:55 tbox Exp $ */
|
||||
/* $Id: tsig.h,v 1.54 2010/07/09 05:13:15 each Exp $ */
|
||||
|
||||
#ifndef DNS_TSIG_H
|
||||
#define DNS_TSIG_H 1
|
||||
@@ -62,6 +62,13 @@ struct dns_tsig_keyring {
|
||||
unsigned int writecount;
|
||||
isc_rwlock_t lock;
|
||||
isc_mem_t *mctx;
|
||||
/*
|
||||
* LRU list of generated key along with a count of the keys on the
|
||||
* list and a maximum size.
|
||||
*/
|
||||
unsigned int generated;
|
||||
unsigned int maxgenerated;
|
||||
ISC_LIST(dns_tsigkey_t) lru;
|
||||
};
|
||||
|
||||
struct dns_tsigkey {
|
||||
@@ -77,6 +84,7 @@ struct dns_tsigkey {
|
||||
isc_stdtime_t expire; /*%< end of validity period */
|
||||
dns_tsig_keyring_t *ring; /*%< the enclosing keyring */
|
||||
isc_refcount_t refs; /*%< reference counter */
|
||||
ISC_LINK(dns_tsigkey_t) link;
|
||||
};
|
||||
|
||||
#define dns_tsigkey_identity(tsigkey) \
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: name.c,v 1.171 2010/05/12 23:51:13 tbox Exp $ */
|
||||
/* $Id: name.c,v 1.172 2010/07/09 05:13:15 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -1323,6 +1323,21 @@ totext_filter_proc_key_init(void) {
|
||||
isc_result_t
|
||||
dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
isc_buffer_t *target)
|
||||
{
|
||||
unsigned int options = DNS_NAME_MASTERFILE;
|
||||
|
||||
if (omit_final_dot)
|
||||
options |= DNS_NAME_OMITFINALDOT;
|
||||
return (dns_name_totext2(name, options, target));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
|
||||
return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
|
||||
{
|
||||
unsigned char *ndata;
|
||||
char *tdata;
|
||||
@@ -1337,6 +1352,8 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
dns_name_totextfilter_t totext_filter_proc = NULL;
|
||||
isc_result_t result;
|
||||
#endif
|
||||
isc_boolean_t omit_final_dot =
|
||||
ISC_TF(options & DNS_NAME_OMITFINALDOT);
|
||||
|
||||
/*
|
||||
* This function assumes the name is in proper uncompressed
|
||||
@@ -1412,15 +1429,17 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
while (count > 0) {
|
||||
c = *ndata;
|
||||
switch (c) {
|
||||
/* Special modifiers in zone files. */
|
||||
case 0x40: /* '@' */
|
||||
case 0x24: /* '$' */
|
||||
if ((options & DNS_NAME_MASTERFILE) == 0)
|
||||
goto no_escape;
|
||||
case 0x22: /* '"' */
|
||||
case 0x28: /* '(' */
|
||||
case 0x29: /* ')' */
|
||||
case 0x2E: /* '.' */
|
||||
case 0x3B: /* ';' */
|
||||
case 0x5C: /* '\\' */
|
||||
/* Special modifiers in zone files. */
|
||||
case 0x40: /* '@' */
|
||||
case 0x24: /* '$' */
|
||||
if (trem < 2)
|
||||
return (ISC_R_NOSPACE);
|
||||
*tdata++ = '\\';
|
||||
@@ -1430,6 +1449,7 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
trem -= 2;
|
||||
nlen--;
|
||||
break;
|
||||
no_escape:
|
||||
default:
|
||||
if (c > 0x20 && c < 0x7f) {
|
||||
if (trem == 0)
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: tkey.c,v 1.92 2009/09/02 23:48:02 tbox Exp $
|
||||
* $Id: tkey.c,v 1.93 2010/07/09 05:13:15 each Exp $
|
||||
*/
|
||||
/*! \file */
|
||||
#include <config.h>
|
||||
@@ -456,18 +456,15 @@ process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
|
||||
if (result == ISC_R_SUCCESS)
|
||||
gss_ctx = dst_key_getgssctx(tsigkey->key);
|
||||
|
||||
|
||||
dns_fixedname_init(&principal);
|
||||
|
||||
result = dst_gssapi_acceptctx(tctx->gsscred, &intoken,
|
||||
&outtoken, &gss_ctx,
|
||||
dns_fixedname_name(&principal),
|
||||
tctx->mctx);
|
||||
|
||||
if (tsigkey != NULL)
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
|
||||
if (result == DNS_R_INVALIDTKEY) {
|
||||
if (tsigkey != NULL)
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
tkeyout->error = dns_tsigerror_badkey;
|
||||
tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
|
||||
return (ISC_R_SUCCESS);
|
||||
@@ -478,20 +475,38 @@ process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
|
||||
* XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
|
||||
*/
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
||||
if (tsigkey == NULL) {
|
||||
#ifdef GSSAPI
|
||||
OM_uint32 gret, minor, lifetime;
|
||||
#endif
|
||||
isc_uint32_t expire;
|
||||
|
||||
RETERR(dst_key_fromgssapi(name, gss_ctx, msg->mctx, &dstkey));
|
||||
/*
|
||||
* Limit keys to 1 hour or the context's lifetime whichever
|
||||
* is smaller.
|
||||
*/
|
||||
expire = now + 3600;
|
||||
#ifdef GSSAPI
|
||||
gret = gss_context_time(&minor, gss_ctx, &lifetime);
|
||||
if (gret == GSS_S_COMPLETE && now + lifetime < expire)
|
||||
expire = now + lifetime;
|
||||
#endif
|
||||
RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
|
||||
dstkey, ISC_TRUE,
|
||||
dns_fixedname_name(&principal),
|
||||
tkeyin->inception,
|
||||
tkeyin->expire,
|
||||
ring->mctx, ring, NULL));
|
||||
now, expire, ring->mctx, ring,
|
||||
NULL));
|
||||
tkeyout->inception = now;
|
||||
tkeyout->expire = expire;
|
||||
} else {
|
||||
tkeyout->inception = tsigkey->inception;
|
||||
tkeyout->expire = tkeyout->expire;
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
}
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
tkeyout->inception = tkeyin->inception;
|
||||
tkeyout->expire = tkeyin->expire;
|
||||
|
||||
if (outtoken) {
|
||||
tkeyout->key = isc_mem_get(tkeyout->mctx,
|
||||
isc_buffer_usedlength(outtoken));
|
||||
@@ -520,6 +535,9 @@ process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
failure:
|
||||
if (tsigkey != NULL)
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
|
||||
if (dstkey != NULL)
|
||||
dst_key_free(&dstkey);
|
||||
|
||||
@@ -1364,10 +1382,10 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
|
||||
|
||||
if (win2k == ISC_TRUE)
|
||||
RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
|
||||
DNS_SECTION_ANSWER));
|
||||
DNS_SECTION_ANSWER));
|
||||
else
|
||||
RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
|
||||
DNS_SECTION_ADDITIONAL));
|
||||
DNS_SECTION_ADDITIONAL));
|
||||
|
||||
RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: tsig.c,v 1.140 2010/03/12 23:51:11 tbox Exp $
|
||||
* $Id: tsig.c,v 1.141 2010/07/09 05:13:15 each 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 && \
|
||||
@@ -215,6 +220,31 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
|
||||
level, "tsig key '%s': %s", namestr, message);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A supplemental routine just to add a key to ring. Note that reference
|
||||
* counter should be counted separately because we may be adding the key
|
||||
@@ -241,6 +271,15 @@ keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
|
||||
}
|
||||
|
||||
result = dns_rbt_addname(ring->keys, name, tkey);
|
||||
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);
|
||||
|
||||
return (result);
|
||||
@@ -470,9 +509,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;
|
||||
}
|
||||
}
|
||||
@@ -482,7 +519,6 @@ cleanup_ring(dns_tsig_keyring_t *ring)
|
||||
dns_rbtnodechain_invalidate(&chain);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,7 +683,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);
|
||||
}
|
||||
|
||||
@@ -1490,19 +1526,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);
|
||||
}
|
||||
@@ -1548,6 +1595,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;
|
||||
|
Reference in New Issue
Block a user