Cygwin: s4uauth: drop fallback to MsV1_0 if Kerberos fails

This never really worked.  While at it, restructure code to
do common stuff only in one spot.  Improve debug output.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2019-03-01 16:04:51 +01:00
parent 379598dd67
commit f18a161cff
1 changed files with 77 additions and 91 deletions

View File

@ -1509,7 +1509,7 @@ s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status)
HANDLE lsa_hdl = NULL; HANDLE lsa_hdl = NULL;
LSA_OPERATIONAL_MODE sec_mode; LSA_OPERATIONAL_MODE sec_mode;
NTSTATUS status, sub_status; NTSTATUS status, sub_status;
bool try_kerb_auth; bool kerberos_auth;
ULONG package_id, size; ULONG package_id, size;
struct { struct {
LSA_STRING str; LSA_STRING str;
@ -1530,11 +1530,16 @@ s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status)
if (logon) if (logon)
{ {
/* Register as logon process. */ /* Register as logon process. */
debug_printf ("Impersonation requested");
RtlInitAnsiString (&name, "Cygwin"); RtlInitAnsiString (&name, "Cygwin");
status = LsaRegisterLogonProcess (&name, &lsa_hdl, &sec_mode); status = LsaRegisterLogonProcess (&name, &lsa_hdl, &sec_mode);
} }
else else
{
/* Connect untrusted to just create a identification token */
debug_printf ("Identification requested");
status = LsaConnectUntrusted (&lsa_hdl); status = LsaConnectUntrusted (&lsa_hdl);
}
if (status != STATUS_SUCCESS) if (status != STATUS_SUCCESS)
{ {
debug_printf ("%s: %y", logon ? "LsaRegisterLogonProcess" debug_printf ("%s: %y", logon ? "LsaRegisterLogonProcess"
@ -1543,22 +1548,16 @@ s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status)
goto out; goto out;
} }
/* Check if this is a domain user. If so, try Kerberos first. */ /* Check if this is a domain user. If so, use Kerberos. */
try_kerb_auth = cygheap->dom.member_machine () kerberos_auth = cygheap->dom.member_machine ()
&& wcscasecmp (domain, cygheap->dom.account_flat_name ()); && wcscasecmp (domain, cygheap->dom.account_flat_name ());
/* Create origin. */ debug_printf ("kerb %d, domain member %d, user domain <%W>, machine <%W>",
stpcpy (origin.buf, "Cygwin"); kerberos_auth, cygheap->dom.member_machine (), domain,
RtlInitAnsiString (&origin.str, origin.buf); cygheap->dom.account_flat_name ());
if (try_kerb_auth) /* Connect to authentication package. */
{ RtlInitAnsiString (&name, kerberos_auth ? MICROSOFT_KERBEROS_NAME_A
PWCHAR sam_name = tp.w_get (); : MSV1_0_PACKAGE_NAME);
PWCHAR upn_name = tp.w_get ();
size = NT_MAX_PATH;
KERB_S4U_LOGON *s4u_logon;
USHORT name_len;
RtlInitAnsiString (&name, MICROSOFT_KERBEROS_NAME_A);
status = LsaLookupAuthenticationPackage (lsa_hdl, &name, &package_id); status = LsaLookupAuthenticationPackage (lsa_hdl, &name, &package_id);
if (status != STATUS_SUCCESS) if (status != STATUS_SUCCESS)
{ {
@ -1566,6 +1565,24 @@ s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status)
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto out; goto out;
} }
/* Create origin. */
stpcpy (origin.buf, "Cygwin");
RtlInitAnsiString (&origin.str, origin.buf);
/* Create token source. */
memcpy (ts.SourceName, "Cygwin.1", 8);
ts.SourceIdentifier.HighPart = 0;
ts.SourceIdentifier.LowPart = kerberos_auth ? 0x0105 : 0x0106;
if (kerberos_auth)
{
PWCHAR sam_name = tp.w_get ();
PWCHAR upn_name = tp.w_get ();
size = NT_MAX_PATH;
KERB_S4U_LOGON *s4u_logon;
USHORT name_len;
wcpcpy (wcpcpy (wcpcpy (sam_name, domain), L"\\"), user); wcpcpy (wcpcpy (wcpcpy (sam_name, domain), L"\\"), user);
if (TranslateNameW (sam_name, NameSamCompatible, NameUserPrincipal, if (TranslateNameW (sam_name, NameSamCompatible, NameUserPrincipal,
upn_name, &size) == 0) upn_name, &size) == 0)
@ -1579,8 +1596,7 @@ s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status)
translated_name, &size) == 0) translated_name, &size) == 0)
{ {
debug_printf ("TranslateNameW(%W, NameCanonical) %E", sam_name); debug_printf ("TranslateNameW(%W, NameCanonical) %E", sam_name);
debug_printf ("Fallback to MsV1_0 auth"); goto out;
goto msv1_0_auth; /* Fall through to MSV1_0 authentication */
} }
p = wcschr (translated_name, L'/'); p = wcschr (translated_name, L'/');
if (p) if (p)
@ -1600,49 +1616,15 @@ s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status)
(PWCHAR) (s4u_logon + 1), (PWCHAR) (s4u_logon + 1),
name_len); name_len);
RtlAppendUnicodeToString (&s4u_logon->ClientUpn, upn_name); RtlAppendUnicodeToString (&s4u_logon->ClientUpn, upn_name);
debug_printf ("ClientUpn: <%S>", &s4u_logon->ClientUpn); debug_printf ("KerbS4ULogon: ClientUpn: <%S>", &s4u_logon->ClientUpn);
/* Create token source. */ }
memcpy (ts.SourceName, "Cygwin.1", 8); else
ts.SourceIdentifier.HighPart = 0;
ts.SourceIdentifier.LowPart = 0x0105;
status = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network,
package_id, authinf, authinf_size, NULL,
&ts, (PVOID *) &profile, &size,
&luid, &token, &quota, &sub_status);
switch (status)
{ {
case STATUS_SUCCESS: /* Per MSDN MsV1_0S4ULogon is not implemented on Vista, but surprisingly
goto out; it works. */
/* These failures are fatal */
case STATUS_QUOTA_EXCEEDED:
case STATUS_LOGON_FAILURE:
debug_printf ("Kerberos S4U LsaLogonUser failed: %y", status);
goto out;
case STATUS_ACCOUNT_RESTRICTION:
debug_printf ("Kerberos S4U LsaLogonUser failed: %y (%s)",
status, account_restriction (sub_status));
goto out;
default:
break;
}
debug_printf ("Kerberos S4U LsaLogonUser failed: %y, try MsV1_0", status);
/* Fall through to MSV1_0 authentication */
}
msv1_0_auth:
MSV1_0_S4U_LOGON *s4u_logon; MSV1_0_S4U_LOGON *s4u_logon;
USHORT user_len, domain_len; USHORT user_len, domain_len;
/* Per MSDN MsV1_0S4ULogon is not implemented on Vista, but surprisingly
it works. */
RtlInitAnsiString (&name, MSV1_0_PACKAGE_NAME);
status = LsaLookupAuthenticationPackage (lsa_hdl, &name, &package_id);
if (status != STATUS_SUCCESS)
{
debug_printf ("LsaLookupAuthenticationPackage: %y", status);
__seterrno_from_nt_status (status);
goto out;
}
user_len = wcslen (user) * sizeof (WCHAR); user_len = wcslen (user) * sizeof (WCHAR);
domain_len = wcslen (domain) * sizeof (WCHAR); /* Local machine */ domain_len = wcslen (domain) * sizeof (WCHAR); /* Local machine */
authinf_size = sizeof (MSV1_0_S4U_LOGON) + user_len + domain_len; authinf_size = sizeof (MSV1_0_S4U_LOGON) + user_len + domain_len;
@ -1661,23 +1643,27 @@ msv1_0_auth:
domain_len); domain_len);
RtlAppendUnicodeToString (&s4u_logon->UserPrincipalName, user); RtlAppendUnicodeToString (&s4u_logon->UserPrincipalName, user);
RtlAppendUnicodeToString (&s4u_logon->DomainName, domain); RtlAppendUnicodeToString (&s4u_logon->DomainName, domain);
debug_printf ("DomainName: <%S> UserPrincipalName: <%S>", debug_printf ("MsV1_0S4ULogon: DomainName: <%S> UserPrincipalName: <%S>",
&s4u_logon->DomainName, &s4u_logon->UserPrincipalName); &s4u_logon->DomainName, &s4u_logon->UserPrincipalName);
/* Create token source. */ }
memcpy (ts.SourceName, "Cygwin.1", 8);
ts.SourceIdentifier.HighPart = 0; /* Try to logon. */
ts.SourceIdentifier.LowPart = 0x0106; status = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network, package_id,
if ((status = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network, authinf, authinf_size, NULL, &ts, (PVOID *) &profile,
package_id, authinf, authinf_size, NULL, &size, &luid, &token, &quota, &sub_status);
&ts, (PVOID *) &profile, &size, switch (status)
&luid, &token, &quota, &sub_status))
!= STATUS_SUCCESS)
{ {
if (status == STATUS_ACCOUNT_RESTRICTION) case STATUS_SUCCESS:
debug_printf ("MSV1_0 S4U LsaLogonUser failed: %y (%s)", break;
status, account_restriction (sub_status)); case STATUS_ACCOUNT_RESTRICTION:
else debug_printf ("%s S4U LsaLogonUser failed: %y (%s)",
debug_printf ("MSV1_0 S4U LsaLogonUser failed: %y", status); kerberos_auth ? "Kerberos" : "MsV1_0", status,
account_restriction (sub_status));
break;
default:
debug_printf ("%s S4U LsaLogonUser failed: %y",
kerberos_auth ? "Kerberos" : "MsV1_0", status);
break;
} }
out: out: