* 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:
Corinna Vinschen 2001-05-20 08:10:47 +00:00
parent df7cd7fb0c
commit 1fcc912f13
9 changed files with 1041 additions and 161 deletions

View File

@ -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>
* fork.cc (fork_parent): Move atforkprepare call here.

View File

@ -333,9 +333,15 @@ LoadDLLfunc (InitializeSid, 12, advapi32)
LoadDLLfunc (IsValidSid, 4, advapi32)
LoadDLLfunc (LogonUserA, 24, advapi32)
LoadDLLfunc (LookupAccountNameA, 28, advapi32)
LoadDLLfunc (LookupAccountNameW, 28, advapi32)
LoadDLLfunc (LookupAccountSidA, 28, 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 (OpenProcessToken, 12, advapi32)
LoadDLLfunc (RegCloseKey, 4, advapi32)
@ -358,10 +364,15 @@ LoadDLLfunc (SetSecurityDescriptorGroup, 12, advapi32)
LoadDLLfunc (SetSecurityDescriptorOwner, 12, advapi32)
LoadDLLfunc (SetTokenInformation, 16, advapi32)
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
LoadDLLfunc (NetUserGetInfo, 16, 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 (NtOpenSection, 12, ntdll, 1)
LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)

View File

@ -136,12 +136,17 @@ typedef struct _SYSTEM_PROCESSES
standard Win32 header. */
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,
PLARGE_INTEGER, PULONG, SECTION_INHERIT,
ULONG, ULONG);
NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);
VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR);
ULONG NTAPI RtlNtStatusToDosError (NTSTATUS);

View File

