The branch, master has been updated via f60780c8b63 libcli/dns: Fix TCP fallback from d1891a0c4f6 autobuild: Fix path for libwbclient ldd checks
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f60780c8b633ece61c952122aee4f313edb26010 Author: Volker Lendecke <v...@samba.org> Date: Thu Jan 20 12:23:43 2022 +0100 libcli/dns: Fix TCP fallback A customer has come across a DNS server that really just cuts a SRV reply if it's too long. This makes the packet invalid according to ndr_pull and according to wireshark. DNS_FLAG_TRUNCATION is however set. As this seems to be legal according to the DNS RFCs, we need to hand-parse the first two uint16's and look whether DNS_FLAG_TRUNCATION is set. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Thu Jan 20 18:01:41 UTC 2022 on sn-devel-184 ----------------------------------------------------------------------- Summary of changes: libcli/dns/dns.c | 56 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 25 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/dns/dns.c b/libcli/dns/dns.c index 483697145ad..943b4d5b33e 100644 --- a/libcli/dns/dns.c +++ b/libcli/dns/dns.c @@ -475,6 +475,7 @@ static void dns_cli_request_udp_done(struct tevent_req *subreq) req, struct dns_cli_request_state); DATA_BLOB reply; enum ndr_err_code ndr_err; + uint16_t reply_id, operation; int ret; ret = dns_udp_request_recv(subreq, state, &reply.data, &reply.length); @@ -483,46 +484,51 @@ static void dns_cli_request_udp_done(struct tevent_req *subreq) return; } - state->reply = talloc(state, struct dns_name_packet); - if (tevent_req_nomem(state->reply, req)) { - return; - } - - ndr_err = ndr_pull_struct_blob( - &reply, state->reply, state->reply, - (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - tevent_req_error(req, ndr_map_error2errno(ndr_err)); + if (reply.length < 4) { + DBG_DEBUG("Short DNS packet: length=%zu\n", reply.length); + tevent_req_error(req, EINVAL); return; } - TALLOC_FREE(reply.data); - if (state->reply->id != state->req_id) { + reply_id = PULL_BE_U16(reply.data, 0); + if (reply_id != state->req_id) { DBG_DEBUG("Got id %"PRIu16", expected %"PRIu16"\n", state->reply->id, state->req_id); tevent_req_error(req, ENOMSG); return; } - if ((state->reply->operation & DNS_FLAG_TRUNCATION) == 0) { - DBG_DEBUG("Got op=%x %"PRIu16"/%"PRIu16"/%"PRIu16"/%"PRIu16 - " recs\n", (int)state->reply->operation, - state->reply->qdcount, state->reply->ancount, - state->reply->nscount, state->reply->nscount); - tevent_req_done(req); + operation = PULL_BE_U16(reply.data, 2); + if ((operation & DNS_FLAG_TRUNCATION) != 0) { + DBG_DEBUG("Reply was truncated, retrying TCP\n"); + subreq = dns_tcp_request_send( + state, + state->ev, + state->nameserver, + state->query.data, + state->query.length); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, dns_cli_request_tcp_done, req); return; } - DBG_DEBUG("Reply was truncated, retrying TCP\n"); - - TALLOC_FREE(state->reply); + state->reply = talloc(state, struct dns_name_packet); + if (tevent_req_nomem(state->reply, req)) { + return; + } - subreq = dns_tcp_request_send(state, state->ev, state->nameserver, - state->query.data, state->query.length); - if (tevent_req_nomem(subreq, req)) { + ndr_err = ndr_pull_struct_blob( + &reply, state->reply, state->reply, + (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + tevent_req_error(req, ndr_map_error2errno(ndr_err)); return; } - tevent_req_set_callback(subreq, dns_cli_request_tcp_done, req); + TALLOC_FREE(reply.data); + + tevent_req_done(req); } static void dns_cli_request_tcp_done(struct tevent_req *subreq) -- Samba Shared Repository