Cygwin: s4uauth: allow to be called for identification only

s4uath was only callable to create an impersonation token so
far.  Rework the function to allow creating an identification
token for informational purposes even from untrusted processes.

Take domainname and username instead of a passwd pointer to be
more multi-purpose.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2019-02-22 18:27:38 +01:00
parent 82c2cf6abc
commit 105fbdebdd
4 changed files with 27 additions and 16 deletions

View File

@ -642,6 +642,7 @@ LoadDLLfunc (NetUserGetLocalGroups, 32, netapi32)
LoadDLLfunc (CoTaskMemFree, 4, ole32) LoadDLLfunc (CoTaskMemFree, 4, ole32)
LoadDLLfunc (LsaConnectUntrusted, 4, secur32)
LoadDLLfunc (LsaDeregisterLogonProcess, 4, secur32) LoadDLLfunc (LsaDeregisterLogonProcess, 4, secur32)
LoadDLLfunc (LsaFreeReturnBuffer, 4, secur32) LoadDLLfunc (LsaFreeReturnBuffer, 4, secur32)
LoadDLLfunc (LsaLogonUser, 56, secur32) LoadDLLfunc (LsaLogonUser, 56, secur32)

View File

@ -22,7 +22,6 @@ details. */
#include "tls_pbuf.h" #include "tls_pbuf.h"
#include <lm.h> #include <lm.h>
#include <iptypes.h> #include <iptypes.h>
#include <wininet.h>
#include <userenv.h> #include <userenv.h>
#define SECURITY_WIN32 #define SECURITY_WIN32
#include <secext.h> #include <secext.h>
@ -1421,7 +1420,7 @@ out:
*/ */
/* In Mingw-w64, MsV1_0S4ULogon and MSV1_0_S4U_LOGON are only defined /* In Mingw-w64, MsV1_0S4ULogon and MSV1_0_S4U_LOGON are only defined
in ddk/ntifs.h. We can't inlcude this. */ in ddk/ntifs.h. We can't include this. */
#define MsV1_0S4ULogon ((MSV1_0_LOGON_SUBMIT_TYPE) 12) #define MsV1_0S4ULogon ((MSV1_0_LOGON_SUBMIT_TYPE) 12)
@ -1433,15 +1432,18 @@ typedef struct _MSV1_0_S4U_LOGON
UNICODE_STRING DomainName; UNICODE_STRING DomainName;
} MSV1_0_S4U_LOGON, *PMSV1_0_S4U_LOGON; } MSV1_0_S4U_LOGON, *PMSV1_0_S4U_LOGON;
/* Missing in Mingw-w64 */
#define KERB_S4U_LOGON_FLAG_IDENTITY 0x08
/* If logon is true we need an impersonation token. Otherwise we just
need an identification token, e. g. to fetch the group list. */
HANDLE HANDLE
s4uauth (struct passwd *pw, NTSTATUS &ret_status) s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status)
{ {
LSA_STRING name; LSA_STRING name;
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;
WCHAR domain[MAX_DOMAIN_NAME_LEN + 1];
WCHAR user[UNLEN + 1];
bool try_kerb_auth; bool try_kerb_auth;
ULONG package_id, size; ULONG package_id, size;
struct { struct {
@ -1460,19 +1462,23 @@ s4uauth (struct passwd *pw, NTSTATUS &ret_status)
push_self_privilege (SE_TCB_PRIVILEGE, true); push_self_privilege (SE_TCB_PRIVILEGE, true);
/* Register as logon process. */ if (logon)
RtlInitAnsiString (&name, "Cygwin"); {
status = LsaRegisterLogonProcess (&name, &lsa_hdl, &sec_mode); /* Register as logon process. */
RtlInitAnsiString (&name, "Cygwin");
status = LsaRegisterLogonProcess (&name, &lsa_hdl, &sec_mode);
}
else
status = LsaConnectUntrusted (&lsa_hdl);
if (status != STATUS_SUCCESS) if (status != STATUS_SUCCESS)
{ {
debug_printf ("LsaRegisterLogonProcess: %y", status); debug_printf ("%s: %y", logon ? "LsaRegisterLogonProcess"
: "LsaConnectUntrusted", status);
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto out; goto out;
} }
/* Fetch user and domain name and check if this is a domain user. /* Check if this is a domain user. If so, try Kerberos first. */
If so, try Kerberos first. */
extract_nt_dom_user (pw, domain, user);
try_kerb_auth = cygheap->dom.member_machine () try_kerb_auth = cygheap->dom.member_machine ()
&& wcscasecmp (domain, cygheap->dom.account_flat_name ()); && wcscasecmp (domain, cygheap->dom.account_flat_name ());
/* Create origin. */ /* Create origin. */
@ -1523,7 +1529,7 @@ s4uauth (struct passwd *pw, NTSTATUS &ret_status)
RtlSecureZeroMemory (authinf, authinf_size); RtlSecureZeroMemory (authinf, authinf_size);
s4u_logon = (KERB_S4U_LOGON *) authinf; s4u_logon = (KERB_S4U_LOGON *) authinf;
s4u_logon->MessageType = KerbS4ULogon; s4u_logon->MessageType = KerbS4ULogon;
s4u_logon->Flags = 0; s4u_logon->Flags = logon ? 0 : KERB_S4U_LOGON_FLAG_IDENTITY;
/* Append user to login info */ /* Append user to login info */
RtlInitEmptyUnicodeString (&s4u_logon->ClientUpn, RtlInitEmptyUnicodeString (&s4u_logon->ClientUpn,
(PWCHAR) (s4u_logon + 1), (PWCHAR) (s4u_logon + 1),
@ -1615,7 +1621,7 @@ out:
if (profile) if (profile)
LsaFreeReturnBuffer (profile); LsaFreeReturnBuffer (profile);
if (token) if (token && logon)
{ {
/* Convert to primary token. Strictly speaking this is only /* Convert to primary token. Strictly speaking this is only
required on Vista/2008. CreateProcessAsUser also takes required on Vista/2008. CreateProcessAsUser also takes

View File

@ -480,7 +480,7 @@ HANDLE lsaauth (cygsid &, user_groups &);
/* LSA private key storage authentication, same as when using service logons. */ /* LSA private key storage authentication, same as when using service logons. */
HANDLE lsaprivkeyauth (struct passwd *pw); HANDLE lsaprivkeyauth (struct passwd *pw);
/* Kerberos or MsV1 S4U logon. */ /* Kerberos or MsV1 S4U logon. */
HANDLE s4uauth (struct passwd *pw, NTSTATUS &ret_status); HANDLE s4uauth (bool logon, PCWSTR domain, PCWSTR user, NTSTATUS &ret_status);
/* Verify an existing token */ /* Verify an existing token */
bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL); bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL);
/* Get groups of a user */ /* Get groups of a user */

View File

@ -37,6 +37,7 @@ details. */
#include <sys/wait.h> #include <sys/wait.h>
#include <dirent.h> #include <dirent.h>
#include <ntsecapi.h> #include <ntsecapi.h>
#include <iptypes.h>
#include "ntdll.h" #include "ntdll.h"
#undef fstat #undef fstat
@ -3565,9 +3566,12 @@ seteuid32 (uid_t uid)
if (!new_token) if (!new_token)
{ {
NTSTATUS status; NTSTATUS status;
WCHAR domain[MAX_DOMAIN_NAME_LEN + 1];
WCHAR user[UNLEN + 1];
debug_printf ("lsaprivkeyauth failed, try s4uauth."); debug_printf ("lsaprivkeyauth failed, try s4uauth.");
if (!(new_token = s4uauth (pw_new, status))) extract_nt_dom_user (pw_new, domain, user);
if (!(new_token = s4uauth (true, domain, user, status)))
{ {
if (status != STATUS_INVALID_PARAMETER) if (status != STATUS_INVALID_PARAMETER)
{ {