"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/tsig.c" (7 Sep 2020, 54046 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tsig.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.17.3_vs_9.17.4.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 #include <config.h>
   14 
   15 #include <inttypes.h>
   16 #include <stdbool.h>
   17 #include <stdlib.h>
   18 
   19 #include <isc/buffer.h>
   20 #include <isc/mem.h>
   21 #include <isc/print.h>
   22 #include <isc/refcount.h>
   23 #include <isc/serial.h>
   24 #include <isc/string.h>     /* Required for HP/UX (and others?) */
   25 #include <isc/util.h>
   26 #include <isc/time.h>
   27 
   28 #include <pk11/site.h>
   29 
   30 #include <dns/keyvalues.h>
   31 #include <dns/log.h>
   32 #include <dns/message.h>
   33 #include <dns/fixedname.h>
   34 #include <dns/rbt.h>
   35 #include <dns/rdata.h>
   36 #include <dns/rdatalist.h>
   37 #include <dns/rdataset.h>
   38 #include <dns/rdatastruct.h>
   39 #include <dns/result.h>
   40 #include <dns/tsig.h>
   41 
   42 #include <dst/result.h>
   43 
   44 #define TSIG_MAGIC      ISC_MAGIC('T', 'S', 'I', 'G')
   45 #define VALID_TSIG_KEY(x)   ISC_MAGIC_VALID(x, TSIG_MAGIC)
   46 
   47 #ifndef DNS_TSIG_MAXGENERATEDKEYS
   48 #define DNS_TSIG_MAXGENERATEDKEYS 4096
   49 #endif
   50 
   51 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
   52 #ifndef PK11_MD5_DISABLE
   53 #define algname_is_allocated(algname) \
   54     ((algname) != dns_tsig_hmacmd5_name && \
   55      (algname) != dns_tsig_hmacsha1_name && \
   56      (algname) != dns_tsig_hmacsha224_name && \
   57      (algname) != dns_tsig_hmacsha256_name && \
   58      (algname) != dns_tsig_hmacsha384_name && \
   59      (algname) != dns_tsig_hmacsha512_name && \
   60      (algname) != dns_tsig_gssapi_name && \
   61      (algname) != dns_tsig_gssapims_name)
   62 #else
   63 #define algname_is_allocated(algname) \
   64     ((algname) != dns_tsig_hmacsha1_name && \
   65      (algname) != dns_tsig_hmacsha224_name && \
   66      (algname) != dns_tsig_hmacsha256_name && \
   67      (algname) != dns_tsig_hmacsha384_name && \
   68      (algname) != dns_tsig_hmacsha512_name && \
   69      (algname) != dns_tsig_gssapi_name && \
   70      (algname) != dns_tsig_gssapims_name)
   71 #endif
   72 
   73 #define BADTIMELEN 6
   74 
   75 #ifndef PK11_MD5_DISABLE
   76 static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
   77 static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
   78 
   79 static dns_name_t hmacmd5 =
   80     DNS_NAME_INITABSOLUTE(hmacmd5_ndata, hmacmd5_offsets);
   81 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
   82 #endif
   83 
   84 static unsigned char gsstsig_ndata[] = "\010gss-tsig";
   85 static unsigned char gsstsig_offsets[] = { 0, 9 };
   86 static dns_name_t gsstsig =
   87     DNS_NAME_INITABSOLUTE(gsstsig_ndata, gsstsig_offsets);
   88 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
   89 
   90 /*
   91  * Since Microsoft doesn't follow its own standard, we will use this
   92  * alternate name as a second guess.
   93  */
   94 static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
   95 static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
   96 static dns_name_t gsstsigms =
   97     DNS_NAME_INITABSOLUTE(gsstsigms_ndata, gsstsigms_offsets);
   98 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
   99 
  100 static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
  101 static unsigned char hmacsha1_offsets[] = { 0, 10 };
  102 static dns_name_t hmacsha1 =
  103     DNS_NAME_INITABSOLUTE(hmacsha1_ndata, hmacsha1_offsets);
  104 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
  105 
  106 static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
  107 static unsigned char hmacsha224_offsets[] = { 0, 12 };
  108 static dns_name_t hmacsha224 =
  109     DNS_NAME_INITABSOLUTE(hmacsha224_ndata, hmacsha224_offsets);
  110 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
  111 
  112 static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
  113 static unsigned char hmacsha256_offsets[] = { 0, 12 };
  114 static dns_name_t hmacsha256 =
  115     DNS_NAME_INITABSOLUTE(hmacsha256_ndata, hmacsha256_offsets);
  116 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
  117 
  118 static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
  119 static unsigned char hmacsha384_offsets[] = { 0, 12 };
  120 static dns_name_t hmacsha384 =
  121     DNS_NAME_INITABSOLUTE(hmacsha384_ndata, hmacsha384_offsets);
  122 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
  123 
  124 static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
  125 static unsigned char hmacsha512_offsets[] = { 0, 12 };
  126 static dns_name_t hmacsha512 =
  127     DNS_NAME_INITABSOLUTE(hmacsha512_ndata, hmacsha512_offsets);
  128 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
  129 
  130 static isc_result_t
  131 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
  132 
  133 static void
  134 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
  135      ISC_FORMAT_PRINTF(3, 4);
  136 
  137 static void
  138 cleanup_ring(dns_tsig_keyring_t *ring);
  139 static void
  140 tsigkey_free(dns_tsigkey_t *key);
  141 
  142 static void
  143 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
  144     va_list ap;
  145     char message[4096];
  146     char namestr[DNS_NAME_FORMATSIZE];
  147     char creatorstr[DNS_NAME_FORMATSIZE];
  148 
  149     if (isc_log_wouldlog(dns_lctx, level) == false)
  150         return;
  151     if (key != NULL) {
  152         dns_name_format(&key->name, namestr, sizeof(namestr));
  153     } else {
  154         strlcpy(namestr, "<null>", sizeof(namestr));
  155     }
  156 
  157     if (key != NULL && key->generated && key->creator) {
  158         dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
  159     } else {
  160         strlcpy(creatorstr, "<null>", sizeof(creatorstr));
  161     }
  162 
  163     va_start(ap, fmt);
  164     vsnprintf(message, sizeof(message), fmt, ap);
  165     va_end(ap);
  166     if (key != NULL && key->generated) {
  167         isc_log_write(dns_lctx,
  168                   DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
  169                   level, "tsig key '%s' (%s): %s",
  170                   namestr, creatorstr, message);
  171     } else {
  172         isc_log_write(dns_lctx,
  173                   DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
  174                   level, "tsig key '%s': %s", namestr, message);
  175     }
  176 }
  177 
  178 static void
  179 remove_fromring(dns_tsigkey_t *tkey) {
  180     if (tkey->generated) {
  181         ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
  182         tkey->ring->generated--;
  183     }
  184     (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, false);
  185 }
  186 
  187 static void
  188 adjust_lru(dns_tsigkey_t *tkey) {
  189     if (tkey->generated) {
  190         RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
  191         /*
  192          * We may have been removed from the LRU list between
  193          * removing the read lock and acquiring the write lock.
  194          */
  195         if (ISC_LINK_LINKED(tkey, link) &&
  196             tkey->ring->lru.tail != tkey)
  197         {
  198             ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
  199             ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
  200         }
  201         RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
  202     }
  203 }
  204 
  205 /*
  206  * A supplemental routine just to add a key to ring.  Note that reference
  207  * counter should be counted separately because we may be adding the key
  208  * as part of creation of the key, in which case the reference counter was
  209  * already initialized.  Also note we don't need RWLOCK for the reference
  210  * counter: it's protected by a separate lock.
  211  */
  212 static isc_result_t
  213 keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
  214         dns_tsigkey_t *tkey)
  215 {
  216     isc_result_t result;
  217 
  218     RWLOCK(&ring->lock, isc_rwlocktype_write);
  219     ring->writecount++;
  220 
  221     /*
  222      * Do on the fly cleaning.  Find some nodes we might not
  223      * want around any more.
  224      */
  225     if (ring->writecount > 10) {
  226         cleanup_ring(ring);
  227         ring->writecount = 0;
  228     }
  229 
  230     result = dns_rbt_addname(ring->keys, name, tkey);
  231     if (result == ISC_R_SUCCESS && tkey->generated) {
  232         /*
  233          * Add the new key to the LRU list and remove the least
  234          * recently used key if there are too many keys on the list.
  235          */
  236         ISC_LIST_APPEND(ring->lru, tkey, link);
  237         if (ring->generated++ > ring->maxgenerated)
  238             remove_fromring(ISC_LIST_HEAD(ring->lru));
  239     }
  240     RWUNLOCK(&ring->lock, isc_rwlocktype_write);
  241 
  242     return (result);
  243 }
  244 
  245 isc_result_t
  246 dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
  247               dst_key_t *dstkey, bool generated,
  248               dns_name_t *creator, isc_stdtime_t inception,
  249               isc_stdtime_t expire, isc_mem_t *mctx,
  250               dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
  251 {
  252     dns_tsigkey_t *tkey;
  253     isc_result_t ret;
  254     unsigned int refs = 0;
  255 
  256     REQUIRE(key == NULL || *key == NULL);
  257     REQUIRE(name != NULL);
  258     REQUIRE(algorithm != NULL);
  259     REQUIRE(mctx != NULL);
  260     REQUIRE(key != NULL || ring != NULL);
  261 
  262     tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
  263     if (tkey == NULL)
  264         return (ISC_R_NOMEMORY);
  265 
  266     dns_name_init(&tkey->name, NULL);
  267     ret = dns_name_dup(name, mctx, &tkey->name);
  268     if (ret != ISC_R_SUCCESS)
  269         goto cleanup_key;
  270     (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
  271 
  272 #ifndef PK11_MD5_DISABLE
  273     if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
  274         tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
  275         if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
  276             ret = DNS_R_BADALG;
  277             goto cleanup_name;
  278         }
  279     } else
  280 #endif
  281     if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
  282         tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
  283         if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
  284             ret = DNS_R_BADALG;
  285             goto cleanup_name;
  286         }
  287     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
  288         tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
  289         if (dstkey != NULL &&
  290             dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
  291             ret = DNS_R_BADALG;
  292             goto cleanup_name;
  293         }
  294     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
  295         tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
  296         if (dstkey != NULL &&
  297             dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
  298             ret = DNS_R_BADALG;
  299             goto cleanup_name;
  300         }
  301     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
  302         tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
  303         if (dstkey != NULL &&
  304             dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
  305             ret = DNS_R_BADALG;
  306             goto cleanup_name;
  307         }
  308     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
  309         tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
  310         if (dstkey != NULL &&
  311             dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
  312             ret = DNS_R_BADALG;
  313             goto cleanup_name;
  314         }
  315     } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
  316         tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
  317         if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
  318             ret = DNS_R_BADALG;
  319             goto cleanup_name;
  320         }
  321     } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
  322         tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
  323         if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
  324             ret = DNS_R_BADALG;
  325             goto cleanup_name;
  326         }
  327     } else {
  328         if (dstkey != NULL) {
  329             ret = DNS_R_BADALG;
  330             goto cleanup_name;
  331         }
  332         tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
  333         if (tkey->algorithm == NULL) {
  334             ret = ISC_R_NOMEMORY;
  335             goto cleanup_name;
  336         }
  337         dns_name_init(tkey->algorithm, NULL);
  338         ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
  339         if (ret != ISC_R_SUCCESS)
  340             goto cleanup_algorithm;
  341         (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
  342                     NULL);
  343     }
  344 
  345     if (creator != NULL) {
  346         tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
  347         if (tkey->creator == NULL) {
  348             ret = ISC_R_NOMEMORY;
  349             goto cleanup_algorithm;
  350         }
  351         dns_name_init(tkey->creator, NULL);
  352         ret = dns_name_dup(creator, mctx, tkey->creator);
  353         if (ret != ISC_R_SUCCESS) {
  354             isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
  355             goto cleanup_algorithm;
  356         }
  357     } else
  358         tkey->creator = NULL;
  359 
  360     tkey->key = NULL;
  361     if (dstkey != NULL)
  362         dst_key_attach(dstkey, &tkey->key);
  363     tkey->ring = ring;
  364 
  365     if (key != NULL)
  366         refs = 1;
  367     if (ring != NULL)
  368         refs++;
  369     ret = isc_refcount_init(&tkey->refs, refs);
  370     if (ret != ISC_R_SUCCESS)
  371         goto cleanup_creator;
  372 
  373     tkey->generated = generated;
  374     tkey->inception = inception;
  375     tkey->expire = expire;
  376     tkey->mctx = NULL;
  377     isc_mem_attach(mctx, &tkey->mctx);
  378     ISC_LINK_INIT(tkey, link);
  379 
  380     tkey->magic = TSIG_MAGIC;
  381 
  382     if (ring != NULL) {
  383         ret = keyring_add(ring, name, tkey);
  384         if (ret != ISC_R_SUCCESS)
  385             goto cleanup_refs;
  386     }
  387 
  388     /*
  389      * Ignore this if it's a GSS key, since the key size is meaningless.
  390      */
  391     if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
  392         !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
  393         !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
  394         char namestr[DNS_NAME_FORMATSIZE];
  395         dns_name_format(name, namestr, sizeof(namestr));
  396         isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
  397                   DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
  398                   "the key '%s' is too short to be secure",
  399                   namestr);
  400     }
  401 
  402     if (key != NULL)
  403         *key = tkey;
  404 
  405     return (ISC_R_SUCCESS);
  406 
  407  cleanup_refs:
  408     tkey->magic = 0;
  409     while (refs-- > 0)
  410         isc_refcount_decrement(&tkey->refs, NULL);
  411     isc_refcount_destroy(&tkey->refs);
  412  cleanup_creator:
  413     if (tkey->key != NULL)
  414         dst_key_free(&tkey->key);
  415     if (tkey->creator != NULL) {
  416         dns_name_free(tkey->creator, mctx);
  417         isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
  418     }
  419  cleanup_algorithm:
  420     if (algname_is_allocated(tkey->algorithm)) {
  421         if (dns_name_dynamic(tkey->algorithm))
  422             dns_name_free(tkey->algorithm, mctx);
  423         isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
  424     }
  425  cleanup_name:
  426     dns_name_free(&tkey->name, mctx);
  427  cleanup_key:
  428     isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
  429 
  430     return (ret);
  431 }
  432 
  433 /*
  434  * Find a few nodes to destroy if possible.
  435  */
  436 static void
  437 cleanup_ring(dns_tsig_keyring_t *ring)
  438 {
  439     isc_result_t result;
  440     dns_rbtnodechain_t chain;
  441     dns_name_t foundname;
  442     dns_fixedname_t fixedorigin;
  443     dns_name_t *origin;
  444     isc_stdtime_t now;
  445     dns_rbtnode_t *node;
  446     dns_tsigkey_t *tkey;
  447 
  448     /*
  449      * Start up a new iterator each time.
  450      */
  451     isc_stdtime_get(&now);
  452     dns_name_init(&foundname, NULL);
  453     origin = dns_fixedname_initname(&fixedorigin);
  454 
  455  again:
  456     dns_rbtnodechain_init(&chain, ring->mctx);
  457     result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
  458                     origin);
  459     if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  460         dns_rbtnodechain_invalidate(&chain);
  461         return;
  462     }
  463 
  464     for (;;) {
  465         node = NULL;
  466         dns_rbtnodechain_current(&chain, &foundname, origin, &node);
  467         tkey = node->data;
  468         if (tkey != NULL) {
  469             if (tkey->generated
  470                 && isc_refcount_current(&tkey->refs) == 1
  471                 && tkey->inception != tkey->expire
  472                 && tkey->expire < now) {
  473                 tsig_log(tkey, 2, "tsig expire: deleting");
  474                 /* delete the key */
  475                 dns_rbtnodechain_invalidate(&chain);
  476                 remove_fromring(tkey);
  477                 goto again;
  478             }
  479         }
  480         result = dns_rbtnodechain_next(&chain, &foundname,
  481                            origin);
  482         if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  483             dns_rbtnodechain_invalidate(&chain);
  484             return;
  485         }
  486     }
  487 }
  488 
  489 static void
  490 destroyring(dns_tsig_keyring_t *ring) {
  491     dns_rbt_destroy(&ring->keys);
  492     isc_rwlock_destroy(&ring->lock);
  493     isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
  494 }
  495 
  496 static unsigned int
  497 dst_alg_fromname(dns_name_t *algorithm) {
  498 #ifndef PK11_MD5_DISABLE
  499     if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
  500         return (DST_ALG_HMACMD5);
  501     } else
  502 #endif
  503     if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
  504         return (DST_ALG_HMACSHA1);
  505     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
  506         return (DST_ALG_HMACSHA224);
  507     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
  508         return (DST_ALG_HMACSHA256);
  509     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
  510         return (DST_ALG_HMACSHA384);
  511     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
  512         return (DST_ALG_HMACSHA512);
  513     } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
  514         return (DST_ALG_GSSAPI);
  515     } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
  516         return (DST_ALG_GSSAPI);
  517     } else
  518         return (0);
  519 }
  520 
  521 static isc_result_t
  522 restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
  523     dst_key_t *dstkey = NULL;
  524     char namestr[1024];
  525     char creatorstr[1024];
  526     char algorithmstr[1024];
  527     char keystr[4096];
  528     unsigned int inception, expire;
  529     int n;
  530     isc_buffer_t b;
  531     dns_name_t *name, *creator, *algorithm;
  532     dns_fixedname_t fname, fcreator, falgorithm;
  533     isc_result_t result;
  534     unsigned int dstalg;
  535 
  536     n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
  537            creatorstr, &inception, &expire, algorithmstr, keystr);
  538     if (n == EOF)
  539         return (ISC_R_NOMORE);
  540     if (n != 6)
  541         return (ISC_R_FAILURE);
  542 
  543     if (isc_serial_lt(expire, now))
  544         return (DNS_R_EXPIRED);
  545 
  546     name = dns_fixedname_initname(&fname);
  547     isc_buffer_init(&b, namestr, strlen(namestr));
  548     isc_buffer_add(&b, strlen(namestr));
  549     result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
  550     if (result != ISC_R_SUCCESS)
  551         return (result);
  552 
  553     creator = dns_fixedname_initname(&fcreator);
  554     isc_buffer_init(&b, creatorstr, strlen(creatorstr));
  555     isc_buffer_add(&b, strlen(creatorstr));
  556     result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
  557     if (result != ISC_R_SUCCESS)
  558         return (result);
  559 
  560     algorithm = dns_fixedname_initname(&falgorithm);
  561     isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
  562     isc_buffer_add(&b, strlen(algorithmstr));
  563     result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
  564     if (result != ISC_R_SUCCESS)
  565         return (result);
  566 
  567     dstalg = dst_alg_fromname(algorithm);
  568     if (dstalg == 0)
  569         return (DNS_R_BADALG);
  570 
  571     result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
  572                  DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
  573                  ring->mctx, keystr, &dstkey);
  574     if (result != ISC_R_SUCCESS)
  575         return (result);
  576 
  577     result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
  578                        true, creator, inception,
  579                        expire, ring->mctx, ring, NULL);
  580     if (dstkey != NULL)
  581         dst_key_free(&dstkey);
  582     return (result);
  583 }
  584 
  585 static void
  586 dump_key(dns_tsigkey_t *tkey, FILE *fp) {
  587     char *buffer = NULL;
  588     int length = 0;
  589     char namestr[DNS_NAME_FORMATSIZE];
  590     char creatorstr[DNS_NAME_FORMATSIZE];
  591     char algorithmstr[DNS_NAME_FORMATSIZE];
  592     isc_result_t result;
  593 
  594     REQUIRE(tkey != NULL);
  595     REQUIRE(fp != NULL);
  596 
  597     dns_name_format(&tkey->name, namestr, sizeof(namestr));
  598     dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
  599     dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr));
  600     result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
  601     if (result == ISC_R_SUCCESS)
  602         fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
  603             tkey->inception, tkey->expire, algorithmstr,
  604             length, buffer);
  605     if (buffer != NULL)
  606         isc_mem_put(tkey->mctx, buffer, length);
  607 }
  608 
  609 isc_result_t
  610 dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
  611     isc_result_t result;
  612     dns_rbtnodechain_t chain;
  613     dns_name_t foundname;
  614     dns_fixedname_t fixedorigin;
  615     dns_name_t *origin;
  616     isc_stdtime_t now;
  617     dns_rbtnode_t *node;
  618     dns_tsigkey_t *tkey;
  619     dns_tsig_keyring_t *ring;
  620     unsigned int references;
  621 
  622     REQUIRE(ringp != NULL && *ringp != NULL);
  623 
  624     ring = *ringp;
  625     *ringp = NULL;
  626 
  627     RWLOCK(&ring->lock, isc_rwlocktype_write);
  628     INSIST(ring->references > 0);
  629     ring->references--;
  630     references = ring->references;
  631     RWUNLOCK(&ring->lock, isc_rwlocktype_write);
  632 
  633     if (references != 0)
  634         return (DNS_R_CONTINUE);
  635 
  636     isc_stdtime_get(&now);
  637     dns_name_init(&foundname, NULL);
  638     origin = dns_fixedname_initname(&fixedorigin);
  639     dns_rbtnodechain_init(&chain, ring->mctx);
  640     result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
  641                     origin);
  642     if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  643         dns_rbtnodechain_invalidate(&chain);
  644         goto destroy;
  645     }
  646 
  647     for (;;) {
  648         node = NULL;
  649         dns_rbtnodechain_current(&chain, &foundname, origin, &node);
  650         tkey = node->data;
  651         if (tkey != NULL && tkey->generated && tkey->expire >= now)
  652             dump_key(tkey, fp);
  653         result = dns_rbtnodechain_next(&chain, &foundname,
  654                            origin);
  655         if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  656             dns_rbtnodechain_invalidate(&chain);
  657             if (result == ISC_R_NOMORE)
  658                 result = ISC_R_SUCCESS;
  659             goto destroy;
  660         }
  661     }
  662 
  663  destroy:
  664     destroyring(ring);
  665     return (result);
  666 }
  667 
  668 const dns_name_t *
  669 dns_tsigkey_identity(const dns_tsigkey_t *tsigkey) {
  670     REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
  671 
  672     if (tsigkey == NULL) {
  673         return (NULL);
  674     }
  675     if (tsigkey->generated) {
  676         return (tsigkey->creator);
  677     } else {
  678         return (&tsigkey->name);
  679     }
  680 }
  681 
  682 isc_result_t
  683 dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
  684            unsigned char *secret, int length, bool generated,
  685            dns_name_t *creator, isc_stdtime_t inception,
  686            isc_stdtime_t expire, isc_mem_t *mctx,
  687            dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
  688 {
  689     dst_key_t *dstkey = NULL;
  690     isc_result_t result;
  691 
  692     REQUIRE(length >= 0);
  693     if (length > 0)
  694         REQUIRE(secret != NULL);
  695 
  696 #ifndef PK11_MD5_DISABLE
  697     if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
  698         if (secret != NULL) {
  699             isc_buffer_t b;
  700 
  701             isc_buffer_init(&b, secret, length);
  702             isc_buffer_add(&b, length);
  703             result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
  704                             DNS_KEYOWNER_ENTITY,
  705                             DNS_KEYPROTO_DNSSEC,
  706                             dns_rdataclass_in,
  707                             &b, mctx, &dstkey);
  708                 if (result != ISC_R_SUCCESS)
  709                     return (result);
  710         }
  711     } else
  712 #endif
  713     if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
  714         if (secret != NULL) {
  715             isc_buffer_t b;
  716 
  717             isc_buffer_init(&b, secret, length);
  718             isc_buffer_add(&b, length);
  719             result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
  720                             DNS_KEYOWNER_ENTITY,
  721                             DNS_KEYPROTO_DNSSEC,
  722                             dns_rdataclass_in,
  723                             &b, mctx, &dstkey);
  724                 if (result != ISC_R_SUCCESS)
  725                     return (result);
  726         }
  727     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
  728         if (secret != NULL) {
  729             isc_buffer_t b;
  730 
  731             isc_buffer_init(&b, secret, length);
  732             isc_buffer_add(&b, length);
  733             result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
  734                             DNS_KEYOWNER_ENTITY,
  735                             DNS_KEYPROTO_DNSSEC,
  736                             dns_rdataclass_in,
  737                             &b, mctx, &dstkey);
  738                 if (result != ISC_R_SUCCESS)
  739                     return (result);
  740         }
  741     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
  742         if (secret != NULL) {
  743             isc_buffer_t b;
  744 
  745             isc_buffer_init(&b, secret, length);
  746             isc_buffer_add(&b, length);
  747             result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
  748                             DNS_KEYOWNER_ENTITY,
  749                             DNS_KEYPROTO_DNSSEC,
  750                             dns_rdataclass_in,
  751                             &b, mctx, &dstkey);
  752                 if (result != ISC_R_SUCCESS)
  753                     return (result);
  754         }
  755     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
  756         if (secret != NULL) {
  757             isc_buffer_t b;
  758 
  759             isc_buffer_init(&b, secret, length);
  760             isc_buffer_add(&b, length);
  761             result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
  762                             DNS_KEYOWNER_ENTITY,
  763                             DNS_KEYPROTO_DNSSEC,
  764                             dns_rdataclass_in,
  765                             &b, mctx, &dstkey);
  766                 if (result != ISC_R_SUCCESS)
  767                     return (result);
  768         }
  769     } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
  770         if (secret != NULL) {
  771             isc_buffer_t b;
  772 
  773             isc_buffer_init(&b, secret, length);
  774             isc_buffer_add(&b, length);
  775             result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
  776                             DNS_KEYOWNER_ENTITY,
  777                             DNS_KEYPROTO_DNSSEC,
  778                             dns_rdataclass_in,
  779                             &b, mctx, &dstkey);
  780                 if (result != ISC_R_SUCCESS)
  781                     return (result);
  782         }
  783     } else if (length > 0)
  784         return (DNS_R_BADALG);
  785 
  786     result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
  787                        generated, creator,
  788                        inception, expire, mctx, ring, key);
  789     if (dstkey != NULL)
  790         dst_key_free(&dstkey);
  791     return (result);
  792 }
  793 
  794 void
  795 dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
  796     REQUIRE(VALID_TSIG_KEY(source));
  797     REQUIRE(targetp != NULL && *targetp == NULL);
  798 
  799     isc_refcount_increment(&source->refs, NULL);
  800     *targetp = source;
  801 }
  802 
  803 static void
  804 tsigkey_free(dns_tsigkey_t *key) {
  805     REQUIRE(VALID_TSIG_KEY(key));
  806 
  807     key->magic = 0;
  808     dns_name_free(&key->name, key->mctx);
  809     if (algname_is_allocated(key->algorithm)) {
  810         dns_name_free(key->algorithm, key->mctx);
  811         isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
  812     }
  813     if (key->key != NULL)
  814         dst_key_free(&key->key);
  815     if (key->creator != NULL) {
  816         dns_name_free(key->creator, key->mctx);
  817         isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
  818     }
  819     isc_refcount_destroy(&key->refs);
  820     isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
  821 }
  822 
  823 void
  824 dns_tsigkey_detach(dns_tsigkey_t **keyp) {
  825     dns_tsigkey_t *key;
  826     unsigned int refs;
  827 
  828     REQUIRE(keyp != NULL);
  829     REQUIRE(VALID_TSIG_KEY(*keyp));
  830 
  831     key = *keyp;
  832     isc_refcount_decrement(&key->refs, &refs);
  833 
  834     if (refs == 0)
  835         tsigkey_free(key);
  836 
  837     *keyp = NULL;
  838 }
  839 
  840 void
  841 dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
  842     REQUIRE(VALID_TSIG_KEY(key));
  843     REQUIRE(key->ring != NULL);
  844 
  845     RWLOCK(&key->ring->lock, isc_rwlocktype_write);
  846     remove_fromring(key);
  847     RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
  848 }
  849 
  850 isc_result_t
  851 dns_tsig_sign(dns_message_t *msg) {
  852     dns_tsigkey_t *key = NULL;
  853     dns_rdata_any_tsig_t tsig, querytsig;
  854     unsigned char data[128];
  855     isc_buffer_t databuf, sigbuf;
  856     isc_buffer_t *dynbuf = NULL;
  857     dns_name_t *owner;
  858     dns_rdata_t *rdata = NULL;
  859     dns_rdatalist_t *datalist = NULL;
  860     dns_rdataset_t *dataset = NULL;
  861     isc_region_t r;
  862     isc_stdtime_t now;
  863     isc_mem_t *mctx;
  864     dst_context_t *ctx = NULL;
  865     isc_result_t ret;
  866     unsigned char badtimedata[BADTIMELEN];
  867     unsigned int sigsize = 0;
  868     bool response;
  869 
  870     REQUIRE(msg != NULL);
  871     key = dns_message_gettsigkey(msg);
  872     REQUIRE(VALID_TSIG_KEY(key));
  873 
  874     /*
  875      * If this is a response, there should be a TSIG in the query with the
  876      * the exception if this is a TKEY request (see RFC 3645, Section 2.2).
  877      */
  878     response = is_response(msg);
  879     if (response && msg->querytsig == NULL) {
  880         if (msg->tkey != 1) {
  881             return (DNS_R_EXPECTEDTSIG);
  882         }
  883     }
  884 
  885     mctx = msg->mctx;
  886 
  887     tsig.mctx = mctx;
  888     tsig.common.rdclass = dns_rdataclass_any;
  889     tsig.common.rdtype = dns_rdatatype_tsig;
  890     ISC_LINK_INIT(&tsig.common, link);
  891     dns_name_init(&tsig.algorithm, NULL);
  892     dns_name_clone(key->algorithm, &tsig.algorithm);
  893 
  894     isc_stdtime_get(&now);
  895     tsig.timesigned = now + msg->timeadjust;
  896     tsig.fudge = DNS_TSIG_FUDGE;
  897 
  898     tsig.originalid = msg->id;
  899 
  900     isc_buffer_init(&databuf, data, sizeof(data));
  901 
  902     if (response)
  903         tsig.error = msg->querytsigstatus;
  904     else
  905         tsig.error = dns_rcode_noerror;
  906 
  907     if (tsig.error != dns_tsigerror_badtime) {
  908         tsig.otherlen = 0;
  909         tsig.other = NULL;
  910     } else {
  911         isc_buffer_t otherbuf;
  912 
  913         tsig.otherlen = BADTIMELEN;
  914         tsig.other = badtimedata;
  915         isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
  916         isc_buffer_putuint48(&otherbuf, tsig.timesigned);
  917     }
  918 
  919     if ((key->key != NULL) &&
  920         (tsig.error != dns_tsigerror_badsig) &&
  921         (tsig.error != dns_tsigerror_badkey))
  922     {
  923         unsigned char header[DNS_MESSAGE_HEADERLEN];
  924         isc_buffer_t headerbuf;
  925         uint16_t digestbits;
  926         bool querytsig_ok = false;
  927 
  928         /*
  929          * If it is a response, we assume that the request MAC
  930          * has validated at this point. This is why we include a
  931          * MAC length > 0 in the reply.
  932          */
  933         ret = dst_context_create3(key->key, mctx,
  934                       DNS_LOGCATEGORY_DNSSEC,
  935                       true, &ctx);
  936         if (ret != ISC_R_SUCCESS)
  937             return (ret);
  938 
  939         /*
  940          * If this is a response, and if there was a TSIG in
  941          * the query, digest the request's MAC.
  942          *
  943          * (Note: querytsig should be non-NULL for all
  944          * responses except TKEY responses. Those may be signed
  945          * with the newly-negotiated TSIG key even if the query
  946          * wasn't signed.)
  947          */
  948         if (response && msg->querytsig != NULL) {
  949             dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
  950 
  951             INSIST(msg->verified_sig);
  952 
  953             ret = dns_rdataset_first(msg->querytsig);
  954             if (ret != ISC_R_SUCCESS)
  955                 goto cleanup_context;
  956             dns_rdataset_current(msg->querytsig, &querytsigrdata);
  957             ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
  958                          NULL);
  959             if (ret != ISC_R_SUCCESS)
  960                 goto cleanup_context;
  961             isc_buffer_putuint16(&databuf, querytsig.siglen);
  962             if (isc_buffer_availablelength(&databuf) <
  963                 querytsig.siglen) {
  964                 ret = ISC_R_NOSPACE;
  965                 goto cleanup_context;
  966             }
  967             isc_buffer_putmem(&databuf, querytsig.signature,
  968                       querytsig.siglen);
  969             isc_buffer_usedregion(&databuf, &r);
  970             ret = dst_context_adddata(ctx, &r);
  971             if (ret != ISC_R_SUCCESS)
  972                 goto cleanup_context;
  973             querytsig_ok = true;
  974         }
  975 
  976         /*
  977          * Digest the header.
  978          */
  979         isc_buffer_init(&headerbuf, header, sizeof(header));
  980         dns_message_renderheader(msg, &headerbuf);
  981         isc_buffer_usedregion(&headerbuf, &r);
  982         ret = dst_context_adddata(ctx, &r);
  983         if (ret != ISC_R_SUCCESS)
  984             goto cleanup_context;
  985 
  986         /*
  987          * Digest the remainder of the message.
  988          */
  989         isc_buffer_usedregion(msg->buffer, &r);
  990         isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
  991         ret = dst_context_adddata(ctx, &r);
  992         if (ret != ISC_R_SUCCESS)
  993             goto cleanup_context;
  994 
  995         if (msg->tcp_continuation == 0) {
  996             /*
  997              * Digest the name, class, ttl, alg.
  998              */
  999             dns_name_toregion(&key->name, &r);
 1000             ret = dst_context_adddata(ctx, &r);
 1001             if (ret != ISC_R_SUCCESS)
 1002                 goto cleanup_context;
 1003 
 1004             isc_buffer_clear(&databuf);
 1005             isc_buffer_putuint16(&databuf, dns_rdataclass_any);
 1006             isc_buffer_putuint32(&databuf, 0); /* ttl */
 1007             isc_buffer_usedregion(&databuf, &r);
 1008             ret = dst_context_adddata(ctx, &r);
 1009             if (ret != ISC_R_SUCCESS)
 1010                 goto cleanup_context;
 1011 
 1012             dns_name_toregion(&tsig.algorithm, &r);
 1013             ret = dst_context_adddata(ctx, &r);
 1014             if (ret != ISC_R_SUCCESS)
 1015                 goto cleanup_context;
 1016 
 1017         }
 1018         /* Digest the timesigned and fudge */
 1019         isc_buffer_clear(&databuf);
 1020         if (tsig.error == dns_tsigerror_badtime && querytsig_ok) {
 1021             tsig.timesigned = querytsig.timesigned;
 1022         }
 1023         isc_buffer_putuint48(&databuf, tsig.timesigned);
 1024         isc_buffer_putuint16(&databuf, tsig.fudge);
 1025         isc_buffer_usedregion(&databuf, &r);
 1026         ret = dst_context_adddata(ctx, &r);
 1027         if (ret != ISC_R_SUCCESS)
 1028             goto cleanup_context;
 1029 
 1030         if (msg->tcp_continuation == 0) {
 1031             /*
 1032              * Digest the error and other data length.
 1033              */
 1034             isc_buffer_clear(&databuf);
 1035             isc_buffer_putuint16(&databuf, tsig.error);
 1036             isc_buffer_putuint16(&databuf, tsig.otherlen);
 1037 
 1038             isc_buffer_usedregion(&databuf, &r);
 1039             ret = dst_context_adddata(ctx, &r);
 1040             if (ret != ISC_R_SUCCESS)
 1041                 goto cleanup_context;
 1042 
 1043             /*
 1044              * Digest other data.
 1045              */
 1046             if (tsig.otherlen > 0) {
 1047                 r.length = tsig.otherlen;
 1048                 r.base = tsig.other;
 1049                 ret = dst_context_adddata(ctx, &r);
 1050                 if (ret != ISC_R_SUCCESS)
 1051                     goto cleanup_context;
 1052             }
 1053         }
 1054 
 1055         ret = dst_key_sigsize(key->key, &sigsize);
 1056         if (ret != ISC_R_SUCCESS)
 1057             goto cleanup_context;
 1058         tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
 1059         if (tsig.signature == NULL) {
 1060             ret = ISC_R_NOMEMORY;
 1061             goto cleanup_context;
 1062         }
 1063 
 1064         isc_buffer_init(&sigbuf, tsig.signature, sigsize);
 1065         ret = dst_context_sign(ctx, &sigbuf);
 1066         if (ret != ISC_R_SUCCESS)
 1067             goto cleanup_signature;
 1068         dst_context_destroy(&ctx);
 1069         digestbits = dst_key_getbits(key->key);
 1070         if (digestbits != 0) {
 1071             unsigned int bytes = (digestbits + 7) / 8;
 1072             if (querytsig_ok && bytes < querytsig.siglen)
 1073                 bytes = querytsig.siglen;
 1074             if (bytes > isc_buffer_usedlength(&sigbuf))
 1075                 bytes = isc_buffer_usedlength(&sigbuf);
 1076             tsig.siglen = bytes;
 1077         } else
 1078             tsig.siglen = isc_buffer_usedlength(&sigbuf);
 1079     } else {
 1080         tsig.siglen = 0;
 1081         tsig.signature = NULL;
 1082     }
 1083 
 1084     ret = dns_message_gettemprdata(msg, &rdata);
 1085     if (ret != ISC_R_SUCCESS)
 1086         goto cleanup_signature;
 1087     ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
 1088     if (ret != ISC_R_SUCCESS)
 1089         goto cleanup_rdata;
 1090     ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
 1091                    dns_rdatatype_tsig, &tsig, dynbuf);
 1092     if (ret != ISC_R_SUCCESS)
 1093         goto cleanup_dynbuf;
 1094 
 1095     dns_message_takebuffer(msg, &dynbuf);
 1096 
 1097     if (tsig.signature != NULL) {
 1098         isc_mem_put(mctx, tsig.signature, sigsize);
 1099         tsig.signature = NULL;
 1100     }
 1101 
 1102     owner = NULL;
 1103     ret = dns_message_gettempname(msg, &owner);
 1104     if (ret != ISC_R_SUCCESS)
 1105         goto cleanup_rdata;
 1106     dns_name_init(owner, NULL);
 1107     ret = dns_name_dup(&key->name, msg->mctx, owner);
 1108     if (ret != ISC_R_SUCCESS)
 1109         goto cleanup_owner;
 1110 
 1111     datalist = NULL;
 1112     ret = dns_message_gettemprdatalist(msg, &datalist);
 1113     if (ret != ISC_R_SUCCESS)
 1114         goto cleanup_owner;
 1115     dataset = NULL;
 1116     ret = dns_message_gettemprdataset(msg, &dataset);
 1117     if (ret != ISC_R_SUCCESS)
 1118         goto cleanup_rdatalist;
 1119     datalist->rdclass = dns_rdataclass_any;
 1120     datalist->type = dns_rdatatype_tsig;
 1121     ISC_LIST_APPEND(datalist->rdata, rdata, link);
 1122     RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
 1123               == ISC_R_SUCCESS);
 1124     msg->tsig = dataset;
 1125     msg->tsigname = owner;
 1126 
 1127     /* Windows does not like the tsig name being compressed. */
 1128     msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
 1129 
 1130     return (ISC_R_SUCCESS);
 1131 
 1132  cleanup_rdatalist:
 1133     dns_message_puttemprdatalist(msg, &datalist);
 1134  cleanup_owner:
 1135     dns_message_puttempname(msg, &owner);
 1136     goto cleanup_rdata;
 1137  cleanup_dynbuf:
 1138     isc_buffer_free(&dynbuf);
 1139  cleanup_rdata:
 1140     dns_message_puttemprdata(msg, &rdata);
 1141  cleanup_signature:
 1142     if (tsig.signature != NULL)
 1143         isc_mem_put(mctx, tsig.signature, sigsize);
 1144  cleanup_context:
 1145     if (ctx != NULL)
 1146         dst_context_destroy(&ctx);
 1147     return (ret);
 1148 }
 1149 
 1150 isc_result_t
 1151 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
 1152         dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
 1153 {
 1154     dns_rdata_any_tsig_t tsig, querytsig;
 1155     isc_region_t r, source_r, header_r, sig_r;
 1156     isc_buffer_t databuf;
 1157     unsigned char data[32];
 1158     dns_name_t *keyname;
 1159     dns_rdata_t rdata = DNS_RDATA_INIT;
 1160     isc_stdtime_t now;
 1161     isc_result_t ret;
 1162     dns_tsigkey_t *tsigkey;
 1163     dst_key_t *key = NULL;
 1164     unsigned char header[DNS_MESSAGE_HEADERLEN];
 1165     dst_context_t *ctx = NULL;
 1166     isc_mem_t *mctx;
 1167     uint16_t addcount, id;
 1168     unsigned int siglen;
 1169     unsigned int alg;
 1170     bool response;
 1171 
 1172     REQUIRE(source != NULL);
 1173     REQUIRE(DNS_MESSAGE_VALID(msg));
 1174     tsigkey = dns_message_gettsigkey(msg);
 1175     response = is_response(msg);
 1176 
 1177     REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
 1178 
 1179     msg->verify_attempted = 1;
 1180     msg->verified_sig = 0;
 1181     msg->tsigstatus = dns_tsigerror_badsig;
 1182 
 1183     if (msg->tcp_continuation) {
 1184         if (tsigkey == NULL || msg->querytsig == NULL)
 1185             return (DNS_R_UNEXPECTEDTSIG);
 1186         return (tsig_verify_tcp(source, msg));
 1187     }
 1188 
 1189     /*
 1190      * There should be a TSIG record...
 1191      */
 1192     if (msg->tsig == NULL)
 1193         return (DNS_R_EXPECTEDTSIG);
 1194 
 1195     /*
 1196      * If this is a response and there's no key or query TSIG, there
 1197      * shouldn't be one on the response.
 1198      */
 1199     if (response && (tsigkey == NULL || msg->querytsig == NULL))
 1200         return (DNS_R_UNEXPECTEDTSIG);
 1201 
 1202     mctx = msg->mctx;
 1203 
 1204     /*
 1205      * If we're here, we know the message is well formed and contains a
 1206      * TSIG record.
 1207      */
 1208 
 1209     keyname = msg->tsigname;
 1210     ret = dns_rdataset_first(msg->tsig);
 1211     if (ret != ISC_R_SUCCESS)
 1212         return (ret);
 1213     dns_rdataset_current(msg->tsig, &rdata);
 1214     ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
 1215     if (ret != ISC_R_SUCCESS)
 1216         return (ret);
 1217     dns_rdata_reset(&rdata);
 1218     if (response) {
 1219         ret = dns_rdataset_first(msg->querytsig);
 1220         if (ret != ISC_R_SUCCESS)
 1221             return (ret);
 1222         dns_rdataset_current(msg->querytsig, &rdata);
 1223         ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
 1224         if (ret != ISC_R_SUCCESS)
 1225             return (ret);
 1226     }
 1227 #if defined(__clang__) && \
 1228        ( __clang_major__ < 3 || \
 1229     (__clang_major__ == 3 && __clang_minor__ < 2) || \
 1230     (__clang_major__ == 4 && __clang_minor__ < 2))
 1231     /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */
 1232         else memset(&querytsig, 0, sizeof(querytsig));
 1233 #endif
 1234 
 1235     /*
 1236      * Do the key name and algorithm match that of the query?
 1237      */
 1238     if (response &&
 1239         (!dns_name_equal(keyname, &tsigkey->name) ||
 1240          !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
 1241         msg->tsigstatus = dns_tsigerror_badkey;
 1242         tsig_log(msg->tsigkey, 2,
 1243              "key name and algorithm do not match");
 1244         return (DNS_R_TSIGVERIFYFAILURE);
 1245     }
 1246 
 1247     /*
 1248      * Get the current time.
 1249      */
 1250     isc_stdtime_get(&now);
 1251 
 1252     /*
 1253      * Find dns_tsigkey_t based on keyname.
 1254      */
 1255     if (tsigkey == NULL) {
 1256         ret = ISC_R_NOTFOUND;
 1257         if (ring1 != NULL)
 1258             ret = dns_tsigkey_find(&tsigkey, keyname,
 1259                            &tsig.algorithm, ring1);
 1260         if (ret == ISC_R_NOTFOUND && ring2 != NULL)
 1261             ret = dns_tsigkey_find(&tsigkey, keyname,
 1262                            &tsig.algorithm, ring2);
 1263         if (ret != ISC_R_SUCCESS) {
 1264             msg->tsigstatus = dns_tsigerror_badkey;
 1265             ret = dns_tsigkey_create(keyname, &tsig.algorithm,
 1266                          NULL, 0, false, NULL,
 1267                          now, now,
 1268                          mctx, NULL, &msg->tsigkey);
 1269             if (ret != ISC_R_SUCCESS)
 1270                 return (ret);
 1271             tsig_log(msg->tsigkey, 2, "unknown key");
 1272             return (DNS_R_TSIGVERIFYFAILURE);
 1273         }
 1274         msg->tsigkey = tsigkey;
 1275     }
 1276 
 1277     key = tsigkey->key;
 1278 
 1279     /*
 1280      * Check digest length.
 1281      */
 1282     alg = dst_key_alg(key);
 1283     ret = dst_key_sigsize(key, &siglen);
 1284     if (ret != ISC_R_SUCCESS)
 1285         return (ret);
 1286     if (
 1287 #ifndef PK11_MD5_DISABLE
 1288         alg == DST_ALG_HMACMD5 ||
 1289 #endif
 1290         alg == DST_ALG_HMACSHA1 ||
 1291         alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
 1292         alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
 1293     {
 1294         if (tsig.siglen > siglen) {
 1295             tsig_log(msg->tsigkey, 2, "signature length too big");
 1296             return (DNS_R_FORMERR);
 1297         }
 1298         if (tsig.siglen > 0 &&
 1299             (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2)))
 1300         {
 1301             tsig_log(msg->tsigkey, 2,
 1302                  "signature length below minimum");
 1303             return (DNS_R_FORMERR);
 1304         }
 1305     }
 1306 
 1307     if (tsig.siglen > 0) {
 1308         uint16_t addcount_n;
 1309 
 1310         sig_r.base = tsig.signature;
 1311         sig_r.length = tsig.siglen;
 1312 
 1313         ret = dst_context_create3(key, mctx,
 1314                       DNS_LOGCATEGORY_DNSSEC,
 1315                       false, &ctx);
 1316         if (ret != ISC_R_SUCCESS)
 1317             return (ret);
 1318 
 1319         if (response) {
 1320             isc_buffer_init(&databuf, data, sizeof(data));
 1321             isc_buffer_putuint16(&databuf, querytsig.siglen);
 1322             isc_buffer_usedregion(&databuf, &r);
 1323             ret = dst_context_adddata(ctx, &r);
 1324             if (ret != ISC_R_SUCCESS)
 1325                 goto cleanup_context;
 1326             if (querytsig.siglen > 0) {
 1327                 r.length = querytsig.siglen;
 1328                 r.base = querytsig.signature;
 1329                 ret = dst_context_adddata(ctx, &r);
 1330                 if (ret != ISC_R_SUCCESS)
 1331                     goto cleanup_context;
 1332             }
 1333         }
 1334 
 1335         /*
 1336          * Extract the header.
 1337          */
 1338         isc_buffer_usedregion(source, &r);
 1339         memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
 1340         isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
 1341 
 1342         /*
 1343          * Decrement the additional field counter.
 1344          */
 1345         memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
 1346         addcount_n = ntohs(addcount);
 1347         addcount = htons((uint16_t)(addcount_n - 1));
 1348         memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
 1349 
 1350         /*
 1351          * Put in the original id.
 1352          */
 1353         id = htons(tsig.originalid);
 1354         memmove(&header[0], &id, 2);
 1355 
 1356         /*
 1357          * Digest the modified header.
 1358          */
 1359         header_r.base = (unsigned char *) header;
 1360         header_r.length = DNS_MESSAGE_HEADERLEN;
 1361         ret = dst_context_adddata(ctx, &header_r);
 1362         if (ret != ISC_R_SUCCESS)
 1363             goto cleanup_context;
 1364 
 1365         /*
 1366          * Digest all non-TSIG records.
 1367          */
 1368         isc_buffer_usedregion(source, &source_r);
 1369         r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
 1370         r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
 1371         ret = dst_context_adddata(ctx, &r);
 1372         if (ret != ISC_R_SUCCESS)
 1373             goto cleanup_context;
 1374 
 1375         /*
 1376          * Digest the key name.
 1377          */
 1378         dns_name_toregion(&tsigkey->name, &r);
 1379         ret = dst_context_adddata(ctx, &r);
 1380         if (ret != ISC_R_SUCCESS)
 1381             goto cleanup_context;
 1382 
 1383         isc_buffer_init(&databuf, data, sizeof(data));
 1384         isc_buffer_putuint16(&databuf, tsig.common.rdclass);
 1385         isc_buffer_putuint32(&databuf, msg->tsig->ttl);
 1386         isc_buffer_usedregion(&databuf, &r);
 1387         ret = dst_context_adddata(ctx, &r);
 1388         if (ret != ISC_R_SUCCESS)
 1389             goto cleanup_context;
 1390 
 1391         /*
 1392          * Digest the key algorithm.
 1393          */
 1394         dns_name_toregion(tsigkey->algorithm, &r);
 1395         ret = dst_context_adddata(ctx, &r);
 1396         if (ret != ISC_R_SUCCESS)
 1397             goto cleanup_context;
 1398 
 1399         isc_buffer_clear(&databuf);
 1400         isc_buffer_putuint48(&databuf, tsig.timesigned);
 1401         isc_buffer_putuint16(&databuf, tsig.fudge);
 1402         isc_buffer_putuint16(&databuf, tsig.error);
 1403         isc_buffer_putuint16(&databuf, tsig.otherlen);
 1404         isc_buffer_usedregion(&databuf, &r);
 1405         ret = dst_context_adddata(ctx, &r);
 1406         if (ret != ISC_R_SUCCESS)
 1407             goto cleanup_context;
 1408 
 1409         if (tsig.otherlen > 0) {
 1410             r.base = tsig.other;
 1411             r.length = tsig.otherlen;
 1412             ret = dst_context_adddata(ctx, &r);
 1413             if (ret != ISC_R_SUCCESS)
 1414                 goto cleanup_context;
 1415         }
 1416 
 1417         ret = dst_context_verify(ctx, &sig_r);
 1418         if (ret == DST_R_VERIFYFAILURE) {
 1419             ret = DNS_R_TSIGVERIFYFAILURE;
 1420             tsig_log(msg->tsigkey, 2,
 1421                  "signature failed to verify(1)");
 1422             goto cleanup_context;
 1423         } else if (ret != ISC_R_SUCCESS) {
 1424             goto cleanup_context;
 1425         }
 1426         msg->verified_sig = 1;
 1427     } else if (!response || (tsig.error != dns_tsigerror_badsig &&
 1428                  tsig.error != dns_tsigerror_badkey))
 1429     {
 1430         tsig_log(msg->tsigkey, 2, "signature was empty");
 1431         return (DNS_R_TSIGVERIFYFAILURE);
 1432     }
 1433 
 1434     /*
 1435      * Here at this point, the MAC has been verified. Even if any of
 1436      * the following code returns a TSIG error, the reply will be
 1437      * signed and WILL always include the request MAC in the digest
 1438      * computation.
 1439      */
 1440 
 1441     /*
 1442      * Is the time ok?
 1443      */
 1444     if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
 1445         msg->tsigstatus = dns_tsigerror_badtime;
 1446         tsig_log(msg->tsigkey, 2, "signature has expired");
 1447         ret = DNS_R_CLOCKSKEW;
 1448         goto cleanup_context;
 1449     } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
 1450         msg->tsigstatus = dns_tsigerror_badtime;
 1451         tsig_log(msg->tsigkey, 2, "signature is in the future");
 1452         ret = DNS_R_CLOCKSKEW;
 1453         goto cleanup_context;
 1454     }
 1455 
 1456     if (
 1457 #ifndef PK11_MD5_DISABLE
 1458         alg == DST_ALG_HMACMD5 ||
 1459 #endif
 1460         alg == DST_ALG_HMACSHA1 ||
 1461         alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
 1462         alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
 1463     {
 1464         uint16_t digestbits = dst_key_getbits(key);
 1465 
 1466         if (tsig.siglen > 0 && digestbits != 0 &&
 1467             tsig.siglen < ((digestbits + 7) / 8))
 1468         {
 1469             msg->tsigstatus = dns_tsigerror_badtrunc;
 1470             tsig_log(msg->tsigkey, 2,
 1471                  "truncated signature length too small");
 1472             ret = DNS_R_TSIGVERIFYFAILURE;
 1473             goto cleanup_context;
 1474         }
 1475         if (tsig.siglen > 0 && digestbits == 0 &&
 1476             tsig.siglen < siglen)
 1477         {
 1478             msg->tsigstatus = dns_tsigerror_badtrunc;
 1479             tsig_log(msg->tsigkey, 2, "signature length too small");
 1480             ret = DNS_R_TSIGVERIFYFAILURE;
 1481             goto cleanup_context;
 1482         }
 1483     }
 1484 
 1485     if (response && tsig.error != dns_rcode_noerror) {
 1486         msg->tsigstatus = tsig.error;
 1487         if (tsig.error == dns_tsigerror_badtime)
 1488             ret = DNS_R_CLOCKSKEW;
 1489         else
 1490             ret = DNS_R_TSIGERRORSET;
 1491         goto cleanup_context;
 1492     }
 1493 
 1494     msg->tsigstatus = dns_rcode_noerror;
 1495     ret = ISC_R_SUCCESS;
 1496 
 1497  cleanup_context:
 1498     if (ctx != NULL)
 1499         dst_context_destroy(&ctx);
 1500 
 1501     return (ret);
 1502 }
 1503 
 1504 static isc_result_t
 1505 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
 1506     dns_rdata_any_tsig_t tsig, querytsig;
 1507     isc_region_t r, source_r, header_r, sig_r;
 1508     isc_buffer_t databuf;
 1509     unsigned char data[32];
 1510     dns_name_t *keyname;
 1511     dns_rdata_t rdata = DNS_RDATA_INIT;
 1512     isc_stdtime_t now;
 1513     isc_result_t ret;
 1514     dns_tsigkey_t *tsigkey;
 1515     dst_key_t *key = NULL;
 1516     unsigned char header[DNS_MESSAGE_HEADERLEN];
 1517     uint16_t addcount, id;
 1518     bool has_tsig = false;
 1519     isc_mem_t *mctx;
 1520     unsigned int siglen;
 1521     unsigned int alg;
 1522 
 1523     REQUIRE(source != NULL);
 1524     REQUIRE(msg != NULL);
 1525     REQUIRE(dns_message_gettsigkey(msg) != NULL);
 1526     REQUIRE(msg->tcp_continuation == 1);
 1527     REQUIRE(msg->querytsig != NULL);
 1528 
 1529     msg->verified_sig = 0;
 1530     msg->tsigstatus = dns_tsigerror_badsig;
 1531 
 1532     if (!is_response(msg))
 1533         return (DNS_R_EXPECTEDRESPONSE);
 1534 
 1535     mctx = msg->mctx;
 1536 
 1537     tsigkey = dns_message_gettsigkey(msg);
 1538     key = tsigkey->key;
 1539 
 1540     /*
 1541      * Extract and parse the previous TSIG
 1542      */
 1543     ret = dns_rdataset_first(msg->querytsig);
 1544     if (ret != ISC_R_SUCCESS)
 1545         return (ret);
 1546     dns_rdataset_current(msg->querytsig, &rdata);
 1547     ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
 1548     if (ret != ISC_R_SUCCESS)
 1549         return (ret);
 1550     dns_rdata_reset(&rdata);
 1551 
 1552     /*
 1553      * If there is a TSIG in this message, do some checks.
 1554      */
 1555     if (msg->tsig != NULL) {
 1556         has_tsig = true;
 1557 
 1558         keyname = msg->tsigname;
 1559         ret = dns_rdataset_first(msg->tsig);
 1560         if (ret != ISC_R_SUCCESS)
 1561             goto cleanup_querystruct;
 1562         dns_rdataset_current(msg->tsig, &rdata);
 1563         ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
 1564         if (ret != ISC_R_SUCCESS)
 1565             goto cleanup_querystruct;
 1566 
 1567         /*
 1568          * Do the key name and algorithm match that of the query?
 1569          */
 1570         if (!dns_name_equal(keyname, &tsigkey->name) ||
 1571             !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
 1572         {
 1573             msg->tsigstatus = dns_tsigerror_badkey;
 1574             ret = DNS_R_TSIGVERIFYFAILURE;
 1575             tsig_log(msg->tsigkey, 2,
 1576                  "key name and algorithm do not match");
 1577             goto cleanup_querystruct;
 1578         }
 1579 
 1580         /*
 1581          * Check digest length.
 1582          */
 1583         alg = dst_key_alg(key);
 1584         ret = dst_key_sigsize(key, &siglen);
 1585         if (ret != ISC_R_SUCCESS)
 1586             goto cleanup_querystruct;
 1587         if (
 1588 #ifndef PK11_MD5_DISABLE
 1589             alg == DST_ALG_HMACMD5 ||
 1590 #endif
 1591             alg == DST_ALG_HMACSHA1 ||
 1592             alg == DST_ALG_HMACSHA224 ||
 1593             alg == DST_ALG_HMACSHA256 ||
 1594             alg == DST_ALG_HMACSHA384 ||
 1595             alg == DST_ALG_HMACSHA512)
 1596         {
 1597             if (tsig.siglen > siglen) {
 1598                 tsig_log(tsigkey, 2,
 1599                      "signature length too big");
 1600                 ret = DNS_R_FORMERR;
 1601                 goto cleanup_querystruct;
 1602             }
 1603             if (tsig.siglen > 0 &&
 1604                 (tsig.siglen < 10 ||
 1605                  tsig.siglen < ((siglen + 1) / 2)))
 1606             {
 1607                 tsig_log(tsigkey, 2,
 1608                      "signature length below minimum");
 1609                 ret = DNS_R_FORMERR;
 1610                 goto cleanup_querystruct;
 1611             }
 1612         }
 1613     }
 1614 
 1615     if (msg->tsigctx == NULL) {
 1616         ret = dst_context_create3(key, mctx,
 1617                       DNS_LOGCATEGORY_DNSSEC,
 1618                       false, &msg->tsigctx);
 1619         if (ret != ISC_R_SUCCESS)
 1620             goto cleanup_querystruct;
 1621 
 1622         /*
 1623          * Digest the length of the query signature
 1624          */
 1625         isc_buffer_init(&databuf, data, sizeof(data));
 1626         isc_buffer_putuint16(&databuf, querytsig.siglen);
 1627         isc_buffer_usedregion(&databuf, &r);
 1628         ret = dst_context_adddata(msg->tsigctx, &r);
 1629         if (ret != ISC_R_SUCCESS)
 1630             goto cleanup_context;
 1631 
 1632         /*
 1633          * Digest the data of the query signature
 1634          */
 1635         if (querytsig.siglen > 0) {
 1636             r.length = querytsig.siglen;
 1637             r.base = querytsig.signature;
 1638             ret = dst_context_adddata(msg->tsigctx, &r);
 1639             if (ret != ISC_R_SUCCESS)
 1640                 goto cleanup_context;
 1641         }
 1642     }
 1643 
 1644     /*
 1645      * Extract the header.
 1646      */
 1647     isc_buffer_usedregion(source, &r);
 1648     memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
 1649     isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
 1650 
 1651     /*
 1652      * Decrement the additional field counter if necessary.
 1653      */
 1654     if (has_tsig) {
 1655         uint16_t addcount_n;
 1656 
 1657         memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
 1658         addcount_n = ntohs(addcount);
 1659         addcount = htons((uint16_t)(addcount_n - 1));
 1660         memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
 1661 
 1662         /*
 1663          * Put in the original id.
 1664          *
 1665          * XXX Can TCP transfers be forwarded?  How would that
 1666          * work?
 1667          */
 1668         /* cppcheck-suppress uninitStructMember symbolName=tsig.originalid */
 1669         id = htons(tsig.originalid);
 1670         memmove(&header[0], &id, 2);
 1671     }
 1672 
 1673     /*
 1674      * Digest the modified header.
 1675      */
 1676     header_r.base = (unsigned char *) header;
 1677     header_r.length = DNS_MESSAGE_HEADERLEN;
 1678     ret = dst_context_adddata(msg->tsigctx, &header_r);
 1679     if (ret != ISC_R_SUCCESS)
 1680         goto cleanup_context;
 1681 
 1682     /*
 1683      * Digest all non-TSIG records.
 1684      */
 1685     isc_buffer_usedregion(source, &source_r);
 1686     r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
 1687     if (has_tsig)
 1688         r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
 1689     else
 1690         r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
 1691     ret = dst_context_adddata(msg->tsigctx, &r);
 1692     if (ret != ISC_R_SUCCESS)
 1693         goto cleanup_context;
 1694 
 1695     /*
 1696      * Digest the time signed and fudge.
 1697      */
 1698     if (has_tsig) {
 1699         isc_buffer_init(&databuf, data, sizeof(data));
 1700         isc_buffer_putuint48(&databuf, tsig.timesigned);
 1701         isc_buffer_putuint16(&databuf, tsig.fudge);
 1702         isc_buffer_usedregion(&databuf, &r);
 1703         ret = dst_context_adddata(msg->tsigctx, &r);
 1704         if (ret != ISC_R_SUCCESS)
 1705             goto cleanup_context;
 1706 
 1707         sig_r.base = tsig.signature;
 1708         sig_r.length = tsig.siglen;
 1709         if (tsig.siglen == 0) {
 1710             if (tsig.error != dns_rcode_noerror) {
 1711                 msg->tsigstatus = tsig.error;
 1712                 if (tsig.error == dns_tsigerror_badtime) {
 1713                     ret = DNS_R_CLOCKSKEW;
 1714                 } else {
 1715                     ret = DNS_R_TSIGERRORSET;
 1716                 }
 1717             } else {
 1718                 tsig_log(msg->tsigkey, 2,
 1719                      "signature is empty");
 1720                 ret = DNS_R_TSIGVERIFYFAILURE;
 1721             }
 1722             goto cleanup_context;
 1723         }
 1724 
 1725         ret = dst_context_verify(msg->tsigctx, &sig_r);
 1726         if (ret == DST_R_VERIFYFAILURE) {
 1727             tsig_log(msg->tsigkey, 2,
 1728                  "signature failed to verify(2)");
 1729             ret = DNS_R_TSIGVERIFYFAILURE;
 1730             goto cleanup_context;
 1731         } else if (ret != ISC_R_SUCCESS) {
 1732             goto cleanup_context;
 1733         }
 1734         msg->verified_sig = 1;
 1735 
 1736         /*
 1737          * Here at this point, the MAC has been verified. Even
 1738          * if any of the following code returns a TSIG error,
 1739          * the reply will be signed and WILL always include the
 1740          * request MAC in the digest computation.
 1741          */
 1742 
 1743         /*
 1744          * Is the time ok?
 1745          */
 1746         isc_stdtime_get(&now);
 1747 
 1748         if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
 1749             msg->tsigstatus = dns_tsigerror_badtime;
 1750             tsig_log(msg->tsigkey, 2, "signature has expired");
 1751             ret = DNS_R_CLOCKSKEW;
 1752             goto cleanup_context;
 1753         } else if (now + msg->timeadjust <
 1754                tsig.timesigned - tsig.fudge)
 1755         {
 1756             msg->tsigstatus = dns_tsigerror_badtime;
 1757             tsig_log(msg->tsigkey, 2,
 1758                  "signature is in the future");
 1759             ret = DNS_R_CLOCKSKEW;
 1760             goto cleanup_context;
 1761         }
 1762 
 1763         alg = dst_key_alg(key);
 1764         ret = dst_key_sigsize(key, &siglen);
 1765         if (ret != ISC_R_SUCCESS)
 1766             goto cleanup_context;
 1767         if (
 1768 #ifndef PK11_MD5_DISABLE
 1769             alg == DST_ALG_HMACMD5 ||
 1770 #endif
 1771             alg == DST_ALG_HMACSHA1 ||
 1772             alg == DST_ALG_HMACSHA224 ||
 1773             alg == DST_ALG_HMACSHA256 ||
 1774             alg == DST_ALG_HMACSHA384 ||
 1775             alg == DST_ALG_HMACSHA512)
 1776         {
 1777             uint16_t digestbits = dst_key_getbits(key);
 1778 
 1779             if (tsig.siglen > 0 && digestbits != 0 &&
 1780                 tsig.siglen < ((digestbits + 7) / 8))
 1781             {
 1782                 msg->tsigstatus = dns_tsigerror_badtrunc;
 1783                 tsig_log(msg->tsigkey, 2,
 1784                      "truncated signature length "
 1785                      "too small");
 1786                 ret = DNS_R_TSIGVERIFYFAILURE;
 1787                 goto cleanup_context;
 1788             }
 1789             if (tsig.siglen > 0 && digestbits == 0 &&
 1790                 tsig.siglen < siglen)
 1791             {
 1792                 msg->tsigstatus = dns_tsigerror_badtrunc;
 1793                 tsig_log(msg->tsigkey, 2,
 1794                      "signature length too small");
 1795                 ret = DNS_R_TSIGVERIFYFAILURE;
 1796                 goto cleanup_context;
 1797             }
 1798         }
 1799 
 1800         if (tsig.error != dns_rcode_noerror) {
 1801             msg->tsigstatus = tsig.error;
 1802             if (tsig.error == dns_tsigerror_badtime)
 1803                 ret = DNS_R_CLOCKSKEW;
 1804             else
 1805                 ret = DNS_R_TSIGERRORSET;
 1806             goto cleanup_context;
 1807         }
 1808     }
 1809 
 1810     msg->tsigstatus = dns_rcode_noerror;
 1811     ret = ISC_R_SUCCESS;
 1812 
 1813  cleanup_context:
 1814     /*
 1815      * Except in error conditions, don't destroy the DST context
 1816      * for unsigned messages; it is a running sum till the next
 1817      * TSIG signed message.
 1818      */
 1819     if ((ret != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) {
 1820         dst_context_destroy(&msg->tsigctx);
 1821     }
 1822 
 1823  cleanup_querystruct:
 1824     dns_rdata_freestruct(&querytsig);
 1825 
 1826     return (ret);
 1827 }
 1828 
 1829 isc_result_t
 1830 dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
 1831          dns_name_t *algorithm, dns_tsig_keyring_t *ring)
 1832 {
 1833     dns_tsigkey_t *key;
 1834     isc_stdtime_t now;
 1835     isc_result_t result;
 1836 
 1837     REQUIRE(tsigkey != NULL);
 1838     REQUIRE(*tsigkey == NULL);
 1839     REQUIRE(name != NULL);
 1840     REQUIRE(ring != NULL);
 1841 
 1842     RWLOCK(&ring->lock, isc_rwlocktype_write);
 1843     cleanup_ring(ring);
 1844     RWUNLOCK(&ring->lock, isc_rwlocktype_write);
 1845 
 1846     isc_stdtime_get(&now);
 1847     RWLOCK(&ring->lock, isc_rwlocktype_read);
 1848     key = NULL;
 1849     result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
 1850     if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
 1851         RWUNLOCK(&ring->lock, isc_rwlocktype_read);
 1852         return (ISC_R_NOTFOUND);
 1853     }
 1854     if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
 1855         RWUNLOCK(&ring->lock, isc_rwlocktype_read);
 1856         return (ISC_R_NOTFOUND);
 1857     }
 1858     if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
 1859         /*
 1860          * The key has expired.
 1861          */
 1862         RWUNLOCK(&ring->lock, isc_rwlocktype_read);
 1863         RWLOCK(&ring->lock, isc_rwlocktype_write);
 1864         remove_fromring(key);
 1865         RWUNLOCK(&ring->lock, isc_rwlocktype_write);
 1866         return (ISC_R_NOTFOUND);
 1867     }
 1868 #if 0
 1869     /*
 1870      * MPAXXX We really should look at the inception time.
 1871      */
 1872     if (key->inception != key->expire &&
 1873         isc_serial_lt(key->inception, now)) {
 1874         RWUNLOCK(&ring->lock, isc_rwlocktype_read);
 1875         adjust_lru(key);
 1876         return (ISC_R_NOTFOUND);
 1877     }
 1878 #endif
 1879     isc_refcount_increment(&key->refs, NULL);
 1880     RWUNLOCK(&ring->lock, isc_rwlocktype_read);
 1881     adjust_lru(key);
 1882     *tsigkey = key;
 1883     return (ISC_R_SUCCESS);
 1884 }
 1885 
 1886 static void
 1887 free_tsignode(void *node, void *_unused) {
 1888     dns_tsigkey_t *key;
 1889 
 1890     REQUIRE(node != NULL);
 1891 
 1892     UNUSED(_unused);
 1893 
 1894     key = node;
 1895     if (key->generated) {
 1896         if (ISC_LINK_LINKED(key, link))
 1897             ISC_LIST_UNLINK(key->ring->lru, key, link);
 1898     }
 1899     dns_tsigkey_detach(&key);
 1900 }
 1901 
 1902 isc_result_t
 1903 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
 1904     isc_result_t result;
 1905     dns_tsig_keyring_t *ring;
 1906 
 1907     REQUIRE(mctx != NULL);
 1908     REQUIRE(ringp != NULL);
 1909     REQUIRE(*ringp == NULL);
 1910 
 1911     ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
 1912     if (ring == NULL)
 1913         return (ISC_R_NOMEMORY);
 1914 
 1915     result = isc_rwlock_init(&ring->lock, 0, 0);
 1916     if (result != ISC_R_SUCCESS) {
 1917         isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
 1918         return (result);
 1919     }
 1920 
 1921     ring->keys = NULL;
 1922     result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
 1923     if (result != ISC_R_SUCCESS) {
 1924         isc_rwlock_destroy(&ring->lock);
 1925         isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
 1926         return (result);
 1927     }
 1928 
 1929     ring->writecount = 0;
 1930     ring->mctx = NULL;
 1931     ring->generated = 0;
 1932     ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
 1933     ISC_LIST_INIT(ring->lru);
 1934     isc_mem_attach(mctx, &ring->mctx);
 1935     ring->references = 1;
 1936 
 1937     *ringp = ring;
 1938     return (ISC_R_SUCCESS);
 1939 }
 1940 
 1941 isc_result_t
 1942 dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
 1943             dns_tsigkey_t *tkey)
 1944 {
 1945     isc_result_t result;
 1946 
 1947     result = keyring_add(ring, name, tkey);
 1948     if (result == ISC_R_SUCCESS)
 1949         isc_refcount_increment(&tkey->refs, NULL);
 1950 
 1951     return (result);
 1952 }
 1953 
 1954 void
 1955 dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
 1956 {
 1957     REQUIRE(source != NULL);
 1958     REQUIRE(target != NULL && *target == NULL);
 1959 
 1960     RWLOCK(&source->lock, isc_rwlocktype_write);
 1961     INSIST(source->references > 0);
 1962     source->references++;
 1963     INSIST(source->references > 0);
 1964     *target = source;
 1965     RWUNLOCK(&source->lock, isc_rwlocktype_write);
 1966 }
 1967 
 1968 void
 1969 dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
 1970     dns_tsig_keyring_t *ring;
 1971     unsigned int references;
 1972 
 1973     REQUIRE(ringp != NULL);
 1974     REQUIRE(*ringp != NULL);
 1975 
 1976     ring = *ringp;
 1977     *ringp = NULL;
 1978 
 1979     RWLOCK(&ring->lock, isc_rwlocktype_write);
 1980     INSIST(ring->references > 0);
 1981     ring->references--;
 1982     references = ring->references;
 1983     RWUNLOCK(&ring->lock, isc_rwlocktype_write);
 1984 
 1985     if (references == 0)
 1986         destroyring(ring);
 1987 }
 1988 
 1989 void
 1990 dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
 1991     isc_stdtime_t now;
 1992     isc_result_t result;
 1993 
 1994     isc_stdtime_get(&now);
 1995     do {
 1996         result = restore_key(ring, now, fp);
 1997         if (result == ISC_R_NOMORE)
 1998             return;
 1999         if (result == DNS_R_BADALG || result == DNS_R_EXPIRED)
 2000             result = ISC_R_SUCCESS;
 2001     } while (result == ISC_R_SUCCESS);
 2002 }