From 5356bfde2c7a150181b31b633474355bb8a99023 Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Tue, 2 Oct 2007 15:55:13 +0100 Subject: [PATCH] server: Add a new get_security_object call for getting the security descriptor of an object. Use it to implement NtQuerySecurityObject. --- dlls/ntdll/om.c | 200 +++++++++++---------------------- include/wine/server_protocol.h | 18 ++- server/handle.c | 65 +++++++++++ server/protocol.def | 8 ++ server/request.h | 2 + server/trace.c | 16 +++ 6 files changed, 174 insertions(+), 135 deletions(-) diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c index 06ec9f63ab..7cb7f06006 100644 --- a/dlls/ntdll/om.c +++ b/dlls/ntdll/om.c @@ -162,152 +162,84 @@ NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle, * * An ntdll analogue to GetKernelObjectSecurity(). * - * NOTES - * only the lowest 4 bit of SecurityObjectInformationClass are used - * 0x7-0xf returns STATUS_ACCESS_DENIED (even running with system privileges) - * - * FIXME - * We are constructing a fake sid (Administrators:Full, System:Full, Everyone:Read) */ NTSTATUS WINAPI NtQuerySecurityObject( IN HANDLE Object, IN SECURITY_INFORMATION RequestedInformation, - OUT PSECURITY_DESCRIPTOR pSecurityDesriptor, + OUT PSECURITY_DESCRIPTOR pSecurityDescriptor, IN ULONG Length, OUT PULONG ResultLength) { - static const SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY}; - static const SID_IDENTIFIER_AUTHORITY worldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY}; - BYTE Buffer[256]; - PISECURITY_DESCRIPTOR_RELATIVE psd = (PISECURITY_DESCRIPTOR_RELATIVE)Buffer; - UINT BufferIndex = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + PISECURITY_DESCRIPTOR_RELATIVE psd = pSecurityDescriptor; + NTSTATUS status; + unsigned int buffer_size = 512; + BOOLEAN need_more_memory = FALSE; - FIXME("(%p,0x%08x,%p,0x%08x,%p) stub!\n", - Object, RequestedInformation, pSecurityDesriptor, Length, ResultLength); + TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", + Object, RequestedInformation, pSecurityDescriptor, Length, ResultLength); - RequestedInformation &= 0x0000000f; + do + { + char *buffer = RtlAllocateHeap(GetProcessHeap(), 0, buffer_size); + if (!buffer) + return STATUS_NO_MEMORY; - ZeroMemory(Buffer, 256); - RtlCreateSecurityDescriptor((PSECURITY_DESCRIPTOR)psd, SECURITY_DESCRIPTOR_REVISION); - psd->Control = SE_SELF_RELATIVE | - ((RequestedInformation & DACL_SECURITY_INFORMATION) ? SE_DACL_PRESENT:0); + SERVER_START_REQ( get_security_object ) + { + req->handle = Object; + req->security_info = RequestedInformation; + wine_server_set_reply( req, buffer, buffer_size ); + status = wine_server_call( req ); + if (status == STATUS_SUCCESS) + { + struct security_descriptor *sd = (struct security_descriptor *)buffer; + if (reply->sd_len) + { + *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len; + if (Length >= *ResultLength) + { + psd->Revision = SECURITY_DESCRIPTOR_REVISION; + psd->Sbz1 = 0; + psd->Control = sd->control | SE_SELF_RELATIVE; + psd->Owner = sd->owner_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) : 0; + psd->Group = sd->group_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len : 0; + psd->Sacl = sd->sacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len : 0; + psd->Dacl = sd->dacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len + sd->sacl_len : 0; + /* owner, group, sacl and dacl are the same type as in the server + * and in the same order so we copy the memory in one block */ + memcpy((char *)pSecurityDescriptor + sizeof(SECURITY_DESCRIPTOR_RELATIVE), + buffer + sizeof(struct security_descriptor), + sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len); + } + else + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + if (Length >= *ResultLength) + { + memset(psd, 0, sizeof(*psd)); + psd->Revision = SECURITY_DESCRIPTOR_REVISION; + psd->Control = SE_SELF_RELATIVE; + } + else + status = STATUS_BUFFER_TOO_SMALL; + } + } + else if (status == STATUS_BUFFER_TOO_SMALL) + { + buffer_size = reply->sd_len; + need_more_memory = TRUE; + } + } + SERVER_END_REQ; + RtlFreeHeap(GetProcessHeap(), 0, buffer); + } while (need_more_memory); - /* owner: administrator S-1-5-20-220*/ - if (OWNER_SECURITY_INFORMATION & RequestedInformation) - { - SID* psid = (SID*)&(Buffer[BufferIndex]); - - psd->Owner = BufferIndex; - BufferIndex += RtlLengthRequiredSid(2); - - psid->Revision = SID_REVISION; - psid->SubAuthorityCount = 2; - psid->IdentifierAuthority = localSidAuthority; - psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID; - psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS; - } - - /* group: built in domain S-1-5-12 */ - if (GROUP_SECURITY_INFORMATION & RequestedInformation) - { - SID* psid = (SID*) &(Buffer[BufferIndex]); - - psd->Group = BufferIndex; - BufferIndex += RtlLengthRequiredSid(1); - - psid->Revision = SID_REVISION; - psid->SubAuthorityCount = 1; - psid->IdentifierAuthority = localSidAuthority; - psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID; - } - - /* discretionary ACL */ - if (DACL_SECURITY_INFORMATION & RequestedInformation) - { - /* acl header */ - PACL pacl = (PACL)&(Buffer[BufferIndex]); - PACCESS_ALLOWED_ACE pace; - SID* psid; - - psd->Dacl = BufferIndex; - - pacl->AclRevision = MIN_ACL_REVISION; - pacl->AceCount = 3; - pacl->AclSize = BufferIndex; /* storing the start index temporary */ - - BufferIndex += sizeof(ACL); - - /* ACE System - full access */ - pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]); - BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD); - - pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; - pace->Header.AceFlags = CONTAINER_INHERIT_ACE; - pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1); - pace->Mask = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; - pace->SidStart = BufferIndex; - - /* SID S-1-5-12 (System) */ - psid = (SID*)&(Buffer[BufferIndex]); - - BufferIndex += RtlLengthRequiredSid(1); - - psid->Revision = SID_REVISION; - psid->SubAuthorityCount = 1; - psid->IdentifierAuthority = localSidAuthority; - psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID; - - /* ACE Administrators - full access*/ - pace = (PACCESS_ALLOWED_ACE) &(Buffer[BufferIndex]); - BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD); - - pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; - pace->Header.AceFlags = CONTAINER_INHERIT_ACE; - pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(2); - pace->Mask = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; - pace->SidStart = BufferIndex; - - /* S-1-5-12 (Administrators) */ - psid = (SID*)&(Buffer[BufferIndex]); - - BufferIndex += RtlLengthRequiredSid(2); - - psid->Revision = SID_REVISION; - psid->SubAuthorityCount = 2; - psid->IdentifierAuthority = localSidAuthority; - psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID; - psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS; - - /* ACE Everyone - read access */ - pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]); - BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD); - - pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; - pace->Header.AceFlags = CONTAINER_INHERIT_ACE; - pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1); - pace->Mask = READ_CONTROL| 0x19; - pace->SidStart = BufferIndex; - - /* SID S-1-1-0 (Everyone) */ - psid = (SID*)&(Buffer[BufferIndex]); - - BufferIndex += RtlLengthRequiredSid(1); - - psid->Revision = SID_REVISION; - psid->SubAuthorityCount = 1; - psid->IdentifierAuthority = worldSidAuthority; - psid->SubAuthority[0] = 0; - - /* calculate used bytes */ - pacl->AclSize = BufferIndex - pacl->AclSize; - } - *ResultLength = BufferIndex; - TRACE("len=%u\n", *ResultLength); - if (Length < *ResultLength) return STATUS_BUFFER_TOO_SMALL; - memcpy(pSecurityDesriptor, Buffer, *ResultLength); - - return STATUS_SUCCESS; + return status; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 314a3a624e..edaea23be6 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3832,6 +3832,19 @@ struct set_security_object_reply struct reply_header __header; }; +struct get_security_object_request +{ + struct request_header __header; + obj_handle_t handle; + unsigned int security_info; +}; +struct get_security_object_reply +{ + struct reply_header __header; + unsigned int sd_len; + /* VARARG(sd,security_descriptor); */ +}; + struct create_mailslot_request { @@ -4376,6 +4389,7 @@ enum request REQ_get_token_user, REQ_get_token_groups, REQ_set_security_object, + REQ_get_security_object, REQ_create_mailslot, REQ_set_mailslot_info, REQ_create_directory, @@ -4609,6 +4623,7 @@ union generic_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 get_security_object_request get_security_object_request; struct create_mailslot_request create_mailslot_request; struct set_mailslot_info_request set_mailslot_info_request; struct create_directory_request create_directory_request; @@ -4840,6 +4855,7 @@ union generic_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 get_security_object_reply get_security_object_reply; struct create_mailslot_reply create_mailslot_reply; struct set_mailslot_info_reply set_mailslot_info_reply; struct create_directory_reply create_directory_reply; @@ -4864,6 +4880,6 @@ union generic_reply struct set_completion_info_reply set_completion_info_reply; }; -#define SERVER_PROTOCOL_VERSION 315 +#define SERVER_PROTOCOL_VERSION 316 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/handle.c b/server/handle.c index 39911fb3e8..65b4205d24 100644 --- a/server/handle.c +++ b/server/handle.c @@ -615,3 +615,68 @@ DECL_HANDLER(set_security_object) set_object_sd( obj, sd, req->security_info ); release_object( obj ); } + +DECL_HANDLER(get_security_object) +{ + const struct security_descriptor *sd; + struct object *obj; + unsigned int access = READ_CONTROL; + struct security_descriptor req_sd; + int present; + const SID *owner, *group; + const ACL *sacl, *dacl; + + if (req->security_info & SACL_SECURITY_INFORMATION) + access |= ACCESS_SYSTEM_SECURITY; + + if (!(obj = get_handle_obj( current->process, req->handle, access, NULL ))) return; + + sd = obj->sd; + if (sd) + { + req_sd.control = sd->control & ~SE_SELF_RELATIVE; + + owner = sd_get_owner( sd ); + if (req->security_info & OWNER_SECURITY_INFORMATION) + req_sd.owner_len = sd->owner_len; + + group = sd_get_group( sd ); + if (req->security_info & GROUP_SECURITY_INFORMATION) + req_sd.group_len = sd->group_len; + + req_sd.control |= SE_SACL_PRESENT; + sacl = sd_get_sacl( sd, &present ); + if (req->security_info & SACL_SECURITY_INFORMATION && present) + req_sd.sacl_len = sd->sacl_len; + else + req_sd.sacl_len = 0; + + req_sd.control |= SE_DACL_PRESENT; + dacl = sd_get_dacl( sd, &present ); + if (req->security_info & DACL_SECURITY_INFORMATION && present) + req_sd.dacl_len = sd->dacl_len; + else + req_sd.dacl_len = 0; + + reply->sd_len = sizeof(req_sd) + req_sd.owner_len + req_sd.group_len + + req_sd.sacl_len + req_sd.dacl_len; + if (reply->sd_len <= get_reply_max_size()) + { + char *ptr = set_reply_data_size(reply->sd_len); + + memcpy( ptr, &req_sd, sizeof(req_sd) ); + ptr += sizeof(req_sd); + memcpy( ptr, owner, req_sd.owner_len ); + ptr += req_sd.owner_len; + memcpy( ptr, group, req_sd.group_len ); + ptr += req_sd.group_len; + memcpy( ptr, sacl, req_sd.sacl_len ); + ptr += req_sd.sacl_len; + memcpy( ptr, dacl, req_sd.dacl_len ); + } + else + set_error(STATUS_BUFFER_TOO_SMALL); + } + + release_object( obj ); +} diff --git a/server/protocol.def b/server/protocol.def index 2e83c12ebd..d7d4248033 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2768,6 +2768,14 @@ enum message_type VARARG(sd,security_descriptor); /* security descriptor to set */ @END +@REQ(get_security_object) + obj_handle_t handle; /* handle to the object */ + unsigned int security_info; /* which parts of security descriptor to get */ +@REPLY + unsigned int sd_len; /* buffer size needed for sd */ + VARARG(sd,security_descriptor); /* retrieved security descriptor */ +@END + /* Create a mailslot */ @REQ(create_mailslot) unsigned int access; /* wanted access rights */ diff --git a/server/request.h b/server/request.h index 0a013abb31..90ec2e1992 100644 --- a/server/request.h +++ b/server/request.h @@ -314,6 +314,7 @@ DECL_HANDLER(access_check); DECL_HANDLER(get_token_user); DECL_HANDLER(get_token_groups); DECL_HANDLER(set_security_object); +DECL_HANDLER(get_security_object); DECL_HANDLER(create_mailslot); DECL_HANDLER(set_mailslot_info); DECL_HANDLER(create_directory); @@ -546,6 +547,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_token_user, (req_handler)req_get_token_groups, (req_handler)req_set_security_object, + (req_handler)req_get_security_object, (req_handler)req_create_mailslot, (req_handler)req_set_mailslot_info, (req_handler)req_create_directory, diff --git a/server/trace.c b/server/trace.c index d1575e1b9e..53e0de8ab7 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3350,6 +3350,19 @@ static void dump_set_security_object_request( const struct set_security_object_r dump_varargs_security_descriptor( cur_size ); } +static void dump_get_security_object_request( const struct get_security_object_request *req ) +{ + fprintf( stderr, " handle=%p,", req->handle ); + fprintf( stderr, " security_info=%08x", req->security_info ); +} + +static void dump_get_security_object_reply( const struct get_security_object_reply *req ) +{ + fprintf( stderr, " sd_len=%08x,", req->sd_len ); + 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 ); @@ -3840,6 +3853,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_token_user_request, (dump_func)dump_get_token_groups_request, (dump_func)dump_set_security_object_request, + (dump_func)dump_get_security_object_request, (dump_func)dump_create_mailslot_request, (dump_func)dump_set_mailslot_info_request, (dump_func)dump_create_directory_request, @@ -4069,6 +4083,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_token_user_reply, (dump_func)dump_get_token_groups_reply, (dump_func)0, + (dump_func)dump_get_security_object_reply, (dump_func)dump_create_mailslot_reply, (dump_func)dump_set_mailslot_info_reply, (dump_func)dump_create_directory_reply, @@ -4298,6 +4313,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_token_user", "get_token_groups", "set_security_object", + "get_security_object", "create_mailslot", "set_mailslot_info", "create_directory",