TMP s4 dns: tsig test program
authorKai Blin <kai@samba.org>
Thu, 29 Mar 2012 08:08:26 +0000 (10:08 +0200)
committerKai Blin <kai@samba.org>
Tue, 8 May 2012 08:05:38 +0000 (10:05 +0200)
utils/dns-tsig.c [new file with mode: 0644]
utils/wscript_build

diff --git a/utils/dns-tsig.c b/utils/dns-tsig.c
new file mode 100644 (file)
index 0000000..abbfedd
--- /dev/null
@@ -0,0 +1,283 @@
+#include "includes.h"
+#include <talloc.h>
+#include <tevent.h>
+#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 <dns-server-ip>\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;
+}
index 3c22ad27aebdd7a031e5cdc99b434bbaa22df8f4..9f2f246168ea8a02459aabb22809354bc0dd840c 100644 (file)
@@ -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'
+       )