📄 tsig.c
字号:
/* * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* * $Id: tsig.c,v 1.117.18.9 2006/05/02 04:23:12 marka Exp $ *//*! \file */#include <config.h>#include <stdlib.h>#include <isc/buffer.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/refcount.h>#include <isc/string.h> /* Required for HP/UX (and others?) */#include <isc/util.h>#include <dns/keyvalues.h>#include <dns/log.h>#include <dns/message.h>#include <dns/rbt.h>#include <dns/rdata.h>#include <dns/rdatalist.h>#include <dns/rdataset.h>#include <dns/rdatastruct.h>#include <dns/result.h>#include <dns/tsig.h>#include <dst/result.h>#define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')#define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)#define algname_is_allocated(algname) \ ((algname) != dns_tsig_hmacmd5_name && \ (algname) != dns_tsig_hmacsha1_name && \ (algname) != dns_tsig_hmacsha224_name && \ (algname) != dns_tsig_hmacsha256_name && \ (algname) != dns_tsig_hmacsha384_name && \ (algname) != dns_tsig_hmacsha512_name && \ (algname) != dns_tsig_gssapi_name && \ (algname) != dns_tsig_gssapims_name)#define BADTIMELEN 6static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };static dns_name_t hmacmd5 = { DNS_NAME_MAGIC, hmacmd5_ndata, 26, 5, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, hmacmd5_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;static unsigned char gsstsig_ndata[] = "\010gss-tsig";static unsigned char gsstsig_offsets[] = { 0, 9 };static dns_name_t gsstsig = { DNS_NAME_MAGIC, gsstsig_ndata, 10, 2, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, gsstsig_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;/* It's nice of Microsoft to conform to their own standard. */static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };static dns_name_t gsstsigms = { DNS_NAME_MAGIC, gsstsigms_ndata, 19, 4, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, gsstsigms_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";static unsigned char hmacsha1_offsets[] = { 0, 10 };static dns_name_t hmacsha1 = { DNS_NAME_MAGIC, hmacsha1_ndata, 11, 2, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, hmacsha1_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";static unsigned char hmacsha224_offsets[] = { 0, 12 };static dns_name_t hmacsha224 = { DNS_NAME_MAGIC, hmacsha224_ndata, 13, 2, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, hmacsha224_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";static unsigned char hmacsha256_offsets[] = { 0, 12 };static dns_name_t hmacsha256 = { DNS_NAME_MAGIC, hmacsha256_ndata, 13, 2, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, hmacsha256_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";static unsigned char hmacsha384_offsets[] = { 0, 12 };static dns_name_t hmacsha384 = { DNS_NAME_MAGIC, hmacsha384_ndata, 13, 2, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, hmacsha384_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";static unsigned char hmacsha512_offsets[] = { 0, 12 };static dns_name_t hmacsha512 = { DNS_NAME_MAGIC, hmacsha512_ndata, 13, 2, DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, hmacsha512_offsets, NULL, {(void *)-1, (void *)-1}, {NULL, NULL}};LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;static isc_result_ttsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);static voidtsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4);static voidtsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) { va_list ap; char message[4096]; char namestr[DNS_NAME_FORMATSIZE]; if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) return; if (key != NULL) dns_name_format(&key->name, namestr, sizeof(namestr)); else strcpy(namestr, "<null>"); va_start(ap, fmt); vsnprintf(message, sizeof(message), fmt, ap); va_end(ap); isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG, level, "tsig key '%s': %s", namestr, message);}isc_result_tdns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, dst_key_t *dstkey, isc_boolean_t generated, dns_name_t *creator, isc_stdtime_t inception, isc_stdtime_t expire, isc_mem_t *mctx, dns_tsig_keyring_t *ring, dns_tsigkey_t **key){ dns_tsigkey_t *tkey; isc_result_t ret; unsigned int refs = 0; REQUIRE(key == NULL || *key == NULL); REQUIRE(name != NULL); REQUIRE(algorithm != NULL); REQUIRE(mctx != NULL); REQUIRE(key != NULL || ring != NULL); tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t)); if (tkey == NULL) return (ISC_R_NOMEMORY); dns_name_init(&tkey->name, NULL); ret = dns_name_dup(name, mctx, &tkey->name); if (ret != ISC_R_SUCCESS) goto cleanup_key; (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey->algorithm = DNS_TSIG_HMACMD5_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA1_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA224_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA224) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA256_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA256) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA384_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA384) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA512_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA512) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) { tkey->algorithm = DNS_TSIG_GSSAPI_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { ret = DNS_R_BADALG; goto cleanup_name; } } else { if (dstkey != NULL) { ret = DNS_R_BADALG; goto cleanup_name; } tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t)); if (tkey->algorithm == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_name; } dns_name_init(tkey->algorithm, NULL); ret = dns_name_dup(algorithm, mctx, tkey->algorithm); if (ret != ISC_R_SUCCESS) goto cleanup_algorithm; (void)dns_name_downcase(tkey->algorithm, tkey->algorithm, NULL); } if (creator != NULL) { tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t)); if (tkey->creator == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_algorithm; } dns_name_init(tkey->creator, NULL); ret = dns_name_dup(creator, mctx, tkey->creator); if (ret != ISC_R_SUCCESS) { isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); goto cleanup_algorithm; } } else tkey->creator = NULL; tkey->key = dstkey; tkey->ring = ring; if (key != NULL) refs++; if (ring != NULL) refs++; ret = isc_refcount_init(&tkey->refs, refs); if (ret != ISC_R_SUCCESS) goto cleanup_creator; tkey->generated = generated; tkey->inception = inception; tkey->expire = expire; tkey->mctx = mctx; tkey->magic = TSIG_MAGIC; if (ring != NULL) { RWLOCK(&ring->lock, isc_rwlocktype_write); ret = dns_rbt_addname(ring->keys, name, tkey); if (ret != ISC_R_SUCCESS) { RWUNLOCK(&ring->lock, isc_rwlocktype_write); goto cleanup_refs; } RWUNLOCK(&ring->lock, isc_rwlocktype_write); } if (dstkey != NULL && dst_key_size(dstkey) < 64) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG, ISC_LOG_INFO, "the key '%s' is too short to be secure", namestr); } if (key != NULL) *key = tkey; return (ISC_R_SUCCESS); cleanup_refs: tkey->magic = 0; while (refs-- > 0) isc_refcount_decrement(&tkey->refs, NULL); isc_refcount_destroy(&tkey->refs); cleanup_creator: if (tkey->creator != NULL) { dns_name_free(tkey->creator, mctx); isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); } cleanup_algorithm: if (algname_is_allocated(tkey->algorithm)) { if (dns_name_dynamic(tkey->algorithm)) dns_name_free(tkey->algorithm, mctx); isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t)); } cleanup_name: dns_name_free(&tkey->name, mctx); cleanup_key: isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t)); return (ret);}isc_result_tdns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, unsigned char *secret, int length, isc_boolean_t generated, dns_name_t *creator, isc_stdtime_t inception, isc_stdtime_t expire, isc_mem_t *mctx, dns_tsig_keyring_t *ring, dns_tsigkey_t **key){ dst_key_t *dstkey = NULL; isc_result_t result; REQUIRE(length >= 0); if (length > 0) REQUIRE(secret != NULL); if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { if (secret != NULL) { isc_buffer_t b; isc_buffer_init(&b, secret, length); isc_buffer_add(&b, length); result = dst_key_frombuffer(name, DST_ALG_HMACMD5, DNS_KEYOWNER_ENTITY, DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (result); } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { if (secret != NULL) { isc_buffer_t b; isc_buffer_init(&b, secret, length); isc_buffer_add(&b, length); result = dst_key_frombuffer(name, DST_ALG_HMACSHA1, DNS_KEYOWNER_ENTITY, DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (result); } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { if (secret != NULL) { isc_buffer_t b; isc_buffer_init(&b, secret, length); isc_buffer_add(&b, length); result = dst_key_frombuffer(name, DST_ALG_HMACSHA224, DNS_KEYOWNER_ENTITY, DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (result); } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { if (secret != NULL) { isc_buffer_t b; isc_buffer_init(&b, secret, length); isc_buffer_add(&b, length); result = dst_key_frombuffer(name, DST_ALG_HMACSHA256, DNS_KEYOWNER_ENTITY, DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (result); } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { if (secret != NULL) { isc_buffer_t b; isc_buffer_init(&b, secret, length); isc_buffer_add(&b, length); result = dst_key_frombuffer(name, DST_ALG_HMACSHA384, DNS_KEYOWNER_ENTITY, DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (result); } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { if (secret != NULL) { isc_buffer_t b; isc_buffer_init(&b, secret, length); isc_buffer_add(&b, length); result = dst_key_frombuffer(name, DST_ALG_HMACSHA512, DNS_KEYOWNER_ENTITY, DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (result); } } else if (length > 0) return (DNS_R_BADALG); result = dns_tsigkey_createfromkey(name, algorithm, dstkey, generated, creator, inception, expire, mctx, ring, key); if (result != ISC_R_SUCCESS && dstkey != NULL) dst_key_free(&dstkey); return (result);}voiddns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) { REQUIRE(VALID_TSIG_KEY(source));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -