Module: wine Branch: master Commit: 7c08e787b1a0381a4741cd8710834bfbae29e32c URL: http://source.winehq.org/git/wine.git/?a=commit;h=7c08e787b1a0381a4741cd8710...
Author: Michael Müller michael@fds-team.de Date: Wed Jun 14 20:20:43 2017 +0200
server: Implement setting a security descriptor when duplicating tokens.
Signed-off-by: Matteo Bruni mbruni@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/nt.c | 7 ++++++- include/wine/server_protocol.h | 5 +++-- server/process.c | 2 +- server/protocol.def | 2 +- server/request.h | 5 ++--- server/security.h | 2 +- server/token.c | 14 +++++++++++--- server/trace.c | 2 +- 8 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 86beb03..8938d5d 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -83,11 +83,15 @@ NTSTATUS WINAPI NtDuplicateToken( OUT PHANDLE NewToken) { NTSTATUS status; + data_size_t len; + struct object_attributes *objattr;
TRACE("(%p,0x%08x,%s,0x%08x,0x%08x,%p)\n", ExistingToken, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes), ImpersonationLevel, TokenType, NewToken);
+ if ((status = alloc_object_attributes( ObjectAttributes, &objattr, &len ))) return status; + if (ObjectAttributes && ObjectAttributes->SecurityQualityOfService) { SECURITY_QUALITY_OF_SERVICE *SecurityQOS = ObjectAttributes->SecurityQualityOfService; @@ -102,14 +106,15 @@ NTSTATUS WINAPI NtDuplicateToken( { req->handle = wine_server_obj_handle( ExistingToken ); req->access = DesiredAccess; - req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0; req->primary = (TokenType == TokenPrimary); req->impersonation_level = ImpersonationLevel; + wine_server_add_data( req, objattr, len ); status = wine_server_call( req ); if (!status) *NewToken = wine_server_ptr_handle( reply->new_handle ); } SERVER_END_REQ;
+ RtlFreeHeap( GetProcessHeap(), 0, objattr ); return status; }
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 0d7a7cd..d31579c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4732,9 +4732,10 @@ struct duplicate_token_request struct request_header __header; obj_handle_t handle; unsigned int access; - unsigned int attributes; int primary; int impersonation_level; + /* VARARG(objattr,object_attributes); */ + char __pad_28[4]; }; struct duplicate_token_reply { @@ -6418,6 +6419,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; };
-#define SERVER_PROTOCOL_VERSION 532 +#define SERVER_PROTOCOL_VERSION 533
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/process.c b/server/process.c index 5eabbbe..4f38ae1 100644 --- a/server/process.c +++ b/server/process.c @@ -565,7 +565,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit : alloc_handle_table( process, 0 ); /* Note: for security reasons, starting a new process does not attempt * to use the current impersonation token for the new process */ - process->token = token_duplicate( parent->token, TRUE, 0 ); + process->token = token_duplicate( parent->token, TRUE, 0, NULL ); process->affinity = parent->affinity; } if (!process->handles || !process->token) goto error; diff --git a/server/protocol.def b/server/protocol.def index 7eaaec2..1f88c6a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3316,9 +3316,9 @@ enum caret_state @REQ(duplicate_token) obj_handle_t handle; /* handle to the token to duplicate */ unsigned int access; /* access rights to the new token */ - unsigned int attributes; /* object attributes */ int primary; /* is the new token to be a primary one? */ int impersonation_level; /* impersonation level of the new token */ + VARARG(objattr,object_attributes); /* object attributes */ @REPLY obj_handle_t new_handle; /* duplicated handle */ @END diff --git a/server/request.h b/server/request.h index ad89f30..30d2234 100644 --- a/server/request.h +++ b/server/request.h @@ -2113,9 +2113,8 @@ C_ASSERT( FIELD_OFFSET(struct check_token_privileges_reply, has_privileges) == 8 C_ASSERT( sizeof(struct check_token_privileges_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, access) == 16 ); -C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, attributes) == 20 ); -C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, primary) == 24 ); -C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, impersonation_level) == 28 ); +C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, primary) == 20 ); +C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, impersonation_level) == 24 ); C_ASSERT( sizeof(struct duplicate_token_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct duplicate_token_reply, new_handle) == 8 ); C_ASSERT( sizeof(struct duplicate_token_reply) == 16 ); diff --git a/server/security.h b/server/security.h index 5c76821..3cbfcb9 100644 --- a/server/security.h +++ b/server/security.h @@ -53,7 +53,7 @@ extern const PSID security_builtin_admins_sid;
extern struct token *token_create_admin(void); extern struct token *token_duplicate( struct token *src_token, unsigned primary, - int impersonation_level ); + int impersonation_level, const struct security_descriptor *sd ); extern int token_check_privileges( struct token *token, int all_required, const LUID_AND_ATTRIBUTES *reqprivs, unsigned int count, LUID_AND_ATTRIBUTES *usedprivs); diff --git a/server/token.c b/server/token.c index 9183595..f518544 100644 --- a/server/token.c +++ b/server/token.c @@ -622,7 +622,7 @@ static struct token *create_token( unsigned primary, const SID *user, }
struct token *token_duplicate( struct token *src_token, unsigned primary, - int impersonation_level ) + int impersonation_level, const struct security_descriptor *sd ) { const luid_t *modified_id = primary || (impersonation_level == src_token->impersonation_level) ? @@ -672,6 +672,9 @@ struct token *token_duplicate( struct token *src_token, unsigned primary, return NULL; }
+ if (sd) default_set_sd( &token->obj, sd, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION ); + return token; }
@@ -1240,15 +1243,20 @@ DECL_HANDLER(get_token_privileges) DECL_HANDLER(duplicate_token) { struct token *src_token; + struct unicode_str name; + const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); + + if (!objattr) return;
if ((src_token = (struct token *)get_handle_obj( current->process, req->handle, TOKEN_DUPLICATE, &token_ops ))) { - struct token *token = token_duplicate( src_token, req->primary, req->impersonation_level ); + struct token *token = token_duplicate( src_token, req->primary, req->impersonation_level, sd ); if (token) { - reply->new_handle = alloc_handle( current->process, token, req->access, req->attributes); + reply->new_handle = alloc_handle_no_access_check( current->process, token, req->access, objattr->attributes ); release_object( token ); } release_object( src_token ); diff --git a/server/trace.c b/server/trace.c index 6e23184..962b122 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3927,9 +3927,9 @@ static void dump_duplicate_token_request( const struct duplicate_token_request * { fprintf( stderr, " handle=%04x", req->handle ); fprintf( stderr, ", access=%08x", req->access ); - fprintf( stderr, ", attributes=%08x", req->attributes ); fprintf( stderr, ", primary=%d", req->primary ); fprintf( stderr, ", impersonation_level=%d", req->impersonation_level ); + dump_varargs_object_attributes( ", objattr=", cur_size ); }
static void dump_duplicate_token_reply( const struct duplicate_token_reply *req )