From cce28460fe93c21d30e227331dcbbdf1d29a96b9 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 19 Jul 2007 08:33:22 +0000 Subject: [PATCH] * cygheap.h (init_cygheap::luid): Remove. * mmap.cc (mlock): Accommodate parameter change in call to push_thread_privilege. (munlock): Ditto. * ntdll.h (STATUS_NOT_ALL_ASSIGNED): Define. (NtAdjustPrivilegesToken): Declare. * sec_helper.cc (cygpriv): Reorder to match numerical privilege order. (privilege_luid): Take job of privilege_luid_by_name, using new cygpriv. (privilege_luid_by_name): Remove. (privilege_name): Accommodate new cygpriv array. (set_privilege): Call NtAdjustPrivilegesToken to avoid using advapi32. Accommodate changes to privilege_name. (set_cygwin_privileges): Simplify. Don't try to set SE_CREATE_GLOBAL_PRIVILEGE on systems not supporting it. * security.cc (sys_privs): Reorder to match numerical privilege order. Use real privilege values as defined in security.h. (get_system_priv_list): Drop unused grp_list argument. Create list of privileges according to new wincapc::max_sys_priv value. (get_priv_list): Call privilege_luid instead of privilege_luid_by_name. Make priv a local value instead of a pointer. (create_token): Accommodate parameter change in call to push_self_privilege. (lsaauth): Ditto. (check_access): Use privilege values directly instead of calling privilege_luid. * security.h: Define real privilege values. (cygpriv_idx): Remove. (privilege_luid): Change declaration. (privilege_luid_by_name): Drop declaration. (set_privilege): Change declaration. (set_process_privilege): Drop definition. (_push_thread_privilege): Accomodate new set_privilege parameters. * wincap.h (wincapc::max_sys_priv): New element. * wincap.cc: Implement above element throughout. (wincap_2000sp4): New wincaps structure. (wincap_xpsp1): Ditto. (wincap_xpsp2): Ditto. (wincapc::init): Use new wincaps. (wincapc::max_sys_priv): New element. --- winsup/cygwin/ChangeLog | 43 ++++++++++++++ winsup/cygwin/cygheap.h | 1 - winsup/cygwin/mmap.cc | 4 +- winsup/cygwin/ntdll.h | 3 + winsup/cygwin/sec_helper.cc | 105 +++++++++++++--------------------- winsup/cygwin/security.cc | 111 +++++++++++++++++++----------------- winsup/cygwin/security.h | 92 +++++++++++++++--------------- winsup/cygwin/wincap.cc | 111 +++++++++++++++++++++++++++++++++++- winsup/cygwin/wincap.h | 2 + 9 files changed, 302 insertions(+), 170 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c47df0116..2a879fb54 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,46 @@ +2007-07-19 Corinna Vinschen + + * cygheap.h (init_cygheap::luid): Remove. + * mmap.cc (mlock): Accommodate parameter change in call to + push_thread_privilege. + (munlock): Ditto. + * ntdll.h (STATUS_NOT_ALL_ASSIGNED): Define. + (NtAdjustPrivilegesToken): Declare. + * sec_helper.cc (cygpriv): Reorder to match numerical privilege order. + (privilege_luid): Take job of privilege_luid_by_name, using new + cygpriv. + (privilege_luid_by_name): Remove. + (privilege_name): Accommodate new cygpriv array. + (set_privilege): Call NtAdjustPrivilegesToken to avoid using advapi32. + Accommodate changes to privilege_name. + (set_cygwin_privileges): Simplify. Don't try to set + SE_CREATE_GLOBAL_PRIVILEGE on systems not supporting it. + * security.cc (sys_privs): Reorder to match numerical privilege order. + Use real privilege values as defined in security.h. + (get_system_priv_list): Drop unused grp_list argument. Create + list of privileges according to new wincapc::max_sys_priv value. + (get_priv_list): Call privilege_luid instead of privilege_luid_by_name. + Make priv a local value instead of a pointer. + (create_token): Accommodate parameter change in call to + push_self_privilege. + (lsaauth): Ditto. + (check_access): Use privilege values directly instead of calling + privilege_luid. + * security.h: Define real privilege values. + (cygpriv_idx): Remove. + (privilege_luid): Change declaration. + (privilege_luid_by_name): Drop declaration. + (set_privilege): Change declaration. + (set_process_privilege): Drop definition. + (_push_thread_privilege): Accomodate new set_privilege parameters. + * wincap.h (wincapc::max_sys_priv): New element. + * wincap.cc: Implement above element throughout. + (wincap_2000sp4): New wincaps structure. + (wincap_xpsp1): Ditto. + (wincap_xpsp2): Ditto. + (wincapc::init): Use new wincaps. + (wincapc::max_sys_priv): New element. + 2007-07-19 Corinna Vinschen * dcrt0.cc (dll_crt0_0): Call set_cygwin_privileges here, after diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 3ac43ba2d..212578612 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -278,7 +278,6 @@ struct init_cygheap HANDLE console_h; cwdstuff cwd; dtable fdtab; - LUID luid[SE_NUM_PRIVS]; char *shared_prefix; char shared_prefix_buf[8]; #ifdef DEBUGGING diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 18c8ec846..5a378946e 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -1309,7 +1309,7 @@ mlock (const void *addr, size_t len) POSIX systems does. On NT, this requires SeLockMemoryPrivilege, which is given only to SYSTEM by default. */ - push_thread_privilege (SE_LOCK_MEMORY_PRIV, true); + push_thread_privilege (SE_LOCK_MEMORY_PRIVILEGE, true); /* Align address and length values to page size. */ size_t pagesize = getpagesize (); @@ -1368,7 +1368,7 @@ munlock (const void *addr, size_t len) { int ret = -1; - push_thread_privilege (SE_LOCK_MEMORY_PRIV, true); + push_thread_privilege (SE_LOCK_MEMORY_PRIVILEGE, true); /* Align address and length values to page size. */ size_t pagesize = getpagesize (); diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 0bbb5a521..a509f1fce 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -19,6 +19,7 @@ #define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043) #define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056) #define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1) +#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106) #define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148) #define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006) #define PDI_MODULES 0x01 @@ -685,6 +686,8 @@ typedef struct _FILE_FULL_EA_INFORMATION standard Win32 header. */ extern "C" { + NTSTATUS NTAPI NtAdjustPrivilegesToken (HANDLE, BOOLEAN, PTOKEN_PRIVILEGES, + ULONG, PTOKEN_PRIVILEGES, PULONG); NTSTATUS NTAPI NtClose (HANDLE); NTSTATUS NTAPI NtCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 416488a33..6667357a8 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -31,6 +31,7 @@ details. */ #include "cygheap.h" #include "cygtls.h" #include "pwdgrp.h" +#include "ntdll.h" /* General purpose security attribute objects for global use. */ SECURITY_ATTRIBUTES NO_COPY sec_none; @@ -361,14 +362,15 @@ got_it: #undef DOMLEN #endif //unused -/* Order must be same as cygpriv_idx in security.h. */ +/* Index must match the correspoding foo_PRIVILEGE value, see security.h. */ static const char *cygpriv[] = { + "", + "", 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, @@ -388,81 +390,62 @@ static const char *cygpriv[] = SE_SYSTEM_ENVIRONMENT_NAME, SE_CHANGE_NOTIFY_NAME, SE_REMOTE_SHUTDOWN_NAME, - SE_CREATE_GLOBAL_NAME, SE_UNDOCK_NAME, + SE_SYNC_AGENT_NAME, + SE_ENABLE_DELEGATION_NAME, SE_MANAGE_VOLUME_NAME, SE_IMPERSONATE_NAME, - SE_ENABLE_DELEGATION_NAME, - SE_SYNC_AGENT_NAME, + SE_CREATE_GLOBAL_NAME, + SE_TRUSTED_CREDMAN_ACCESS_NAME, SE_RELABEL_NAME, SE_INCREASE_WORKING_SET_NAME, SE_TIME_ZONE_NAME, SE_CREATE_SYMBOLIC_LINK_NAME }; -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 (); - return NULL; - } - return &cygheap->luid[idx]; -} - -const LUID * -privilege_luid_by_name (const char *pname) +bool +privilege_luid (const char *pname, LUID *luid) { - 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; + ULONG idx; + for (idx = SE_CREATE_TOKEN_PRIVILEGE; + idx <= SE_MAX_WELL_KNOWN_PRIVILEGE; + ++idx) + if (!strcmp (cygpriv[idx], pname)) + { + luid->HighPart = 0; + luid->LowPart = idx; + return true; + } + return false; } static const char * -privilege_name (const LUID *priv_luid, char *buf, DWORD *size) +privilege_name (const LUID &priv_luid) { - if (!priv_luid || !LookupPrivilegeName (NULL, (LUID *) priv_luid, buf, size)) + if (priv_luid.HighPart || priv_luid.LowPart < SE_CREATE_TOKEN_PRIVILEGE + || priv_luid.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE) return ""; - return buf; + return cygpriv[priv_luid.LowPart]; } int -set_privilege (HANDLE token, const LUID *priv_luid, bool enable) +set_privilege (HANDLE token, DWORD privilege, bool enable) { int ret = -1; TOKEN_PRIVILEGES new_priv, orig_priv; - DWORD size; - - if (!priv_luid) - { - __seterrno (); - goto out; - } + ULONG size; + NTSTATUS status; new_priv.PrivilegeCount = 1; - new_priv.Privileges[0].Luid = *priv_luid; + new_priv.Privileges[0].Luid.HighPart = 0L; + new_priv.Privileges[0].Luid.LowPart = privilege; new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; - if (!AdjustTokenPrivileges (token, FALSE, &new_priv, - sizeof orig_priv, &orig_priv, &size)) - { - __seterrno (); - goto out; - } - /* AdjustTokenPrivileges returns TRUE even if the privilege could not - be enabled. GetLastError () returns an correct error code, though. */ - if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED) + status = NtAdjustPrivilegesToken (token, FALSE, &new_priv, sizeof orig_priv, + &orig_priv, &size); + if (!NT_SUCCESS (status)) { - __seterrno (); + __seterrno_from_nt_status (status); goto out; } @@ -474,12 +457,8 @@ set_privilege (HANDLE token, const LUID *priv_luid, bool enable) out: if (ret < 0) - { - DWORD siz = 256; - char buf[siz]; - debug_printf ("%d = set_privilege ((token %x) %s, %d)", - ret, token, privilege_name (priv_luid, buf, &siz), enable); - } + debug_printf ("%d = set_privilege ((token %x) %s, %d)\n", ret, token, + privilege_name (new_priv.Privileges[0].Luid), enable); return ret; } @@ -488,14 +467,10 @@ out: void set_cygwin_privileges (HANDLE token) { - LUID priv_luid; - - if (LookupPrivilegeValue (NULL, SE_RESTORE_NAME, &priv_luid)) - set_privilege (token, &priv_luid, true); - if (LookupPrivilegeValue (NULL, SE_BACKUP_NAME, &priv_luid)) - set_privilege (token, &priv_luid, true); - if (LookupPrivilegeValue (NULL, SE_CREATE_GLOBAL_NAME, &priv_luid)) - set_privilege (token, &priv_luid, true); + set_privilege (token, SE_RESTORE_PRIVILEGE, true); + set_privilege (token, SE_BACKUP_PRIVILEGE, true); + if (wincap.has_create_global_privilege ()) + set_privilege (token, SE_CREATE_GLOBAL_PRIVILEGE, true); } /* Function to return a common SECURITY_DESCRIPTOR that diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 2c3cb141c..d76bbb1d8 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -562,46 +562,50 @@ get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid, struct passwd *pw, tmp_list += groups.pgsid; } -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, - SE_INCREASE_WORKING_SET_PRIV, - SE_TIME_ZONE_PRIV, - SE_CREATE_SYMBOLIC_LINK_PRIV +static ULONG sys_privs[] = { + SE_CREATE_TOKEN_PRIVILEGE, + SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, + SE_LOCK_MEMORY_PRIVILEGE, + SE_INCREASE_QUOTA_PRIVILEGE, + SE_TCB_PRIVILEGE, + SE_SECURITY_PRIVILEGE, + SE_TAKE_OWNERSHIP_PRIVILEGE, + SE_LOAD_DRIVER_PRIVILEGE, + SE_SYSTEM_PROFILE_PRIVILEGE, /* Vista ONLY */ + SE_SYSTEMTIME_PRIVILEGE, + SE_PROF_SINGLE_PROCESS_PRIVILEGE, + SE_INC_BASE_PRIORITY_PRIVILEGE, + SE_CREATE_PAGEFILE_PRIVILEGE, + SE_CREATE_PERMANENT_PRIVILEGE, + SE_BACKUP_PRIVILEGE, + SE_RESTORE_PRIVILEGE, + SE_SHUTDOWN_PRIVILEGE, + SE_DEBUG_PRIVILEGE, + SE_AUDIT_PRIVILEGE, + SE_SYSTEM_ENVIRONMENT_PRIVILEGE, + SE_CHANGE_NOTIFY_PRIVILEGE, + SE_UNDOCK_PRIVILEGE, + SE_MANAGE_VOLUME_PRIVILEGE, + SE_IMPERSONATE_PRIVILEGE, + SE_CREATE_GLOBAL_PRIVILEGE, + SE_INCREASE_WORKING_SET_PRIVILEGE, + SE_TIME_ZONE_PRIVILEGE, + SE_CREATE_SYMBOLIC_LINK_PRIVILEGE }; #define SYSTEM_PRIVILEGES_COUNT (sizeof sys_privs / sizeof *sys_privs) static PTOKEN_PRIVILEGES -get_system_priv_list (cygsidlist &grp_list, size_t &size) +get_system_priv_list (size_t &size) { - const LUID *priv; - size = sizeof (ULONG) - + SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES); + ULONG max_idx = 0; + while (max_idx < SYSTEM_PRIVILEGES_COUNT + && sys_privs[max_idx] != wincap.max_sys_priv ()) + ++max_idx; + if (max_idx >= SYSTEM_PRIVILEGES_COUNT) + api_fatal ("Coding error: wincap privilege %u doesn't exist in sys_privs", + wincap.max_sys_priv ()); + size = sizeof (ULONG) + (max_idx + 1) * sizeof (LUID_AND_ATTRIBUTES); PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (size); if (!privs) { @@ -609,15 +613,14 @@ get_system_priv_list (cygsidlist &grp_list, size_t &size) return NULL; } privs->PrivilegeCount = 0; - - 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].Attributes = - SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; - ++privs->PrivilegeCount; - } + for (ULONG i = 0; i <= max_idx; ++i) + { + privs->Privileges[privs->PrivilegeCount].Luid.HighPart = 0L; + privs->Privileges[privs->PrivilegeCount].Luid.LowPart = sys_privs[i]; + privs->Privileges[privs->PrivilegeCount].Attributes = + SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; + ++privs->PrivilegeCount; + } return privs; } @@ -632,7 +635,7 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list, char buf[INTERNET_MAX_HOST_NAME_LENGTH + 1]; if (usersid == well_known_system_sid) - return get_system_priv_list (grp_list, size); + return get_system_priv_list (size); for (int grp = -1; grp < grp_list.count (); ++grp) { @@ -648,13 +651,13 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list, continue; for (ULONG i = 0; i < cnt; ++i) { - const LUID *priv; + LUID priv; PTOKEN_PRIVILEGES tmp; DWORD tmp_count; sys_wcstombs (buf, sizeof (buf), privstrs[i].Buffer, privstrs[i].Length / 2); - if (!(priv = privilege_luid_by_name (buf))) + if (!privilege_luid (buf, &priv)) continue; if (privs) @@ -662,8 +665,8 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list, 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) + if (priv.HighPart == p->Luid.HighPart + && priv.LowPart == p->Luid.LowPart) goto next_account_right; } @@ -681,7 +684,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; @@ -827,7 +830,7 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw) size_t psize = 0; /* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */ - push_self_privilege (SE_CREATE_TOKEN_PRIV, true); + push_self_privilege (SE_CREATE_TOKEN_PRIVILEGE, true); /* Open policy object. */ if ((lsa = open_local_policy ()) == INVALID_HANDLE_VALUE) @@ -964,7 +967,7 @@ lsaauth (cygsid &usersid, user_groups &new_groups, struct passwd *pw) HANDLE user_token = NULL; - push_self_privilege (SE_TCB_PRIV, true); + push_self_privilege (SE_TCB_PRIVILEGE, true); /* Register as logon process. */ str2lsa (name, "Cygwin"); @@ -1978,7 +1981,8 @@ check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, { pset->PrivilegeCount = 1; pset->Control = 0; - pset->Privilege[0].Luid = *privilege_luid (SE_BACKUP_PRIV); + pset->Privilege[0].Luid.HighPart = 0L; + pset->Privilege[0].Luid.LowPart = SE_BACKUP_PRIVILEGE; pset->Privilege[0].Attributes = 0; if (PrivilegeCheck (tok, pset, &status) && status) granted_flags |= R_OK; @@ -1987,7 +1991,8 @@ check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, { pset->PrivilegeCount = 1; pset->Control = 0; - pset->Privilege[0].Luid = *privilege_luid (SE_RESTORE_PRIV); + pset->Privilege[0].Luid.HighPart = 0L; + pset->Privilege[0].Luid.LowPart = SE_RESTORE_PRIVILEGE; pset->Privilege[0].Attributes = 0; if (PrivilegeCheck (tok, pset, &status) && status) granted_flags |= W_OK; diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 861f53201..9aaaadb7d 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -23,6 +23,49 @@ details. */ #define ACL_DEFAULT_SIZE 3072 #define NO_SID ((PSID)NULL) +#ifndef SE_CREATE_TOKEN_PRIVILEGE +#define SE_CREATE_TOKEN_PRIVILEGE 2UL +#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE 3UL +#define SE_LOCK_MEMORY_PRIVILEGE 4UL +#define SE_INCREASE_QUOTA_PRIVILEGE 5UL +#define SE_MACHINE_ACCOUNT_PRIVILEGE 6UL +#define SE_TCB_PRIVILEGE 7UL +#define SE_SECURITY_PRIVILEGE 8UL +#define SE_TAKE_OWNERSHIP_PRIVILEGE 9UL +#define SE_LOAD_DRIVER_PRIVILEGE 10UL +#define SE_SYSTEM_PROFILE_PRIVILEGE 11UL +#define SE_SYSTEMTIME_PRIVILEGE 12UL +#define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13UL +#define SE_INC_BASE_PRIORITY_PRIVILEGE 14UL +#define SE_CREATE_PAGEFILE_PRIVILEGE 15UL +#define SE_CREATE_PERMANENT_PRIVILEGE 16UL +#define SE_BACKUP_PRIVILEGE 17UL +#define SE_RESTORE_PRIVILEGE 18UL +#define SE_SHUTDOWN_PRIVILEGE 19UL +#define SE_DEBUG_PRIVILEGE 20UL +#define SE_AUDIT_PRIVILEGE 21UL +#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE 22UL +#define SE_CHANGE_NOTIFY_PRIVILEGE 23UL +#define SE_REMOTE_SHUTDOWN_PRIVILEGE 24UL +/* Starting with Windows 2000 */ +#define SE_UNDOCK_PRIVILEGE 25UL +#define SE_SYNC_AGENT_PRIVILEGE 26UL +#define SE_ENABLE_DELEGATION_PRIVILEGE 27UL +#define SE_MANAGE_VOLUME_PRIVILEGE 28UL +/* Starting with Windows 2000 SP4, XP SP2, 2003 Server */ +#define SE_IMPERSONATE_PRIVILEGE 29UL +#define SE_CREATE_GLOBAL_PRIVILEGE 30UL +/* Starting with Vista */ +#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE 31UL +#define SE_RELABEL_PRIVILEGE 32UL +#define SE_INCREASE_WORKING_SET_PRIVILEGE 33UL +#define SE_TIME_ZONE_PRIVILEGE 34UL +#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE 35UL + +#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE + +#endif /* ! SE_CREATE_TOKEN_PRIVILEGE */ + /* Added for debugging purposes. */ typedef struct { BYTE Revision; @@ -279,48 +322,7 @@ extern cygpsid well_known_system_sid; extern cygpsid well_known_admins_sid; extern cygpsid fake_logon_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_RELABEL_PRIV, - SE_INCREASE_WORKING_SET_PRIV, - SE_TIME_ZONE_PRIV, - SE_CREATE_SYMBOLIC_LINK_PRIV, - - SE_NUM_PRIVS -}; - -const LUID *privilege_luid (enum cygpriv_idx idx); -const LUID *privilege_luid_by_name (const char *pname); +bool privilege_luid (const char *pname, LUID *luid); inline BOOL legal_sid_type (SID_NAME_USE type) @@ -380,11 +382,9 @@ bool get_logon_server (const char * domain, char * server, WCHAR *wserver, bool rediscovery); /* sec_helper.cc: Security helper functions. */ -int set_privilege (HANDLE token, const LUID *priv_luid, bool enable); +int set_privilege (HANDLE token, DWORD privilege, bool enable); void set_cygwin_privileges (HANDLE token); -#define set_process_privilege(p,v) set_privilege (hProcToken, privilege_luid (p), (v)) - #define _push_thread_privilege(_priv, _val, _check) { \ HANDLE _dup_token = NULL; \ HANDLE _token = (cygheap->user.issetuid () && (_check)) \ @@ -396,7 +396,7 @@ void set_cygwin_privileges (HANDLE token); else if (!ImpersonateLoggedOnUser (_dup_token)) \ debug_printf ("ImpersonateLoggedOnUser: %E"); \ else \ - set_privilege (_dup_token, privilege_luid (_priv), (_val)); + 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) diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 7923d5aa6..ef4376801 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -10,11 +10,13 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include "winsup.h" +#include "security.h" /* Minimal set of capabilities which is equivalent to NT4. */ static NO_COPY wincaps wincap_unknown = { chunksize:0, heapslop:0x0, + max_sys_priv:SE_CHANGE_NOTIFY_PRIVILEGE, is_server:false, has_security_descriptor_control:false, has_ip_helper_lib:false, @@ -43,6 +45,7 @@ static NO_COPY wincaps wincap_unknown = { static NO_COPY wincaps wincap_nt4 = { chunksize:0, heapslop:0x0, + max_sys_priv:SE_CHANGE_NOTIFY_PRIVILEGE, is_server:false, has_security_descriptor_control:false, has_ip_helper_lib:false, @@ -71,6 +74,7 @@ static NO_COPY wincaps wincap_nt4 = { static NO_COPY wincaps wincap_nt4sp4 = { chunksize:0, heapslop:0x0, + max_sys_priv:SE_CHANGE_NOTIFY_PRIVILEGE, is_server:false, has_security_descriptor_control:false, has_ip_helper_lib:true, @@ -99,6 +103,7 @@ static NO_COPY wincaps wincap_nt4sp4 = { static NO_COPY wincaps wincap_2000 = { chunksize:0, heapslop:0x0, + max_sys_priv:SE_MANAGE_VOLUME_PRIVILEGE, is_server:false, has_security_descriptor_control:true, has_ip_helper_lib:true, @@ -124,9 +129,39 @@ static NO_COPY wincaps wincap_2000 = { supports_all_posix_ai_flags:false, }; +static NO_COPY wincaps wincap_2000sp4 = { + chunksize:0, + heapslop:0x0, + max_sys_priv:SE_CREATE_GLOBAL_PRIVILEGE, + is_server:false, + has_security_descriptor_control:true, + has_ip_helper_lib:true, + has_broken_if_oper_status:false, + has_physical_mem_access:true, + has_process_io_counters:true, + has_terminal_services:true, + has_create_global_privilege:true, + has_ioctl_storage_get_media_types_ex:false, + has_extended_priority_class:true, + has_guid_volumes:true, + has_disk_ex_ioctls:false, + has_disabled_user_tos_setting:true, + has_fileid_dirinfo:true, + has_exclusiveaddruse:true, + has_buggy_restart_scan:true, + has_mandatory_integrity_control:false, + needs_logon_sid_in_sid_list:true, + needs_count_in_si_lpres2:false, + has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, + supports_all_posix_ai_flags:false, +}; + static NO_COPY wincaps wincap_xp = { chunksize:0, heapslop:0x0, + max_sys_priv:SE_MANAGE_VOLUME_PRIVILEGE, is_server:false, has_security_descriptor_control:true, has_ip_helper_lib:true, @@ -147,6 +182,64 @@ static NO_COPY wincaps wincap_xp = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, + supports_all_posix_ai_flags:false, +}; + +static NO_COPY wincaps wincap_xpsp1 = { + chunksize:0, + heapslop:0x0, + max_sys_priv:SE_MANAGE_VOLUME_PRIVILEGE, + is_server:false, + has_security_descriptor_control:true, + has_ip_helper_lib:true, + has_broken_if_oper_status:false, + has_physical_mem_access:true, + has_process_io_counters:true, + has_terminal_services:true, + has_create_global_privilege:false, + has_ioctl_storage_get_media_types_ex:true, + has_extended_priority_class:true, + has_guid_volumes:true, + has_disk_ex_ioctls:true, + has_disabled_user_tos_setting:true, + has_fileid_dirinfo:true, + has_exclusiveaddruse:true, + has_buggy_restart_scan:false, + has_mandatory_integrity_control:false, + needs_logon_sid_in_sid_list:false, + needs_count_in_si_lpres2:false, + has_recycle_dot_bin:false, + has_gaa_prefixes:true, + has_gaa_on_link_prefix:false, + supports_all_posix_ai_flags:false, +}; + +static NO_COPY wincaps wincap_xpsp2 = { + chunksize:0, + heapslop:0x0, + max_sys_priv:SE_CREATE_GLOBAL_PRIVILEGE, + is_server:false, + has_security_descriptor_control:true, + has_ip_helper_lib:true, + has_broken_if_oper_status:false, + has_physical_mem_access:true, + has_process_io_counters:true, + has_terminal_services:true, + has_create_global_privilege:true, + has_ioctl_storage_get_media_types_ex:true, + has_extended_priority_class:true, + has_guid_volumes:true, + has_disk_ex_ioctls:true, + has_disabled_user_tos_setting:true, + has_fileid_dirinfo:true, + has_exclusiveaddruse:true, + has_buggy_restart_scan:false, + has_mandatory_integrity_control:false, + needs_logon_sid_in_sid_list:false, + needs_count_in_si_lpres2:false, + has_recycle_dot_bin:false, has_gaa_prefixes:true, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, @@ -155,6 +248,7 @@ static NO_COPY wincaps wincap_xp = { static NO_COPY wincaps wincap_2003 = { chunksize:0, heapslop:0x4, + max_sys_priv:SE_CREATE_GLOBAL_PRIVILEGE, is_server:true, has_security_descriptor_control:true, has_ip_helper_lib:true, @@ -183,6 +277,7 @@ static NO_COPY wincaps wincap_2003 = { static NO_COPY wincaps wincap_vista = { chunksize:0, heapslop:0x4, + max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, is_server:false, has_security_descriptor_control:true, has_ip_helper_lib:true, @@ -248,13 +343,23 @@ wincapc::init () switch (version.dwMinorVersion) { case 0: - caps = &wincap_2000; + if (version.wServicePackMajor < 4) + caps = &wincap_2000; + else + caps = &wincap_2000sp4; break; case 1: caps = &wincap_xp; - if (version.wServicePackMajor < 1) - ((wincaps *)this->caps)->has_gaa_prefixes = false; + switch (version.wServicePackMajor) + { + case 0: + caps = &wincap_xp; + case 1: + caps = &wincap_xpsp1; + default: + caps = &wincap_xpsp2; + } break; default: diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 2215bf974..903e531ca 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -15,6 +15,7 @@ struct wincaps { DWORD chunksize; DWORD heapslop; + DWORD max_sys_priv; unsigned is_server : 1; unsigned has_security_descriptor_control : 1; unsigned has_ip_helper_lib : 1; @@ -59,6 +60,7 @@ public: DWORD IMPLEMENT (chunksize) DWORD IMPLEMENT (heapslop) + DWORD IMPLEMENT (max_sys_priv) bool IMPLEMENT (is_server) bool IMPLEMENT (has_security_descriptor_control) bool IMPLEMENT (has_ip_helper_lib) -- 2.43.5