summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/tsig.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/dns/tsig.c')
-rw-r--r--contrib/bind9/lib/dns/tsig.c309
1 files changed, 274 insertions, 35 deletions
diff --git a/contrib/bind9/lib/dns/tsig.c b/contrib/bind9/lib/dns/tsig.c
index 9bdde06..c5107b5 100644
--- a/contrib/bind9/lib/dns/tsig.c
+++ b/contrib/bind9/lib/dns/tsig.c
@@ -16,9 +16,9 @@
*/
/*
- * $Id: tsig.c,v 1.112.2.3.8.10 2006/05/02 04:21:42 marka Exp $
+ * $Id: tsig.c,v 1.117.18.9 2006/05/02 04:23:12 marka Exp $
*/
-
+/*! \file */
#include <config.h>
#include <stdlib.h>
@@ -48,6 +48,11 @@
#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
#define algname_is_allocated(algname) \
((algname) != dns_tsig_hmacmd5_name && \
+ (algname) != dns_tsig_hmacsha1_name && \
+ (algname) != dns_tsig_hmacsha224_name && \
+ (algname) != dns_tsig_hmacsha256_name && \
+ (algname) != dns_tsig_hmacsha384_name && \
+ (algname) != dns_tsig_hmacsha512_name && \
(algname) != dns_tsig_gssapi_name && \
(algname) != dns_tsig_gssapims_name)
@@ -96,6 +101,76 @@ static dns_name_t gsstsigms = {
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
+static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
+static unsigned char hmacsha1_offsets[] = { 0, 10 };
+
+static dns_name_t hmacsha1 = {
+ DNS_NAME_MAGIC,
+ hmacsha1_ndata, 11, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha1_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
+
+static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
+static unsigned char hmacsha224_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha224 = {
+ DNS_NAME_MAGIC,
+ hmacsha224_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha224_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
+
+static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
+static unsigned char hmacsha256_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha256 = {
+ DNS_NAME_MAGIC,
+ hmacsha256_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha256_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
+
+static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
+static unsigned char hmacsha384_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha384 = {
+ DNS_NAME_MAGIC,
+ hmacsha384_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha384_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
+
+static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
+static unsigned char hmacsha512_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha512 = {
+ DNS_NAME_MAGIC,
+ hmacsha512_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha512_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
+
static isc_result_t
tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
@@ -137,6 +212,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
REQUIRE(name != NULL);
REQUIRE(algorithm != NULL);
REQUIRE(mctx != NULL);
+ REQUIRE(key != NULL || ring != NULL);
tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
if (tkey == NULL)
@@ -154,6 +230,40 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
ret = DNS_R_BADALG;
goto cleanup_name;
}
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
+ if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
@@ -202,20 +312,14 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
tkey->key = dstkey;
tkey->ring = ring;
- if (ring != NULL) {
- RWLOCK(&ring->lock, isc_rwlocktype_write);
- ret = dns_rbt_addname(ring->keys, name, tkey);
- if (ret != ISC_R_SUCCESS) {
- RWUNLOCK(&ring->lock, isc_rwlocktype_write);
- goto cleanup_algorithm;
- }
- refs++;
- RWUNLOCK(&ring->lock, isc_rwlocktype_write);
- }
-
if (key != NULL)
refs++;
- isc_refcount_init(&tkey->refs, refs);
+ if (ring != NULL)
+ refs++;
+ ret = isc_refcount_init(&tkey->refs, refs);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_creator;
+
tkey->generated = generated;
tkey->inception = inception;
tkey->expire = expire;
@@ -223,6 +327,16 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
tkey->magic = TSIG_MAGIC;
+ if (ring != NULL) {
+ RWLOCK(&ring->lock, isc_rwlocktype_write);
+ ret = dns_rbt_addname(ring->keys, name, tkey);
+ if (ret != ISC_R_SUCCESS) {
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+ goto cleanup_refs;
+ }
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+ }
+
if (dstkey != NULL && dst_key_size(dstkey) < 64) {
char namestr[DNS_NAME_FORMATSIZE];
dns_name_format(name, namestr, sizeof(namestr));
@@ -236,6 +350,16 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
return (ISC_R_SUCCESS);
+ cleanup_refs:
+ tkey->magic = 0;
+ while (refs-- > 0)
+ isc_refcount_decrement(&tkey->refs, NULL);
+ isc_refcount_destroy(&tkey->refs);
+ cleanup_creator:
+ if (tkey->creator != NULL) {
+ dns_name_free(tkey->creator, mctx);
+ isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
+ }
cleanup_algorithm:
if (algname_is_allocated(tkey->algorithm)) {
if (dns_name_dynamic(tkey->algorithm))
@@ -264,22 +388,93 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
if (length > 0)
REQUIRE(secret != NULL);
- if (!dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && length > 0)
+ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (length > 0)
return (DNS_R_BADALG);
- if (secret != NULL) {
- isc_buffer_t b;
-
- isc_buffer_init(&b, secret, length);
- isc_buffer_add(&b, length);
- result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
- DNS_KEYOWNER_ENTITY,
- DNS_KEYPROTO_DNSSEC,
- dns_rdataclass_in,
- &b, mctx, &dstkey);
- if (result != ISC_R_SUCCESS)
- return (result);
- }
result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
generated, creator,
inception, expire, mctx, ring, key);
@@ -423,6 +618,7 @@ dns_tsig_sign(dns_message_t *msg) {
if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
unsigned char header[DNS_MESSAGE_HEADERLEN];
isc_buffer_t headerbuf;
+ isc_uint16_t digestbits;
ret = dst_context_create(key->key, mctx, &ctx);
if (ret != ISC_R_SUCCESS)
@@ -549,7 +745,16 @@ dns_tsig_sign(dns_message_t *msg) {
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
dst_context_destroy(&ctx);
- tsig.siglen = isc_buffer_usedlength(&sigbuf);
+ digestbits = dst_key_getbits(key->key);
+ if (digestbits != 0) {
+ unsigned int bytes = (digestbits + 1) / 8;
+ if (is_response(msg) && bytes < querytsig.siglen)
+ bytes = querytsig.siglen;
+ if (bytes > isc_buffer_usedlength(&sigbuf))
+ bytes = isc_buffer_usedlength(&sigbuf);
+ tsig.siglen = bytes;
+ } else
+ tsig.siglen = isc_buffer_usedlength(&sigbuf);
} else {
tsig.siglen = 0;
tsig.signature = NULL;
@@ -640,6 +845,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
dst_context_t *ctx = NULL;
isc_mem_t *mctx;
isc_uint16_t addcount, id;
+ unsigned int siglen;
+ unsigned int alg;
REQUIRE(source != NULL);
REQUIRE(DNS_MESSAGE_VALID(msg));
@@ -752,6 +959,42 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
return (DNS_R_CLOCKSKEW);
}
+ /*
+ * Check digest length.
+ */
+ alg = dst_key_alg(key);
+ ret = dst_key_sigsize(key, &siglen);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
+ alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
+ alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
+ isc_uint16_t digestbits = dst_key_getbits(key);
+ if (tsig.siglen > siglen) {
+ tsig_log(msg->tsigkey, 2, "signature length to big");
+ return (DNS_R_FORMERR);
+ }
+ if (tsig.siglen > 0 &&
+ (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
+ tsig_log(msg->tsigkey, 2,
+ "signature length below minimum");
+ return (DNS_R_FORMERR);
+ }
+ if (tsig.siglen > 0 && digestbits != 0 &&
+ tsig.siglen < ((digestbits + 1) / 8)) {
+ msg->tsigstatus = dns_tsigerror_badtrunc;
+ tsig_log(msg->tsigkey, 2,
+ "truncated signature length too small");
+ return (DNS_R_TSIGVERIFYFAILURE);
+ }
+ if (tsig.siglen > 0 && digestbits == 0 &&
+ tsig.siglen < siglen) {
+ msg->tsigstatus = dns_tsigerror_badtrunc;
+ tsig_log(msg->tsigkey, 2, "signature length too small");
+ return (DNS_R_TSIGVERIFYFAILURE);
+ }
+ }
+
if (tsig.siglen > 0) {
sig_r.base = tsig.signature;
sig_r.length = tsig.siglen;
@@ -1186,12 +1429,8 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
return (ISC_R_NOMEMORY);
result = isc_rwlock_init(&ring->lock, 0, 0);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_rwlock_init() failed: %s",
- isc_result_totext(result));
- return (ISC_R_UNEXPECTED);
- }
+ if (result != ISC_R_SUCCESS)
+ return (result);
ring->keys = NULL;
result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
OpenPOWER on IntegriCloud