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
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2015-08-17 19:29:24 +0300
committerCorinna Vinschen <corinna@vinschen.de>2015-11-19 00:28:33 +0300
commit42fad6ffa56f4627f414c8b76758bd71592e8400 (patch)
treea21b94a9819c130425c85f4fe62154b8bd22fe27 /winsup
parente2742d467a9f02803582787a111c6bb260969d15 (diff)
Add Authz class to compute exact POSIX user perms in a security descriptor
* autoload.cc (AuthzAccessCheck): Import. (AuthzFreeContext): Import. (AuthzInitializeContextFromSid): Import. (AuthzInitializeContextFromToken): Import. (AuthzInitializeResourceManager): Import. * sec_helper.cc (get_sids_info): Remove. (class authz_ctx_cache_entry): New class. (class authz_ctx_cache): New class. (class authz_ctx): New class. (authz_get_user_attribute): New function. * security.h (get_sids_info): Drop prototype. (authz_get_user_attribute): Add prototype. * winlean.h (_AUTHZ_): Define. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog16
-rw-r--r--winsup/cygwin/autoload.cc6
-rw-r--r--winsup/cygwin/sec_helper.cc191
-rw-r--r--winsup/cygwin/security.h3
-rw-r--r--winsup/cygwin/winlean.h3
5 files changed, 194 insertions, 25 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 987b4c008..6d0f91afe 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,21 @@
2015-11-18 Corinna Vinschen <corinna@vinschen.de>
+ * autoload.cc (AuthzAccessCheck): Import.
+ (AuthzFreeContext): Import.
+ (AuthzInitializeContextFromSid): Import.
+ (AuthzInitializeContextFromToken): Import.
+ (AuthzInitializeResourceManager): Import.
+ * sec_helper.cc (get_sids_info): Remove.
+ (class authz_ctx_cache_entry): New class.
+ (class authz_ctx_cache): New class.
+ (class authz_ctx): New class.
+ (authz_get_user_attribute): New function.
+ * security.h (get_sids_info): Drop prototype.
+ (authz_get_user_attribute): Add prototype.
+ * winlean.h (_AUTHZ_): Define.
+
+2015-11-18 Corinna Vinschen <corinna@vinschen.de>
+
* sec_acl.cc (get_posix_access): Fix class_perm in !new_style case.
2015-11-18 Corinna Vinschen <corinna@vinschen.de>
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 0192c6d64..e14647c2d 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -558,6 +558,12 @@ LoadDLLfunc (RegisterEventSourceW, 8, advapi32)
LoadDLLfunc (ReportEventW, 36, advapi32)
LoadDLLfunc (SystemFunction036, 8, advapi32) /* Aka "RtlGenRandom" */
+LoadDLLfunc (AuthzAccessCheck, 36, authz)
+LoadDLLfunc (AuthzFreeContext, 4, authz)
+LoadDLLfunc (AuthzInitializeContextFromSid, 32, authz)
+LoadDLLfunc (AuthzInitializeContextFromToken, 32, authz)
+LoadDLLfunc (AuthzInitializeResourceManager, 24, authz)
+
LoadDLLfunc (DnsQuery_A, 24, dnsapi)
LoadDLLfunc (DnsRecordListFree, 8, dnsapi)
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
index ab86aa7a4..40b8017d1 100644
--- a/winsup/cygwin/sec_helper.cc
+++ b/winsup/cygwin/sec_helper.cc
@@ -14,6 +14,8 @@ details. */
#include "winsup.h"
#include <stdlib.h>
#include <sys/acl.h>
+#include <sys/queue.h>
+#include <authz.h>
#include <wchar.h>
#include "cygerrno.h"
#include "security.h"
@@ -324,29 +326,6 @@ cygsidlist::add (const PSID nsi, bool well_known)
return TRUE;
}
-bool
-get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gidret)
-{
- BOOL ret = false;
- cyg_ldap cldap;
-
- owner_sid.debug_print ("get_sids_info: owner SID =");
- group_sid.debug_print ("get_sids_info: group SID =");
-
- *uidret = owner_sid.get_uid (&cldap);
- *gidret = group_sid.get_gid (&cldap);
- if (*uidret == myself->uid)
- {
- if (*gidret == myself->gid)
- ret = TRUE;
- else
- CheckTokenMembership (cygheap->user.issetuid ()
- ? cygheap->user.imp_token () : NULL,
- group_sid, &ret);
- }
- return (bool) ret;
-}
-
PSECURITY_DESCRIPTOR
security_descriptor::malloc (size_t nsize)
{
@@ -690,3 +669,169 @@ _everyone_sd (void *buf, ACCESS_MASK access)
return psd;
}
+static NO_COPY muto authz_guard;
+static LUID authz_dummy_luid = { 0 };
+
+class authz_ctx_cache_entry
+{
+ SLIST_ENTRY (authz_ctx_cache_entry) ctx_next;
+ cygsid sid;
+ AUTHZ_CLIENT_CONTEXT_HANDLE ctx_hdl;
+
+ authz_ctx_cache_entry ()
+ : sid (NO_SID), ctx_hdl (NULL)
+ {
+ ctx_next.sle_next = NULL;
+ }
+ authz_ctx_cache_entry (bool)
+ : sid (NO_SID), ctx_hdl (NULL)
+ {
+ ctx_next.sle_next = NULL;
+ }
+ void set (PSID psid, AUTHZ_CLIENT_CONTEXT_HANDLE hdl)
+ {
+ sid = psid;
+ ctx_hdl = hdl;
+ }
+ bool is (PSID psid) const { return RtlEqualSid (sid, psid); }
+ AUTHZ_CLIENT_CONTEXT_HANDLE context () const { return ctx_hdl; }
+
+ friend class authz_ctx_cache;
+};
+
+class authz_ctx_cache
+{
+ SLIST_HEAD (, authz_ctx_cache_entry) ctx_list;
+
+ AUTHZ_CLIENT_CONTEXT_HANDLE context (PSID);
+
+ friend class authz_ctx;
+};
+
+class authz_ctx
+{
+ AUTHZ_RESOURCE_MANAGER_HANDLE authz_hdl;
+ AUTHZ_CLIENT_CONTEXT_HANDLE user_ctx_hdl;
+ authz_ctx_cache ctx_cache;
+ operator AUTHZ_RESOURCE_MANAGER_HANDLE ();
+
+ friend class authz_ctx_cache;
+public:
+ void get_user_attribute (mode_t *, PSECURITY_DESCRIPTOR, PSID);
+};
+
+/* Authz handles are not inheritable. */
+static NO_COPY authz_ctx authz;
+
+authz_ctx::operator AUTHZ_RESOURCE_MANAGER_HANDLE ()
+{
+ if (!authz_hdl)
+ {
+ /* Create handle to Authz resource manager */
+ authz_guard.init ("authz_guard")->acquire ();
+ if (!authz_hdl
+ && !AuthzInitializeResourceManager (AUTHZ_RM_FLAG_NO_AUDIT,
+ NULL, NULL, NULL, NULL,
+ &authz_hdl))
+ debug_printf ("AuthzInitializeResourceManager, %E");
+ authz_guard.release ();
+ }
+ return authz_hdl;
+}
+
+AUTHZ_CLIENT_CONTEXT_HANDLE
+authz_ctx_cache::context (PSID user_sid)
+{
+ authz_ctx_cache_entry *entry;
+ AUTHZ_CLIENT_CONTEXT_HANDLE ctx_hdl = NULL;
+
+ SLIST_FOREACH (entry, &ctx_list, ctx_next)
+ {
+ if (entry->is (user_sid))
+ return entry->context ();
+ }
+ entry = new authz_ctx_cache_entry (true);
+ /* If the user is the current user, prefer to create the context from the
+ token, as outlined in MSDN. */
+ if (RtlEqualSid (user_sid, cygheap->user.sid ())
+ && !AuthzInitializeContextFromToken (0, cygheap->user.issetuid ()
+ ? cygheap->user.primary_token ()
+ : hProcToken,
+ authz, NULL, authz_dummy_luid,
+ NULL, &ctx_hdl))
+ debug_printf ("AuthzInitializeContextFromToken, %E");
+ /* In any other case, create the context from the user SID. */
+ else if (!AuthzInitializeContextFromSid (0, user_sid, authz, NULL,
+ authz_dummy_luid, NULL, &ctx_hdl))
+ debug_printf ("AuthzInitializeContextFromSid, %E");
+ else
+ {
+ entry->set (user_sid, ctx_hdl);
+ authz_guard.acquire ();
+ SLIST_INSERT_HEAD (&ctx_list, entry, ctx_next);
+ authz_guard.release ();
+ return entry->context ();
+ }
+ delete entry;
+ return NULL;
+}
+
+/* Ask Authz for the effective user permissions of the user with SID user_sid
+ on the object with security descriptor psd. We're caching the handles for
+ the Authz resource manager and the user contexts. */
+void
+authz_ctx::get_user_attribute (mode_t *attribute, PSECURITY_DESCRIPTOR psd,
+ PSID user_sid)
+{
+ /* If the owner is the main user of the process token (not some impersonated
+ user), cache the user context in the global user_ctx_hdl variable. */
+ AUTHZ_CLIENT_CONTEXT_HANDLE ctx_hdl = NULL;
+ if (RtlEqualSid (user_sid, cygheap->user.sid ())
+ && !cygheap->user.issetuid ())
+ {
+ if (!user_ctx_hdl)
+ {
+ authz_guard.acquire ();
+ if (!AuthzInitializeContextFromToken (0, hProcToken, authz, NULL,
+ authz_dummy_luid, NULL,
+ &user_ctx_hdl))
+ debug_printf ("AuthzInitializeContextFromToken, %E");
+ authz_guard.release ();
+ }
+ if (user_ctx_hdl)
+ ctx_hdl = user_ctx_hdl;
+ }
+ if (!ctx_hdl && !(ctx_hdl = ctx_cache.context (user_sid)))
+ return;
+ /* All set, check access. */
+ ACCESS_MASK access = 0;
+ DWORD error = 0;
+ AUTHZ_ACCESS_REQUEST req = {
+ .DesiredAccess = MAXIMUM_ALLOWED,
+ .PrincipalSelfSid = NULL,
+ .ObjectTypeList = NULL,
+ .ObjectTypeListLength = 0,
+ .OptionalArguments = NULL
+ };
+ AUTHZ_ACCESS_REPLY repl = {
+ .ResultListLength = 1,
+ .GrantedAccessMask = &access,
+ .SaclEvaluationResults = NULL,
+ .Error = &error
+ };
+ if (AuthzAccessCheck (0, ctx_hdl, &req, NULL, psd, NULL, 0, &repl, NULL))
+ {
+ if (access & FILE_READ_BITS)
+ *attribute |= S_IRUSR;
+ if (access & FILE_WRITE_BITS)
+ *attribute |= S_IWUSR;
+ if (access & FILE_EXEC_BITS)
+ *attribute |= S_IXUSR;
+ }
+}
+
+void authz_get_user_attribute (mode_t *attribute, PSECURITY_DESCRIPTOR psd,
+ PSID user_sid)
+{
+ authz.get_user_attribute (attribute, psd, user_sid);
+}
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 5378b2a45..9c70121ae 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -456,7 +456,8 @@ void set_security_attribute (path_conv &pc, int attribute,
PSECURITY_ATTRIBUTES psa,
security_descriptor &sd_buf);
-bool get_sids_info (cygpsid, cygpsid, uid_t * , gid_t *);
+void authz_get_user_attribute (mode_t *attribute, PSECURITY_DESCRIPTOR psd,
+ PSID user_sid);
/* sec_acl.cc */
struct acl;
diff --git a/winsup/cygwin/winlean.h b/winsup/cygwin/winlean.h
index 329199a28..cb9b07cd7 100644
--- a/winsup/cygwin/winlean.h
+++ b/winsup/cygwin/winlean.h
@@ -1,6 +1,6 @@
/* winlean.h - Standard "lean" windows include
- Copyright 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ Copyright 2010, 2011, 2012, 2013, 2014, 2015 Red Hat, Inc.
This file is part of Cygwin.
@@ -20,6 +20,7 @@ details. */
autoloaded symbols, which in turn clashes with the definition in the
w32api library exporting the symbols. */
#define _ADVAPI32_
+#define _AUTHZ_
#define _DSGETDCAPI_
#define _GDI32_
#define _KERNEL32_