windows-nt/Source/XPSP1/NT/net/rras/ras/autodial/rasauto/imperson.c
2020-09-26 16:20:57 +08:00

1158 lines
26 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright(c) 1995 Microsoft Corporation
MODULE NAME
impersn.c
ABSTRACT
Impersonation routines for the automatic connection service.
AUTHOR
Anthony Discolo (adiscolo) 04-Aug-1995
REVISION HISTORY
--*/
#define UNICODE
#define _UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <npapi.h>
#include <acd.h>
#include <debug.h>
#include "reg.h"
#include "misc.h"
#include "process.h"
#include "imperson.h"
#include "mprlog.h"
#include "rtutils.h"
extern HANDLE g_hLogEvent;
DWORD
LoadGroupMemberships();
//
// The static information we
// need to impersonate the currently
// logged-in user.
//
IMPERSONATION_INFO ImpersonationInfoG;
//
// TRUE if ImpersonationInfoG has been initialized
//
BOOLEAN ImpersonationInfoInitializedG = FALSE;
//
// Security attributes and descriptor
// necessary for creating shareable handles.
//
SECURITY_ATTRIBUTES SecurityAttributeG;
SECURITY_DESCRIPTOR SecurityDescriptorG;
HKEY hkeyCUG = NULL;
#ifdef notdef
BOOLEAN
InteractiveSession()
/*++
DESCRIPTION
Determine whether the active process is owned by the
currently logged-in user.
ARGUMENTS
None.
RETURNS
TRUE if it is, FALSE if it isn't.
--*/
{
HANDLE hToken;
BOOLEAN bStatus;
ULONG ulInfoLength;
PTOKEN_GROUPS pTokenGroupList;
PTOKEN_USER pTokenUser;
ULONG ulGroupIndex;
BOOLEAN bFoundInteractive = FALSE;
PSID InteractiveSid;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
static BOOLEAN fIsInteractiveSession = 0xffff;
#if 0
//
// Return the previous value of this function
// if we're called multiple times?! Doesn't
// GetCurrentProcess() return different values?
//
if (fIsInteractiveSession != 0xffff) {
return fIsInteractiveSession;
}
#endif
bStatus = AllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_INTERACTIVE_RID,
0, 0, 0, 0, 0, 0, 0,
&InteractiveSid);
if (!bStatus) {
RASAUTO_TRACE("InteractiveSession: AllocateAndInitializeSid failed");
return (fIsInteractiveSession = FALSE);
}
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
RASAUTO_TRACE("InteractiveSession: OpenProcessToken failed");
FreeSid(InteractiveSid);
return (fIsInteractiveSession = FALSE);
}
//
// Get a list of groups in the token.
//
GetTokenInformation(
hToken,
TokenGroups,
NULL,
0,
&ulInfoLength);
pTokenGroupList = (PTOKEN_GROUPS)LocalAlloc(LPTR, ulInfoLength);
if (pTokenGroupList == NULL) {
RASAUTO_TRACE("InteractiveSession: LocalAlloc failed");
FreeSid(InteractiveSid);
return (fIsInteractiveSession = FALSE);
}
bStatus = GetTokenInformation(
hToken,
TokenGroups,
pTokenGroupList,
ulInfoLength,
&ulInfoLength);
if (!bStatus) {
RASAUTO_TRACE("InteractiveSession: GetTokenInformation failed");
FreeSid(InteractiveSid);
LocalFree(pTokenGroupList);
return (fIsInteractiveSession = FALSE);
}
//
// Search group list for admin alias. If we
// find a match, it most certainly is an
// interactive process.
//
bFoundInteractive = FALSE;
for (ulGroupIndex=0; ulGroupIndex < pTokenGroupList->GroupCount;
ulGroupIndex++)
{
if (EqualSid(
pTokenGroupList->Groups[ulGroupIndex].Sid,
InteractiveSid))
{
bFoundInteractive = TRUE;
break;
}
}
if (!bFoundInteractive) {
//
// If we haven't found a match,
// query and check the user ID.
//
GetTokenInformation(
hToken,
TokenUser,
NULL,
0,
&ulInfoLength);
pTokenUser = LocalAlloc(LPTR, ulInfoLength);
if (pTokenUser == NULL) {
RASAUTO_TRACE("InteractiveSession: LocalAlloc failed");
FreeSid(InteractiveSid);
LocalFree(pTokenGroupList);
return (fIsInteractiveSession = FALSE);
}
bStatus = GetTokenInformation(
hToken,
TokenUser,
pTokenUser,
ulInfoLength,
&ulInfoLength);
if (!bStatus) {
RASAUTO_TRACE("InteractiveSession: GetTokenInformation failed");
FreeSid(InteractiveSid);
LocalFree(pTokenGroupList);
LocalFree(pTokenUser);
return (fIsInteractiveSession = FALSE);
}
if (EqualSid(pTokenUser->User.Sid, InteractiveSid))
fIsInteractiveSession = TRUE;
LocalFree(pTokenUser);
}
FreeSid(InteractiveSid);
LocalFree(pTokenGroupList);
return (fIsInteractiveSession = bFoundInteractive);
}
#endif
BOOLEAN
SetProcessImpersonationToken(
HANDLE hProcess
)
{
NTSTATUS status;
HANDLE hThread,
hToken = NULL;
//
// Open the impersonation token for the
// process we want to impersonate.
//
if (ImpersonationInfoG.hTokenImpersonation == NULL)
{
if (!OpenProcessToken(
hProcess,
TOKEN_ALL_ACCESS,
&hToken))
{
RASAUTO_TRACE1(
"SetProcessImpersonationToken: OpenProcessToken failed (dwErr=%d)",
GetLastError());
return FALSE;
}
//
// Duplicate the impersonation token.
//
if(!DuplicateToken(
hToken,
TokenImpersonation,
&ImpersonationInfoG.hTokenImpersonation))
{
RASAUTO_TRACE1(
"SetProcessImpersonationToken: NtSetInformationThread failed (error=%d)",
GetLastError());
return FALSE;
}
}
//
// Set the impersonation token on the current
// thread. We are now running in the same
// security context as the supplied process.
//
hThread = NtCurrentThread();
status = NtSetInformationThread(
hThread,
ThreadImpersonationToken,
(PVOID)&ImpersonationInfoG.hTokenImpersonation,
sizeof (ImpersonationInfoG.hTokenImpersonation));
if (status != STATUS_SUCCESS)
{
RASAUTO_TRACE1(
"SetProcessImpersonationToken: NtSetInformationThread failed (error=%d)",
GetLastError());
}
if(NULL != hToken)
{
CloseHandle(hToken);
}
return (status == STATUS_SUCCESS);
} // SetProcessImpersonationToken
VOID
ClearImpersonationToken()
{
//
// Clear the impersonation token on the current
// thread. We are now running in LocalSystem
// security context.
//
if (!SetThreadToken(NULL, NULL)) {
DWORD retcode = GetLastError();
RASAUTO_TRACE1(
"ClearImpersonationToken: SetThreadToken failed (error=%d)",
retcode);
//
// Event log that thread failed to revert.
//
RouterLogWarning(
g_hLogEvent,
ROUTERLOG_CANNOT_REVERT_IMPERSONATION,
0, NULL, retcode) ;
}
} // ClearImpersonationToken
BOOLEAN
SetPrivilege(
HANDLE hToken,
LPCTSTR Privilege,
BOOLEAN fEnable
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
if (!LookupPrivilegeValue(NULL, Privilege, &luid))
return FALSE;
//
// First pass. Get current privilege setting.
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious);
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
//
// Second pass. Set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if (fEnable)
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
else {
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL);
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
return TRUE;
} // SetPrivilege
BOOLEAN
GetCurrentlyLoggedOnUser(
HANDLE *phProcess
)
{
BOOLEAN fSuccess = FALSE;
HKEY hkey;
DWORD dwErr, dwType;
DWORD dwDisp;
WCHAR *pszShell = NULL, **pszShellArray = NULL;
PSYSTEM_PROCESS_INFORMATION pSystemInfo, pProcessInfo;
PWCHAR psz, pszStart;
DWORD i, dwSize, dwcCommands;
NTSTATUS status;
HANDLE hProcess = NULL;
DWORD dwPid = 0;
//
// Get the shell process name. We will look for this
// to find out who the currently logged-on user is.
// Create a unicode string that describes this name.
//
if (RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
SHELL_REGKEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkey,
&dwDisp) == ERROR_SUCCESS)
{
dwSize = 0;
if (RegQueryValueEx(
hkey,
SHELL_REGVAL,
NULL,
&dwType,
NULL,
&dwSize) == ERROR_SUCCESS)
{
pszShell = (PWCHAR)LocalAlloc(LPTR, dwSize + sizeof (WCHAR));
if (pszShell == NULL) {
RegCloseKey(hkey);
return FALSE;
}
dwErr = RegQueryValueEx(
hkey,
SHELL_REGVAL,
NULL,
&dwType,
(LPBYTE)pszShell,
&dwSize);
RegCloseKey(hkey);
if (dwErr != ERROR_SUCCESS || dwType != REG_SZ) {
LocalFree(pszShell);
pszShell = NULL;
}
}
}
//
// If no shell was found, use DEFAULT_SHELL.
//
if (pszShell == NULL) {
pszShell = (PWCHAR)LocalAlloc(
LPTR,
(lstrlen(DEFAULT_SHELL) + 1) * sizeof (WCHAR));
if (pszShell == NULL)
return FALSE;
lstrcpy(pszShell, DEFAULT_SHELL);
}
RASAUTO_TRACE1("ImpersonateCurrentlyLoggedInUser: pszShell is %S", pszShell);
//
// This string can be a comma separated list,
// so we need to parse it into a list of commands.
//
dwcCommands = 1;
for (psz = pszShell; *psz != L'\0'; psz++) {
if (*psz == L',')
dwcCommands++;
}
//
// Allocate the list of string pointers.
//
pszShellArray = LocalAlloc(LPTR, sizeof (PWCHAR) * dwcCommands);
if (pszShellArray == NULL) {
LocalFree(pszShell);
return FALSE;
}
//
// Ignore any arguments from the command line.
//
dwcCommands = 0;
psz = pszShell;
pszStart = NULL;
for (;;) {
if (*psz == L'\0') {
if (pszStart != NULL)
pszShellArray[dwcCommands++] = pszStart;
break;
}
else if (*psz == L',') {
if (pszStart != NULL)
pszShellArray[dwcCommands++] = pszStart;
*psz = L'\0';
pszStart = NULL;
}
else if (*psz == L' ') {
if (pszStart != NULL)
*psz = L'\0';
}
else {
if (pszStart == NULL)
pszStart = psz;
}
psz++;
}
for (i = 0; i < dwcCommands; i++) {
RASAUTO_TRACE2(
"ImpersonateCurrentlyLoggedInUser: pszShellArray[%d] is %S",
i,
pszShellArray[i]);
}
//
// Get the process list.
//
pSystemInfo = GetSystemProcessInfo();
if(NULL == pSystemInfo)
{
LocalFree(pszShell);
LocalFree(pszShellArray);
return FALSE;
}
while(TRUE)
{
//
// See if any of the processes are running.
//
pProcessInfo =
FindProcessByNameList(
pSystemInfo,
pszShellArray,
dwcCommands,
dwPid,
ImpersonationInfoG.fSessionInitialized,
ImpersonationInfoG.dwCurSessionId);
//
// Open the process token if we've found a match.
//
if (pProcessInfo != NULL)
{
HANDLE hToken;
//
// Open the process.
//
hProcess = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
PtrToUlong(pProcessInfo->UniqueProcessId));
if (hProcess == NULL)
{
RASAUTO_TRACE2(
"ImpersonateCurrentlyLoggedInUser: OpenProcess(%d) failed (dwErr=%d)",
PtrToUlong(pProcessInfo->UniqueProcessId),
GetLastError());
dwPid = PtrToUlong(pProcessInfo->UniqueProcessId);
}
else
{
fSuccess = TRUE;
break;
}
}
else
{
break;
}
}
#ifdef notdef
done:
#endif
//
// Free resources.
//
FreeSystemProcessInfo(pSystemInfo);
if (pszShell != NULL)
LocalFree(pszShell);
if (pszShellArray != NULL)
LocalFree(pszShellArray);
//
// Return process handle.
//
*phProcess = hProcess;
return fSuccess;
} // GetCurrentlyLoggedOnUser
DWORD
SetCurrentLoginSession(
IN DWORD dwSessionId)
{
RASAUTO_TRACE1("SetCurrentLoginSession %d", dwSessionId);
EnterCriticalSection(&ImpersonationInfoG.csLock);
ImpersonationInfoG.dwCurSessionId = dwSessionId;
ImpersonationInfoG.fSessionInitialized = TRUE;
LeaveCriticalSection(&ImpersonationInfoG.csLock);
return NO_ERROR;
}
HANDLE
RefreshImpersonation(
HANDLE hProcess
)
{
NTSTATUS status;
EnterCriticalSection(&ImpersonationInfoG.csLock);
//
// If the process still exists,
// we can return.
//
if (ImpersonationInfoG.hProcess != NULL &&
hProcess == ImpersonationInfoG.hProcess)
{
RASAUTO_TRACE1("RefreshImpersonation: hProcess=0x%x no change", hProcess);
goto done;
}
//
// Otherwise recalcuate the current information.
// We have to clear the previous impersonation token,
// if any.
//
if (hProcess != NULL)
ClearImpersonationToken();
if (ImpersonationInfoG.hProcess == NULL) {
RASAUTO_TRACE("RefreshImpersonation: recalcuating token");
if (!GetCurrentlyLoggedOnUser(&ImpersonationInfoG.hProcess)) {
RASAUTO_TRACE("RefreshImpersonation: GetCurrentlyLoggedOnUser failed");
goto done;
}
RASAUTO_TRACE("RefreshImpersonation: new user logged in");
}
//
// Impersonate the currently logged-in user.
//
if (!SetProcessImpersonationToken(ImpersonationInfoG.hProcess))
{
RASAUTO_TRACE(
"RefreshImpersonation: SetProcessImpersonationToken failed");
goto done;
}
#ifdef notdef // imperson
//
// Reset HKEY_CURRENT_USER to get the
// correct value with the new impersonation
// token.
//
RegCloseKey(HKEY_CURRENT_USER);
#endif
RASAUTO_TRACE1(
"RefreshImpersonation: new hProcess=0x%x",
ImpersonationInfoG.hProcess);
TraceCurrentUser();
//
// Open the currently logged on users hive and store it in a global
//
if(NULL != hkeyCUG)
{
NtClose(hkeyCUG);
hkeyCUG = NULL;
}
if(STATUS_SUCCESS != RtlOpenCurrentUser(KEY_ALL_ACCESS, &hkeyCUG))
{
RASAUTO_TRACE("Failed to open HKCU for the current user");
}
done:
LeaveCriticalSection(&ImpersonationInfoG.csLock);
return ImpersonationInfoG.hProcess;
} // RefreshImpersonation
VOID
RevertImpersonation()
/*++
DESCRIPTION
Close all open handles associated with the
logged-in user who has just logged out.
ARGUMENTS
None.
RETURN VALUE
None.
--*/
{
EnterCriticalSection(&ImpersonationInfoG.csLock);
if(ImpersonationInfoG.hToken != NULL)
{
CloseHandle(ImpersonationInfoG.hToken);
ImpersonationInfoG.hToken = NULL;
}
if(ImpersonationInfoG.hTokenImpersonation != NULL)
{
CloseHandle(ImpersonationInfoG.hTokenImpersonation);
ImpersonationInfoG.hTokenImpersonation = NULL;
}
if(ImpersonationInfoG.hProcess != NULL)
{
CloseHandle(ImpersonationInfoG.hProcess);
ImpersonationInfoG.hProcess = NULL;
}
ImpersonationInfoG.fGroupsLoaded = FALSE;
if(NULL != hkeyCUG)
{
NtClose(hkeyCUG);
hkeyCUG = NULL;
}
//
// Clear the thread's impersonation
// token, or it won't be able to open
// another user's process the next
// time around.
//
ClearImpersonationToken();
LeaveCriticalSection(&ImpersonationInfoG.csLock);
} // RevertImpersonation
DWORD
InitSecurityDescriptor(
IN PSECURITY_DESCRIPTOR pSecurityDescriptor
)
/*++
DESCRIPTION
Initialize a security descriptor allowing administrator
access for the sharing of handles between rasman.dll.
This code courtesy of Gurdeep. You need to ask him
exactly what it does.
ARGUMENTS
pSecurityDescriptor: a pointer to the security descriptor
to be initialized.
RETURN VALUE
Win32 error code.
--*/
{
DWORD dwErr = 0;
DWORD cbDaclSize;
PULONG pSubAuthority;
PSID pObjSid = NULL;
PACL pDacl = NULL;
SID_IDENTIFIER_AUTHORITY sidIdentifierWorldAuth =
SECURITY_WORLD_SID_AUTHORITY;
DWORD dwAcls;
//
// Set up the SID for the adminstrators that
// will be allowed access. This SID will have
// 1 sub-authorities: SECURITY_BUILTIN_DOMAIN_RID.
//
pObjSid = (PSID)LocalAlloc(LPTR, GetSidLengthRequired(1));
if (pObjSid == NULL) {
RASAUTO_TRACE("InitSecurityDescriptor: LocalAlloc failed");
return GetLastError();
}
if (!InitializeSid(pObjSid, &sidIdentifierWorldAuth, 1)) {
dwErr = GetLastError();
RASAUTO_TRACE1("InitSecurityDescriptor: InitializeSid failed (dwErr=0x%x)", dwErr);
goto done;
}
//
// Set the sub-authorities.
//
pSubAuthority = GetSidSubAuthority(pObjSid, 0);
*pSubAuthority = SECURITY_WORLD_RID;
//
// Set up the DACL that will allow
// all processes with the above SID all
// access. It should be large enough to
// hold all ACEs.
//
cbDaclSize = sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(pObjSid) +
sizeof (ACL);
pDacl = (PACL)LocalAlloc(LPTR, cbDaclSize);
if (pDacl == NULL ) {
RASAUTO_TRACE("InitSecurityDescriptor: LocalAlloc failed");
dwErr = GetLastError();
goto done;
}
if (!InitializeAcl(pDacl, cbDaclSize, ACL_REVISION2)) {
dwErr = GetLastError();
RASAUTO_TRACE1("InitSecurityDescriptor: InitializeAcl failed (dwErr=0x%x)", dwErr);
goto done;
}
dwAcls = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
dwAcls &= ~(WRITE_DAC | WRITE_OWNER);
//
// Add the ACE to the DACL
//
if (!AddAccessAllowedAce(
pDacl,
ACL_REVISION2,
dwAcls,
pObjSid))
{
dwErr = GetLastError();
RASAUTO_TRACE1("InitSecurityDescriptor: AddAccessAllowedAce failed (dwErr=0x%x)", dwErr);
goto done;
}
//
// Create the security descriptor an put
// the DACL in it.
//
if (!InitializeSecurityDescriptor(pSecurityDescriptor, 1)) {
dwErr = GetLastError();
RASAUTO_TRACE1("InitSecurityDescriptor: InitializeSecurityDescriptor failed (dwErr=0x%x)", dwErr);
goto done;
}
if (!SetSecurityDescriptorDacl(
pSecurityDescriptor,
TRUE,
pDacl,
FALSE))
{
dwErr = GetLastError();
RASAUTO_TRACE1("InitSecurityDescriptor: SetSecurityDescriptorDacl failed (dwErr=0x%x)", dwErr);
goto done;
}
//
// Set owner for the descriptor.
//
if (!SetSecurityDescriptorOwner(pSecurityDescriptor, NULL, FALSE)) {
dwErr = GetLastError();
RASAUTO_TRACE1("InitSecurityDescriptor: SetSecurityDescriptorOwner failed (dwErr=0x%x)", dwErr);
goto done;
}
//
// Set group for the descriptor.
//
if (!SetSecurityDescriptorGroup(pSecurityDescriptor, NULL, FALSE)) {
dwErr = GetLastError();
RASAUTO_TRACE1("InitSecurityDescriptor: SetSecurityDescriptorGroup failed (dwErr=0x%x)", dwErr);
goto done;
}
done:
//
// Cleanup if necessary.
//
if (dwErr) {
if (pObjSid != NULL)
LocalFree(pObjSid);
if (pDacl != NULL)
LocalFree(pDacl);
}
return dwErr;
}
DWORD
InitSecurityAttribute()
/*++
DESCRIPTION
Initializes the global security attribute used in
creating shareable handles.
This code courtesy of Gurdeep. You need to ask him
exactly what it does.
ARGUMENTS
None.
RETURN VALUE
Win32 error code.
--*/
{
DWORD dwErr;
//
// Initialize the security descriptor.
//
dwErr = InitSecurityDescriptor(&SecurityDescriptorG);
if (dwErr)
return dwErr;
//
// Initialize the security attributes.
//
SecurityAttributeG.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttributeG.lpSecurityDescriptor = &SecurityDescriptorG;
SecurityAttributeG.bInheritHandle = TRUE;
return 0;
}
VOID
TraceCurrentUser(VOID)
{
//WCHAR szUserName[512];
//DWORD dwSize = sizeof (szUserName) - 1;
//GetUserName(szUserName, &dwSize);
RASAUTO_TRACE1(
"TraceCurrentUser: impersonating Current User %d",
ImpersonationInfoG.dwCurSessionId);
} // TraceCurrentUser
DWORD
DwGetHkcu()
{
DWORD dwErr = ERROR_SUCCESS;
if(NULL == hkeyCUG)
{
dwErr = RtlOpenCurrentUser(
KEY_ALL_ACCESS,
&hkeyCUG);
if(ERROR_SUCCESS != dwErr)
{
RASAUTO_TRACE1("DwGetHhcu: failed to open current user. 0x%x",
dwErr);
goto done;
}
}
done:
return dwErr;
}
DWORD
InitializeImpersonation()
/*++
DESCRIPTION
Initializes the global structures used for impersonation
ARGUMENTS
None
RETURN VALUE
Win32 error code.
--*/
{
DWORD dwError = ERROR_SUCCESS;
if (!ImpersonationInfoInitializedG)
{
ZeroMemory(&ImpersonationInfoG, sizeof(ImpersonationInfoG));
InitializeCriticalSection(&ImpersonationInfoG.csLock);
ImpersonationInfoInitializedG = TRUE;
}
return dwError;
}
VOID
CleanupImpersonation()
/*++
DESCRIPTION
Cleans up the global structures used for impersonation
ARGUMENTS
None
RETURN VALUE
None
--*/
{
if (ImpersonationInfoInitializedG)
{
EnterCriticalSection(&ImpersonationInfoG.csLock);
if (NULL != ImpersonationInfoG.pGuestSid)
{
FreeSid(ImpersonationInfoG.pGuestSid);
ImpersonationInfoG.pGuestSid = NULL;
}
LeaveCriticalSection(&ImpersonationInfoG.csLock);
DeleteCriticalSection(&ImpersonationInfoG.csLock);
ImpersonationInfoInitializedG = FALSE;
}
}
BOOLEAN
ImpersonatingGuest()
/*++
DESCRIPTION
Returns whether or not the user that is currently being impersonating
is a member of the local guests group
ARGUMENTS
None
RETURN VALUE
BOOLEAN -- TRUE if currently impersonating a guests, FALSE otherwise
--*/
{
BOOLEAN fIsGuest = FALSE;
ASSERT(ImpersonationInfoInitializedG);
EnterCriticalSection(&ImpersonationInfoG.csLock);
if (ERROR_SUCCESS == LoadGroupMemberships())
{
fIsGuest = ImpersonationInfoG.fGuest;
}
LeaveCriticalSection(&ImpersonationInfoG.csLock);
return fIsGuest;
}
DWORD
LoadGroupMemberships()
/*++
DESCRIPTION
Caches the group membership information for the impersonated user.
ARGUMENTS
None
RETURN VALUE
Win32 error code.
--*/
{
DWORD dwError = ERROR_SUCCESS;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority = SECURITY_NT_AUTHORITY;
BOOL fIsGuest;
EnterCriticalSection(&ImpersonationInfoG.csLock);
do
{
if (ImpersonationInfoG.fGroupsLoaded)
{
//
// Information already loaded
//
break;
}
if (NULL == ImpersonationInfoG.hTokenImpersonation)
{
//
// There isn't an impersonated user.
//
dwError = ERROR_CAN_NOT_COMPLETE;
break;
}
if (NULL == ImpersonationInfoG.pGuestSid)
{
//
// Allocate the SID for the local guests group;
//
if (!AllocateAndInitializeSid(
&IdentifierAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_GUESTS,
0,
0,
0,
0,
0,
0,
&ImpersonationInfoG.pGuestSid
))
{
dwError = GetLastError();
break;
}
}
if (!CheckTokenMembership(
ImpersonationInfoG.hTokenImpersonation,
ImpersonationInfoG.pGuestSid,
&fIsGuest
))
{
dwError = GetLastError();
break;
}
ImpersonationInfoG.fGuest = !!fIsGuest;
} while (FALSE);
LeaveCriticalSection(&ImpersonationInfoG.csLock);
return dwError;
}
VOID
LockImpersonation()
{
ASSERT(ImpersonationInfoInitializedG);
if(ImpersonationInfoInitializedG)
{
EnterCriticalSection(&ImpersonationInfoG.csLock);
}
}
VOID
UnlockImpersonation()
{
ASSERT(ImpersonationInfoInitializedG);
if(ImpersonationInfoInitializedG)
{
LeaveCriticalSection(&ImpersonationInfoG.csLock);
}
}