6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington/*
710a238dfe2f6df8e22fb6cff944ef4fa5b1d024Tinderbox User * Copyright (C) 1999-2002, 2004-2017 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington/*
28a8f5b0de57d269cf2845c69cb6abe18cbd3b3aMark Andrews * $Id$
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <config.h>
564c1b8f42d33a66c0f5c67d66bf0cd063c8b047Brian Wellington#include <stdlib.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington#include <isc/buffer.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/mem.h>
6734ac097f78601a8194b06360e62e043dcffdb8Brian Wellington#include <isc/print.h>
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington#include <isc/refcount.h>
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt#include <isc/serial.h>
6028d1ce0380d0ba7f6c6ecd1ad20b31ddd1becbDavid Lawrence#include <isc/string.h> /* Required for HP/UX (and others?) */
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <isc/util.h>
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews#include <isc/time.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#include <pk11/site.h>
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dns/keyvalues.h>
a5e73f3e9d909e86baca18713c5697f52aca87caBrian Wellington#include <dns/log.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dns/message.h>
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews#include <dns/fixedname.h>
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington#include <dns/rbt.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dns/rdata.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dns/rdatalist.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dns/rdataset.h>
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington#include <dns/rdatastruct.h>
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence#include <dns/result.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dns/tsig.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dst/result.h>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt#ifndef DNS_TSIG_MAXGENERATEDKEYS
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt#define DNS_TSIG_MAXGENERATEDKEYS 4096
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt#endif
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington#define algname_is_allocated(algname) \
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington ((algname) != dns_tsig_hmacmd5_name && \
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews (algname) != dns_tsig_hmacsha1_name && \
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews (algname) != dns_tsig_hmacsha224_name && \
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews (algname) != dns_tsig_hmacsha256_name && \
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews (algname) != dns_tsig_hmacsha384_name && \
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews (algname) != dns_tsig_hmacsha512_name && \
0e5d6900bdfcbeef8919e6fb453ca6c44f62ccd8Brian Wellington (algname) != dns_tsig_gssapi_name && \
0e5d6900bdfcbeef8919e6fb453ca6c44f62ccd8Brian Wellington (algname) != dns_tsig_gssapims_name)
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#else
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#define algname_is_allocated(algname) \
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews ((algname) != dns_tsig_hmacsha1_name && \
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews (algname) != dns_tsig_hmacsha224_name && \
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews (algname) != dns_tsig_hmacsha256_name && \
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews (algname) != dns_tsig_hmacsha384_name && \
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews (algname) != dns_tsig_hmacsha512_name && \
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews (algname) != dns_tsig_gssapi_name && \
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews (algname) != dns_tsig_gssapims_name)
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington#define BADTIMELEN 6
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t hmacmd5 =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacmd5_ndata, hmacmd5_offsets);
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafsson
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsig_ndata[] = "\010gss-tsig";
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsig_offsets[] = { 0, 9 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t gsstsig =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(gsstsig_ndata, gsstsig_offsets);
e61793f0865117ad87a19d6e245bea8f3b712d1bDanny MayerLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews/*
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Since Microsoft doesn't follow its own standard, we will use this
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * alternate name as a second guess.
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews */
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t gsstsigms =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(gsstsigms_ndata, gsstsigms_offsets);
e61793f0865117ad87a19d6e245bea8f3b712d1bDanny MayerLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
0e5d6900bdfcbeef8919e6fb453ca6c44f62ccd8Brian Wellington
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha1_offsets[] = { 0, 10 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t hmacsha1 =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha1_ndata, hmacsha1_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha224_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t hmacsha224 =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha224_ndata, hmacsha224_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha256_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t hmacsha256 =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha256_ndata, hmacsha256_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha384_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t hmacsha384 =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha384_ndata, hmacsha384_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha512_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrewsstatic dns_name_t hmacsha512 =
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha512_ndata, hmacsha512_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtonstatic isc_result_t
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellingtontsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafssonstatic void
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafssontsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson ISC_FORMAT_PRINTF(3, 4);
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrewsstatic void
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrewscleanup_ring(dns_tsig_keyring_t *ring);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrewsstatic void
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrewstsigkey_free(dns_tsigkey_t *key);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellingtonstatic void
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellingtontsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington va_list ap;
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington char message[4096];
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington char namestr[DNS_NAME_FORMATSIZE];
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews char creatorstr[DNS_NAME_FORMATSIZE];
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington return;
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt if (key != NULL) {
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington dns_name_format(&key->name, namestr, sizeof(namestr));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt } else {
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcpy(namestr, "<null>", sizeof(namestr));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt if (key != NULL && key->generated && key->creator) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt } else {
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcpy(creatorstr, "<null>", sizeof(creatorstr));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington va_start(ap, fmt);
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington vsnprintf(message, sizeof(message), fmt, ap);
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington va_end(ap);
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt if (key != NULL && key->generated) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_log_write(dns_lctx,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews level, "tsig key '%s' (%s): %s",
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews namestr, creatorstr, message);
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt } else {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_log_write(dns_lctx,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews level, "tsig key '%s': %s", namestr, message);
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt }
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington}
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Huntstatic void
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Huntremove_fromring(dns_tsigkey_t *tkey) {
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt if (tkey->generated) {
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt tkey->ring->generated--;
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt }
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt}
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Huntstatic void
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Huntadjust_lru(dns_tsigkey_t *tkey) {
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt if (tkey->generated) {
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt /*
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt * We may have been removed from the LRU list between
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt * removing the read lock and aquiring the write lock.
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt */
0b8bd3a4ae3efd91f88e8901323faf99b5b06136Evan Hunt if (ISC_LINK_LINKED(tkey, link) &&
3c7df84b2019e454f6333ca354ef709f6451a2abMark Andrews tkey->ring->lru.tail != tkey)
0b8bd3a4ae3efd91f88e8901323faf99b5b06136Evan Hunt {
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt }
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt }
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt}
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * A supplemental routine just to add a key to ring. Note that reference
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * counter should be counted separately because we may be adding the key
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * as part of creation of the key, in which case the reference counter was
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * already initialized. Also note we don't need RWLOCK for the reference
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * counter: it's protected by a separate lock.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Huntstatic isc_result_t
351b62535d4c4f89883bfdba025999dd32490266Evan Huntkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt dns_tsigkey_t *tkey)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt{
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_result_t result;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt RWLOCK(&ring->lock, isc_rwlocktype_write);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt ring->writecount++;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt /*
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Do on the fly cleaning. Find some nodes we might not
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * want around any more.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (ring->writecount > 10) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt cleanup_ring(ring);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt ring->writecount = 0;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt result = dns_rbt_addname(ring->keys, name, tkey);
c2f8108123c40f9be5c7d8255300e578ca8a47a6Mark Andrews if (result == ISC_R_SUCCESS && tkey->generated) {
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt /*
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt * Add the new key to the LRU list and remove the least
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt * recently used key if there are too many keys on the list.
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt */
c2f8108123c40f9be5c7d8255300e578ca8a47a6Mark Andrews ISC_LIST_APPEND(ring->lru, tkey, link);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt if (ring->generated++ > ring->maxgenerated)
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt remove_fromring(ISC_LIST_HEAD(ring->lru));
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt RWUNLOCK(&ring->lock, isc_rwlocktype_write);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return (result);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonisc_result_t
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellingtondns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews dst_key_t *dstkey, isc_boolean_t generated,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dns_name_t *creator, isc_stdtime_t inception,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington isc_stdtime_t expire, isc_mem_t *mctx,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington{
3f6dc1703f76a24b34ed3bc839447291c33ca837Brian Wellington dns_tsigkey_t *tkey;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_result_t ret;
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington unsigned int refs = 0;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
e552b980379e3a7ffce1411a939c62e27f953133Brian Wellington REQUIRE(key == NULL || *key == NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(name != NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(algorithm != NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(mctx != NULL);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews REQUIRE(key != NULL || ring != NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
e552b980379e3a7ffce1411a939c62e27f953133Brian Wellington tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
e552b980379e3a7ffce1411a939c62e27f953133Brian Wellington if (tkey == NULL)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ISC_R_NOMEMORY);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_name_init(&tkey->name, NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_name_dup(name, mctx, &tkey->name);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington goto cleanup_key;
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington ret = DNS_R_BADALG;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington goto cleanup_name;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington }
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews } else
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews ret = DNS_R_BADALG;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews goto cleanup_name;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dstkey != NULL &&
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews ret = DNS_R_BADALG;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews goto cleanup_name;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dstkey != NULL &&
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews ret = DNS_R_BADALG;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews goto cleanup_name;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dstkey != NULL &&
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews ret = DNS_R_BADALG;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews goto cleanup_name;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dstkey != NULL &&
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews ret = DNS_R_BADALG;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews goto cleanup_name;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington ret = DNS_R_BADALG;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington goto cleanup_name;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington }
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
0e5d6900bdfcbeef8919e6fb453ca6c44f62ccd8Brian Wellington tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington ret = DNS_R_BADALG;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington goto cleanup_name;
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington }
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington } else {
713ad87a7f95d06f4bb3e0b92b91172cbebd6c68Mark Andrews if (dstkey != NULL) {
7863e6bd4396e99a82805feccb59275530670829Andreas Gustafsson ret = DNS_R_BADALG;
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington goto cleanup_name;
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington }
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (tkey->algorithm == NULL) {
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington ret = ISC_R_NOMEMORY;
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington goto cleanup_name;
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington }
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington dns_name_init(tkey->algorithm, NULL);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (ret != ISC_R_SUCCESS)
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington goto cleanup_algorithm;
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson NULL);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington if (creator != NULL) {
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington if (tkey->creator == NULL) {
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington ret = ISC_R_NOMEMORY;
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington goto cleanup_algorithm;
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington }
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington dns_name_init(tkey->creator, NULL);
4be64854b4a3da0465bf962caa8488699e0e0681Brian Wellington ret = dns_name_dup(creator, mctx, tkey->creator);
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington if (ret != ISC_R_SUCCESS) {
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington goto cleanup_algorithm;
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington }
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington } else
4a2f65ad8a26261e758d9682d88eb29395422fb9Brian Wellington tkey->creator = NULL;
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews tkey->key = NULL;
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews if (dstkey != NULL)
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews dst_key_attach(dstkey, &tkey->key);
49c8a96fba8d85810d470fdc7dd3388f0c767c9eBrian Wellington tkey->ring = ring;
49c8a96fba8d85810d470fdc7dd3388f0c767c9eBrian Wellington
e552b980379e3a7ffce1411a939c62e27f953133Brian Wellington if (key != NULL)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt refs = 1;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews if (ring != NULL)
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews refs++;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews ret = isc_refcount_init(&tkey->refs, refs);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews if (ret != ISC_R_SUCCESS)
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews goto cleanup_creator;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews
ac335315cddc0a42b9235001197dcf719ae737b6Brian Wellington tkey->generated = generated;
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington tkey->inception = inception;
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington tkey->expire = expire;
dc19dcbc236bc876a6cdb426ec7c5fab964f8dfcMark Andrews tkey->mctx = NULL;
dc19dcbc236bc876a6cdb426ec7c5fab964f8dfcMark Andrews isc_mem_attach(mctx, &tkey->mctx);
c2f8108123c40f9be5c7d8255300e578ca8a47a6Mark Andrews ISC_LINK_INIT(tkey, link);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington tkey->magic = TSIG_MAGIC;
b6666e61dc9b91f4ac6af3aa1172bfd8a5f2d6ffBrian Wellington
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews if (ring != NULL) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt ret = keyring_add(ring, name, tkey);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (ret != ISC_R_SUCCESS)
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews goto cleanup_refs;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews }
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews /*
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Ignore this if it's a GSS key, since the key size is meaningless.
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews */
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
70d950d16e9623fec1bc89b158047de507071ce3Brian Wellington char namestr[DNS_NAME_FORMATSIZE];
70d950d16e9623fec1bc89b158047de507071ce3Brian Wellington dns_name_format(name, namestr, sizeof(namestr));
70d950d16e9623fec1bc89b158047de507071ce3Brian Wellington isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
70d950d16e9623fec1bc89b158047de507071ce3Brian Wellington DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
26a5f97dd8770ced729025488091b77d8beb0ab6Brian Wellington "the key '%s' is too short to be secure",
26a5f97dd8770ced729025488091b77d8beb0ab6Brian Wellington namestr);
70d950d16e9623fec1bc89b158047de507071ce3Brian Wellington }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
b6666e61dc9b91f4ac6af3aa1172bfd8a5f2d6ffBrian Wellington if (key != NULL)
b6666e61dc9b91f4ac6af3aa1172bfd8a5f2d6ffBrian Wellington *key = tkey;
b6666e61dc9b91f4ac6af3aa1172bfd8a5f2d6ffBrian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ISC_R_SUCCESS);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews cleanup_refs:
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews tkey->magic = 0;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews while (refs-- > 0)
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews isc_refcount_decrement(&tkey->refs, NULL);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews isc_refcount_destroy(&tkey->refs);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews cleanup_creator:
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews if (tkey->key != NULL)
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews dst_key_free(&tkey->key);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews if (tkey->creator != NULL) {
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews dns_name_free(tkey->creator, mctx);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews }
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington cleanup_algorithm:
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (algname_is_allocated(tkey->algorithm)) {
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (dns_name_dynamic(tkey->algorithm))
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington dns_name_free(tkey->algorithm, mctx);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington }
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington cleanup_name:
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_name_free(&tkey->name, mctx);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington cleanup_key:
ddbc279e7b6a2d6ba682e60ca12956406030054bBrian Wellington isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ret);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews/*
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Find a few nodes to destroy if possible.
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews */
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrewsstatic void
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrewscleanup_ring(dns_tsig_keyring_t *ring)
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews{
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_result_t result;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_rbtnodechain_t chain;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_name_t foundname;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_fixedname_t fixedorigin;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_name_t *origin;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_stdtime_t now;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_rbtnode_t *node;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_tsigkey_t *tkey;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews /*
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Start up a new iterator each time.
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews */
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_stdtime_get(&now);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_name_init(&foundname, NULL);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_fixedname_init(&fixedorigin);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews origin = dns_fixedname_name(&fixedorigin);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews again:
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater dns_rbtnodechain_init(&chain, ring->mctx);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews origin);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_rbtnodechain_invalidate(&chain);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews return;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews for (;;) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews node = NULL;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_rbtnodechain_current(&chain, &foundname, origin, &node);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews tkey = node->data;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (tkey != NULL) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (tkey->generated
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews && isc_refcount_current(&tkey->refs) == 1
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews && tkey->inception != tkey->expire
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews && tkey->expire < now) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews tsig_log(tkey, 2, "tsig expire: deleting");
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews /* delete the key */
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_rbtnodechain_invalidate(&chain);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt remove_fromring(tkey);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews goto again;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews result = dns_rbtnodechain_next(&chain, &foundname,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews origin);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_rbtnodechain_invalidate(&chain);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews return;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews}
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsstatic void
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdestroyring(dns_tsig_keyring_t *ring) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbt_destroy(&ring->keys);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_rwlock_destroy(&ring->lock);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews}
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsstatic unsigned int
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdst_alg_fromname(dns_name_t *algorithm) {
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DST_ALG_HMACMD5);
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews } else
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DST_ALG_HMACSHA1);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DST_ALG_HMACSHA224);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DST_ALG_HMACSHA256);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DST_ALG_HMACSHA384);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DST_ALG_HMACSHA512);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
135bcc2e42a94543f11af2a4196b13552ab46d89Automatic Updater return (DST_ALG_GSSAPI);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DST_ALG_GSSAPI);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (0);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews}
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsstatic isc_result_t
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsrestore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dst_key_t *dstkey = NULL;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews char namestr[1024];
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews char creatorstr[1024];
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews char algorithmstr[1024];
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews char keystr[4096];
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews unsigned int inception, expire;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews int n;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_t b;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_name_t *name, *creator, *algorithm;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_fixedname_t fname, fcreator, falgorithm;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_result_t result;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews unsigned int dstalg;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews creatorstr, &inception, &expire, algorithmstr, keystr);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (n == EOF)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (ISC_R_NOMORE);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (n != 6)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (ISC_R_FAILURE);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (isc_serial_lt(expire, now))
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DNS_R_EXPIRED);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_fixedname_init(&fname);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews name = dns_fixedname_name(&fname);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_init(&b, namestr, strlen(namestr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_add(&b, strlen(namestr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (result);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_fixedname_init(&fcreator);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews creator = dns_fixedname_name(&fcreator);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_init(&b, creatorstr, strlen(creatorstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_add(&b, strlen(creatorstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (result);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_fixedname_init(&falgorithm);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews algorithm = dns_fixedname_name(&falgorithm);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_add(&b, strlen(algorithmstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (result);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dstalg = dst_alg_fromname(algorithm);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (dstalg == 0)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DNS_R_BADALG);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews ring->mctx, keystr, &dstkey);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (result);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
adccda3b4c426b93a45ce075bd23602b63b6afe9Mark Andrews result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews ISC_TRUE, creator, inception,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews expire, ring->mctx, ring, NULL);
0994d3a21baeedf28cbf7e461b3bd8de5f9a6654Evan Hunt if (dstkey != NULL)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dst_key_free(&dstkey);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (result);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews}
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsstatic void
0b8bd3a4ae3efd91f88e8901323faf99b5b06136Evan Huntdump_key(dns_tsigkey_t *tkey, FILE *fp) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews char *buffer = NULL;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews int length = 0;
135bcc2e42a94543f11af2a4196b13552ab46d89Automatic Updater char namestr[DNS_NAME_FORMATSIZE];
135bcc2e42a94543f11af2a4196b13552ab46d89Automatic Updater char creatorstr[DNS_NAME_FORMATSIZE];
135bcc2e42a94543f11af2a4196b13552ab46d89Automatic Updater char algorithmstr[DNS_NAME_FORMATSIZE];
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_result_t result;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
0b8bd3a4ae3efd91f88e8901323faf99b5b06136Evan Hunt REQUIRE(tkey != NULL);
0b8bd3a4ae3efd91f88e8901323faf99b5b06136Evan Hunt REQUIRE(fp != NULL);
0b8bd3a4ae3efd91f88e8901323faf99b5b06136Evan Hunt
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_name_format(&tkey->name, namestr, sizeof(namestr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result == ISC_R_SUCCESS)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews tkey->inception, tkey->expire, algorithmstr,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews length, buffer);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (buffer != NULL)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_mem_put(tkey->mctx, buffer, length);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews}
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsisc_result_t
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_result_t result;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbtnodechain_t chain;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_name_t foundname;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_fixedname_t fixedorigin;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_name_t *origin;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_stdtime_t now;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbtnode_t *node;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_tsigkey_t *tkey;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_tsig_keyring_t *ring;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews unsigned int references;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews REQUIRE(ringp != NULL && *ringp != NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews ring = *ringp;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews *ringp = NULL;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews RWLOCK(&ring->lock, isc_rwlocktype_write);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews INSIST(ring->references > 0);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews ring->references--;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews references = ring->references;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews RWUNLOCK(&ring->lock, isc_rwlocktype_write);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (references != 0)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (DNS_R_CONTINUE);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_stdtime_get(&now);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_name_init(&foundname, NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_fixedname_init(&fixedorigin);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews origin = dns_fixedname_name(&fixedorigin);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbtnodechain_init(&chain, ring->mctx);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews origin);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbtnodechain_invalidate(&chain);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews goto destroy;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews }
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews for (;;) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews node = NULL;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbtnodechain_current(&chain, &foundname, origin, &node);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews tkey = node->data;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (tkey != NULL && tkey->generated && tkey->expire >= now)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dump_key(tkey, fp);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_rbtnodechain_next(&chain, &foundname,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews origin);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbtnodechain_invalidate(&chain);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result == ISC_R_NOMORE)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = ISC_R_SUCCESS;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews goto destroy;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews }
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews }
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews destroy:
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews destroyring(ring);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return (result);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews}
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellingtonisc_result_t
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellingtondns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington unsigned char *secret, int length, isc_boolean_t generated,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dns_name_t *creator, isc_stdtime_t inception,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington isc_stdtime_t expire, isc_mem_t *mctx,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington{
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dst_key_t *dstkey = NULL;
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington isc_result_t result;
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington REQUIRE(length >= 0);
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington if (length > 0)
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington REQUIRE(secret != NULL);
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (secret != NULL) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_t b;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_init(&b, secret, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_add(&b, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYOWNER_ENTITY,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYPROTO_DNSSEC,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_rdataclass_in,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews &b, mctx, &dstkey);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (result != ISC_R_SUCCESS)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (result);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews } else
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (secret != NULL) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_t b;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_init(&b, secret, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_add(&b, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYOWNER_ENTITY,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYPROTO_DNSSEC,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_rdataclass_in,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews &b, mctx, &dstkey);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (result != ISC_R_SUCCESS)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (result);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (secret != NULL) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_t b;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_init(&b, secret, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_add(&b, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYOWNER_ENTITY,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYPROTO_DNSSEC,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_rdataclass_in,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews &b, mctx, &dstkey);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (result != ISC_R_SUCCESS)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (result);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (secret != NULL) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_t b;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_init(&b, secret, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_add(&b, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYOWNER_ENTITY,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYPROTO_DNSSEC,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_rdataclass_in,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews &b, mctx, &dstkey);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (result != ISC_R_SUCCESS)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (result);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (secret != NULL) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_t b;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_init(&b, secret, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_add(&b, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYOWNER_ENTITY,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYPROTO_DNSSEC,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_rdataclass_in,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews &b, mctx, &dstkey);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (result != ISC_R_SUCCESS)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (result);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (secret != NULL) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_t b;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_init(&b, secret, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_buffer_add(&b, length);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYOWNER_ENTITY,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews DNS_KEYPROTO_DNSSEC,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_rdataclass_in,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews &b, mctx, &dstkey);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (result != ISC_R_SUCCESS)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (result);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (length > 0)
7863e6bd4396e99a82805feccb59275530670829Andreas Gustafsson return (DNS_R_BADALG);
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington generated, creator,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington inception, expire, mctx, ring, key);
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews if (dstkey != NULL)
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dst_key_free(&dstkey);
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington return (result);
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington}
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellingtonvoid
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellingtondns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(VALID_TSIG_KEY(source));
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(targetp != NULL && *targetp == NULL);
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington isc_refcount_increment(&source->refs, NULL);
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington *targetp = source;
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington}
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington
d0345e08f26267c1d11e02af57a6555868068415Brian Wellingtonstatic void
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellingtontsigkey_free(dns_tsigkey_t *key) {
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(VALID_TSIG_KEY(key));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington key->magic = 0;
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington dns_name_free(&key->name, key->mctx);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (algname_is_allocated(key->algorithm)) {
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington dns_name_free(key->algorithm, key->mctx);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington }
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington if (key->key != NULL)
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington dst_key_free(&key->key);
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington if (key->creator != NULL) {
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington dns_name_free(key->creator, key->mctx);
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington }
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington isc_refcount_destroy(&key->refs);
dc19dcbc236bc876a6cdb426ec7c5fab964f8dfcMark Andrews isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
d0345e08f26267c1d11e02af57a6555868068415Brian Wellingtonvoid
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellingtondns_tsigkey_detach(dns_tsigkey_t **keyp) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington dns_tsigkey_t *key;
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington unsigned int refs;
d0345e08f26267c1d11e02af57a6555868068415Brian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(keyp != NULL);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(VALID_TSIG_KEY(*keyp));
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington key = *keyp;
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington isc_refcount_decrement(&key->refs, &refs);
d0345e08f26267c1d11e02af57a6555868068415Brian Wellington
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington if (refs == 0)
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington tsigkey_free(key);
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington *keyp = NULL;
d0345e08f26267c1d11e02af57a6555868068415Brian Wellington}
d0345e08f26267c1d11e02af57a6555868068415Brian Wellington
949d406b57fe80fabc6a60d36a0dcee927c780b3Brian Wellingtonvoid
949d406b57fe80fabc6a60d36a0dcee927c780b3Brian Wellingtondns_tsigkey_setdeleted(dns_tsigkey_t *key) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(VALID_TSIG_KEY(key));
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(key->ring != NULL);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWLOCK(&key->ring->lock, isc_rwlocktype_write);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt remove_fromring(key);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
949d406b57fe80fabc6a60d36a0dcee927c780b3Brian Wellington}
949d406b57fe80fabc6a60d36a0dcee927c780b3Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonisc_result_t
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtondns_tsig_sign(dns_message_t *msg) {
3f6dc1703f76a24b34ed3bc839447291c33ca837Brian Wellington dns_tsigkey_t *key;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_rdata_any_tsig_t tsig, querytsig;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington unsigned char data[128];
3b2b306f47867d0037fb851623fb5a5736d64348Michael Graff isc_buffer_t databuf, sigbuf;
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff isc_buffer_t *dynbuf;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_name_t *owner;
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews dns_rdata_t *rdata = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_rdatalist_t *datalist;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_rdataset_t *dataset;
d1cbf714097e900ed1703529584d3e1a50e8a4a8Brian Wellington isc_region_t r;
d692d9991a731d60b63e6389da1ebf2b2839cfabBrian Wellington isc_stdtime_t now;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_mem_t *mctx;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington dst_context_t *ctx = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_result_t ret;
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington unsigned char badtimedata[BADTIMELEN];
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington unsigned int sigsize = 0;
af9b975ccc2f0e6d82a4dfc2daa6cedfc5f4bdc2Mark Andrews isc_boolean_t response;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(msg != NULL);
af9b975ccc2f0e6d82a4dfc2daa6cedfc5f4bdc2Mark Andrews key = dns_message_gettsigkey(msg);
af9b975ccc2f0e6d82a4dfc2daa6cedfc5f4bdc2Mark Andrews REQUIRE(VALID_TSIG_KEY(key));
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * If this is a response, there should be a query tsig.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
af9b975ccc2f0e6d82a4dfc2daa6cedfc5f4bdc2Mark Andrews response = is_response(msg);
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews if (response && msg->querytsig == NULL)
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington return (DNS_R_EXPECTEDTSIG);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c3a4d8072ccd3b33aa3fc84cdeadd1a6fac87e08Michael Graff dynbuf = NULL;
c3a4d8072ccd3b33aa3fc84cdeadd1a6fac87e08Michael Graff
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington mctx = msg->mctx;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.mctx = mctx;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.common.rdclass = dns_rdataclass_any;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.common.rdtype = dns_rdatatype_tsig;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington ISC_LINK_INIT(&tsig.common, link);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington dns_name_init(&tsig.algorithm, NULL);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington dns_name_clone(key->algorithm, &tsig.algorithm);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
58aaab3687aac838542ee4ef65a9c094a5d34ab0Michael Graff isc_stdtime_get(&now);
19c7cce8555ccc0c95455a0c35dedd017d420d05Mark Andrews tsig.timesigned = now + msg->timeadjust;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.fudge = DNS_TSIG_FUDGE;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.originalid = msg->id;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews if (response)
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.error = msg->querytsigstatus;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington else
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.error = dns_rcode_noerror;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington if (tsig.error != dns_tsigerror_badtime) {
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.otherlen = 0;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.other = NULL;
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington } else {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_t otherbuf;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington tsig.otherlen = BADTIMELEN;
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington tsig.other = badtimedata;
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_buffer_putuint48(&otherbuf, tsig.timesigned);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if ((key->key != NULL) &&
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt (tsig.error != dns_tsigerror_badsig) &&
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt (tsig.error != dns_tsigerror_badkey))
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington unsigned char header[DNS_MESSAGE_HEADERLEN];
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_t headerbuf;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_uint16_t digestbits;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * If it is a response, we assume that the request MAC
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * has validated at this point. This is why we include a
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * MAC length > 0 in the reply.
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ret = dst_context_create3(key->key, mctx,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt DNS_LOGCATEGORY_DNSSEC,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ISC_TRUE, &ctx);
d84ce5d5c69a7e144fb90fd4b3c349e88e4dcdddBrian Wellington if (ret != ISC_R_SUCCESS)
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington return (ret);
d84ce5d5c69a7e144fb90fd4b3c349e88e4dcdddBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * If this is a response, digest the request's MAC.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (response) {
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington
37f6466aa327a5b444e41c8cb57ab5caacfe6279Evan Hunt INSIST(msg->verified_sig);
37f6466aa327a5b444e41c8cb57ab5caacfe6279Evan Hunt
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington ret = dns_rdataset_first(msg->querytsig);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington dns_rdataset_current(msg->querytsig, &querytsigrdata);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington NULL);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, querytsig.siglen);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (isc_buffer_availablelength(&databuf) <
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews querytsig.siglen) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = ISC_R_NOSPACE;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington }
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putmem(&databuf, querytsig.signature,
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington querytsig.siglen);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
d84ce5d5c69a7e144fb90fd4b3c349e88e4dcdddBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
d84ce5d5c69a7e144fb90fd4b3c349e88e4dcdddBrian Wellington }
85a873f00020e088418527a98f38ac684c937d46Mark Andrews#if defined(__clang__) && \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews ( __clang_major__ < 3 || \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews (__clang_major__ == 3 && __clang_minor__ < 2) || \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews (__clang_major__ == 4 && __clang_minor__ < 2))
85a873f00020e088418527a98f38ac684c937d46Mark Andrews /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */
85a873f00020e088418527a98f38ac684c937d46Mark Andrews else memset(&querytsig, 0, sizeof(querytsig));
85a873f00020e088418527a98f38ac684c937d46Mark Andrews#endif
d84ce5d5c69a7e144fb90fd4b3c349e88e4dcdddBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the header.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&headerbuf, header, sizeof(header));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_message_renderheader(msg, &headerbuf);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&headerbuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the remainder of the message.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(msg->buffer, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (msg->tcp_continuation == 0) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the name, class, ttl, alg.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington dns_name_toregion(&key->name, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_buffer_clear(&databuf);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_buffer_putuint16(&databuf, dns_rdataclass_any);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_buffer_putuint32(&databuf, 0); /* ttl */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington dns_name_toregion(&tsig.algorithm, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington /* Digest the timesigned and fudge */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_clear(&databuf);
106561b398eb5de295abcd402f94a88ad72ac8c0Mark Andrews if (tsig.error == dns_tsigerror_badtime) {
106561b398eb5de295abcd402f94a88ad72ac8c0Mark Andrews INSIST(response);
0c70ab306505d89983186e9f8bb8647de55b5d04Mark Andrews tsig.timesigned = querytsig.timesigned;
106561b398eb5de295abcd402f94a88ad72ac8c0Mark Andrews }
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_buffer_putuint48(&databuf, tsig.timesigned);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington isc_buffer_putuint16(&databuf, tsig.fudge);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (msg->tcp_continuation == 0) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the error and other data length.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_buffer_clear(&databuf);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington isc_buffer_putuint16(&databuf, tsig.error);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington isc_buffer_putuint16(&databuf, tsig.otherlen);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
7a30c8f783c59bffa99ac3896a5c3d7fccddf9f3Evan Hunt * Digest other data.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington if (tsig.otherlen > 0) {
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington r.length = tsig.otherlen;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington r.base = tsig.other;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
81ab85fd39c3f6c781ecac725d830364a311479dBrian Wellington ret = dst_key_sigsize(key->key, &sigsize);
d5334bc18380d25e8a7ee804f68f22dc746b9c20Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington if (tsig.signature == NULL) {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = ISC_R_NOMEMORY;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington isc_buffer_init(&sigbuf, tsig.signature, sigsize);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_sign(ctx, &sigbuf);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington goto cleanup_signature;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington dst_context_destroy(&ctx);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews digestbits = dst_key_getbits(key->key);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (digestbits != 0) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * XXXRAY: Is this correct? What is the
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * expected behavior when digestbits is not an
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * integral multiple of 8? It looks like bytes
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * should either be (digestbits/8) or
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * (digestbits+7)/8.
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt *
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * In any case, for current algorithms,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * digestbits are an integral multiple of 8, so
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * it has the same effect as (digestbits/8).
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews unsigned int bytes = (digestbits + 1) / 8;
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews if (response && bytes < querytsig.siglen)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews bytes = querytsig.siglen;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (bytes > isc_buffer_usedlength(&sigbuf))
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews bytes = isc_buffer_usedlength(&sigbuf);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tsig.siglen = bytes;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tsig.siglen = isc_buffer_usedlength(&sigbuf);
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington } else {
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.siglen = 0;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.signature = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_message_gettemprdata(msg, &rdata);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington goto cleanup_signature;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
0dc4e6a6aef01175b8cdd71cb757f09ba1e69c49Brian Wellington if (ret != ISC_R_SUCCESS)
1412643ba5bcc735c3731d8cebf71fd76eedec91Mark Andrews goto cleanup_rdata;
c3a4d8072ccd3b33aa3fc84cdeadd1a6fac87e08Michael Graff ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington dns_rdatatype_tsig, &tsig, dynbuf);
0dc4e6a6aef01175b8cdd71cb757f09ba1e69c49Brian Wellington if (ret != ISC_R_SUCCESS)
2c12fc4d63f1d5f9d55fc0ecb198d582da6fd7d3Brian Wellington goto cleanup_dynbuf;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_message_takebuffer(msg, &dynbuf);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington if (tsig.signature != NULL) {
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington isc_mem_put(mctx, tsig.signature, sigsize);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington tsig.signature = NULL;
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington owner = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_message_gettempname(msg, &owner);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
1412643ba5bcc735c3731d8cebf71fd76eedec91Mark Andrews goto cleanup_rdata;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_name_init(owner, NULL);
d1cbf714097e900ed1703529584d3e1a50e8a4a8Brian Wellington ret = dns_name_dup(&key->name, msg->mctx, owner);
d1cbf714097e900ed1703529584d3e1a50e8a4a8Brian Wellington if (ret != ISC_R_SUCCESS)
d1cbf714097e900ed1703529584d3e1a50e8a4a8Brian Wellington goto cleanup_owner;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington datalist = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_message_gettemprdatalist(msg, &datalist);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
8c56932f9a3dc252ab13a529a75f75966468a7c1Andreas Gustafsson goto cleanup_owner;
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews dataset = NULL;
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews ret = dns_message_gettemprdataset(msg, &dataset);
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews if (ret != ISC_R_SUCCESS)
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews goto cleanup_rdatalist;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington datalist->rdclass = dns_rdataclass_any;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington datalist->type = dns_rdatatype_tsig;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ISC_LIST_APPEND(datalist->rdata, rdata, link);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson == ISC_R_SUCCESS);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington msg->tsig = dataset;
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington msg->tsigname = owner;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c19f322914f380404b613fbb31f5ac2582098f9dMark Andrews /* Windows does not like the tsig name being compressed. */
c19f322914f380404b613fbb31f5ac2582098f9dMark Andrews msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
c19f322914f380404b613fbb31f5ac2582098f9dMark Andrews
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ISC_R_SUCCESS);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews cleanup_rdatalist:
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews dns_message_puttemprdatalist(msg, &datalist);
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews cleanup_owner:
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews dns_message_puttempname(msg, &owner);
1412643ba5bcc735c3731d8cebf71fd76eedec91Mark Andrews goto cleanup_rdata;
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews cleanup_dynbuf:
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews isc_buffer_free(&dynbuf);
1412643ba5bcc735c3731d8cebf71fd76eedec91Mark Andrews cleanup_rdata:
1412643ba5bcc735c3731d8cebf71fd76eedec91Mark Andrews dns_message_puttemprdata(msg, &rdata);
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews cleanup_signature:
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington if (tsig.signature != NULL)
6e5fa98df021f2b1eeb0ca6193b2f9f36e82ff36Brian Wellington isc_mem_put(mctx, tsig.signature, sigsize);
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews cleanup_context:
1412643ba5bcc735c3731d8cebf71fd76eedec91Mark Andrews if (ctx != NULL)
1412643ba5bcc735c3731d8cebf71fd76eedec91Mark Andrews dst_context_destroy(&ctx);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ret);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonisc_result_t
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtondns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
3b2efab212088496d5588ca5ed2d802c72d21a08Brian Wellington dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington{
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_rdata_any_tsig_t tsig, querytsig;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_region_t r, source_r, header_r, sig_r;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_t databuf;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington unsigned char data[32];
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_name_t *keyname;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
d692d9991a731d60b63e6389da1ebf2b2839cfabBrian Wellington isc_stdtime_t now;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_result_t ret;
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington dns_tsigkey_t *tsigkey;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dst_key_t *key = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington unsigned char header[DNS_MESSAGE_HEADERLEN];
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington dst_context_t *ctx = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_mem_t *mctx;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_uint16_t addcount, id;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews unsigned int siglen;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews unsigned int alg;
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews isc_boolean_t response;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(source != NULL);
a523752c602dc6bdb69a8d9c6267a1e4188a9782Andreas Gustafsson REQUIRE(DNS_MESSAGE_VALID(msg));
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington tsigkey = dns_message_gettsigkey(msg);
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews response = is_response(msg);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington
f7fbd68b1cd96c733140fce938a61faf8b459b6fBrian Wellington msg->verify_attempted = 1;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->verified_sig = 0;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->tsigstatus = dns_tsigerror_badsig;
f7fbd68b1cd96c733140fce938a61faf8b459b6fBrian Wellington
a8f950ff05e2e81d425a3411268cdf21f8f26b16Mark Andrews if (msg->tcp_continuation) {
a8f950ff05e2e81d425a3411268cdf21f8f26b16Mark Andrews if (tsigkey == NULL || msg->querytsig == NULL)
a8f950ff05e2e81d425a3411268cdf21f8f26b16Mark Andrews return (DNS_R_UNEXPECTEDTSIG);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington return (tsig_verify_tcp(source, msg));
a8f950ff05e2e81d425a3411268cdf21f8f26b16Mark Andrews }
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * There should be a TSIG record...
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington if (msg->tsig == NULL)
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington return (DNS_R_EXPECTEDTSIG);
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington /*
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington * If this is a response and there's no key or query TSIG, there
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington * shouldn't be one on the response.
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington */
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews if (response && (tsigkey == NULL || msg->querytsig == NULL))
05b6b2e6802d503a9e131415b4720f35ab9f08d1Brian Wellington return (DNS_R_UNEXPECTEDTSIG);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington mctx = msg->mctx;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington /*
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * If we're here, we know the message is well formed and contains a
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * TSIG record.
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington keyname = msg->tsigname;
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington ret = dns_rdataset_first(msg->tsig);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ret);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington dns_rdataset_current(msg->tsig, &rdata);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington return (ret);
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&rdata);
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews if (response) {
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington ret = dns_rdataset_first(msg->querytsig);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (ret != ISC_R_SUCCESS)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington return (ret);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington dns_rdataset_current(msg->querytsig, &rdata);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (ret != ISC_R_SUCCESS)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington return (ret);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington }
85a873f00020e088418527a98f38ac684c937d46Mark Andrews#if defined(__clang__) && \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews ( __clang_major__ < 3 || \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews (__clang_major__ == 3 && __clang_minor__ < 2) || \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews (__clang_major__ == 4 && __clang_minor__ < 2))
85a873f00020e088418527a98f38ac684c937d46Mark Andrews /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */
85a873f00020e088418527a98f38ac684c937d46Mark Andrews else memset(&querytsig, 0, sizeof(querytsig));
85a873f00020e088418527a98f38ac684c937d46Mark Andrews#endif
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Do the key name and algorithm match that of the query?
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews if (response &&
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington (!dns_name_equal(keyname, &tsigkey->name) ||
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington msg->tsigstatus = dns_tsigerror_badkey;
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2,
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington "key name and algorithm do not match");
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (DNS_R_TSIGVERIFYFAILURE);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Get the current time.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington isc_stdtime_get(&now);
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Find dns_tsigkey_t based on keyname.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington if (tsigkey == NULL) {
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington ret = ISC_R_NOTFOUND;
3b2efab212088496d5588ca5ed2d802c72d21a08Brian Wellington if (ring1 != NULL)
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington ret = dns_tsigkey_find(&tsigkey, keyname,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence &tsig.algorithm, ring1);
3b2efab212088496d5588ca5ed2d802c72d21a08Brian Wellington if (ret == ISC_R_NOTFOUND && ring2 != NULL)
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington ret = dns_tsigkey_find(&tsigkey, keyname,
3b2efab212088496d5588ca5ed2d802c72d21a08Brian Wellington &tsig.algorithm, ring2);
0f0162e6297ddf5e4abe848d27f3bcdb373189daBrian Wellington if (ret != ISC_R_SUCCESS) {
0f0162e6297ddf5e4abe848d27f3bcdb373189daBrian Wellington msg->tsigstatus = dns_tsigerror_badkey;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_tsigkey_create(keyname, &tsig.algorithm,
0f0162e6297ddf5e4abe848d27f3bcdb373189daBrian Wellington NULL, 0, ISC_FALSE, NULL,
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington now, now,
49c8a96fba8d85810d470fdc7dd3388f0c767c9eBrian Wellington mctx, NULL, &msg->tsigkey);
0f0162e6297ddf5e4abe848d27f3bcdb373189daBrian Wellington if (ret != ISC_R_SUCCESS)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington return (ret);
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2, "unknown key");
0f0162e6297ddf5e4abe848d27f3bcdb373189daBrian Wellington return (DNS_R_TSIGVERIFYFAILURE);
0f0162e6297ddf5e4abe848d27f3bcdb373189daBrian Wellington }
7077846f3bf941f626a8623bd29a56a5ce7a1e11Brian Wellington msg->tsigkey = tsigkey;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington key = tsigkey->key;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews /*
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews * Check digest length.
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews */
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews alg = dst_key_alg(key);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews ret = dst_key_sigsize(key, &siglen);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (ret != ISC_R_SUCCESS)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (ret);
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if (
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews alg == DST_ALG_HMACMD5 ||
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews alg == DST_ALG_HMACSHA1 ||
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (tsig.siglen > siglen) {
6896fdd3b22221d40a9fdd1761610e5f33b1213bEvan Hunt tsig_log(msg->tsigkey, 2, "signature length too big");
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (DNS_R_FORMERR);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (tsig.siglen > 0 &&
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2)))
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews tsig_log(msg->tsigkey, 2,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews "signature length below minimum");
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews return (DNS_R_FORMERR);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews }
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (tsig.siglen > 0) {
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman isc_uint16_t addcount_n;
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington sig_r.base = tsig.signature;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington sig_r.length = tsig.siglen;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ret = dst_context_create3(key, mctx,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt DNS_LOGCATEGORY_DNSSEC,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ISC_FALSE, &ctx);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington return (ret);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (response) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, querytsig.siglen);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (querytsig.siglen > 0) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington r.length = querytsig.siglen;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington r.base = querytsig.signature;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Extract the header.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(source, &r);
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Decrement the additional field counter.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman addcount_n = ntohs(addcount);
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman addcount = htons((isc_uint16_t)(addcount_n - 1));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Put in the original id.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington id = htons(tsig.originalid);
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&header[0], &id, 2);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the modified header.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington header_r.base = (unsigned char *) header;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington header_r.length = DNS_MESSAGE_HEADERLEN;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &header_r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest all non-TSIG records.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(source, &source_r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the key name.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_name_toregion(&tsigkey->name, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, tsig.common.rdclass);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington isc_buffer_putuint32(&databuf, msg->tsig->ttl);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the key algorithm.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington dns_name_toregion(tsigkey->algorithm, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_clear(&databuf);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_buffer_putuint48(&databuf, tsig.timesigned);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, tsig.fudge);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, tsig.error);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, tsig.otherlen);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (tsig.otherlen > 0) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington r.base = tsig.other;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington r.length = tsig.otherlen;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(ctx, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_verify(ctx, &sig_r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington if (ret == DST_R_VERIFYFAILURE) {
3aec811249fc1bde4476ced9432d3ebea0ad4dc4Brian Wellington ret = DNS_R_TSIGVERIFYFAILURE;
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews "signature failed to verify(1)");
3aec811249fc1bde4476ced9432d3ebea0ad4dc4Brian Wellington goto cleanup_context;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt } else if (ret != ISC_R_SUCCESS) {
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt }
37f6466aa327a5b444e41c8cb57ab5caacfe6279Evan Hunt msg->verified_sig = 1;
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington } else if (tsig.error != dns_tsigerror_badsig &&
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews tsig.error != dns_tsigerror_badkey) {
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2, "signature was empty");
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (DNS_R_TSIGVERIFYFAILURE);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * Here at this point, the MAC has been verified. Even if any of
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * the following code returns a TSIG error, the reply will be
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * signed and WILL always include the request MAC in the digest
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * computation.
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * Is the time ok?
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtime;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature has expired");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_CLOCKSKEW;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtime;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature is in the future");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_CLOCKSKEW;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt#ifndef PK11_MD5_DISABLE
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACMD5 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt#endif
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA1 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt isc_uint16_t digestbits = dst_key_getbits(key);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * XXXRAY: Is this correct? What is the expected
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * behavior when digestbits is not an integral multiple
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * of 8? It looks like bytes should either be
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * (digestbits/8) or (digestbits+7)/8.
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt *
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * In any case, for current algorithms, digestbits are
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * an integral multiple of 8, so it has the same effect
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * as (digestbits/8).
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (tsig.siglen > 0 && digestbits != 0 &&
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig.siglen < ((digestbits + 1) / 8))
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtrunc;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "truncated signature length too small");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_TSIGVERIFYFAILURE;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (tsig.siglen > 0 && digestbits == 0 &&
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig.siglen < siglen)
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtrunc;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature length too small");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_TSIGVERIFYFAILURE;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington if (tsig.error != dns_rcode_noerror) {
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->tsigstatus = tsig.error;
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington if (tsig.error == dns_tsigerror_badtime)
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt ret = DNS_R_CLOCKSKEW;
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington else
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt ret = DNS_R_TSIGERRORSET;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt goto cleanup_context;
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->tsigstatus = dns_rcode_noerror;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt ret = ISC_R_SUCCESS;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews cleanup_context:
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington if (ctx != NULL)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington dst_context_destroy(&ctx);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ret);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtonstatic isc_result_t
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellingtontsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_rdata_any_tsig_t tsig, querytsig;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_region_t r, source_r, header_r, sig_r;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_buffer_t databuf;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington unsigned char data[32];
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington dns_name_t *keyname;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_stdtime_t now;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_result_t ret;
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington dns_tsigkey_t *tsigkey;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington dst_key_t *key = NULL;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington unsigned char header[DNS_MESSAGE_HEADERLEN];
ac335315cddc0a42b9235001197dcf719ae737b6Brian Wellington isc_uint16_t addcount, id;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_boolean_t has_tsig = ISC_FALSE;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington isc_mem_t *mctx;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt unsigned int siglen;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt unsigned int alg;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington REQUIRE(source != NULL);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington REQUIRE(msg != NULL);
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(dns_message_gettsigkey(msg) != NULL);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington REQUIRE(msg->tcp_continuation == 1);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington REQUIRE(msg->querytsig != NULL);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->verified_sig = 0;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->tsigstatus = dns_tsigerror_badsig;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt
4b171ebd702d72200a4d7609f11c5f79d6b6f964Brian Wellington if (!is_response(msg))
4b171ebd702d72200a4d7609f11c5f79d6b6f964Brian Wellington return (DNS_R_EXPECTEDRESPONSE);
4b171ebd702d72200a4d7609f11c5f79d6b6f964Brian Wellington
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington mctx = msg->mctx;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington tsigkey = dns_message_gettsigkey(msg);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt key = tsigkey->key;
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington /*
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * Extract and parse the previous TSIG
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington */
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington ret = dns_rdataset_first(msg->querytsig);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington if (ret != ISC_R_SUCCESS)
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington return (ret);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington dns_rdataset_current(msg->querytsig, &rdata);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington if (ret != ISC_R_SUCCESS)
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington return (ret);
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&rdata);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington /*
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * If there is a TSIG in this message, do some checks.
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington */
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington if (msg->tsig != NULL) {
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington has_tsig = ISC_TRUE;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington keyname = msg->tsigname;
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington ret = dns_rdataset_first(msg->tsig);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington goto cleanup_querystruct;
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington dns_rdataset_current(msg->tsig, &rdata);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (ret != ISC_R_SUCCESS)
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington goto cleanup_querystruct;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Do the key name and algorithm match that of the query?
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington if (!dns_name_equal(keyname, &tsigkey->name) ||
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt {
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington msg->tsigstatus = dns_tsigerror_badkey;
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington ret = DNS_R_TSIGVERIFYFAILURE;
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2,
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington "key name and algorithm do not match");
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington goto cleanup_querystruct;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * Check digest length.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg = dst_key_alg(key);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = dst_key_sigsize(key, &siglen);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (ret != ISC_R_SUCCESS)
564c1b8f42d33a66c0f5c67d66bf0cd063c8b047Brian Wellington goto cleanup_querystruct;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt#ifndef PK11_MD5_DISABLE
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACMD5 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt#endif
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA1 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA224 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA256 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA384 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA512)
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (tsig.siglen > siglen) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(tsigkey, 2,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature length too big");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_FORMERR;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_querystruct;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (tsig.siglen > 0 &&
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt (tsig.siglen < 10 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig.siglen < ((siglen + 1) / 2)))
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(tsigkey, 2,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature length below minimum");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_FORMERR;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_querystruct;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (msg->tsigctx == NULL) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ret = dst_context_create3(key, mctx,
0e37e9e3d7f6de7d93212bd4596d16ebc809492eEvan Hunt DNS_LOGCATEGORY_DNSSEC,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ISC_FALSE, &msg->tsigctx);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington goto cleanup_querystruct;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington /*
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * Digest the length of the query signature
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, querytsig.siglen);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington /*
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * Digest the data of the query signature
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington */
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (querytsig.siglen > 0) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington r.length = querytsig.siglen;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington r.base = querytsig.signature;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Extract the header.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(source, &r);
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Decrement the additional field counter if necessary.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (has_tsig) {
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman isc_uint16_t addcount_n;
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman addcount_n = ntohs(addcount);
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman addcount = htons((isc_uint16_t)(addcount_n - 1));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews /*
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews * Put in the original id.
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews *
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews * XXX Can TCP transfers be forwarded? How would that
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews * work?
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews */
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington id = htons(tsig.originalid);
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&header[0], &id, 2);
dc3fc5830a90b170c0a2fbf2e8fe057aad209678Brian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the modified header.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington header_r.base = (unsigned char *) header;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington header_r.length = DNS_MESSAGE_HEADERLEN;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &header_r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest all non-TSIG records.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(source, &source_r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (has_tsig)
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington else
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the time signed and fudge.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington if (has_tsig) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_buffer_putuint48(&databuf, tsig.timesigned);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, tsig.fudge);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&databuf, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington if (ret != ISC_R_SUCCESS)
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington sig_r.base = tsig.signature;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington sig_r.length = tsig.siglen;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (tsig.siglen == 0) {
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington if (tsig.error != dns_rcode_noerror) {
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->tsigstatus = tsig.error;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt if (tsig.error == dns_tsigerror_badtime) {
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington ret = DNS_R_CLOCKSKEW;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt } else {
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington ret = DNS_R_TSIGERRORSET;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt }
5ea0d11ca45bfd1ea9db8db07f18fbb02f500661Brian Wellington } else {
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2,
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington "signature is empty");
5766ea1011051b4a9f7560041a03d9a562722df3Brian Wellington ret = DNS_R_TSIGVERIFYFAILURE;
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington }
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
5766ea1011051b4a9f7560041a03d9a562722df3Brian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_verify(msg->tsigctx, &sig_r);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington if (ret == DST_R_VERIFYFAILURE) {
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews "signature failed to verify(2)");
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = DNS_R_TSIGVERIFYFAILURE;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt } else if (ret != ISC_R_SUCCESS) {
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington goto cleanup_context;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt }
37f6466aa327a5b444e41c8cb57ab5caacfe6279Evan Hunt msg->verified_sig = 1;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * Here at this point, the MAC has been verified. Even
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * if any of the following code returns a TSIG error,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * the reply will be signed and WILL always include the
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * request MAC in the digest computation.
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * Is the time ok?
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt isc_stdtime_get(&now);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtime;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature has expired");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_CLOCKSKEW;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt } else if (now + msg->timeadjust <
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig.timesigned - tsig.fudge)
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtime;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature is in the future");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_CLOCKSKEW;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg = dst_key_alg(key);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = dst_key_sigsize(key, &siglen);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (ret != ISC_R_SUCCESS)
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt#ifndef PK11_MD5_DISABLE
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACMD5 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt#endif
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA1 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA224 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA256 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA384 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA512)
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt isc_uint16_t digestbits = dst_key_getbits(key);
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt /*
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * XXXRAY: Is this correct? What is the
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * expected behavior when digestbits is not an
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * integral multiple of 8? It looks like bytes
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * should either be (digestbits/8) or
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * (digestbits+7)/8.
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt *
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * In any case, for current algorithms,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * digestbits are an integral multiple of 8, so
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * it has the same effect as (digestbits/8).
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt */
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (tsig.siglen > 0 && digestbits != 0 &&
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig.siglen < ((digestbits + 1) / 8))
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtrunc;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "truncated signature length "
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "too small");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_TSIGVERIFYFAILURE;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (tsig.siglen > 0 && digestbits == 0 &&
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig.siglen < siglen)
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt msg->tsigstatus = dns_tsigerror_badtrunc;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2,
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature length too small");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt ret = DNS_R_TSIGVERIFYFAILURE;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt goto cleanup_context;
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt }
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt if (tsig.error != dns_rcode_noerror) {
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt msg->tsigstatus = tsig.error;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt if (tsig.error == dns_tsigerror_badtime)
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt ret = DNS_R_CLOCKSKEW;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt else
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt ret = DNS_R_TSIGERRORSET;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt goto cleanup_context;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington }
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington msg->tsigstatus = dns_rcode_noerror;
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt ret = ISC_R_SUCCESS;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington cleanup_context:
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews /*
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews * Except in error conditions, don't destroy the DST context
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews * for unsigned messages; it is a running sum till the next
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews * TSIG signed message.
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews */
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews if ((ret != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) {
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt dst_context_destroy(&msg->tsigctx);
398834f7559617bdfd6c10ba555609a2f306e3d4Mark Andrews }
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington cleanup_querystruct:
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington dns_rdata_freestruct(&querytsig);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington return (ret);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington}
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonisc_result_t
3f6dc1703f76a24b34ed3bc839447291c33ca837Brian Wellingtondns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington dns_name_t *algorithm, dns_tsig_keyring_t *ring)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington{
3f6dc1703f76a24b34ed3bc839447291c33ca837Brian Wellington dns_tsigkey_t *key;
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington isc_stdtime_t now;
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington isc_result_t result;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(tsigkey != NULL);
949d406b57fe80fabc6a60d36a0dcee927c780b3Brian Wellington REQUIRE(*tsigkey == NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(name != NULL);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington REQUIRE(ring != NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews RWLOCK(&ring->lock, isc_rwlocktype_write);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews cleanup_ring(ring);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews RWUNLOCK(&ring->lock, isc_rwlocktype_write);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington isc_stdtime_get(&now);
49c8a96fba8d85810d470fdc7dd3388f0c767c9eBrian Wellington RWLOCK(&ring->lock, isc_rwlocktype_read);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington key = NULL;
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_read);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington return (ISC_R_NOTFOUND);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington }
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_read);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington return (ISC_R_NOTFOUND);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington }
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington /*
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington * The key has expired.
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington */
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_read);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWLOCK(&ring->lock, isc_rwlocktype_write);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt remove_fromring(key);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_write);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington return (ISC_R_NOTFOUND);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt#if 0
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt /*
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt * MPAXXX We really should look at the inception time.
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt */
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt if (key->inception != key->expire &&
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt isc_serial_lt(key->inception, now)) {
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt RWUNLOCK(&ring->lock, isc_rwlocktype_read);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt adjust_lru(key);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt return (ISC_R_NOTFOUND);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt }
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt#endif
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington isc_refcount_increment(&key->refs, NULL);
49c8a96fba8d85810d470fdc7dd3388f0c767c9eBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_read);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt adjust_lru(key);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington *tsigkey = key;
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington return (ISC_R_SUCCESS);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington}
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellingtonstatic void
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellingtonfree_tsignode(void *node, void *_unused) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington dns_tsigkey_t *key;
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(node != NULL);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington
3c7df84b2019e454f6333ca354ef709f6451a2abMark Andrews UNUSED(_unused);
3c7df84b2019e454f6333ca354ef709f6451a2abMark Andrews
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington key = node;
3c7df84b2019e454f6333ca354ef709f6451a2abMark Andrews if (key->generated) {
3c7df84b2019e454f6333ca354ef709f6451a2abMark Andrews if (ISC_LINK_LINKED(key, link))
3c7df84b2019e454f6333ca354ef709f6451a2abMark Andrews ISC_LIST_UNLINK(key->ring->lru, key, link);
3c7df84b2019e454f6333ca354ef709f6451a2abMark Andrews }
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington dns_tsigkey_detach(&key);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonisc_result_t
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellingtondns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington isc_result_t result;
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington dns_tsig_keyring_t *ring;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
ffdcf33647eb0345dfe84be2c0e7b28264377436Brian Wellington REQUIRE(mctx != NULL);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(ringp != NULL);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(*ringp == NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington if (ring == NULL)
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington return (ISC_R_NOMEMORY);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington result = isc_rwlock_init(&ring->lock, 0, 0);
8327cdb88fdbf306eb4c37fe00a29aac4c2f55c5Evan Hunt if (result != ISC_R_SUCCESS) {
8327cdb88fdbf306eb4c37fe00a29aac4c2f55c5Evan Hunt isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews return (result);
8327cdb88fdbf306eb4c37fe00a29aac4c2f55c5Evan Hunt }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington ring->keys = NULL;
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington if (result != ISC_R_SUCCESS) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington isc_rwlock_destroy(&ring->lock);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington return (result);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington }
e552b980379e3a7ffce1411a939c62e27f953133Brian Wellington
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews ring->writecount = 0;
dc19dcbc236bc876a6cdb426ec7c5fab964f8dfcMark Andrews ring->mctx = NULL;
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt ring->generated = 0;
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt ISC_LIST_INIT(ring->lru);
dc19dcbc236bc876a6cdb426ec7c5fab964f8dfcMark Andrews isc_mem_attach(mctx, &ring->mctx);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews ring->references = 1;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington *ringp = ring;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (ISC_R_SUCCESS);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
351b62535d4c4f89883bfdba025999dd32490266Evan Huntisc_result_t
351b62535d4c4f89883bfdba025999dd32490266Evan Huntdns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt dns_tsigkey_t *tkey)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt{
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_result_t result;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt result = keyring_add(ring, name, tkey);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (result == ISC_R_SUCCESS)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_refcount_increment(&tkey->refs, NULL);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return (result);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonvoid
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews{
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews REQUIRE(source != NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews REQUIRE(target != NULL && *target == NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews RWLOCK(&source->lock, isc_rwlocktype_write);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews INSIST(source->references > 0);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews source->references++;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews INSIST(source->references > 0);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews *target = source;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews RWUNLOCK(&source->lock, isc_rwlocktype_write);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews}
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsvoid
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington dns_tsig_keyring_t *ring;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews unsigned int references;
8dd915daf3f75ac9d04395e61157fdea825f3ebaBrian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(ringp != NULL);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington REQUIRE(*ringp != NULL);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington ring = *ringp;
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington *ringp = NULL;
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews RWLOCK(&ring->lock, isc_rwlocktype_write);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews INSIST(ring->references > 0);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews ring->references--;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews references = ring->references;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews RWUNLOCK(&ring->lock, isc_rwlocktype_write);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (references == 0)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews destroyring(ring);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews}
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsvoid
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_stdtime_t now;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_result_t result;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_stdtime_get(&now);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews do {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = restore_key(ring, now, fp);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result == ISC_R_NOMORE)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews return;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result == DNS_R_BADALG || result == DNS_R_EXPIRED)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = ISC_R_SUCCESS;
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } while (result == ISC_R_SUCCESS);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}