Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/sec_helper.cc')
-rw-r--r--winsup/cygwin/sec_helper.cc118
1 files changed, 86 insertions, 32 deletions
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
index 852ef5b52..3aa3b9d1d 100644
--- a/winsup/cygwin/sec_helper.cc
+++ b/winsup/cygwin/sec_helper.cc
@@ -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];
+}
+
+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 ((use_thread
- && !OpenThreadToken (GetCurrentThread (), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
- 0, &hToken))
- ||(!use_thread
- && !OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
- &hToken)))
+ 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);
}
/*