|
|
/*===================================================================
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
}
|