* syscalls.cc (seteuid): Set default dacl in process token.

Replace in-line code by call to verify_token().
	(setegid): Reverse change from 2002-01-21. Add call to
	RevertToSelf and set primary group in impersonation token.
	* security.cc (create_token): Store pgrpsid in token security
	descriptor, except if it already appears in my_grps.
	Use sec_acl() in place of get_dacl().
	(verify_token): Create from code in seteuid(), with tighter checks.
	(get_dacl) Deleted.
	(get_group_sidlist): Add argument to indicate if pgrpsid is already
	in the groups.
	* security.h: Define verify_token().
	* autoload.cc: Load GetKernelObjectSecurity().
This commit is contained in:
Corinna Vinschen 2002-05-16 09:30:48 +00:00
parent a68fa57101
commit ebbdc7034b
5 changed files with 136 additions and 70 deletions

View File

@ -1,3 +1,19 @@
2002-05-13 Pierre Humblet <pierre.humblet@ieee.org>
* syscalls.cc (seteuid): Set default dacl in process token.
Replace in-line code by call to verify_token().
(setegid): Reverse change from 2002-01-21. Add call to
RevertToSelf and set primary group in impersonation token.
* security.cc (create_token): Store pgrpsid in token security
descriptor, except if it already appears in my_grps.
Use sec_acl() in place of get_dacl().
(verify_token): Create from code in seteuid(), with tighter checks.
(get_dacl) Deleted.
(get_group_sidlist): Add argument to indicate if pgrpsid is already
in the groups.
* security.h: Define verify_token().
* autoload.cc: Load GetKernelObjectSecurity().
2002-05-13 Mark Bradshaw <bradshaw@staff.crosswalk.com>
* cygwin.din: Add strlcat and strlcpy.

View File

@ -316,6 +316,7 @@ LoadDLLfuncEx (DuplicateTokenEx, 24, advapi32, 1)
LoadDLLfunc (EqualSid, 8, advapi32)
LoadDLLfunc (GetAce, 12, advapi32)
LoadDLLfunc (GetFileSecurityA, 20, advapi32)
LoadDLLfunc (GetKernelObjectSecurity, 20, advapi32)
LoadDLLfunc (GetLengthSid, 4, advapi32)
LoadDLLfunc (GetSecurityDescriptorDacl, 16, advapi32)
LoadDLLfunc (GetSecurityDescriptorGroup, 12, advapi32)

View File

@ -476,7 +476,8 @@ get_supplementary_group_sidlist (const char *username, cygsidlist &grp_list)
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)
PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos,
BOOL * special_pgrp)
{
WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 1];
char user[INTERNET_MAX_HOST_NAME_LENGTH + 1];
@ -533,19 +534,25 @@ get_group_sidlist (const char *logonserver, cygsidlist &grp_list,
auth_pos = grp_list.count - 1;
}
}
/* special_pgrp true if pgrpsid is not null and not in normal groups */
if (!pgrpsid)
{
* special_pgrp = FALSE;
get_user_primary_group (wserver, user, usersid, pgrpsid);
}
else * special_pgrp = TRUE;
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;
if (get_supplementary_group_sidlist (user, sup_list))
{
for (int i = 0; i < sup_list.count; ++i)
if (!grp_list.contains (sup_list.sids[i]))
grp_list += sup_list.sids[i];
}
if (!grp_list.contains (pgrpsid))
grp_list += pgrpsid;
else * special_pgrp = FALSE;
return TRUE;
}
@ -663,38 +670,56 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
return privs;
}
#define token_acl_size (sizeof (ACL) + \
2 * (sizeof (ACCESS_ALLOWED_ACE) + MAX_SID_LEN))
BOOL
verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL * pintern)
{
DWORD size;
BOOL intern = FALSE;
static BOOL
get_dacl (PACL acl, cygsid usersid, cygsidlist &grp_list)
if (pintern)
{
if (!InitializeAcl(acl, token_acl_size, ACL_REVISION))
{
__seterrno ();
return FALSE;
TOKEN_SOURCE ts;
if (!GetTokenInformation (cygheap->user.token, TokenSource,
&ts, sizeof ts, &size))
debug_printf ("GetTokenInformation(): %E");
else *pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8);
}
if (grp_list.contains (well_known_admins_sid))
/* Verify usersid */
cygsid tok_usersid = NO_SID;
if (!GetTokenInformation (token, TokenUser,
&tok_usersid, sizeof tok_usersid, &size))
debug_printf ("GetTokenInformation(): %E");
if (usersid != tok_usersid) return FALSE;
/* In an internal token, if the sd group is not well_known_null_sid,
it must match pgrpsid */
if (intern)
{
if (!AddAccessAllowedAce(acl, ACL_REVISION, GENERIC_ALL,
well_known_admins_sid))
{
__seterrno ();
return FALSE;
char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)];
PSID gsid = NO_SID;
if (!GetKernelObjectSecurity(token, GROUP_SECURITY_INFORMATION,
(PSECURITY_DESCRIPTOR) sd_buf,
sizeof sd_buf, &size))
debug_printf ("GetKernelObjectSecurity(): %E");
else if (!GetSecurityDescriptorGroup((PSECURITY_DESCRIPTOR) sd_buf,
&gsid, (BOOL *) &size))
debug_printf ("GetSecurityDescriptorGroup(): %E");
if (well_known_null_sid != gsid) return pgrpsid == gsid;
}
}
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;
/* See if the pgrpsid is in the token groups */
PTOKEN_GROUPS my_grps = NULL;
BOOL ret = FALSE;
if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) &&
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
debug_printf ("GetTokenInformation(token, TokenGroups): %E\n");
else if (!(my_grps = (PTOKEN_GROUPS) malloc (size)))
debug_printf ("malloc (my_grps) failed.");
else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size))
debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n");
else ret = sid_in_token_groups (my_grps, pgrpsid);
if (my_grps) free (my_grps);
return ret;
}
HANDLE
@ -711,6 +736,8 @@ create_token (cygsid &usersid, cygsid &pgrpsid)
{ sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE };
OBJECT_ATTRIBUTES oa =
{ sizeof oa, 0, 0, 0, 0, &sqos };
PSECURITY_ATTRIBUTES psa;
BOOL special_pgrp;
char sa_buf[1024];
LUID auth_luid = SYSTEM_LUID;
LARGE_INTEGER exp = { QuadPart:0x7fffffffffffffffLL };
@ -720,7 +747,7 @@ create_token (cygsid &usersid, cygsid &pgrpsid)
PTOKEN_PRIVILEGES privs = NULL;
TOKEN_OWNER owner;
TOKEN_PRIMARY_GROUP pgrp;
char acl_buf[token_acl_size];
char acl_buf[MAX_DACL_LEN(5)];
TOKEN_DEFAULT_DACL dacl;
TOKEN_SOURCE source;
TOKEN_STATISTICS stats;
@ -786,7 +813,7 @@ create_token (cygsid &usersid, cygsid &pgrpsid)
/* 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))
my_grps, auth_luid, auth_pos, &special_pgrp))
goto out;
/* Primary group. */
@ -811,7 +838,8 @@ create_token (cygsid &usersid, cygsid &pgrpsid)
goto out;
/* Create default dacl. */
if (!get_dacl ((PACL) acl_buf, usersid, grpsids))
if (!sec_acl((PACL) acl_buf, FALSE,
grpsids.contains (well_known_admins_sid)?well_known_admins_sid:usersid))
goto out;
dacl.DefaultDacl = (PACL) acl_buf;
@ -826,11 +854,22 @@ create_token (cygsid &usersid, cygsid &pgrpsid)
__seterrno ();
debug_printf ("Loading NtCreateToken failed.");
}
else
{
/* Set security descriptor and primary group */
psa = sec_user (sa_buf, usersid);
if (!SetSecurityDescriptorGroup (
(PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor,
special_pgrp?pgrpsid:well_known_null_sid, FALSE))
debug_printf ("SetSecurityDescriptorGroup %E");
/* Convert to primary token. */
if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, sec_user (sa_buf, usersid),
if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa,
SecurityImpersonation, TokenPrimary, &primary_token))
{
__seterrno ();
debug_printf ("DuplicateTokenEx %E");
}
}
out:
if (old_priv_state >= 0)

View File

@ -181,6 +181,8 @@ void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
HANDLE subauth (struct passwd *pw);
/* Try creating a token directly. */
HANDLE create_token (cygsid &usersid, cygsid &pgrpsid);
/* Verify an existing token */
BOOL verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL * pintern = NULL);
/* Extract U-domain\user field from passwd entry. */
void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);

