* 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> 2002-05-13 Mark Bradshaw <bradshaw@staff.crosswalk.com>
* cygwin.din: Add strlcat and strlcpy. * cygwin.din: Add strlcat and strlcpy.

View File

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

View File

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

View File

@ -2007,7 +2007,7 @@ seteuid (__uid16_t uid)
} }
else else
{ {
cygsid usersid, pgrpsid, tok_pgrpsid; cygsid usersid, pgrpsid, origsid;
HANDLE sav_token = INVALID_HANDLE_VALUE; HANDLE sav_token = INVALID_HANDLE_VALUE;
BOOL sav_impersonation; BOOL sav_impersonation;
BOOL current_token_is_internal_token = FALSE; BOOL current_token_is_internal_token = FALSE;
@ -2024,31 +2024,8 @@ seteuid (__uid16_t uid)
- if reasonable - new pgrp == pgrp of impersonation token. */ - if reasonable - new pgrp == pgrp of impersonation token. */
if (allow_ntsec && cygheap->user.token != INVALID_HANDLE_VALUE) if (allow_ntsec && cygheap->user.token != INVALID_HANDLE_VALUE)
{ {
if (!GetTokenInformation (cygheap->user.token, TokenUser, if (!verify_token(cygheap->user.token, usersid, pgrpsid,
&tok_usersid, sizeof tok_usersid, &siz)) & current_token_is_internal_token))
{
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 not, RevertToSelf and close old token. */ /* If not, RevertToSelf and close old token. */
debug_printf ("tsid != usersid"); debug_printf ("tsid != usersid");
@ -2113,9 +2090,28 @@ seteuid (__uid16_t uid)
&pgrpsid, sizeof pgrpsid)) &pgrpsid, sizeof pgrpsid))
debug_printf ("SetTokenInformation(user.token, " debug_printf ("SetTokenInformation(user.token, "
"TokenPrimaryGroup): %E"); "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. */ /* Now try to impersonate. */
if (!LookupAccountSid (NULL, usersid, username, &ulen, if (!LookupAccountSid (NULL, usersid, username, &ulen,
domain, &dlen, &use)) domain, &dlen, &use))
@ -2180,7 +2176,6 @@ setegid (__gid16_t gid)
return -1; return -1;
} }
myself->gid = gid; myself->gid = gid;
#if 0 // Setting the primary group in token here isn't foolproof enough.
if (allow_ntsec) if (allow_ntsec)
{ {
cygsid gsid; cygsid gsid;
@ -2188,6 +2183,17 @@ setegid (__gid16_t gid)
if (gsid.getfromgr (gr)) 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 (), if (!OpenProcessToken (GetCurrentProcess (),
TOKEN_ADJUST_DEFAULT, TOKEN_ADJUST_DEFAULT,
&ptok)) &ptok))
@ -2196,13 +2202,15 @@ setegid (__gid16_t gid)
{ {
if (!SetTokenInformation (ptok, TokenPrimaryGroup, if (!SetTokenInformation (ptok, TokenPrimaryGroup,
&gsid, sizeof gsid)) &gsid, sizeof gsid))
debug_printf ("SetTokenInformation(myself, " debug_printf ("SetTokenInformation(process, "
"TokenPrimaryGroup): %E"); "TokenPrimaryGroup): %E");
CloseHandle (ptok); CloseHandle (ptok);
} }
if (cygheap->user.token != INVALID_HANDLE_VALUE
&& cygheap->user.impersonated)
ImpersonateLoggedOnUser (cygheap->user.token);
} }
} }
#endif
} }
} }
else else