Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: tsig.h,v 1.11 2026/06/19 20:10:01 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #pragma once
     17 
     18 /*! \file dns/tsig.h */
     19 
     20 #include <stdbool.h>
     21 
     22 #include <isc/hashmap.h>
     23 #include <isc/lang.h>
     24 #include <isc/refcount.h>
     25 #include <isc/rwlock.h>
     26 #include <isc/stdio.h>
     27 #include <isc/stdtime.h>
     28 
     29 #include <dns/fixedname.h>
     30 #include <dns/name.h>
     31 #include <dns/types.h>
     32 
     33 #include <dst/dst.h>
     34 
     35 /* Add -DDNS_TSIG_TRACE=1 to CFLAGS for detailed reference tracing */
     36 
     37 /*
     38  * Algorithms.
     39  */
     40 extern const dns_name_t *dns_tsig_hmacmd5_name;
     41 #define DNS_TSIG_HMACMD5_NAME dns_tsig_hmacmd5_name
     42 extern const dns_name_t *dns_tsig_gssapi_name;
     43 #define DNS_TSIG_GSSAPI_NAME dns_tsig_gssapi_name
     44 extern const dns_name_t *dns_tsig_hmacsha1_name;
     45 #define DNS_TSIG_HMACSHA1_NAME dns_tsig_hmacsha1_name
     46 extern const dns_name_t *dns_tsig_hmacsha224_name;
     47 #define DNS_TSIG_HMACSHA224_NAME dns_tsig_hmacsha224_name
     48 extern const dns_name_t *dns_tsig_hmacsha256_name;
     49 #define DNS_TSIG_HMACSHA256_NAME dns_tsig_hmacsha256_name
     50 extern const dns_name_t *dns_tsig_hmacsha384_name;
     51 #define DNS_TSIG_HMACSHA384_NAME dns_tsig_hmacsha384_name
     52 extern const dns_name_t *dns_tsig_hmacsha512_name;
     53 #define DNS_TSIG_HMACSHA512_NAME dns_tsig_hmacsha512_name
     54 
     55 /*%
     56  * Default fudge value.
     57  */
     58 #define DNS_TSIG_FUDGE 300
     59 
     60 /*%
     61  * Default maximum quota for generated keys.
     62  */
     63 #ifndef DNS_TSIG_MAXGENERATEDKEYS
     64 #define DNS_TSIG_MAXGENERATEDKEYS 4096
     65 #endif /* ifndef DNS_TSIG_MAXGENERATEDKEYS */
     66 
     67 struct dns_tsigkeyring {
     68 	unsigned int   magic; /*%< Magic number. */
     69 	isc_hashmap_t *keys;
     70 	unsigned int   writecount;
     71 	isc_rwlock_t   lock;
     72 	isc_mem_t     *mctx;
     73 	/*
     74 	 * LRU list of generated key along with a count of the keys on the
     75 	 * list and a maximum size.
     76 	 */
     77 	unsigned int generated;
     78 	ISC_LIST(dns_tsigkey_t) lru;
     79 	isc_refcount_t references;
     80 };
     81 
     82 struct dns_tsigkey {
     83 	/* Unlocked */
     84 	unsigned int	magic; /*%< Magic number. */
     85 	isc_mem_t      *mctx;
     86 	dst_key_t      *key; /*%< Key */
     87 	dns_fixedname_t fn;
     88 	dns_name_t     *name;	      /*%< Key name */
     89 	dst_algorithm_t alg;	      /*< Algorithm */
     90 	dns_name_t	algname;      /*< Algorithm name, only used if
     91 					algorithm is DST_ALG_UNKNOWN */
     92 	dns_name_t    *creator;	      /*%< name that created secret */
     93 	bool	       generated : 1; /*%< key was auto-generated */
     94 	bool	       restored	 : 1; /*%< key was restored at startup */
     95 	isc_stdtime_t  inception;     /*%< start of validity period */
     96 	isc_stdtime_t  expire;	      /*%< end of validity period */
     97 	isc_refcount_t references;    /*%< reference counter */
     98 	ISC_LINK(dns_tsigkey_t) link;
     99 };
    100 
    101 ISC_LANG_BEGINDECLS
    102 
    103 const dns_name_t *
    104 dns_tsigkey_identity(const dns_tsigkey_t *tsigkey);
    105 /*%<
    106  *	Returns the identity of the provided TSIG key.
    107  *
    108  *	Requires:
    109  *\li		'tsigkey' is a valid TSIG key or NULL
    110  *
    111  *	Returns:
    112  *\li		NULL if 'tsigkey' was NULL
    113  *\li		identity of the provided TSIG key
    114  */
    115 
    116 isc_result_t
    117 dns_tsigkey_create(const dns_name_t *name, dst_algorithm_t algorithm,
    118 		   unsigned char *secret, int length, isc_mem_t *mctx,
    119 		   dns_tsigkey_t **key);
    120 
    121 isc_result_t
    122 dns_tsigkey_createfromkey(const dns_name_t *name, dst_algorithm_t algorithm,
    123 			  dst_key_t *dstkey, bool generated, bool restored,
    124 			  const dns_name_t *creator, isc_stdtime_t inception,
    125 			  isc_stdtime_t expire, isc_mem_t *mctx,
    126 			  dns_tsigkey_t **key);
    127 /*%<
    128  *	Creates a tsig key structure and stores it in *keyp.
    129  *	The key's validity period is specified by (inception, expire),
    130  *	and will not expire if inception == expire.
    131  *
    132  *	If generated is true (meaning the key was generated
    133  *	via TKEY negotiation), the creating identity (if any), should
    134  *	be specified in the creator parameter.
    135  *
    136  *	If restored is true, this indicates the key was restored from
    137  *	a dump file created by dns_tsigkeyring_dumpanddetach(). This is
    138  *	used only for logging purposes and doesn't affect the key any
    139  *	other way.
    140  *
    141  *	Specifying an unimplemented algorithm will cause failure only if
    142  *	dstkey != NULL; this allows a transient key with an invalid
    143  *	algorithm to exist long enough to generate a BADKEY response.
    144  *
    145  *	If dns_tsigkey_createfromkey() is successful, a new reference to
    146  *	'dstkey' will have been made.
    147  *
    148  *	dns_tsigkey_create() is a simplified interface that omits
    149  *	dstkey, generated, restored, inception, and expired (defaulting
    150  *	to NULL, false, false, 0, and 0).
    151  *
    152  *	Requires:
    153  *\li		'name' is a valid dns_name_t
    154  *\li		'algorithm' is a valid dns_name_t
    155  *\li		'secret' is a valid pointer
    156  *\li		'length' is an integer >= 0
    157  *\li		'dstkey' is a valid dst key or NULL
    158  *\li		'creator' points to a valid dns_name_t or is NULL
    159  *\li		'mctx' is a valid memory context
    160  *\li		'ring' is a valid TSIG keyring or NULL
    161  *\li		'key' or '*key' must be NULL
    162  *
    163  *	Returns:
    164  *\li		#ISC_R_SUCCESS
    165  *\li		#ISC_R_EXISTS - a key with this name already exists
    166  *\li		#ISC_R_NOTIMPLEMENTED - algorithm is not implemented
    167  *\li		#ISC_R_NOMEMORY
    168  */
    169 
    170 void
    171 dns_tsigkey_delete(dns_tsigkeyring_t *ring, dns_tsigkey_t *key);
    172 /*%<
    173  *	Prevents this key from being used again.  It will be deleted when
    174  *	no references exist.
    175  *
    176  *	Requires:
    177  *\li		'ring' is a valid TSIG keyring
    178  *\li		'key' is a valid TSIG key on a keyring 'ring'
    179  */
    180 
    181 isc_result_t
    182 dns_tsig_sign(dns_message_t *msg);
    183 /*%<
    184  *	Generates a TSIG record for this message
    185  *
    186  *	Requires:
    187  *\li		'msg' is a valid message
    188  *\li		'msg->tsigkey' is a valid TSIG key
    189  *\li		'msg->tsig' is NULL
    190  *
    191  *	Returns:
    192  *\li		#ISC_R_SUCCESS
    193  *\li		#ISC_R_NOMEMORY
    194  *\li		#ISC_R_NOSPACE
    195  *\li		#DNS_R_EXPECTEDTSIG
    196  *			- this is a response & msg->querytsig is NULL
    197  */
    198 
    199 isc_result_t
    200 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
    201 		dns_tsigkeyring_t *ring1, dns_tsigkeyring_t *ring2);
    202 /*%<
    203  *	Verifies the TSIG record in this message
    204  *
    205  *	Requires:
    206  *\li		'source' is a valid buffer containing the unparsed message
    207  *\li		'msg' is a valid message
    208  *\li		'msg->tsigkey' is a valid TSIG key if this is a response
    209  *\li		'msg->tsig' is NULL
    210  *\li		'msg->querytsig' is not NULL if this is a response
    211  *\li		'ring1' and 'ring2' are each either a valid keyring or NULL
    212  *
    213  *	Returns:
    214  *\li		#ISC_R_SUCCESS
    215  *\li		#ISC_R_NOMEMORY
    216  *\li		#DNS_R_EXPECTEDTSIG - A TSIG was expected but not seen
    217  *\li		#DNS_R_UNEXPECTEDTSIG - A TSIG was seen but not expected
    218  *\li		#DNS_R_TSIGERRORSET - the TSIG verified but ->error was set
    219  *				     and this is a query
    220  *\li		#DNS_R_CLOCKSKEW - the TSIG failed to verify because of
    221  *				  the time was out of the allowed range.
    222  *\li		#DNS_R_TSIGVERIFYFAILURE - the TSIG failed to verify
    223  *\li		#DNS_R_EXPECTEDRESPONSE - the message was set over TCP and
    224  *					 should have been a response,
    225  *					 but was not.
    226  */
    227 
    228 isc_result_t
    229 dns_tsigkey_find(dns_tsigkey_t **tsigkeyp, const dns_name_t *name,
    230 		 const dns_name_t *algorithm, dns_tsigkeyring_t *ring);
    231 /*%<
    232  *	Returns the TSIG key corresponding to this name and (possibly)
    233  *	algorithm.  Also increments the key's reference counter.
    234  *
    235  *	Requires:
    236  *\li		'tsigkeyp' is not NULL
    237  *\li		'*tsigkeyp' is NULL
    238  *\li		'name' is a valid dns_name_t
    239  *\li		'algorithm' is a valid dns_name_t or NULL
    240  *\li		'ring' is a valid keyring
    241  *
    242  *	Returns:
    243  *\li		#ISC_R_SUCCESS
    244  *\li		#ISC_R_NOTFOUND
    245  */
    246 
    247 const dns_name_t *
    248 dns_tsigkey_algorithm(dns_tsigkey_t *tkey);
    249 /*%<
    250  * 	Returns the key algorithm associated with a tsigkey object.
    251  *
    252  * 	Note that when a tsigkey object is created with algorithm
    253  * 	DST_ALG_UNKNOWN, the unknown algorithm's name must be cloned
    254  * 	into tsigkey->algname.
    255  */
    256 
    257 void
    258 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsigkeyring_t **ringp);
    259 /*%<
    260  *	Create an empty TSIG key ring.
    261  *
    262  *	Requires:
    263  *\li		'mctx' is not NULL
    264  *\li		'ringp' is not NULL, and '*ringp' is NULL
    265  */
    266 
    267 isc_result_t
    268 dns_tsigkeyring_add(dns_tsigkeyring_t *ring, dns_tsigkey_t *tkey);
    269 /*%<
    270  *      Place a TSIG key onto a key ring.
    271  *
    272  *      If the key is generated, it is also placed into an LRU queue.
    273  *      There is a maximum quota of 4096 generated keys per keyring;
    274  *      if this quota is exceeded, the oldest key in the LRU queue is
    275  *      deleted.
    276  *
    277  *	Requires:
    278  *\li		'name' and 'ring' are not NULL
    279  *\li		'tkey' is a valid TSIG key, which has not been
    280  *		       added to any other keyrings
    281  *
    282  *	Returns:
    283  *\li		#ISC_R_SUCCESS
    284  *\li		Any other value indicates failure.
    285  */
    286 
    287 isc_result_t
    288 dns_tsigkeyring_dump(dns_tsigkeyring_t *ring, FILE *fp);
    289 /*%<
    290  *	Dump a TSIG key ring to 'fp'.
    291  *
    292  *	Requires:
    293  *\li		'ring' is a valid keyring.
    294  */
    295 
    296 void
    297 dns_tsigkeyring_restore(dns_tsigkeyring_t *ring, FILE *fp);
    298 /*%<
    299  *	Restore a TSIG keyring from a dump file 'fp'.
    300  */
    301 
    302 #if DNS_TSIG_TRACE
    303 #define dns_tsigkey_ref(ptr) dns_tsigkey__ref(ptr, __func__, __FILE__, __LINE__)
    304 #define dns_tsigkey_unref(ptr) \
    305 	dns_tsigkey__unref(ptr, __func__, __FILE__, __LINE__)
    306 #define dns_tsigkey_attach(ptr, ptrp) \
    307 	dns_tsigkey__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    308 #define dns_tsigkey_detach(ptrp) \
    309 	dns_tsigkey__detach(ptrp, __func__, __FILE__, __LINE__)
    310 ISC_REFCOUNT_TRACE_DECL(dns_tsigkey);
    311 
    312 #define dns_tsigkeyring_ref(ptr) \
    313 	dns_tsigkeyring__ref(ptr, __func__, __FILE__, __LINE__)
    314 #define dns_tsigkeyring_unref(ptr) \
    315 	dns_tsigkeyring__unref(ptr, __func__, __FILE__, __LINE__)
    316 #define dns_tsigkeyring_attach(ptr, ptrp) \
    317 	dns_tsigkeyring__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    318 #define dns_tsigkeyring_detach(ptrp) \
    319 	dns_tsigkeyring__detach(ptrp, __func__, __FILE__, __LINE__)
    320 ISC_REFCOUNT_TRACE_DECL(dns_tsigkeyring);
    321 #else
    322 ISC_REFCOUNT_DECL(dns_tsigkey);
    323 ISC_REFCOUNT_DECL(dns_tsigkeyring);
    324 #endif
    325 
    326 ISC_LANG_ENDDECLS
    327