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:
parent
e2742d467a
commit
42fad6ffa5
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
||||||
|
|
Loading…
Reference in New Issue