windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/mdadmin/ntsec.cxx

340 lines
8.2 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*===================================================================
Microsoft IIS
Microsoft Confidential.
Copyright 1996-1997 Microsoft Corporation. All Rights Reserved.
Component: Server object
File: NTSec.cxx
Owner: AndrewS
This file contains code related to NT security on WinSta's and Desktops
===================================================================*/
#include <dbgutil.h>
#include <apiutil.h>
#include <loadmd.hxx>
#include <loadadm.hxx>
#include <ole2.h>
#include <inetsvcs.h>
#include "ntsec.h"
// Globals
HWINSTA ghWinSta = NULL;
HWINSTA ghWinStaPrev = NULL;
HDESK ghDesktop = NULL;
HDESK ghdeskPrev = NULL;
HRESULT InitOleSecurity(BOOL);
/*===================================================================
InitDesktopWinsta
Create a desktop and a winstation for IIS to use
Parameters:
Returns:
HRESULT NOERROR on success
Side effects
Sets global variables
===================================================================*/
HRESULT InitDesktopWinsta(
BOOL fAllowError
)
{
HRESULT hr = NOERROR;
DWORD err;
HWINSTA hWinSta = NULL;
HDESK hDesktop = NULL;
OSVERSIONINFO osInfo;
BOOL fWinNT = FALSE;
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if ( GetVersionEx( &osInfo ) ) {
fWinNT = (osInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
// Only applies to NT
if ( !fWinNT )
return(NOERROR);
// Save our old window station so we can restore it later
ghWinStaPrev = GetProcessWindowStation();
if (ghWinStaPrev == NULL)
goto LErr;
// Create a winsta for IIS to use
if ((hWinSta = CreateWindowStation(SZ_IIS_WINSTA, NULL, WINSTA_ALL, NULL)) == NULL)
{
if ( !fAllowError )
{
goto LErr;
}
}
else
{
// Set this as IIS's window station
if (!SetProcessWindowStation(hWinSta))
goto LErr;
}
// Save the old desktop because we might need it later for an obscure error condition
if ((ghdeskPrev = GetThreadDesktop(GetCurrentThreadId())) == NULL)
{
goto LErr;
}
// Create a desktop for IIS to use
if ((hDesktop = CreateDesktop(SZ_IIS_DESKTOP, NULL, NULL, 0, DESKTOP_ALL, NULL)) == NULL)
{
if ( !fAllowError )
{
goto LErr;
}
}
// store these handles in the globals
ghWinSta = hWinSta;
ghDesktop = hDesktop;
// Now initialize Ole security
hr = InitOleSecurity(fAllowError);
return(hr);
LErr:
if (ghWinStaPrev != NULL)
SetProcessWindowStation(ghWinStaPrev);
if (hWinSta != NULL)
CloseWindowStation(hWinSta);
if (hDesktop != NULL)
CloseDesktop(hDesktop);
err = GetLastError();
hr = HRESULT_FROM_WIN32(err);
return(hr);
}
/*===================================================================
UnInitDesktopWinsta
Destroy the IIS desktop and winstation
Parameters:
None
Returns:
Nothing
Side effects
Sets global variables
===================================================================*/
VOID UnInitDesktopWinsta()
{
BOOL fClosed;
if (ghWinSta != NULL)
{
// Set winsta back to the old winsta so we can close the new one
fClosed = SetProcessWindowStation(ghWinStaPrev);
DBG_ASSERT(fClosed);
fClosed = CloseWindowStation(ghWinSta);
DBG_ASSERT(fClosed);
ghWinSta = NULL;
}
if (ghDesktop != NULL)
{
BOOL fRetried = FALSE;
LRetry:
DBG_ASSERT(ghDesktop != NULL);
fClosed = CloseDesktop(ghDesktop);
// If this fails, it probably means that we are in the obscure case where
// IIS's CacheExtensions registry setting is 0. In this case, we are shutting
// down in a worker thread. This worker thread is using the desktop, so
// it cant be closed. In this case, attempt to set the desktop back to the
// original IIS desktop, and then retry closing the desktop. Only retry once.
if (!fClosed && !fRetried)
{
fRetried = TRUE;
if (!SetThreadDesktop(ghdeskPrev))
DBG_ASSERT(FALSE);
goto LRetry;
}
DBG_ASSERT(fClosed);
ghDesktop = NULL;
}
return;
}
/*===================================================================
SetDesktop
Set the desktop for the calling thread
Parameters:
None
Returns:
NOERROR on success
Side effects:
Sets desktop
===================================================================*/
HRESULT SetDesktop(
BOOL fAllowError
)
{
DWORD err;
if (!SetThreadDesktop(ghDesktop))
goto LErr;
return(NOERROR);
LErr:
if ( !fAllowError )
{
DBG_ASSERT(FALSE);
}
err = GetLastError();
return(HRESULT_FROM_WIN32(err));
}
/*===================================================================
InitOleSecurity
Setup for and call CoInitializeSecurity. This will avoid problems with
DCOM security on sites that have no default security.
Parameters:
None
Returns:
Retail -- Always returns NOERROR, failures are ignored.
We dont want to have a failure of setting up security
stop IIS from running at all.
Debug -- DBG_ASSERTs on error and returns error code
Side effects:
Sets desktop
===================================================================*/
HRESULT InitOleSecurity(
BOOL fAllowError
)
{
HRESULT hr = NOERROR;
BOOL fDoCoUninit = TRUE;
DWORD err;
SECURITY_DESCRIPTOR SecurityDesc;
SID NullSid = { SID_REVISION, 1, SECURITY_NULL_SID_AUTHORITY, SECURITY_NULL_RID };
HDESK hdeskSave = NULL;
/*
* We need to set up a security descriptor with an empty ACL so that
* we can CoInitializeSecurity but not give everyone access to the server.
*/
if (!InitializeSecurityDescriptor(&SecurityDesc, SECURITY_DESCRIPTOR_REVISION))
goto LErr;
ACL Acl;
// Initialize a new ACL.
if (!InitializeAcl(&Acl, sizeof(ACL), ACL_REVISION2))
goto LErr;
// Add new ACL to the security descriptor.
if (!SetSecurityDescriptorDacl( &SecurityDesc, TRUE, &Acl, FALSE ))
goto LErr;
if (!SetSecurityDescriptorOwner(&SecurityDesc, &NullSid, FALSE))
goto LErr;
if (!SetSecurityDescriptorGroup(&SecurityDesc, &NullSid, FALSE))
goto LErr;
/*
* This work must be done on the desktop that our threads are going to use.
* However, we are currently running on IIS's thread, and we dont want to
* whack their desktop. So, set to our desktop, do the CoInitializeSecurity,
* then set the old desktop back again. Ole will cache the desktop that
* was set when this CoInitSec was done.
*/
if (FAILED(hr = SetDesktop(fAllowError)))
{
goto LErr;
}
hr = CoInitialize(NULL);
if( FAILED(hr) )
{
fDoCoUninit = FALSE;
}
hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_DYNAMIC_CLOAKING,
NULL );
if( FAILED(hr) )
{
DBGERROR(( DBG_CONTEXT,
"CoInitializeSecurity failed running with default "
"DCOM security settings, hr=%8x\n",
hr
));
}
if( fDoCoUninit )
{
CoUninitialize();
}
// Set the desktop back to what IIS expected it to be
if (!SetThreadDesktop(ghdeskPrev))
{
// Nothing we can do if this fails
DBG_ASSERT(FALSE);
}
//
// This may fire if CoInitializeSecurity fails. So it is probably
// overactive we would have let the CoInitializeSecurity call fail
// in the past, before some PREFIX changes.
//
DBG_ASSERT(SUCCEEDED(hr));
return(hr);
LErr:
DBG_ASSERT(FALSE);
if (SUCCEEDED(hr))
{
err = GetLastError();
hr = HRESULT_FROM_WIN32(err);
}
#ifdef DEBUG
return(hr);
#else
return(NOERROR);
#endif
}