diff --git a/server/event.c b/server/event.c index 971c054b86a..591f1e2df64 100644 --- a/server/event.c +++ b/server/event.c @@ -287,16 +287,10 @@ 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; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); - reply->handle = 0; - - if (!objattr_is_valid( objattr, get_req_data_size() )) - return; - - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - objattr_get_name( objattr, &name ); + if (!objattr) return; if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return; @@ -378,13 +372,10 @@ DECL_HANDLER(create_keyed_event) struct keyed_event *event; struct unicode_str name; struct directory *root = NULL; - const struct object_attributes *objattr = get_req_data(); const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); - if (!objattr_is_valid( objattr, get_req_data_size() )) return; - - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - objattr_get_name( objattr, &name ); + if (!objattr) return; if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return; diff --git a/server/file.c b/server/file.c index 3cd1675b32e..9fd3a9e957e 100644 --- a/server/file.c +++ b/server/file.c @@ -686,17 +686,16 @@ DECL_HANDLER(create_file) { struct object *file; struct fd *root_fd = NULL; - const struct object_attributes *objattr = get_req_data(); + struct unicode_str unicode_name; const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &unicode_name ); const char *name; data_size_t name_len; - reply->handle = 0; + if (!objattr) return; - if (!objattr_is_valid( objattr, get_req_data_size() )) - return; /* name is transferred in the unix codepage outside of the objattr structure */ - if (objattr->name_len) + if (unicode_name.len) { set_error( STATUS_INVALID_PARAMETER ); return; @@ -712,8 +711,6 @@ DECL_HANDLER(create_file) if (!root_fd) return; } - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - name = (const char *)get_req_data() + sizeof(*objattr) + objattr->sd_len; name_len = get_req_data_size() - sizeof(*objattr) - objattr->sd_len; diff --git a/server/mapping.c b/server/mapping.c index f9ca017eb3b..e206dea8eec 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -664,16 +664,10 @@ DECL_HANDLER(create_mapping) struct object *obj; struct unicode_str name; struct directory *root = NULL; - const struct object_attributes *objattr = get_req_data(); const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); - reply->handle = 0; - - if (!objattr_is_valid( objattr, get_req_data_size() )) - return; - - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - objattr_get_name( objattr, &name ); + if (!objattr) return; if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return; diff --git a/server/mutex.c b/server/mutex.c index 3bee320b10a..98490e00e4b 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -211,16 +211,10 @@ DECL_HANDLER(create_mutex) struct mutex *mutex; struct unicode_str name; struct directory *root = NULL; - const struct object_attributes *objattr = get_req_data(); const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); - reply->handle = 0; - - if (!objattr_is_valid( objattr, get_req_data_size() )) - return; - - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - objattr_get_name( objattr, &name ); + if (!objattr) return; if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return; diff --git a/server/named_pipe.c b/server/named_pipe.c index b9f0379a1c8..870192d67e9 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -923,8 +923,10 @@ DECL_HANDLER(create_named_pipe) struct pipe_server *server; struct unicode_str name; struct directory *root = NULL; - const struct object_attributes *objattr = get_req_data(); const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); + + if (!objattr) return; if (!req->sharing || (req->sharing & ~(FILE_SHARE_READ | FILE_SHARE_WRITE)) || (!(req->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE) && (req->flags & NAMED_PIPE_MESSAGE_STREAM_READ))) @@ -933,14 +935,6 @@ DECL_HANDLER(create_named_pipe) return; } - reply->handle = 0; - - if (!objattr_is_valid( objattr, get_req_data_size() )) - return; - - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - objattr_get_name( objattr, &name ); - if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return; diff --git a/server/process.c b/server/process.c index 3ccf8eb0347..ce26947fc20 100644 --- a/server/process.c +++ b/server/process.c @@ -1539,13 +1539,10 @@ DECL_HANDLER(create_job) struct job *job; struct unicode_str name; struct directory *root = NULL; - const struct object_attributes *objattr = get_req_data(); const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); - if (!objattr_is_valid( objattr, get_req_data_size() )) return; - - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - objattr_get_name( objattr, &name ); + if (!objattr) return; if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return; diff --git a/server/request.c b/server/request.c index f78026a061d..7b7d8b1b3fc 100644 --- a/server/request.c +++ b/server/request.c @@ -65,6 +65,8 @@ #include "file.h" #include "process.h" +#include "thread.h" +#include "security.h" #define WANT_REQUEST_HANDLERS #include "request.h" @@ -163,6 +165,31 @@ void *set_reply_data_size( data_size_t size ) return current->reply_data; } +/* return object attributes from the current request */ +const struct object_attributes *get_req_object_attributes( const struct security_descriptor **sd, + struct unicode_str *name ) +{ + const struct object_attributes *attr = get_req_data(); + data_size_t size = get_req_data_size(); + + if ((size < sizeof(*attr)) || (size - sizeof(*attr) < attr->sd_len) || + (size - sizeof(*attr) - attr->sd_len < attr->name_len)) + { + set_error( STATUS_ACCESS_VIOLATION ); + return NULL; + } + if (attr->sd_len && !sd_is_valid( (const struct security_descriptor *)(attr + 1), attr->sd_len )) + { + set_error( STATUS_INVALID_SECURITY_DESCR ); + return NULL; + } + + *sd = attr->sd_len ? (const struct security_descriptor *)(attr + 1) : NULL; + name->len = (attr->name_len / sizeof(WCHAR)) * sizeof(WCHAR); + name->str = (const WCHAR *)(attr + 1) + attr->sd_len / sizeof(WCHAR); + return attr; +} + /* write the remaining part of the reply */ void write_reply( struct thread *thread ) { diff --git a/server/request.h b/server/request.h index 9df89ed65de..b2e57194b3b 100644 --- a/server/request.h +++ b/server/request.h @@ -46,6 +46,8 @@ extern void fatal_error( const char *err, ... ); extern const char *get_config_dir(void); extern void *set_reply_data_size( data_size_t size ); +extern const struct object_attributes *get_req_object_attributes( const struct security_descriptor **sd, + struct unicode_str *name ); extern int receive_fd( struct process *process ); extern int send_client_fd( struct process *process, int fd, obj_handle_t handle ); extern void read_request( struct thread *thread ); diff --git a/server/security.h b/server/security.h index 855f2e77efb..925a85b90a6 100644 --- a/server/security.h +++ b/server/security.h @@ -139,13 +139,4 @@ static inline const SID *sd_get_group( const struct security_descriptor *sd ) 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 ); -static inline void objattr_get_name( const struct object_attributes *objattr, struct unicode_str *name ) -{ - name->len = ((objattr->name_len) / sizeof(WCHAR)) * sizeof(WCHAR); - name->str = (const WCHAR *)objattr + (sizeof(*objattr) + objattr->sd_len) / sizeof(WCHAR); -} - #endif /* __WINE_SERVER_SECURITY_H */ diff --git a/server/semaphore.c b/server/semaphore.c index a0bf478d9f4..a9786b13609 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -179,16 +179,10 @@ DECL_HANDLER(create_semaphore) struct semaphore *sem; struct unicode_str name; struct directory *root = NULL; - const struct object_attributes *objattr = get_req_data(); const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name ); - reply->handle = 0; - - if (!objattr_is_valid( objattr, get_req_data_size() )) - return; - - sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL; - objattr_get_name( objattr, &name ); + if (!objattr) return; if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return; diff --git a/server/token.c b/server/token.c index 6c2871f1161..da1f2557588 100644 --- a/server/token.c +++ b/server/token.c @@ -334,30 +334,6 @@ 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) || - (size - sizeof(*objattr) - objattr->sd_len < objattr->name_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) {