* autoload.cc: Add load statements for `LookupAccountNameW',
`LsaClose', `LsaEnumerateAccountRights', `LsaFreeMemory', `LsaOpenPolicy', `LsaQueryInformationPolicy', `NetLocalGroupEnum', `NetLocalGroupGetMembers', `NetServerEnum', `NetUserGetGroups' and `NtCreateToken'. * ntdll.h: Add declaration for `NtCreateToken'. * sec_helper.cc: Add `well_known_local_sid', `well_known_dialup_sid', `well_known_network_sid', `well_known_batch_sid', `well_known_interactive_sid', `well_known_service_sid' and `well_known_authenticated_users_sid'. (cygsid::string): Define as const method. (cygsid::get_sid): Set psid to NO_SID on error. (cygsid::getfromstr): Ditto. (cygsid::getfrompw): Simplify. (cygsid::getfromgr): Check for gr == NULL. (legal_sid_type): Move to security.h. (set_process_privilege): Return -1 on error, otherwise 0 or 1 related to previous privilege setting. * security.cc (extract_nt_dom_user): Remove `static'. (lsa2wchar): New function. (open_local_policy): Ditto. (close_local_policy): Ditto. (get_lsa_srv_inf): Ditto. (get_logon_server): Ditto. (get_logon_server_and_user_domain): Ditto. (get_user_groups): Ditto. (is_group_member): Ditto. (get_user_local_groups): Ditto. (sid_in_token_groups): Ditto. (get_user_primary_group): Ditto. (get_group_sidlist): Ditto. (get_system_priv_list): Ditto. (get_priv_list): Ditto. (get_dacl): Ditto. (create_token): Ditto. (subauth): Return immediately if SE_TCB_NAME can't be assigned. Change all return statements in case of error to jumps to `out' label. Add `out' label to support cleanup. * security.h: Add extern declarations for `well_known_local_sid', `well_known_dialup_sid', `well_known_network_sid', `well_known_batch_sid', `well_known_interactive_sid', `well_known_service_sid' and `well_known_authenticated_users_sid'. Add extern declarations for functions `create_token', `extract_nt_dom_user' and `get_logon_server_and_user_domain'. (class cygsid): Add method `assign'. Change operator= to call new `assign' method. Add `debug_print' method. (class cygsidlist): New class. (legal_sid_type): Moved from sec_helper.cc to here. * spawn.cc (spawn_guts) Revert reversion of previous patch. Call `RevertToSelf' and `ImpersonateLoggedOnUser' instead of `seteuid' again. * syscalls.cc (seteuid): Rearranged. Call `create_token' now when needed. Call `subauth' if `create_token' fails. Try setting token owner and primary group only if token was not explicitely created by `create_token'. * uinfo.cc (internal_getlogin): Try harder to generate correct user information. Especially don't trust return value of `GetUserName'.
This commit is contained in:
parent
df7cd7fb0c
commit
1fcc912f13
@ -1,3 +1,63 @@
|
|||||||
|
Sat May 19 23:40:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* autoload.cc: Add load statements for `LookupAccountNameW',
|
||||||
|
`LsaClose', `LsaEnumerateAccountRights', `LsaFreeMemory',
|
||||||
|
`LsaOpenPolicy', `LsaQueryInformationPolicy', `NetLocalGroupEnum',
|
||||||
|
`NetLocalGroupGetMembers', `NetServerEnum', `NetUserGetGroups' and
|
||||||
|
`NtCreateToken'.
|
||||||
|
* ntdll.h: Add declaration for `NtCreateToken'.
|
||||||
|
* sec_helper.cc: Add `well_known_local_sid', `well_known_dialup_sid',
|
||||||
|
`well_known_network_sid', `well_known_batch_sid',
|
||||||
|
`well_known_interactive_sid', `well_known_service_sid' and
|
||||||
|
`well_known_authenticated_users_sid'.
|
||||||
|
(cygsid::string): Define as const method.
|
||||||
|
(cygsid::get_sid): Set psid to NO_SID on error.
|
||||||
|
(cygsid::getfromstr): Ditto.
|
||||||
|
(cygsid::getfrompw): Simplify.
|
||||||
|
(cygsid::getfromgr): Check for gr == NULL.
|
||||||
|
(legal_sid_type): Move to security.h.
|
||||||
|
(set_process_privilege): Return -1 on error, otherwise 0 or 1 related
|
||||||
|
to previous privilege setting.
|
||||||
|
* security.cc (extract_nt_dom_user): Remove `static'.
|
||||||
|
(lsa2wchar): New function.
|
||||||
|
(open_local_policy): Ditto.
|
||||||
|
(close_local_policy): Ditto.
|
||||||
|
(get_lsa_srv_inf): Ditto.
|
||||||
|
(get_logon_server): Ditto.
|
||||||
|
(get_logon_server_and_user_domain): Ditto.
|
||||||
|
(get_user_groups): Ditto.
|
||||||
|
(is_group_member): Ditto.
|
||||||
|
(get_user_local_groups): Ditto.
|
||||||
|
(sid_in_token_groups): Ditto.
|
||||||
|
(get_user_primary_group): Ditto.
|
||||||
|
(get_group_sidlist): Ditto.
|
||||||
|
(get_system_priv_list): Ditto.
|
||||||
|
(get_priv_list): Ditto.
|
||||||
|
(get_dacl): Ditto.
|
||||||
|
(create_token): Ditto.
|
||||||
|
(subauth): Return immediately if SE_TCB_NAME can't be assigned.
|
||||||
|
Change all return statements in case of error to jumps to `out'
|
||||||
|
label. Add `out' label to support cleanup.
|
||||||
|
* security.h: Add extern declarations for `well_known_local_sid',
|
||||||
|
`well_known_dialup_sid', `well_known_network_sid',
|
||||||
|
`well_known_batch_sid', `well_known_interactive_sid',
|
||||||
|
`well_known_service_sid' and `well_known_authenticated_users_sid'.
|
||||||
|
Add extern declarations for functions `create_token',
|
||||||
|
`extract_nt_dom_user' and `get_logon_server_and_user_domain'.
|
||||||
|
(class cygsid): Add method `assign'. Change operator= to call new
|
||||||
|
`assign' method. Add `debug_print' method.
|
||||||
|
(class cygsidlist): New class.
|
||||||
|
(legal_sid_type): Moved from sec_helper.cc to here.
|
||||||
|
* spawn.cc (spawn_guts) Revert reversion of previous patch.
|
||||||
|
Call `RevertToSelf' and `ImpersonateLoggedOnUser' instead of `seteuid'
|
||||||
|
again.
|
||||||
|
* syscalls.cc (seteuid): Rearranged. Call `create_token' now when
|
||||||
|
needed. Call `subauth' if `create_token' fails. Try setting token
|
||||||
|
owner and primary group only if token was not explicitely created
|
||||||
|
by `create_token'.
|
||||||
|
* uinfo.cc (internal_getlogin): Try harder to generate correct user
|
||||||
|
information. Especially don't trust return value of `GetUserName'.
|
||||||
|
|
||||||
Sat May 19 21:16:07 2001 Christopher Faylor <cgf@cygnus.com>
|
Sat May 19 21:16:07 2001 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
* fork.cc (fork_parent): Move atforkprepare call here.
|
* fork.cc (fork_parent): Move atforkprepare call here.
|
||||||
|
@ -333,9 +333,15 @@ LoadDLLfunc (InitializeSid, 12, advapi32)
|
|||||||
LoadDLLfunc (IsValidSid, 4, advapi32)
|
LoadDLLfunc (IsValidSid, 4, advapi32)
|
||||||
LoadDLLfunc (LogonUserA, 24, advapi32)
|
LoadDLLfunc (LogonUserA, 24, advapi32)
|
||||||
LoadDLLfunc (LookupAccountNameA, 28, advapi32)
|
LoadDLLfunc (LookupAccountNameA, 28, advapi32)
|
||||||
|
LoadDLLfunc (LookupAccountNameW, 28, advapi32)
|
||||||
LoadDLLfunc (LookupAccountSidA, 28, advapi32)
|
LoadDLLfunc (LookupAccountSidA, 28, advapi32)
|
||||||
LoadDLLfunc (LookupPrivilegeValueA, 12, advapi32)
|
LoadDLLfunc (LookupPrivilegeValueA, 12, advapi32)
|
||||||
LoadDLLfuncEx (LsaNtStatusToWinError, 4, advapi32, 1)
|
LoadDLLfunc (LsaClose, 4, advapi32)
|
||||||
|
LoadDLLfunc (LsaEnumerateAccountRights, 16, advapi32)
|
||||||
|
LoadDLLfunc (LsaFreeMemory, 4, advapi32)
|
||||||
|
LoadDLLfunc (LsaNtStatusToWinError, 4, advapi32)
|
||||||
|
LoadDLLfunc (LsaOpenPolicy, 16, advapi32)
|
||||||
|
LoadDLLfunc (LsaQueryInformationPolicy, 12, advapi32)
|
||||||
LoadDLLfunc (MakeSelfRelativeSD, 12, advapi32)
|
LoadDLLfunc (MakeSelfRelativeSD, 12, advapi32)
|
||||||
LoadDLLfunc (OpenProcessToken, 12, advapi32)
|
LoadDLLfunc (OpenProcessToken, 12, advapi32)
|
||||||
LoadDLLfunc (RegCloseKey, 4, advapi32)
|
LoadDLLfunc (RegCloseKey, 4, advapi32)
|
||||||
@ -358,10 +364,15 @@ LoadDLLfunc (SetSecurityDescriptorGroup, 12, advapi32)
|
|||||||
LoadDLLfunc (SetSecurityDescriptorOwner, 12, advapi32)
|
LoadDLLfunc (SetSecurityDescriptorOwner, 12, advapi32)
|
||||||
LoadDLLfunc (SetTokenInformation, 16, advapi32)
|
LoadDLLfunc (SetTokenInformation, 16, advapi32)
|
||||||
|
|
||||||
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
|
|
||||||
LoadDLLfunc (NetUserGetInfo, 16, netapi32)
|
|
||||||
LoadDLLfunc (NetApiBufferFree, 4, netapi32)
|
LoadDLLfunc (NetApiBufferFree, 4, netapi32)
|
||||||
|
LoadDLLfunc (NetLocalGroupEnum, 28, netapi32)
|
||||||
|
LoadDLLfunc (NetLocalGroupGetMembers, 32, netapi32)
|
||||||
|
LoadDLLfunc (NetServerEnum, 36, netapi32)
|
||||||
|
LoadDLLfunc (NetUserGetGroups, 28, netapi32)
|
||||||
|
LoadDLLfunc (NetUserGetInfo, 16, netapi32)
|
||||||
|
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
|
||||||
|
|
||||||
|
LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1)
|
||||||
LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
|
LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
|
||||||
LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1)
|
LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1)
|
||||||
LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)
|
LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)
|
||||||
|
@ -136,12 +136,17 @@ typedef struct _SYSTEM_PROCESSES
|
|||||||
standard Win32 header. */
|
standard Win32 header. */
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
NTSTATUS NTAPI NtCreateToken (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
|
||||||
|
TOKEN_TYPE, PLUID, PLARGE_INTEGER, PTOKEN_USER,
|
||||||
|
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,
|
||||||
|
PTOKEN_PRIMARY_GROUP, PTOKEN_DEFAULT_DACL,
|
||||||
|
PTOKEN_SOURCE);
|
||||||
NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG,
|
NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG,
|
||||||
PLARGE_INTEGER, PULONG, SECTION_INHERIT,
|
PLARGE_INTEGER, PULONG, SECTION_INHERIT,
|
||||||
ULONG, ULONG);
|
ULONG, ULONG);
|
||||||
|
NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
|
||||||
NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS,
|
NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS,
|
||||||
PVOID, ULONG, PULONG);
|
PVOID, ULONG, PULONG);
|
||||||
NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
|
|
||||||
NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);
|
NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);
|
||||||
VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR);
|
VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR);
|
||||||
ULONG NTAPI RtlNtStatusToDosError (NTSTATUS);
|
ULONG NTAPI RtlNtStatusToDosError (NTSTATUS);
|
||||||
|
@ -44,13 +44,20 @@ SID_IDENTIFIER_AUTHORITY sid_auth[] = {
|
|||||||
{SECURITY_NT_AUTHORITY}
|
{SECURITY_NT_AUTHORITY}
|
||||||
};
|
};
|
||||||
|
|
||||||
cygsid well_known_admin_sid ("S-1-5-32-544");
|
|
||||||
cygsid well_known_system_sid ("S-1-5-18");
|
|
||||||
cygsid well_known_creator_owner_sid ("S-1-3-0");
|
|
||||||
cygsid well_known_world_sid ("S-1-1-0");
|
cygsid well_known_world_sid ("S-1-1-0");
|
||||||
|
cygsid well_known_local_sid ("S-1-2-0");
|
||||||
|
cygsid well_known_creator_owner_sid ("S-1-3-0");
|
||||||
|
cygsid well_known_dialup_sid ("S-1-5-1");
|
||||||
|
cygsid well_known_network_sid ("S-1-5-2");
|
||||||
|
cygsid well_known_batch_sid ("S-1-5-3");
|
||||||
|
cygsid well_known_interactive_sid ("S-1-5-4");
|
||||||
|
cygsid well_known_service_sid ("S-1-5-6");
|
||||||
|
cygsid well_known_authenticated_users_sid ("S-1-5-11");
|
||||||
|
cygsid well_known_system_sid ("S-1-5-18");
|
||||||
|
cygsid well_known_admin_sid ("S-1-5-32-544");
|
||||||
|
|
||||||
char *
|
char *
|
||||||
cygsid::string (char *nsidstr)
|
cygsid::string (char *nsidstr) const
|
||||||
{
|
{
|
||||||
char t[32];
|
char t[32];
|
||||||
DWORD i;
|
DWORD i;
|
||||||
@ -74,7 +81,10 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r)
|
|||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
if (s > 5 || cnt < 1 || cnt > 8)
|
if (s > 5 || cnt < 1 || cnt > 8)
|
||||||
return NULL;
|
{
|
||||||
|
psid = NO_SID;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
set ();
|
set ();
|
||||||
InitializeSid(psid, &sid_auth[s], cnt);
|
InitializeSid(psid, &sid_auth[s], cnt);
|
||||||
for (i = 0; i < cnt; ++i)
|
for (i = 0; i < cnt; ++i)
|
||||||
@ -92,7 +102,10 @@ cygsid::getfromstr (const char *nsidstr)
|
|||||||
DWORD i, r[8];
|
DWORD i, r[8];
|
||||||
|
|
||||||
if (!nsidstr || strncmp (nsidstr, "S-1-", 4))
|
if (!nsidstr || strncmp (nsidstr, "S-1-", 4))
|
||||||
return NULL;
|
{
|
||||||
|
psid = NO_SID;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
strcpy (sid_buf, nsidstr);
|
strcpy (sid_buf, nsidstr);
|
||||||
|
|
||||||
@ -110,17 +123,15 @@ cygsid::getfromstr (const char *nsidstr)
|
|||||||
BOOL
|
BOOL
|
||||||
cygsid::getfrompw (struct passwd *pw)
|
cygsid::getfrompw (struct passwd *pw)
|
||||||
{
|
{
|
||||||
char *sp = pw->pw_gecos ? strrchr (pw->pw_gecos, ',') : NULL;
|
char *sp = (pw && pw->pw_gecos) ? strrchr (pw->pw_gecos, ',') : NULL;
|
||||||
|
return (*this = sp ? sp + 1 : "") != NULL;
|
||||||
if (!sp)
|
|
||||||
return FALSE;
|
|
||||||
return (*this = ++sp) != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
cygsid::getfromgr (struct group *gr)
|
cygsid::getfromgr (struct group *gr)
|
||||||
{
|
{
|
||||||
return (*this = gr->gr_passwd) != NULL;
|
char *sp = (gr && gr->gr_passwd) ? gr->gr_passwd : NULL;
|
||||||
|
return (*this = sp ?: "") != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -238,13 +249,6 @@ cygsid::get_id (BOOL search_grp, int *type)
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BOOL
|
|
||||||
legal_sid_type (SID_NAME_USE type)
|
|
||||||
{
|
|
||||||
return type == SidTypeUser || type == SidTypeGroup
|
|
||||||
|| type == SidTypeAlias || type == SidTypeWellKnownGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
is_grp_member (uid_t uid, gid_t gid)
|
is_grp_member (uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
@ -338,10 +342,12 @@ set_process_privilege (const char *privilege, BOOL enable)
|
|||||||
{
|
{
|
||||||
HANDLE hToken = NULL;
|
HANDLE hToken = NULL;
|
||||||
LUID restore_priv;
|
LUID restore_priv;
|
||||||
TOKEN_PRIVILEGES new_priv;
|
TOKEN_PRIVILEGES new_priv, orig_priv;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
if (!OpenProcessToken (hMainProc, TOKEN_ADJUST_PRIVILEGES, &hToken))
|
if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||||
|
&hToken))
|
||||||
{
|
{
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
goto out;
|
goto out;
|
||||||
@ -357,13 +363,22 @@ set_process_privilege (const char *privilege, BOOL enable)
|
|||||||
new_priv.Privileges[0].Luid = restore_priv;
|
new_priv.Privileges[0].Luid = restore_priv;
|
||||||
new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
|
new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
|
||||||
|
|
||||||
if (!AdjustTokenPrivileges (hToken, FALSE, &new_priv, 0, NULL, NULL))
|
if (!AdjustTokenPrivileges (hToken, FALSE, &new_priv,
|
||||||
|
sizeof orig_priv, &orig_priv, &size))
|
||||||
{
|
{
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* AdjustTokenPrivileges returns TRUE even if the privilege could not
|
||||||
|
be enabled. GetLastError() returns an correct error code, though. */
|
||||||
|
if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
|
||||||
|
{
|
||||||
|
debug_printf ("Privilege %s couldn't be assigned", privilege);
|
||||||
|
__seterrno ();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (hToken)
|
if (hToken)
|
||||||
|
@ -37,6 +37,10 @@ details. */
|
|||||||
#include "pinfo.h"
|
#include "pinfo.h"
|
||||||
#include "cygheap.h"
|
#include "cygheap.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
#include <ntdef.h>
|
||||||
|
#include "ntdll.h"
|
||||||
|
#include "lm.h"
|
||||||
|
|
||||||
|
|
||||||
extern BOOL allow_ntea;
|
extern BOOL allow_ntea;
|
||||||
BOOL allow_ntsec = FALSE;
|
BOOL allow_ntsec = FALSE;
|
||||||
@ -57,7 +61,7 @@ cygwin_set_impersonation_token (const HANDLE hToken)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
|
extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
|
||||||
{
|
{
|
||||||
char buf[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
|
char buf[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
|
||||||
@ -129,7 +133,7 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
|
|||||||
static void
|
static void
|
||||||
str2lsa (LSA_STRING &tgt, const char *srcstr)
|
str2lsa (LSA_STRING &tgt, const char *srcstr)
|
||||||
{
|
{
|
||||||
tgt.Length = strlen(srcstr);
|
tgt.Length = strlen (srcstr);
|
||||||
tgt.MaximumLength = tgt.Length + 1;
|
tgt.MaximumLength = tgt.Length + 1;
|
||||||
tgt.Buffer = (PCHAR) srcstr;
|
tgt.Buffer = (PCHAR) srcstr;
|
||||||
}
|
}
|
||||||
@ -137,7 +141,7 @@ str2lsa (LSA_STRING &tgt, const char *srcstr)
|
|||||||
static void
|
static void
|
||||||
str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr)
|
str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr)
|
||||||
{
|
{
|
||||||
tgt.Length = strlen(srcstr);
|
tgt.Length = strlen (srcstr);
|
||||||
tgt.MaximumLength = tgt.Length + 1;
|
tgt.MaximumLength = tgt.Length + 1;
|
||||||
tgt.Buffer = (PCHAR) buf;
|
tgt.Buffer = (PCHAR) buf;
|
||||||
memcpy(buf, srcstr, tgt.MaximumLength);
|
memcpy(buf, srcstr, tgt.MaximumLength);
|
||||||
@ -146,12 +150,644 @@ str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr)
|
|||||||
static void
|
static void
|
||||||
str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
|
str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
|
||||||
{
|
{
|
||||||
tgt.Length = strlen(srcstr) * sizeof (WCHAR);
|
tgt.Length = strlen (srcstr) * sizeof (WCHAR);
|
||||||
tgt.MaximumLength = tgt.Length + sizeof(WCHAR);
|
tgt.MaximumLength = tgt.Length + sizeof(WCHAR);
|
||||||
tgt.Buffer = (PWCHAR) buf;
|
tgt.Buffer = (PWCHAR) buf;
|
||||||
mbstowcs (buf, srcstr, tgt.MaximumLength);
|
mbstowcs (buf, srcstr, tgt.MaximumLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size)
|
||||||
|
{
|
||||||
|
size = (size - 1) * sizeof (WCHAR);
|
||||||
|
if (src.Length < size)
|
||||||
|
size = src.Length;
|
||||||
|
memcpy (tgt, src.Buffer, size);
|
||||||
|
size >>= 1;
|
||||||
|
tgt[size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LSA_HANDLE
|
||||||
|
open_local_policy ()
|
||||||
|
{
|
||||||
|
LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 };
|
||||||
|
LSA_HANDLE lsa = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
NTSTATUS ret = LsaOpenPolicy(NULL, &oa, POLICY_ALL_ACCESS, &lsa);
|
||||||
|
if (ret != STATUS_SUCCESS)
|
||||||
|
set_errno (LsaNtStatusToWinError (ret));
|
||||||
|
return lsa;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
close_local_policy (LSA_HANDLE &lsa)
|
||||||
|
{
|
||||||
|
if (lsa != INVALID_HANDLE_VALUE)
|
||||||
|
LsaClose (lsa);
|
||||||
|
lsa = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
get_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain)
|
||||||
|
{
|
||||||
|
NET_API_STATUS ret;
|
||||||
|
LPSERVER_INFO_101 buf;
|
||||||
|
DWORD cnt, tot;
|
||||||
|
char name[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
WCHAR account[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
WCHAR primary[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
PPOLICY_ACCOUNT_DOMAIN_INFO adi;
|
||||||
|
PPOLICY_PRIMARY_DOMAIN_INFO pdi;
|
||||||
|
|
||||||
|
if ((ret = LsaQueryInformationPolicy (lsa, PolicyAccountDomainInformation,
|
||||||
|
(PVOID *) &adi)) != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
lsa2wchar (account, adi->DomainName, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
LsaFreeMemory (adi);
|
||||||
|
if ((ret = LsaQueryInformationPolicy (lsa, PolicyPrimaryDomainInformation,
|
||||||
|
(PVOID *) &pdi)) != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
lsa2wchar (primary, pdi->Name, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
LsaFreeMemory (pdi);
|
||||||
|
if ((ret = NetServerEnum (NULL, 101, (LPBYTE *) &buf, MAX_PREFERRED_LENGTH,
|
||||||
|
&cnt, &tot, SV_TYPE_DOMAIN_CTRL, primary, NULL))
|
||||||
|
== STATUS_SUCCESS && cnt > 0)
|
||||||
|
{
|
||||||
|
wcstombs (name, buf[0].sv101_name, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
if (domain)
|
||||||
|
wcstombs (domain, primary, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wcstombs (name, account, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
if (domain)
|
||||||
|
wcstombs (domain, account, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
}
|
||||||
|
if (ret == STATUS_SUCCESS)
|
||||||
|
NetApiBufferFree (buf);
|
||||||
|
strcpy (logonserver, "\\\\");
|
||||||
|
strcat (logonserver, name);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
get_logon_server (LSA_HANDLE lsa, char *logonserver)
|
||||||
|
{
|
||||||
|
return get_lsa_srv_inf (lsa, logonserver, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
get_logon_server_and_user_domain (char *logonserver, char *userdomain)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
LSA_HANDLE lsa = open_local_policy ();
|
||||||
|
if (lsa)
|
||||||
|
{
|
||||||
|
ret = get_lsa_srv_inf (lsa, logonserver, userdomain);
|
||||||
|
close_local_policy (lsa);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user)
|
||||||
|
{
|
||||||
|
WCHAR wuser[UNLEN + 1];
|
||||||
|
mbstowcs (wuser, user, UNLEN + 1);
|
||||||
|
LPGROUP_USERS_INFO_0 buf;
|
||||||
|
DWORD cnt, tot;
|
||||||
|
NET_API_STATUS ret;
|
||||||
|
|
||||||
|
if ((ret = NetUserGetGroups (wlogonserver, wuser, 0, (LPBYTE *) &buf,
|
||||||
|
MAX_PREFERRED_LENGTH, &cnt, &tot)))
|
||||||
|
{
|
||||||
|
debug_printf ("%d = NetUserGetGroups ()", ret);
|
||||||
|
set_errno (ret);
|
||||||
|
/* It's no error when the user name can't be found. */
|
||||||
|
return ret == NERR_UserNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < cnt; ++i)
|
||||||
|
{
|
||||||
|
cygsid gsid;
|
||||||
|
char group[UNLEN + 1];
|
||||||
|
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
DWORD glen = UNLEN + 1;
|
||||||
|
DWORD dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
SID_NAME_USE use = SidTypeInvalid;
|
||||||
|
|
||||||
|
wcstombs (group, buf[i].grui0_name, UNLEN + 1);
|
||||||
|
if (!LookupAccountName (NULL, group, gsid, &glen, domain, &dlen, &use))
|
||||||
|
debug_printf ("LookupAccountName(%s): %lu\n", group, GetLastError ());
|
||||||
|
if (!legal_sid_type (use))
|
||||||
|
{
|
||||||
|
strcat (strcpy (group, domain), "\\");
|
||||||
|
wcstombs (group + strlen (group), buf[i].grui0_name,
|
||||||
|
UNLEN + 1 - strlen (group));
|
||||||
|
glen = UNLEN + 1;
|
||||||
|
dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
if (!LookupAccountName(NULL, group, gsid, &glen, domain, &dlen, &use))
|
||||||
|
debug_printf ("LookupAccountName(%s): %lu\n", group,GetLastError());
|
||||||
|
}
|
||||||
|
if (legal_sid_type (use))
|
||||||
|
grp_list += gsid;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetApiBufferFree (buf);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
is_group_member (WCHAR *wlogonserver, WCHAR *wgroup,
|
||||||
|
cygsid &usersid, cygsidlist &grp_list)
|
||||||
|
{
|
||||||
|
LPLOCALGROUP_MEMBERS_INFO_0 buf;
|
||||||
|
DWORD cnt, tot;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
if (NetLocalGroupGetMembers (wlogonserver, wgroup, 0, (LPBYTE *) &buf,
|
||||||
|
MAX_PREFERRED_LENGTH, &cnt, &tot, NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (DWORD bidx = 0; !ret && bidx < cnt; ++bidx)
|
||||||
|
if (EqualSid (usersid, buf[bidx].lgrmi0_sid))
|
||||||
|
ret = TRUE;
|
||||||
|
else
|
||||||
|
for (int glidx = 0; !ret && glidx < grp_list.count; ++glidx)
|
||||||
|
if (EqualSid (grp_list.sids[glidx], buf[bidx].lgrmi0_sid))
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
NetApiBufferFree (buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
get_user_local_groups (WCHAR *wlogonserver, const char *logonserver,
|
||||||
|
cygsidlist &grp_list, cygsid &usersid)
|
||||||
|
{
|
||||||
|
LPLOCALGROUP_INFO_0 buf;
|
||||||
|
DWORD cnt, tot;
|
||||||
|
NET_API_STATUS ret;
|
||||||
|
|
||||||
|
if ((ret = NetLocalGroupEnum (wlogonserver, 0, (LPBYTE *) &buf,
|
||||||
|
MAX_PREFERRED_LENGTH, &cnt, &tot, NULL)))
|
||||||
|
{
|
||||||
|
debug_printf ("%d = NetLocalGroupEnum ()", ret);
|
||||||
|
set_errno (ret);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < cnt; ++i)
|
||||||
|
if (is_group_member (wlogonserver, buf[i].lgrpi0_name, usersid, grp_list))
|
||||||
|
{
|
||||||
|
cygsid gsid;
|
||||||
|
char group[UNLEN + 1];
|
||||||
|
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
DWORD glen = UNLEN + 1;
|
||||||
|
DWORD dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
SID_NAME_USE use = SidTypeInvalid;
|
||||||
|
|
||||||
|
wcstombs (group, buf[i].lgrpi0_name, UNLEN + 1);
|
||||||
|
if (!LookupAccountName (NULL, group, gsid, &glen, domain, &dlen, &use))
|
||||||
|
{
|
||||||
|
glen = UNLEN + 1;
|
||||||
|
dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
if (!LookupAccountName (logonserver + 2, group,
|
||||||
|
gsid, &glen, domain, &dlen, &use))
|
||||||
|
debug_printf ("LookupAccountName(%s): %lu\n", group,
|
||||||
|
GetLastError ());
|
||||||
|
}
|
||||||
|
else if (!legal_sid_type (use))
|
||||||
|
{
|
||||||
|
strcat (strcpy (group, domain), "\\");
|
||||||
|
wcstombs (group + strlen (group), buf[i].lgrpi0_name,
|
||||||
|
UNLEN + 1 - strlen (group));
|
||||||
|
glen = UNLEN + 1;
|
||||||
|
dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
if (!LookupAccountName (NULL, group, gsid, &glen,
|
||||||
|
domain, &dlen, &use))
|
||||||
|
debug_printf ("LookupAccountName(%s): %lu\n", group,
|
||||||
|
GetLastError ());
|
||||||
|
}
|
||||||
|
if (legal_sid_type (use))
|
||||||
|
grp_list += gsid;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetApiBufferFree (buf);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
sid_in_token_groups (PTOKEN_GROUPS grps, cygsid &sid)
|
||||||
|
{
|
||||||
|
if (!grps)
|
||||||
|
return FALSE;
|
||||||
|
for (DWORD i = 0; i < grps->GroupCount; ++i)
|
||||||
|
if (sid == grps->Groups[i].Sid)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
get_user_primary_group (WCHAR *wlogonserver, const char *user,
|
||||||
|
cygsid &usersid, cygsid &pgrpsid)
|
||||||
|
{
|
||||||
|
LPUSER_INFO_3 buf;
|
||||||
|
WCHAR wuser[UNLEN + 1];
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
UCHAR count;
|
||||||
|
|
||||||
|
if (usersid == well_known_system_sid)
|
||||||
|
{
|
||||||
|
pgrpsid = well_known_system_sid;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbstowcs (wuser, user, UNLEN + 1);
|
||||||
|
if (NetUserGetInfo (wlogonserver, wuser, 3, (LPBYTE *) &buf))
|
||||||
|
return FALSE;
|
||||||
|
pgrpsid = usersid;
|
||||||
|
if (IsValidSid (pgrpsid) && (count = *GetSidSubAuthorityCount (pgrpsid)) > 1)
|
||||||
|
{
|
||||||
|
*GetSidSubAuthority (pgrpsid, count - 1) = buf->usri3_primary_group_id;
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
NetApiBufferFree (buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
get_group_sidlist (const char *logonserver, cygsidlist &grp_list,
|
||||||
|
cygsid &usersid, cygsid &pgrpsid,
|
||||||
|
PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos)
|
||||||
|
{
|
||||||
|
WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
char user[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
DWORD ulen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
DWORD dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
SID_NAME_USE use;
|
||||||
|
|
||||||
|
auth_pos = -1;
|
||||||
|
mbstowcs (wserver, logonserver, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
if (!LookupAccountSid (NULL, usersid, user, &ulen, domain, &dlen, &use))
|
||||||
|
{
|
||||||
|
debug_printf ("LookupAccountSid () %E");
|
||||||
|
__seterrno ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
grp_list += well_known_world_sid;
|
||||||
|
if (usersid == well_known_system_sid)
|
||||||
|
{
|
||||||
|
grp_list += well_known_system_sid;
|
||||||
|
grp_list += well_known_admin_sid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (my_grps)
|
||||||
|
{
|
||||||
|
if (sid_in_token_groups (my_grps, well_known_local_sid))
|
||||||
|
grp_list += well_known_local_sid;
|
||||||
|
if (sid_in_token_groups (my_grps, well_known_dialup_sid))
|
||||||
|
grp_list += well_known_dialup_sid;
|
||||||
|
if (sid_in_token_groups (my_grps, well_known_network_sid))
|
||||||
|
grp_list += well_known_network_sid;
|
||||||
|
if (sid_in_token_groups (my_grps, well_known_batch_sid))
|
||||||
|
grp_list += well_known_batch_sid;
|
||||||
|
if (sid_in_token_groups (my_grps, well_known_interactive_sid))
|
||||||
|
grp_list += well_known_interactive_sid;
|
||||||
|
if (sid_in_token_groups (my_grps, well_known_service_sid))
|
||||||
|
grp_list += well_known_service_sid;
|
||||||
|
grp_list += well_known_authenticated_users_sid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grp_list += well_known_local_sid;
|
||||||
|
grp_list += well_known_interactive_sid;
|
||||||
|
grp_list += well_known_authenticated_users_sid;
|
||||||
|
}
|
||||||
|
if (auth_luid.QuadPart != 999) /* != SYSTEM_LUID */
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
__small_sprintf (buf, "S-1-5-5-%u-%u", auth_luid.HighPart,
|
||||||
|
auth_luid.LowPart);
|
||||||
|
grp_list += buf;
|
||||||
|
auth_pos = grp_list.count - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pgrpsid)
|
||||||
|
get_user_primary_group (wserver, user, usersid, pgrpsid);
|
||||||
|
if (!get_user_groups (wserver, grp_list, user) ||
|
||||||
|
!get_user_local_groups (wserver, logonserver, grp_list, usersid))
|
||||||
|
return FALSE;
|
||||||
|
if (!grp_list.contains (pgrpsid))
|
||||||
|
grp_list += pgrpsid;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sys_privs[] = {
|
||||||
|
SE_TCB_NAME,
|
||||||
|
SE_ASSIGNPRIMARYTOKEN_NAME,
|
||||||
|
SE_CREATE_TOKEN_NAME,
|
||||||
|
SE_CHANGE_NOTIFY_NAME,
|
||||||
|
SE_SECURITY_NAME,
|
||||||
|
SE_BACKUP_NAME,
|
||||||
|
SE_RESTORE_NAME,
|
||||||
|
SE_SYSTEMTIME_NAME,
|
||||||
|
SE_SHUTDOWN_NAME,
|
||||||
|
SE_REMOTE_SHUTDOWN_NAME,
|
||||||
|
SE_TAKE_OWNERSHIP_NAME,
|
||||||
|
SE_DEBUG_NAME,
|
||||||
|
SE_SYSTEM_ENVIRONMENT_NAME,
|
||||||
|
SE_SYSTEM_PROFILE_NAME,
|
||||||
|
SE_PROF_SINGLE_PROCESS_NAME,
|
||||||
|
SE_INC_BASE_PRIORITY_NAME,
|
||||||
|
SE_LOAD_DRIVER_NAME,
|
||||||
|
SE_CREATE_PAGEFILE_NAME,
|
||||||
|
SE_INCREASE_QUOTA_NAME
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SYSTEM_PERMISSION_COUNT (sizeof sys_privs / sizeof (const char *))
|
||||||
|
|
||||||
|
PTOKEN_PRIVILEGES
|
||||||
|
get_system_priv_list (cygsidlist &grp_list)
|
||||||
|
{
|
||||||
|
LUID priv;
|
||||||
|
PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (sizeof (ULONG) +
|
||||||
|
20 * sizeof (LUID_AND_ATTRIBUTES));
|
||||||
|
if (!privs)
|
||||||
|
{
|
||||||
|
debug_printf ("malloc (system_privs) failed.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
privs->PrivilegeCount = 0;
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < SYSTEM_PERMISSION_COUNT; ++i)
|
||||||
|
if (LookupPrivilegeValue (NULL, sys_privs[i], &priv))
|
||||||
|
{
|
||||||
|
privs->Privileges[privs->PrivilegeCount].Luid = priv;
|
||||||
|
privs->Privileges[privs->PrivilegeCount].Attributes =
|
||||||
|
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
|
||||||
|
++privs->PrivilegeCount;
|
||||||
|
}
|
||||||
|
return privs;
|
||||||
|
}
|
||||||
|
|
||||||
|
PTOKEN_PRIVILEGES
|
||||||
|
get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
|
||||||
|
{
|
||||||
|
PLSA_UNICODE_STRING privstrs;
|
||||||
|
ULONG cnt;
|
||||||
|
PTOKEN_PRIVILEGES privs = NULL;
|
||||||
|
NTSTATUS ret;
|
||||||
|
char buf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
|
||||||
|
if (usersid == well_known_system_sid)
|
||||||
|
return get_system_priv_list (grp_list);
|
||||||
|
|
||||||
|
for (int grp = -1; grp < grp_list.count; ++grp)
|
||||||
|
{
|
||||||
|
if (grp == -1)
|
||||||
|
{
|
||||||
|
if ((ret = LsaEnumerateAccountRights (lsa, usersid, &privstrs, &cnt))
|
||||||
|
!= STATUS_SUCCESS)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ((ret = LsaEnumerateAccountRights (lsa, grp_list.sids[grp],
|
||||||
|
&privstrs, &cnt))
|
||||||
|
!= STATUS_SUCCESS)
|
||||||
|
continue;
|
||||||
|
for (ULONG i = 0; i < cnt; ++i)
|
||||||
|
{
|
||||||
|
LUID priv;
|
||||||
|
PTOKEN_PRIVILEGES tmp;
|
||||||
|
DWORD tmp_count;
|
||||||
|
|
||||||
|
wcstombs (buf, privstrs[i].Buffer, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
if (!LookupPrivilegeValue (NULL, buf, &priv))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (DWORD p = 0; privs && p < privs->PrivilegeCount; ++p)
|
||||||
|
if (!memcmp (&priv, &privs->Privileges[p].Luid, sizeof (LUID)))
|
||||||
|
goto next_account_right;
|
||||||
|
|
||||||
|
tmp_count = privs ? privs->PrivilegeCount : 0;
|
||||||
|
tmp = (PTOKEN_PRIVILEGES)
|
||||||
|
realloc (privs, sizeof (ULONG) +
|
||||||
|
(tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES));
|
||||||
|
if (!tmp)
|
||||||
|
{
|
||||||
|
if (privs)
|
||||||
|
free (privs);
|
||||||
|
LsaFreeMemory (privstrs);
|
||||||
|
debug_printf ("realloc (privs) failed.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tmp->PrivilegeCount = tmp_count;
|
||||||
|
privs = tmp;
|
||||||
|
privs->Privileges[privs->PrivilegeCount].Luid = priv;
|
||||||
|
privs->Privileges[privs->PrivilegeCount].Attributes =
|
||||||
|
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
|
||||||
|
++privs->PrivilegeCount;
|
||||||
|
|
||||||
|
next_account_right:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
LsaFreeMemory (privstrs);
|
||||||
|
}
|
||||||
|
return privs;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define token_acl_size (sizeof (ACL) + \
|
||||||
|
2 * (sizeof (ACCESS_ALLOWED_ACE) + MAX_SID_LEN))
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
get_dacl (PACL acl, cygsid usersid, cygsidlist &grp_list)
|
||||||
|
{
|
||||||
|
if (!InitializeAcl(acl, token_acl_size, ACL_REVISION))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (grp_list.contains (well_known_admin_sid))
|
||||||
|
{
|
||||||
|
if (!AddAccessAllowedAce(acl, ACL_REVISION, GENERIC_ALL,
|
||||||
|
well_known_admin_sid))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!AddAccessAllowedAce(acl, ACL_REVISION, GENERIC_ALL, usersid))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!AddAccessAllowedAce(acl, ACL_REVISION, GENERIC_ALL,
|
||||||
|
well_known_system_sid))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE
|
||||||
|
create_token (cygsid &usersid, cygsid &pgrpsid)
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
LSA_HANDLE lsa = NULL;
|
||||||
|
char logonserver[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
int old_priv_state;
|
||||||
|
|
||||||
|
cygsidlist grpsids;
|
||||||
|
|
||||||
|
SECURITY_QUALITY_OF_SERVICE sqos =
|
||||||
|
{ sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE };
|
||||||
|
OBJECT_ATTRIBUTES oa =
|
||||||
|
{ sizeof oa, 0, 0, 0, 0, &sqos };
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, TRUE };
|
||||||
|
LUID auth_luid = SYSTEM_LUID;
|
||||||
|
LARGE_INTEGER exp = { 0x7fffffffffffffffLL } ;
|
||||||
|
|
||||||
|
TOKEN_USER user;
|
||||||
|
PTOKEN_GROUPS grps = NULL;
|
||||||
|
PTOKEN_PRIVILEGES privs = NULL;
|
||||||
|
TOKEN_OWNER owner;
|
||||||
|
TOKEN_PRIMARY_GROUP pgrp;
|
||||||
|
char acl_buf[token_acl_size];
|
||||||
|
TOKEN_DEFAULT_DACL dacl;
|
||||||
|
TOKEN_SOURCE source;
|
||||||
|
TOKEN_STATISTICS stats;
|
||||||
|
memcpy(source.SourceName, "Cygwin.1", 8);
|
||||||
|
source.SourceIdentifier.HighPart = 0;
|
||||||
|
source.SourceIdentifier.LowPart = 0x0101;
|
||||||
|
|
||||||
|
HANDLE token;
|
||||||
|
HANDLE primary_token = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
HANDLE my_token = INVALID_HANDLE_VALUE;
|
||||||
|
PTOKEN_GROUPS my_grps = NULL;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
/* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */
|
||||||
|
if ((old_priv_state = set_process_privilege (SE_CREATE_TOKEN_NAME)) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Open policy object. */
|
||||||
|
if ((lsa = open_local_policy ()) == INVALID_HANDLE_VALUE)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Get logon server. */
|
||||||
|
if (!get_logon_server (lsa, logonserver))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* User, owner, primary group. */
|
||||||
|
user.User.Sid = usersid;
|
||||||
|
user.User.Attributes = 0;
|
||||||
|
owner.Owner = usersid;
|
||||||
|
|
||||||
|
/* Retrieve authentication id and group list from own process. */
|
||||||
|
if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &my_token))
|
||||||
|
debug_printf ("OpenProcessToken(my_token): %E\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Switching user context to SYSTEM doesn't inherit the authentication
|
||||||
|
id of the user account running current process. */
|
||||||
|
if (usersid != well_known_system_sid)
|
||||||
|
if (!GetTokenInformation (my_token, TokenStatistics,
|
||||||
|
&stats, sizeof stats, &size))
|
||||||
|
debug_printf ("GetTokenInformation(my_token, TokenStatistics): %E\n");
|
||||||
|
else
|
||||||
|
auth_luid = stats.AuthenticationId;
|
||||||
|
|
||||||
|
/* Retrieving current processes group list to be able to inherit
|
||||||
|
some important well known group sids. */
|
||||||
|
if (!GetTokenInformation (my_token, TokenGroups, NULL, 0, &size) &&
|
||||||
|
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n");
|
||||||
|
else if (!(my_grps = (PTOKEN_GROUPS) malloc (size)))
|
||||||
|
debug_printf ("malloc (my_grps) failed.");
|
||||||
|
else if (!GetTokenInformation (my_token, TokenGroups, my_grps,
|
||||||
|
size, &size))
|
||||||
|
{
|
||||||
|
debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n");
|
||||||
|
free (my_grps);
|
||||||
|
my_grps = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create list of groups, the user is member in. */
|
||||||
|
int auth_pos;
|
||||||
|
if (!get_group_sidlist (logonserver, grpsids, usersid, pgrpsid,
|
||||||
|
my_grps, auth_luid, auth_pos))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Primary group. */
|
||||||
|
pgrp.PrimaryGroup = pgrpsid;
|
||||||
|
|
||||||
|
/* Create a TOKEN_GROUPS list from the above retrieved list of sids. */
|
||||||
|
char grps_buf[sizeof (ULONG) + grpsids.count * sizeof (SID_AND_ATTRIBUTES)];
|
||||||
|
grps = (PTOKEN_GROUPS) grps_buf;
|
||||||
|
grps->GroupCount = grpsids.count;
|
||||||
|
for (DWORD i = 0; i < grps->GroupCount; ++i)
|
||||||
|
{
|
||||||
|
grps->Groups[i].Sid = grpsids.sids[i];
|
||||||
|
grps->Groups[i].Attributes = SE_GROUP_MANDATORY |
|
||||||
|
SE_GROUP_ENABLED_BY_DEFAULT |
|
||||||
|
SE_GROUP_ENABLED;
|
||||||
|
if (auth_pos >= 0 && i == (DWORD) auth_pos)
|
||||||
|
grps->Groups[i].Attributes |= SE_GROUP_LOGON_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve list of privileges of that user. */
|
||||||
|
if (!(privs = get_priv_list (lsa, usersid, grpsids)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Create default dacl. */
|
||||||
|
if (!get_dacl ((PACL) acl_buf, usersid, grpsids))
|
||||||
|
goto out;
|
||||||
|
dacl.DefaultDacl = (PACL) acl_buf;
|
||||||
|
|
||||||
|
/* Let's be heroic... */
|
||||||
|
ret = NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa, TokenImpersonation,
|
||||||
|
&auth_luid, &exp, &user, grps, privs, &owner, &pgrp,
|
||||||
|
&dacl, &source);
|
||||||
|
if (ret)
|
||||||
|
set_errno (RtlNtStatusToDosError (ret));
|
||||||
|
else if (GetLastError () == ERROR_PROC_NOT_FOUND)
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
debug_printf ("Loading NtCreateToken failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to primary token. */
|
||||||
|
if (!DuplicateTokenEx (token, TOKEN_ALL_ACCESS, &sa,
|
||||||
|
SecurityImpersonation, TokenPrimary,
|
||||||
|
&primary_token))
|
||||||
|
__seterrno ();
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (old_priv_state >= 0)
|
||||||
|
set_process_privilege (SE_CREATE_TOKEN_NAME, old_priv_state);
|
||||||
|
if (token != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle (token);
|
||||||
|
if (privs)
|
||||||
|
free (privs);
|
||||||
|
if (my_grps)
|
||||||
|
free (my_grps);
|
||||||
|
close_local_policy (lsa);
|
||||||
|
|
||||||
|
debug_printf ("%d = create_token ()", primary_token);
|
||||||
|
return primary_token;
|
||||||
|
}
|
||||||
|
|
||||||
int subauth_id = 255;
|
int subauth_id = 255;
|
||||||
|
|
||||||
HANDLE
|
HANDLE
|
||||||
@ -177,12 +813,16 @@ subauth (struct passwd *pw)
|
|||||||
TOKEN_SOURCE ts;
|
TOKEN_SOURCE ts;
|
||||||
PMSV1_0_LM20_LOGON_PROFILE profile;
|
PMSV1_0_LM20_LOGON_PROFILE profile;
|
||||||
LUID luid;
|
LUID luid;
|
||||||
HANDLE user_token;
|
|
||||||
QUOTA_LIMITS quota;
|
QUOTA_LIMITS quota;
|
||||||
char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
char nt_user[UNLEN + 1];
|
char nt_user[UNLEN + 1];
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, TRUE };
|
||||||
|
HANDLE user_token = INVALID_HANDLE_VALUE;
|
||||||
|
HANDLE primary_token = INVALID_HANDLE_VALUE;
|
||||||
|
int old_tcb_state;
|
||||||
|
|
||||||
set_process_privilege(SE_TCB_NAME);
|
if ((old_tcb_state = set_process_privilege(SE_TCB_NAME)) < 0)
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
/* Register as logon process. */
|
/* Register as logon process. */
|
||||||
str2lsa (name, "Cygwin");
|
str2lsa (name, "Cygwin");
|
||||||
@ -192,12 +832,12 @@ subauth (struct passwd *pw)
|
|||||||
{
|
{
|
||||||
debug_printf ("LsaRegisterLogonProcess: %d", ret);
|
debug_printf ("LsaRegisterLogonProcess: %d", ret);
|
||||||
set_errno (LsaNtStatusToWinError(ret));
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
return INVALID_HANDLE_VALUE;
|
goto out;
|
||||||
}
|
}
|
||||||
else if (GetLastError () == ERROR_PROC_NOT_FOUND)
|
else if (GetLastError () == ERROR_PROC_NOT_FOUND)
|
||||||
{
|
{
|
||||||
debug_printf ("Couldn't load Secur32.dll");
|
debug_printf ("Couldn't load Secur32.dll");
|
||||||
return INVALID_HANDLE_VALUE;
|
goto out;
|
||||||
}
|
}
|
||||||
/* Get handle to MSV1_0 package. */
|
/* Get handle to MSV1_0 package. */
|
||||||
str2lsa (name, MSV1_0_PACKAGE_NAME);
|
str2lsa (name, MSV1_0_PACKAGE_NAME);
|
||||||
@ -207,7 +847,7 @@ subauth (struct passwd *pw)
|
|||||||
debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
|
debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
|
||||||
set_errno (LsaNtStatusToWinError(ret));
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
LsaDeregisterLogonProcess(lsa_hdl);
|
LsaDeregisterLogonProcess(lsa_hdl);
|
||||||
return INVALID_HANDLE_VALUE;
|
goto out;
|
||||||
}
|
}
|
||||||
/* Create origin. */
|
/* Create origin. */
|
||||||
str2buf2lsa (origin.str, origin.buf, "Cygwin");
|
str2buf2lsa (origin.str, origin.buf, "Cygwin");
|
||||||
@ -236,20 +876,19 @@ subauth (struct passwd *pw)
|
|||||||
debug_printf ("LsaLogonUser: %d", ret);
|
debug_printf ("LsaLogonUser: %d", ret);
|
||||||
set_errno (LsaNtStatusToWinError(ret));
|
set_errno (LsaNtStatusToWinError(ret));
|
||||||
LsaDeregisterLogonProcess(lsa_hdl);
|
LsaDeregisterLogonProcess(lsa_hdl);
|
||||||
return INVALID_HANDLE_VALUE;
|
goto out;
|
||||||
}
|
}
|
||||||
LsaFreeReturnBuffer(profile);
|
LsaFreeReturnBuffer(profile);
|
||||||
/* Convert to primary token. */
|
/* Convert to primary token. */
|
||||||
SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, TRUE };
|
|
||||||
HANDLE primary_token;
|
|
||||||
if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa,
|
if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa,
|
||||||
SecurityImpersonation, TokenPrimary,
|
SecurityImpersonation, TokenPrimary,
|
||||||
&primary_token))
|
&primary_token))
|
||||||
{
|
__seterrno ();
|
||||||
CloseHandle (user_token);
|
|
||||||
return INVALID_HANDLE_VALUE;
|
out:
|
||||||
}
|
set_process_privilege(SE_TCB_NAME, old_tcb_state);
|
||||||
CloseHandle (user_token);
|
if (user_token != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle (user_token);
|
||||||
return primary_token;
|
return primary_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,18 @@ class cygsid {
|
|||||||
const PSID getfromstr (const char *nsidstr);
|
const PSID getfromstr (const char *nsidstr);
|
||||||
PSID get_sid (DWORD s, DWORD cnt, DWORD *r);
|
PSID get_sid (DWORD s, DWORD cnt, DWORD *r);
|
||||||
|
|
||||||
|
inline const PSID assign (const PSID nsid)
|
||||||
|
{
|
||||||
|
if (!nsid)
|
||||||
|
psid = NO_SID;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psid = (PSID) sbuf;
|
||||||
|
CopySid (MAX_SID_LEN, psid, nsid);
|
||||||
|
}
|
||||||
|
return psid;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline cygsid () : psid ((PSID) sbuf) {}
|
inline cygsid () : psid ((PSID) sbuf) {}
|
||||||
inline cygsid (const PSID nsid) { *this = nsid; }
|
inline cygsid (const PSID nsid) { *this = nsid; }
|
||||||
@ -40,19 +52,12 @@ public:
|
|||||||
inline int get_uid () { return get_id (FALSE); }
|
inline int get_uid () { return get_id (FALSE); }
|
||||||
inline int get_gid () { return get_id (TRUE); }
|
inline int get_gid () { return get_id (TRUE); }
|
||||||
|
|
||||||
char *string (char *nsidstr);
|
char *string (char *nsidstr) const;
|
||||||
|
|
||||||
|
inline const PSID operator= (cygsid &nsid)
|
||||||
|
{ return assign (nsid); }
|
||||||
inline const PSID operator= (const PSID nsid)
|
inline const PSID operator= (const PSID nsid)
|
||||||
{
|
{ return assign (nsid); }
|
||||||
if (!nsid)
|
|
||||||
psid = NULL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
psid = (PSID) sbuf;
|
|
||||||
CopySid (MAX_SID_LEN, psid, nsid);
|
|
||||||
}
|
|
||||||
return psid;
|
|
||||||
}
|
|
||||||
inline const PSID operator= (const char *nsidstr)
|
inline const PSID operator= (const char *nsidstr)
|
||||||
{ return getfromstr (nsidstr); }
|
{ return getfromstr (nsidstr); }
|
||||||
|
|
||||||
@ -73,12 +78,77 @@ public:
|
|||||||
{ return !(*this == nsidstr); }
|
{ return !(*this == nsidstr); }
|
||||||
|
|
||||||
inline operator const PSID () { return psid; }
|
inline operator const PSID () { return psid; }
|
||||||
|
|
||||||
|
void debug_print (const char *prefix = NULL) const
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
debug_printf ("%s %s", prefix ?: "", string (buf) ?: "NULL");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class cygsidlist {
|
||||||
|
public:
|
||||||
|
int count;
|
||||||
|
cygsid *sids;
|
||||||
|
|
||||||
|
cygsidlist () : count (0), sids (NULL) {}
|
||||||
|
~cygsidlist () { delete [] sids; }
|
||||||
|
|
||||||
|
BOOL add (cygsid &nsi)
|
||||||
|
{
|
||||||
|
cygsid *tmp = new cygsid [count + 1];
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
tmp[i] = sids[i];
|
||||||
|
delete [] sids;
|
||||||
|
sids = tmp;
|
||||||
|
sids[count++] = nsi;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
BOOL add (const PSID nsid) { return add (nsid); }
|
||||||
|
BOOL add (const char *sidstr)
|
||||||
|
{ cygsid nsi (sidstr); return add (nsi); }
|
||||||
|
|
||||||
|
BOOL operator+= (cygsid &si) { return add (si); }
|
||||||
|
BOOL operator+= (const char *sidstr) { return add (sidstr); }
|
||||||
|
|
||||||
|
BOOL contains (cygsid &sid) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
if (sids[i] == sid)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
void debug_print (const char *prefix = NULL) const
|
||||||
|
{
|
||||||
|
debug_printf ("-- begin sidlist ---");
|
||||||
|
if (!count)
|
||||||
|
debug_printf ("No elements");
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
sids[i].debug_print (prefix);
|
||||||
|
debug_printf ("-- ende sidlist ---");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cygsid well_known_admin_sid;
|
|
||||||
extern cygsid well_known_system_sid;
|
|
||||||
extern cygsid well_known_creator_owner_sid;
|
|
||||||
extern cygsid well_known_world_sid;
|
extern cygsid well_known_world_sid;
|
||||||
|
extern cygsid well_known_local_sid;
|
||||||
|
extern cygsid well_known_creator_owner_sid;
|
||||||
|
extern cygsid well_known_dialup_sid;
|
||||||
|
extern cygsid well_known_network_sid;
|
||||||
|
extern cygsid well_known_batch_sid;
|
||||||
|
extern cygsid well_known_interactive_sid;
|
||||||
|
extern cygsid well_known_service_sid;
|
||||||
|
extern cygsid well_known_authenticated_users_sid;
|
||||||
|
extern cygsid well_known_system_sid;
|
||||||
|
extern cygsid well_known_admin_sid;
|
||||||
|
|
||||||
|
inline BOOL
|
||||||
|
legal_sid_type (SID_NAME_USE type)
|
||||||
|
{
|
||||||
|
return type == SidTypeUser || type == SidTypeGroup
|
||||||
|
|| type == SidTypeAlias || type == SidTypeWellKnownGroup;
|
||||||
|
}
|
||||||
|
|
||||||
extern BOOL allow_ntsec;
|
extern BOOL allow_ntsec;
|
||||||
extern BOOL allow_smbntsec;
|
extern BOOL allow_smbntsec;
|
||||||
@ -102,6 +172,13 @@ BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PS
|
|||||||
|
|
||||||
/* Try a subauthentication. */
|
/* Try a subauthentication. */
|
||||||
HANDLE subauth (struct passwd *pw);
|
HANDLE subauth (struct passwd *pw);
|
||||||
|
/* Try creating a token directly. */
|
||||||
|
HANDLE create_token (cygsid &usersid, cygsid &pgrpsid);
|
||||||
|
|
||||||
|
/* Extract U-domain\user field from passwd entry. */
|
||||||
|
void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);
|
||||||
|
/* Get default logonserver and domain for this box. */
|
||||||
|
BOOL get_logon_server_and_user_domain (char *logonserver, char *domain);
|
||||||
|
|
||||||
/* sec_helper.cc: Security helper functions. */
|
/* sec_helper.cc: Security helper functions. */
|
||||||
BOOL __stdcall is_grp_member (uid_t uid, gid_t gid);
|
BOOL __stdcall is_grp_member (uid_t uid, gid_t gid);
|
||||||
|
@ -622,10 +622,9 @@ skip_arg_parsing:
|
|||||||
: &sec_all_nih;
|
: &sec_all_nih;
|
||||||
|
|
||||||
/* Remove impersonation */
|
/* Remove impersonation */
|
||||||
uid_t uid = geteuid ();
|
|
||||||
if (cygheap->user.impersonated
|
if (cygheap->user.impersonated
|
||||||
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
&& cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
seteuid (cygheap->user.orig_uid);
|
RevertToSelf ();
|
||||||
|
|
||||||
/* Load users registry hive. */
|
/* Load users registry hive. */
|
||||||
load_registry_hive (sid);
|
load_registry_hive (sid);
|
||||||
@ -664,7 +663,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;
|
||||||
|
@ -1954,109 +1954,156 @@ seteuid (uid_t uid)
|
|||||||
sigframe thisframe (mainthread);
|
sigframe thisframe (mainthread);
|
||||||
if (os_being_run == winNT)
|
if (os_being_run == winNT)
|
||||||
{
|
{
|
||||||
if (uid != (uid_t) -1)
|
if (uid == (uid_t) -1 || uid == myself->uid)
|
||||||
{
|
{
|
||||||
struct passwd *pw_new = getpwuid (uid);
|
debug_printf ("new euid == current euid, nothing happens");
|
||||||
if (!pw_new)
|
return 0;
|
||||||
|
}
|
||||||
|
struct passwd *pw_new = getpwuid (uid);
|
||||||
|
if (!pw_new)
|
||||||
|
{
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
cygsid usersid, pgrpsid, tok_usersid, tok_pgrpsid;
|
||||||
|
DWORD siz;
|
||||||
|
HANDLE sav_token = INVALID_HANDLE_VALUE;
|
||||||
|
BOOL sav_impersonation;
|
||||||
|
BOOL explicitely_created_token = FALSE;
|
||||||
|
|
||||||
|
struct group *gr = getgrgid (myself->gid);
|
||||||
|
debug_printf ("myself->gid: %d, gr: %d", myself->gid, gr);
|
||||||
|
|
||||||
|
usersid.getfrompw (pw_new);
|
||||||
|
pgrpsid.getfromgr (gr);
|
||||||
|
|
||||||
|
/* Check if new user == user of impersonation token and
|
||||||
|
- if available - new pgrp == pgrp of impersonation token. */
|
||||||
|
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
if (!GetTokenInformation (cygheap->user.token, TokenUser,
|
||||||
return -1;
|
&tok_usersid, sizeof tok_usersid, &siz))
|
||||||
|
{
|
||||||
|
debug_printf ("GetTokenInformation(): %E");
|
||||||
|
tok_usersid = NO_SID;
|
||||||
|
}
|
||||||
|
if (!GetTokenInformation (cygheap->user.token, TokenPrimaryGroup,
|
||||||
|
&tok_pgrpsid, sizeof tok_pgrpsid, &siz))
|
||||||
|
{
|
||||||
|
debug_printf ("GetTokenInformation(): %E");
|
||||||
|
tok_pgrpsid = NO_SID;
|
||||||
|
}
|
||||||
|
if ((usersid && tok_usersid && usersid != tok_usersid) ||
|
||||||
|
(pgrpsid && tok_pgrpsid && pgrpsid != tok_pgrpsid))
|
||||||
|
{
|
||||||
|
/* If not, RevertToSelf and close old token. */
|
||||||
|
debug_printf ("tsid != usersid");
|
||||||
|
RevertToSelf ();
|
||||||
|
sav_token = cygheap->user.token;
|
||||||
|
sav_impersonation = cygheap->user.impersonated;
|
||||||
|
cygheap->user.token = INVALID_HANDLE_VALUE;
|
||||||
|
cygheap->user.impersonated = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid != myself->uid)
|
/* If no impersonation token is available, try to
|
||||||
|
authenticate using NtCreateToken() or subauthentication. */
|
||||||
|
if (cygheap->user.token == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (uid == cygheap->user.orig_uid)
|
HANDLE ptok = INVALID_HANDLE_VALUE;
|
||||||
{
|
|
||||||
debug_printf ("RevertToSelf () (uid == orig_uid, token=%d)",
|
ptok = create_token (usersid, pgrpsid);
|
||||||
cygheap->user.token);
|
if (ptok != INVALID_HANDLE_VALUE)
|
||||||
RevertToSelf ();
|
explicitely_created_token = TRUE;
|
||||||
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
|
||||||
cygheap->user.impersonated = FALSE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cygsid tsid, psid, gsid;
|
/* create_token failed. Try subauthentication. */
|
||||||
DWORD siz;
|
debug_printf ("create token failed, try subauthentication.");
|
||||||
|
ptok = subauth (pw_new);
|
||||||
/* Check if new user == user of impersonation token. */
|
}
|
||||||
if (cygheap->user.token != INVALID_HANDLE_VALUE)
|
if (ptok != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
cygwin_set_impersonation_token (ptok);
|
||||||
|
/* If sav_token was internally created, destroy it. */
|
||||||
|
if (sav_token != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (!GetTokenInformation (cygheap->user.token, TokenUser,
|
TOKEN_SOURCE ts;
|
||||||
&tsid, sizeof tsid, &siz))
|
if (!GetTokenInformation (sav_token, TokenSource,
|
||||||
|
&ts, sizeof ts, &siz))
|
||||||
debug_printf ("GetTokenInformation(): %E");
|
debug_printf ("GetTokenInformation(): %E");
|
||||||
else if (psid.getfrompw (pw_new) && tsid != psid)
|
else if (!memcmp (ts.SourceName, "Cygwin.1", 8))
|
||||||
{
|
CloseHandle (sav_token);
|
||||||
/* If not, RevertToSelf and close old token. */
|
|
||||||
char tstr[256], pstr[256];
|
|
||||||
debug_printf ("tsid (%s) != psid (%s)",
|
|
||||||
tsid.string (tstr), psid.string (pstr));
|
|
||||||
RevertToSelf ();
|
|
||||||
cygwin_set_impersonation_token (INVALID_HANDLE_VALUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* If no impersonation token is available, try to
|
}
|
||||||
authenticate using subauthentication. */
|
else if (sav_token != INVALID_HANDLE_VALUE)
|
||||||
if (cygheap->user.token == INVALID_HANDLE_VALUE)
|
cygheap->user.token = sav_token;
|
||||||
{
|
}
|
||||||
HANDLE ptok = subauth (pw_new);
|
/* If no impersonation is active but an impersonation
|
||||||
if (ptok != INVALID_HANDLE_VALUE)
|
token is available, try to impersonate. */
|
||||||
cygwin_set_impersonation_token (ptok);
|
if (cygheap->user.token != INVALID_HANDLE_VALUE &&
|
||||||
else
|
!cygheap->user.impersonated)
|
||||||
cygheap->user.impersonated = TRUE;
|
{
|
||||||
}
|
debug_printf ("Impersonate (uid == %d)", uid);
|
||||||
/* If no impersonation is active but an impersonation
|
RevertToSelf ();
|
||||||
token is available, try to impersonate. */
|
|
||||||
if (cygheap->user.token != INVALID_HANDLE_VALUE &&
|
|
||||||
!cygheap->user.impersonated)
|
|
||||||
{
|
|
||||||
debug_printf ("Impersonate (uid == %d)", uid);
|
|
||||||
RevertToSelf ();
|
|
||||||
|
|
||||||
struct group *gr;
|
/* If the token was explicitely created, all information has
|
||||||
|
already been set correctly. */
|
||||||
|
if (!explicitely_created_token)
|
||||||
|
{
|
||||||
|
/* Try setting owner to same value as user. */
|
||||||
|
if (usersid &&
|
||||||
|
!SetTokenInformation (cygheap->user.token, TokenOwner,
|
||||||
|
&usersid, sizeof usersid))
|
||||||
|
debug_printf ("SetTokenInformation(user.token, "
|
||||||
|
"TokenOwner): %E");
|
||||||
|
/* Try setting primary group in token to current group
|
||||||
|
if token not explicitely created. */
|
||||||
|
if (pgrpsid &&
|
||||||
|
!SetTokenInformation (cygheap->user.token,
|
||||||
|
TokenPrimaryGroup,
|
||||||
|
&pgrpsid, sizeof pgrpsid))
|
||||||
|
debug_printf ("SetTokenInformation(user.token, "
|
||||||
|
"TokenPrimaryGroup): %E");
|
||||||
|
|
||||||
/* 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)) &&
|
|
||||||
gsid.getfromgr (gr) &&
|
|
||||||
!SetTokenInformation (cygheap->user.token,
|
|
||||||
TokenPrimaryGroup,
|
|
||||||
&gsid, sizeof gsid))
|
|
||||||
debug_printf ("SetTokenInformation(user.token, "
|
|
||||||
"TokenPrimaryGroup): %E");
|
|
||||||
|
|
||||||
/* Now try to impersonate. */
|
/* Now try to impersonate. */
|
||||||
if (!ImpersonateLoggedOnUser (cygheap->user.token))
|
if (!ImpersonateLoggedOnUser (cygheap->user.token))
|
||||||
system_printf ("Impersonating (%d) in set(e)uid "
|
system_printf ("Impersonating (%d) in set(e)uid failed: %E",
|
||||||
"failed: %E", cygheap->user.token);
|
cygheap->user.token);
|
||||||
else
|
else
|
||||||
cygheap->user.impersonated = TRUE;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
set_errno (ENOSYS);
|
set_errno (ENOSYS);
|
||||||
|
@ -38,12 +38,15 @@ internal_getlogin (cygheap_user &user)
|
|||||||
user.set_name ("unknown");
|
user.set_name ("unknown");
|
||||||
else
|
else
|
||||||
user.set_name (username);
|
user.set_name (username);
|
||||||
|
debug_printf ("GetUserName() = %s", user.name ());
|
||||||
|
|
||||||
if (os_being_run == winNT)
|
if (os_being_run == winNT)
|
||||||
{
|
{
|
||||||
LPWKSTA_USER_INFO_1 wui;
|
LPWKSTA_USER_INFO_1 wui;
|
||||||
char buf[MAX_PATH], *env;
|
NET_API_STATUS ret;
|
||||||
char *un = NULL;
|
char buf[512];
|
||||||
|
char dom[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
char *env, *un = NULL;
|
||||||
|
|
||||||
/* First trying to get logon info from environment */
|
/* First trying to get logon info from environment */
|
||||||
if ((env = getenv ("USERNAME")) != NULL)
|
if ((env = getenv ("USERNAME")) != NULL)
|
||||||
@ -58,10 +61,8 @@ internal_getlogin (cygheap_user &user)
|
|||||||
debug_printf ("Domain: %s, Logon Server: %s",
|
debug_printf ("Domain: %s, Logon Server: %s",
|
||||||
user.domain (), user.logsrv ());
|
user.domain (), user.logsrv ());
|
||||||
/* If that failed, try to get that info from NetBIOS */
|
/* If that failed, try to get that info from NetBIOS */
|
||||||
else if (!NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&wui))
|
else if (!(ret = NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&wui)))
|
||||||
{
|
{
|
||||||
char buf[512]; /* Bigger than each of the below defines. */
|
|
||||||
|
|
||||||
sys_wcstombs (buf, wui->wkui1_username, UNLEN + 1);
|
sys_wcstombs (buf, wui->wkui1_username, UNLEN + 1);
|
||||||
user.set_name (buf);
|
user.set_name (buf);
|
||||||
sys_wcstombs (buf, wui->wkui1_logon_server,
|
sys_wcstombs (buf, wui->wkui1_logon_server,
|
||||||
@ -112,6 +113,22 @@ internal_getlogin (cygheap_user &user)
|
|||||||
user.domain (), user.logsrv (), user.name ());
|
user.domain (), user.logsrv (), user.name ());
|
||||||
NetApiBufferFree (wui);
|
NetApiBufferFree (wui);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If `NetWkstaUserGetInfo' failed, try to get default values known
|
||||||
|
by local policy object.*/
|
||||||
|
debug_printf ("NetWkstaUserGetInfo() Err %d", ret);
|
||||||
|
|
||||||
|
if (get_logon_server_and_user_domain (buf, dom))
|
||||||
|
{
|
||||||
|
user.set_logsrv (buf + 2);
|
||||||
|
user.set_domain (dom);
|
||||||
|
setenv ("LOGONSERVER", buf, 1);
|
||||||
|
setenv ("USERDOMAIN", dom, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
debug_printf ("get_logon_server_and_user_domain() failed");
|
||||||
|
}
|
||||||
if (allow_ntsec)
|
if (allow_ntsec)
|
||||||
{
|
{
|
||||||
HANDLE ptok = user.token; /* Which is INVALID_HANDLE_VALUE if no
|
HANDLE ptok = user.token; /* Which is INVALID_HANDLE_VALUE if no
|
||||||
@ -147,7 +164,7 @@ internal_getlogin (cygheap_user &user)
|
|||||||
/* If that fails, too, as a last resort try to get the SID from
|
/* If that fails, too, as a last resort try to get the SID from
|
||||||
the logon server. */
|
the logon server. */
|
||||||
if (!ret && !(ret = lookup_name (user.name (), user.logsrv (),
|
if (!ret && !(ret = lookup_name (user.name (), user.logsrv (),
|
||||||
user.sid ())))
|
user.sid ())))
|
||||||
debug_printf ("Couldn't retrieve SID from '%s'!", user.logsrv ());
|
debug_printf ("Couldn't retrieve SID from '%s'!", user.logsrv ());
|
||||||
|
|
||||||
/* If we have a SID, try to get the corresponding Cygwin user name
|
/* If we have a SID, try to get the corresponding Cygwin user name
|
||||||
@ -157,12 +174,6 @@ internal_getlogin (cygheap_user &user)
|
|||||||
{
|
{
|
||||||
cygsid psid;
|
cygsid psid;
|
||||||
|
|
||||||
if (!strcasematch (user.name (), "SYSTEM")
|
|
||||||
&& user.domain () && user.logsrv ())
|
|
||||||
{
|
|
||||||
if (get_registry_hive_path (user.sid (), buf))
|
|
||||||
setenv ("USERPROFILE", buf, 1);
|
|
||||||
}
|
|
||||||
for (int pidx = 0; (pw = internal_getpwent (pidx)); ++pidx)
|
for (int pidx = 0; (pw = internal_getpwent (pidx)); ++pidx)
|
||||||
if (psid.getfrompw (pw) && EqualSid (user.sid (), psid))
|
if (psid.getfrompw (pw) && EqualSid (user.sid (), psid))
|
||||||
{
|
{
|
||||||
@ -171,8 +182,24 @@ internal_getlogin (cygheap_user &user)
|
|||||||
if (gr)
|
if (gr)
|
||||||
if (!gsid.getfromgr (gr))
|
if (!gsid.getfromgr (gr))
|
||||||
gsid = NO_SID;
|
gsid = NO_SID;
|
||||||
|
extract_nt_dom_user (pw, dom, buf);
|
||||||
|
setenv ("USERNAME", buf, 1);
|
||||||
|
if (*dom)
|
||||||
|
user.set_domain (dom);
|
||||||
|
else if (user.logsrv ())
|
||||||
|
user.set_domain (user.logsrv ());
|
||||||
|
if (user.domain ())
|
||||||
|
setenv ("USERDOMAIN", user.domain (), 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!strcasematch (user.name (), "SYSTEM")
|
||||||
|
&& user.domain () && user.logsrv ())
|
||||||
|
{
|
||||||
|
if (get_registry_hive_path (user.sid (), buf))
|
||||||
|
setenv ("USERPROFILE", buf, 1);
|
||||||
|
else
|
||||||
|
unsetenv ("USERPROFILE");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this process is started from a non Cygwin process,
|
/* If this process is started from a non Cygwin process,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user