710a238dfe2f6df8e22fb6cff944ef4fa5b1d024Tinderbox User * Copyright (C) 1999-2002, 2004-2017 Internet Systems Consortium, Inc. ("ISC")
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/.
6028d1ce0380d0ba7f6c6ecd1ad20b31ddd1becbDavid Lawrence#include <isc/string.h> /* Required for HP/UX (and others?) */
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacmd5_ndata, hmacmd5_offsets);
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsig_ndata[] = "\010gss-tsig";
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsig_offsets[] = { 0, 9 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(gsstsig_ndata, gsstsig_offsets);
e61793f0865117ad87a19d6e245bea8f3b712d1bDanny MayerLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Since Microsoft doesn't follow its own standard, we will use this
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * alternate name as a second guess.
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
4755b174df8221dff7e872f21d42b3572a74bf2fAndreas Gustafssonstatic unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(gsstsigms_ndata, gsstsigms_offsets);
e61793f0865117ad87a19d6e245bea8f3b712d1bDanny MayerLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha1_offsets[] = { 0, 10 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha1_ndata, hmacsha1_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha224_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha224_ndata, hmacsha224_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha256_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha256_ndata, hmacsha256_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha384_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha384_ndata, hmacsha384_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrewsstatic unsigned char hmacsha512_offsets[] = { 0, 12 };
3ed16e796dba90c96933c8a8a3f5b9404d8d3e61Mark Andrews DNS_NAME_INITABSOLUTE(hmacsha512_ndata, hmacsha512_offsets);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark AndrewsLIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellingtontsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafssontsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellingtontsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington dns_name_format(&key->name, namestr, sizeof(namestr));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt if (key != NULL && key->generated && key->creator) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcpy(creatorstr, "<null>", sizeof(creatorstr));
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington vsnprintf(message, sizeof(message), fmt, ap);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
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 RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
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 Huntkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Do on the fly cleaning. Find some nodes we might not
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * want around any more.
c2f8108123c40f9be5c7d8255300e578ca8a47a6Mark Andrews if (result == ISC_R_SUCCESS && tkey->generated) {
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.
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellingtondns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dns_name_t *creator, isc_stdtime_t inception,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
e552b980379e3a7ffce1411a939c62e27f953133Brian Wellington tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_name_dup(name, mctx, &tkey->name);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
ff7b9eede951083d1f8a1ad919611659c3e20b34Brian Wellington if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
4be64854b4a3da0465bf962caa8488699e0e0681Brian Wellington ret = dns_name_dup(creator, mctx, tkey->creator);
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Ignore this if it's a GSS key, since the key size is meaningless.
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 dns_name_format(name, namestr, sizeof(namestr));
70d950d16e9623fec1bc89b158047de507071ce3Brian Wellington isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
26a5f97dd8770ced729025488091b77d8beb0ab6Brian Wellington "the key '%s' is too short to be secure",
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews while (refs-- > 0)
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (algname_is_allocated(tkey->algorithm)) {
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
ddbc279e7b6a2d6ba682e60ca12956406030054bBrian Wellington isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Find a few nodes to destroy if possible.
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews * Start up a new iterator each time.
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater dns_rbtnodechain_init(&chain, ring->mctx);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_rbtnodechain_current(&chain, &foundname, origin, &node);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews /* delete the key */
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews result = dns_rbtnodechain_next(&chain, &foundname,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsstatic unsigned int
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsrestore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews creatorstr, &inception, &expire, algorithmstr, keystr);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_init(&b, creatorstr, strlen(creatorstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
adccda3b4c426b93a45ce075bd23602b63b6afe9Mark Andrews result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
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 fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_rbtnodechain_current(&chain, &foundname, origin, &node);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (tkey != NULL && tkey->generated && tkey->expire >= now)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews result = dns_rbtnodechain_next(&chain, &foundname,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
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 dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews } else if (length > 0)
9f9b7f0e8d455b1c88e51ddcefdbf19b472e1ef2Mark Andrews result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellingtondns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(targetp != NULL && *targetp == NULL);
100d0d2ec64ab1a85f8c0d2da9b47ae411a10b21Brian Wellington isc_refcount_increment(&source->refs, NULL);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (algname_is_allocated(key->algorithm)) {
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
dc19dcbc236bc876a6cdb426ec7c5fab964f8dfcMark Andrews isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
949d406b57fe80fabc6a60d36a0dcee927c780b3Brian Wellingtondns_tsigkey_setdeleted(dns_tsigkey_t *key) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWLOCK(&key->ring->lock, isc_rwlocktype_write);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * If this is a response, there should be a query tsig.
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington dns_name_clone(key->algorithm, &tsig.algorithm);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_buffer_putuint48(&otherbuf, tsig.timesigned);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington unsigned char header[DNS_MESSAGE_HEADERLEN];
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 * If this is a response, digest the request's MAC.
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington dns_rdataset_current(msg->querytsig, &querytsigrdata);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, querytsig.siglen);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putmem(&databuf, querytsig.signature,
85a873f00020e088418527a98f38ac684c937d46Mark Andrews#if defined(__clang__) && \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews (__clang_major__ == 3 && __clang_minor__ < 2) || \
85a873f00020e088418527a98f38ac684c937d46Mark Andrews /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the header.
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&headerbuf, header, sizeof(header));
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the remainder of the message.
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the name, class, ttl, alg.
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_buffer_putuint16(&databuf, dns_rdataclass_any);
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_buffer_putuint32(&databuf, 0); /* ttl */
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington /* Digest the timesigned and fudge */
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_buffer_putuint48(&databuf, tsig.timesigned);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington isc_buffer_putuint16(&databuf, tsig.fudge);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the error and other data length.
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington isc_buffer_putuint16(&databuf, tsig.error);
7e8dd00fce7057d1da8158b65395a09ced43a892Brian Wellington isc_buffer_putuint16(&databuf, tsig.otherlen);
7a30c8f783c59bffa99ac3896a5c3d7fccddf9f3Evan Hunt * Digest other data.
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington isc_buffer_init(&sigbuf, tsig.signature, sigsize);
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 * 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).
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_message_gettemprdata(msg, &rdata);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
c3a4d8072ccd3b33aa3fc84cdeadd1a6fac87e08Michael Graff ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
a00c5e2151cc03c06bae5cdd3b40a5de05664059Brian Wellington isc_mem_put(mctx, tsig.signature, sigsize);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_message_gettempname(msg, &owner);
d1cbf714097e900ed1703529584d3e1a50e8a4a8Brian Wellington ret = dns_name_dup(&key->name, msg->mctx, owner);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ret = dns_message_gettemprdatalist(msg, &datalist);
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews ret = dns_message_gettemprdataset(msg, &dataset);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington ISC_LIST_APPEND(datalist->rdata, rdata, link);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
c19f322914f380404b613fbb31f5ac2582098f9dMark Andrews /* Windows does not like the tsig name being compressed. */
c19f322914f380404b613fbb31f5ac2582098f9dMark Andrews msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
6e5fa98df021f2b1eeb0ca6193b2f9f36e82ff36Brian Wellington isc_mem_put(mctx, tsig.signature, sigsize);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtondns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
3b2efab212088496d5588ca5ed2d802c72d21a08Brian Wellington dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington unsigned char header[DNS_MESSAGE_HEADERLEN];
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * There should be a TSIG record...
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.
f67bcc9dc631ddc5ae263e969658331044f2b150Mark Andrews if (response && (tsigkey == NULL || msg->querytsig == NULL))
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * If we're here, we know the message is well formed and contains a
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * TSIG record.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington dns_rdataset_current(msg->querytsig, &rdata);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
85a873f00020e088418527a98f38ac684c937d46Mark Andrews#if defined(__clang__) && \
c6f03e79030a4609b31388f9946a2bab7e59e7d7Mark Andrews (__clang_major__ == 3 && __clang_minor__ < 2) || \
85a873f00020e088418527a98f38ac684c937d46Mark Andrews /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Do the key name and algorithm match that of the query?
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington (!dns_name_equal(keyname, &tsigkey->name) ||
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington "key name and algorithm do not match");
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Get the current time.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Find dns_tsigkey_t based on keyname.
3b2efab212088496d5588ca5ed2d802c72d21a08Brian Wellington if (ret == ISC_R_NOTFOUND && ring2 != NULL)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_tsigkey_create(keyname, &tsig.algorithm,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews * Check digest length.
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
6896fdd3b22221d40a9fdd1761610e5f33b1213bEvan Hunt tsig_log(msg->tsigkey, 2, "signature length too big");
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2)))
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews "signature length below minimum");
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, querytsig.siglen);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Extract the header.
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Decrement the additional field counter.
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman addcount = htons((isc_uint16_t)(addcount_n - 1));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Put in the original id.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the modified header.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest all non-TSIG records.
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the key name.
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);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the key algorithm.
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);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews "signature failed to verify(1)");
1e2749dba8aae3233b8962f1efe15385e92a77d9Brian Wellington } else if (tsig.error != dns_tsigerror_badsig &&
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington tsig_log(msg->tsigkey, 2, "signature was empty");
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 * Is the time ok?
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature has expired");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature is in the future");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
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 * 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 "truncated signature length too small");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature length too small");
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellingtontsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington unsigned char header[DNS_MESSAGE_HEADERLEN];
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington REQUIRE(dns_message_gettsigkey(msg) != NULL);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * Extract and parse the previous TSIG
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington dns_rdataset_current(msg->querytsig, &rdata);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * If there is a TSIG in this message, do some checks.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Do the key name and algorithm match that of the query?
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington if (!dns_name_equal(keyname, &tsigkey->name) ||
a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3Evan Hunt !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington "key name and algorithm do not match");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt * Check digest length.
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature length too big");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature length below minimum");
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * Digest the length of the query signature
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&databuf, data, sizeof(data));
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putuint16(&databuf, querytsig.siglen);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
809fdfba224a83fcc5a8ae4394cf2a477d13dc91Brian Wellington * Digest the data of the query signature
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Extract the header.
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Decrement the additional field counter if necessary.
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
f5a62d97e3bcb32dde26e632671ce81b5cc568f7Mukund Sivaraman addcount = htons((isc_uint16_t)(addcount_n - 1));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews * Put in the original id.
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews * XXX Can TCP transfers be forwarded? How would that
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the modified header.
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &header_r);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest all non-TSIG records.
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
d598338952797df77417e69fcb8782b73651f9a9Brian Wellington r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
c7f13217d11f26739a79f0dab391ec372b49b96bBrian Wellington r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Digest the time signed and fudge.
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);
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_adddata(msg->tsigctx, &r);
020ebf119089ef68070d6a0df2def3142f1eeff4Brian Wellington "signature is empty");
4fe8755480c108a1232b7189fd5434ab35a6b623Brian Wellington ret = dst_context_verify(msg->tsigctx, &sig_r);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews "signature failed to verify(2)");
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 * Is the time ok?
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt tsig_log(msg->tsigkey, 2, "signature has expired");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature is in the future");
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 * 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 "truncated signature length "
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "too small");
68bdc7fbc4e61589848a98b076c7360b3262817fEvan Hunt "signature length too small");
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 if ((ret != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) {
3f6dc1703f76a24b34ed3bc839447291c33ca837Brian Wellingtondns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington dns_name_t *algorithm, dns_tsig_keyring_t *ring)
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);
f2338a0d6aa0327372eb20ab5dc29502bc8c71efBrian Wellington if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_read);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington * The key has expired.
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_read);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_write);
bf9b852c3eaf2c9847f926751b57a06f1ae3d72aEvan Hunt * MPAXXX We really should look at the inception time.
49c8a96fba8d85810d470fdc7dd3388f0c767c9eBrian Wellington RWUNLOCK(&ring->lock, isc_rwlocktype_read);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellingtondns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington result = isc_rwlock_init(&ring->lock, 0, 0);
8327cdb88fdbf306eb4c37fe00a29aac4c2f55c5Evan Hunt isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
a49acbf201a411a47e18d136b38bbea8cf283adaBrian Wellington isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
351b62535d4c4f89883bfdba025999dd32490266Evan Huntdns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrewsdns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {