]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
winbindd: blacklist servers returning ACCESS_DENIED/authoritative=0
authorStefan Metzmacher <metze@samba.org>
Wed, 16 Feb 2022 13:23:16 +0000 (14:23 +0100)
committerJule Anger <janger@samba.org>
Wed, 6 Aug 2025 08:08:10 +0000 (08:08 +0000)
https://bugzilla.samba.org/show_bug.cgi?id=14981

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
(cherry picked from commit ce80451f3af4418d1c83be009b58b3824c071cae)

source3/winbindd/winbindd_pam.c

index 8d68ed198e3fc6435998e825167fe1207c019175..406dd37c6719a53db4ac4df6342e588aefb56521 100644 (file)
@@ -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