Microsoft KB Archive/106387

= How To Share Kernel Objects Between Processes =

Article ID: 106387

Article Last Modified on 11/21/2006

-

APPLIES TO

 Microsoft Win32 Application Programming Interface, when used with:  Microsoft Windows NT 4.0

 Microsoft Windows 2000 Standard Edition

 Microsoft Windows XP Professional 

-

<div class="notice_section">

This article was previously published under Q106387

<div class="summary_section">

SUMMARY
This article demonstrates how to construct a security descriptor that grants a given group access to a kernel object so that the object can be shared between processes that are running under different user accounts.

<div class="moreinformation_section">

MORE INFORMATION
Sometimes it is necessary for a service to create a kernel object that can be accessed by a process running under a different user account. To allow an object to be shared in this manner, the service must create the object by using a security descriptor that explicitly grants the user access to the object. Alternatively, the security descriptor can grant access to an entire group of users.

The sample code in this article is very specific in that it grants the authenticated users group access to a mutex. This code makes use of numerous security APIs to construct the security descriptor for the mutex. For complete documentation on these security functions, see "Access Control" section of the Platform SDK Documentation in the MSDN Library:

http://msdn.microsoft.com/library/en-us/security/hh/winbase/accctrl_2hf0.asp

You must have a full understanding of these calls (and the Access Control technology, in general) in order to adapt the code for other users, groups, and kernel objects.

Sample Code
The following sample code demonstrates how to construct a security descriptor that grants the authenticated users group GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access. The newly constructed security descriptor is then applied to a mutex.

For demonstration purposes, this sample code uses generic access rights. These generic rights take advantage of generic mappings that can be used for all kernel objects. In a real-world application, it is preferable to use object-specific access rights when creating an object.

It is possible that a given resource manager may interpret a given set of generic rights to include other standard access rights when mapping to object-specific access rights. For example, specifying GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE rights for a mutex is the same as specifying the object-specific rights MUTEX_MODIFY_STATE and SYNCHRONIZE. As a result, another thread can only obtain a handle to the mutex by specifying MUTEX_MODIFY_STATE and/or SYNCHRONIZE for the dwDesiredAccess parameter in OpenMutex. An attempt to open the mutex with MUTEX_ALL_ACCESS will fail with error code 5 (ERROR_ACCESS_DENIED).
 * 1) include <windows.h>
 * 2) include <stdio.h>

// The following function initializes the supplied security descriptor // with a DACL that grants the Authenticated Users group GENERIC_READ, // GENERIC_WRITE, and GENERIC_EXECUTE access. // // The function returns NULL if any of the access control APIs fail. // Otherwise, it returns a PVOID pointer that should be freed by calling // FreeRestrictedSD after the security descriptor has been used to // create the object.

PVOID BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD) {

DWORD dwAclLength;

PSID  pAuthenticatedUsersSID = NULL;

PACL  pDACL   = NULL; BOOL  bResult = FALSE;

PACCESS_ALLOWED_ACE pACE = NULL;

SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; __try {

// initialize the security descriptor if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor failed with error %d\n",              GetLastError); __leave; }

// obtain a sid for the Authenticated Users Group if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0, &pAuthenticatedUsersSID)) { printf("AllocateAndInitializeSid failed with error %d\n",              GetLastError); __leave; }

// NOTE: //      // The Authenticated Users group includes all user accounts that // have been successfully authenticated by the system. If access // must be restricted to a specific user or group other than // Authenticated Users, the SID can be constructed using the // LookupAccountSid API based on a user or group name.

// calculate the DACL length dwAclLength = sizeof(ACL) // add space for Authenticated Users group ACE + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pAuthenticatedUsersSID);

// allocate memory for the DACL pDACL = (PACL) HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY,            dwAclLength); if (!pDACL) { printf("HeapAlloc failed with error %d\n", GetLastError); __leave; }

// initialize the DACL if (!InitializeAcl(pDACL, dwAclLength, ACL_REVISION)) { printf("InitializeAcl failed with error %d\n",               GetLastError); __leave; }     // add the Authenticated Users group ACE to the DACL with // GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access if (!AddAccessAllowedAce(pDACL, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, pAuthenticatedUsersSID)) { printf("AddAccessAllowedAce failed with error %d\n",              GetLastError); __leave; }

// set the DACL in the security descriptor if (!SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE)) { printf("SetSecurityDescriptorDacl failed with error %d\n",              GetLastError); __leave; }

bResult = TRUE; } __finally {

if (pAuthenticatedUsersSID) FreeSid(pAuthenticatedUsersSID); }

if (bResult == FALSE) { if (pDACL) HeapFree(GetProcessHeap, 0, pDACL); pDACL = NULL; }

return (PVOID) pDACL; }

// The following function frees memory allocated in the // BuildRestrictedSD function VOID FreeRestrictedSD(PVOID ptr) {

if (ptr) HeapFree(GetProcessHeap, 0, ptr);

return; }

void main(void) {  SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd;

PVOID ptr; HANDLE hMutex;

// build a restricted security descriptor ptr = BuildRestrictedSD(&sd); if (!ptr) { printf("BuildRestrictedSD failed\n"); return; }

// create a mutex using the security descriptor sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = FALSE;

hMutex = CreateMutex(&sa, FALSE, "RestrictedMutex"); if (!hMutex) printf("CreateMutex failed with error %d\n", GetLastError);

// free the memory allocated by BuildRestrictedSD FreeRestrictedSD(ptr);

// use the mutex ...

printf("Press the return key to close the mutex handle...\n"); getchar;

// close the mutex handle CloseHandle(hMutex); }

Keywords: kbacl kbapi kbhowto kbkernbase kbsecurity kbservice KB106387

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.