This document describes how to construct a security descriptor to grant a given group access permission to the kernel object so that the object can be shared between processes running in different user accounts. Back to Top
More information sometimes, the Service must create kernel objects that can be accessed by processes running under different user accounts. To allow objects to be shared in this way, the Service must use a security descriptor that explicitly authorizes the access permission of user objects to create objects. Alternatively, you can grant the Security Descriptor the access permission to the entire user group.
The sample code in this article is very specific because it grantsAuthenticated UsersThe Group's access permissions to the mutex. This Code uses a large number of security APIs to construct the security descriptor of the mutex. For the complete documentation on these security functions, see the 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 fully understand these calls (usually including access control technology) to adapt code to other users, groups, and kernel objects. Return to the top sample code
The following sample code illustrates how to construct a security descriptor to grantAuthenticated UsersGroup generic_read, generic_write, and generic_execute permissions. The newly constructed security descriptor is immediately applied to the mutex.
For illustration purposes, this sample code uses general access permissions. These general permissions take advantage of common mappings that can be used for all kernel objects. In actual applications, it is best to use the object-specific access permissions when creating objects.
When a given resource manager maps to a specific object access permission, it may explain the given general permission set to include other standard access permissions. For example, specifying the generic_read, generic_write, and generic_execute permissions for mutex is equivalent to specifying the object-specific permissions mutex_modify_state and synchronize. Therefore, to obtain the mutex handle, other threads can only specify mutex_modify_state and/or synchronize for the dwdesiredaccess parameter in openmutex. The attempt to use mutex_all_access to open the mutex fails and Error Code 5 (error_access_denied) is displayed ).
#include <windows.h>#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() functionVOID 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);}