Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1042 lines
30 KiB

/*++
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 <Sddl.h>
#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
);
}