diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2002-05-16 09:30:48 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2002-05-16 09:30:48 +0000 |
commit | ebbdc7034b5251f379ff7959adb5bd65f592ebd2 (patch) | |
tree | ed296dd5207ef129529062efb60e1857dab234c1 /winsup/cygwin | |
parent | a68fa571015ee98e51c21f2189c6ffed8e0314ba (diff) | |
download | cygnal-ebbdc7034b5251f379ff7959adb5bd65f592ebd2.tar.gz cygnal-ebbdc7034b5251f379ff7959adb5bd65f592ebd2.tar.bz2 cygnal-ebbdc7034b5251f379ff7959adb5bd65f592ebd2.zip |
* 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().
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 16 | ||||
-rw-r--r-- | winsup/cygwin/autoload.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/security.cc | 125 | ||||
-rw-r--r-- | winsup/cygwin/security.h | 2 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 70 |
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 |