From cca369221b788ad12e89b8b91b3856b2b5d3b811 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 28 Feb 2018 07:59:08 +0000 Subject: [PATCH 01/15] utils: Add destroy_netlogon_creds_cli This is a pure testing utility that will garble the netlogon_creds_cli session_key. This creates a similar effect to our schannel credentials as does a domain controller reboot. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher (backported from commit bffae41842fe218959fe6f8b43df694feec1589c) --- source3/utils/destroy_netlogon_creds_cli.c | 136 +++++++++++++++++++++++++++++ source3/utils/wscript_build | 9 ++ 2 files changed, 145 insertions(+) create mode 100644 source3/utils/destroy_netlogon_creds_cli.c diff --git a/source3/utils/destroy_netlogon_creds_cli.c b/source3/utils/destroy_netlogon_creds_cli.c new file mode 100644 index 00000000000..c7726d25fdb --- /dev/null +++ b/source3/utils/destroy_netlogon_creds_cli.c @@ -0,0 +1,136 @@ +/* + * Unix SMB/CIFS implementation. + * Garble the netlogon_creds_cli key for testing purposes + * Copyright (C) Volker Lendecke 2018 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "includes.h" +#include "system/filesys.h" +#include +#include +#include "messages.h" +#include "lib/util/talloc_stack.h" +#include "popt_common.h" +#include "lib/param/loadparm.h" +#include "lib/param/param.h" +#include "libcli/auth/netlogon_creds_cli.h" +#include "lib/dbwrap/dbwrap.h" +#include "lib/dbwrap/dbwrap_open.h" + +int main(int argc, const char *argv[]) +{ + TALLOC_CTX *mem_ctx = talloc_stackframe(); + struct tevent_context *ev; + struct messaging_context *msg_ctx; + struct loadparm_context *lp_ctx; + struct db_context *global_db; + struct netlogon_creds_cli_context *ctx; + struct netlogon_creds_CredentialState *creds; + NTSTATUS status; + int ret = 1; + + smb_init_locale(); + + if (!lp_load_global(get_dyn_CONFIGFILE())) { + fprintf(stderr, "error opening config file %s. Error was %s\n", + get_dyn_CONFIGFILE(), strerror(errno)); + goto done; + } + + if (argc != 4) { + fprintf(stderr, "usage: %s cli_computer domain dc\n", argv[0]); + goto done; + } + + lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + fprintf(stderr, "loadparm_init_s3 failed\n"); + goto done; + } + + ev = samba_tevent_context_init(mem_ctx); + if (ev == NULL) { + fprintf(stderr, "samba3_tevent_context_init failed\n"); + goto done; + } + msg_ctx = messaging_init(mem_ctx, ev); + if (msg_ctx == NULL) { + fprintf(stderr, "messaging_init failed\n"); + goto done; + } + + global_db = db_open( + mem_ctx, + lpcfg_private_db_path(mem_ctx, lp_ctx, "netlogon_creds_cli"), + 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, + O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2, + DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS); + if (global_db == NULL) { + fprintf(stderr, "db_open failed\n"); + goto done; + } + + status = netlogon_creds_cli_set_global_db(&global_db); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "netlogon_creds_cli_set_global_db failed: %s\n", + nt_errstr(status)); + goto done; + } + + status = netlogon_creds_cli_context_global( + lp_ctx, + msg_ctx, + talloc_asprintf(mem_ctx, "%s$", argv[1]), + SEC_CHAN_WKSTA, + argv[3], + argv[2], + mem_ctx, + &ctx); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "netlogon_creds_cli_context_global failed: %s\n", + nt_errstr(status)); + goto done; + } + + status = netlogon_creds_cli_lock(ctx, + mem_ctx, + &creds); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "netlogon_creds_cli_get failed: %s\n", + nt_errstr(status)); + goto done; + } + + creds->session_key[0]++; + + status = netlogon_creds_cli_store(ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "netlogon_creds_cli_store failed: %s\n", + nt_errstr(status)); + goto done; + } + + TALLOC_FREE(creds); + + ret = 0; +done: + TALLOC_FREE(mem_ctx); + return ret; +} diff --git a/source3/utils/wscript_build b/source3/utils/wscript_build index 3c1f9a4773d..f2e118e1666 100644 --- a/source3/utils/wscript_build +++ b/source3/utils/wscript_build @@ -258,3 +258,12 @@ bld.SAMBA3_BINARY('mvxattr', popt_samba3 ''', enabled=bld.env.build_mvxattr) + +bld.SAMBA3_BINARY('destroy_netlogon_creds_cli', + source='destroy_netlogon_creds_cli.c', + deps = ''' + talloc + popt_samba3 + NETLOGON_CREDS_CLI + ''', + install=False) -- 2.13.6 From 3cbb3064bcca13ce45ead93021a1441eba0c0eda Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 28 Feb 2018 15:08:44 +0000 Subject: [PATCH 02/15] winbind: Add smbcontrol disconnect-dc Make a winbind child drop all DC connections Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme (backported from commit 0af88b98e7e1bba14827305257e77b63dc82d902) --- librpc/idl/messaging.idl | 1 + source3/utils/smbcontrol.c | 14 ++++++++++++++ source3/winbindd/winbindd.c | 4 ++++ source3/winbindd/winbindd_cm.c | 16 ++++++++++++++++ source3/winbindd/winbindd_dual.c | 21 ++++++++++++++++++++- source3/winbindd/winbindd_proto.h | 10 ++++++++++ 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl index b962ab17be2..969e2275214 100644 --- a/librpc/idl/messaging.idl +++ b/librpc/idl/messaging.idl @@ -124,6 +124,7 @@ interface messaging MSG_WINBIND_DOMAIN_ONLINE = 0x040B, MSG_WINBIND_DOMAIN_OFFLINE = 0x040C, MSG_WINBIND_NEW_TRUSTED_DOMAIN = 0x040D, + MSG_WINBIND_DISCONNECT_DC = 0x040E, /* event messages */ MSG_DUMP_EVENT_LIST = 0x0500, diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index 4c4bfcb4e5b..1fc00134395 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -1267,6 +1267,19 @@ static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx, return num_replies; } +static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx, + struct messaging_context *msg_ctx, + const struct server_id pid, + const int argc, const char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol disconnect-dc\n"); + return False; + } + + return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0); +} + static void winbind_validate_cache_cb(struct messaging_context *msg, void *private_data, uint32_t msg_type, @@ -1445,6 +1458,7 @@ static const struct { { "validate-cache" , do_winbind_validate_cache, "Validate winbind's credential cache" }, { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"}, + { "disconnect-dc", do_msg_disconnect_dc }, { "notify-cleanup", do_notify_cleanup }, { "num-children", do_num_children, "Print number of smbd child processes" }, diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index ceb131e9b32..4925fa4b8fb 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1356,6 +1356,10 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx, MSG_DEBUG, winbind_msg_debug); + messaging_register(msg_ctx, NULL, + MSG_WINBIND_DISCONNECT_DC, + winbind_disconnect_dc_parent); + netsamlogon_cache_init(); /* Non-critical */ /* clear the cached list of trusted domains */ diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ee168fc3e4b..dbefe72e718 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -3467,3 +3467,19 @@ void winbind_msg_ip_dropped(struct messaging_context *msg_ctx, } TALLOC_FREE(freeit); } + +void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_domain *domain; + + for (domain = domain_list(); domain; domain = domain->next) { + if (domain->internal) { + continue; + } + invalidate_cm_connection(domain); + } +} diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 512ecd06141..778f7f1b423 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -785,6 +785,23 @@ void winbind_msg_debug(struct messaging_context *msg_ctx, strlen((char *) data->data) + 1); } } +void winbind_disconnect_dc_parent(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbindd_child *child = NULL; + + DBG_DEBUG("Got disconnect_dc message\n"); + + for (child = winbindd_children; child != NULL; child = child->next) { + messaging_send_buf(msg_ctx, + pid_to_procid(child->pid), + MSG_WINBIND_DISCONNECT_DC, + NULL, 0); + } +} /* Set our domains as offline and forward the offline message to our children. */ @@ -1658,7 +1675,9 @@ static bool fork_domain_child(struct winbindd_child *child) messaging_register(server_messaging_context(), NULL, MSG_WINBIND_IP_DROPPED, winbind_msg_ip_dropped); - + messaging_register(server_messaging_context(), NULL, + MSG_WINBIND_DISCONNECT_DC, + winbind_msg_disconnect_dc); primary_domain = find_our_domain(); diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index a300a534d03..f9841797166 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -320,6 +320,11 @@ void winbind_msg_debug(struct messaging_context *msg_ctx, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data); +void winbind_disconnect_dc_parent(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); void winbind_msg_offline(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, @@ -350,6 +355,11 @@ void winbind_msg_ip_dropped(struct messaging_context *msg_ctx, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data); +void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); void winbind_msg_ip_dropped_parent(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, -- 2.13.6 From 030ced4c1b15b6ec8898054ef8ffe0f573a51d81 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 28 Feb 2018 15:09:28 +0000 Subject: [PATCH 03/15] winbind: Keep "force_reauth" in invalidate_cm_connection Right now I don't see a way to actually force a re-serverauth from the client side as long as an entry in netlogon_creds_cli.tdb exists. cm_connect_netlogon goes through invalidate_cm_connection, and this wipes our wish to force a reauthenticatoin. Keep this intact until we actually did reauthenticate. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher (cherry picked from commit 4b7a9d560a51b51ac88f30276c87edc097b00d0b) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index dbefe72e718..e19fe02ffad 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2036,7 +2036,6 @@ void invalidate_cm_connection(struct winbindd_domain *domain) } conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; - conn->netlogon_force_reauth = false; conn->netlogon_flags = 0; TALLOC_FREE(conn->netlogon_creds); @@ -3347,6 +3346,7 @@ static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain, creds, conn->netlogon_creds, &conn->netlogon_pipe); + conn->netlogon_force_reauth = false; if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " "was %s\n", nt_errstr(result))); -- 2.13.6 From fd4d51d7ff6bc8fcf7be592b1b657970155b1d00 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 13:30:01 +0100 Subject: [PATCH 04/15] winbindd: add and use ldap_reconnect_need_retry() in winbindd_reconnect_ads.c ldap_reconnect_need_retry() is a copy of reconnect_need_retry() minus the RPC connection invalidation. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit a8d5e4d36768bc199c631626488b2d0acbd6e91a) --- source3/winbindd/winbindd_reconnect_ads.c | 58 +++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/source3/winbindd/winbindd_reconnect_ads.c b/source3/winbindd/winbindd_reconnect_ads.c index 3bb8b5ecba1..0a0a14f6dd0 100644 --- a/source3/winbindd/winbindd_reconnect_ads.c +++ b/source3/winbindd/winbindd_reconnect_ads.c @@ -31,6 +31,52 @@ extern struct winbindd_methods ads_methods; +static bool ldap_reconnect_need_retry(NTSTATUS status, + struct winbindd_domain *domain) +{ + if (NT_STATUS_IS_OK(status)) { + return false; + } + + if (!NT_STATUS_IS_ERR(status)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_GROUP)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_ALIAS)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_MEMBER)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_PRIVILEGE)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) { + return false; + } + + return true; +} + /* List all users */ static NTSTATUS query_user_list(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -40,7 +86,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, result = ads_methods.query_user_list(domain, mem_ctx, rids); - if (reconnect_need_retry(result, domain)) { + if (ldap_reconnect_need_retry(result, domain)) { result = ads_methods.query_user_list(domain, mem_ctx, rids); } @@ -58,7 +104,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, result = ads_methods.enum_dom_groups(domain, mem_ctx, num_entries, info); - if (reconnect_need_retry(result, domain)) { + if (ldap_reconnect_need_retry(result, domain)) { result = ads_methods.enum_dom_groups(domain, mem_ctx, num_entries, info); } @@ -77,7 +123,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, result = ads_methods.enum_local_groups(domain, mem_ctx, num_entries, info); - if (reconnect_need_retry(result, domain)) { + if (ldap_reconnect_need_retry(result, domain)) { result = ads_methods.enum_local_groups(domain, mem_ctx, num_entries, info); } @@ -165,7 +211,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, result = ads_methods.lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); - if (reconnect_need_retry(result, domain)) { + if (ldap_reconnect_need_retry(result, domain)) { result = ads_methods.lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); @@ -210,7 +256,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, num_names, sid_mem, names, name_types); - if (reconnect_need_retry(result, domain)) { + if (ldap_reconnect_need_retry(result, domain)) { result = ads_methods.lookup_groupmem(domain, mem_ctx, group_sid, type, num_names, sid_mem, names, name_types); @@ -226,7 +272,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq) result = ads_methods.sequence_number(domain, seq); - if (reconnect_need_retry(result, domain)) { + if (ldap_reconnect_need_retry(result, domain)) { result = ads_methods.sequence_number(domain, seq); } -- 2.13.6 From 66e18985c77b6daaa8da739da25476d1c6edfb9f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 11:12:34 +0100 Subject: [PATCH 05/15] winbindd: check for NT_STATUS_IO_DEVICE_ERROR in reset_cm_connection_on_error() reconnect_need_retry() already checks for this error, it surfaces up from tstream_smbXcli_np as a mapping for EIO. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit a33c1d25e0422483c903001dd246626f84c4cbc1) --- source3/winbindd/winbindd_dual_srv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 8449bf3dfd2..c9d3c41cbff 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -42,7 +42,9 @@ void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r) static bool reset_cm_connection_on_error(struct winbindd_domain *domain, NTSTATUS status) { - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) || + NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR)) + { invalidate_cm_connection(domain); /* We invalidated the connection. */ return true; -- 2.13.6 From 5b2f71341aed5ecc9769b3aaefeacc0cd74ee939 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 11:29:22 +0100 Subject: [PATCH 06/15] winbindd: make reset_cm_connection_on_error() public Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (backported from commit 17749a5d9fa08da1c61de45728656a2c9b85782d) --- source3/winbindd/winbindd_dual_srv.c | 4 ++-- source3/winbindd/winbindd_proto.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index c9d3c41cbff..e67f72ffdd7 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -39,8 +39,8 @@ void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r) *r->out.out_data = r->in.in_data; } -static bool reset_cm_connection_on_error(struct winbindd_domain *domain, - NTSTATUS status) +bool reset_cm_connection_on_error(struct winbindd_domain *domain, + NTSTATUS status) { if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) || NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR)) diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index f9841797166..1edca1fee58 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -970,4 +970,8 @@ NTSTATUS wb_irpc_register(void); /* The following definitions come from winbindd/winbindd_reconnect.c */ bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain); +/* The following comes from winbindd/winbindd_dual_srv.c */ +bool reset_cm_connection_on_error(struct winbindd_domain *domain, + NTSTATUS status); + #endif /* _WINBINDD_PROTO_H_ */ -- 2.13.6 From 94934fc3b0bb84d8ca3b941b783c824da66ad94a Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 12:20:04 +0100 Subject: [PATCH 07/15] winbindd: call reset_cm_connection_on_error() from reconnect_need_retry() This ensures we use the same disconnect logic in the reconnect backend, which calls reconnect_need_retry(), and in the dual_srv frontend which calls reset_cm_connection_on_error. Both reset_cm_connection_on_error() and reconnect_need_retry() are very similar, both return a bool indicating whether a retry should be attempted, unfortunately the functions have a different default return, so I don't dare unifying them, but instead just call one from the other. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 2837b796af3e491b6bb34bd441758ae214f629ee) --- source3/winbindd/winbindd_reconnect.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c index bbb5a37f390..aa7cd12e8b4 100644 --- a/source3/winbindd/winbindd_reconnect.c +++ b/source3/winbindd/winbindd_reconnect.c @@ -69,13 +69,7 @@ bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain) return false; } - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR)) { - /* - * RPC call sent on expired session, needs - * reauthentication. - */ - invalidate_cm_connection(domain); - } + reset_cm_connection_on_error(domain, status); return true; } -- 2.13.6 From 5d2e139ec893869b8c37227043de7cc7f3fa5146 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 13:39:59 +0100 Subject: [PATCH 08/15] winbindd: force netlogon reauth for certain errors in reset_cm_connection_on_error() NT_STATUS_RPC_SEC_PKG_ERROR is returned by the server if the server doesn't know the server-side netlogon credentials anymore, eg after a reboot. If this happens we must force a full netlogon reauth. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Volker Lendecke Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 2d1f00cc3ad77bed4e810dc910979e6cdf582216) --- source3/winbindd/winbindd_dual_srv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index e67f72ffdd7..b91d15ceb40 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -42,6 +42,14 @@ void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r) bool reset_cm_connection_on_error(struct winbindd_domain *domain, NTSTATUS status) { + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || + NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) || + NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { + invalidate_cm_connection(domain); + domain->conn.netlogon_force_reauth = true; + return true; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) || NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR)) { -- 2.13.6 From f61abde944224c3562829b273486bfef7186d972 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 16:11:37 +0100 Subject: [PATCH 09/15] winbindd: call dcerpc_binding_handle_is_connected() from reset_cm_connection_on_error() To consolidate the error handling for RPC calls, add the binding handle as an additional argument to reset_cm_connection_on_error(). All callers pass NULL for now, so no change in behaviour up to here. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 966ff3793a867a5ffe1a49e48c8ab3ecb02f8359) --- source3/winbindd/winbindd_dual_srv.c | 51 ++++++++++++++++++++--------------- source3/winbindd/winbindd_proto.h | 1 + source3/winbindd/winbindd_reconnect.c | 2 +- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index b91d15ceb40..cbac76f8fe6 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -40,6 +40,7 @@ void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r) } bool reset_cm_connection_on_error(struct winbindd_domain *domain, + struct dcerpc_binding_handle *b, NTSTATUS status) { if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || @@ -57,6 +58,12 @@ bool reset_cm_connection_on_error(struct winbindd_domain *domain, /* We invalidated the connection. */ return true; } + + if (b != NULL && !dcerpc_binding_handle_is_connected(b)) { + invalidate_cm_connection(domain); + return true; + } + return false; } @@ -74,7 +81,7 @@ NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r) status = wb_cache_sid_to_name(domain, p->mem_ctx, r->in.sid, &dom_name, &name, &type); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -108,7 +115,7 @@ NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r) r->out.domains = domains; } - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); return status; } @@ -124,7 +131,7 @@ NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r) status = wb_cache_name_to_sid(domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags, r->out.sid, r->out.type); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); return status; } @@ -312,7 +319,7 @@ NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p, r->in.sids->sids, &r->out.rids->num_rids, &r->out.rids->rids); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); return status; } @@ -329,7 +336,7 @@ NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p, status = wb_cache_lookup_usergroups(domain, p->mem_ctx, r->in.sid, &r->out.sids->num_sids, &r->out.sids->sids); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); return status; } @@ -344,7 +351,7 @@ NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p, } status = wb_cache_sequence_number(domain, r->out.sequence); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); return status; } @@ -365,7 +372,7 @@ NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p, status = wb_cache_lookup_groupmem(domain, p->mem_ctx, r->in.sid, r->in.type, &num_names, &sid_mem, &names, &name_types); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -429,7 +436,7 @@ NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p, status = wb_cache_enum_local_groups(domain, talloc_tos(), &num_local_groups, &local_groups); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -438,7 +445,7 @@ NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p, status = wb_cache_enum_dom_groups(domain, talloc_tos(), &num_dom_groups, &dom_groups); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -511,7 +518,7 @@ NTSTATUS _wbint_QueryUserRidList(struct pipes_struct *p, status = wb_cache_query_user_list(domain, p->mem_ctx, &r->out.rids->rids); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { return status; @@ -542,7 +549,7 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Can't contact the NETLOGON pipe\n")); return status; @@ -563,11 +570,11 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) { goto done; } - if (reset_cm_connection_on_error(domain, status)) { + if (reset_cm_connection_on_error(domain, NULL, status)) { /* Re-initialize. */ status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Can't contact the NETLOGON pipe\n")); return status; @@ -602,7 +609,7 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) r->in.domain_name, &dc_info->dc_unc, &werr); } - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n", nt_errstr(status))); @@ -642,7 +649,7 @@ NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r) status = wb_cache_rids_to_names(domain, talloc_tos(), r->in.domain_sid, r->in.rids->rids, r->in.rids->num_rids, &domain_name, &names, &types); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -780,7 +787,7 @@ NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r) reconnect: status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n", nt_errstr(status))); @@ -814,7 +821,7 @@ NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r) goto reconnect; } - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n", nt_errstr(status))); @@ -936,7 +943,7 @@ static WERROR _winbind_LogonControl_REDISCOVER(struct pipes_struct *p, invalidate_cm_connection(domain); domain->conn.netlogon_force_reauth = true; status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { status = NT_STATUS_NO_LOGON_SERVERS; } @@ -1005,7 +1012,7 @@ static WERROR _winbind_LogonControl_TC_QUERY(struct pipes_struct *p, } status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { status = NT_STATUS_NO_LOGON_SERVERS; } @@ -1184,7 +1191,7 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p, reconnect: status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { status = NT_STATUS_NO_LOGON_SERVERS; } @@ -1404,7 +1411,7 @@ static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p, reconnect: status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { status = NT_STATUS_NO_LOGON_SERVERS; } @@ -1609,7 +1616,7 @@ WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p, reconnect: status = cm_connect_netlogon(domain, &netlogon_pipe); - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { status = NT_STATUS_NO_LOGON_SERVERS; } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 1edca1fee58..25fae5fe939 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -972,6 +972,7 @@ bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain); /* The following comes from winbindd/winbindd_dual_srv.c */ bool reset_cm_connection_on_error(struct winbindd_domain *domain, + struct dcerpc_binding_handle *b, NTSTATUS status); #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c index aa7cd12e8b4..1d0e8e6d472 100644 --- a/source3/winbindd/winbindd_reconnect.c +++ b/source3/winbindd/winbindd_reconnect.c @@ -69,7 +69,7 @@ bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain) return false; } - reset_cm_connection_on_error(domain, status); + reset_cm_connection_on_error(domain, NULL, status); return true; } -- 2.13.6 From cd3299db1912a8125c36d787638ecec52e07d141 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 16:15:02 +0100 Subject: [PATCH 10/15] winbindd: fix logic calling dcerpc_binding_handle_is_connected() The calls were missing the negation operator, a retry should be attempted is the binding handle got somehow disconnected behind the scenes and is NOT connected. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 08718af36f3ed6cf2308beb3800abfb0414f94b9) --- source3/winbindd/winbindd_dual_srv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index cbac76f8fe6..510eb8ba0ca 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -1221,7 +1221,7 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p, status = NT_STATUS_OK; } if (!NT_STATUS_IS_OK(status)) { - if (!retry && dcerpc_binding_handle_is_connected(b)) { + if (!retry && !dcerpc_binding_handle_is_connected(b)) { invalidate_cm_connection(domain); retry = true; goto reconnect; @@ -1287,7 +1287,7 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p, goto verify_return; } if (!NT_STATUS_IS_OK(status)) { - if (!retry && dcerpc_binding_handle_is_connected(b)) { + if (!retry && !dcerpc_binding_handle_is_connected(b)) { invalidate_cm_connection(domain); retry = true; goto reconnect; @@ -1438,7 +1438,7 @@ static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p, domain->dcname, true); /* force */ if (!NT_STATUS_IS_OK(status)) { - if (!retry && dcerpc_binding_handle_is_connected(b)) { + if (!retry && !dcerpc_binding_handle_is_connected(b)) { invalidate_cm_connection(domain); retry = true; goto reconnect; @@ -1632,7 +1632,7 @@ WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p, b, p->mem_ctx, &new_fti); if (!NT_STATUS_IS_OK(status)) { - if (!retry && dcerpc_binding_handle_is_connected(b)) { + if (!retry && !dcerpc_binding_handle_is_connected(b)) { invalidate_cm_connection(domain); retry = true; goto reconnect; -- 2.13.6 From 823519ca08df42be793a13dd42cfea7ca3a378d5 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 16:53:49 +0100 Subject: [PATCH 11/15] winbindd: use reset_cm_connection_on_error() instead of dcerpc_binding_handle_is_connected() This catches more errors and triggers retry as appropriate. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 6244a2beb184de8d050389e304f087ef153d61dd) --- source3/winbindd/winbindd_dual_srv.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 510eb8ba0ca..29a91040898 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -813,15 +813,11 @@ NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r) logon_server, NETLOGON_CONTROL_QUERY, 2, &info, &werr); - if (!dcerpc_binding_handle_is_connected(b) && !retry) { - DEBUG(10, ("Session might have expired. " - "Reconnect and retry once.\n")); - invalidate_cm_connection(domain); + if (!retry && reset_cm_connection_on_error(domain, b, status)) { retry = true; goto reconnect; } - reset_cm_connection_on_error(domain, NULL, status); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n", nt_errstr(status))); @@ -1221,8 +1217,9 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p, status = NT_STATUS_OK; } if (!NT_STATUS_IS_OK(status)) { - if (!retry && !dcerpc_binding_handle_is_connected(b)) { - invalidate_cm_connection(domain); + if (!retry && + reset_cm_connection_on_error(domain, b, status)) + { retry = true; goto reconnect; } @@ -1287,8 +1284,7 @@ static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p, goto verify_return; } if (!NT_STATUS_IS_OK(status)) { - if (!retry && !dcerpc_binding_handle_is_connected(b)) { - invalidate_cm_connection(domain); + if (!retry && reset_cm_connection_on_error(domain, b, status)) { retry = true; goto reconnect; } @@ -1438,8 +1434,7 @@ static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p, domain->dcname, true); /* force */ if (!NT_STATUS_IS_OK(status)) { - if (!retry && !dcerpc_binding_handle_is_connected(b)) { - invalidate_cm_connection(domain); + if (!retry && reset_cm_connection_on_error(domain, b, status)) { retry = true; goto reconnect; } @@ -1632,8 +1627,7 @@ WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p, b, p->mem_ctx, &new_fti); if (!NT_STATUS_IS_OK(status)) { - if (!retry && !dcerpc_binding_handle_is_connected(b)) { - invalidate_cm_connection(domain); + if (!retry && reset_cm_connection_on_error(domain, b, status)) { retry = true; goto reconnect; } -- 2.13.6 From e685ff8c918aadfb48206df891dd7d46c8349f96 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 17:09:34 +0100 Subject: [PATCH 12/15] winbindd: add retry to _wbint_LookupSids() Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit c2cd2d3f3137e27cd6e4cabd34f27b49251f078d) --- source3/winbindd/winbindd_dual_srv.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 29a91040898..555bec47419 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -97,6 +97,7 @@ NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r) struct winbindd_domain *domain = wb_child_domain(); struct lsa_RefDomainList *domains = r->out.domains; NTSTATUS status; + bool retry = false; if (domain == NULL) { return NT_STATUS_REQUEST_NOT_ACCEPTED; @@ -108,6 +109,7 @@ NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r) * and winbindd_ad call into lsa_lookupsids anyway. Caching is * done at the wbint RPC layer. */ +again: status = rpc_lookup_sids(p->mem_ctx, domain, r->in.sids, &domains, &r->out.names); @@ -115,7 +117,11 @@ NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r) r->out.domains = domains; } - reset_cm_connection_on_error(domain, NULL, status); + if (!retry && reset_cm_connection_on_error(domain, NULL, status)) { + retry = true; + goto again; + } + return status; } -- 2.13.6 From 46b7738d356d84e023e492493c9e738da8027c5c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 19:53:26 +0100 Subject: [PATCH 13/15] winbindd: add retry to _wbint_DsGetDcName Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit fcf8edf9b8cdf5f3897c1a63ed97c302a231742f) --- source3/winbindd/winbindd_dual_srv.c | 37 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 555bec47419..9c5df024280 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -544,6 +544,8 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) WERROR werr; unsigned int orig_timeout; struct dcerpc_binding_handle *b; + bool retry = false; + bool try_dsrgetdcname = false; if (domain == NULL) { return dsgetdcname(p->mem_ctx, server_messaging_context(), @@ -553,6 +555,11 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) r->out.dc_info); } + if (domain->active_directory) { + try_dsrgetdcname = true; + } + +reconnect: status = cm_connect_netlogon(domain, &netlogon_pipe); reset_cm_connection_on_error(domain, NULL, status); @@ -568,7 +575,7 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000); - if (domain->active_directory) { + if (try_dsrgetdcname) { status = dcerpc_netr_DsRGetDCName(b, p->mem_ctx, domain->dcname, r->in.domain_name, NULL, r->in.domain_guid, @@ -576,23 +583,14 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) { goto done; } - if (reset_cm_connection_on_error(domain, NULL, status)) { - /* Re-initialize. */ - status = cm_connect_netlogon(domain, &netlogon_pipe); - - reset_cm_connection_on_error(domain, NULL, status); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("Can't contact the NETLOGON pipe\n")); - return status; - } - - b = netlogon_pipe->binding_handle; - - /* This call can take a long time - allow the server to time out. - 35 seconds should do it. */ - - orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000); + if (!retry && + reset_cm_connection_on_error(domain, NULL, status)) + { + retry = true; + goto reconnect; } + try_dsrgetdcname = false; + retry = false; } /* @@ -615,7 +613,10 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) r->in.domain_name, &dc_info->dc_unc, &werr); } - reset_cm_connection_on_error(domain, NULL, status); + if (!retry && reset_cm_connection_on_error(domain, b, status)) { + retry = true; + goto reconnect; + } if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n", nt_errstr(status))); -- 2.13.6 From 7b97a902736baaeaade958b5cc0a6ede912ee2b2 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 19:53:53 +0100 Subject: [PATCH 14/15] winbindd: add retry to _winbind_DsrUpdateReadOnlyServerDnsRecords Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (backported from commit e608f058b8f2d2295e24498daa35852de3212b23) --- source3/winbindd/winbindd_dual_srv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 9c5df024280..59730e3fa0d 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -848,24 +848,34 @@ NTSTATUS _winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p, struct winbindd_domain *domain; NTSTATUS status; struct rpc_pipe_client *netlogon_pipe; + struct dcerpc_binding_handle *b = NULL; + bool retry = false; domain = wb_child_domain(); if (domain == NULL) { return NT_STATUS_REQUEST_NOT_ACCEPTED; } +reconnect: status = cm_connect_netlogon(domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); goto done; } + b = netlogon_pipe->binding_handle; + status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(domain->conn.netlogon_creds, netlogon_pipe->binding_handle, r->in.site_name, r->in.dns_ttl, r->in.dns_names); + if (!retry && reset_cm_connection_on_error(domain, b, status)) { + retry = true; + goto reconnect; + } + /* Pass back result code - zero for success, other values for specific failures. */ -- 2.13.6 From b0f38f876bf850b0b929d349aa15a6c7c036c34f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 12 Mar 2018 19:54:37 +0100 Subject: [PATCH 15/15] winbindd: add retry to _winbind_SendToSam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: https://bugzilla.samba.org/show_bug.cgi?id=13332 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Thu Mar 15 20:57:44 CET 2018 on sn-devel-144 (backported from commit c37fbfcb248e5a8d6088a28eb0c1a62423f94502) --- source3/winbindd/winbindd_dual_srv.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 59730e3fa0d..8ed95c81a37 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -1738,6 +1738,8 @@ NTSTATUS _winbind_SendToSam(struct pipes_struct *p, struct winbind_SendToSam *r) struct winbindd_domain *domain; NTSTATUS status; struct rpc_pipe_client *netlogon_pipe; + struct dcerpc_binding_handle *b = NULL; + bool retry = false; DEBUG(5, ("_winbind_SendToSam received\n")); domain = wb_child_domain(); @@ -1745,15 +1747,22 @@ NTSTATUS _winbind_SendToSam(struct pipes_struct *p, struct winbind_SendToSam *r) return NT_STATUS_REQUEST_NOT_ACCEPTED; } +reconnect: status = cm_connect_netlogon(domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); return status; } + b = netlogon_pipe->binding_handle; + status = netlogon_creds_cli_SendToSam(domain->conn.netlogon_creds, netlogon_pipe->binding_handle, &r->in.message); + if (!retry && reset_cm_connection_on_error(domain, b, status)) { + retry = true; + goto reconnect; + } return status; } -- 2.13.6