00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include <stdlib.h>
00024
00025 #include <isc/buffer.h>
00026 #include <isc/mem.h>
00027 #include <isc/print.h>
00028 #include <isc/refcount.h>
00029 #include <isc/serial.h>
00030 #include <isc/string.h>
00031 #include <isc/util.h>
00032 #include <isc/time.h>
00033
00034 #include <dns/keyvalues.h>
00035 #include <dns/log.h>
00036 #include <dns/message.h>
00037 #include <dns/fixedname.h>
00038 #include <dns/rbt.h>
00039 #include <dns/rdata.h>
00040 #include <dns/rdatalist.h>
00041 #include <dns/rdataset.h>
00042 #include <dns/rdatastruct.h>
00043 #include <dns/result.h>
00044 #include <dns/tsig.h>
00045
00046 #include <dst/result.h>
00047
00048 #define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
00049 #define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
00050
00051 #ifndef DNS_TSIG_MAXGENERATEDKEYS
00052 #define DNS_TSIG_MAXGENERATEDKEYS 4096
00053 #endif
00054
00055 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
00056 #define algname_is_allocated(algname) \
00057 ((algname) != dns_tsig_hmacmd5_name && \
00058 (algname) != dns_tsig_hmacsha1_name && \
00059 (algname) != dns_tsig_hmacsha224_name && \
00060 (algname) != dns_tsig_hmacsha256_name && \
00061 (algname) != dns_tsig_hmacsha384_name && \
00062 (algname) != dns_tsig_hmacsha512_name && \
00063 (algname) != dns_tsig_gssapi_name && \
00064 (algname) != dns_tsig_gssapims_name)
00065
00066 #define BADTIMELEN 6
00067
00068 static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
00069 static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
00070
00071 static dns_name_t hmacmd5 = {
00072 DNS_NAME_MAGIC,
00073 hmacmd5_ndata, 26, 5,
00074 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00075 hmacmd5_offsets, NULL,
00076 {(void *)-1, (void *)-1},
00077 {NULL, NULL}
00078 };
00079
00080 dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
00081
00082 static unsigned char gsstsig_ndata[] = "\010gss-tsig";
00083 static unsigned char gsstsig_offsets[] = { 0, 9 };
00084 static dns_name_t gsstsig = {
00085 DNS_NAME_MAGIC,
00086 gsstsig_ndata, 10, 2,
00087 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00088 gsstsig_offsets, NULL,
00089 {(void *)-1, (void *)-1},
00090 {NULL, NULL}
00091 };
00092 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
00093
00094
00095
00096
00097
00098 static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
00099 static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
00100 static dns_name_t gsstsigms = {
00101 DNS_NAME_MAGIC,
00102 gsstsigms_ndata, 19, 4,
00103 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00104 gsstsigms_offsets, NULL,
00105 {(void *)-1, (void *)-1},
00106 {NULL, NULL}
00107 };
00108 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
00109
00110 static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
00111 static unsigned char hmacsha1_offsets[] = { 0, 10 };
00112
00113 static dns_name_t hmacsha1 = {
00114 DNS_NAME_MAGIC,
00115 hmacsha1_ndata, 11, 2,
00116 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00117 hmacsha1_offsets, NULL,
00118 {(void *)-1, (void *)-1},
00119 {NULL, NULL}
00120 };
00121
00122 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
00123
00124 static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
00125 static unsigned char hmacsha224_offsets[] = { 0, 12 };
00126
00127 static dns_name_t hmacsha224 = {
00128 DNS_NAME_MAGIC,
00129 hmacsha224_ndata, 13, 2,
00130 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00131 hmacsha224_offsets, NULL,
00132 {(void *)-1, (void *)-1},
00133 {NULL, NULL}
00134 };
00135
00136 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
00137
00138 static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
00139 static unsigned char hmacsha256_offsets[] = { 0, 12 };
00140
00141 static dns_name_t hmacsha256 = {
00142 DNS_NAME_MAGIC,
00143 hmacsha256_ndata, 13, 2,
00144 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00145 hmacsha256_offsets, NULL,
00146 {(void *)-1, (void *)-1},
00147 {NULL, NULL}
00148 };
00149
00150 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
00151
00152 static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
00153 static unsigned char hmacsha384_offsets[] = { 0, 12 };
00154
00155 static dns_name_t hmacsha384 = {
00156 DNS_NAME_MAGIC,
00157 hmacsha384_ndata, 13, 2,
00158 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00159 hmacsha384_offsets, NULL,
00160 {(void *)-1, (void *)-1},
00161 {NULL, NULL}
00162 };
00163
00164 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
00165
00166 static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
00167 static unsigned char hmacsha512_offsets[] = { 0, 12 };
00168
00169 static dns_name_t hmacsha512 = {
00170 DNS_NAME_MAGIC,
00171 hmacsha512_ndata, 13, 2,
00172 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00173 hmacsha512_offsets, NULL,
00174 {(void *)-1, (void *)-1},
00175 {NULL, NULL}
00176 };
00177
00178 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
00179
00180 static isc_result_t
00181 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
00182
00183 static void
00184 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
00185 ISC_FORMAT_PRINTF(3, 4);
00186
00187 static void
00188 cleanup_ring(dns_tsig_keyring_t *ring);
00189 static void
00190 tsigkey_free(dns_tsigkey_t *key);
00191
00192 static void
00193 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
00194 va_list ap;
00195 char message[4096];
00196 char namestr[DNS_NAME_FORMATSIZE];
00197 char creatorstr[DNS_NAME_FORMATSIZE];
00198
00199 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
00200 return;
00201 if (key != NULL)
00202 dns_name_format(&key->name, namestr, sizeof(namestr));
00203 else
00204 strcpy(namestr, "<null>");
00205
00206 if (key != NULL && key->generated && key->creator)
00207 dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
00208 else
00209 strcpy(creatorstr, "<null>");
00210
00211 va_start(ap, fmt);
00212 vsnprintf(message, sizeof(message), fmt, ap);
00213 va_end(ap);
00214 if (key != NULL && key->generated)
00215 isc_log_write(dns_lctx,
00216 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
00217 level, "tsig key '%s' (%s): %s",
00218 namestr, creatorstr, message);
00219 else
00220 isc_log_write(dns_lctx,
00221 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
00222 level, "tsig key '%s': %s", namestr, message);
00223 }
00224
00225 static void
00226 remove_fromring(dns_tsigkey_t *tkey) {
00227 if (tkey->generated) {
00228 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
00229 tkey->ring->generated--;
00230 }
00231 (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
00232 }
00233
00234 static void
00235 adjust_lru(dns_tsigkey_t *tkey) {
00236 if (tkey->generated) {
00237 RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
00238
00239
00240
00241
00242 if (ISC_LINK_LINKED(tkey, link) &&
00243 tkey->ring->lru.tail != tkey)
00244 {
00245 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
00246 ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
00247 }
00248 RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259 static isc_result_t
00260 keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
00261 dns_tsigkey_t *tkey)
00262 {
00263 isc_result_t result;
00264
00265 RWLOCK(&ring->lock, isc_rwlocktype_write);
00266 ring->writecount++;
00267
00268
00269
00270
00271
00272 if (ring->writecount > 10) {
00273 cleanup_ring(ring);
00274 ring->writecount = 0;
00275 }
00276
00277 result = dns_rbt_addname(ring->keys, name, tkey);
00278 if (result == ISC_R_SUCCESS && tkey->generated) {
00279
00280
00281
00282
00283 ISC_LIST_APPEND(ring->lru, tkey, link);
00284 if (ring->generated++ > ring->maxgenerated)
00285 remove_fromring(ISC_LIST_HEAD(ring->lru));
00286 }
00287 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
00288
00289 return (result);
00290 }
00291
00292 isc_result_t
00293 dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
00294 dst_key_t *dstkey, isc_boolean_t generated,
00295 dns_name_t *creator, isc_stdtime_t inception,
00296 isc_stdtime_t expire, isc_mem_t *mctx,
00297 dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
00298 {
00299 dns_tsigkey_t *tkey;
00300 isc_result_t ret;
00301 unsigned int refs = 0;
00302
00303 REQUIRE(key == NULL || *key == NULL);
00304 REQUIRE(name != NULL);
00305 REQUIRE(algorithm != NULL);
00306 REQUIRE(mctx != NULL);
00307 REQUIRE(key != NULL || ring != NULL);
00308
00309 tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
00310 if (tkey == NULL)
00311 return (ISC_R_NOMEMORY);
00312
00313 dns_name_init(&tkey->name, NULL);
00314 ret = dns_name_dup(name, mctx, &tkey->name);
00315 if (ret != ISC_R_SUCCESS)
00316 goto cleanup_key;
00317 (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
00318
00319 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
00320 tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
00321 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
00322 ret = DNS_R_BADALG;
00323 goto cleanup_name;
00324 }
00325 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
00326 tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
00327 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
00328 ret = DNS_R_BADALG;
00329 goto cleanup_name;
00330 }
00331 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
00332 tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
00333 if (dstkey != NULL &&
00334 dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
00335 ret = DNS_R_BADALG;
00336 goto cleanup_name;
00337 }
00338 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
00339 tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
00340 if (dstkey != NULL &&
00341 dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
00342 ret = DNS_R_BADALG;
00343 goto cleanup_name;
00344 }
00345 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
00346 tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
00347 if (dstkey != NULL &&
00348 dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
00349 ret = DNS_R_BADALG;
00350 goto cleanup_name;
00351 }
00352 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
00353 tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
00354 if (dstkey != NULL &&
00355 dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
00356 ret = DNS_R_BADALG;
00357 goto cleanup_name;
00358 }
00359 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
00360 tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
00361 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
00362 ret = DNS_R_BADALG;
00363 goto cleanup_name;
00364 }
00365 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
00366 tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
00367 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
00368 ret = DNS_R_BADALG;
00369 goto cleanup_name;
00370 }
00371 } else {
00372 if (dstkey != NULL) {
00373 ret = DNS_R_BADALG;
00374 goto cleanup_name;
00375 }
00376 tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
00377 if (tkey->algorithm == NULL) {
00378 ret = ISC_R_NOMEMORY;
00379 goto cleanup_name;
00380 }
00381 dns_name_init(tkey->algorithm, NULL);
00382 ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
00383 if (ret != ISC_R_SUCCESS)
00384 goto cleanup_algorithm;
00385 (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
00386 NULL);
00387 }
00388
00389 if (creator != NULL) {
00390 tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
00391 if (tkey->creator == NULL) {
00392 ret = ISC_R_NOMEMORY;
00393 goto cleanup_algorithm;
00394 }
00395 dns_name_init(tkey->creator, NULL);
00396 ret = dns_name_dup(creator, mctx, tkey->creator);
00397 if (ret != ISC_R_SUCCESS) {
00398 isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
00399 goto cleanup_algorithm;
00400 }
00401 } else
00402 tkey->creator = NULL;
00403
00404 tkey->key = NULL;
00405 if (dstkey != NULL)
00406 dst_key_attach(dstkey, &tkey->key);
00407 tkey->ring = ring;
00408
00409 if (key != NULL)
00410 refs = 1;
00411 if (ring != NULL)
00412 refs++;
00413 ret = isc_refcount_init(&tkey->refs, refs);
00414 if (ret != ISC_R_SUCCESS)
00415 goto cleanup_creator;
00416
00417 tkey->generated = generated;
00418 tkey->inception = inception;
00419 tkey->expire = expire;
00420 tkey->mctx = NULL;
00421 isc_mem_attach(mctx, &tkey->mctx);
00422 ISC_LINK_INIT(tkey, link);
00423
00424 tkey->magic = TSIG_MAGIC;
00425
00426 if (ring != NULL) {
00427 ret = keyring_add(ring, name, tkey);
00428 if (ret != ISC_R_SUCCESS)
00429 goto cleanup_refs;
00430 }
00431
00432
00433
00434
00435 if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
00436 !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
00437 !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
00438 char namestr[DNS_NAME_FORMATSIZE];
00439 dns_name_format(name, namestr, sizeof(namestr));
00440 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
00441 DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
00442 "the key '%s' is too short to be secure",
00443 namestr);
00444 }
00445
00446 if (key != NULL)
00447 *key = tkey;
00448
00449 return (ISC_R_SUCCESS);
00450
00451 cleanup_refs:
00452 tkey->magic = 0;
00453 while (refs-- > 0)
00454 isc_refcount_decrement(&tkey->refs, NULL);
00455 isc_refcount_destroy(&tkey->refs);
00456 cleanup_creator:
00457 if (tkey->key != NULL)
00458 dst_key_free(&tkey->key);
00459 if (tkey->creator != NULL) {
00460 dns_name_free(tkey->creator, mctx);
00461 isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
00462 }
00463 cleanup_algorithm:
00464 if (algname_is_allocated(tkey->algorithm)) {
00465 if (dns_name_dynamic(tkey->algorithm))
00466 dns_name_free(tkey->algorithm, mctx);
00467 isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
00468 }
00469 cleanup_name:
00470 dns_name_free(&tkey->name, mctx);
00471 cleanup_key:
00472 isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
00473
00474 return (ret);
00475 }
00476
00477
00478
00479
00480 static void
00481 cleanup_ring(dns_tsig_keyring_t *ring)
00482 {
00483 isc_result_t result;
00484 dns_rbtnodechain_t chain;
00485 dns_name_t foundname;
00486 dns_fixedname_t fixedorigin;
00487 dns_name_t *origin;
00488 isc_stdtime_t now;
00489 dns_rbtnode_t *node;
00490 dns_tsigkey_t *tkey;
00491
00492
00493
00494
00495 isc_stdtime_get(&now);
00496 dns_name_init(&foundname, NULL);
00497 dns_fixedname_init(&fixedorigin);
00498 origin = dns_fixedname_name(&fixedorigin);
00499
00500 again:
00501 dns_rbtnodechain_init(&chain, ring->mctx);
00502 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
00503 origin);
00504 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00505 dns_rbtnodechain_invalidate(&chain);
00506 return;
00507 }
00508
00509 for (;;) {
00510 node = NULL;
00511 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
00512 tkey = node->data;
00513 if (tkey != NULL) {
00514 if (tkey->generated
00515 && isc_refcount_current(&tkey->refs) == 1
00516 && tkey->inception != tkey->expire
00517 && tkey->expire < now) {
00518 tsig_log(tkey, 2, "tsig expire: deleting");
00519
00520 dns_rbtnodechain_invalidate(&chain);
00521 remove_fromring(tkey);
00522 goto again;
00523 }
00524 }
00525 result = dns_rbtnodechain_next(&chain, &foundname,
00526 origin);
00527 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00528 dns_rbtnodechain_invalidate(&chain);
00529 return;
00530 }
00531 }
00532 }
00533
00534 static void
00535 destroyring(dns_tsig_keyring_t *ring) {
00536 dns_rbt_destroy(&ring->keys);
00537 isc_rwlock_destroy(&ring->lock);
00538 isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
00539 }
00540
00541 static unsigned int
00542 dst_alg_fromname(dns_name_t *algorithm) {
00543 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
00544 return (DST_ALG_HMACMD5);
00545 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
00546 return (DST_ALG_HMACSHA1);
00547 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
00548 return (DST_ALG_HMACSHA224);
00549 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
00550 return (DST_ALG_HMACSHA256);
00551 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
00552 return (DST_ALG_HMACSHA384);
00553 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
00554 return (DST_ALG_HMACSHA512);
00555 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
00556 return (DST_ALG_GSSAPI);
00557 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
00558 return (DST_ALG_GSSAPI);
00559 } else
00560 return (0);
00561 }
00562
00563 static isc_result_t
00564 restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
00565 dst_key_t *dstkey = NULL;
00566 char namestr[1024];
00567 char creatorstr[1024];
00568 char algorithmstr[1024];
00569 char keystr[4096];
00570 unsigned int inception, expire;
00571 int n;
00572 isc_buffer_t b;
00573 dns_name_t *name, *creator, *algorithm;
00574 dns_fixedname_t fname, fcreator, falgorithm;
00575 isc_result_t result;
00576 unsigned int dstalg;
00577
00578 n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
00579 creatorstr, &inception, &expire, algorithmstr, keystr);
00580 if (n == EOF)
00581 return (ISC_R_NOMORE);
00582 if (n != 6)
00583 return (ISC_R_FAILURE);
00584
00585 if (isc_serial_lt(expire, now))
00586 return (DNS_R_EXPIRED);
00587
00588 dns_fixedname_init(&fname);
00589 name = dns_fixedname_name(&fname);
00590 isc_buffer_init(&b, namestr, strlen(namestr));
00591 isc_buffer_add(&b, strlen(namestr));
00592 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
00593 if (result != ISC_R_SUCCESS)
00594 return (result);
00595
00596 dns_fixedname_init(&fcreator);
00597 creator = dns_fixedname_name(&fcreator);
00598 isc_buffer_init(&b, creatorstr, strlen(creatorstr));
00599 isc_buffer_add(&b, strlen(creatorstr));
00600 result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
00601 if (result != ISC_R_SUCCESS)
00602 return (result);
00603
00604 dns_fixedname_init(&falgorithm);
00605 algorithm = dns_fixedname_name(&falgorithm);
00606 isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
00607 isc_buffer_add(&b, strlen(algorithmstr));
00608 result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
00609 if (result != ISC_R_SUCCESS)
00610 return (result);
00611
00612 dstalg = dst_alg_fromname(algorithm);
00613 if (dstalg == 0)
00614 return (DNS_R_BADALG);
00615
00616 result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
00617 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
00618 ring->mctx, keystr, &dstkey);
00619 if (result != ISC_R_SUCCESS)
00620 return (result);
00621
00622 result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
00623 ISC_TRUE, creator, inception,
00624 expire, ring->mctx, ring, NULL);
00625 if (dstkey != NULL)
00626 dst_key_free(&dstkey);
00627 return (result);
00628 }
00629
00630 static void
00631 dump_key(dns_tsigkey_t *tkey, FILE *fp) {
00632 char *buffer = NULL;
00633 int length = 0;
00634 char namestr[DNS_NAME_FORMATSIZE];
00635 char creatorstr[DNS_NAME_FORMATSIZE];
00636 char algorithmstr[DNS_NAME_FORMATSIZE];
00637 isc_result_t result;
00638
00639 REQUIRE(tkey != NULL);
00640 REQUIRE(fp != NULL);
00641
00642 dns_name_format(&tkey->name, namestr, sizeof(namestr));
00643 dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
00644 dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr));
00645 result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
00646 if (result == ISC_R_SUCCESS)
00647 fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
00648 tkey->inception, tkey->expire, algorithmstr,
00649 length, buffer);
00650 if (buffer != NULL)
00651 isc_mem_put(tkey->mctx, buffer, length);
00652 }
00653
00654 isc_result_t
00655 dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
00656 isc_result_t result;
00657 dns_rbtnodechain_t chain;
00658 dns_name_t foundname;
00659 dns_fixedname_t fixedorigin;
00660 dns_name_t *origin;
00661 isc_stdtime_t now;
00662 dns_rbtnode_t *node;
00663 dns_tsigkey_t *tkey;
00664 dns_tsig_keyring_t *ring;
00665 unsigned int references;
00666
00667 REQUIRE(ringp != NULL && *ringp != NULL);
00668
00669 ring = *ringp;
00670 *ringp = NULL;
00671
00672 RWLOCK(&ring->lock, isc_rwlocktype_write);
00673 INSIST(ring->references > 0);
00674 ring->references--;
00675 references = ring->references;
00676 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
00677
00678 if (references != 0)
00679 return (DNS_R_CONTINUE);
00680
00681 isc_stdtime_get(&now);
00682 dns_name_init(&foundname, NULL);
00683 dns_fixedname_init(&fixedorigin);
00684 origin = dns_fixedname_name(&fixedorigin);
00685 dns_rbtnodechain_init(&chain, ring->mctx);
00686 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
00687 origin);
00688 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00689 dns_rbtnodechain_invalidate(&chain);
00690 goto destroy;
00691 }
00692
00693 for (;;) {
00694 node = NULL;
00695 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
00696 tkey = node->data;
00697 if (tkey != NULL && tkey->generated && tkey->expire >= now)
00698 dump_key(tkey, fp);
00699 result = dns_rbtnodechain_next(&chain, &foundname,
00700 origin);
00701 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00702 dns_rbtnodechain_invalidate(&chain);
00703 if (result == ISC_R_NOMORE)
00704 result = ISC_R_SUCCESS;
00705 goto destroy;
00706 }
00707 }
00708
00709 destroy:
00710 destroyring(ring);
00711 return (result);
00712 }
00713
00714 isc_result_t
00715 dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
00716 unsigned char *secret, int length, isc_boolean_t generated,
00717 dns_name_t *creator, isc_stdtime_t inception,
00718 isc_stdtime_t expire, isc_mem_t *mctx,
00719 dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
00720 {
00721 dst_key_t *dstkey = NULL;
00722 isc_result_t result;
00723
00724 REQUIRE(length >= 0);
00725 if (length > 0)
00726 REQUIRE(secret != NULL);
00727
00728 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
00729 if (secret != NULL) {
00730 isc_buffer_t b;
00731
00732 isc_buffer_init(&b, secret, length);
00733 isc_buffer_add(&b, length);
00734 result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
00735 DNS_KEYOWNER_ENTITY,
00736 DNS_KEYPROTO_DNSSEC,
00737 dns_rdataclass_in,
00738 &b, mctx, &dstkey);
00739 if (result != ISC_R_SUCCESS)
00740 return (result);
00741 }
00742 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
00743 if (secret != NULL) {
00744 isc_buffer_t b;
00745
00746 isc_buffer_init(&b, secret, length);
00747 isc_buffer_add(&b, length);
00748 result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
00749 DNS_KEYOWNER_ENTITY,
00750 DNS_KEYPROTO_DNSSEC,
00751 dns_rdataclass_in,
00752 &b, mctx, &dstkey);
00753 if (result != ISC_R_SUCCESS)
00754 return (result);
00755 }
00756 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
00757 if (secret != NULL) {
00758 isc_buffer_t b;
00759
00760 isc_buffer_init(&b, secret, length);
00761 isc_buffer_add(&b, length);
00762 result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
00763 DNS_KEYOWNER_ENTITY,
00764 DNS_KEYPROTO_DNSSEC,
00765 dns_rdataclass_in,
00766 &b, mctx, &dstkey);
00767 if (result != ISC_R_SUCCESS)
00768 return (result);
00769 }
00770 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
00771 if (secret != NULL) {
00772 isc_buffer_t b;
00773
00774 isc_buffer_init(&b, secret, length);
00775 isc_buffer_add(&b, length);
00776 result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
00777 DNS_KEYOWNER_ENTITY,
00778 DNS_KEYPROTO_DNSSEC,
00779 dns_rdataclass_in,
00780 &b, mctx, &dstkey);
00781 if (result != ISC_R_SUCCESS)
00782 return (result);
00783 }
00784 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
00785 if (secret != NULL) {
00786 isc_buffer_t b;
00787
00788 isc_buffer_init(&b, secret, length);
00789 isc_buffer_add(&b, length);
00790 result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
00791 DNS_KEYOWNER_ENTITY,
00792 DNS_KEYPROTO_DNSSEC,
00793 dns_rdataclass_in,
00794 &b, mctx, &dstkey);
00795 if (result != ISC_R_SUCCESS)
00796 return (result);
00797 }
00798 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
00799 if (secret != NULL) {
00800 isc_buffer_t b;
00801
00802 isc_buffer_init(&b, secret, length);
00803 isc_buffer_add(&b, length);
00804 result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
00805 DNS_KEYOWNER_ENTITY,
00806 DNS_KEYPROTO_DNSSEC,
00807 dns_rdataclass_in,
00808 &b, mctx, &dstkey);
00809 if (result != ISC_R_SUCCESS)
00810 return (result);
00811 }
00812 } else if (length > 0)
00813 return (DNS_R_BADALG);
00814
00815 result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
00816 generated, creator,
00817 inception, expire, mctx, ring, key);
00818 if (dstkey != NULL)
00819 dst_key_free(&dstkey);
00820 return (result);
00821 }
00822
00823 void
00824 dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
00825 REQUIRE(VALID_TSIG_KEY(source));
00826 REQUIRE(targetp != NULL && *targetp == NULL);
00827
00828 isc_refcount_increment(&source->refs, NULL);
00829 *targetp = source;
00830 }
00831
00832 static void
00833 tsigkey_free(dns_tsigkey_t *key) {
00834 REQUIRE(VALID_TSIG_KEY(key));
00835
00836 key->magic = 0;
00837 dns_name_free(&key->name, key->mctx);
00838 if (algname_is_allocated(key->algorithm)) {
00839 dns_name_free(key->algorithm, key->mctx);
00840 isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
00841 }
00842 if (key->key != NULL)
00843 dst_key_free(&key->key);
00844 if (key->creator != NULL) {
00845 dns_name_free(key->creator, key->mctx);
00846 isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
00847 }
00848 isc_refcount_destroy(&key->refs);
00849 isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
00850 }
00851
00852 void
00853 dns_tsigkey_detach(dns_tsigkey_t **keyp) {
00854 dns_tsigkey_t *key;
00855 unsigned int refs;
00856
00857 REQUIRE(keyp != NULL);
00858 REQUIRE(VALID_TSIG_KEY(*keyp));
00859
00860 key = *keyp;
00861 isc_refcount_decrement(&key->refs, &refs);
00862
00863 if (refs == 0)
00864 tsigkey_free(key);
00865
00866 *keyp = NULL;
00867 }
00868
00869 void
00870 dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
00871 REQUIRE(VALID_TSIG_KEY(key));
00872 REQUIRE(key->ring != NULL);
00873
00874 RWLOCK(&key->ring->lock, isc_rwlocktype_write);
00875 remove_fromring(key);
00876 RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
00877 }
00878
00879 isc_result_t
00880 dns_tsig_sign(dns_message_t *msg) {
00881 dns_tsigkey_t *key;
00882 dns_rdata_any_tsig_t tsig, querytsig;
00883 unsigned char data[128];
00884 isc_buffer_t databuf, sigbuf;
00885 isc_buffer_t *dynbuf;
00886 dns_name_t *owner;
00887 dns_rdata_t *rdata = NULL;
00888 dns_rdatalist_t *datalist;
00889 dns_rdataset_t *dataset;
00890 isc_region_t r;
00891 isc_stdtime_t now;
00892 isc_mem_t *mctx;
00893 dst_context_t *ctx = NULL;
00894 isc_result_t ret;
00895 unsigned char badtimedata[BADTIMELEN];
00896 unsigned int sigsize = 0;
00897 isc_boolean_t response = is_response(msg);
00898
00899 REQUIRE(msg != NULL);
00900 REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));
00901
00902
00903
00904
00905 if (response && msg->querytsig == NULL)
00906 return (DNS_R_EXPECTEDTSIG);
00907
00908 dynbuf = NULL;
00909
00910 mctx = msg->mctx;
00911 key = dns_message_gettsigkey(msg);
00912
00913 tsig.mctx = mctx;
00914 tsig.common.rdclass = dns_rdataclass_any;
00915 tsig.common.rdtype = dns_rdatatype_tsig;
00916 ISC_LINK_INIT(&tsig.common, link);
00917 dns_name_init(&tsig.algorithm, NULL);
00918 dns_name_clone(key->algorithm, &tsig.algorithm);
00919
00920 isc_stdtime_get(&now);
00921 tsig.timesigned = now + msg->timeadjust;
00922 tsig.fudge = DNS_TSIG_FUDGE;
00923
00924 tsig.originalid = msg->id;
00925
00926 isc_buffer_init(&databuf, data, sizeof(data));
00927
00928 if (response)
00929 tsig.error = msg->querytsigstatus;
00930 else
00931 tsig.error = dns_rcode_noerror;
00932
00933 if (tsig.error != dns_tsigerror_badtime) {
00934 tsig.otherlen = 0;
00935 tsig.other = NULL;
00936 } else {
00937 isc_buffer_t otherbuf;
00938
00939 tsig.otherlen = BADTIMELEN;
00940 tsig.other = badtimedata;
00941 isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
00942 isc_buffer_putuint48(&otherbuf, tsig.timesigned);
00943 }
00944
00945 if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
00946 unsigned char header[DNS_MESSAGE_HEADERLEN];
00947 isc_buffer_t headerbuf;
00948 isc_uint16_t digestbits;
00949
00950 ret = dst_context_create3(key->key, mctx,
00951 DNS_LOGCATEGORY_DNSSEC,
00952 ISC_TRUE, &ctx);
00953 if (ret != ISC_R_SUCCESS)
00954 return (ret);
00955
00956
00957
00958
00959 if (response) {
00960 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
00961
00962 ret = dns_rdataset_first(msg->querytsig);
00963 if (ret != ISC_R_SUCCESS)
00964 goto cleanup_context;
00965 dns_rdataset_current(msg->querytsig, &querytsigrdata);
00966 ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
00967 NULL);
00968 if (ret != ISC_R_SUCCESS)
00969 goto cleanup_context;
00970 isc_buffer_putuint16(&databuf, querytsig.siglen);
00971 if (isc_buffer_availablelength(&databuf) <
00972 querytsig.siglen) {
00973 ret = ISC_R_NOSPACE;
00974 goto cleanup_context;
00975 }
00976 isc_buffer_putmem(&databuf, querytsig.signature,
00977 querytsig.siglen);
00978 isc_buffer_usedregion(&databuf, &r);
00979 ret = dst_context_adddata(ctx, &r);
00980 if (ret != ISC_R_SUCCESS)
00981 goto cleanup_context;
00982 }
00983 #if defined(__clang__) && \
00984 ( __clang_major__ < 3 || \
00985 (__clang_major__ == 3 && __clang_minor__ < 2) || \
00986 (__clang_major__ == 4 && __clang_minor__ < 2))
00987
00988 else memset(&querytsig, 0, sizeof(querytsig));
00989 #endif
00990
00991
00992
00993
00994 isc_buffer_init(&headerbuf, header, sizeof(header));
00995 dns_message_renderheader(msg, &headerbuf);
00996 isc_buffer_usedregion(&headerbuf, &r);
00997 ret = dst_context_adddata(ctx, &r);
00998 if (ret != ISC_R_SUCCESS)
00999 goto cleanup_context;
01000
01001
01002
01003
01004 isc_buffer_usedregion(msg->buffer, &r);
01005 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
01006 ret = dst_context_adddata(ctx, &r);
01007 if (ret != ISC_R_SUCCESS)
01008 goto cleanup_context;
01009
01010 if (msg->tcp_continuation == 0) {
01011
01012
01013
01014 dns_name_toregion(&key->name, &r);
01015 ret = dst_context_adddata(ctx, &r);
01016 if (ret != ISC_R_SUCCESS)
01017 goto cleanup_context;
01018
01019 isc_buffer_clear(&databuf);
01020 isc_buffer_putuint16(&databuf, dns_rdataclass_any);
01021 isc_buffer_putuint32(&databuf, 0);
01022 isc_buffer_usedregion(&databuf, &r);
01023 ret = dst_context_adddata(ctx, &r);
01024 if (ret != ISC_R_SUCCESS)
01025 goto cleanup_context;
01026
01027 dns_name_toregion(&tsig.algorithm, &r);
01028 ret = dst_context_adddata(ctx, &r);
01029 if (ret != ISC_R_SUCCESS)
01030 goto cleanup_context;
01031
01032 }
01033
01034 isc_buffer_clear(&databuf);
01035 if (tsig.error == dns_tsigerror_badtime) {
01036 INSIST(response);
01037 tsig.timesigned = querytsig.timesigned;
01038 }
01039 isc_buffer_putuint48(&databuf, tsig.timesigned);
01040 isc_buffer_putuint16(&databuf, tsig.fudge);
01041 isc_buffer_usedregion(&databuf, &r);
01042 ret = dst_context_adddata(ctx, &r);
01043 if (ret != ISC_R_SUCCESS)
01044 goto cleanup_context;
01045
01046 if (msg->tcp_continuation == 0) {
01047
01048
01049
01050 isc_buffer_clear(&databuf);
01051 isc_buffer_putuint16(&databuf, tsig.error);
01052 isc_buffer_putuint16(&databuf, tsig.otherlen);
01053
01054 isc_buffer_usedregion(&databuf, &r);
01055 ret = dst_context_adddata(ctx, &r);
01056 if (ret != ISC_R_SUCCESS)
01057 goto cleanup_context;
01058
01059
01060
01061
01062 if (tsig.otherlen > 0) {
01063 r.length = tsig.otherlen;
01064 r.base = tsig.other;
01065 ret = dst_context_adddata(ctx, &r);
01066 if (ret != ISC_R_SUCCESS)
01067 goto cleanup_context;
01068 }
01069 }
01070
01071 ret = dst_key_sigsize(key->key, &sigsize);
01072 if (ret != ISC_R_SUCCESS)
01073 goto cleanup_context;
01074 tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
01075 if (tsig.signature == NULL) {
01076 ret = ISC_R_NOMEMORY;
01077 goto cleanup_context;
01078 }
01079
01080 isc_buffer_init(&sigbuf, tsig.signature, sigsize);
01081 ret = dst_context_sign(ctx, &sigbuf);
01082 if (ret != ISC_R_SUCCESS)
01083 goto cleanup_signature;
01084 dst_context_destroy(&ctx);
01085 digestbits = dst_key_getbits(key->key);
01086 if (digestbits != 0) {
01087 unsigned int bytes = (digestbits + 1) / 8;
01088 if (response && bytes < querytsig.siglen)
01089 bytes = querytsig.siglen;
01090 if (bytes > isc_buffer_usedlength(&sigbuf))
01091 bytes = isc_buffer_usedlength(&sigbuf);
01092 tsig.siglen = bytes;
01093 } else
01094 tsig.siglen = isc_buffer_usedlength(&sigbuf);
01095 } else {
01096 tsig.siglen = 0;
01097 tsig.signature = NULL;
01098 }
01099
01100 ret = dns_message_gettemprdata(msg, &rdata);
01101 if (ret != ISC_R_SUCCESS)
01102 goto cleanup_signature;
01103 ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
01104 if (ret != ISC_R_SUCCESS)
01105 goto cleanup_rdata;
01106 ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
01107 dns_rdatatype_tsig, &tsig, dynbuf);
01108 if (ret != ISC_R_SUCCESS)
01109 goto cleanup_dynbuf;
01110
01111 dns_message_takebuffer(msg, &dynbuf);
01112
01113 if (tsig.signature != NULL) {
01114 isc_mem_put(mctx, tsig.signature, sigsize);
01115 tsig.signature = NULL;
01116 }
01117
01118 owner = NULL;
01119 ret = dns_message_gettempname(msg, &owner);
01120 if (ret != ISC_R_SUCCESS)
01121 goto cleanup_rdata;
01122 dns_name_init(owner, NULL);
01123 ret = dns_name_dup(&key->name, msg->mctx, owner);
01124 if (ret != ISC_R_SUCCESS)
01125 goto cleanup_owner;
01126
01127 datalist = NULL;
01128 ret = dns_message_gettemprdatalist(msg, &datalist);
01129 if (ret != ISC_R_SUCCESS)
01130 goto cleanup_owner;
01131 dataset = NULL;
01132 ret = dns_message_gettemprdataset(msg, &dataset);
01133 if (ret != ISC_R_SUCCESS)
01134 goto cleanup_rdatalist;
01135 datalist->rdclass = dns_rdataclass_any;
01136 datalist->type = dns_rdatatype_tsig;
01137 ISC_LIST_APPEND(datalist->rdata, rdata, link);
01138 dns_rdataset_init(dataset);
01139 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
01140 == ISC_R_SUCCESS);
01141 msg->tsig = dataset;
01142 msg->tsigname = owner;
01143
01144
01145 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
01146
01147 return (ISC_R_SUCCESS);
01148
01149 cleanup_rdatalist:
01150 dns_message_puttemprdatalist(msg, &datalist);
01151 cleanup_owner:
01152 dns_message_puttempname(msg, &owner);
01153 goto cleanup_rdata;
01154 cleanup_dynbuf:
01155 isc_buffer_free(&dynbuf);
01156 cleanup_rdata:
01157 dns_message_puttemprdata(msg, &rdata);
01158 cleanup_signature:
01159 if (tsig.signature != NULL)
01160 isc_mem_put(mctx, tsig.signature, sigsize);
01161 cleanup_context:
01162 if (ctx != NULL)
01163 dst_context_destroy(&ctx);
01164 return (ret);
01165 }
01166
01167 isc_result_t
01168 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
01169 dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
01170 {
01171 dns_rdata_any_tsig_t tsig, querytsig;
01172 isc_region_t r, source_r, header_r, sig_r;
01173 isc_buffer_t databuf;
01174 unsigned char data[32];
01175 dns_name_t *keyname;
01176 dns_rdata_t rdata = DNS_RDATA_INIT;
01177 isc_stdtime_t now;
01178 isc_result_t ret;
01179 dns_tsigkey_t *tsigkey;
01180 dst_key_t *key = NULL;
01181 unsigned char header[DNS_MESSAGE_HEADERLEN];
01182 dst_context_t *ctx = NULL;
01183 isc_mem_t *mctx;
01184 isc_uint16_t addcount, id;
01185 unsigned int siglen;
01186 unsigned int alg;
01187 isc_boolean_t response;
01188
01189 REQUIRE(source != NULL);
01190 REQUIRE(DNS_MESSAGE_VALID(msg));
01191 tsigkey = dns_message_gettsigkey(msg);
01192 response = is_response(msg);
01193
01194 REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
01195
01196 msg->verify_attempted = 1;
01197
01198 if (msg->tcp_continuation) {
01199 if (tsigkey == NULL || msg->querytsig == NULL)
01200 return (DNS_R_UNEXPECTEDTSIG);
01201 return (tsig_verify_tcp(source, msg));
01202 }
01203
01204
01205
01206
01207 if (msg->tsig == NULL)
01208 return (DNS_R_EXPECTEDTSIG);
01209
01210
01211
01212
01213
01214 if (response && (tsigkey == NULL || msg->querytsig == NULL))
01215 return (DNS_R_UNEXPECTEDTSIG);
01216
01217 mctx = msg->mctx;
01218
01219
01220
01221
01222
01223
01224 keyname = msg->tsigname;
01225 ret = dns_rdataset_first(msg->tsig);
01226 if (ret != ISC_R_SUCCESS)
01227 return (ret);
01228 dns_rdataset_current(msg->tsig, &rdata);
01229 ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
01230 if (ret != ISC_R_SUCCESS)
01231 return (ret);
01232 dns_rdata_reset(&rdata);
01233 if (response) {
01234 ret = dns_rdataset_first(msg->querytsig);
01235 if (ret != ISC_R_SUCCESS)
01236 return (ret);
01237 dns_rdataset_current(msg->querytsig, &rdata);
01238 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
01239 if (ret != ISC_R_SUCCESS)
01240 return (ret);
01241 }
01242 #if defined(__clang__) && \
01243 ( __clang_major__ < 3 || \
01244 (__clang_major__ == 3 && __clang_minor__ < 2) || \
01245 (__clang_major__ == 4 && __clang_minor__ < 2))
01246
01247 else memset(&querytsig, 0, sizeof(querytsig));
01248 #endif
01249
01250
01251
01252
01253 if (response &&
01254 (!dns_name_equal(keyname, &tsigkey->name) ||
01255 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
01256 msg->tsigstatus = dns_tsigerror_badkey;
01257 tsig_log(msg->tsigkey, 2,
01258 "key name and algorithm do not match");
01259 return (DNS_R_TSIGVERIFYFAILURE);
01260 }
01261
01262
01263
01264
01265 isc_stdtime_get(&now);
01266
01267
01268
01269
01270 if (tsigkey == NULL) {
01271 ret = ISC_R_NOTFOUND;
01272 if (ring1 != NULL)
01273 ret = dns_tsigkey_find(&tsigkey, keyname,
01274 &tsig.algorithm, ring1);
01275 if (ret == ISC_R_NOTFOUND && ring2 != NULL)
01276 ret = dns_tsigkey_find(&tsigkey, keyname,
01277 &tsig.algorithm, ring2);
01278 if (ret != ISC_R_SUCCESS) {
01279 msg->tsigstatus = dns_tsigerror_badkey;
01280 ret = dns_tsigkey_create(keyname, &tsig.algorithm,
01281 NULL, 0, ISC_FALSE, NULL,
01282 now, now,
01283 mctx, NULL, &msg->tsigkey);
01284 if (ret != ISC_R_SUCCESS)
01285 return (ret);
01286 tsig_log(msg->tsigkey, 2, "unknown key");
01287 return (DNS_R_TSIGVERIFYFAILURE);
01288 }
01289 msg->tsigkey = tsigkey;
01290 }
01291
01292 key = tsigkey->key;
01293
01294
01295
01296
01297 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
01298 msg->tsigstatus = dns_tsigerror_badtime;
01299 tsig_log(msg->tsigkey, 2, "signature has expired");
01300 return (DNS_R_CLOCKSKEW);
01301 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
01302 msg->tsigstatus = dns_tsigerror_badtime;
01303 tsig_log(msg->tsigkey, 2, "signature is in the future");
01304 return (DNS_R_CLOCKSKEW);
01305 }
01306
01307
01308
01309
01310 alg = dst_key_alg(key);
01311 ret = dst_key_sigsize(key, &siglen);
01312 if (ret != ISC_R_SUCCESS)
01313 return (ret);
01314 if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
01315 alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
01316 alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
01317 isc_uint16_t digestbits = dst_key_getbits(key);
01318 if (tsig.siglen > siglen) {
01319 tsig_log(msg->tsigkey, 2, "signature length too big");
01320 return (DNS_R_FORMERR);
01321 }
01322 if (tsig.siglen > 0 &&
01323 (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
01324 tsig_log(msg->tsigkey, 2,
01325 "signature length below minimum");
01326 return (DNS_R_FORMERR);
01327 }
01328 if (tsig.siglen > 0 && digestbits != 0 &&
01329 tsig.siglen < ((digestbits + 1) / 8)) {
01330 msg->tsigstatus = dns_tsigerror_badtrunc;
01331 tsig_log(msg->tsigkey, 2,
01332 "truncated signature length too small");
01333 return (DNS_R_TSIGVERIFYFAILURE);
01334 }
01335 if (tsig.siglen > 0 && digestbits == 0 &&
01336 tsig.siglen < siglen) {
01337 msg->tsigstatus = dns_tsigerror_badtrunc;
01338 tsig_log(msg->tsigkey, 2, "signature length too small");
01339 return (DNS_R_TSIGVERIFYFAILURE);
01340 }
01341 }
01342
01343 if (tsig.siglen > 0) {
01344 isc_uint16_t addcount_n;
01345
01346 sig_r.base = tsig.signature;
01347 sig_r.length = tsig.siglen;
01348
01349 ret = dst_context_create3(key, mctx,
01350 DNS_LOGCATEGORY_DNSSEC,
01351 ISC_FALSE, &ctx);
01352 if (ret != ISC_R_SUCCESS)
01353 return (ret);
01354
01355 if (response) {
01356 isc_buffer_init(&databuf, data, sizeof(data));
01357 isc_buffer_putuint16(&databuf, querytsig.siglen);
01358 isc_buffer_usedregion(&databuf, &r);
01359 ret = dst_context_adddata(ctx, &r);
01360 if (ret != ISC_R_SUCCESS)
01361 goto cleanup_context;
01362 if (querytsig.siglen > 0) {
01363 r.length = querytsig.siglen;
01364 r.base = querytsig.signature;
01365 ret = dst_context_adddata(ctx, &r);
01366 if (ret != ISC_R_SUCCESS)
01367 goto cleanup_context;
01368 }
01369 }
01370
01371
01372
01373
01374 isc_buffer_usedregion(source, &r);
01375 memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
01376 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
01377
01378
01379
01380
01381 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
01382 addcount_n = ntohs(addcount);
01383 addcount = htons((isc_uint16_t)(addcount_n - 1));
01384 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
01385
01386
01387
01388
01389 id = htons(tsig.originalid);
01390 memmove(&header[0], &id, 2);
01391
01392
01393
01394
01395 header_r.base = (unsigned char *) header;
01396 header_r.length = DNS_MESSAGE_HEADERLEN;
01397 ret = dst_context_adddata(ctx, &header_r);
01398 if (ret != ISC_R_SUCCESS)
01399 goto cleanup_context;
01400
01401
01402
01403
01404 isc_buffer_usedregion(source, &source_r);
01405 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
01406 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
01407 ret = dst_context_adddata(ctx, &r);
01408 if (ret != ISC_R_SUCCESS)
01409 goto cleanup_context;
01410
01411
01412
01413
01414 dns_name_toregion(&tsigkey->name, &r);
01415 ret = dst_context_adddata(ctx, &r);
01416 if (ret != ISC_R_SUCCESS)
01417 goto cleanup_context;
01418
01419 isc_buffer_init(&databuf, data, sizeof(data));
01420 isc_buffer_putuint16(&databuf, tsig.common.rdclass);
01421 isc_buffer_putuint32(&databuf, msg->tsig->ttl);
01422 isc_buffer_usedregion(&databuf, &r);
01423 ret = dst_context_adddata(ctx, &r);
01424 if (ret != ISC_R_SUCCESS)
01425 goto cleanup_context;
01426
01427
01428
01429
01430 dns_name_toregion(tsigkey->algorithm, &r);
01431 ret = dst_context_adddata(ctx, &r);
01432 if (ret != ISC_R_SUCCESS)
01433 goto cleanup_context;
01434
01435 isc_buffer_clear(&databuf);
01436 isc_buffer_putuint48(&databuf, tsig.timesigned);
01437 isc_buffer_putuint16(&databuf, tsig.fudge);
01438 isc_buffer_putuint16(&databuf, tsig.error);
01439 isc_buffer_putuint16(&databuf, tsig.otherlen);
01440 isc_buffer_usedregion(&databuf, &r);
01441 ret = dst_context_adddata(ctx, &r);
01442 if (ret != ISC_R_SUCCESS)
01443 goto cleanup_context;
01444
01445 if (tsig.otherlen > 0) {
01446 r.base = tsig.other;
01447 r.length = tsig.otherlen;
01448 ret = dst_context_adddata(ctx, &r);
01449 if (ret != ISC_R_SUCCESS)
01450 goto cleanup_context;
01451 }
01452
01453 ret = dst_context_verify(ctx, &sig_r);
01454 if (ret == DST_R_VERIFYFAILURE) {
01455 msg->tsigstatus = dns_tsigerror_badsig;
01456 ret = DNS_R_TSIGVERIFYFAILURE;
01457 tsig_log(msg->tsigkey, 2,
01458 "signature failed to verify(1)");
01459 goto cleanup_context;
01460 } else if (ret != ISC_R_SUCCESS)
01461 goto cleanup_context;
01462
01463 dst_context_destroy(&ctx);
01464 } else if (tsig.error != dns_tsigerror_badsig &&
01465 tsig.error != dns_tsigerror_badkey) {
01466 msg->tsigstatus = dns_tsigerror_badsig;
01467 tsig_log(msg->tsigkey, 2, "signature was empty");
01468 return (DNS_R_TSIGVERIFYFAILURE);
01469 }
01470
01471 msg->tsigstatus = dns_rcode_noerror;
01472
01473 if (tsig.error != dns_rcode_noerror) {
01474 if (tsig.error == dns_tsigerror_badtime)
01475 return (DNS_R_CLOCKSKEW);
01476 else
01477 return (DNS_R_TSIGERRORSET);
01478 }
01479
01480 msg->verified_sig = 1;
01481
01482 return (ISC_R_SUCCESS);
01483
01484 cleanup_context:
01485 if (ctx != NULL)
01486 dst_context_destroy(&ctx);
01487
01488 return (ret);
01489 }
01490
01491 static isc_result_t
01492 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
01493 dns_rdata_any_tsig_t tsig, querytsig;
01494 isc_region_t r, source_r, header_r, sig_r;
01495 isc_buffer_t databuf;
01496 unsigned char data[32];
01497 dns_name_t *keyname;
01498 dns_rdata_t rdata = DNS_RDATA_INIT;
01499 isc_stdtime_t now;
01500 isc_result_t ret;
01501 dns_tsigkey_t *tsigkey;
01502 dst_key_t *key = NULL;
01503 unsigned char header[DNS_MESSAGE_HEADERLEN];
01504 isc_uint16_t addcount, id;
01505 isc_boolean_t has_tsig = ISC_FALSE;
01506 isc_mem_t *mctx;
01507
01508 REQUIRE(source != NULL);
01509 REQUIRE(msg != NULL);
01510 REQUIRE(dns_message_gettsigkey(msg) != NULL);
01511 REQUIRE(msg->tcp_continuation == 1);
01512 REQUIRE(msg->querytsig != NULL);
01513
01514 if (!is_response(msg))
01515 return (DNS_R_EXPECTEDRESPONSE);
01516
01517 mctx = msg->mctx;
01518
01519 tsigkey = dns_message_gettsigkey(msg);
01520
01521
01522
01523
01524 ret = dns_rdataset_first(msg->querytsig);
01525 if (ret != ISC_R_SUCCESS)
01526 return (ret);
01527 dns_rdataset_current(msg->querytsig, &rdata);
01528 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
01529 if (ret != ISC_R_SUCCESS)
01530 return (ret);
01531 dns_rdata_reset(&rdata);
01532
01533
01534
01535
01536 if (msg->tsig != NULL) {
01537 has_tsig = ISC_TRUE;
01538
01539 keyname = msg->tsigname;
01540 ret = dns_rdataset_first(msg->tsig);
01541 if (ret != ISC_R_SUCCESS)
01542 goto cleanup_querystruct;
01543 dns_rdataset_current(msg->tsig, &rdata);
01544 ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
01545 if (ret != ISC_R_SUCCESS)
01546 goto cleanup_querystruct;
01547
01548
01549
01550
01551 if (!dns_name_equal(keyname, &tsigkey->name) ||
01552 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
01553 msg->tsigstatus = dns_tsigerror_badkey;
01554 ret = DNS_R_TSIGVERIFYFAILURE;
01555 tsig_log(msg->tsigkey, 2,
01556 "key name and algorithm do not match");
01557 goto cleanup_querystruct;
01558 }
01559
01560
01561
01562
01563 isc_stdtime_get(&now);
01564
01565 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
01566 msg->tsigstatus = dns_tsigerror_badtime;
01567 tsig_log(msg->tsigkey, 2, "signature has expired");
01568 ret = DNS_R_CLOCKSKEW;
01569 goto cleanup_querystruct;
01570 } else if (now + msg->timeadjust <
01571 tsig.timesigned - tsig.fudge) {
01572 msg->tsigstatus = dns_tsigerror_badtime;
01573 tsig_log(msg->tsigkey, 2,
01574 "signature is in the future");
01575 ret = DNS_R_CLOCKSKEW;
01576 goto cleanup_querystruct;
01577 }
01578 }
01579
01580 key = tsigkey->key;
01581
01582 if (msg->tsigctx == NULL) {
01583 ret = dst_context_create3(key, mctx,
01584 DNS_LOGCATEGORY_DNSSEC,
01585 ISC_FALSE, &msg->tsigctx);
01586 if (ret != ISC_R_SUCCESS)
01587 goto cleanup_querystruct;
01588
01589
01590
01591
01592 isc_buffer_init(&databuf, data, sizeof(data));
01593 isc_buffer_putuint16(&databuf, querytsig.siglen);
01594 isc_buffer_usedregion(&databuf, &r);
01595 ret = dst_context_adddata(msg->tsigctx, &r);
01596 if (ret != ISC_R_SUCCESS)
01597 goto cleanup_context;
01598
01599
01600
01601
01602 if (querytsig.siglen > 0) {
01603 r.length = querytsig.siglen;
01604 r.base = querytsig.signature;
01605 ret = dst_context_adddata(msg->tsigctx, &r);
01606 if (ret != ISC_R_SUCCESS)
01607 goto cleanup_context;
01608 }
01609 }
01610
01611
01612
01613
01614 isc_buffer_usedregion(source, &r);
01615 memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
01616 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
01617
01618
01619
01620
01621 if (has_tsig) {
01622 isc_uint16_t addcount_n;
01623
01624 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
01625 addcount_n = ntohs(addcount);
01626 addcount = htons((isc_uint16_t)(addcount_n - 1));
01627 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
01628 }
01629
01630
01631
01632
01633
01634 if (has_tsig) {
01635 id = htons(tsig.originalid);
01636 memmove(&header[0], &id, 2);
01637 }
01638
01639
01640
01641
01642 header_r.base = (unsigned char *) header;
01643 header_r.length = DNS_MESSAGE_HEADERLEN;
01644 ret = dst_context_adddata(msg->tsigctx, &header_r);
01645 if (ret != ISC_R_SUCCESS)
01646 goto cleanup_context;
01647
01648
01649
01650
01651 isc_buffer_usedregion(source, &source_r);
01652 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
01653 if (has_tsig)
01654 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
01655 else
01656 r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
01657 ret = dst_context_adddata(msg->tsigctx, &r);
01658 if (ret != ISC_R_SUCCESS)
01659 goto cleanup_context;
01660
01661
01662
01663
01664 if (has_tsig) {
01665 isc_buffer_init(&databuf, data, sizeof(data));
01666 isc_buffer_putuint48(&databuf, tsig.timesigned);
01667 isc_buffer_putuint16(&databuf, tsig.fudge);
01668 isc_buffer_usedregion(&databuf, &r);
01669 ret = dst_context_adddata(msg->tsigctx, &r);
01670 if (ret != ISC_R_SUCCESS)
01671 goto cleanup_context;
01672
01673 sig_r.base = tsig.signature;
01674 sig_r.length = tsig.siglen;
01675 if (tsig.siglen == 0) {
01676 if (tsig.error != dns_rcode_noerror) {
01677 if (tsig.error == dns_tsigerror_badtime)
01678 ret = DNS_R_CLOCKSKEW;
01679 else
01680 ret = DNS_R_TSIGERRORSET;
01681 } else {
01682 tsig_log(msg->tsigkey, 2,
01683 "signature is empty");
01684 ret = DNS_R_TSIGVERIFYFAILURE;
01685 }
01686 goto cleanup_context;
01687 }
01688
01689 ret = dst_context_verify(msg->tsigctx, &sig_r);
01690 if (ret == DST_R_VERIFYFAILURE) {
01691 msg->tsigstatus = dns_tsigerror_badsig;
01692 tsig_log(msg->tsigkey, 2,
01693 "signature failed to verify(2)");
01694 ret = DNS_R_TSIGVERIFYFAILURE;
01695 goto cleanup_context;
01696 }
01697 else if (ret != ISC_R_SUCCESS)
01698 goto cleanup_context;
01699
01700 dst_context_destroy(&msg->tsigctx);
01701 }
01702
01703 msg->tsigstatus = dns_rcode_noerror;
01704 return (ISC_R_SUCCESS);
01705
01706 cleanup_context:
01707 dst_context_destroy(&msg->tsigctx);
01708
01709 cleanup_querystruct:
01710 dns_rdata_freestruct(&querytsig);
01711
01712 return (ret);
01713
01714 }
01715
01716 isc_result_t
01717 dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
01718 dns_name_t *algorithm, dns_tsig_keyring_t *ring)
01719 {
01720 dns_tsigkey_t *key;
01721 isc_stdtime_t now;
01722 isc_result_t result;
01723
01724 REQUIRE(tsigkey != NULL);
01725 REQUIRE(*tsigkey == NULL);
01726 REQUIRE(name != NULL);
01727 REQUIRE(ring != NULL);
01728
01729 RWLOCK(&ring->lock, isc_rwlocktype_write);
01730 cleanup_ring(ring);
01731 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
01732
01733 isc_stdtime_get(&now);
01734 RWLOCK(&ring->lock, isc_rwlocktype_read);
01735 key = NULL;
01736 result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
01737 if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
01738 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
01739 return (ISC_R_NOTFOUND);
01740 }
01741 if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
01742 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
01743 return (ISC_R_NOTFOUND);
01744 }
01745 if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
01746
01747
01748
01749 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
01750 RWLOCK(&ring->lock, isc_rwlocktype_write);
01751 remove_fromring(key);
01752 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
01753 return (ISC_R_NOTFOUND);
01754 }
01755 #if 0
01756
01757
01758
01759 if (key->inception != key->expire &&
01760 isc_serial_lt(key->inception, now)) {
01761 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
01762 adjust_lru(key);
01763 return (ISC_R_NOTFOUND);
01764 }
01765 #endif
01766 isc_refcount_increment(&key->refs, NULL);
01767 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
01768 adjust_lru(key);
01769 *tsigkey = key;
01770 return (ISC_R_SUCCESS);
01771 }
01772
01773 static void
01774 free_tsignode(void *node, void *_unused) {
01775 dns_tsigkey_t *key;
01776
01777 REQUIRE(node != NULL);
01778
01779 UNUSED(_unused);
01780
01781 key = node;
01782 if (key->generated) {
01783 if (ISC_LINK_LINKED(key, link))
01784 ISC_LIST_UNLINK(key->ring->lru, key, link);
01785 }
01786 dns_tsigkey_detach(&key);
01787 }
01788
01789 isc_result_t
01790 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
01791 isc_result_t result;
01792 dns_tsig_keyring_t *ring;
01793
01794 REQUIRE(mctx != NULL);
01795 REQUIRE(ringp != NULL);
01796 REQUIRE(*ringp == NULL);
01797
01798 ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
01799 if (ring == NULL)
01800 return (ISC_R_NOMEMORY);
01801
01802 result = isc_rwlock_init(&ring->lock, 0, 0);
01803 if (result != ISC_R_SUCCESS) {
01804 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
01805 return (result);
01806 }
01807
01808 ring->keys = NULL;
01809 result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
01810 if (result != ISC_R_SUCCESS) {
01811 isc_rwlock_destroy(&ring->lock);
01812 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
01813 return (result);
01814 }
01815
01816 ring->writecount = 0;
01817 ring->mctx = NULL;
01818 ring->generated = 0;
01819 ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
01820 ISC_LIST_INIT(ring->lru);
01821 isc_mem_attach(mctx, &ring->mctx);
01822 ring->references = 1;
01823
01824 *ringp = ring;
01825 return (ISC_R_SUCCESS);
01826 }
01827
01828 isc_result_t
01829 dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
01830 dns_tsigkey_t *tkey)
01831 {
01832 isc_result_t result;
01833
01834 result = keyring_add(ring, name, tkey);
01835 if (result == ISC_R_SUCCESS)
01836 isc_refcount_increment(&tkey->refs, NULL);
01837
01838 return (result);
01839 }
01840
01841 void
01842 dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
01843 {
01844 REQUIRE(source != NULL);
01845 REQUIRE(target != NULL && *target == NULL);
01846
01847 RWLOCK(&source->lock, isc_rwlocktype_write);
01848 INSIST(source->references > 0);
01849 source->references++;
01850 INSIST(source->references > 0);
01851 *target = source;
01852 RWUNLOCK(&source->lock, isc_rwlocktype_write);
01853 }
01854
01855 void
01856 dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
01857 dns_tsig_keyring_t *ring;
01858 unsigned int references;
01859
01860 REQUIRE(ringp != NULL);
01861 REQUIRE(*ringp != NULL);
01862
01863 ring = *ringp;
01864 *ringp = NULL;
01865
01866 RWLOCK(&ring->lock, isc_rwlocktype_write);
01867 INSIST(ring->references > 0);
01868 ring->references--;
01869 references = ring->references;
01870 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
01871
01872 if (references == 0)
01873 destroyring(ring);
01874 }
01875
01876 void
01877 dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
01878 isc_stdtime_t now;
01879 isc_result_t result;
01880
01881 isc_stdtime_get(&now);
01882 do {
01883 result = restore_key(ring, now, fp);
01884 if (result == ISC_R_NOMORE)
01885 return;
01886 if (result == DNS_R_BADALG || result == DNS_R_EXPIRED)
01887 result = ISC_R_SUCCESS;
01888 } while (result == ISC_R_SUCCESS);
01889 }