From 7e01c28e817778222733c26fde758110697a8d01 Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Thu, 29 Mar 2012 10:08:26 +0200 Subject: [PATCH] TMP s4 dns: tsig test program --- utils/dns-tsig.c | 283 ++++++++++++++++++++++++++++++++++++++++++++ utils/wscript_build | 4 + 2 files changed, 287 insertions(+) create mode 100644 utils/dns-tsig.c diff --git a/utils/dns-tsig.c b/utils/dns-tsig.c new file mode 100644 index 00000000000..abbfedd83a2 --- /dev/null +++ b/utils/dns-tsig.c @@ -0,0 +1,283 @@ +#include "includes.h" +#include +#include +#include "lib/util/samba_util.h" +#include "librpc/ndr/libndr.h" +#include "librpc/gen_ndr/ndr_dns.h" +#include "libcli/dns/libdns.h" +#include "lib/crypto/hmacmd5.h" +#include "system/network.h" +#include "dns_server/dns_server.h" + +static void usage(void) +{ + printf("Usage: dns-tsig \n\n"); +} + +static WERROR dns_copy_tsig(TALLOC_CTX *mem_ctx, + struct dns_res_rec *old, + struct dns_res_rec *new_rec) +{ + new_rec->name = talloc_strdup(mem_ctx, old->name); + W_ERROR_HAVE_NO_MEMORY(new_rec->name); + + new_rec->rr_type = old->rr_type; + new_rec->rr_class = old->rr_class; + new_rec->ttl = old->ttl; + new_rec->length = old->length; + new_rec->rdata.tsig_record.algorithm_name = talloc_strdup(mem_ctx, + old->rdata.tsig_record.algorithm_name); + W_ERROR_HAVE_NO_MEMORY(new_rec->rdata.tsig_record.algorithm_name); + + new_rec->rdata.tsig_record.time_high = old->rdata.tsig_record.time_high; + new_rec->rdata.tsig_record.time_low = old->rdata.tsig_record.time_low; + new_rec->rdata.tsig_record.fudge = old->rdata.tsig_record.fudge; + new_rec->rdata.tsig_record.mac_size = old->rdata.tsig_record.mac_size; + new_rec->rdata.tsig_record.mac = talloc_memdup(mem_ctx, + old->rdata.tsig_record.mac, + old->rdata.tsig_record.mac_size); + W_ERROR_HAVE_NO_MEMORY(new_rec->rdata.tsig_record.mac); + + new_rec->rdata.tsig_record.original_id = old->rdata.tsig_record.original_id; + new_rec->rdata.tsig_record.error = old->rdata.tsig_record.error; + new_rec->rdata.tsig_record.other_size = old->rdata.tsig_record.other_size; + new_rec->rdata.tsig_record.other_data = talloc_memdup(mem_ctx, + old->rdata.tsig_record.other_data, + old->rdata.tsig_record.other_size); + W_ERROR_HAVE_NO_MEMORY(new_rec->rdata.tsig_record.other_data); + + return WERR_OK; +} + + +static struct dns_name_packet *make_name_packet(TALLOC_CTX *mem_ctx) +{ + struct dns_name_packet *packet = talloc_zero(mem_ctx, + struct dns_name_packet); + struct dns_name_question *q = talloc_zero(packet, struct dns_name_question); + + packet->id = 0x165a; + packet->operation |= DNS_FLAG_RECURSION_DESIRED; + + q->name = talloc_strdup(q, "gonzo.ad.home.kblin.org"); + q->question_type = DNS_QTYPE_A; + q->question_class = DNS_QCLASS_IN; + + packet->qdcount = 1; + packet->questions = q; + + packet->nscount = 0; + packet->nsrecs = NULL; + + packet->arcount = 0; + packet->additional = NULL; + + return packet; +} + +static WERROR dns_generate_tsig_mac(TALLOC_CTX *mem_ctx, + const struct dns_server_key *key, + const struct dns_name_packet *packet, + const struct dns_res_rec *tsig, + uint8_t **mac, + uint16_t *mac_length) +{ + HMACMD5Context *ctx; + uint16_t digest_length = 16; + uint8_t *digest; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + uint16_t dummy16; + uint32_t dummy32; + + if (key == NULL) { + DEBUG(1, ("No key found, bailing out\n")); + *mac = NULL; + *mac_length = 0; + return WERR_OK; + } + + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, packet, + (ndr_push_flags_fn_t)ndr_push_dns_name_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return DNS_ERR(FORMAT_ERROR); + } + + ctx = talloc_zero(mem_ctx, HMACMD5Context); + W_ERROR_HAVE_NO_MEMORY(ctx); + + /* Build up the MAC as per RFC2845 */ + hmac_md5_init_rfc2104(key->data, key->length, ctx); + + dump_data(1, blob.data, blob.length); + + /* 3.4.1 dns message */ + hmac_md5_update(blob.data, blob.length, ctx); + + /* 3.4.2 tsig variables */ + dump_data(1, tsig->name, strlen(tsig->name)+1); + hmac_md5_update((const uint8_t *)tsig->name, strlen(tsig->name)+1, ctx); + + dummy16 = htons(tsig->rr_class); + hmac_md5_update((const uint8_t *)&dummy16, 2, ctx); + + dummy32 = htonl(tsig->ttl); + hmac_md5_update((const uint8_t *)&dummy32, 4, ctx); + + dump_data(1, tsig->rdata.tsig_record.algorithm_name, + strlen(tsig->rdata.tsig_record.algorithm_name)+1); + hmac_md5_update((const uint8_t *)tsig->rdata.tsig_record.algorithm_name, + strlen(tsig->rdata.tsig_record.algorithm_name)+1, ctx); + + dummy16 = htons(tsig->rdata.tsig_record.time_low); + hmac_md5_update((const uint8_t *)&dummy16, 2, ctx); + + dummy32 = htonl(tsig->rdata.tsig_record.time_high); + hmac_md5_update((const uint8_t *)&dummy32, 4, ctx); + + dummy16 = htons(tsig->rdata.tsig_record.fudge); + hmac_md5_update((const uint8_t *)&dummy16, 2, ctx); + + dummy16 = htons(tsig->rdata.tsig_record.error); + hmac_md5_update((const uint8_t *)&dummy16, 2, ctx); + + dummy16 = htons(tsig->rdata.tsig_record.other_size); + hmac_md5_update((const uint8_t *)&dummy16, 2, ctx); + + hmac_md5_update((const uint8_t*)&tsig->rdata.tsig_record.other_data, + tsig->rdata.tsig_record.other_size, ctx); + + digest = talloc_array(mem_ctx, uint8_t, digest_length); + W_ERROR_HAVE_NO_MEMORY(digest); + hmac_md5_final(digest, ctx); + + *mac = digest; + *mac_length = digest_length; + + return WERR_OK; +} + +static WERROR sign_tsig(TALLOC_CTX *mem_ctx, + struct dns_server_key *key, + struct dns_name_packet *packet) +{ + WERROR werror; + time_t current_time = time(NULL); + uint8_t *mac, *fake_mac; + uint16_t mac_length = 0; + struct dns_res_rec *tsig = talloc_zero(packet, struct dns_res_rec); + W_ERROR_HAVE_NO_MEMORY(tsig); + + tsig->name = talloc_strdup(tsig, "\x4test"); + W_ERROR_HAVE_NO_MEMORY(tsig->name); + + tsig->rr_class = DNS_QCLASS_ANY; + tsig->rr_type = DNS_QTYPE_TSIG; + tsig->ttl = 0; + tsig->length = UINT16_MAX; + tsig->rdata.tsig_record.algorithm_name = talloc_strdup(tsig, + "\x8hmac-md5\x7sig-alg\x3reg\x3int"); + tsig->rdata.tsig_record.time_high = 0x4f74; + tsig->rdata.tsig_record.time_low = 0x048e; + tsig->rdata.tsig_record.fudge = 300; + tsig->rdata.tsig_record.original_id = 0x165a; + tsig->rdata.tsig_record.error = 0; + tsig->rdata.tsig_record.other_size = 0; + tsig->rdata.tsig_record.other_data = NULL; + + werror = dns_generate_tsig_mac(mem_ctx, key, packet, tsig, + &mac, &mac_length); + + /* And here's the part where we fake stuff */ + fake_mac = talloc_zero_size(tsig, 16); + fake_mac[0] = 0xe2; + fake_mac[1] = 0x31; + fake_mac[2] = 0x2d; + fake_mac[3] = 0xc3; + fake_mac[4] = 0x80; + fake_mac[5] = 0x71; + fake_mac[6] = 0x2f; + fake_mac[7] = 0x35; + fake_mac[8] = 0x20; + fake_mac[9] = 0x5c; + fake_mac[10] = 0xe2; + fake_mac[11] = 0xed; + fake_mac[12] = 0x01; + fake_mac[13] = 0x62; + fake_mac[14] = 0xc2; + fake_mac[15] = 0x47; + tsig->rdata.tsig_record.mac_size = 16; + tsig->rdata.tsig_record.mac = fake_mac; + + dump_data(1, mac, mac_length); + dump_data(1, fake_mac, 16); + + if (packet->arcount == 0) { + packet->additional = talloc_zero(packet, struct dns_res_rec); + W_ERROR_HAVE_NO_MEMORY(packet->additional); + } + packet->additional = talloc_realloc(packet, packet->additional, + struct dns_res_rec, + packet->arcount + 1); + W_ERROR_HAVE_NO_MEMORY(packet->additional); + + werror = dns_copy_tsig(packet, tsig, + &packet->additional[packet->arcount]); + W_ERROR_NOT_OK_RETURN(werror); + + packet->arcount++; + + return WERR_OK; +} + +int main(int argc, char **argv) +{ + TALLOC_CTX *mem_ctx = talloc_init("samba-dig"); + struct tevent_context *ev; + struct dns_name_packet *dns_packet, *in_packet; + struct dns_server_key *key; + enum dns_qtype type; + enum ndr_err_code ndr_err; + struct tevent_req *req; + WERROR w_err; + DATA_BLOB out, in; + int ret = 0; + +#if 0 + if (argc < 2) { + usage(); + exit(1); + } +#endif + + ev = tevent_context_init(mem_ctx); + setup_logging("samba-dig", DEBUG_STDERR); + debug_parse_levels("1"); + + dns_packet = make_name_packet(mem_ctx); + + key = talloc_zero(mem_ctx, struct dns_server_key); + key->name = talloc_strdup(key, "test"); + + /* FIXME: 12??? */ + key->length = 12; + key->data = talloc_zero_size(key, key->length); + + sign_tsig(mem_ctx, key, dns_packet); + +#if 0 + NDR_PRINT_DEBUG(dns_name_packet, dns_packet); + ndr_err = ndr_push_struct_blob(&out, mem_ctx, dns_packet, + (ndr_push_flags_fn_t)ndr_push_dns_name_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0, ("Failed to marshall dns_name_packet: %d\n", ndr_err)); + ret = 1; + goto error; + } + + dump_data(1, out.data, out.length); +#endif + +error: + return ret; +} diff --git a/utils/wscript_build b/utils/wscript_build index 3c22ad27aeb..9f2f246168e 100644 --- a/utils/wscript_build +++ b/utils/wscript_build @@ -5,3 +5,7 @@ bld.SAMBA_BINARY('samba-dig', deps='samba-util NDR_DNS tevent LIBCLI_DNS' ) +bld.SAMBA_BINARY('dns-tsig', + source='dns-tsig.c', + deps='samba-util NDR_DNS tevent LIBCLI_DNS' + ) -- 2.34.1