The Samba-Bugzilla – Attachment 18690 Details for
Bug 15844
getpwuid does not shift to new DC when current DC is down
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch from master for v4-21-test
bug-15844-v4-21-test.patch (text/plain), 12.59 KB, created by
Guenther Deschner
on 2025-08-19 13:17:40 UTC
(
hide
)
Description:
patch from master for v4-21-test
Filename:
MIME Type:
Creator:
Guenther Deschner
Created:
2025-08-19 13:17:40 UTC
Size:
12.59 KB
patch
obsolete
>From c51775f2e79a11572cb4f554a624a9570519e3ce Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 21 Jul 2025 06:44:22 +0200 >Subject: [PATCH 1/2] tldap: use tevent_req_set_endtime() to terminate LDAP > searches > >Needed to detect unresponsive LDAP servers, otherwise we might be sitting up to >924.6 seconds after sending a request before the kernel notifies us of a broken >connection. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=15844 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit 4e79fe13325385ef4fe37baeec8656c9b332de19) >--- > source3/lib/tldap.c | 5 +++++ > 1 file changed, 5 insertions(+) > >diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c >index ac95272fe06..3d4f672ac00 100644 >--- a/source3/lib/tldap.c >+++ b/source3/lib/tldap.c >@@ -1899,6 +1899,11 @@ struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx, > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >+ if (timelimit != 0) { >+ struct timeval end; >+ end = timeval_current_ofs(timelimit * 1.5F, 0); >+ tevent_req_set_endtime(subreq, ev, end); >+ } > tevent_req_set_callback(subreq, tldap_search_done, req); > return req; > >-- >2.50.1 > > >From c50a6eef48c40033617ab06d60781d66801ea85b Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 24 Jul 2025 15:49:19 +0200 >Subject: [PATCH 2/2] idmap_ad: add and use ldap_timeout and fix LDAP server > failover > >The key parts are: > >1. If an LDAP search fails with the hardcoded fatal error, remove the >retry. That would only retry the query against the same server, taken >from the DCINFO cache key. Instead, force a DC rediscovery. > >2. Set a default ldap_timeout and pass it to tldap_search(). This >avoids tldap_search() hanging forever on a stale TCP connection. > >3. The LDAP server idmap_ad is using is not necessarily the same DC >we're using for RPC, so in case we learn about a dead DC, put it in >the negative-conn-cache. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=15844 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Guenther Deschner <gd@samba.org> >(cherry picked from commit 4d69ec473b7be763399c9787eda8e659a1582184) >--- > source3/winbindd/idmap_ad.c | 33 ++++++++++++++------ > source3/winbindd/wb_queryuser.c | 10 +++++- > source3/winbindd/wb_sids2xids.c | 12 ++++++- > source3/winbindd/wb_xids2sids.c | 10 +++++- > source3/winbindd/winbindd_cm.c | 52 +++++++++++++++++++++++++++++++ > source3/winbindd/winbindd_proto.h | 1 + > 6 files changed, 106 insertions(+), 12 deletions(-) > >diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c >index 00a75a6f3ec..6b40da37724 100644 >--- a/source3/winbindd/idmap_ad.c >+++ b/source3/winbindd/idmap_ad.c >@@ -49,6 +49,7 @@ struct idmap_ad_context { > > bool unix_primary_group; > bool unix_nss_info; >+ int ldap_timeout; > > struct ldb_context *ldb; > struct ldb_dn **deny_ous; >@@ -545,6 +546,8 @@ static NTSTATUS idmap_ad_context_create(TALLOC_CTX *mem_ctx, > domname, "unix_primary_group", false); > ctx->unix_nss_info = idmap_config_bool( > domname, "unix_nss_info", false); >+ ctx->ldap_timeout = idmap_config_int( >+ domname, "ldap_timeout", 10); > > schema_mode = idmap_config_const_string( > domname, "schema_mode", "rfc2307"); >@@ -711,7 +714,7 @@ static NTSTATUS idmap_ad_query_user(struct idmap_domain *domain, > > rc = tldap_search(ctx->ld, ctx->default_nc, TLDAP_SCOPE_SUB, filter, > attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0, >- 0, 0, 0, talloc_tos(), &msgs); >+ ctx->ldap_timeout, 0, 0, talloc_tos(), &msgs); > if (!TLDAP_RC_IS_SUCCESS(rc)) { > return NT_STATUS_LDAP(TLDAP_RC_V(rc)); > } >@@ -784,13 +787,17 @@ static NTSTATUS idmap_ad_query_user_retry(struct idmap_domain *domain, > { > const NTSTATUS status_server_down = > NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN)); >+ const NTSTATUS status_timeout = >+ NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_TIMEOUT)); > NTSTATUS status; > > status = idmap_ad_query_user(domain, info); > >- if (NT_STATUS_EQUAL(status, status_server_down)) { >+ if (NT_STATUS_EQUAL(status, status_server_down) || >+ NT_STATUS_EQUAL(status, status_timeout)) >+ { > TALLOC_FREE(domain->private_data); >- status = idmap_ad_query_user(domain, info); >+ return NT_STATUS_HOST_UNREACHABLE; > } > > return status; >@@ -947,7 +954,7 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, > > rc = tldap_search(ctx->ld, ctx->default_nc, TLDAP_SCOPE_SUB, filter, > attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0, >- 0, 0, 0, talloc_tos(), &msgs); >+ ctx->ldap_timeout, 0, 0, talloc_tos(), &msgs); > if (!TLDAP_RC_IS_SUCCESS(rc)) { > return NT_STATUS_LDAP(TLDAP_RC_V(rc)); > } >@@ -1111,7 +1118,7 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, > > rc = tldap_search(ctx->ld, ctx->default_nc, TLDAP_SCOPE_SUB, filter, > attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0, >- 0, 0, 0, talloc_tos(), &msgs); >+ ctx->ldap_timeout, 0, 0, talloc_tos(), &msgs); > if (!TLDAP_RC_IS_SUCCESS(rc)) { > return NT_STATUS_LDAP(TLDAP_RC_V(rc)); > } >@@ -1218,13 +1225,17 @@ static NTSTATUS idmap_ad_unixids_to_sids_retry(struct idmap_domain *dom, > { > const NTSTATUS status_server_down = > NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN)); >+ const NTSTATUS status_timeout = >+ NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_TIMEOUT)); > NTSTATUS status; > > status = idmap_ad_unixids_to_sids(dom, ids); > >- if (NT_STATUS_EQUAL(status, status_server_down)) { >+ if (NT_STATUS_EQUAL(status, status_server_down) || >+ NT_STATUS_EQUAL(status, status_timeout)) >+ { > TALLOC_FREE(dom->private_data); >- status = idmap_ad_unixids_to_sids(dom, ids); >+ return NT_STATUS_HOST_UNREACHABLE; > } > > return status; >@@ -1235,13 +1246,17 @@ static NTSTATUS idmap_ad_sids_to_unixids_retry(struct idmap_domain *dom, > { > const NTSTATUS status_server_down = > NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN)); >+ const NTSTATUS status_timeout = >+ NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_TIMEOUT)); > NTSTATUS status; > > status = idmap_ad_sids_to_unixids(dom, ids); > >- if (NT_STATUS_EQUAL(status, status_server_down)) { >+ if (NT_STATUS_EQUAL(status, status_server_down) || >+ NT_STATUS_EQUAL(status, status_timeout)) >+ { > TALLOC_FREE(dom->private_data); >- status = idmap_ad_sids_to_unixids(dom, ids); >+ return NT_STATUS_HOST_UNREACHABLE; > } > > return status; >diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c >index db8e946ba71..0f318f8b631 100644 >--- a/source3/winbindd/wb_queryuser.c >+++ b/source3/winbindd/wb_queryuser.c >@@ -279,6 +279,7 @@ static void wb_queryuser_done(struct tevent_req *subreq) > NTSTATUS status, result; > bool need_group_name = false; > const char *tmpl = NULL; >+ uint32_t dsgetdcname_flags = DS_RETURN_DNS_NAME; > > status = dcerpc_wbint_GetNssInfo_recv(subreq, info, &result); > TALLOC_FREE(subreq); >@@ -287,6 +288,13 @@ static void wb_queryuser_done(struct tevent_req *subreq) > return; > } > >+ if (NT_STATUS_EQUAL(result, NT_STATUS_HOST_UNREACHABLE)) { >+ winbind_idmap_add_failed_connection_entry(info->domain_name); >+ /* Trigger DC lookup and reconnect below */ >+ result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; >+ dsgetdcname_flags |= DS_FORCE_REDISCOVERY; >+ } >+ > if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) && > !state->tried_dclookup) { > const char *domain_name = find_dns_domain_name( >@@ -301,7 +309,7 @@ static void wb_queryuser_done(struct tevent_req *subreq) > domain_name, > NULL, > NULL, >- DS_RETURN_DNS_NAME); >+ dsgetdcname_flags); > if (tevent_req_nomem(subreq, req)) { > return; > } >diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c >index 03e5e7e0258..f5ff9223034 100644 >--- a/source3/winbindd/wb_sids2xids.c >+++ b/source3/winbindd/wb_sids2xids.c >@@ -598,6 +598,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq) > NTSTATUS status, result; > const struct wbint_TransIDArray *src = NULL; > struct wbint_TransIDArray *dst = NULL; >+ uint32_t dsgetdcname_flags = DS_RETURN_DNS_NAME; > uint32_t si; > > status = dcerpc_wbint_Sids2UnixIDs_recv(subreq, state, &result); >@@ -608,6 +609,15 @@ static void wb_sids2xids_done(struct tevent_req *subreq) > return; > } > >+ if (NT_STATUS_EQUAL(result, NT_STATUS_HOST_UNREACHABLE)) { >+ struct lsa_DomainInfo *d = >+ &state->idmap_doms.domains[state->dom_index]; >+ winbind_idmap_add_failed_connection_entry(d->name.string); >+ /* Trigger DC lookup and reconnect below */ >+ result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; >+ dsgetdcname_flags |= DS_FORCE_REDISCOVERY; >+ } >+ > if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) && > !state->tried_dclookup) { > >@@ -627,7 +637,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq) > domain_name, > NULL, > NULL, >- DS_RETURN_DNS_NAME); >+ dsgetdcname_flags); > if (tevent_req_nomem(subreq, req)) { > return; > } >diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c >index 6fcf524d94f..0384740d17d 100644 >--- a/source3/winbindd/wb_xids2sids.c >+++ b/source3/winbindd/wb_xids2sids.c >@@ -130,6 +130,7 @@ static void wb_xids2sids_dom_done(struct tevent_req *subreq) > struct wb_xids2sids_dom_state *state = tevent_req_data( > req, struct wb_xids2sids_dom_state); > const struct wb_parent_idmap_config_dom *dom_map = state->dom_map; >+ uint32_t dsgetdcname_flags = DS_RETURN_DNS_NAME; > NTSTATUS status, result; > size_t i; > size_t dom_sid_idx; >@@ -140,6 +141,13 @@ static void wb_xids2sids_dom_done(struct tevent_req *subreq) > return; > } > >+ if (NT_STATUS_EQUAL(result, NT_STATUS_HOST_UNREACHABLE)) { >+ winbind_idmap_add_failed_connection_entry(dom_map->name); >+ /* Trigger DC lookup and reconnect below */ >+ result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; >+ dsgetdcname_flags |= DS_FORCE_REDISCOVERY; >+ } >+ > if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) && > !state->tried_dclookup) { > >@@ -151,7 +159,7 @@ static void wb_xids2sids_dom_done(struct tevent_req *subreq) > domain_name, > NULL, > NULL, >- DS_RETURN_DNS_NAME); >+ dsgetdcname_flags); > if (tevent_req_nomem(subreq, req)) { > return; > } >diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c >index bb2e4c0405d..765009b3496 100644 >--- a/source3/winbindd/winbindd_cm.c >+++ b/source3/winbindd/winbindd_cm.c >@@ -88,6 +88,8 @@ > #include "lib/util/string_wrappers.h" > #include "lib/global_contexts.h" > #include "librpc/gen_ndr/ndr_winbind_c.h" >+#include "source3/libsmb/namequery.h" >+#include "source3/libsmb/dsgetdcname.h" > > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_WINBIND >@@ -336,6 +338,56 @@ void winbind_add_failed_connection_entry( > winbindd_unset_locator_kdc_env(domain); > } > >+void winbind_idmap_add_failed_connection_entry(const char *_domain_name) >+{ >+ struct netr_DsRGetDCNameInfo *dcinfo = NULL; >+ const char *dc_unc = NULL; >+ const char *dc_address = NULL; >+ char *domain_name = NULL; >+ struct winbindd_domain *domain = NULL; >+ NTSTATUS failed_status = NT_STATUS_HOST_UNREACHABLE; >+ NTSTATUS status; >+ >+ domain_name = talloc_strdup_upper(talloc_tos(), _domain_name); >+ if (domain_name == NULL) { >+ DBG_ERR("talloc_strdup_upper failed\n"); >+ return; >+ } >+ >+ status = wb_dsgetdcname_gencache_get(talloc_tos(), domain_name, &dcinfo); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_DEBUG("Missing DC cache for domain '%s'\n", domain_name); >+ goto done; >+ } >+ >+ dc_unc = dcinfo->dc_unc; >+ while (dc_unc[0] == '\\') { >+ dc_unc++; >+ } >+ dc_address = dcinfo->dc_address; >+ while (dc_address[0] == '\\') { >+ dc_address++; >+ } >+ >+ add_failed_connection_entry(domain_name, dc_unc, failed_status); >+ add_failed_connection_entry(domain_name, dc_address, failed_status); >+ >+ domain = find_domain_from_name_noinit(domain_name); >+ if (domain == NULL) { >+ goto done; >+ } >+ if (domain->alt_name == NULL) { >+ goto done; >+ } >+ >+ add_failed_connection_entry(domain->alt_name, dc_unc, failed_status); >+ add_failed_connection_entry(domain->alt_name, dc_address, failed_status); >+ >+done: >+ TALLOC_FREE(domain_name); >+ TALLOC_FREE(dcinfo); >+} >+ > /* Choose between anonymous or authenticated connections. We need to use > an authenticated connection if DCs have the RestrictAnonymous registry > entry set > 0, or the "Additional restrictions for anonymous >diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h >index 9fc037eb04e..59d2ca7859d 100644 >--- a/source3/winbindd/winbindd_proto.h >+++ b/source3/winbindd/winbindd_proto.h >@@ -210,6 +210,7 @@ void winbind_add_failed_connection_entry( > const struct winbindd_domain *domain, > const char *server, > NTSTATUS result); >+void winbind_idmap_add_failed_connection_entry(const char *domain_name); > > struct cli_credentials; > NTSTATUS winbindd_get_trust_credentials(struct winbindd_domain *domain, >-- >2.50.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
slow
:
review+
Actions:
View
Attachments on
bug 15844
:
18631
|
18686
|
18687
| 18690