ntdll/server: Implement NtSetSecurityObject. With tests.
This commit is contained in:
parent
5ec1718d74
commit
b0e9d7e0b5
|
@ -1539,15 +1539,82 @@ NtAccessCheck(
|
|||
|
||||
/******************************************************************************
|
||||
* NtSetSecurityObject [NTDLL.@]
|
||||
* ZwSetSecurityObject [NTDLL.@]
|
||||
*
|
||||
* Sets specified parts of the object's security descriptor.
|
||||
*
|
||||
* PARAMS
|
||||
* Handle [I] Handle to the object to change security descriptor of.
|
||||
* SecurityInformation [I] Specifies which parts of the security descriptor to set.
|
||||
* SecurityDescriptor [I] New parts of a security descriptor for the object.
|
||||
*
|
||||
* RETURNS
|
||||
* NTSTATUS code.
|
||||
*
|
||||
*/
|
||||
NTSTATUS WINAPI
|
||||
NtSetSecurityObject(
|
||||
IN HANDLE Handle,
|
||||
IN SECURITY_INFORMATION SecurityInformation,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
|
||||
SECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
{
|
||||
FIXME("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
|
||||
return STATUS_SUCCESS;
|
||||
NTSTATUS status;
|
||||
struct security_descriptor sd;
|
||||
PACL dacl, sacl;
|
||||
PSID owner, group;
|
||||
BOOLEAN defaulted, present;
|
||||
DWORD revision;
|
||||
SECURITY_DESCRIPTOR_CONTROL control;
|
||||
|
||||
TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
|
||||
|
||||
if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
memset( &sd, 0, sizeof(sd) );
|
||||
RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
|
||||
sd.control = control & ~SE_SELF_RELATIVE;
|
||||
|
||||
if (SecurityInformation & OWNER_SECURITY_INFORMATION)
|
||||
{
|
||||
RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
|
||||
if (!(sd.owner_len = RtlLengthSid( owner )))
|
||||
return STATUS_INVALID_SECURITY_DESCR;
|
||||
}
|
||||
|
||||
if (SecurityInformation & GROUP_SECURITY_INFORMATION)
|
||||
{
|
||||
RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
|
||||
if (!(sd.group_len = RtlLengthSid( group )))
|
||||
return STATUS_INVALID_SECURITY_DESCR;
|
||||
}
|
||||
|
||||
if (SecurityInformation & SACL_SECURITY_INFORMATION)
|
||||
{
|
||||
RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
|
||||
sd.sacl_len = present ? sacl->AclSize : 0;
|
||||
sd.control |= SE_SACL_PRESENT;
|
||||
}
|
||||
|
||||
if (SecurityInformation & DACL_SECURITY_INFORMATION)
|
||||
{
|
||||
RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
|
||||
sd.dacl_len = present ? dacl->AclSize : 0;
|
||||
sd.control |= SE_DACL_PRESENT;
|
||||
}
|
||||
|
||||
SERVER_START_REQ( set_security_object )
|
||||
{
|
||||
req->handle = Handle;
|
||||
req->security_info = SecurityInformation;
|
||||
|
||||
wine_server_add_data( req, &sd, sizeof(sd) );
|
||||
wine_server_add_data( req, owner, sd.owner_len );
|
||||
wine_server_add_data( req, group, sd.group_len );
|
||||
wine_server_add_data( req, sacl, sd.sacl_len );
|
||||
wine_server_add_data( req, dacl, sd.dacl_len );
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -3836,6 +3836,18 @@ struct get_token_groups_reply
|
|||
/* VARARG(user,token_groups); */
|
||||
};
|
||||
|
||||
struct set_security_object_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
unsigned int security_info;
|
||||
/* VARARG(sd,security_descriptor); */
|
||||
};
|
||||
struct set_security_object_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
struct create_mailslot_request
|
||||
{
|
||||
|
@ -4189,6 +4201,7 @@ enum request
|
|||
REQ_access_check,
|
||||
REQ_get_token_user,
|
||||
REQ_get_token_groups,
|
||||
REQ_set_security_object,
|
||||
REQ_create_mailslot,
|
||||
REQ_open_mailslot,
|
||||
REQ_set_mailslot_info,
|
||||
|
@ -4411,6 +4424,7 @@ union generic_request
|
|||
struct access_check_request access_check_request;
|
||||
struct get_token_user_request get_token_user_request;
|
||||
struct get_token_groups_request get_token_groups_request;
|
||||
struct set_security_object_request set_security_object_request;
|
||||
struct create_mailslot_request create_mailslot_request;
|
||||
struct open_mailslot_request open_mailslot_request;
|
||||
struct set_mailslot_info_request set_mailslot_info_request;
|
||||
|
@ -4631,6 +4645,7 @@ union generic_reply
|
|||
struct access_check_reply access_check_reply;
|
||||
struct get_token_user_reply get_token_user_reply;
|
||||
struct get_token_groups_reply get_token_groups_reply;
|
||||
struct set_security_object_reply set_security_object_reply;
|
||||
struct create_mailslot_reply create_mailslot_reply;
|
||||
struct open_mailslot_reply open_mailslot_reply;
|
||||
struct set_mailslot_info_reply set_mailslot_info_reply;
|
||||
|
@ -4642,6 +4657,6 @@ union generic_reply
|
|||
struct get_object_info_reply get_object_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 275
|
||||
#define SERVER_PROTOCOL_VERSION 276
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -2759,6 +2759,12 @@ enum message_type
|
|||
VARARG(user,token_groups); /* groups the token's user belongs to */
|
||||
@END
|
||||
|
||||
@REQ(set_security_object)
|
||||
obj_handle_t handle; /* handle to the object */
|
||||
unsigned int security_info; /* which parts of security descriptor to set */
|
||||
VARARG(sd,security_descriptor); /* security descriptor to set */
|
||||
@END
|
||||
|
||||
/* Create a mailslot */
|
||||
@REQ(create_mailslot)
|
||||
unsigned int access; /* wanted access rights */
|
||||
|
|
|
@ -316,6 +316,7 @@ DECL_HANDLER(duplicate_token);
|
|||
DECL_HANDLER(access_check);
|
||||
DECL_HANDLER(get_token_user);
|
||||
DECL_HANDLER(get_token_groups);
|
||||
DECL_HANDLER(set_security_object);
|
||||
DECL_HANDLER(create_mailslot);
|
||||
DECL_HANDLER(open_mailslot);
|
||||
DECL_HANDLER(set_mailslot_info);
|
||||
|
@ -537,6 +538,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_access_check,
|
||||
(req_handler)req_get_token_user,
|
||||
(req_handler)req_get_token_groups,
|
||||
(req_handler)req_set_security_object,
|
||||
(req_handler)req_create_mailslot,
|
||||
(req_handler)req_open_mailslot,
|
||||
(req_handler)req_set_mailslot_info,
|
||||
|
|
114
server/token.c
114
server/token.c
|
@ -886,6 +886,93 @@ const ACL *token_get_default_dacl( struct token *token )
|
|||
return token->default_dacl;
|
||||
}
|
||||
|
||||
static void set_object_sd( struct object *obj, const struct security_descriptor *sd,
|
||||
unsigned int set_info )
|
||||
{
|
||||
struct security_descriptor new_sd, *pnew_sd;
|
||||
int present;
|
||||
const SID *owner, *group;
|
||||
const ACL *sacl, *dacl;
|
||||
char *ptr;
|
||||
|
||||
if (!set_info) return;
|
||||
|
||||
new_sd.control = sd->control & ~SE_SELF_RELATIVE;
|
||||
|
||||
owner = sd_get_owner( sd );
|
||||
if (set_info & OWNER_SECURITY_INFORMATION && owner)
|
||||
new_sd.owner_len = sd->owner_len;
|
||||
else
|
||||
{
|
||||
owner = current->process->token->user;
|
||||
new_sd.owner_len = FIELD_OFFSET(SID, SubAuthority[owner->SubAuthorityCount]);
|
||||
new_sd.control |= SE_OWNER_DEFAULTED;
|
||||
}
|
||||
|
||||
group = sd_get_group( sd );
|
||||
if (set_info & GROUP_SECURITY_INFORMATION && group)
|
||||
new_sd.group_len = sd->group_len;
|
||||
else
|
||||
{
|
||||
group = current->process->token->primary_group;
|
||||
new_sd.group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
|
||||
new_sd.control |= SE_GROUP_DEFAULTED;
|
||||
}
|
||||
|
||||
new_sd.control |= SE_SACL_PRESENT;
|
||||
sacl = sd_get_sacl( sd, &present );
|
||||
if (set_info & SACL_SECURITY_INFORMATION && present)
|
||||
new_sd.sacl_len = sd->sacl_len;
|
||||
else
|
||||
{
|
||||
if (obj->sd) sacl = sd_get_sacl( obj->sd, &present );
|
||||
|
||||
if (obj->sd && present)
|
||||
new_sd.sacl_len = obj->sd->sacl_len;
|
||||
else
|
||||
{
|
||||
new_sd.sacl_len = 0;
|
||||
new_sd.control |= SE_SACL_DEFAULTED;
|
||||
}
|
||||
}
|
||||
|
||||
new_sd.control |= SE_DACL_PRESENT;
|
||||
dacl = sd_get_dacl( sd, &present );
|
||||
if (set_info & DACL_SECURITY_INFORMATION && present)
|
||||
new_sd.dacl_len = sd->dacl_len;
|
||||
else
|
||||
{
|
||||
if (obj->sd) dacl = sd_get_dacl( obj->sd, &present );
|
||||
|
||||
if (obj->sd && present)
|
||||
new_sd.dacl_len = obj->sd->dacl_len;
|
||||
else
|
||||
{
|
||||
dacl = token_get_default_dacl( current->process->token );
|
||||
new_sd.dacl_len = dacl->AclSize;
|
||||
new_sd.control |= SE_DACL_DEFAULTED;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = mem_alloc( sizeof(new_sd) + new_sd.owner_len + new_sd.group_len +
|
||||
new_sd.sacl_len + new_sd.dacl_len );
|
||||
if (!ptr) return;
|
||||
pnew_sd = (struct security_descriptor*)ptr;
|
||||
|
||||
memcpy( ptr, &new_sd, sizeof(new_sd) );
|
||||
ptr += sizeof(new_sd);
|
||||
memcpy( ptr, owner, new_sd.owner_len );
|
||||
ptr += new_sd.owner_len;
|
||||
memcpy( ptr, group, new_sd.group_len );
|
||||
ptr += new_sd.group_len;
|
||||
memcpy( ptr, sacl, new_sd.sacl_len );
|
||||
ptr += new_sd.sacl_len;
|
||||
memcpy( ptr, dacl, new_sd.dacl_len );
|
||||
|
||||
free( obj->sd );
|
||||
obj->sd = pnew_sd;
|
||||
}
|
||||
|
||||
/* open a security token */
|
||||
DECL_HANDLER(open_token)
|
||||
{
|
||||
|
@ -1206,3 +1293,30 @@ DECL_HANDLER(get_token_groups)
|
|||
release_object( token );
|
||||
}
|
||||
}
|
||||
|
||||
DECL_HANDLER(set_security_object)
|
||||
{
|
||||
data_size_t sd_size = get_req_data_size();
|
||||
const struct security_descriptor *sd = get_req_data();
|
||||
struct object *obj;
|
||||
unsigned int access = 0;
|
||||
|
||||
if (!sd_is_valid( sd, sd_size ))
|
||||
{
|
||||
set_error( STATUS_ACCESS_VIOLATION );
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->security_info & OWNER_SECURITY_INFORMATION ||
|
||||
req->security_info & GROUP_SECURITY_INFORMATION)
|
||||
access |= WRITE_OWNER;
|
||||
if (req->security_info & SACL_SECURITY_INFORMATION)
|
||||
access |= ACCESS_SYSTEM_SECURITY;
|
||||
if (req->security_info & DACL_SECURITY_INFORMATION)
|
||||
access |= WRITE_DAC;
|
||||
|
||||
if (!(obj = get_handle_obj( current->process, req->handle, access, NULL ))) return;
|
||||
|
||||
set_object_sd( obj, sd, req->security_info );
|
||||
release_object( obj );
|
||||
}
|
||||
|
|
|
@ -3309,6 +3309,14 @@ static void dump_get_token_groups_reply( const struct get_token_groups_reply *re
|
|||
dump_varargs_token_groups( cur_size );
|
||||
}
|
||||
|
||||
static void dump_set_security_object_request( const struct set_security_object_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p,", req->handle );
|
||||
fprintf( stderr, " security_info=%08x,", req->security_info );
|
||||
fprintf( stderr, " sd=" );
|
||||
dump_varargs_security_descriptor( cur_size );
|
||||
}
|
||||
|
||||
static void dump_create_mailslot_request( const struct create_mailslot_request *req )
|
||||
{
|
||||
fprintf( stderr, " access=%08x,", req->access );
|
||||
|
@ -3642,6 +3650,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_access_check_request,
|
||||
(dump_func)dump_get_token_user_request,
|
||||
(dump_func)dump_get_token_groups_request,
|
||||
(dump_func)dump_set_security_object_request,
|
||||
(dump_func)dump_create_mailslot_request,
|
||||
(dump_func)dump_open_mailslot_request,
|
||||
(dump_func)dump_set_mailslot_info_request,
|
||||
|
@ -3860,6 +3869,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_access_check_reply,
|
||||
(dump_func)dump_get_token_user_reply,
|
||||
(dump_func)dump_get_token_groups_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_create_mailslot_reply,
|
||||
(dump_func)dump_open_mailslot_reply,
|
||||
(dump_func)dump_set_mailslot_info_reply,
|
||||
|
@ -4078,6 +4088,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"access_check",
|
||||
"get_token_user",
|
||||
"get_token_groups",
|
||||
"set_security_object",
|
||||
"create_mailslot",
|
||||
"open_mailslot",
|
||||
"set_mailslot_info",
|
||||
|
|
Loading…
Reference in New Issue