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_prefix = old->rdata.tsig_record.time_prefix;
- new_rec->rdata.tsig_record.time = old->rdata.tsig_record.time;
- 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,
return wire_format;
}
-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,
- const uint8_t *req_mac,
- uint16_t req_mac_length,
- 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;
- char *fake_name;
- char *fake_alg;
-
- 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);
-
- /* 4.2 on replies, also hash the request MAC */
- if (req_mac != NULL) {
- hmac_md5_update(req_mac, req_mac_length, ctx);
- }
-
- /* 3.4.1 dns message */
- hmac_md5_update(blob.data, blob.length, ctx);
-
- /* 3.4.2 tsig variables */
- fake_name = dns_get_string_wire_format(mem_ctx, tsig->name);
- hmac_md5_update((const uint8_t *)fake_name, strlen(fake_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);
-
- fake_alg = dns_get_string_wire_format(mem_ctx,
- tsig->rdata.tsig_record.algorithm_name);
- hmac_md5_update((const uint8_t *)fake_alg,
- strlen(fake_alg)+1, ctx);
-
- dummy16 = htons(tsig->rdata.tsig_record.time_prefix);
- hmac_md5_update((const uint8_t *)&dummy16, 2, ctx);
-
- dummy32 = htonl(tsig->rdata.tsig_record.time);
- 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;
- 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, "test");
- 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,
- "hmac-md5.sig-alg.reg.int");
- tsig->rdata.tsig_record.time_prefix = 0;
-// tsig->rdata.tsig_record.time = 0x4f74260d;
- tsig->rdata.tsig_record.time = current_time;
- tsig->rdata.tsig_record.fudge = 300;
- tsig->rdata.tsig_record.original_id = 0xc25d;
- 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,
- NULL, 0, &mac, &mac_length);
- tsig->rdata.tsig_record.mac = mac;
- tsig->rdata.tsig_record.mac_size = mac_length;
-
- 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;
-}
-
-static WERROR verify_tsig(TALLOC_CTX *mem_ctx,
- struct dns_server_key *key,
- const uint8_t old_mac[16],
- struct dns_name_packet *packet)
-{
- WERROR werror;
- bool found_tsig = false;
- uint16_t i, mac_length = 0;
- uint8_t *mac = NULL;
- struct dns_res_rec *tsig;
-
- /* Find the first TSIG record in the additional records */
- for (i=0; i < packet->arcount; i++) {
- if (packet->additional[i].rr_type == DNS_QTYPE_TSIG) {
- found_tsig = true;
- break;
- }
- }
-
- if (!found_tsig) {
- return WERR_OK;
- }
-
- /* The TSIG record needs to be the last additional record */
- if (found_tsig && i + 1 != packet->arcount) {
- DEBUG(0, ("TSIG record not the last additional record!\n"));
- return DNS_ERR(FORMAT_ERROR);
- }
-
- NDR_PRINT_DEBUG(dns_name_packet, packet);
- /* We got a TSIG, so we need to sign our reply */
-
- tsig = talloc_zero(mem_ctx, struct dns_res_rec);
- W_ERROR_HAVE_NO_MEMORY(tsig);
-
- werror = dns_copy_tsig(tsig, &packet->additional[i],
- tsig);
- W_ERROR_NOT_OK_RETURN(werror);
-
- packet->arcount--;
-
- werror = dns_generate_tsig_mac(mem_ctx, key, packet, tsig,
- old_mac, 16, &mac, &mac_length);
- W_ERROR_NOT_OK_RETURN(werror);
-
-
- if (memcmp(tsig->rdata.tsig_record.mac, mac, mac_length) != 0) {
- DEBUG(1, ("TSIG MAC mismatch\n"));
- dump_data(1, tsig->rdata.tsig_record.mac,
- tsig->rdata.tsig_record.mac_size);
- dump_data(1, mac, mac_length);
- return DNS_ERR(NOTAUTH);
- }
-
- /* FIXME: Do a time check here, too. */
- 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;
+ struct dns_server_tkey *key;
enum ndr_err_code ndr_err;
struct tevent_req *req;
uint8_t out_mac[16];
dns_packet = make_name_packet(mem_ctx);
+ state = talloc_zero(mem_ctx, struct dns_request_state);
+
key = talloc_zero(mem_ctx, struct dns_server_key);
key->name = talloc_strdup(key, "test");
key->length = 12;
key->data = talloc_zero_size(key, key->length);
- sign_tsig(mem_ctx, key, dns_packet);
+ dns_sign_tsig(key, dns_packet);
memcpy(out_mac, dns_packet->additional[0].rdata.tsig_record.mac, 16);
//NDR_PRINT_DEBUG(dns_name_packet, in_packet);
- verify_tsig(mem_ctx, key, out_mac, in_packet);
+ dns_verify_tsig(mem_ctx, key, out_mac, in_packet);
error:
return ret;