View File

@ -2007,7 +2007,7 @@ seteuid (__uid16_t uid)
}
else
{
cygsid usersid, pgrpsid, tok_pgrpsid;
cygsid usersid, pgrpsid, origsid;
HANDLE sav_token = INVALID_HANDLE_VALUE;
BOOL sav_impersonation;
BOOL current_token_is_internal_token = FALSE;
@ -2024,31 +2024,8 @@ seteuid (__uid16_t uid)
- if reasonable - new pgrp == pgrp of impersonation token. */
if (allow_ntsec && cygheap->user.token != INVALID_HANDLE_VALUE)
{
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;
}
/* Check if the current user token was internally created. */
TOKEN_SOURCE ts;
if (!GetTokenInformation (cygheap->user.token, TokenSource,
&ts, sizeof ts, &siz))
debug_printf ("GetTokenInformation(): %E");
else if (!memcmp (ts.SourceName, "Cygwin.1", 8))
current_token_is_internal_token = TRUE;
if ((usersid && tok_usersid && usersid != tok_usersid) ||
/* Check for pgrp only if current token is an internal
token. Otherwise the external provided token is
very likely overwritten here. */
(current_token_is_internal_token &&
pgrpsid && tok_pgrpsid && pgrpsid != tok_pgrpsid))
if (!verify_token(cygheap->user.token, usersid, pgrpsid,
& current_token_is_internal_token))
{
/* If not, RevertToSelf and close old token. */
debug_printf ("tsid != usersid");
@ -2113,9 +2090,28 @@ seteuid (__uid16_t uid)
&pgrpsid, sizeof pgrpsid))
debug_printf ("SetTokenInformation(user.token, "
"TokenPrimaryGroup): %E");
}
/* Set process def dacl to allow access to impersonated token */
char dacl_buf[MAX_DACL_LEN(5)];
origsid = cygheap->user.orig_sid ();
if (usersid && origsid &&
sec_acl((PACL) dacl_buf, FALSE, origsid, usersid))
{
HANDLE ptok = INVALID_HANDLE_VALUE;
TOKEN_DEFAULT_DACL tdacl;
tdacl.DefaultDacl = (PACL) dacl_buf;
if (!OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_DEFAULT,
&ptok))
debug_printf ("OpenProcessToken(): %E");
else
{
if (!SetTokenInformation (ptok, TokenDefaultDacl,
&tdacl, sizeof dacl_buf))
debug_printf ("SetTokenInformation"
"(TokenDefaultDacl): %E");
}
if (ptok != INVALID_HANDLE_VALUE) CloseHandle (ptok);
}
/* Now try to impersonate. */
if (!LookupAccountSid (NULL, usersid, username, &ulen,
domain, &dlen, &use))
@ -2180,7 +2176,6 @@ setegid (__gid16_t gid)
return -1;
}
myself->gid = gid;
#if 0 // Setting the primary group in token here isn't foolproof enough.
if (allow_ntsec)
{
cygsid gsid;
@ -2188,6 +2183,17 @@ setegid (__gid16_t gid)
if (gsid.getfromgr (gr))
{
/* Remove impersonation */
if (cygheap->user.token != INVALID_HANDLE_VALUE
&& cygheap->user.impersonated)
{
if (!SetTokenInformation (cygheap->user.token,
TokenPrimaryGroup,
&gsid, sizeof gsid))
debug_printf ("SetTokenInformation(primary, "
"TokenPrimaryGroup): %E");
RevertToSelf ();
}
if (!OpenProcessToken (GetCurrentProcess (),
TOKEN_ADJUST_DEFAULT,
&ptok))
@ -2196,13 +2202,15 @@ setegid (__gid16_t gid)
{
if (!SetTokenInformation (ptok, TokenPrimaryGroup,
&gsid, sizeof gsid))
debug_printf ("SetTokenInformation(myself, "
debug_printf ("SetTokenInformation(process, "
"TokenPrimaryGroup): %E");
CloseHandle (ptok);
}
if (cygheap->user.token != INVALID_HANDLE_VALUE
&& cygheap->user.impersonated)
ImpersonateLoggedOnUser (cygheap->user.token);
}
}
#endif
}
}
else