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>
This commit is contained in:
parent
187b53e5a5
commit
7c08e787b1
|
@ -83,11 +83,15 @@ NTSTATUS WINAPI NtDuplicateToken(
|
||||||
OUT PHANDLE NewToken)
|
OUT PHANDLE NewToken)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
data_size_t len;
|
||||||
|
struct object_attributes *objattr;
|
||||||
|
|
||||||
TRACE("(%p,0x%08x,%s,0x%08x,0x%08x,%p)\n",
|
TRACE("(%p,0x%08x,%s,0x%08x,0x%08x,%p)\n",
|
||||||
ExistingToken, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes),
|
ExistingToken, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes),
|
||||||
ImpersonationLevel, TokenType, NewToken);
|
ImpersonationLevel, TokenType, NewToken);
|
||||||
|
|
||||||
|
if ((status = alloc_object_attributes( ObjectAttributes, &objattr, &len ))) return status;
|
||||||
|
|
||||||
if (ObjectAttributes && ObjectAttributes->SecurityQualityOfService)
|
if (ObjectAttributes && ObjectAttributes->SecurityQualityOfService)
|
||||||
{
|
{
|
||||||
SECURITY_QUALITY_OF_SERVICE *SecurityQOS = ObjectAttributes->SecurityQualityOfService;
|
SECURITY_QUALITY_OF_SERVICE *SecurityQOS = ObjectAttributes->SecurityQualityOfService;
|
||||||
|
@ -102,14 +106,15 @@ NTSTATUS WINAPI NtDuplicateToken(
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( ExistingToken );
|
req->handle = wine_server_obj_handle( ExistingToken );
|
||||||
req->access = DesiredAccess;
|
req->access = DesiredAccess;
|
||||||
req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
|
|
||||||
req->primary = (TokenType == TokenPrimary);
|
req->primary = (TokenType == TokenPrimary);
|
||||||
req->impersonation_level = ImpersonationLevel;
|
req->impersonation_level = ImpersonationLevel;
|
||||||
|
wine_server_add_data( req, objattr, len );
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
if (!status) *NewToken = wine_server_ptr_handle( reply->new_handle );
|
if (!status) *NewToken = wine_server_ptr_handle( reply->new_handle );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4732,9 +4732,10 @@ struct duplicate_token_request
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
obj_handle_t handle;
|
obj_handle_t handle;
|
||||||
unsigned int access;
|
unsigned int access;
|
||||||
unsigned int attributes;
|
|
||||||
int primary;
|
int primary;
|
||||||
int impersonation_level;
|
int impersonation_level;
|
||||||
|
/* VARARG(objattr,object_attributes); */
|
||||||
|
char __pad_28[4];
|
||||||
};
|
};
|
||||||
struct duplicate_token_reply
|
struct duplicate_token_reply
|
||||||
{
|
{
|
||||||
|
@ -6418,6 +6419,6 @@ union generic_reply
|
||||||
struct terminate_job_reply terminate_job_reply;
|
struct terminate_job_reply terminate_job_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 532
|
#define SERVER_PROTOCOL_VERSION 533
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -565,7 +565,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
|
||||||
: alloc_handle_table( process, 0 );
|
: alloc_handle_table( process, 0 );
|
||||||
/* Note: for security reasons, starting a new process does not attempt
|
/* Note: for security reasons, starting a new process does not attempt
|
||||||
* to use the current impersonation token for the new process */
|
* 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;
|
process->affinity = parent->affinity;
|
||||||
}
|
}
|
||||||
if (!process->handles || !process->token) goto error;
|
if (!process->handles || !process->token) goto error;
|
||||||
|
|
|
@ -3316,9 +3316,9 @@ enum caret_state
|
||||||
@REQ(duplicate_token)
|
@REQ(duplicate_token)
|
||||||
obj_handle_t handle; /* handle to the token to duplicate */
|
obj_handle_t handle; /* handle to the token to duplicate */
|
||||||
unsigned int access; /* access rights to the new token */
|
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 primary; /* is the new token to be a primary one? */
|
||||||
int impersonation_level; /* impersonation level of the new token */
|
int impersonation_level; /* impersonation level of the new token */
|
||||||
|
VARARG(objattr,object_attributes); /* object attributes */
|
||||||
@REPLY
|
@REPLY
|
||||||
obj_handle_t new_handle; /* duplicated handle */
|
obj_handle_t new_handle; /* duplicated handle */
|
||||||
@END
|
@END
|
||||||
|
|
|
@ -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( 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, handle) == 12 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, access) == 16 );
|
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) == 20 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, primary) == 24 );
|
C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, impersonation_level) == 24 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct duplicate_token_request, impersonation_level) == 28 );
|
|
||||||
C_ASSERT( sizeof(struct duplicate_token_request) == 32 );
|
C_ASSERT( sizeof(struct duplicate_token_request) == 32 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct duplicate_token_reply, new_handle) == 8 );
|
C_ASSERT( FIELD_OFFSET(struct duplicate_token_reply, new_handle) == 8 );
|
||||||
C_ASSERT( sizeof(struct duplicate_token_reply) == 16 );
|
C_ASSERT( sizeof(struct duplicate_token_reply) == 16 );
|
||||||
|
|
|
@ -53,7 +53,7 @@ extern const PSID security_builtin_admins_sid;
|
||||||
|
|
||||||
extern struct token *token_create_admin(void);
|
extern struct token *token_create_admin(void);
|
||||||
extern struct token *token_duplicate( struct token *src_token, unsigned primary,
|
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,
|
extern int token_check_privileges( struct token *token, int all_required,
|
||||||
const LUID_AND_ATTRIBUTES *reqprivs,
|
const LUID_AND_ATTRIBUTES *reqprivs,
|
||||||
unsigned int count, LUID_AND_ATTRIBUTES *usedprivs);
|
unsigned int count, LUID_AND_ATTRIBUTES *usedprivs);
|
||||||
|
|
|
@ -622,7 +622,7 @@ static struct token *create_token( unsigned primary, const SID *user,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct token *token_duplicate( struct token *src_token, unsigned primary,
|
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 =
|
const luid_t *modified_id =
|
||||||
primary || (impersonation_level == src_token->impersonation_level) ?
|
primary || (impersonation_level == src_token->impersonation_level) ?
|
||||||
|
@ -672,6 +672,9 @@ struct token *token_duplicate( struct token *src_token, unsigned primary,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sd) default_set_sd( &token->obj, sd, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||||
|
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION );
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1240,15 +1243,20 @@ DECL_HANDLER(get_token_privileges)
|
||||||
DECL_HANDLER(duplicate_token)
|
DECL_HANDLER(duplicate_token)
|
||||||
{
|
{
|
||||||
struct token *src_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,
|
if ((src_token = (struct token *)get_handle_obj( current->process, req->handle,
|
||||||
TOKEN_DUPLICATE,
|
TOKEN_DUPLICATE,
|
||||||
&token_ops )))
|
&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)
|
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( token );
|
||||||
}
|
}
|
||||||
release_object( src_token );
|
release_object( src_token );
|
||||||
|
|
|
@ -3927,9 +3927,9 @@ static void dump_duplicate_token_request( const struct duplicate_token_request *
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%04x", req->handle );
|
fprintf( stderr, " handle=%04x", req->handle );
|
||||||
fprintf( stderr, ", access=%08x", req->access );
|
fprintf( stderr, ", access=%08x", req->access );
|
||||||
fprintf( stderr, ", attributes=%08x", req->attributes );
|
|
||||||
fprintf( stderr, ", primary=%d", req->primary );
|
fprintf( stderr, ", primary=%d", req->primary );
|
||||||
fprintf( stderr, ", impersonation_level=%d", req->impersonation_level );
|
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 )
|
static void dump_duplicate_token_reply( const struct duplicate_token_reply *req )
|
||||||
|
|
Loading…
Reference in New Issue