Commit 6a76a0ac authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

server: Check object's security when creating handles.

Don't check object's security when duplicating a handle of the same or lower access rights. Based on a patch by Vitaliy Margolen.
parent ca6fe3fb
...@@ -857,7 +857,7 @@ static void test_token_attr(void) ...@@ -857,7 +857,7 @@ static void test_token_attr(void)
BYTE buf[1024]; BYTE buf[1024];
DWORD bufsize = sizeof(buf); DWORD bufsize = sizeof(buf);
ret = GetTokenInformation(Token, TokenUser,(void*)buf, bufsize, &bufsize); ret = GetTokenInformation(Token, TokenUser,(void*)buf, bufsize, &bufsize);
todo_wine ok(ret, "GetTokenInformation failed with error %d\n", GetLastError()); ok(ret, "GetTokenInformation failed with error %d\n", GetLastError());
CloseHandle(Token); CloseHandle(Token);
} }
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "handle.h" #include "handle.h"
#include "process.h" #include "process.h"
#include "thread.h" #include "thread.h"
#include "security.h"
#include "request.h" #include "request.h"
struct handle_entry struct handle_entry
...@@ -222,11 +223,10 @@ static obj_handle_t alloc_entry( struct handle_table *table, void *obj, unsigned ...@@ -222,11 +223,10 @@ static obj_handle_t alloc_entry( struct handle_table *table, void *obj, unsigned
/* allocate a handle for an object, incrementing its refcount */ /* allocate a handle for an object, incrementing its refcount */
/* return the handle, or 0 on error */ /* return the handle, or 0 on error */
obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int access, unsigned int attr ) static obj_handle_t alloc_handle_no_access_check( struct process *process, void *ptr, unsigned int access, unsigned int attr )
{ {
struct object *obj = ptr; struct object *obj = ptr;
access = obj->ops->map_access( obj, access );
access &= ~RESERVED_ALL; access &= ~RESERVED_ALL;
if (attr & OBJ_INHERIT) access |= RESERVED_INHERIT; if (attr & OBJ_INHERIT) access |= RESERVED_INHERIT;
if (!process->handles) if (!process->handles)
...@@ -237,9 +237,20 @@ obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int acce ...@@ -237,9 +237,20 @@ obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int acce
return alloc_entry( process->handles, obj, access ); return alloc_entry( process->handles, obj, access );
} }
/* allocate a handle for an object, checking the dacl allows the process to */
/* access it and incrementing its refcount */
/* return the handle, or 0 on error */
obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int access, unsigned int attr )
{
struct object *obj = ptr;
access = obj->ops->map_access( obj, access );
if (access && !check_object_access( obj, &access )) return 0;
return alloc_handle_no_access_check( process, ptr, access, attr );
}
/* allocate a global handle for an object, incrementing its refcount */ /* allocate a global handle for an object, incrementing its refcount */
/* return the handle, or 0 on error */ /* return the handle, or 0 on error */
static obj_handle_t alloc_global_handle( void *obj, unsigned int access ) static obj_handle_t alloc_global_handle_no_access_check( void *obj, unsigned int access )
{ {
if (!global_table) if (!global_table)
{ {
...@@ -250,6 +261,15 @@ static obj_handle_t alloc_global_handle( void *obj, unsigned int access ) ...@@ -250,6 +261,15 @@ static obj_handle_t alloc_global_handle( void *obj, unsigned int access )
return handle_local_to_global( alloc_entry( global_table, obj, access )); return handle_local_to_global( alloc_entry( global_table, obj, access ));
} }
/* allocate a global handle for an object, checking the dacl allows the */
/* process to access it and incrementing its refcount and incrementing its refcount */
/* return the handle, or 0 on error */
static obj_handle_t alloc_global_handle( void *obj, unsigned int access )
{
if (access && !check_object_access( obj, &access )) return 0;
return alloc_global_handle_no_access_check( obj, access );
}
/* return a handle entry, or NULL if the handle is invalid */ /* return a handle entry, or NULL if the handle is invalid */
static struct handle_entry *get_handle( struct process *process, obj_handle_t handle ) static struct handle_entry *get_handle( struct process *process, obj_handle_t handle )
{ {
...@@ -449,25 +469,41 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str ...@@ -449,25 +469,41 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str
unsigned int access, unsigned int attr, unsigned int options ) unsigned int access, unsigned int attr, unsigned int options )
{ {
obj_handle_t res; obj_handle_t res;
struct handle_entry *entry;
unsigned int src_access;
struct object *obj = get_handle_obj( src, src_handle, 0, NULL ); struct object *obj = get_handle_obj( src, src_handle, 0, NULL );
if (!obj) return 0; if (!obj) return 0;
if ((entry = get_handle( src, src_handle )))
src_access = entry->access;
else /* pseudo-handle, give it full access */
{
src_access = obj->ops->map_access( obj, GENERIC_ALL );
clear_error();
}
src_access &= ~RESERVED_ALL;
if (options & DUP_HANDLE_SAME_ACCESS) if (options & DUP_HANDLE_SAME_ACCESS)
access = src_access;
else
access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL;
/* asking for the more access rights than src_access? */
if (access & ~src_access)
{ {
struct handle_entry *entry = get_handle( src, src_handle ); if (options & DUP_HANDLE_MAKE_GLOBAL)
if (entry) res = alloc_global_handle( obj, access );
access = entry->access; else
else /* pseudo-handle, give it full access */ res = alloc_handle( dst, obj, access, attr );
{
access = obj->ops->map_access( obj, GENERIC_ALL );
clear_error();
}
} }
access &= ~RESERVED_ALL;
if (options & DUP_HANDLE_MAKE_GLOBAL)
res = alloc_global_handle( obj, access );
else else
res = alloc_handle( dst, obj, access, attr ); {
if (options & DUP_HANDLE_MAKE_GLOBAL)
res = alloc_global_handle_no_access_check( obj, access );
else
res = alloc_handle_no_access_check( dst, obj, access, attr );
}
release_object( obj ); release_object( obj );
return res; return res;
} }
......
...@@ -47,6 +47,7 @@ extern int token_check_privileges( struct token *token, int all_required, ...@@ -47,6 +47,7 @@ extern int token_check_privileges( struct token *token, int all_required,
unsigned int count, LUID_AND_ATTRIBUTES *usedprivs); unsigned int count, LUID_AND_ATTRIBUTES *usedprivs);
extern const ACL *token_get_default_dacl( struct token *token ); extern const ACL *token_get_default_dacl( struct token *token );
extern void security_set_thread_token( struct thread *thread, obj_handle_t handle ); extern void security_set_thread_token( struct thread *thread, obj_handle_t handle );
extern int check_object_access( struct object *obj, unsigned int *access );
static inline int thread_single_check_privilege( struct thread *thread, const LUID *priv) static inline int thread_single_check_privilege( struct thread *thread, const LUID *priv)
{ {
......
...@@ -1005,6 +1005,36 @@ static void set_object_sd( struct object *obj, const struct security_descriptor ...@@ -1005,6 +1005,36 @@ static void set_object_sd( struct object *obj, const struct security_descriptor
obj->sd = pnew_sd; obj->sd = pnew_sd;
} }
int check_object_access(struct object *obj, unsigned int *access)
{
GENERIC_MAPPING mapping;
struct token *token = current->token ? current->token : current->process->token;
LUID_AND_ATTRIBUTES priv;
unsigned int status, priv_count = 1;
int res;
mapping.GenericAll = obj->ops->map_access( obj, GENERIC_ALL );
if (!obj->sd)
{
if (*access & MAXIMUM_ALLOWED)
*access = mapping.GenericAll;
return TRUE;
}
mapping.GenericRead = obj->ops->map_access( obj, GENERIC_READ );
mapping.GenericWrite = obj->ops->map_access( obj, GENERIC_WRITE );
mapping.GenericExecute = obj->ops->map_access( obj, GENERIC_EXECUTE );
res = token_access_check( token, obj->sd, *access, &priv, &priv_count,
&mapping, access, &status ) == STATUS_SUCCESS &&
status == STATUS_SUCCESS;
if (!res) set_error( STATUS_ACCESS_DENIED );
return res;
}
/* open a security token */ /* open a security token */
DECL_HANDLER(open_token) DECL_HANDLER(open_token)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment