summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog16
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/security.cc125
-rw-r--r--winsup/cygwin/security.h2
-rw-r--r--winsup/cygwin/syscalls.cc70
5 files changed, 140 insertions, 74 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 98e197985..3a6bd26cf 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 6592ef2c0..c95d8e6c3 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -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)
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 358756488..0f2cee4d0 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -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)
- 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) ||
!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))
-
-static BOOL
-get_dacl (PACL acl, cygsid usersid, cygsidlist &grp_list)
+BOOL
+verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL * pintern)
{
- if (!InitializeAcl(acl, token_acl_size, ACL_REVISION))
- {
- __seterrno ();
- return FALSE;
- }
- if (grp_list.contains (well_known_admins_sid))
- {
- if (!AddAccessAllowedAce(acl, ACL_REVISION, GENERIC_ALL,
- well_known_admins_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;
+ DWORD size;
+ BOOL intern = FALSE;
+
+ if (pintern)
+ {
+ 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);
+ }
+ /* 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)
+ {
+ 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;
+ }
+ /* 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.");
}
-
- /* Convert to primary token. */
- if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, sec_user (sa_buf, usersid),
- SecurityImpersonation, TokenPrimary, &primary_token))
- __seterrno ();
+ 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, psa,
+ SecurityImpersonation, TokenPrimary, &primary_token))
+ {
+ __seterrno ();
+ debug_printf ("DuplicateTokenEx %E");
+ }
+ }
out:
if (old_priv_state >= 0)
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 8b95ad0e0..81cbd51e2 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -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);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 46ea12fd1..2eb09017b 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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