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