📄 tsig.c
字号:
/* * Copyright (C) 2004 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.112.2.3.8.4 2004/03/08 09:04:32 marka Exp $ */#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_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 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); 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_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 (key != 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 (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_algorithm; } refs++; RWUNLOCK(&ring->lock, isc_rwlocktype_write); } if (key != NULL) refs++; isc_refcount_init(&tkey->refs, refs); tkey->generated = generated; tkey->inception = inception; tkey->expire = expire; tkey->mctx = mctx; tkey->magic = TSIG_MAGIC; 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_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) && length > 0) return (DNS_R_BADALG); 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); } 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)); REQUIRE(targetp != NULL && *targetp == NULL); isc_refcount_increment(&source->refs, NULL); *targetp = source;}static voidtsigkey_free(dns_tsigkey_t *key) { REQUIRE(VALID_TSIG_KEY(key)); key->magic = 0; dns_name_free(&key->name, key->mctx); if (algname_is_allocated(key->algorithm)) { dns_name_free(key->algorithm, key->mctx); isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t)); } if (key->key != NULL) dst_key_free(&key->key); if (key->creator != NULL) { dns_name_free(key->creator, key->mctx); isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t)); } isc_refcount_destroy(&key->refs); isc_mem_put(key->mctx, key, sizeof(dns_tsigkey_t));}voiddns_tsigkey_detach(dns_tsigkey_t **keyp) { dns_tsigkey_t *key; unsigned int refs; REQUIRE(keyp != NULL); REQUIRE(VALID_TSIG_KEY(*keyp)); key = *keyp; isc_refcount_decrement(&key->refs, &refs); if (refs == 0) tsigkey_free(key); *keyp = NULL;}voiddns_tsigkey_setdeleted(dns_tsigkey_t *key) { REQUIRE(VALID_TSIG_KEY(key)); REQUIRE(key->ring != NULL); RWLOCK(&key->ring->lock, isc_rwlocktype_write); (void)dns_rbt_deletename(key->ring->keys, &key->name, ISC_FALSE); RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);}static voidbuffer_putuint48(isc_buffer_t *b, isc_uint64_t val) { isc_uint16_t valhi; isc_uint32_t vallo; valhi = (isc_uint16_t)(val >> 32); vallo = (isc_uint32_t)(val & 0xFFFFFFFF); isc_buffer_putuint16(b, valhi); isc_buffer_putuint32(b, vallo);}isc_result_tdns_tsig_sign(dns_message_t *msg) { dns_tsigkey_t *key; dns_rdata_any_tsig_t tsig, querytsig; unsigned char data[128]; isc_buffer_t databuf, sigbuf; isc_buffer_t *dynbuf; dns_name_t *owner; dns_rdata_t *rdata; dns_rdatalist_t *datalist; dns_rdataset_t *dataset; isc_region_t r; isc_stdtime_t now; isc_mem_t *mctx; dst_context_t *ctx = NULL; isc_result_t ret; unsigned char badtimedata[BADTIMELEN]; unsigned int sigsize = 0; REQUIRE(msg != NULL); REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg))); /* * If this is a response, there should be a query tsig. */ if (is_response(msg) && msg->querytsig == NULL) return (DNS_R_EXPECTEDTSIG); dynbuf = NULL; mctx = msg->mctx; key = dns_message_gettsigkey(msg); tsig.mctx = mctx; tsig.common.rdclass = dns_rdataclass_any; tsig.common.rdtype = dns_rdatatype_tsig; ISC_LINK_INIT(&tsig.common, link); dns_name_init(&tsig.algorithm, NULL); dns_name_clone(key->algorithm, &tsig.algorithm); isc_stdtime_get(&now); tsig.timesigned = now + msg->timeadjust; tsig.fudge = DNS_TSIG_FUDGE; tsig.originalid = msg->id; isc_buffer_init(&databuf, data, sizeof(data)); if (is_response(msg)) tsig.error = msg->querytsigstatus;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -