server: Use the security descriptor passed in when creating events.
This commit is contained in:
parent
87b15db617
commit
dd9e392796
|
@ -61,6 +61,74 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
|
||||
|
||||
static NTSTATUS create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_descriptor **server_sd,
|
||||
data_size_t *server_sd_len)
|
||||
{
|
||||
unsigned int len;
|
||||
PSID owner, group;
|
||||
ACL *dacl, *sacl;
|
||||
BOOLEAN owner_present, group_present, dacl_present, sacl_present;
|
||||
BOOLEAN defaulted;
|
||||
NTSTATUS status;
|
||||
unsigned char *ptr;
|
||||
|
||||
if (!nt_sd)
|
||||
{
|
||||
*server_sd = NULL;
|
||||
*server_sd_len = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
len = sizeof(struct security_descriptor);
|
||||
|
||||
status = RtlGetOwnerSecurityDescriptor(nt_sd, &owner, &owner_present);
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
status = RtlGetGroupSecurityDescriptor(nt_sd, &group, &group_present);
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
status = RtlGetSaclSecurityDescriptor(nt_sd, &sacl_present, &sacl, &defaulted);
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
status = RtlGetDaclSecurityDescriptor(nt_sd, &dacl_present, &dacl, &defaulted);
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
|
||||
if (owner_present)
|
||||
len += RtlLengthSid(owner);
|
||||
if (group_present)
|
||||
len += RtlLengthSid(group);
|
||||
if (sacl_present && sacl)
|
||||
len += sacl->AclSize;
|
||||
if (dacl_present && dacl)
|
||||
len += dacl->AclSize;
|
||||
|
||||
/* fix alignment for the Unicode name that follows the structure */
|
||||
len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
|
||||
*server_sd = RtlAllocateHeap(GetProcessHeap(), 0, len);
|
||||
if (!*server_sd) return STATUS_NO_MEMORY;
|
||||
|
||||
(*server_sd)->control = ((SECURITY_DESCRIPTOR *)nt_sd)->Control & ~SE_SELF_RELATIVE;
|
||||
(*server_sd)->owner_len = owner_present ? RtlLengthSid(owner) : 0;
|
||||
(*server_sd)->group_len = group_present ? RtlLengthSid(group) : 0;
|
||||
(*server_sd)->sacl_len = (sacl_present && sacl) ? sacl->AclSize : 0;
|
||||
(*server_sd)->dacl_len = (dacl_present && dacl) ? dacl->AclSize : 0;
|
||||
|
||||
ptr = (unsigned char *)(*server_sd + 1);
|
||||
memcpy(ptr, owner, (*server_sd)->owner_len);
|
||||
ptr += (*server_sd)->owner_len;
|
||||
memcpy(ptr, group, (*server_sd)->group_len);
|
||||
ptr += (*server_sd)->group_len;
|
||||
memcpy(ptr, sacl, (*server_sd)->sacl_len);
|
||||
ptr += (*server_sd)->sacl_len;
|
||||
memcpy(ptr, dacl, (*server_sd)->dacl_len);
|
||||
|
||||
*server_sd_len = len;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void free_struct_sd(struct security_descriptor *server_sd)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, server_sd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Semaphores
|
||||
*/
|
||||
|
@ -172,21 +240,35 @@ NTSTATUS WINAPI NtCreateEvent(
|
|||
{
|
||||
DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
|
||||
NTSTATUS ret;
|
||||
struct security_descriptor *sd = NULL;
|
||||
struct object_attributes objattr;
|
||||
|
||||
if (len >= MAX_PATH * sizeof(WCHAR)) return STATUS_NAME_TOO_LONG;
|
||||
|
||||
objattr.rootdir = attr ? attr->RootDirectory : 0;
|
||||
objattr.sd_len = 0;
|
||||
if (attr)
|
||||
{
|
||||
ret = create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len );
|
||||
if (ret != STATUS_SUCCESS) return ret;
|
||||
}
|
||||
|
||||
SERVER_START_REQ( create_event )
|
||||
{
|
||||
req->access = DesiredAccess;
|
||||
req->attributes = (attr) ? attr->Attributes : 0;
|
||||
req->rootdir = attr ? attr->RootDirectory : 0;
|
||||
req->manual_reset = ManualReset;
|
||||
req->initial_state = InitialState;
|
||||
wine_server_add_data( req, &objattr, sizeof(objattr) );
|
||||
if (objattr.sd_len) wine_server_add_data( req, sd, objattr.sd_len );
|
||||
if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
|
||||
ret = wine_server_call( req );
|
||||
*EventHandle = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
free_struct_sd( sd );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -215,6 +215,14 @@ struct security_descriptor
|
|||
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct object_attributes
|
||||
{
|
||||
obj_handle_t rootdir;
|
||||
data_size_t sd_len;
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct token_groups
|
||||
|
@ -860,10 +868,9 @@ struct create_event_request
|
|||
struct request_header __header;
|
||||
unsigned int access;
|
||||
unsigned int attributes;
|
||||
obj_handle_t rootdir;
|
||||
int manual_reset;
|
||||
int initial_state;
|
||||
/* VARARG(name,unicode_str); */
|
||||
/* VARARG(objattr,object_attributes); */
|
||||
};
|
||||
struct create_event_reply
|
||||
{
|
||||
|
@ -4873,6 +4880,6 @@ union generic_reply
|
|||
struct set_completion_info_reply set_completion_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 317
|
||||
#define SERVER_PROTOCOL_VERSION 318
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -289,7 +289,7 @@ static struct object *create_console_input( struct thread* renderer )
|
|||
console_input->input_cp = 0;
|
||||
console_input->output_cp = 0;
|
||||
console_input->win = 0;
|
||||
console_input->event = create_event( NULL, NULL, 0, 1, 0 );
|
||||
console_input->event = create_event( NULL, NULL, 0, 1, 0, NULL );
|
||||
|
||||
if (!console_input->history || !console_input->evt)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "handle.h"
|
||||
#include "thread.h"
|
||||
#include "request.h"
|
||||
#include "security.h"
|
||||
|
||||
struct event
|
||||
{
|
||||
|
@ -69,7 +70,8 @@ static const struct object_ops event_ops =
|
|||
|
||||
|
||||
struct event *create_event( struct directory *root, const struct unicode_str *name,
|
||||
unsigned int attr, int manual_reset, int initial_state )
|
||||
unsigned int attr, int manual_reset, int initial_state,
|
||||
const struct security_descriptor *sd )
|
||||
{
|
||||
struct event *event;
|
||||
|
||||
|
@ -80,6 +82,10 @@ struct event *create_event( struct directory *root, const struct unicode_str *na
|
|||
/* initialize it if it didn't already exist */
|
||||
event->manual_reset = manual_reset;
|
||||
event->signaled = initial_state;
|
||||
if (sd) default_set_sd( &event->obj, sd, OWNER_SECURITY_INFORMATION|
|
||||
GROUP_SECURITY_INFORMATION|
|
||||
DACL_SECURITY_INFORMATION|
|
||||
SACL_SECURITY_INFORMATION );
|
||||
}
|
||||
}
|
||||
return event;
|
||||
|
@ -165,13 +171,24 @@ DECL_HANDLER(create_event)
|
|||
struct event *event;
|
||||
struct unicode_str name;
|
||||
struct directory *root = NULL;
|
||||
const struct object_attributes *objattr = get_req_data();
|
||||
const struct security_descriptor *sd;
|
||||
|
||||
reply->handle = 0;
|
||||
get_req_unicode_str( &name );
|
||||
if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
|
||||
|
||||
if (!objattr_is_valid( objattr, get_req_data_size() ))
|
||||
return;
|
||||
|
||||
if ((event = create_event( root, &name, req->attributes, req->manual_reset, req->initial_state )))
|
||||
sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL;
|
||||
|
||||
/* get unicode string */
|
||||
name.len = ((get_req_data_size() - sizeof(*objattr) - objattr->sd_len) / sizeof(WCHAR)) * sizeof(WCHAR);
|
||||
name.str = (const WCHAR *)get_req_data() + (sizeof(*objattr) + objattr->sd_len) / sizeof(WCHAR);
|
||||
|
||||
if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 )))
|
||||
return;
|
||||
|
||||
if ((event = create_event( root, &name, req->attributes, req->manual_reset, req->initial_state, sd )))
|
||||
{
|
||||
reply->handle = alloc_handle( current->process, event, req->access, req->attributes );
|
||||
release_object( event );
|
||||
|
|
|
@ -539,7 +539,7 @@ static void pipe_server_flush( struct fd *fd, struct event **event )
|
|||
{
|
||||
/* this kind of sux -
|
||||
there's no unix way to be alerted when a pipe becomes empty */
|
||||
server->event = create_event( NULL, NULL, 0, 0, 0 );
|
||||
server->event = create_event( NULL, NULL, 0, 0, 0, NULL );
|
||||
if (!server->event) return;
|
||||
server->flush_poll = add_timeout_user( -TICKS_PER_SEC / 10, check_flushed, server );
|
||||
*event = server->event;
|
||||
|
@ -569,7 +569,7 @@ static enum server_fd_type pipe_client_get_fd_type( struct fd *fd )
|
|||
static obj_handle_t alloc_wait_event( struct process *process )
|
||||
{
|
||||
obj_handle_t handle = 0;
|
||||
struct event *event = create_event( NULL, NULL, 0, 1, 0 );
|
||||
struct event *event = create_event( NULL, NULL, 0, 1, 0, NULL );
|
||||
|
||||
if (event)
|
||||
{
|
||||
|
|
|
@ -148,7 +148,8 @@ extern void close_objects(void);
|
|||
struct event;
|
||||
|
||||
extern struct event *create_event( struct directory *root, const struct unicode_str *name,
|
||||
unsigned int attr, int manual_reset, int initial_state );
|
||||
unsigned int attr, int manual_reset, int initial_state,
|
||||
const struct security_descriptor *sd );
|
||||
extern struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
|
||||
extern void pulse_event( struct event *event );
|
||||
extern void set_event( struct event *event );
|
||||
|
|
|
@ -991,7 +991,7 @@ DECL_HANDLER(init_process_done)
|
|||
generate_startup_debug_events( process, req->entry );
|
||||
set_process_startup_state( process, STARTUP_DONE );
|
||||
|
||||
if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0 );
|
||||
if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0, NULL );
|
||||
if (current->suspend + process->suspend > 0) stop_thread( current );
|
||||
if (process->debugger) set_process_debug_flag( process, 1 );
|
||||
}
|
||||
|
@ -1170,7 +1170,7 @@ DECL_HANDLER(make_process_system)
|
|||
|
||||
if (!user_process_event)
|
||||
{
|
||||
if (!(user_process_event = create_event( NULL, NULL, 0, 1, 0 ))) return;
|
||||
if (!(user_process_event = create_event( NULL, NULL, 0, 1, 0, NULL ))) return;
|
||||
make_object_static( (struct object *)user_process_event );
|
||||
}
|
||||
|
||||
|
|
|
@ -227,17 +227,25 @@ struct security_descriptor
|
|||
data_size_t group_len;
|
||||
data_size_t sacl_len;
|
||||
data_size_t dacl_len;
|
||||
/* VARARGS(owner,SID); */
|
||||
/* VARARGS(group,SID); */
|
||||
/* VARARGS(sacl,ACL); */
|
||||
/* VARARGS(dacl,ACL); */
|
||||
/* VARARG(owner,SID); */
|
||||
/* VARARG(group,SID); */
|
||||
/* VARARG(sacl,ACL); */
|
||||
/* VARARG(dacl,ACL); */
|
||||
};
|
||||
|
||||
struct object_attributes
|
||||
{
|
||||
obj_handle_t rootdir; /* root directory */
|
||||
data_size_t sd_len; /* length of security_descriptor data. may be 0 */
|
||||
/* VARARG(sd,security_descriptor); */
|
||||
/* VARARG(name,unicode_str); */
|
||||
};
|
||||
|
||||
struct token_groups
|
||||
{
|
||||
unsigned int count;
|
||||
/* unsigned int attributes[count]; */
|
||||
/* VARARGS(sids,SID); */
|
||||
/* VARARG(sids,SID); */
|
||||
};
|
||||
|
||||
enum apc_type
|
||||
|
@ -743,10 +751,9 @@ typedef union
|
|||
@REQ(create_event)
|
||||
unsigned int access; /* wanted access rights */
|
||||
unsigned int attributes; /* object attributes */
|
||||
obj_handle_t rootdir; /* root directory */
|
||||
int manual_reset; /* manual reset event */
|
||||
int initial_state; /* initial state of the event */
|
||||
VARARG(name,unicode_str); /* object name */
|
||||
VARARG(objattr,object_attributes); /* object attributes */
|
||||
@REPLY
|
||||
obj_handle_t handle; /* handle to the event */
|
||||
@END
|
||||
|
|
|
@ -127,3 +127,7 @@ static inline const SID *sd_get_group( const struct security_descriptor *sd )
|
|||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* determines whether an object_attributes struct is valid in a buffer
|
||||
* and calls set_error appropriately */
|
||||
extern int objattr_is_valid( const struct object_attributes *objattr, data_size_t size );
|
||||
|
|
|
@ -305,6 +305,29 @@ int sd_is_valid( const struct security_descriptor *sd, data_size_t size )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* determines whether an object_attributes struct is valid in a buffer
|
||||
* and calls set_error appropriately */
|
||||
int objattr_is_valid( const struct object_attributes *objattr, data_size_t size )
|
||||
{
|
||||
if ((size < sizeof(*objattr)) || (size - sizeof(*objattr) < objattr->sd_len))
|
||||
{
|
||||
set_error( STATUS_ACCESS_VIOLATION );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (objattr->sd_len)
|
||||
{
|
||||
const struct security_descriptor *sd = (const struct security_descriptor *)(objattr + 1);
|
||||
if (!sd_is_valid( sd, objattr->sd_len ))
|
||||
{
|
||||
set_error( STATUS_INVALID_SECURITY_DESCR );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* maps from generic rights to specific rights as given by a mapping */
|
||||
static inline void map_generic_mask(unsigned int *mask, const GENERIC_MAPPING *mapping)
|
||||
{
|
||||
|
|
|
@ -782,6 +782,26 @@ static void dump_varargs_token_groups( data_size_t size )
|
|||
fputc( '}', stderr );
|
||||
}
|
||||
|
||||
static void dump_varargs_object_attributes( data_size_t size )
|
||||
{
|
||||
const struct object_attributes *objattr = cur_data;
|
||||
fputc( '{', stderr );
|
||||
if (size >= sizeof(struct object_attributes))
|
||||
{
|
||||
const WCHAR *str;
|
||||
fprintf( stderr, "rootdir=%p,sd=", objattr->rootdir );
|
||||
if (objattr->sd_len > size - sizeof(*objattr)) return;
|
||||
dump_inline_security_descriptor( (const struct security_descriptor *)(objattr + 1), objattr->sd_len );
|
||||
str = (const WCHAR *)cur_data + (sizeof(*objattr) + objattr->sd_len) / sizeof(WCHAR);
|
||||
fprintf( stderr, ",name=L\"" );
|
||||
dump_strW( str, (size - sizeof(*objattr) - objattr->sd_len) / sizeof(WCHAR),
|
||||
stderr, "\"\"" );
|
||||
fputc( '\"', stderr );
|
||||
remove_data( size );
|
||||
}
|
||||
fputc( '}', stderr );
|
||||
}
|
||||
|
||||
typedef void (*dump_func)( const void *req );
|
||||
|
||||
/* Everything below this line is generated automatically by tools/make_requests */
|
||||
|
@ -1136,11 +1156,10 @@ static void dump_create_event_request( const struct create_event_request *req )
|
|||
{
|
||||
fprintf( stderr, " access=%08x,", req->access );
|
||||
fprintf( stderr, " attributes=%08x,", req->attributes );
|
||||
fprintf( stderr, " rootdir=%p,", req->rootdir );
|
||||
fprintf( stderr, " manual_reset=%d,", req->manual_reset );
|
||||
fprintf( stderr, " initial_state=%d,", req->initial_state );
|
||||
fprintf( stderr, " name=" );
|
||||
dump_varargs_unicode_str( cur_size );
|
||||
fprintf( stderr, " objattr=" );
|
||||
dump_varargs_object_attributes( cur_size );
|
||||
}
|
||||
|
||||
static void dump_create_event_reply( const struct create_event_reply *req )
|
||||
|
|
Loading…
Reference in New Issue