From: Stefan Metzmacher Date: Wed, 16 Feb 2022 13:23:16 +0000 (+0100) Subject: winbindd: blacklist servers returning ACCESS_DENIED/authoritative=0 X-Git-Tag: samba-4.22.4~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=04c938d82b7c772529816f47240310fd7f769798;p=thirdparty%2Fsamba.git winbindd: blacklist servers returning ACCESS_DENIED/authoritative=0 https://bugzilla.samba.org/show_bug.cgi?id=14981 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme Reviewed-by: Guenther Deschner (cherry picked from commit ce80451f3af4418d1c83be009b58b3824c071cae) --- diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 8d68ed198e3..406dd37c671 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1641,6 +1641,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, { int attempts = 0; int netr_attempts = 0; + int invalid_servers = 0; bool retry = false; bool valid_result = false; NTSTATUS result; @@ -1801,6 +1802,98 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, &validation); } + /* + * MS-NRPC 3.5.4.5.1 NetrLogonSamLogonEx (Opnum 39) says: + * ... + * + * Authoritative: ... + * This Boolean value indicates whether the validation + * information is final. This field is necessary because + * the request might be forwarded through multiple servers. + * + * The value TRUE indicates that the validation information + * is an authoritative response and MUST remain unchanged. + * + * The value FALSE indicates that the validation information + * is not an authoritative response and that the client can + * resend the request to another server. + * + * ... + * If the server cannot service the request due to an + * implementation-specific condition, the server + * returns STATUS_ACCESS_DENIED. + * ... + * + * One reason for this is that SysvolReady is still 0 in + * HKLM\\SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters + * It means there are problems with sysvol replication. + * + * The response looks like this: + * + * netr_LogonSamLogonEx: struct netr_LogonSamLogonEx + * out: struct netr_LogonSamLogonEx + * validation : * + * validation : union netr_Validation(case 6) + * sam6 : NULL + * authoritative : * + * authoritative : 0x00 (0) + * flags : * + * flags : 0x00000000 (0) + * 0: NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT + * 0: NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP + * 0: NETLOGON_SAMLOGON_FLAG_RODC_TO_OTHER_DOMAIN + * 0: NETLOGON_SAMLOGON_FLAG_RODC_NTLM_REQUEST + * result : NT_STATUS_ACCESS_DENIED + * + * In that case we'll mark the dc as broken and retry. + * In order to prevent a fallback to a local user due to + * authoritative=0, we reset authoritative=1 and continue + * with NT_STATUS_NETLOGON_NOT_STARTED. + * + * In the end we may result in NT_STATUS_NO_LOGON_SERVERS + * if we never reach 'valid_result = true'. + * This matches what windows does. In a chain of transitive + * trusts the ACCESS_DENIED/authoritative=0 is not propagated + * instead of NT_STATUS_NO_LOGON_SERVERS/authoritative=1 is + * passed along the chain if there's no other DC is available. + */ + if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && + *authoritative == 0) + { + reset_cm_connection_on_error( + domain, + netlogon_pipe->binding_handle, + result); + + *authoritative = true; + result = NT_STATUS_NETLOGON_NOT_STARTED; + DBG_WARNING("sam_logon[%s\\%s] returned ACCESS_DENIED " + "authoritative=0.\n" + "The DC may have set SysvolReady=0 in " + "HKLM\\SYSTEM\\CurrentControlSet\\Services" + "\\Netlogon\\Parameters\n" + "%s: Adding DC to the negative cache list: " + "%s %s\n", + domainname, + username, + nt_errstr(result), + domain->name, + domain->dcname); + + winbind_add_failed_connection_entry(domain, + domain->dcname, + result); + + /* Only allow 3 retries */ + if (invalid_servers < 3) { + DBG_NOTICE("Retry another server\n"); + invalid_servers++; + retry = true; + continue; + } + break; + } + /* * we increment this after the "feature negotiation" * for can_do_samlogon_ex and can_do_validation6