ntdll/server: Implement NtSetSecurityObject. With tests.
diff --git a/dlls/ntdll/sec.c b/dlls/ntdll/sec.c
index b4e5773..7380786 100644
--- a/dlls/ntdll/sec.c
+++ b/dlls/ntdll/sec.c
@@ -1539,15 +1539,82 @@
/******************************************************************************
* 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;
}
/******************************************************************************
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index be21fc4..4e7cec0 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -3836,6 +3836,18 @@
/* 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 @@
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 @@
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 @@
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 @@
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 */
diff --git a/server/protocol.def b/server/protocol.def
index f49f331..2073a20 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2759,6 +2759,12 @@
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 */
diff --git a/server/request.h b/server/request.h
index b52c1aa..9119ec1 100644
--- a/server/request.h
+++ b/server/request.h
@@ -316,6 +316,7 @@
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 @@
(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,
diff --git a/server/token.c b/server/token.c
index 9a59188..88558e6 100644
--- a/server/token.c
+++ b/server/token.c
@@ -886,6 +886,93 @@
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 @@
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 );
+}
diff --git a/server/trace.c b/server/trace.c
index f9ff323..2909ded 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3309,6 +3309,14 @@
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 @@
(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 @@
(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 @@
"access_check",
"get_token_user",
"get_token_groups",
+ "set_security_object",
"create_mailslot",
"open_mailslot",
"set_mailslot_info",