From 672488bdd19fe67ccc8df71e59dda05fe0a83cf9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Aug 2021 14:17:47 +0200 Subject: [PATCH] winbindd_pam: add NT4 DC handling into winbind_samlogon_retry_loop() Handle the case where a NT4 DC does not fill in the acct_flags in the samlogon reply info3. Yes, in 2021, there are still admins arround with real NT4 DCs. NT4 DCs reject authentication with workstation accounts with NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, even if MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT is specified. We no longer call dcerpc_samr_QueryUserInfo(level=16) to get the acct_flags, as we only ever got ACB_NORMAL back (maybe with ACB_PWNOEXP in addition), which is easy to calculate on our own. This was removed in commit (for 4.15.0rc1): commit 73528f26eea24033a7093e5591b8f89ad2b8644e Author: Ralph Boehme AuthorDate: Mon Jan 11 14:59:46 2021 +0100 Commit: Jeremy Allison CommitDate: Thu Jan 21 22:56:20 2021 +0000 winbind: remove legacy flags fallback Some very old NT4 DCs might have not returned the account flags filled in. This shouldn't be a problem anymore. Additionally, on a typical domain member server, this request is (and can only be) send to the primary domain, so this will not work with accounts from trusted domains. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Thu Jan 21 22:56:20 UTC 2021 on sn-devel-184 It means one more caller of the problematic cm_connect_sam() function is removed! SAMR connections may not be allowed for machine accounts with modern AD DCs. For network logons NT4 DCs also skip the account_name, so we have to fallback to the one given by the client. We have code to cope with that deeply hidden inside of netsamlogon_cache_store(). Up to Samba 4.7 netsamlogon_cache_store() operated on the info3 structure that was passed to the caller of winbind_dual_SamLogon() and pass propagated up to auth_winbind in smbd. But for Samba 4.8 the following commit: commit f153c95176b7759e10996b24b66d9917945372ed Author: Ralph Boehme Date: Mon Dec 11 16:25:35 2017 +0100 winbindd: let winbind_dual_SamLogon return validation Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher actually changed the situation and only a temporary info3 structure was passed into netsamlogon_cache_store(), which means account_name was NULL and get propagated as "" into auth_winbind in smbd, where getpwnam() is no longer possible and every smb access gets NT_STATUS_LOGON_FAILURE. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14772 Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_pam.c | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 14b4ec1c2bea..fc194b8b8b41 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1475,6 +1475,8 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, enum netr_LogonInfoClass logon_type_n; uint16_t validation_level = UINT16_MAX; union netr_Validation *validation = NULL; + TALLOC_CTX *base_ctx = NULL; + struct netr_SamBaseInfo *base_info = NULL; do { struct rpc_pipe_client *netlogon_pipe; @@ -1718,6 +1720,69 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, return result; } + switch (validation_level) { + case 3: + base_ctx = validation->sam3; + base_info = &validation->sam3->base; + break; + case 6: + base_ctx = validation->sam6; + base_info = &validation->sam6->base; + break; + default: + smb_panic(__location__); + } + + if (base_info->acct_flags == 0 || base_info->account_name.string == NULL) { + struct dom_sid user_sid; + struct dom_sid_buf sid_buf; + const char *acct_flags_src = "server"; + const char *acct_name_src = "server"; + + /* + * Handle the case where a NT4 DC does not fill in the acct_flags in + * the samlogon reply info3. Yes, in 2021, there are still admins + * arround with real NT4 DCs. + * + * We used to call dcerpc_samr_QueryUserInfo(level=16) to fetch + * acct_flags, but as NT4 DCs reject authentication with workstation + * accounts with NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, even if + * MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT is specified, we only ever got + * ACB_NORMAL back (maybe with ACB_PWNOEXP in addition). + * + * For network logons NT4 DCs also skip the + * account_name, so we have to fallback to the + * one given by the client. + */ + + if (base_info->acct_flags == 0) { + base_info->acct_flags = ACB_NORMAL; + if (base_info->force_password_change == INT64_MAX) { + base_info->acct_flags |= ACB_PWNOEXP; + } + acct_flags_src = "calculated"; + } + + if (base_info->account_name.string == NULL) { + base_info->account_name.string = talloc_strdup(base_ctx, + username); + if (base_info->account_name.string == NULL) { + TALLOC_FREE(validation); + return NT_STATUS_NO_MEMORY; + } + acct_name_src = "client"; + } + + sid_compose(&user_sid, base_info->domain_sid, base_info->rid); + + DBG_DEBUG("Fallback to %s_acct_flags[0x%x] %s_acct_name[%s] for %s\n", + acct_flags_src, + base_info->acct_flags, + acct_name_src, + base_info->account_name.string, + dom_sid_str_buf(&user_sid, &sid_buf)); + } + *_validation_level = validation_level; *_validation = validation; return NT_STATUS_OK; -- 2.25.1