From 6474c932d4353994113d36f38e3b6be7a1999a41 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 20 May 2015 11:17:38 +0300 Subject: [PATCH] s4: libcli/finddcs_cldap: continue processing CLDAP until all addresses are used This is a subtle bug that causes CLDAP pings to fail if SRV records discovered cannot be resolved or connection to them cannot be established. The code that fires up CLDAP ping will silently cancel the whole tevent request without going to the next server in the queue. This may happen, for example, when connection to IPv6 addresses couldn't be established, or when IPv4 address is not online or blocked by firewall. Fixes https://bugzilla.samba.org/show_bug.cgi?id=11284 Signed-off-by: Alexander Bokovoy --- source4/libcli/finddcs_cldap.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/source4/libcli/finddcs_cldap.c b/source4/libcli/finddcs_cldap.c index ce0e1c7..cebf205 100644 --- a/source4/libcli/finddcs_cldap.c +++ b/source4/libcli/finddcs_cldap.c @@ -42,6 +42,7 @@ struct finddcs_cldap_state { uint32_t srv_address_index; struct cldap_socket *cldap; struct cldap_netlogon *netlogon; + NTSTATUS status; }; static void finddcs_cldap_srv_resolved(struct composite_context *ctx); @@ -245,10 +246,14 @@ static void finddcs_cldap_next_server(struct finddcs_cldap_state *state) struct tevent_req *subreq; struct tsocket_address *dest; int ret; - NTSTATUS status; + TALLOC_FREE(state->cldap); if (state->srv_addresses[state->srv_address_index] == NULL) { - tevent_req_nterror(state->req, NT_STATUS_OBJECT_NAME_NOT_FOUND); + if (NT_STATUS_IS_OK(state->status)) { + tevent_req_nterror(state->req, NT_STATUS_OBJECT_NAME_NOT_FOUND); + } else { + tevent_req_nterror(state->req, state->status); + } DEBUG(2,("finddcs: No matching CLDAP server found\n")); return; } @@ -259,22 +264,29 @@ static void finddcs_cldap_next_server(struct finddcs_cldap_state *state) 389, &dest); if (ret == 0) { - status = NT_STATUS_OK; + state->status = NT_STATUS_OK; } else { - status = map_nt_error_from_unix_common(errno); + state->status = map_nt_error_from_unix_common(errno); } - if (tevent_req_nterror(state->req, status)) { + if (!NT_STATUS_IS_OK(state->status)) { + state->srv_address_index++; + finddcs_cldap_next_server(state); return; } - status = cldap_socket_init(state, NULL, dest, &state->cldap); - if (tevent_req_nterror(state->req, status)) { + state->status = cldap_socket_init(state, NULL, dest, &state->cldap); + if (!NT_STATUS_IS_OK(state->status)) { + state->srv_address_index++; + finddcs_cldap_next_server(state); return; } TALLOC_FREE(state->netlogon); state->netlogon = talloc_zero(state, struct cldap_netlogon); - if (tevent_req_nomem(state->netlogon, state->req)) { + if (state->netlogon == NULL) { + state->status = NT_STATUS_NO_MEMORY; + state->srv_address_index++; + finddcs_cldap_next_server(state); return; } @@ -283,7 +295,10 @@ static void finddcs_cldap_next_server(struct finddcs_cldap_state *state) } if (state->domain_sid) { state->netlogon->in.domain_sid = dom_sid_string(state, state->domain_sid); - if (tevent_req_nomem(state->netlogon->in.domain_sid, state->req)) { + if (state->netlogon->in.domain_sid == NULL) { + state->status = NT_STATUS_NO_MEMORY; + state->srv_address_index++; + finddcs_cldap_next_server(state); return; } } @@ -299,7 +314,10 @@ static void finddcs_cldap_next_server(struct finddcs_cldap_state *state) subreq = cldap_netlogon_send(state, state->ev, state->cldap, state->netlogon); - if (tevent_req_nomem(subreq, state->req)) { + if (subreq == NULL) { + state->status = NT_STATUS_NO_MEMORY; + state->srv_address_index++; + finddcs_cldap_next_server(state); return; } @@ -321,6 +339,7 @@ static void finddcs_cldap_netlogon_replied(struct tevent_req *subreq) TALLOC_FREE(subreq); TALLOC_FREE(state->cldap); if (!NT_STATUS_IS_OK(status)) { + state->status = status; state->srv_address_index++; finddcs_cldap_next_server(state); return; @@ -364,6 +383,7 @@ static void finddcs_cldap_name_resolved(struct composite_context *ctx) state->srv_address_index = 0; + state->status = NT_STATUS_OK; finddcs_cldap_next_server(state); } @@ -416,6 +436,7 @@ static void finddcs_cldap_srv_resolved(struct composite_context *ctx) state->srv_address_index = 0; + state->status = NT_STATUS_OK; finddcs_cldap_next_server(state); } -- 2.1.0