@ -44,13 +44,20 @@ SID_IDENTIFIER_AUTHORITY sid_auth[] = {
{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_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 *
cygsid::string (char *nsidstr)
cygsid::string (char *nsidstr) const
{
char t[32];
DWORD i;
@ -74,7 +81,10 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r)
DWORD i;
if (s > 5 || cnt < 1 || cnt > 8)
return NULL;
{
psid = NO_SID;
return NULL;
}
set ();
InitializeSid(psid, &sid_auth[s], cnt);
for (i = 0; i < cnt; ++i)
@ -92,7 +102,10 @@ cygsid::getfromstr (const char *nsidstr)
DWORD i, r[8];
if (!nsidstr || strncmp (nsidstr, "S-1-", 4))
return NULL;
{
psid = NO_SID;
return NULL;
}
strcpy (sid_buf, nsidstr);
@ -110,17 +123,15 @@ cygsid::getfromstr (const char *nsidstr)
BOOL
cygsid::getfrompw (struct passwd *pw)
{
char *sp = pw->pw_gecos ? strrchr (pw->pw_gecos, ',') : NULL;
if (!sp)
return FALSE;
return (*this = ++sp) != NULL;
char *sp = (pw && pw->pw_gecos) ? strrchr (pw->pw_gecos, ',') : NULL;
return (*this = sp ? sp + 1 : "") != NULL;
}
BOOL
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
@ -238,13 +249,6 @@ cygsid::get_id (BOOL search_grp, int *type)
return id;
}
static inline BOOL
legal_sid_type (SID_NAME_USE type)
{
return type == SidTypeUser || type == SidTypeGroup
|| type == SidTypeAlias || type == SidTypeWellKnownGroup;
}
BOOL
is_grp_member (uid_t uid, gid_t gid)
{
@ -338,10 +342,12 @@ set_process_privilege (const char *privilege, BOOL enable)
{
HANDLE hToken = NULL;
LUID restore_priv;
TOKEN_PRIVILEGES new_priv;
TOKEN_PRIVILEGES new_priv, orig_priv;
int ret = -1;
DWORD size;
if (!OpenProcessToken (hMainProc, TOKEN_ADJUST_PRIVILEGES, &hToken))
if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
&hToken))
{
__seterrno ();
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].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 ();
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:
if (hToken)

View File

@ -37,6 +37,10 @@ details. */
#include "pinfo.h"
#include "cygheap.h"
#include "security.h"
#include <ntdef.h>
#include "ntdll.h"
#include "lm.h"
extern BOOL allow_ntea;
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)
{
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
str2lsa (LSA_STRING &tgt, const char *srcstr)
{
tgt.Length = strlen(srcstr);
tgt.Length = strlen (srcstr);
tgt.MaximumLength = tgt.Length + 1;
tgt.Buffer = (PCHAR) srcstr;
}
@ -137,7 +141,7 @@ str2lsa (LSA_STRING &tgt, const char *srcstr)
static void
str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr)
{
tgt.Length = strlen(srcstr);
tgt.Length = strlen (srcstr);
tgt.MaximumLength = tgt.Length + 1;
tgt.Buffer = (PCHAR) buf;
memcpy(buf, srcstr, tgt.MaximumLength);
@ -146,12 +150,644 @@ str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr)
static void
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.Buffer = (PWCHAR) buf;
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;
HANDLE
@ -177,12 +813,16 @@ subauth (struct passwd *pw)
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];
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. */
str2lsa (name, "Cygwin");
@ -192,12 +832,12 @@ subauth (struct passwd *pw)
{
debug_printf ("LsaRegisterLogonProcess: %d", ret);
set_errno (LsaNtStatusToWinError(ret));
return INVALID_HANDLE_VALUE;
goto out;
}
else if (GetLastError () == ERROR_PROC_NOT_FOUND)
{
debug_printf ("Couldn't load Secur32.dll");
return INVALID_HANDLE_VALUE;
goto out;
}
/* Get handle to MSV1_0 package. */
str2lsa (name, MSV1_0_PACKAGE_NAME);
@ -207,7 +847,7 @@ subauth (struct passwd *pw)
debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
set_errno (LsaNtStatusToWinError(ret));
LsaDeregisterLogonProcess(lsa_hdl);
return INVALID_HANDLE_VALUE;
goto out;
}
/* Create origin. */
str2buf2lsa (origin.str, origin.buf, "Cygwin");
@ -236,20 +876,19 @@ subauth (struct passwd *pw)
debug_printf ("LsaLogonUser: %d", ret);
set_errno (LsaNtStatusToWinError(ret));
LsaDeregisterLogonProcess(lsa_hdl);
return INVALID_HANDLE_VALUE;
goto out;
}
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);
__seterrno ();
out:
set_process_privilege(SE_TCB_NAME, old_tcb_state);
if (user_token != INVALID_HANDLE_VALUE)
CloseHandle (user_token);
return primary_token;
}

View File

@ -26,6 +26,18 @@ class cygsid {
const PSID getfromstr (const char *nsidstr);
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:
inline cygsid () : psid ((PSID) sbuf) {}
inline cygsid (const PSID nsid) { *this = nsid; }
@ -40,19 +52,12 @@ public:
inline int get_uid () { return get_id (FALSE); }
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)
{
if (!nsid)
psid = NULL;
else
{
psid = (PSID) sbuf;
CopySid (MAX_SID_LEN, psid, nsid);
}
return psid;
}
{ return assign (nsid); }
inline const PSID operator= (const char *nsidstr)
{ return getfromstr (nsidstr); }
@ -73,12 +78,77 @@ public:
{ return !(*this == nsidstr); }
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_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_smbntsec;
@ -102,6 +172,13 @@ BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PS
/* Try a subauthentication. */
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. */
BOOL __stdcall is_grp_member (uid_t uid, gid_t gid);

View File

@ -622,10 +622,9 @@ skip_arg_parsing:
: &sec_all_nih;
/* Remove impersonation */
uid_t uid = geteuid ();
if (cygheap->user.impersonated
&& cygheap->user.token != INVALID_HANDLE_VALUE)
seteuid (cygheap->user.orig_uid);
RevertToSelf ();
/* Load users registry hive. */
load_registry_hive (sid);
@ -664,7 +663,7 @@ skip_arg_parsing:
if (mode != _P_OVERLAY && mode != _P_VFORK
&& cygheap->user.impersonated
&& cygheap->user.token != INVALID_HANDLE_VALUE)
seteuid (uid);
ImpersonateLoggedOnUser (cygheap->user.token);
}
MALLOC_CHECK;

