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>
This commit is contained in:
Corinna Vinschen 2015-08-17 18:29:24 +02:00
parent e2742d467a
commit 42fad6ffa5
5 changed files with 194 additions and 25 deletions

View File

@ -1,3 +1,19 @@
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> 2015-11-18 Corinna Vinschen <corinna@vinschen.de>
* sec_acl.cc (get_posix_access): Fix class_perm in !new_style case. * sec_acl.cc (get_posix_access): Fix class_perm in !new_style case.

View File

@ -558,6 +558,12 @@ LoadDLLfunc (RegisterEventSourceW, 8, advapi32)
LoadDLLfunc (ReportEventW, 36, advapi32) LoadDLLfunc (ReportEventW, 36, advapi32)
LoadDLLfunc (SystemFunction036, 8, advapi32) /* Aka "RtlGenRandom" */ 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 (DnsQuery_A, 24, dnsapi)
LoadDLLfunc (DnsRecordListFree, 8, dnsapi) LoadDLLfunc (DnsRecordListFree, 8, dnsapi)

View File

@ -14,6 +14,8 @@ details. */
#include "winsup.h" #include "winsup.h"
#include <stdlib.h> #include <stdlib.h>
#include <sys/acl.h> #include <sys/acl.h>
#include <sys/queue.h>
#include <authz.h>
#include <wchar.h> #include <wchar.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
@ -324,29 +326,6 @@ cygsidlist::add (const PSID nsi, bool well_known)
return TRUE; 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 PSECURITY_DESCRIPTOR
security_descriptor::malloc (size_t nsize) security_descriptor::malloc (size_t nsize)
{ {
@ -690,3 +669,169 @@ _everyone_sd (void *buf, ACCESS_MASK access)
return psd; 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);
}

View File

@ -456,7 +456,8 @@ void set_security_attribute (path_conv &pc, int attribute,
PSECURITY_ATTRIBUTES psa, PSECURITY_ATTRIBUTES psa,
security_descriptor &sd_buf); 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 */ /* sec_acl.cc */
struct acl; struct acl;

View File

@ -1,6 +1,6 @@
/* winlean.h - Standard "lean" windows include /* 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. This file is part of Cygwin.
@ -20,6 +20,7 @@ details. */
autoloaded symbols, which in turn clashes with the definition in the autoloaded symbols, which in turn clashes with the definition in the
w32api library exporting the symbols. */ w32api library exporting the symbols. */
#define _ADVAPI32_ #define _ADVAPI32_
#define _AUTHZ_
#define _DSGETDCAPI_ #define _DSGETDCAPI_
#define _GDI32_ #define _GDI32_
#define _KERNEL32_ #define _KERNEL32_