diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2005-04-03 17:06:43 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2005-04-03 17:06:43 +0400 |
commit | f4a1f8a1dbc28b1f0330ebb19ed3eef2ea0618b2 (patch) | |
tree | 8170a7d08115c82afaf666a110e57f322329c505 /winsup/cygwin/security.cc | |
parent | fe3e3336611e938e9d97be5cbce677d0be5a6fc9 (diff) |
* cygheap.cc (cygheap_init): Accomodate set_process_privilege change.
* cygheap.h (cygheap_user::curr_primary_token): New member.
(cygheap_user::primary_token): New method.
(cygheap_user::deimpersonate): Always revert to processes'
impersonation token.
(cygheap_user::reimpersonate): Set processes' or setuid token as
necessary.
(cygheap_user::has_impersonation_tokens): Look for curr_primary_token
value.
(cygheap_user::close_impersonation_tokens): Close curr_primary_token
here if necessary. Don't reset token values to NO_IMPERSONATION since
that's done in uinfo_init anyway.
(init_cygheap::luid): New LUID array keeping privilege LUIDs.
* cygtls.cc (_cygtls::init_thread): Call cygheap->user.reimpersonate.
* dcrt0.cc (hProcToken): New global variable to keep process token.
(hProcImpToken): Ditto for process impersonation token.
(dll_crt0_0): Open process token here once. Duplicate to create
hProcImpToken.
(dll_crt0_1): Call set_cygwin_privileges.
* environ.cc (allow_ntea): Drop duplicate declaration.
(allow_smbntsec): Ditto.
(set_traverse): Only set allow_traverse here.
(environ_init): Ditto.
* fhandler_disk_file.cc (fhandler_disk_file::fchmod): Drop call to
enable_restore_privilege.
(fhandler_disk_file::fchown): Ditto.
(fhandler_disk_file::facl): Ditto.
* fork.cc (fork_child): Move call to cygheap->user.reimpersonate after
syn with parent. Call set_cygwin_privileges.
* grp.cc (internal_getgroups): Use hProcImpToken instead of opening
process token.
* path.cc (fs_info::update): Bypass traverse checking when retrieving
volume information using push/pop_thread_privileges.
* registry.cc (load_registry_hive): Drop setting restore privilege
since it's already set if available.
* sec_helper.cc: Include cygtls.h.
(cygpriv): Privilege string array.
(privilege_luid): New function, evaluate LUID from cygpriv_idx.
(privilege_luid_by_name): New function, evaluate LUID from privilege
string.
(privilege_name): New function, evaluate privilege string from
cygpriv_idx.
(set_privilege): New static function called by set_process_privilege
and set_thread_privilege. Call privilege_luid to get privilege LUID.
Fix bug in return value evaluation. Improve debug output.
(set_cygwin_privileges): New function.
(set_process_privilege): Remove.
(enable_restore_privilege): Remove.
* security.cc (allow_traverse): New global variable.
(sys_privs): Change type to cygpriv_idx and store privilege indices
instead of strings.
(SYSTEM_PRIVILEGES_COUNT): Renamed from SYSTEM_PERMISSION_COUNT.
(get_system_priv_list): Don't use numerical constant in malloc call.
Use privilege_luid to get privilege LUIDs.
(get_priv_list): Call privilege_luid_by_name to get LUIDs. Improve
inner privilege LUID comparison loop.
(create_token): Enable create token privilege using
push/pop_self_privileges. Use hProcToken instead of opening process
token. Use default DACL when duplicating token.
(subauth): Enable tcb privilege using push/pop_self_privileges.
Use sec_none instead of homw made security attributes when duplicating
token.
(check_file_access): Don't duplicate access token, use active
impersonation token as is.
* security.h (enum cygpriv_idx): New enumeration type enumerating
possible privileges.
(privilege_luid): Declare new function.
(privilege_luid_by_name): Ditto.
(privilege_name): Ditto.
(allow_traverse): Declare.
(set_privilege): Declare function.
(set_process_privilege): Define as macro.
(enable_restore_privilege): Remove declaration.
(_push_thread_privilege): Define macro.
(push_thread_privilege): Ditto.
(pop_thread_privilege): Ditto.
(pop_self_privilege): Ditto.
* spawn.cc (spawn_guts): Use cygheap->user.primary_token instead of
cygheap->user.token.
* syscalls.cc (statvfs): Bypass traverse checking when retrieving
volume information using push/pop_thread_privileges. Rearrange code
to simplify push/pop bracketing.
(seteuid32): Use hProcToken instead of opening process token. Call
cygheap->user.deimpersonate instead of RevertToSelf. Create
impersonation token from primary internal or external token. Set
cygheap->user.curr_primary_token and cygheap->user.current_token
privileges once here. Drop "failed" and "failed_ptok" labels.
Drop setting DefaultDacl of process token.
(setegid32): Use hProcToken and hProcImpToken instead of opening
process token. Always reimpersonate afterwards.
* uinfo.cc (cygheap_user::init): Use hProcToken instead of opening
process token.
(internal_getlogin): Ditto. Set hProcImpToken, too.
(uinfo_init): Initialize cygheap->user.curr_primary_token.
* winsup.h (hProcToken): Declare.
(hProcImpToken): Declare.
Diffstat (limited to 'winsup/cygwin/security.cc')
-rw-r--r-- | winsup/cygwin/security.cc | 147 |
1 files changed, 66 insertions, 81 deletions
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 5fd401908..44ae8b477 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -45,6 +45,7 @@ bool allow_ntsec; It's defined here because of it's strong relationship to allow_ntsec. The default is TRUE to reflect the old behaviour. */ bool allow_smbntsec; +bool allow_traverse; cygsid * cygsidlist::alloc_sids (int n) @@ -593,36 +594,44 @@ get_setgroups_sidlist (cygsidlist &tmp_list, PTOKEN_GROUPS my_grps, tmp_list += pgpsid; } -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 +static const cygpriv_idx sys_privs[] = { + SE_TCB_PRIV, + SE_ASSIGNPRIMARYTOKEN_PRIV, + SE_CREATE_TOKEN_PRIV, + SE_CHANGE_NOTIFY_PRIV, + SE_SECURITY_PRIV, + SE_BACKUP_PRIV, + SE_RESTORE_PRIV, + SE_SYSTEMTIME_PRIV, + SE_SHUTDOWN_PRIV, + SE_REMOTE_SHUTDOWN_PRIV, + SE_TAKE_OWNERSHIP_PRIV, + SE_DEBUG_PRIV, + SE_SYSTEM_ENVIRONMENT_PRIV, + SE_SYSTEM_PROFILE_PRIV, + SE_PROF_SINGLE_PROCESS_PRIV, + SE_INC_BASE_PRIORITY_PRIV, + SE_LOAD_DRIVER_PRIV, + SE_CREATE_PAGEFILE_PRIV, + SE_INCREASE_QUOTA_PRIV, + SE_LOCK_MEMORY_PRIV, + SE_CREATE_PERMANENT_PRIV, + SE_AUDIT_PRIV, + SE_UNDOCK_PRIV, + SE_MANAGE_VOLUME_PRIV, + SE_IMPERSONATE_PRIV, + SE_CREATE_GLOBAL_PRIV }; -#define SYSTEM_PERMISSION_COUNT (sizeof sys_privs / sizeof (const char *)) +#define SYSTEM_PRIVILEGES_COUNT (sizeof sys_privs / sizeof *sys_privs) PTOKEN_PRIVILEGES get_system_priv_list (cygsidlist &grp_list) { - LUID priv; + const LUID *priv; PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) - malloc (sizeof (ULONG) + 20 * sizeof (LUID_AND_ATTRIBUTES)); + malloc (sizeof (ULONG) + + SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES)); if (!privs) { debug_printf ("malloc (system_privs) failed."); @@ -630,10 +639,10 @@ get_system_priv_list (cygsidlist &grp_list) } privs->PrivilegeCount = 0; - for (DWORD i = 0; i < SYSTEM_PERMISSION_COUNT; ++i) - if (LookupPrivilegeValue (NULL, sys_privs[i], &priv)) + for (DWORD i = 0; i < SYSTEM_PRIVILEGES_COUNT; ++i) + if ((priv = privilege_luid (sys_privs[i]))) { - privs->Privileges[privs->PrivilegeCount].Luid = priv; + privs->Privileges[privs->PrivilegeCount].Luid = *priv; privs->Privileges[privs->PrivilegeCount].Attributes = SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; ++privs->PrivilegeCount; @@ -667,17 +676,23 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list) continue; for (ULONG i = 0; i < cnt; ++i) { - LUID priv; + const LUID *priv; PTOKEN_PRIVILEGES tmp; DWORD tmp_count; lsa2str (buf, privstrs[i], sizeof (buf) - 1); - if (!LookupPrivilegeValue (NULL, buf, &priv)) + if (!(priv = privilege_luid_by_name (buf))) continue; - for (DWORD p = 0; privs && p < privs->PrivilegeCount; ++p) - if (!memcmp (&priv, &privs->Privileges[p].Luid, sizeof (LUID))) - goto next_account_right; + if (privs) + { + DWORD pcnt = privs->PrivilegeCount; + LUID_AND_ATTRIBUTES *p = privs->Privileges; + for (; pcnt > 0; --pcnt, ++p) + if (priv->HighPart == p->Luid.HighPart + && priv->LowPart == p->Luid.LowPart) + goto next_account_right; + } tmp_count = privs ? privs->PrivilegeCount : 0; tmp = (PTOKEN_PRIVILEGES) @@ -693,7 +708,7 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list) } tmp->PrivilegeCount = tmp_count; privs = tmp; - privs->Privileges[privs->PrivilegeCount].Luid = priv; + privs->Privileges[privs->PrivilegeCount].Luid = *priv; privs->Privileges[privs->PrivilegeCount].Attributes = SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; ++privs->PrivilegeCount; @@ -812,16 +827,13 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw) { NTSTATUS ret; LSA_HANDLE lsa = INVALID_HANDLE_VALUE; - int old_priv_state; cygsidlist tmp_gsids (cygsidlist_auto, 12); SECURITY_QUALITY_OF_SERVICE sqos = { sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE }; OBJECT_ATTRIBUTES oa = { sizeof oa, 0, 0, 0, 0, &sqos }; - PSECURITY_ATTRIBUTES psa; bool special_pgrp = false; - char sa_buf[1024]; LUID auth_luid = SYSTEM_LUID; LARGE_INTEGER exp = { QuadPart:INT64_MAX }; @@ -840,13 +852,11 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw) HANDLE token = INVALID_HANDLE_VALUE; HANDLE primary_token = INVALID_HANDLE_VALUE; - HANDLE my_token = INVALID_HANDLE_VALUE; PTOKEN_GROUPS my_tok_gsids = 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; + push_self_privilege (SE_CREATE_TOKEN_PRIV, true); /* Open policy object. */ if ((lsa = open_local_policy ()) == INVALID_HANDLE_VALUE) @@ -858,35 +868,32 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw) owner.Owner = usersid; /* Retrieve authentication id and group list from own process. */ - if (!OpenProcessToken (hMainProc, TOKEN_QUERY, &my_token)) - debug_printf ("OpenProcessToken(my_token), %E"); - else + if (hProcToken) { /* 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, + if (!GetTokenInformation (hProcToken, TokenStatistics, &stats, sizeof stats, &size)) debug_printf - ("GetTokenInformation(my_token, TokenStatistics), %E"); + ("GetTokenInformation(hProcToken, TokenStatistics), %E"); 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) && + if (!GetTokenInformation (hProcToken, TokenGroups, NULL, 0, &size) && GetLastError () != ERROR_INSUFFICIENT_BUFFER) - debug_printf ("GetTokenInformation(my_token, TokenGroups), %E"); + debug_printf ("GetTokenInformation(hProcToken, TokenGroups), %E"); else if (!(my_tok_gsids = (PTOKEN_GROUPS) malloc (size))) debug_printf ("malloc (my_tok_gsids) failed."); - else if (!GetTokenInformation (my_token, TokenGroups, my_tok_gsids, + else if (!GetTokenInformation (hProcToken, TokenGroups, my_tok_gsids, size, &size)) { - debug_printf ("GetTokenInformation(my_token, TokenGroups), %E"); + debug_printf ("GetTokenInformation(hProcToken, TokenGroups), %E"); free (my_tok_gsids); my_tok_gsids = NULL; } - CloseHandle (my_token); } /* Create list of groups, the user is member in. */ @@ -932,18 +939,10 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw) } else { - /* Set security descriptor and primary group */ - psa = sec_user (sa_buf, usersid); - if (psa->lpSecurityDescriptor && - !SetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) - psa->lpSecurityDescriptor, - special_pgrp ? new_groups.pgsid - : well_known_null_sid, - FALSE)) - debug_printf ("SetSecurityDescriptorGroup %E"); /* Convert to primary token. */ - if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, SecurityImpersonation, - TokenPrimary, &primary_token)) + if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, &sec_none, + SecurityImpersonation, TokenPrimary, + &primary_token)) { __seterrno (); debug_printf ("DuplicateTokenEx %E"); @@ -951,8 +950,7 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw) } out: - if (old_priv_state >= 0) - set_process_privilege (SE_CREATE_TOKEN_NAME, old_priv_state); + pop_self_privilege (); if (token != INVALID_HANDLE_VALUE) CloseHandle (token); if (privs) @@ -993,13 +991,10 @@ subauth (struct passwd *pw) 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; - if ((old_tcb_state = set_process_privilege (SE_TCB_NAME)) < 0) - return INVALID_HANDLE_VALUE; + push_self_privilege (SE_TCB_PRIV, true); /* Register as logon process. */ str2lsa (name, "Cygwin"); @@ -1057,12 +1052,12 @@ subauth (struct passwd *pw) } LsaFreeReturnBuffer (profile); /* Convert to primary token. */ - if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa, + if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sec_none, SecurityImpersonation, TokenPrimary, &primary_token)) __seterrno (); out: - set_process_privilege (SE_TCB_NAME, old_tcb_state); + pop_self_privilege (); if (user_token != INVALID_HANDLE_VALUE) CloseHandle (user_token); return primary_token; @@ -1832,7 +1827,7 @@ check_file_access (const char *fn, int flags) security_descriptor sd; - HANDLE hToken, hIToken; + HANDLE hToken; BOOL status; char pbuf[sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES)]; DWORD desired = 0, granted, plength = sizeof pbuf; @@ -1845,17 +1840,8 @@ check_file_access (const char *fn, int flags) if (cygheap->user.issetuid ()) hToken = cygheap->user.token (); - else if (!OpenProcessToken (hMainProc, TOKEN_DUPLICATE, &hToken)) - { - __seterrno (); - goto done; - } - if (!(status = DuplicateToken (hToken, SecurityIdentification, &hIToken))) - __seterrno (); - if (!cygheap->user.issetuid ()) - CloseHandle (hToken); - if (!status) - goto done; + else + hToken = hProcImpToken; if (flags & R_OK) desired |= FILE_READ_DATA; @@ -1863,14 +1849,13 @@ check_file_access (const char *fn, int flags) desired |= FILE_WRITE_DATA; if (flags & X_OK) desired |= FILE_EXECUTE; - if (!AccessCheck (sd, hIToken, desired, &mapping, + if (!AccessCheck (sd, hToken, desired, &mapping, (PPRIVILEGE_SET) pbuf, &plength, &granted, &status)) __seterrno (); else if (!status) set_errno (EACCES); else ret = 0; - CloseHandle (hIToken); done: debug_printf ("flags %x, ret %d", flags, ret); return ret; |