View File

@ -1954,109 +1954,156 @@ seteuid (uid_t uid)
sigframe thisframe (mainthread);
if (os_being_run == winNT)
{
if (uid != (uid_t) -1)
if (uid == (uid_t) -1 || uid == myself->uid)
{
struct passwd *pw_new = getpwuid (uid);
if (!pw_new)
debug_printf ("new euid == current euid, nothing happens");
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);
return -1;
if (!GetTokenInformation (cygheap->user.token, TokenUser,
&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)
{
debug_printf ("RevertToSelf () (uid == orig_uid, token=%d)",
cygheap->user.token);
RevertToSelf ();
if (cygheap->user.token != INVALID_HANDLE_VALUE)
cygheap->user.impersonated = FALSE;
}
HANDLE ptok = INVALID_HANDLE_VALUE;
ptok = create_token (usersid, pgrpsid);
if (ptok != INVALID_HANDLE_VALUE)
explicitely_created_token = TRUE;
else
{
cygsid tsid, psid, gsid;
DWORD siz;
/* Check if new user == user of impersonation token. */
if (cygheap->user.token != INVALID_HANDLE_VALUE)
/* create_token failed. Try subauthentication. */
debug_printf ("create token failed, try subauthentication.");
ptok = subauth (pw_new);
}
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,
&tsid, sizeof tsid, &siz))
TOKEN_SOURCE ts;
if (!GetTokenInformation (sav_token, TokenSource,
&ts, sizeof ts, &siz))
debug_printf ("GetTokenInformation(): %E");
else if (psid.getfrompw (pw_new) && tsid != psid)
{
/* 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);
}
else if (!memcmp (ts.SourceName, "Cygwin.1", 8))
CloseHandle (sav_token);
}
/* 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.token != INVALID_HANDLE_VALUE &&
!cygheap->user.impersonated)
{
debug_printf ("Impersonate (uid == %d)", uid);
RevertToSelf ();
}
else if (sav_token != INVALID_HANDLE_VALUE)
cygheap->user.token = sav_token;
}
/* If no impersonation is active but an impersonation
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. */
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;
/* 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;
}
else
set_errno (ENOSYS);

View File

@ -38,12 +38,15 @@ internal_getlogin (cygheap_user &user)
user.set_name ("unknown");
else
user.set_name (username);
debug_printf ("GetUserName() = %s", user.name ());
if (os_being_run == winNT)
{
LPWKSTA_USER_INFO_1 wui;
char buf[MAX_PATH], *env;
char *un = NULL;
NET_API_STATUS ret;
char buf[512];
char dom[INTERNET_MAX_HOST_NAME_LENGTH + 1];
char *env, *un = NULL;
/* First trying to get logon info from environment */
if ((env = getenv ("USERNAME")) != NULL)
@ -58,10 +61,8 @@ internal_getlogin (cygheap_user &user)
debug_printf ("Domain: %s, Logon Server: %s",
user.domain (), user.logsrv ());
/* 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);
user.set_name (buf);
sys_wcstombs (buf, wui->wkui1_logon_server,
@ -112,6 +113,22 @@ internal_getlogin (cygheap_user &user)
user.domain (), user.logsrv (), user.name ());
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)
{
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
the logon server. */
if (!ret && !(ret = lookup_name (user.name (), user.logsrv (),
user.sid ())))
user.sid ())))
debug_printf ("Couldn't retrieve SID from '%s'!", user.logsrv ());
/* If we have a SID, try to get the corresponding Cygwin user name
@ -157,12 +174,6 @@ internal_getlogin (cygheap_user &user)
{
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)
if (psid.getfrompw (pw) && EqualSid (user.sid (), psid))
{
@ -171,8 +182,24 @@ internal_getlogin (cygheap_user &user)
if (gr)
if (!gsid.getfromgr (gr))
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;
}
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,