/*++ Copyright (c) 2001 Microsoft Corporation All rights reserved Module Name: utils.cxx Abstract: utils Author: Larry Zhu (LZhu) December 1, 2001 Created Environment: User Mode -Win32 Revision History: --*/ #include "precomp.hxx" #pragma hdrstop #include "utils.hxx" #include #define MAXDWORD 0xffffffff NTSTATUS CreateUnicodeStringFromAsciiz( IN PCSZ pszSourceString, OUT UNICODE_STRING* pDestinationString ) { TNtStatus Status; ANSI_STRING AnsiString; RtlInitAnsiString( &AnsiString, pszSourceString ); Status DBGCHK = RtlAnsiStringToUnicodeString( pDestinationString, &AnsiString, TRUE ); return Status; } VOID PackStringAsString32( IN VOID* pvBufferBase, IN OUT STRING* pString ) { pString->Buffer = (CHAR*) (pString->Buffer - (CHAR*) pvBufferBase); } NTSTATUS CreateString32FromAsciiz( IN VOID* pvBufferBase, IN PCSZ pszSourceString, OUT UNICODE_STRING* pDestinationString ) { TNtStatus Status; Status DBGCHK = CreateUnicodeStringFromAsciiz(pszSourceString, pDestinationString); if (NT_SUCCESS(Status)) { PackStringAsString32(pvBufferBase, (STRING*) pDestinationString); } return Status; } VOID RelocatePackString( IN OUT STRING* pString, IN OUT CHAR** ppWhere ) { RtlCopyMemory(*ppWhere, pString->Buffer, pString->Length); pString->Buffer = *ppWhere; *ppWhere += pString->Length; } VOID RelocatePackUnicodeString( IN UNICODE_STRING* pString, IN OUT CHAR** ppWhere ) { RelocatePackString((STRING*) pString, ppWhere); } VOID PackUnicodeStringAsUnicodeStringZ( IN UNICODE_STRING* pString, IN OUT WCHAR** ppWhere, OUT UNICODE_STRING* pDestString ) { RtlCopyMemory(*ppWhere, pString->Buffer, pString->Length); pDestString->Buffer = *ppWhere; pDestString->Length = pString->Length; pDestString->MaximumLength = pString->Length + sizeof(WCHAR); *ppWhere += pDestString->MaximumLength / sizeof(WCHAR); // // add unicode NULL // pDestString->Buffer[(pDestString->MaximumLength / sizeof(WCHAR)) - 1] = UNICODE_NULL; } VOID PackString( IN STRING* pString, IN OUT CHAR** ppWhere, OUT STRING* pDestString ) { RtlCopyMemory(*ppWhere, pString->Buffer, pString->Length); pDestString->Buffer = *ppWhere; *ppWhere += pString->Length; pDestString->Length = pString->Length; pDestString->MaximumLength = pString->Length; } VOID DebugPrintSysTimeAsLocalTime( IN ULONG ulLevel, IN PCSTR pszBanner, IN LARGE_INTEGER* pSysTime ) { TNtStatus NtStatus = STATUS_UNSUCCESSFUL; TIME_FIELDS TimeFields = {0}; LARGE_INTEGER LocalTime = {0}; NtStatus DBGCHK = RtlSystemTimeToLocalTime(pSysTime, &LocalTime); if (NT_SUCCESS(NtStatus)) { RtlTimeToTimeFields(&LocalTime, &TimeFields); DebugPrintf(ulLevel, "%s LocalTime(%ld/%ld/%ld %ld:%2.2ld:%2.2ld) SystemTime(H%8.8lx L%8.8lx)\n", pszBanner, TimeFields.Month, TimeFields.Day, TimeFields.Year, TimeFields.Hour, TimeFields.Minute, TimeFields.Second, pSysTime->HighPart, pSysTime->LowPart); } } VOID DebugPrintLocalTime( IN ULONG ulLevel, IN PCSTR pszBanner, IN LARGE_INTEGER* pLocalTime ) { TIME_FIELDS TimeFields = {0}; RtlTimeToTimeFields(pLocalTime, &TimeFields); DebugPrintf(ulLevel, "%s LocalTime(%ld/%ld/%ld %ld:%2.2ld:%2.2ld) H%8.8lx L%8.8lx\n", pszBanner, TimeFields.Month, TimeFields.Day, TimeFields.Year, TimeFields.Hour, TimeFields.Minute, TimeFields.Second, pLocalTime->HighPart, pLocalTime->LowPart); } #define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED) #define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | STANDARD_RIGHTS_REQUIRED) #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL) HRESULT StartInteractiveClientProcessAsUser( IN HANDLE hToken, IN PTSTR pszCommandLine // command line to execute ) { THResult hRetval = E_FAIL; HANDLE hDup = NULL; HDESK hdesk = NULL; HWINSTA hwinsta = NULL; HWINSTA hwinstaSave = NULL; PROCESS_INFORMATION pi = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0}; PSID pSid = NULL; STARTUPINFO si = {0}; HANDLE hSystemToken = NULL; CHAR TokenUserInfoBuffer[MAX_PATH + sizeof(TOKEN_USER)] = {0}; // MAX_SID_SIZE is 256 TOKEN_USER* pTokenUserInfo = (TOKEN_USER*) TokenUserInfoBuffer; ULONG cbReturn = 0; // Save a handle to the caller's current window station. hwinstaSave = GetProcessWindowStation(); hRetval DBGCHK = hwinstaSave ? S_OK : GetLastErrorAsHResult(); // Get the SID for the client's logon session. if (SUCCEEDED(hRetval)) { hRetval DBGCHK = GetLogonSIDOrUserSid(hToken, &pSid) ? S_OK : GetLastErrorAsHResult(); } // Get a handle to the interactive window station. if (SUCCEEDED(hRetval)) { hwinsta = OpenWindowStation( TEXT("winsta0"), // the interactive window station FALSE, // handle is not inheritable MAXIMUM_ALLOWED // rights to read/write the DACL ); hRetval DBGCHK = hwinsta ? S_OK : GetLastErrorAsHResult(); } // Allow logon SID full access to interactive window station. if (SUCCEEDED(hRetval)) { hRetval DBGCHK = AddAceToWindowStation(hwinsta, pSid) ? S_OK : GetLastErrorAsHResult(); } // To get the correct default desktop, set the caller's // window station to the interactive window station. if (SUCCEEDED(hRetval)) { hRetval DBGCHK = SetProcessWindowStation(hwinsta) ? S_OK : GetLastErrorAsHResult(); } // Get a handle to the interactive desktop. if (SUCCEEDED(hRetval)) { TImpersonation imper(NULL); hRetval DBGCHK = imper.Validate(); if (SUCCEEDED(hRetval)) { hdesk = OpenDesktop( TEXT("default"), // the interactive window station 0, // no interaction with other desktop processes FALSE, // handle is not inheritable MAXIMUM_ALLOWED ); hRetval DBGCHK = hdesk ? S_OK : GetLastErrorAsHResult(); } // Allow logon SID full access to interactive desktop. if (SUCCEEDED(hRetval)) { hRetval DBGCHK = AddAceToDesktop(hdesk, pSid) ? S_OK : GetLastErrorAsHResult(); } } // // get the necessary privileges enabled // if (SUCCEEDED(hRetval)) { hRetval DBGCHK = GetSystemToken(&hSystemToken); } if (SUCCEEDED(hRetval)) { TImpersonation imper(hSystemToken); hRetval DBGCHK = imper.Validate(); // Allow logon SID full access to interactive desktop. if (SUCCEEDED(hRetval)) { hRetval DBGCHK = SetThreadDesktop(hdesk) ? S_OK : GetLastErrorAsHResult(); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = GetTokenInformation( hToken, TokenUser, TokenUserInfoBuffer, sizeof(TokenUserInfoBuffer), &cbReturn ) ? S_OK : GetLastErrorAsHResult(); } // Initialize the STARTUPINFO structure. // Specify that the process runs in the interactive desktop. if (SUCCEEDED(hRetval)) { si.cb = sizeof(STARTUPINFO); si.lpDesktop = TEXT("winsta0\\default"); hRetval DBGCHK = ConvertSidToStringSid(pTokenUserInfo->User.Sid, &si.lpTitle) ? S_OK : GetLastErrorAsHResult(); } // Launch the process in the client's logon session. if (SUCCEEDED(hRetval)) { DBGCFG1(hRetval, HRESULT_FROM_WIN32(ERROR_BAD_TOKEN_TYPE)); hRetval DBGCHK = CreateProcessAsUser( hToken, // client's access token NULL, // file to execute pszCommandLine, // command line NULL, // pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, // creation flags NULL, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ) ? S_OK : GetLastErrorAsHResult(); if (FAILED(hRetval) && (ERROR_BAD_TOKEN_TYPE == HRESULT_CODE(hRetval))) { DebugPrintf(SSPI_WARN, "CreateProcessAsUser failed with ERROR_BAD_TOKEN_TYPE\n"); hRetval DBGCHK = DuplicateTokenEx( hToken, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, NULL, SecurityImpersonation, TokenPrimary, &hDup ) ? S_OK : GetLastErrorAsHResult(); if (SUCCEEDED(hRetval)) { hRetval DBGCHK = CreateProcessAsUser( hDup, // client's access token NULL, // file to execute pszCommandLine, // command line NULL, // pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, // creation flags NULL, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ) ? S_OK : GetLastErrorAsHResult(); } } } if (SUCCEEDED(hRetval)) { SspiPrint(SSPI_LOG, TEXT("StartInteractiveClientProcessAsUser succeeded: process id %d(%#x), user is %s, pszCommandLine \"%s\"\n"), pi.dwProcessId, pi.dwProcessId, si.lpTitle, pszCommandLine); } if (si.lpTitle) { LocalFree(si.lpTitle); } } THResult hr; // Restore the caller's window station. if (hwinstaSave) { hr DBGCHK = SetProcessWindowStation(hwinstaSave) ? S_OK : GetLastErrorAsHResult(); hr DBGCHK = CloseWindowStation(hwinstaSave) ? S_OK : GetLastErrorAsHResult(); } if (hDup) { hr DBGCHK = CloseHandle(hDup) ? S_OK : GetLastErrorAsHResult(); } if (hSystemToken) { hr DBGCHK = CloseHandle(hSystemToken) ? S_OK : GetLastErrorAsHResult(); } if (pi.hProcess != INVALID_HANDLE_VALUE) { // WaitForSingleObject(pi.hProcess, INFINITE); hr DBGCHK = CloseHandle(pi.hProcess) ? S_OK : GetLastErrorAsHResult(); } if (pi.hThread != INVALID_HANDLE_VALUE) { hr DBGCHK = CloseHandle(pi.hThread) ? S_OK : GetLastErrorAsHResult(); } // Close the handles to the interactive window station and desktop. if (hwinsta) { hr DBGCHK = CloseWindowStation(hwinsta) ? S_OK : GetLastErrorAsHResult(); } if (hdesk) { DBGCFG1(hr, HRESULT_FROM_WIN32(ERROR_BUSY)); hr DBGCHK = CloseDesktop(hdesk) ? S_OK : GetLastErrorAsHResult(); } // Free the buffer for the logon SID. if (pSid) { FreeLogonSID(&pSid); } return hRetval; } BOOL AddAceToWindowStation(IN HWINSTA hwinsta, IN PSID psid) { ACCESS_ALLOWED_ACE *pace; ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl; PACL pNewAcl; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; __try { // Obtain the DACL for the window station. if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psd == NULL) __leave; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) __leave; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded)) __leave; } else __leave; } // Create a new DACL. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION)) __leave; // Get the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist)) __leave; // Initialize the ACL. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if the DACL is not NULL. if (pacl != NULL) { // get the file ACL size info if (!GetAclInformation( pacl, (PVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) __leave; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + (2 * sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * sizeof(DWORD)); // Allocate memory for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) __leave; // Initialize the new DACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) __leave; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) __leave; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize)) __leave; } } } // Add the first ACE to the window station. pace = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); if (pace == NULL) __leave; pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; pace->Header.AceSize = (USHORT) (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); pace->Mask = GENERIC_ACCESS; if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid)) __leave; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (PVOID)pace, pace->Header.AceSize)) __leave; // Add the second ACE to the window station. pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; pace->Mask = WINSTA_ALL; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (PVOID)pace, pace->Header.AceSize)) __leave; // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE)) __leave; // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psdNew)) __leave; // Indicate success. bSuccess = TRUE; } __finally { // Free the allocated buffers. if (pace != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)pace); if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)psdNew); } return bSuccess; } BOOL AddAceToDesktop(IN HDESK hdesk, IN PSID psid) { ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl; PACL pNewAcl; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; __try { // Obtain the security descriptor for the desktop object. if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded ); if (psd == NULL) __leave; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) __leave; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded)) __leave; } else __leave; } // Create a new security descriptor. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION)) __leave; // Obtain the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist)) __leave; // Initialize. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if NULL DACL. if (pacl != NULL) { // Determine the size of the ACL information. if (!GetAclInformation( pacl, (PVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) __leave; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD); // Allocate buffer for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) __leave; // Initialize the new ACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) __leave; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) __leave; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize)) __leave; } } } // Add ACE to the DACL. if (!AddAccessAllowedAce( pNewAcl, ACL_REVISION, DESKTOP_ALL, psid)) __leave; // Set new DACL to the new security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE)) __leave; // Set the new security descriptor for the desktop object. if (!SetUserObjectSecurity(hdesk, &si, psdNew)) __leave; // Indicate success. bSuccess = TRUE; } __finally { // Free buffers. if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)psdNew); } return bSuccess; } BOOL GetLogonSIDOrUserSid(IN HANDLE hToken, OUT PSID *ppsid) { BOOL bSuccess = FALSE; DWORD dwIndex; DWORD dwLength = 0; PTOKEN_GROUPS ptg = NULL; *ppsid = NULL; // Get required buffer size and allocate the TOKEN_GROUPS buffer. if (!GetTokenInformation( hToken, // handle to the access token TokenGroups, // get information about the token's groups (PVOID) ptg, // pointer to TOKEN_GROUPS buffer 0, // size of buffer &dwLength // receives required buffer size )) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto Cleanup; ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (ptg == NULL) goto Cleanup; } // Get the token group information from the access token. if (!GetTokenInformation( hToken, // handle to the access token TokenGroups, // get information about the token's groups (PVOID) ptg, // pointer to TOKEN_GROUPS buffer dwLength, // size of buffer &dwLength // receives required buffer size )) { goto Cleanup; } // Loop through the groups to find the logon SID. for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) if (0 != (ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID)) { // Found the logon SID; make a copy of it. dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid); *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (*ppsid == NULL) goto Cleanup; if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid)) { HeapFree(GetProcessHeap(), 0, (PVOID)*ppsid); goto Cleanup; } break; } if (NULL == *ppsid) { ULONG cbUserInfo; PUCHAR pnSubAuthorityCount = 0; CHAR UserInfoBuffer[4096] = {0}; PTOKEN_USER pUserInfo = (PTOKEN_USER) UserInfoBuffer; SspiPrint(SSPI_WARN, TEXT("GetLogonSIDOrUserSid failed to find logon id, trying user sid\n")); if (!GetTokenInformation( hToken, TokenUser, UserInfoBuffer, sizeof(UserInfoBuffer), &cbUserInfo )) { goto Cleanup; } if (!IsValidSid(pUserInfo->User.Sid)) goto Cleanup; pnSubAuthorityCount = GetSidSubAuthorityCount(pUserInfo->User.Sid); dwLength = GetSidLengthRequired(*pnSubAuthorityCount); *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (*ppsid == NULL) goto Cleanup; if (!CopySid(dwLength, *ppsid, pUserInfo->User.Sid)) { HeapFree(GetProcessHeap(), 0, (PVOID)*ppsid); goto Cleanup; } } bSuccess = TRUE; Cleanup: // Free the buffer for the token groups. if (ptg != NULL) HeapFree(GetProcessHeap(), 0, (PVOID)ptg); return bSuccess; } VOID FreeLogonSID(IN PSID *ppsid) { HeapFree(GetProcessHeap(), 0, (PVOID)*ppsid); } /** This function builds a Dacl which grants the creator of the objects FILE_ALL_ACCESS and Everyone FILE_GENERIC_READ and FILE_GENERIC_WRITE access to the object. This Dacl allows for higher security than a NULL Dacl, which is common for named-pipes, as this only grants the creator/owner write access to the security descriptor, and grants Everyone the ability to "use" the named-pipe. This scenario prevents a malevolent user from disrupting service by preventing arbitrary access manipulation. **/ BOOL BuildNamedPipeAcl( IN OUT PACL pAcl, OUT PDWORD pcbAclSize ) { DWORD cbAclSize = 0; SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY siaCreator = SECURITY_CREATOR_SID_AUTHORITY; BYTE BufEveryoneSid[32] = {0}; BYTE BufOwnerSid[32] = {0}; PSID pEveryoneSid = (PSID)BufEveryoneSid; PSID pOwnerSid = (PSID)BufOwnerSid; // // compute size of acl // cbAclSize = sizeof(ACL) + 2 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) + GetSidLengthRequired( 1 ) // well-known Everyone Sid + GetSidLengthRequired( 1 ) ; // well-known Creator Owner Sid if (*pcbAclSize < cbAclSize) { *pcbAclSize = cbAclSize; return FALSE; } *pcbAclSize = cbAclSize; // // intialize well known sids // if (!InitializeSid(pEveryoneSid, &siaWorld, 1)) return FALSE; *GetSidSubAuthority(pEveryoneSid, 0) = SECURITY_WORLD_RID; if (!InitializeSid(pOwnerSid, &siaCreator, 1)) return FALSE; *GetSidSubAuthority(pOwnerSid, 0) = SECURITY_CREATOR_OWNER_RID; if (!InitializeAcl(pAcl, cbAclSize, ACL_REVISION)) return FALSE; if (!AddAccessAllowedAce( pAcl, ACL_REVISION, FILE_GENERIC_READ | FILE_GENERIC_WRITE, pEveryoneSid )) return FALSE; return AddAccessAllowedAce( pAcl, ACL_REVISION, FILE_ALL_ACCESS, pOwnerSid ); }