mirror of https://github.com/tongzx/nt5src
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.
339 lines
8.2 KiB
339 lines
8.2 KiB
/*===================================================================
|
|
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
|
|
}
|
|
|