server: Use the security descriptor passed in when creating events.

This commit is contained in:
Rob Shearman 2007-10-24 16:04:42 +01:00 committed by Alexandre Julliard
parent 87b15db617
commit dd9e392796
11 changed files with 184 additions and 24 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)
{

View File

@ -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 );

View File

@ -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)
{

View File

@ -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 );

View File

@ -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 );
}

View File

@ -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

View File

@ -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 );

View File

@ -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)
{

View File

@ -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 )