>From 6c74a621f721e685f8bb4a3b14ca18e8d5e1f2a5 Mon Sep 17 00:00:00 2001 From: Matthieu Patou Date: Wed, 8 Oct 2014 18:59:12 -0700 Subject: [PATCH] WIP patch to fix the use after free in the DNS server Change-Id: I5b967e93a53214761b393fcd9af64a32f85addc0 --- source4/dns_server/dns_crypto.c | 3 ++- source4/dns_server/dns_query.c | 2 +- source4/dns_server/dns_server.c | 21 +++++++++++---------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/source4/dns_server/dns_crypto.c b/source4/dns_server/dns_crypto.c index aba906d..6b462f2 100644 --- a/source4/dns_server/dns_crypto.c +++ b/source4/dns_server/dns_crypto.c @@ -225,8 +225,9 @@ WERROR dns_verify_tsig(struct dns_server *dns, return ntstatus_to_werror(status); } + state->authenticated = true; - state->key_name = talloc_strdup(mem_ctx, tkey->name); + state->key_name = talloc_strdup(state, tkey->name); if (state->key_name == NULL) { return WERR_NOMEM; } diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index b57cdb8..1b9f9fe 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -529,7 +529,7 @@ static WERROR handle_tkey(struct dns_server *dns, reply.data, reply.length); state->sign = true; - state->key_name = talloc_strdup(mem_ctx, tkey->name); + state->key_name = talloc_strdup(state, tkey->name); if (state->key_name == NULL) { return WERR_NOMEM; } diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index 7ea70db..b0595a7 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -103,7 +103,7 @@ struct dns_process_state { DATA_BLOB *in; struct dns_server *dns; struct dns_name_packet in_packet; - struct dns_request_state state; + struct dns_request_state *state; uint16_t dns_err; struct dns_name_packet out_packet; DATA_BLOB out; @@ -128,6 +128,7 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx, state->in = in; state->dns = dns; + state->state = talloc_zero(state, struct dns_request_state); if (in->length < 12) { tevent_req_werror(req, WERR_INVALID_PARAM); @@ -148,7 +149,7 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx, NDR_PRINT_DEBUGC(DBGC_DNS, dns_name_packet, &state->in_packet); } - ret = dns_verify_tsig(dns, state, &state->state, &state->in_packet, in); + ret = dns_verify_tsig(dns, state, state->state, &state->in_packet, in); if (!W_ERROR_IS_OK(ret)) { DEBUG(1, ("Failed to verify TSIG!\n")); state->dns_err = werr_to_dns_err(ret); @@ -162,12 +163,12 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - state->state.flags = state->in_packet.operation; - state->state.flags |= DNS_FLAG_REPLY; + state->state->flags = state->in_packet.operation; + state->state->flags |= DNS_FLAG_REPLY; if (forwarder && *forwarder) { - state->state.flags |= DNS_FLAG_RECURSION_AVAIL; + state->state->flags |= DNS_FLAG_RECURSION_AVAIL; } state->out_packet = state->in_packet; @@ -175,7 +176,7 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx, switch (state->in_packet.operation & DNS_OPCODE) { case DNS_OPCODE_QUERY: subreq = dns_server_process_query_send( - state, ev, dns, &state->state, &state->in_packet); + state, ev, dns, state->state, &state->in_packet); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -183,7 +184,7 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx, return req; case DNS_OPCODE_UPDATE: ret = dns_server_process_update( - dns, &state->state, state, &state->in_packet, + dns, state->state, state, &state->in_packet, &state->out_packet.answers, &state->out_packet.ancount, &state->out_packet.nsrecs, &state->out_packet.nscount, &state->out_packet.additional, @@ -234,10 +235,10 @@ static WERROR dns_process_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, if (state->dns_err != DNS_RCODE_OK) { goto drop; } - state->out_packet.operation |= state->state.flags; + state->out_packet.operation |= state->state->flags; - if (state->state.sign) { - ret = dns_sign_tsig(state->dns, mem_ctx, &state->state, + if (state->state->sign) { + ret = dns_sign_tsig(state->dns, mem_ctx, state->state, &state->out_packet, 0); if (!W_ERROR_IS_OK(ret)) { state->dns_err = DNS_RCODE_SERVFAIL; -- 2.1.0