* 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.
This commit is contained in:
parent
fe3e333661
commit
f4a1f8a1db
|
@ -1,3 +1,102 @@
|
|||
2005-04-03 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* 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.
|
||||
|
||||
2005-04-03 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
Unify usage of CYG_MAX_PATH throughout. Change buffers from
|
||||
|
|
|
@ -268,7 +268,7 @@ cygheap_init ()
|
|||
if (!cygheap->shared_prefix)
|
||||
cygheap->shared_prefix = cstrdup (
|
||||
wincap.has_terminal_services ()
|
||||
&& (set_process_privilege (SE_CREATE_GLOBAL_NAME, true) >= 0
|
||||
&& (set_process_privilege (SE_CREATE_GLOBAL_PRIV, true) >= 0
|
||||
|| GetLastError () == ERROR_NO_SUCH_PRIVILEGE)
|
||||
? "Global\\" : "");
|
||||
}
|
||||
|
@ -511,4 +511,3 @@ cygheap_user::set_name (const char *new_name)
|
|||
cfree_and_set (pdomain);
|
||||
cfree_and_set (pwinname);
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ public:
|
|||
to `set_impersonation_token()'. */
|
||||
HANDLE external_token;
|
||||
HANDLE internal_token;
|
||||
HANDLE curr_primary_token;
|
||||
HANDLE current_token;
|
||||
|
||||
/* CGF 2002-06-27. I removed the initializaton from this constructor
|
||||
|
@ -172,40 +173,36 @@ public:
|
|||
const char *ontherange (homebodies what, struct passwd * = NULL);
|
||||
#define NO_IMPERSONATION NULL
|
||||
bool issetuid () const { return current_token != NO_IMPERSONATION; }
|
||||
HANDLE primary_token () { return curr_primary_token; }
|
||||
HANDLE token () { return current_token; }
|
||||
void deimpersonate ()
|
||||
{
|
||||
if (issetuid ())
|
||||
RevertToSelf ();
|
||||
{
|
||||
RevertToSelf ();
|
||||
ImpersonateLoggedOnUser (hProcImpToken);
|
||||
}
|
||||
}
|
||||
void reimpersonate ()
|
||||
bool reimpersonate ()
|
||||
{
|
||||
if (issetuid ()
|
||||
&& !ImpersonateLoggedOnUser (token ()))
|
||||
system_printf ("ImpersonateLoggedOnUser: %E");
|
||||
return ImpersonateLoggedOnUser (issetuid () ? token () : hProcImpToken);
|
||||
}
|
||||
bool has_impersonation_tokens ()
|
||||
{ return external_token != NO_IMPERSONATION
|
||||
|| internal_token != NO_IMPERSONATION
|
||||
|| current_token != NO_IMPERSONATION; }
|
||||
|| curr_primary_token != NO_IMPERSONATION; }
|
||||
void close_impersonation_tokens ()
|
||||
{
|
||||
if (current_token != NO_IMPERSONATION)
|
||||
{
|
||||
if( current_token != external_token && current_token != internal_token)
|
||||
CloseHandle (current_token);
|
||||
current_token = NO_IMPERSONATION;
|
||||
}
|
||||
CloseHandle (current_token);
|
||||
if (curr_primary_token != NO_IMPERSONATION
|
||||
&& curr_primary_token != external_token
|
||||
&& curr_primary_token != internal_token)
|
||||
CloseHandle (curr_primary_token);
|
||||
if (external_token != NO_IMPERSONATION)
|
||||
{
|
||||
CloseHandle (external_token);
|
||||
external_token = NO_IMPERSONATION;
|
||||
}
|
||||
CloseHandle (external_token);
|
||||
if (internal_token != NO_IMPERSONATION)
|
||||
{
|
||||
CloseHandle (internal_token);
|
||||
internal_token = NO_IMPERSONATION;
|
||||
}
|
||||
CloseHandle (internal_token);
|
||||
}
|
||||
char * get_windows_id (char * buf)
|
||||
{
|
||||
|
@ -284,6 +281,7 @@ struct init_cygheap
|
|||
char *cygwin_regname;
|
||||
cwdstuff cwd;
|
||||
dtable fdtab;
|
||||
LUID luid[SE_NUM_PRIVS];
|
||||
const char *shared_prefix;
|
||||
#ifdef DEBUGGING
|
||||
cygheap_debug debug;
|
||||
|
|
|
@ -124,6 +124,9 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
|
|||
|| (void *) func == (void *) cygthread::simplestub)
|
||||
return;
|
||||
|
||||
if (wincap.has_security ())
|
||||
cygheap->user.reimpersonate ();
|
||||
|
||||
sentry here (INFINITE);
|
||||
if (nthreads >= cygheap->sthreads)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,8 @@ void ld_preload ();
|
|||
|
||||
HANDLE NO_COPY hMainProc = (HANDLE) -1;
|
||||
HANDLE NO_COPY hMainThread;
|
||||
HANDLE NO_COPY hProcToken;
|
||||
HANDLE NO_COPY hProcImpToken;
|
||||
|
||||
bool display_title;
|
||||
bool strip_title_path;
|
||||
|
@ -589,6 +591,8 @@ dll_crt0_0 ()
|
|||
|
||||
DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
|
||||
&hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
|
||||
if (wincap.has_security ())
|
||||
OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
|
||||
|
||||
(void) SetErrorMode (SEM_FAILCRITICALERRORS);
|
||||
|
||||
|
@ -688,6 +692,12 @@ dll_crt0_0 ()
|
|||
events_init ();
|
||||
|
||||
cygheap->cwd.init ();
|
||||
|
||||
/* Late duplicate simplifies tweaking the process token in uinfo.cc. */
|
||||
if (wincap.has_security ())
|
||||
DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
|
||||
SecurityImpersonation, TokenImpersonation,
|
||||
&hProcImpToken);
|
||||
}
|
||||
|
||||
/* Take over from libc's crt0.o and start the application. Note the
|
||||
|
@ -759,6 +769,9 @@ dll_crt0_1 (char *)
|
|||
/* Initialize our process table entry. */
|
||||
pinfo_init (envp, envc);
|
||||
|
||||
/* Can be set only after environment has been initialized. */
|
||||
set_cygwin_privileges (hProcImpToken);
|
||||
|
||||
if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
|
||||
old_title = title_buf;
|
||||
|
||||
|
|
|
@ -22,14 +22,13 @@ details. */
|
|||
#include "fhandler.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "cygtls.h"
|
||||
#include "registry.h"
|
||||
#include "environ.h"
|
||||
#include "child_info.h"
|
||||
|
||||
extern bool allow_glob;
|
||||
extern bool ignore_case_with_glob;
|
||||
extern bool allow_ntea;
|
||||
extern bool allow_smbntsec;
|
||||
extern bool allow_winsymlinks;
|
||||
extern bool strip_title_path;
|
||||
extern int pcheck_case;
|
||||
|
@ -533,9 +532,7 @@ set_ntsec (const char *buf)
|
|||
static void
|
||||
set_traverse (const char *buf)
|
||||
{
|
||||
if (wincap.has_security ())
|
||||
set_process_privilege (SE_CHANGE_NOTIFY_NAME,
|
||||
!buf || !strcasematch (buf, "yes"));
|
||||
allow_traverse = (buf && strcasematch (buf, "yes") && wincap.has_security ());
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -738,7 +735,7 @@ environ_init (char **envp, int envc)
|
|||
if (wincap.has_security ())
|
||||
{
|
||||
allow_ntsec = true;
|
||||
set_process_privilege (SE_CHANGE_NOTIFY_NAME, false);
|
||||
allow_traverse = true;
|
||||
}
|
||||
|
||||
if (!envp)
|
||||
|
|
|
@ -409,7 +409,6 @@ fhandler_disk_file::fchmod (mode_t mode)
|
|||
|
||||
if (wincap.has_security ())
|
||||
{
|
||||
enable_restore_privilege ();
|
||||
if (!get_io_handle () && pc.has_acls ())
|
||||
{
|
||||
query_open (query_write_control);
|
||||
|
@ -461,7 +460,6 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
enable_restore_privilege ();
|
||||
if (!get_io_handle ())
|
||||
{
|
||||
query_open (query_write_control);
|
||||
|
@ -548,8 +546,6 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (cmd == SETACL)
|
||||
enable_restore_privilege ();
|
||||
if (!get_io_handle ())
|
||||
{
|
||||
query_open (cmd == SETACL ? query_write_control : query_read_control);
|
||||
|
|
|
@ -160,10 +160,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
|||
debug_printf ("child is running. pid %d, ppid %d, stack here %p",
|
||||
myself->pid, myself->ppid, __builtin_frame_address (0));
|
||||
|
||||
/* Restore the inheritance state as in parent
|
||||
Don't call setuid here! The flags are already set. */
|
||||
cygheap->user.reimpersonate ();
|
||||
|
||||
sync_with_parent ("after longjmp", true);
|
||||
sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d", hParent,
|
||||
first_dll, load_dlls);
|
||||
|
@ -179,6 +175,12 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
|||
_impure_ptr = &_main_tls->local_clib;
|
||||
}
|
||||
|
||||
if (wincap.has_security ())
|
||||
{
|
||||
set_cygwin_privileges (hProcImpToken);
|
||||
cygheap->user.reimpersonate ();
|
||||
}
|
||||
|
||||
#ifdef DEBUGGING
|
||||
char c;
|
||||
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
|
||||
|
|
|
@ -347,8 +347,8 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
|
|||
/* If impersonated, use impersonation token. */
|
||||
if (cygheap->user.issetuid ())
|
||||
hToken = cygheap->user.token ();
|
||||
else if (!OpenProcessToken (hMainProc, TOKEN_QUERY, &hToken))
|
||||
hToken = NULL;
|
||||
else
|
||||
hToken = hProcImpToken;
|
||||
}
|
||||
if (hToken)
|
||||
{
|
||||
|
@ -379,19 +379,13 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
|
|||
grouplist[cnt] = gr->gr_gid;
|
||||
++cnt;
|
||||
if (gidsetsize && cnt > gidsetsize)
|
||||
{
|
||||
if (!cygheap->user.issetuid ())
|
||||
CloseHandle (hToken);
|
||||
goto error;
|
||||
}
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
debug_printf ("%d = GetTokenInformation(NULL) %E", size);
|
||||
if (!cygheap->user.issetuid ())
|
||||
CloseHandle (hToken);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
|
|
@ -348,6 +348,7 @@ fs_info::update (const char *win32_path)
|
|||
{
|
||||
char fsname [CYG_MAX_PATH];
|
||||
char root_dir [CYG_MAX_PATH];
|
||||
bool ret;
|
||||
|
||||
if (!rootdir (win32_path, root_dir))
|
||||
{
|
||||
|
@ -372,6 +373,10 @@ fs_info::update (const char *win32_path)
|
|||
}
|
||||
name_hash = tmp_name_hash;
|
||||
|
||||
/* I have no idea why, but some machines require SeChangeNotifyPrivilege
|
||||
to access volume information. */
|
||||
push_thread_privilege (SE_CHANGE_NOTIFY_PRIV, true);
|
||||
|
||||
drive_type (GetDriveType (root_dir));
|
||||
if (drive_type () == DRIVE_REMOTE
|
||||
|| (drive_type () == DRIVE_UNKNOWN
|
||||
|
@ -380,9 +385,12 @@ fs_info::update (const char *win32_path)
|
|||
else
|
||||
is_remote_drive (false);
|
||||
|
||||
if (!GetVolumeInformation (root_dir, NULL, 0, &status.serial, NULL,
|
||||
&status.flags, fsname, sizeof (fsname))
|
||||
&& !is_remote_drive ())
|
||||
ret = GetVolumeInformation (root_dir, NULL, 0, &status.serial, NULL,
|
||||
&status.flags, fsname, sizeof (fsname));
|
||||
|
||||
pop_thread_privilege ();
|
||||
|
||||
if (!ret && !is_remote_drive ())
|
||||
{
|
||||
debug_printf ("Cannot get volume information (%s), %E", root_dir);
|
||||
has_buggy_open (false);
|
||||
|
@ -390,6 +398,7 @@ fs_info::update (const char *win32_path)
|
|||
flags () = serial () = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* FIXME: Samba by default returns "NTFS" in file system name, but
|
||||
* doesn't support Extended Attributes. If there's some fast way to
|
||||
* distinguish between samba and real ntfs, it should be implemented
|
||||
|
|
|
@ -251,8 +251,6 @@ load_registry_hive (const char * name)
|
|||
RegCloseKey (hkey);
|
||||
return;
|
||||
}
|
||||
/* This is only called while deimpersonated */
|
||||
set_process_privilege (SE_RESTORE_NAME);
|
||||
if (get_registry_hive_path (name, path))
|
||||
{
|
||||
if (wincap.is_winnt ())
|
||||
|
|
|
@ -30,6 +30,7 @@ details. */
|
|||
#include "dtable.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
#include "cygtls.h"
|
||||
#include "pwdgrp.h"
|
||||
|
||||
/* General purpose security attribute objects for global use. */
|
||||
|
@ -321,37 +322,95 @@ got_it:
|
|||
#undef DOMLEN
|
||||
#endif //unused
|
||||
|
||||
int
|
||||
set_process_privilege (const char *privilege, bool enable, bool use_thread)
|
||||
/* Order must be same as cygperm_idx in winsup.h. */
|
||||
static const char *cygpriv[] =
|
||||
{
|
||||
HANDLE hToken = NULL;
|
||||
LUID priv_luid;
|
||||
TOKEN_PRIVILEGES new_priv, orig_priv;
|
||||
int ret = -1;
|
||||
DWORD size;
|
||||
SE_CREATE_TOKEN_NAME,
|
||||
SE_ASSIGNPRIMARYTOKEN_NAME,
|
||||
SE_LOCK_MEMORY_NAME,
|
||||
SE_INCREASE_QUOTA_NAME,
|
||||
SE_UNSOLICITED_INPUT_NAME,
|
||||
SE_MACHINE_ACCOUNT_NAME,
|
||||
SE_TCB_NAME,
|
||||
SE_SECURITY_NAME,
|
||||
SE_TAKE_OWNERSHIP_NAME,
|
||||
SE_LOAD_DRIVER_NAME,
|
||||
SE_SYSTEM_PROFILE_NAME,
|
||||
SE_SYSTEMTIME_NAME,
|
||||
SE_PROF_SINGLE_PROCESS_NAME,
|
||||
SE_INC_BASE_PRIORITY_NAME,
|
||||
SE_CREATE_PAGEFILE_NAME,
|
||||
SE_CREATE_PERMANENT_NAME,
|
||||
SE_BACKUP_NAME,
|
||||
SE_RESTORE_NAME,
|
||||
SE_SHUTDOWN_NAME,
|
||||
SE_DEBUG_NAME,
|
||||
SE_AUDIT_NAME,
|
||||
SE_SYSTEM_ENVIRONMENT_NAME,
|
||||
SE_CHANGE_NOTIFY_NAME,
|
||||
SE_REMOTE_SHUTDOWN_NAME,
|
||||
SE_CREATE_GLOBAL_NAME,
|
||||
SE_UNDOCK_NAME,
|
||||
SE_MANAGE_VOLUME_NAME,
|
||||
SE_IMPERSONATE_NAME,
|
||||
SE_ENABLE_DELEGATION_NAME,
|
||||
SE_SYNC_AGENT_NAME
|
||||
};
|
||||
|
||||
if (!LookupPrivilegeValue (NULL, privilege, &priv_luid))
|
||||
const LUID *
|
||||
privilege_luid (cygpriv_idx idx)
|
||||
{
|
||||
if (idx < 0 || idx >= SE_NUM_PRIVS)
|
||||
return NULL;
|
||||
if (!cygheap->luid[idx].LowPart && !cygheap->luid[idx].HighPart
|
||||
&& !LookupPrivilegeValue (NULL, cygpriv[idx], &cygheap->luid[idx]))
|
||||
{
|
||||
__seterrno ();
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
return &cygheap->luid[idx];
|
||||
}
|
||||
|
||||
if ((use_thread
|
||||
&& !OpenThreadToken (GetCurrentThread (), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||
0, &hToken))
|
||||
||(!use_thread
|
||||
&& !OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||
&hToken)))
|
||||
const LUID *
|
||||
privilege_luid_by_name (const char *pname)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (!pname)
|
||||
return NULL;
|
||||
for (idx = 0; idx < SE_NUM_PRIVS; ++idx)
|
||||
if (!strcmp (pname, cygpriv[idx]))
|
||||
return privilege_luid ((cygpriv_idx) idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
privilege_name (cygpriv_idx idx)
|
||||
{
|
||||
if (idx < 0 || idx >= SE_NUM_PRIVS)
|
||||
return "<unknown privilege>";
|
||||
return cygpriv[idx];
|
||||
}
|
||||
|
||||
int
|
||||
set_privilege (HANDLE token, cygpriv_idx privilege, bool enable)
|
||||
{
|
||||
int ret = -1;
|
||||
const LUID *priv_luid;
|
||||
TOKEN_PRIVILEGES new_priv, orig_priv;
|
||||
DWORD size;
|
||||
|
||||
if (!(priv_luid = privilege_luid (privilege)))
|
||||
{
|
||||
__seterrno ();
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_priv.PrivilegeCount = 1;
|
||||
new_priv.Privileges[0].Luid = priv_luid;
|
||||
new_priv.Privileges[0].Luid = *priv_luid;
|
||||
new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
|
||||
|
||||
if (!AdjustTokenPrivileges (hToken, FALSE, &new_priv,
|
||||
if (!AdjustTokenPrivileges (token, FALSE, &new_priv,
|
||||
sizeof orig_priv, &orig_priv, &size))
|
||||
{
|
||||
__seterrno ();
|
||||
|
@ -365,28 +424,23 @@ set_process_privilege (const char *privilege, bool enable, bool use_thread)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
|
||||
/* If orig_priv.PrivilegeCount is 0, the privilege hasn't been changed. */
|
||||
if (!orig_priv.PrivilegeCount)
|
||||
ret = enable ? 1 : 0;
|
||||
else
|
||||
ret = (orig_priv.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) ? 1 : 0;
|
||||
|
||||
out:
|
||||
if (hToken)
|
||||
CloseHandle (hToken);
|
||||
|
||||
syscall_printf ("%d = set_process_privilege (%s, %d)", ret, privilege, enable);
|
||||
syscall_printf ("%d = set_privilege ((token %x) %s, %d)",
|
||||
ret, token, privilege_name (privilege), enable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper function to set the SE_RESTORE_NAME privilege once. */
|
||||
void
|
||||
enable_restore_privilege ()
|
||||
set_cygwin_privileges (HANDLE token)
|
||||
{
|
||||
static int NO_COPY saved_res;
|
||||
bool issetuid = cygheap->user.issetuid ();
|
||||
if (!saved_res || issetuid)
|
||||
{
|
||||
int res = 2 + set_process_privilege (SE_RESTORE_NAME, true, issetuid);
|
||||
if (!issetuid)
|
||||
saved_res = res;
|
||||
}
|
||||
set_privilege (token, SE_RESTORE_PRIV, true);
|
||||
set_privilege (token, SE_CHANGE_NOTIFY_PRIV, !allow_traverse);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -236,6 +236,46 @@ extern cygpsid well_known_authenticated_users_sid;
|
|||
extern cygpsid well_known_system_sid;
|
||||
extern cygpsid well_known_admins_sid;
|
||||
|
||||
/* Order must be same as cygpriv in sec_helper.cc. */
|
||||
enum cygpriv_idx {
|
||||
SE_CREATE_TOKEN_PRIV = 0,
|
||||
SE_ASSIGNPRIMARYTOKEN_PRIV,
|
||||
SE_LOCK_MEMORY_PRIV,
|
||||
SE_INCREASE_QUOTA_PRIV,
|
||||
SE_UNSOLICITED_INPUT_PRIV,
|
||||
SE_MACHINE_ACCOUNT_PRIV,
|
||||
SE_TCB_PRIV,
|
||||
SE_SECURITY_PRIV,
|
||||
SE_TAKE_OWNERSHIP_PRIV,
|
||||
SE_LOAD_DRIVER_PRIV,
|
||||
SE_SYSTEM_PROFILE_PRIV,
|
||||
SE_SYSTEMTIME_PRIV,
|
||||
SE_PROF_SINGLE_PROCESS_PRIV,
|
||||
SE_INC_BASE_PRIORITY_PRIV,
|
||||
SE_CREATE_PAGEFILE_PRIV,
|
||||
SE_CREATE_PERMANENT_PRIV,
|
||||
SE_BACKUP_PRIV,
|
||||
SE_RESTORE_PRIV,
|
||||
SE_SHUTDOWN_PRIV,
|
||||
SE_DEBUG_PRIV,
|
||||
SE_AUDIT_PRIV,
|
||||
SE_SYSTEM_ENVIRONMENT_PRIV,
|
||||
SE_CHANGE_NOTIFY_PRIV,
|
||||
SE_REMOTE_SHUTDOWN_PRIV,
|
||||
SE_CREATE_GLOBAL_PRIV,
|
||||
SE_UNDOCK_PRIV,
|
||||
SE_MANAGE_VOLUME_PRIV,
|
||||
SE_IMPERSONATE_PRIV,
|
||||
SE_ENABLE_DELEGATION_PRIV,
|
||||
SE_SYNC_AGENT_PRIV,
|
||||
|
||||
SE_NUM_PRIVS
|
||||
};
|
||||
|
||||
const LUID *privilege_luid (enum cygpriv_idx idx);
|
||||
const LUID *privilege_luid_by_name (const char *pname);
|
||||
const char *privilege_name (enum cygpriv_idx idx);
|
||||
|
||||
inline BOOL
|
||||
legal_sid_type (SID_NAME_USE type)
|
||||
{
|
||||
|
@ -246,6 +286,7 @@ legal_sid_type (SID_NAME_USE type)
|
|||
extern bool allow_ntea;
|
||||
extern bool allow_ntsec;
|
||||
extern bool allow_smbntsec;
|
||||
extern bool allow_traverse;
|
||||
|
||||
/* File manipulation */
|
||||
int __stdcall get_file_attribute (int, HANDLE, const char *, mode_t *,
|
||||
|
@ -291,8 +332,37 @@ void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);
|
|||
bool get_logon_server (const char * domain, char * server, WCHAR *wserver = NULL);
|
||||
|
||||
/* sec_helper.cc: Security helper functions. */
|
||||
int set_process_privilege (const char *privilege, bool enable = true, bool use_thread = false);
|
||||
void enable_restore_privilege (void);
|
||||
int set_privilege (HANDLE token, enum cygpriv_idx privilege, bool enable);
|
||||
void set_cygwin_privileges (HANDLE token);
|
||||
|
||||
#define set_process_privilege(p,v) set_privilege (hProcImpToken, (p), (v))
|
||||
|
||||
#define _push_thread_privilege(_priv, _val, _check) { \
|
||||
HANDLE _token = NULL, _dup_token = NULL; \
|
||||
if (wincap.has_security ()) \
|
||||
{ \
|
||||
_token = (cygheap->user.issetuid () && (_check)) \
|
||||
? cygheap->user.token () : hProcImpToken; \
|
||||
if (!DuplicateTokenEx (_token, MAXIMUM_ALLOWED, NULL, \
|
||||
SecurityImpersonation, TokenImpersonation, \
|
||||
&_dup_token)) \
|
||||
debug_printf ("DuplicateTokenEx: %E"); \
|
||||
else if (!ImpersonateLoggedOnUser (_dup_token)) \
|
||||
debug_printf ("ImpersonateLoggedOnUser: %E"); \
|
||||
else \
|
||||
set_privilege (_dup_token, (_priv), (_val)); \
|
||||
}
|
||||
#define push_thread_privilege(_priv, _val) _push_thread_privilege(_priv,_val,1)
|
||||
#define push_self_privilege(_priv, _val) _push_thread_privilege(_priv,_val,0)
|
||||
|
||||
#define pop_thread_privilege() \
|
||||
if (_dup_token) \
|
||||
{ \
|
||||
ImpersonateLoggedOnUser (_token); \
|
||||
CloseHandle (_dup_token); \
|
||||
} \
|
||||
}
|
||||
#define pop_self_privilege() pop_thread_privilege()
|
||||
|
||||
/* shared.cc: */
|
||||
/* Retrieve a security descriptor that allows all access */
|
||||
|
|
|
@ -711,7 +711,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
|||
ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
|
||||
real_path.iscygexec ());
|
||||
newheap = cygheap_setup_for_child (&ciresrv, cygheap->fdtab.need_fixup_before ());
|
||||
rc = CreateProcessAsUser (cygheap->user.token (),
|
||||
rc = CreateProcessAsUser (cygheap->user.primary_token (),
|
||||
runpath, /* image name - with full path */
|
||||
one_line.buf, /* what was passed to exec */
|
||||
&sec_none_nih, /* process security attrs */
|
||||
|
|
|
@ -1698,6 +1698,7 @@ get_osfhandle (int fd)
|
|||
extern "C" int
|
||||
statvfs (const char *fname, struct statvfs *sfs)
|
||||
{
|
||||
int ret = -1;
|
||||
char root[CYG_MAX_PATH];
|
||||
|
||||
if (check_null_empty_str_errno (fname)
|
||||
|
@ -1716,47 +1717,47 @@ statvfs (const char *fname, struct statvfs *sfs)
|
|||
if (!rootdir (full_path, root))
|
||||
return -1;
|
||||
|
||||
ULARGE_INTEGER availb, freeb, totalb;
|
||||
DWORD spc, bps, availc, freec, totalc, vsn, maxlen, flags;
|
||||
BOOL status;
|
||||
|
||||
push_thread_privilege (SE_CHANGE_NOTIFY_PRIV, true);
|
||||
|
||||
/* GetDiskFreeSpaceEx must be called before GetDiskFreeSpace on
|
||||
WinME, to avoid the MS KB 314417 bug */
|
||||
ULARGE_INTEGER availb, freeb, totalb;
|
||||
BOOL status = GetDiskFreeSpaceEx (root, &availb, &totalb, &freeb);
|
||||
|
||||
DWORD spc, bps, availc, freec, totalc;
|
||||
|
||||
if (!GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc))
|
||||
status = GetDiskFreeSpaceEx (root, &availb, &totalb, &freeb);
|
||||
if (GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc))
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
if (status)
|
||||
{
|
||||
availc = availb.QuadPart / (spc*bps);
|
||||
totalc = totalb.QuadPart / (spc*bps);
|
||||
freec = freeb.QuadPart / (spc*bps);
|
||||
}
|
||||
else
|
||||
availc = freec;
|
||||
if (GetVolumeInformation (root, NULL, 0, &vsn, &maxlen, &flags, NULL, 0))
|
||||
{
|
||||
sfs->f_bsize = spc*bps;
|
||||
sfs->f_frsize = spc*bps;
|
||||
sfs->f_blocks = totalc;
|
||||
sfs->f_bfree = freec;
|
||||
sfs->f_bavail = availc;
|
||||
sfs->f_files = ULONG_MAX;
|
||||
sfs->f_ffree = ULONG_MAX;
|
||||
sfs->f_favail = ULONG_MAX;
|
||||
sfs->f_fsid = vsn;
|
||||
sfs->f_flag = flags;
|
||||
sfs->f_namemax = maxlen;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
__seterrno ();
|
||||
|
||||
if (status)
|
||||
{
|
||||
availc = availb.QuadPart / (spc*bps);
|
||||
totalc = totalb.QuadPart / (spc*bps);
|
||||
freec = freeb.QuadPart / (spc*bps);
|
||||
}
|
||||
else
|
||||
availc = freec;
|
||||
pop_thread_privilege ();
|
||||
|
||||
DWORD vsn, maxlen, flags;
|
||||
|
||||
if (!GetVolumeInformation (root, NULL, 0, &vsn, &maxlen, &flags, NULL, 0))
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
sfs->f_bsize = spc*bps;
|
||||
sfs->f_frsize = spc*bps;
|
||||
sfs->f_blocks = totalc;
|
||||
sfs->f_bfree = freec;
|
||||
sfs->f_bavail = availc;
|
||||
sfs->f_files = ULONG_MAX;
|
||||
sfs->f_ffree = ULONG_MAX;
|
||||
sfs->f_favail = ULONG_MAX;
|
||||
sfs->f_fsid = vsn;
|
||||
sfs->f_flag = flags;
|
||||
sfs->f_namemax = maxlen;
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
|
@ -1968,11 +1969,9 @@ seteuid32 (__uid32_t uid)
|
|||
|
||||
cygsid usersid;
|
||||
user_groups &groups = cygheap->user.groups;
|
||||
HANDLE ptok, new_token = INVALID_HANDLE_VALUE;
|
||||
HANDLE new_token = INVALID_HANDLE_VALUE;
|
||||
struct passwd * pw_new;
|
||||
bool token_is_internal, issamesid = false;
|
||||
char dacl_buf[MAX_DACL_LEN (5)];
|
||||
TOKEN_DEFAULT_DACL tdacl = {};
|
||||
|
||||
pw_new = internal_getpwuid (uid);
|
||||
if (!wincap.has_security () && pw_new)
|
||||
|
@ -1986,29 +1985,24 @@ seteuid32 (__uid32_t uid)
|
|||
return -1;
|
||||
}
|
||||
|
||||
RevertToSelf ();
|
||||
if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &ptok))
|
||||
{
|
||||
__seterrno ();
|
||||
goto failed_ptok;;
|
||||
}
|
||||
cygheap->user.deimpersonate ();
|
||||
|
||||
/* Verify if the process token is suitable. */
|
||||
if (verify_token (ptok, usersid, groups))
|
||||
new_token = ptok;
|
||||
if (verify_token (hProcToken, usersid, groups))
|
||||
new_token = hProcToken;
|
||||
/* Verify if the external token is suitable */
|
||||
else if (cygheap->user.external_token != NO_IMPERSONATION
|
||||
&& verify_token (cygheap->user.external_token, usersid, groups))
|
||||
new_token = cygheap->user.external_token;
|
||||
/* Verify if the current token (internal or former external) is suitable */
|
||||
else if (cygheap->user.current_token != NO_IMPERSONATION
|
||||
&& cygheap->user.current_token != cygheap->user.external_token
|
||||
&& verify_token (cygheap->user.current_token, usersid, groups,
|
||||
else if (cygheap->user.curr_primary_token != NO_IMPERSONATION
|
||||
&& cygheap->user.curr_primary_token != cygheap->user.external_token
|
||||
&& verify_token (cygheap->user.curr_primary_token, usersid, groups,
|
||||
&token_is_internal))
|
||||
new_token = cygheap->user.current_token;
|
||||
new_token = cygheap->user.curr_primary_token;
|
||||
/* Verify if the internal token is suitable */
|
||||
else if (cygheap->user.internal_token != NO_IMPERSONATION
|
||||
&& cygheap->user.internal_token != cygheap->user.current_token
|
||||
&& cygheap->user.internal_token != cygheap->user.curr_primary_token
|
||||
&& verify_token (cygheap->user.internal_token, usersid, groups,
|
||||
&token_is_internal))
|
||||
new_token = cygheap->user.internal_token;
|
||||
|
@ -2026,7 +2020,10 @@ seteuid32 (__uid32_t uid)
|
|||
debug_printf ("create token failed, try subauthentication.");
|
||||
new_token = subauth (pw_new);
|
||||
if (new_token == INVALID_HANDLE_VALUE)
|
||||
goto failed;
|
||||
{
|
||||
cygheap->user.reimpersonate ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Keep at most one internal token */
|
||||
if (cygheap->user.internal_token != NO_IMPERSONATION)
|
||||
|
@ -2034,17 +2031,7 @@ seteuid32 (__uid32_t uid)
|
|||
cygheap->user.internal_token = new_token;
|
||||
}
|
||||
|
||||
/* Set process def dacl to allow access to impersonated token */
|
||||
if (sec_acl ((PACL) dacl_buf, true, true, usersid))
|
||||
{
|
||||
tdacl.DefaultDacl = (PACL) dacl_buf;
|
||||
if (!SetTokenInformation (ptok, TokenDefaultDacl,
|
||||
&tdacl, sizeof dacl_buf))
|
||||
debug_printf ("SetTokenInformation"
|
||||
"(TokenDefaultDacl), %E");
|
||||
}
|
||||
|
||||
if (new_token != ptok)
|
||||
if (new_token != hProcToken)
|
||||
{
|
||||
/* Avoid having HKCU use default user */
|
||||
char name[128];
|
||||
|
@ -2053,26 +2040,48 @@ seteuid32 (__uid32_t uid)
|
|||
/* Try setting owner to same value as user. */
|
||||
if (!SetTokenInformation (new_token, TokenOwner,
|
||||
&usersid, sizeof usersid))
|
||||
debug_printf ("SetTokenInformation(user.token, "
|
||||
"TokenOwner), %E");
|
||||
debug_printf ("SetTokenInformation(user.token, TokenOwner), %E");
|
||||
/* Try setting primary group in token to current group */
|
||||
if (!SetTokenInformation (new_token, TokenPrimaryGroup,
|
||||
&groups.pgsid, sizeof (cygsid)))
|
||||
debug_printf ("SetTokenInformation(user.token, "
|
||||
"TokenPrimaryGroup), %E");
|
||||
debug_printf ("SetTokenInformation(user.token, TokenPrimaryGroup), %E");
|
||||
/* Try setting default DACL */
|
||||
if (tdacl.DefaultDacl
|
||||
&& !SetTokenInformation (new_token, TokenDefaultDacl,
|
||||
&tdacl, sizeof (tdacl)))
|
||||
debug_printf ("SetTokenInformation (TokenDefaultDacl), %E");
|
||||
char dacl_buf[MAX_DACL_LEN (5)];
|
||||
if (sec_acl ((PACL) dacl_buf, true, true, usersid))
|
||||
{
|
||||
TOKEN_DEFAULT_DACL tdacl = { (PACL) dacl_buf };
|
||||
if (!SetTokenInformation (new_token, TokenDefaultDacl,
|
||||
&tdacl, sizeof (tdacl)))
|
||||
debug_printf ("SetTokenInformation (TokenDefaultDacl), %E");
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle (ptok);
|
||||
issamesid = (usersid == cygheap->user.sid ());
|
||||
cygheap->user.set_sid (usersid);
|
||||
cygheap->user.current_token = new_token == ptok ? NO_IMPERSONATION
|
||||
: new_token;
|
||||
cygheap->user.reimpersonate ();
|
||||
cygheap->user.curr_primary_token = new_token == hProcToken ? NO_IMPERSONATION
|
||||
: new_token;
|
||||
if (cygheap->user.current_token != NO_IMPERSONATION)
|
||||
{
|
||||
CloseHandle (cygheap->user.current_token);
|
||||
cygheap->user.current_token = NO_IMPERSONATION;
|
||||
}
|
||||
if (cygheap->user.curr_primary_token != NO_IMPERSONATION)
|
||||
{
|
||||
if (!DuplicateTokenEx (cygheap->user.curr_primary_token, MAXIMUM_ALLOWED,
|
||||
&sec_none, SecurityImpersonation,
|
||||
TokenImpersonation, &cygheap->user.current_token))
|
||||
{
|
||||
__seterrno ();
|
||||
cygheap->user.curr_primary_token = NO_IMPERSONATION;
|
||||
return -1;
|
||||
}
|
||||
set_cygwin_privileges (cygheap->user.current_token);
|
||||
}
|
||||
if (!cygheap->user.reimpersonate ())
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
success_9x:
|
||||
cygheap->user.set_name (pw_new->pw_name);
|
||||
|
@ -2081,12 +2090,6 @@ success_9x:
|
|||
if (!issamesid)
|
||||
user_shared_initialize (true);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
CloseHandle (ptok);
|
||||
failed_ptok:
|
||||
cygheap->user.reimpersonate ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
|
@ -2151,7 +2154,6 @@ setegid32 (__gid32_t gid)
|
|||
|
||||
user_groups * groups = &cygheap->user.groups;
|
||||
cygsid gsid;
|
||||
HANDLE ptok;
|
||||
struct __group32 * gr = internal_getgrgid (gid);
|
||||
|
||||
if (!gsid.getfromgr (gr))
|
||||
|
@ -2162,29 +2164,24 @@ setegid32 (__gid32_t gid)
|
|||
myself->gid = gid;
|
||||
|
||||
groups->update_pgrp (gsid);
|
||||
/* If impersonated, update primary group and revert */
|
||||
if (cygheap->user.issetuid ())
|
||||
{
|
||||
if (!SetTokenInformation (cygheap->user.token (),
|
||||
TokenPrimaryGroup,
|
||||
&gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(thread, "
|
||||
/* If impersonated, update impersonation token... */
|
||||
if (!SetTokenInformation (cygheap->user.primary_token (),
|
||||
TokenPrimaryGroup, &gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(primary_token, "
|
||||
"TokenPrimaryGroup), %E");
|
||||
RevertToSelf ();
|
||||
}
|
||||
if (!OpenProcessToken (hMainProc, TOKEN_ADJUST_DEFAULT, &ptok))
|
||||
debug_printf ("OpenProcessToken(), %E");
|
||||
else
|
||||
{
|
||||
if (!SetTokenInformation (ptok, TokenPrimaryGroup,
|
||||
if (!SetTokenInformation (cygheap->user.token (), TokenPrimaryGroup,
|
||||
&gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(process, "
|
||||
"TokenPrimaryGroup), %E");
|
||||
CloseHandle (ptok);
|
||||
debug_printf ("SetTokenInformation(token, TokenPrimaryGroup), %E");
|
||||
}
|
||||
if (cygheap->user.issetuid ()
|
||||
&& !ImpersonateLoggedOnUser (cygheap->user.token ()))
|
||||
system_printf ("Impersonating in setegid failed, %E");
|
||||
cygheap->user.deimpersonate ();
|
||||
if (!SetTokenInformation (hProcToken, TokenPrimaryGroup, &gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(hProcToken, TokenPrimaryGroup), %E");
|
||||
if (!SetTokenInformation (hProcImpToken, TokenPrimaryGroup, &gsid,
|
||||
sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(hProcImpToken, TokenPrimaryGroup), %E");
|
||||
cygheap->user.reimpersonate ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,51 +44,45 @@ cygheap_user::init ()
|
|||
if (!wincap.has_security ())
|
||||
return;
|
||||
|
||||
HANDLE ptok;
|
||||
DWORD siz;
|
||||
PSECURITY_DESCRIPTOR psd;
|
||||
|
||||
if (!OpenProcessToken (hMainProc, TOKEN_ADJUST_DEFAULT | TOKEN_QUERY,
|
||||
&ptok))
|
||||
{
|
||||
system_printf ("OpenProcessToken(), %E");
|
||||
return;
|
||||
}
|
||||
if (!GetTokenInformation (ptok, TokenPrimaryGroup,
|
||||
if (!GetTokenInformation (hProcToken, TokenPrimaryGroup,
|
||||
&groups.pgsid, sizeof (cygsid), &siz))
|
||||
system_printf ("GetTokenInformation (TokenPrimaryGroup), %E");
|
||||
|
||||
/* Get the SID from current process and store it in effec_cygsid */
|
||||
if (!GetTokenInformation (ptok, TokenUser, &effec_cygsid, sizeof (cygsid), &siz))
|
||||
if (!GetTokenInformation (hProcToken, TokenUser, &effec_cygsid,
|
||||
sizeof (cygsid), &siz))
|
||||
{
|
||||
system_printf ("GetTokenInformation (TokenUser), %E");
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set token owner to the same value as token user */
|
||||
if (!SetTokenInformation (ptok, TokenOwner, &effec_cygsid, sizeof (cygsid)))
|
||||
if (!SetTokenInformation (hProcToken, TokenOwner, &effec_cygsid,
|
||||
sizeof (cygsid)))
|
||||
debug_printf ("SetTokenInformation(TokenOwner), %E");
|
||||
|
||||
/* Standard way to build a security descriptor with the usual DACL */
|
||||
char sa_buf[1024];
|
||||
psd = (PSECURITY_DESCRIPTOR) (sec_user_nih (sa_buf, sid()))->lpSecurityDescriptor;
|
||||
psd = (PSECURITY_DESCRIPTOR)
|
||||
(sec_user_nih (sa_buf, sid()))->lpSecurityDescriptor;
|
||||
|
||||
BOOL acl_exists, dummy;
|
||||
TOKEN_DEFAULT_DACL dacl;
|
||||
if (GetSecurityDescriptorDacl (psd, &acl_exists,
|
||||
&dacl.DefaultDacl, &dummy)
|
||||
if (GetSecurityDescriptorDacl (psd, &acl_exists, &dacl.DefaultDacl, &dummy)
|
||||
&& acl_exists && dacl.DefaultDacl)
|
||||
{
|
||||
/* Set the default DACL and the process DACL */
|
||||
if (!SetTokenInformation (ptok, TokenDefaultDacl, &dacl, sizeof (dacl)))
|
||||
if (!SetTokenInformation (hProcToken, TokenDefaultDacl, &dacl,
|
||||
sizeof (dacl)))
|
||||
system_printf ("SetTokenInformation (TokenDefaultDacl), %E");
|
||||
if (!SetKernelObjectSecurity (hMainProc, DACL_SECURITY_INFORMATION, psd))
|
||||
system_printf ("SetKernelObjectSecurity, %E");
|
||||
}
|
||||
else
|
||||
system_printf("Cannot get dacl, %E");
|
||||
out:
|
||||
CloseHandle (ptok);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -115,17 +109,17 @@ internal_getlogin (cygheap_user &user)
|
|||
cygsid gsid;
|
||||
if (gsid.getfromgr (internal_getgrgid (pw->pw_gid)))
|
||||
{
|
||||
HANDLE ptok;
|
||||
if (gsid != user.groups.pgsid
|
||||
&& OpenProcessToken (hMainProc, TOKEN_ADJUST_DEFAULT, &ptok))
|
||||
if (gsid != user.groups.pgsid)
|
||||
{
|
||||
/* Set primary group to the group in /etc/passwd. */
|
||||
if (!SetTokenInformation (ptok, TokenPrimaryGroup,
|
||||
if (!SetTokenInformation (hProcToken, TokenPrimaryGroup,
|
||||
&gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(TokenPrimaryGroup), %E");
|
||||
if (!SetTokenInformation (hProcImpToken, TokenPrimaryGroup,
|
||||
&gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(TokenPrimaryGroup), %E");
|
||||
else
|
||||
user.groups.pgsid = gsid;
|
||||
CloseHandle (ptok);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -162,6 +156,7 @@ uinfo_init ()
|
|||
cygheap->user.saved_gid = cygheap->user.real_gid = myself->gid;
|
||||
cygheap->user.external_token = NO_IMPERSONATION;
|
||||
cygheap->user.internal_token = NO_IMPERSONATION;
|
||||
cygheap->user.curr_primary_token = NO_IMPERSONATION;
|
||||
cygheap->user.current_token = NO_IMPERSONATION;
|
||||
cygheap->user.set_saved_sid (); /* Update the original sid */
|
||||
}
|
||||
|
|
|
@ -343,6 +343,8 @@ extern bool display_title;
|
|||
|
||||
extern HANDLE hMainThread;
|
||||
extern HANDLE hMainProc;
|
||||
extern HANDLE hProcToken;
|
||||
extern HANDLE hProcImpToken;
|
||||
|
||||
extern bool cygwin_testing;
|
||||
|
||||
|
|
Loading…
Reference in New Issue