* autoload.cc: Add LoadDLLinitfunc for secur32.dll.
Add LoadDLLfuncEx statements for AllocateLocallyUniqueId@4, DuplicateTokenEx@24, LsaNtStatusToWinError@4, LsaDeregisterLogonProcess@4, LsaFreeReturnBuffer@4, LsaLogonUser@56, LsaLookupAuthenticationPackage@12, LsaRegisterLogonProcess@12, * environ.cc: Add extern declaration for `subauth_id'. (subauth_id_init): New function for setting `subauth_id'. (struct parse_thing): Add entry for `subauth_id'. * fork.cc (fork_parent): Call `RevertToSelf' and `ImpersonateLoggedOnUser' instead of `seteuid'. * security.cc: Define global variable `subauth_id'. (extract_nt_dom_user): New function. (cygwin_logon_user): Call `extract_nt_dom_user' now. (str2lsa): New static function. (str2buf2lsa): Ditto. (str2buf2uni): Ditto. (subauth): Ditto. * security.h: Add prototype for `subauth'. * spawn.cc (spawn_guts): Use cygheap->user.token only if impersonated. Use `cygsid' type. Remove impersonation before allowing access to workstation/desktop to everyone. Call `RevertToSelf' and `ImpersonateLoggedOnUser' instead of `seteuid'. * syscalls.cc (seteuid): Rearranged to allow using subauthentication to retrieve user tokens when needed.
This commit is contained in:
parent
965cecdfca
commit
57ff940dd4
@ -1,3 +1,31 @@
|
|||||||
|
Mon Apr 30 22:09:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* autoload.cc: Add LoadDLLinitfunc for secur32.dll.
|
||||||
|
Add LoadDLLfuncEx statements for AllocateLocallyUniqueId@4,
|
||||||
|
DuplicateTokenEx@24, LsaNtStatusToWinError@4,
|
||||||
|
LsaDeregisterLogonProcess@4, LsaFreeReturnBuffer@4,
|
||||||
|
LsaLogonUser@56, LsaLookupAuthenticationPackage@12,
|
||||||
|
LsaRegisterLogonProcess@12,
|
||||||
|
* environ.cc: Add extern declaration for `subauth_id'.
|
||||||
|
(subauth_id_init): New function for setting `subauth_id'.
|
||||||
|
(struct parse_thing): Add entry for `subauth_id'.
|
||||||
|
* fork.cc (fork_parent): Call `RevertToSelf' and
|
||||||
|
`ImpersonateLoggedOnUser' instead of `seteuid'.
|
||||||
|
* security.cc: Define global variable `subauth_id'.
|
||||||
|
(extract_nt_dom_user): New function.
|
||||||
|
(cygwin_logon_user): Call `extract_nt_dom_user' now.
|
||||||
|
(str2lsa): New static function.
|
||||||
|
(str2buf2lsa): Ditto.
|
||||||
|
(str2buf2uni): Ditto.
|
||||||
|
(subauth): Ditto.
|
||||||
|
* security.h: Add prototype for `subauth'.
|
||||||
|
* spawn.cc (spawn_guts): Use cygheap->user.token only if impersonated.
|
||||||
|
Use `cygsid' type. Remove impersonation before allowing access to
|
||||||
|
workstation/desktop to everyone. Call `RevertToSelf' and
|
||||||
|
`ImpersonateLoggedOnUser' instead of `seteuid'.
|
||||||
|
* syscalls.cc (seteuid): Rearranged to allow using subauthentication
|
||||||
|
to retrieve user tokens when needed.
|
||||||
|
|
||||||
Mon Apr 30 20:26:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
Mon Apr 30 20:26:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* uinfo.cc (internal_getlogin): Formatting change.
|
* uinfo.cc (internal_getlogin): Formatting change.
|
||||||
|
@ -129,6 +129,28 @@ LoadDLLinitfunc (ntdll)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadDLLinitfunc (secur32)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
static NO_COPY LONG here = -1L;
|
||||||
|
|
||||||
|
while (InterlockedIncrement (&here))
|
||||||
|
{
|
||||||
|
InterlockedDecrement (&here);
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secur32_handle)
|
||||||
|
/* nothing to do */;
|
||||||
|
else if ((h = LoadLibrary ("secur32.dll")) != NULL)
|
||||||
|
secur32_handle = h;
|
||||||
|
else if (!secur32_handle)
|
||||||
|
api_fatal ("could not load secur32.dll, %E");
|
||||||
|
|
||||||
|
InterlockedDecrement (&here);
|
||||||
|
return 0; /* Already done by another thread? */
|
||||||
|
}
|
||||||
|
|
||||||
LoadDLLinitfunc (user32)
|
LoadDLLinitfunc (user32)
|
||||||
{
|
{
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
@ -271,12 +293,14 @@ LoadDLLfunc (AddAccessAllowedAce, 16, advapi32)
|
|||||||
LoadDLLfunc (AddAccessDeniedAce, 16, advapi32)
|
LoadDLLfunc (AddAccessDeniedAce, 16, advapi32)
|
||||||
LoadDLLfunc (AddAce, 20, advapi32)
|
LoadDLLfunc (AddAce, 20, advapi32)
|
||||||
LoadDLLfunc (AdjustTokenPrivileges, 24, advapi32)
|
LoadDLLfunc (AdjustTokenPrivileges, 24, advapi32)
|
||||||
|
LoadDLLfuncEx (AllocateLocallyUniqueId, 4, advapi32, 1)
|
||||||
LoadDLLfunc (CopySid, 12, advapi32)
|
LoadDLLfunc (CopySid, 12, advapi32)
|
||||||
LoadDLLfunc (CreateProcessAsUserA, 44, advapi32)
|
LoadDLLfunc (CreateProcessAsUserA, 44, advapi32)
|
||||||
LoadDLLfuncEx (CryptAcquireContextA, 20, advapi32, 1)
|
LoadDLLfuncEx (CryptAcquireContextA, 20, advapi32, 1)
|
||||||
LoadDLLfuncEx (CryptGenRandom, 12, advapi32, 1)
|
LoadDLLfuncEx (CryptGenRandom, 12, advapi32, 1)
|
||||||
LoadDLLfuncEx (CryptReleaseContext, 8, advapi32, 1)
|
LoadDLLfuncEx (CryptReleaseContext, 8, advapi32, 1)
|
||||||
LoadDLLfunc (DeregisterEventSource, 4, advapi32)
|
LoadDLLfunc (DeregisterEventSource, 4, advapi32)
|
||||||
|
LoadDLLfuncEx (DuplicateTokenEx, 24, advapi32, 1)
|
||||||
LoadDLLfunc (EqualSid, 8, advapi32)
|
LoadDLLfunc (EqualSid, 8, advapi32)
|
||||||
LoadDLLfunc (GetAce, 12, advapi32)
|
LoadDLLfunc (GetAce, 12, advapi32)
|
||||||
LoadDLLfunc (GetFileSecurityA, 20, advapi32)
|
LoadDLLfunc (GetFileSecurityA, 20, advapi32)
|
||||||
@ -298,6 +322,7 @@ LoadDLLfunc (LogonUserA, 24, advapi32)
|
|||||||
LoadDLLfunc (LookupAccountNameA, 28, advapi32)
|
LoadDLLfunc (LookupAccountNameA, 28, advapi32)
|
||||||
LoadDLLfunc (LookupAccountSidA, 28, advapi32)
|
LoadDLLfunc (LookupAccountSidA, 28, advapi32)
|
||||||
LoadDLLfunc (LookupPrivilegeValueA, 12, advapi32)
|
LoadDLLfunc (LookupPrivilegeValueA, 12, advapi32)
|
||||||
|
LoadDLLfuncEx (LsaNtStatusToWinError, 4, advapi32, 1)
|
||||||
LoadDLLfunc (MakeSelfRelativeSD, 12, advapi32)
|
LoadDLLfunc (MakeSelfRelativeSD, 12, advapi32)
|
||||||
LoadDLLfunc (OpenProcessToken, 12, advapi32)
|
LoadDLLfunc (OpenProcessToken, 12, advapi32)
|
||||||
LoadDLLfunc (RegCloseKey, 4, advapi32)
|
LoadDLLfunc (RegCloseKey, 4, advapi32)
|
||||||
@ -334,6 +359,13 @@ LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
|
|||||||
LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
|
LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
|
||||||
LoadDLLfuncEx (ZwQuerySystemInformation, 16, ntdll, 1)
|
LoadDLLfuncEx (ZwQuerySystemInformation, 16, ntdll, 1)
|
||||||
|
|
||||||
|
LoadDLLinit (secur32)
|
||||||
|
LoadDLLfuncEx (LsaDeregisterLogonProcess, 4, secur32, 1)
|
||||||
|
LoadDLLfuncEx (LsaFreeReturnBuffer, 4, secur32, 1)
|
||||||
|
LoadDLLfuncEx (LsaLogonUser, 56, secur32, 1)
|
||||||
|
LoadDLLfuncEx (LsaLookupAuthenticationPackage, 12, secur32, 1)
|
||||||
|
LoadDLLfuncEx (LsaRegisterLogonProcess, 12, secur32, 1)
|
||||||
|
|
||||||
LoadDLLinit (user32)
|
LoadDLLinit (user32)
|
||||||
LoadDLLfunc (CharToOemA, 8, user32)
|
LoadDLLfunc (CharToOemA, 8, user32)
|
||||||
LoadDLLfunc (CharToOemBuffA, 12, user32)
|
LoadDLLfunc (CharToOemBuffA, 12, user32)
|
||||||
|
@ -35,6 +35,7 @@ extern BOOL allow_winsymlinks;
|
|||||||
extern BOOL strip_title_path;
|
extern BOOL strip_title_path;
|
||||||
extern int pcheck_case;
|
extern int pcheck_case;
|
||||||
extern DWORD chunksize;
|
extern DWORD chunksize;
|
||||||
|
extern int subauth_id;
|
||||||
BOOL reset_com = TRUE;
|
BOOL reset_com = TRUE;
|
||||||
static BOOL envcache = TRUE;
|
static BOOL envcache = TRUE;
|
||||||
|
|
||||||
@ -446,6 +447,19 @@ codepage_init (const char *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
subauth_id_init (const char *buf)
|
||||||
|
{
|
||||||
|
if (!buf || !*buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int i = strtol (buf, NULL, 0);
|
||||||
|
|
||||||
|
/* 0..127 are reserved by Microsoft, 132 is IIS subauthentication. */
|
||||||
|
if (i > 127 && i != 132 && i <= 255)
|
||||||
|
subauth_id = i;
|
||||||
|
}
|
||||||
|
|
||||||
/* The structure below is used to set up an array which is used to
|
/* The structure below is used to set up an array which is used to
|
||||||
parse the CYGWIN environment variable or, if enabled, options from
|
parse the CYGWIN environment variable or, if enabled, options from
|
||||||
the registry. */
|
the registry. */
|
||||||
@ -482,6 +496,7 @@ struct parse_thing
|
|||||||
{"smbntsec", {&allow_smbntsec}, justset, NULL, {{FALSE}, {TRUE}}},
|
{"smbntsec", {&allow_smbntsec}, justset, NULL, {{FALSE}, {TRUE}}},
|
||||||
{"reset_com", {&reset_com}, justset, NULL, {{FALSE}, {TRUE}}},
|
{"reset_com", {&reset_com}, justset, NULL, {{FALSE}, {TRUE}}},
|
||||||
{"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
|
{"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
|
||||||
|
{"subauth_id", {func: &subauth_id_init}, isfunc, NULL, {{0}, {0}}},
|
||||||
{"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},
|
{"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},
|
||||||
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
|
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
|
||||||
{"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{FALSE}, {TRUE}}},
|
{"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{FALSE}, {TRUE}}},
|
||||||
|
@ -436,7 +436,7 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll,
|
|||||||
uid_t uid;
|
uid_t uid;
|
||||||
uid = geteuid();
|
uid = geteuid();
|
||||||
if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
|
if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
seteuid (cygheap->user.orig_uid);
|
RevertToSelf ();
|
||||||
|
|
||||||
ch.parent = hParent;
|
ch.parent = hParent;
|
||||||
ch.cygheap = cygheap;
|
ch.cygheap = cygheap;
|
||||||
@ -484,7 +484,7 @@ out:
|
|||||||
/* Restore impersonation */
|
/* Restore impersonation */
|
||||||
if (cygheap->user.impersonated
|
if (cygheap->user.impersonated
|
||||||
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
seteuid (uid);
|
ImpersonateLoggedOnUser (cygheap->user.token);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ out:
|
|||||||
|
|
||||||
/* Restore impersonation */
|
/* Restore impersonation */
|
||||||
if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
|
if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
seteuid (uid);
|
ImpersonateLoggedOnUser (cygheap->user.token);
|
||||||
|
|
||||||
ProtectHandle (pi.hThread);
|
ProtectHandle (pi.hThread);
|
||||||
/* Protect the handle but name it similarly to the way it will
|
/* Protect the handle but name it similarly to the way it will
|
||||||
|
@ -24,6 +24,9 @@ details. */
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <wingdi.h>
|
#include <wingdi.h>
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
|
#include <wininet.h>
|
||||||
|
#include <ntsecapi.h>
|
||||||
|
#include <subauth.h>
|
||||||
#include "cygerrno.h"
|
#include "cygerrno.h"
|
||||||
#include "perprocess.h"
|
#include "perprocess.h"
|
||||||
#include "fhandler.h"
|
#include "fhandler.h"
|
||||||
@ -56,6 +59,39 @@ cygwin_set_impersonation_token (const HANDLE hToken)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
|
||||||
|
{
|
||||||
|
char buf[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
|
||||||
|
char *c;
|
||||||
|
|
||||||
|
strcpy (domain, "");
|
||||||
|
strcpy (buf, pw->pw_name);
|
||||||
|
debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
|
||||||
|
if (pw->pw_gecos)
|
||||||
|
{
|
||||||
|
if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
|
||||||
|
(c == pw->pw_gecos || c[-1] == ','))
|
||||||
|
{
|
||||||
|
buf[0] = '\0';
|
||||||
|
strncat (buf, c + 2, INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 1);
|
||||||
|
if ((c = strchr (buf, ',')) != NULL)
|
||||||
|
*c = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((c = strchr (buf, '\\')) != NULL)
|
||||||
|
{
|
||||||
|
*c++ = '\0';
|
||||||
|
strcpy (domain, buf);
|
||||||
|
strcpy (user, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy (domain, "");
|
||||||
|
strcpy (user, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
HANDLE
|
HANDLE
|
||||||
cygwin_logon_user (const struct passwd *pw, const char *password)
|
cygwin_logon_user (const struct passwd *pw, const char *password)
|
||||||
@ -71,32 +107,13 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
|
|||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *c, *nt_user, *nt_domain = NULL;
|
char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
char usernamebuf[256];
|
char nt_user[UNLEN + 1];
|
||||||
HANDLE hToken;
|
HANDLE hToken;
|
||||||
|
|
||||||
strcpy (usernamebuf, pw->pw_name);
|
extract_nt_dom_user (pw, nt_domain, nt_user);
|
||||||
debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
|
|
||||||
if (pw->pw_gecos)
|
|
||||||
{
|
|
||||||
if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
|
|
||||||
(c == pw->pw_gecos || c[-1] == ','))
|
|
||||||
{
|
|
||||||
usernamebuf[0] = '\0';
|
|
||||||
strncat (usernamebuf, c + 2, 255);
|
|
||||||
if ((c = strchr (usernamebuf, ',')) != NULL)
|
|
||||||
*c = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nt_user = usernamebuf;
|
|
||||||
if ((c = strchr (nt_user, '\\')) != NULL)
|
|
||||||
{
|
|
||||||
nt_domain = nt_user;
|
|
||||||
*c = '\0';
|
|
||||||
nt_user = c + 1;
|
|
||||||
}
|
|
||||||
debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password);
|
debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password);
|
||||||
if (!LogonUserA (nt_user, nt_domain, (char *) password,
|
if (!LogonUserA (nt_user, *nt_domain ? nt_domain : NULL, (char *) password,
|
||||||
LOGON32_LOGON_INTERACTIVE,
|
LOGON32_LOGON_INTERACTIVE,
|
||||||
LOGON32_PROVIDER_DEFAULT,
|
LOGON32_PROVIDER_DEFAULT,
|
||||||
&hToken)
|
&hToken)
|
||||||
@ -111,6 +128,126 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
|
|||||||
return hToken;
|
return hToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
str2lsa (LSA_STRING &tgt, const char *srcstr)
|
||||||
|
{
|
||||||
|
tgt.Length = strlen(srcstr);
|
||||||
|
tgt.MaximumLength = tgt.Length + 1;
|
||||||
|
tgt.Buffer = (PCHAR) srcstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr)
|
||||||
|
{
|
||||||
|
tgt.Length = strlen(srcstr);
|
||||||
|
tgt.MaximumLength = tgt.Length + 1;
|
||||||
|
tgt.Buffer = (PCHAR) buf;
|
||||||
|
memcpy(buf, srcstr, tgt.MaximumLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
|
||||||
|
{
|
||||||
|
tgt.Length = strlen(srcstr) * sizeof (WCHAR);
|
||||||
|
tgt.MaximumLength = tgt.Length + sizeof(WCHAR);
|
||||||
|
tgt.Buffer = (PWCHAR) buf;
|
||||||
|
mbstowcs (buf, srcstr, tgt.MaximumLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
int subauth_id = 255;
|
||||||
|
|
||||||
|
HANDLE
|
||||||
|
subauth (struct passwd *pw)
|
||||||
|
{
|
||||||
|
LSA_STRING name;
|
||||||
|
HANDLE lsa_hdl;
|
||||||
|
LSA_OPERATIONAL_MODE sec_mode;
|
||||||
|
NTSTATUS ret, ret2;
|
||||||
|
ULONG package_id, size;
|
||||||
|
struct {
|
||||||
|
LSA_STRING str;
|
||||||
|
CHAR buf[16];
|
||||||
|
} origin;
|
||||||
|
struct {
|
||||||
|
MSV1_0_LM20_LOGON auth;
|
||||||
|
WCHAR dombuf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
WCHAR usrbuf[UNLEN + 1];
|
||||||
|
WCHAR wkstbuf[1];
|
||||||
|
CHAR authinf1[1];
|
||||||
|
CHAR authinf2[1];
|
||||||
|
} subbuf;
|
||||||
|
TOKEN_SOURCE ts;
|
||||||
|
PMSV1_0_LM20_LOGON_PROFILE profile;
|
||||||
|
LUID luid;
|
||||||
|
HANDLE user_token;
|
||||||
|
QUOTA_LIMITS quota;
|
||||||
|
char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
char nt_user[UNLEN + 1];
|
||||||
|
|
||||||
|
set_process_privilege(SE_TCB_NAME);
|
||||||
|
|
||||||
|
/* Register as logon process. */
|
||||||
|
str2lsa (name, "Cygwin");
|
||||||
|
ret = LsaRegisterLogonProcess(&name, &lsa_hdl, &sec_mode);
|
||||||
|
if (ret != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
debug_printf ("LsaRegisterLogonProcess: %d", ret);
|
||||||
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
/* Get handle to MSV1_0 package. */
|
||||||
|
str2lsa (name, MSV1_0_PACKAGE_NAME);
|
||||||
|
ret = LsaLookupAuthenticationPackage(lsa_hdl, &name, &package_id);
|
||||||
|
if (ret != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
|
||||||
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
|
LsaDeregisterLogonProcess(lsa_hdl);
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
/* Create origin. */
|
||||||
|
str2buf2lsa (origin.str, origin.buf, "Cygwin");
|
||||||
|
/* Create token source. */
|
||||||
|
memcpy(ts.SourceName, "Cygwin.1", 8);
|
||||||
|
AllocateLocallyUniqueId(&ts.SourceIdentifier);
|
||||||
|
/* Get user information. */
|
||||||
|
extract_nt_dom_user (pw, nt_domain, nt_user);
|
||||||
|
/* Fill subauth with values. */
|
||||||
|
subbuf.auth.MessageType = MsV1_0NetworkLogon;
|
||||||
|
str2buf2uni(subbuf.auth.LogonDomainName, subbuf.dombuf, nt_domain);
|
||||||
|
str2buf2uni(subbuf.auth.UserName, subbuf.usrbuf, nt_user);
|
||||||
|
str2buf2uni(subbuf.auth.Workstation, subbuf.wkstbuf, "");
|
||||||
|
memcpy(subbuf.auth.ChallengeToClient, "12345678", MSV1_0_CHALLENGE_LENGTH);
|
||||||
|
str2buf2lsa(subbuf.auth.CaseSensitiveChallengeResponse, subbuf.authinf1, "");
|
||||||
|
str2buf2lsa(subbuf.auth.CaseInsensitiveChallengeResponse, subbuf.authinf2,"");
|
||||||
|
subbuf.auth.ParameterControl = 0 | (subauth_id << 24);
|
||||||
|
/* Try to logon... */
|
||||||
|
ret = LsaLogonUser(lsa_hdl, (PLSA_STRING) &origin, Network,
|
||||||
|
package_id, &subbuf, sizeof subbuf,
|
||||||
|
NULL, &ts, (PVOID *)&profile, &size,
|
||||||
|
&luid, &user_token, "a, &ret2);
|
||||||
|
if (ret != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
debug_printf ("LsaLogonUser: %d", ret);
|
||||||
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
|
LsaDeregisterLogonProcess(lsa_hdl);
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
LsaFreeReturnBuffer(profile);
|
||||||
|
/* Convert to primary token. */
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, TRUE };
|
||||||
|
HANDLE primary_token;
|
||||||
|
if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa,
|
||||||
|
SecurityImpersonation, TokenPrimary,
|
||||||
|
&primary_token))
|
||||||
|
{
|
||||||
|
CloseHandle (user_token);
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
CloseHandle (user_token);
|
||||||
|
return primary_token;
|
||||||
|
}
|
||||||
|
|
||||||
/* read_sd reads a security descriptor from a file.
|
/* read_sd reads a security descriptor from a file.
|
||||||
In case of error, -1 is returned and errno is set.
|
In case of error, -1 is returned and errno is set.
|
||||||
If sd_buf is too small, 0 is returned and sd_size
|
If sd_buf is too small, 0 is returned and sd_size
|
||||||
|
@ -66,6 +66,8 @@ LONG __stdcall write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_
|
|||||||
BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
|
BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
|
||||||
BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
|
BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
|
||||||
|
|
||||||
|
/* Try a subauthentication. */
|
||||||
|
HANDLE subauth (struct passwd *pw);
|
||||||
|
|
||||||
/* sec_helper.cc: Security helper functions. */
|
/* sec_helper.cc: Security helper functions. */
|
||||||
char *__stdcall convert_sid_to_string_sid (PSID psid, char *sid_str);
|
char *__stdcall convert_sid_to_string_sid (PSID psid, char *sid_str);
|
||||||
|
@ -578,7 +578,8 @@ skip_arg_parsing:
|
|||||||
/* Preallocated buffer for `sec_user' call */
|
/* Preallocated buffer for `sec_user' call */
|
||||||
char sa_buf[1024];
|
char sa_buf[1024];
|
||||||
|
|
||||||
if (!hToken && cygheap->user.token != INVALID_HANDLE_VALUE)
|
if (!hToken && cygheap->user.impersonated
|
||||||
|
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
hToken = cygheap->user.token;
|
hToken = cygheap->user.token;
|
||||||
|
|
||||||
const char *runpath = null_app_name ? NULL : (const char *) real_path;
|
const char *runpath = null_app_name ? NULL : (const char *) real_path;
|
||||||
@ -607,6 +608,28 @@ skip_arg_parsing:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
cygsid sid;
|
||||||
|
DWORD ret_len;
|
||||||
|
if (!GetTokenInformation (hToken, TokenUser, &sid, sizeof sid, &ret_len))
|
||||||
|
{
|
||||||
|
sid = NULL;
|
||||||
|
system_printf ("GetTokenInformation: %E");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve security attributes before setting psid to NULL
|
||||||
|
since it's value is needed by `sec_user'. */
|
||||||
|
PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid
|
||||||
|
? sec_user (sa_buf, sid)
|
||||||
|
: &sec_all_nih;
|
||||||
|
|
||||||
|
/* Remove impersonation */
|
||||||
|
if (cygheap->user.impersonated
|
||||||
|
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
|
RevertToSelf ();
|
||||||
|
|
||||||
|
/* Load users registry hive. */
|
||||||
|
load_registry_hive (sid);
|
||||||
|
|
||||||
/* allow the child to interact with our window station/desktop */
|
/* allow the child to interact with our window station/desktop */
|
||||||
HANDLE hwst, hdsk;
|
HANDLE hwst, hdsk;
|
||||||
SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION;
|
SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION;
|
||||||
@ -625,31 +648,6 @@ skip_arg_parsing:
|
|||||||
strcat (wstname, dskname);
|
strcat (wstname, dskname);
|
||||||
si.lpDesktop = wstname;
|
si.lpDesktop = wstname;
|
||||||
|
|
||||||
char tu[1024];
|
|
||||||
PSID sid = NULL;
|
|
||||||
DWORD ret_len;
|
|
||||||
if (GetTokenInformation (hToken, TokenUser,
|
|
||||||
(LPVOID) &tu, sizeof tu,
|
|
||||||
&ret_len))
|
|
||||||
sid = ((TOKEN_USER *) &tu)->User.Sid;
|
|
||||||
else
|
|
||||||
system_printf ("GetTokenInformation: %E");
|
|
||||||
|
|
||||||
/* Retrieve security attributes before setting psid to NULL
|
|
||||||
since it's value is needed by `sec_user'. */
|
|
||||||
PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid
|
|
||||||
? sec_user (sa_buf, sid)
|
|
||||||
: &sec_all_nih;
|
|
||||||
|
|
||||||
/* Remove impersonation */
|
|
||||||
uid_t uid = geteuid ();
|
|
||||||
if (cygheap->user.impersonated
|
|
||||||
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
|
||||||
seteuid (cygheap->user.orig_uid);
|
|
||||||
|
|
||||||
/* Load users registry hive. */
|
|
||||||
load_registry_hive (sid);
|
|
||||||
|
|
||||||
rc = CreateProcessAsUser (hToken,
|
rc = CreateProcessAsUser (hToken,
|
||||||
runpath, /* image name - with full path */
|
runpath, /* image name - with full path */
|
||||||
one_line.buf, /* what was passed to exec */
|
one_line.buf, /* what was passed to exec */
|
||||||
@ -666,7 +664,7 @@ skip_arg_parsing:
|
|||||||
if (mode != _P_OVERLAY && mode != _P_VFORK
|
if (mode != _P_OVERLAY && mode != _P_VFORK
|
||||||
&& cygheap->user.impersonated
|
&& cygheap->user.impersonated
|
||||||
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
seteuid (uid);
|
ImpersonateLoggedOnUser (cygheap->user.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
|
@ -1964,68 +1964,96 @@ seteuid (uid_t uid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uid != myself->uid)
|
if (uid != myself->uid)
|
||||||
if (uid == cygheap->user.orig_uid)
|
|
||||||
{
|
|
||||||
debug_printf ("RevertToSelf () (uid == orig_uid, token=%d)",
|
|
||||||
cygheap->user.token);
|
|
||||||
RevertToSelf ();
|
|
||||||
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
|
||||||
cygheap->user.impersonated = FALSE;
|
|
||||||
}
|
|
||||||
else if (!cygheap->user.impersonated)
|
|
||||||
{
|
|
||||||
debug_printf ("Impersonate (uid == %d)", uid);
|
|
||||||
RevertToSelf ();
|
|
||||||
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
struct group *gr;
|
|
||||||
cygsid sid;
|
|
||||||
DWORD siz;
|
|
||||||
|
|
||||||
/* Try setting owner to same value as user. */
|
|
||||||
if (!GetTokenInformation (cygheap->user.token, TokenUser,
|
|
||||||
&sid, sizeof sid, &siz))
|
|
||||||
debug_printf ("GetTokenInformation(): %E");
|
|
||||||
else if (!SetTokenInformation (cygheap->user.token,
|
|
||||||
TokenOwner,
|
|
||||||
&sid, sizeof sid))
|
|
||||||
debug_printf ("SetTokenInformation(user.token, "
|
|
||||||
"TokenOwner): %E");
|
|
||||||
/* Try setting primary group in token to current group. */
|
|
||||||
if ((gr = getgrgid (myself->gid)) &&
|
|
||||||
get_gr_sid (sid, gr) &&
|
|
||||||
!SetTokenInformation (cygheap->user.token,
|
|
||||||
TokenPrimaryGroup,
|
|
||||||
&sid, sizeof sid))
|
|
||||||
debug_printf ("SetTokenInformation(user.token, "
|
|
||||||
"TokenPrimaryGroup): %E");
|
|
||||||
|
|
||||||
/* Now try to impersonate. */
|
|
||||||
if (!ImpersonateLoggedOnUser (cygheap->user.token))
|
|
||||||
system_printf ("Impersonate (%d) in set(e)uid failed: %E",
|
|
||||||
cygheap->user.token);
|
|
||||||
else
|
|
||||||
cygheap->user.impersonated = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cygheap_user user;
|
|
||||||
/* user.token is used in internal_getlogin () to determine if
|
|
||||||
impersonation is active. If so, the token is used for
|
|
||||||
retrieving user's SID. */
|
|
||||||
user.token = cygheap->user.impersonated ? cygheap->user.token
|
|
||||||
: INVALID_HANDLE_VALUE;
|
|
||||||
struct passwd *pw_cur = internal_getlogin (user);
|
|
||||||
if (pw_cur != pw_new)
|
|
||||||
{
|
{
|
||||||
debug_printf ("Diffs!!! token: %d, cur: %d, new: %d, orig: %d",
|
if (uid == cygheap->user.orig_uid)
|
||||||
cygheap->user.token, pw_cur->pw_uid,
|
{
|
||||||
pw_new->pw_uid, cygheap->user.orig_uid);
|
debug_printf ("RevertToSelf () (uid == orig_uid, token=%d)",
|
||||||
set_errno (EPERM);
|
cygheap->user.token);
|
||||||
return -1;
|
RevertToSelf ();
|
||||||
|
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
|
cygheap->user.impersonated = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cygsid tsid, psid, gsid;
|
||||||
|
DWORD siz;
|
||||||
|
|
||||||
|
/* Check if new user == user of impersonation token. */
|
||||||
|
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
if (!GetTokenInformation (cygheap->user.token, TokenUser,
|
||||||
|
&tsid, sizeof tsid, &siz))
|
||||||
|
debug_printf ("GetTokenInformation(): %E");
|
||||||
|
else if (get_pw_sid (psid, pw_new) && tsid != psid)
|
||||||
|
{
|
||||||
|
/* If not, RevertToSelf and close old token. */
|
||||||
|
RevertToSelf ();
|
||||||
|
cygwin_set_impersonation_token (INVALID_HANDLE_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If no impersonation token is available, try to
|
||||||
|
authenticate using subauthentication. */
|
||||||
|
if (cygheap->user.token == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
HANDLE ptok = subauth (pw_new);
|
||||||
|
if (ptok != INVALID_HANDLE_VALUE)
|
||||||
|
cygwin_set_impersonation_token (ptok);
|
||||||
|
else
|
||||||
|
cygheap->user.impersonated = TRUE;
|
||||||
|
}
|
||||||
|
/* If no impersonation is active but an impersonation
|
||||||
|
token is available, try to impersonate. */
|
||||||
|
if (!cygheap->user.impersonated)
|
||||||
|
{
|
||||||
|
debug_printf ("Impersonate (uid == %d)", uid);
|
||||||
|
RevertToSelf ();
|
||||||
|
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
struct group *gr;
|
||||||
|
|
||||||
|
/* Try setting owner to same value as user. */
|
||||||
|
if (!SetTokenInformation (cygheap->user.token,
|
||||||
|
TokenOwner,
|
||||||
|
&tsid, sizeof tsid))
|
||||||
|
debug_printf ("SetTokenInformation(user.token, "
|
||||||
|
"TokenOwner): %E");
|
||||||
|
/* Try setting primary group in token to current group. */
|
||||||
|
if ((gr = getgrgid (myself->gid)) &&
|
||||||
|
get_gr_sid (gsid, gr) &&
|
||||||
|
!SetTokenInformation (cygheap->user.token,
|
||||||
|
TokenPrimaryGroup,
|
||||||
|
&gsid, sizeof gsid))
|
||||||
|
debug_printf ("SetTokenInformation(user.token, "
|
||||||
|
"TokenPrimaryGroup): %E");
|
||||||
|
|
||||||
|
/* Now try to impersonate. */
|
||||||
|
if (!ImpersonateLoggedOnUser (cygheap->user.token))
|
||||||
|
system_printf ("Impersonating (%d) in set(e)uid "
|
||||||
|
"failed: %E", cygheap->user.token);
|
||||||
|
else
|
||||||
|
cygheap->user.impersonated = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cygheap_user user;
|
||||||
|
/* user.token is used in internal_getlogin () to determine if
|
||||||
|
impersonation is active. If so, the token is used for
|
||||||
|
retrieving user's SID. */
|
||||||
|
user.token = cygheap->user.impersonated ? cygheap->user.token
|
||||||
|
: INVALID_HANDLE_VALUE;
|
||||||
|
struct passwd *pw_cur = internal_getlogin (user);
|
||||||
|
if (pw_cur != pw_new)
|
||||||
|
{
|
||||||
|
debug_printf ("Diffs!!! token: %d, cur: %d, new: %d, orig: %d",
|
||||||
|
cygheap->user.token, pw_cur->pw_uid,
|
||||||
|
pw_new->pw_uid, cygheap->user.orig_uid);
|
||||||
|
set_errno (EPERM);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
myself->uid = uid;
|
||||||
|
cygheap->user = user;
|
||||||
}
|
}
|
||||||
myself->uid = uid;
|
|
||||||
cygheap->user = user;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user