|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
w3site.cxx
Abstract:
W3_SITE object holds state for each site
Author:
Anil Ruia (AnilR) 18-Jan-2000
Revision History:
--*/
#include "precomp.hxx"
//
// No advance notification
//
#define DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS 14
//
// OWA change flags
//
#define DEFAULT_W3_AUTH_CHANGE_FLAGS 6
//
// In seconds
//
#define DEFAULT_W3_ADV_CACHE_TTL ( 10 * 60 )
//static
CRITICAL_SECTION W3_SITE::sm_csIISCertMapLock;
W3_SITE::W3_SITE( DWORD SiteId ) : m_SiteId ( SiteId ), m_cRefs ( 1 ), m_pInstanceFilterList ( NULL ), m_pLogging ( NULL ), m_fAllowPathInfoForScriptMappings ( FALSE ), m_fUseDSMapper ( FALSE ), m_dwAuthChangeFlags ( 0 ), m_dwAdvNotPwdExpInDays ( DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS ), m_dwAdvCacheTTL ( DEFAULT_W3_ADV_CACHE_TTL ), m_fSSLSupported ( FALSE ), m_pIISCertMap ( NULL ), m_fAlreadyAttemptedToLoadIISCertMap ( FALSE ), m_Signature ( W3_SITE_SIGNATURE ) { ZeroMemory(&m_PerfCounters, sizeof m_PerfCounters); }
W3_SITE::~W3_SITE() { if (m_pInstanceFilterList != NULL) { m_pInstanceFilterList->Dereference(); m_pInstanceFilterList = NULL; } if (m_pLogging != NULL) { m_pLogging->Release(); m_pLogging = NULL; }
if ( m_pIISCertMap != NULL ) { m_pIISCertMap->DereferenceCertMapping(); m_pIISCertMap = NULL; } m_Signature = W3_SITE_SIGNATURE_FREE; }
HRESULT W3_SITE::Initialize(LOGGING *pLogging, FILTER_LIST *pFilterList) /*++
Routine Description:
Initialize W3_SITE. Should be called after constructor
Arguments: None Return Value:
HRESULT
--*/ { HRESULT hr = NO_ERROR; WCHAR idToStr[MAX_SITEID_LENGTH + 6]; CHAR idToStrA[MAX_SITEID_LENGTH + 6];
//
// Setup Site Name like "W3SVC1"
//
sprintf(idToStrA, "W3SVC%u", m_SiteId); if (FAILED(hr = m_SiteName.Copy(idToStrA))) { goto Failure; }
//
// Setup site path (like "/LM/W3SVC/1")
//
hr = m_SiteMBPath.Copy(g_pW3Server->QueryMDPath()); if ( FAILED( hr ) ) { goto Failure; }
_itow(m_SiteId, idToStr, 10);
hr = m_SiteMBPath.Append( idToStr ); if ( FAILED( hr ) ) { goto Failure; }
//
// Setup site root (like "/LM/W3SVC/1/ROOT/")
//
hr = m_SiteMBRoot.Copy( m_SiteMBPath ); if ( FAILED( hr ) ) { goto Failure; }
hr = m_SiteMBRoot.Append( L"/Root/" ); if ( FAILED( hr ) ) { goto Failure; }
//
// Read the per-site properties from the metabase
//
if (FAILED(hr = ReadPrivateProperties())) { goto Failure; }
//
// Initialize instance filters
//
if (pFilterList) { pFilterList->Reference(); m_pInstanceFilterList = pFilterList; } else { m_pInstanceFilterList = new FILTER_LIST(); if (m_pInstanceFilterList == NULL) { hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); goto Failure; }
hr = m_pInstanceFilterList->InsertGlobalFilters(); if (FAILED(hr)) { goto Failure; }
hr = m_pInstanceFilterList->LoadFilters(m_SiteMBPath.QueryStr(), FALSE); if (FAILED(hr)) { goto Failure; } } //
// Initialize logging
//
if (pLogging) { pLogging->AddRef(); m_pLogging = pLogging; } else { m_pLogging = new LOGGING; if (m_pLogging == NULL) { hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); goto Failure; }
if(FAILED(hr = m_pLogging->ActivateLogging(m_SiteName.QueryStr(), m_SiteMBPath.QueryStr(), g_pW3Server->QueryMDObject()))) { goto Failure; } } return S_OK; Failure: return hr; }
HRESULT W3_SITE::ReadPrivateProperties() /*++
Routine description: Read the site specific properties from the metabase
Arguments: none
Return Value: HRESULT --*/ { MB mb( g_pW3Server->QueryMDObject() ); MULTISZ mszSecureBindings;
//
// Read per-site properties from the metabase
//
if ( !mb.Open(m_SiteMBPath.QueryStr()) ) { return HRESULT_FROM_WIN32(GetLastError()); }
if ( !mb.GetDword(L"", MD_ALLOW_PATH_INFO_FOR_SCRIPT_MAPPINGS, IIS_MD_UT_FILE, (DWORD *)&m_fAllowPathInfoForScriptMappings, 0) ) { m_fAllowPathInfoForScriptMappings = FALSE; }
mb.GetStr( L"", MD_AUTH_CHANGE_URL, IIS_MD_UT_SERVER, &m_strAuthChangeUrl );
mb.GetStr( L"", MD_AUTH_EXPIRED_URL, IIS_MD_UT_SERVER, &m_strAuthExpiredUrl );
mb.GetStr( L"", MD_AUTH_NOTIFY_PWD_EXP_URL, IIS_MD_UT_SERVER, &m_strAdvNotPwdExpUrl );
mb.GetStr( L"", MD_AUTH_EXPIRED_UNSECUREURL, IIS_MD_UT_SERVER, &m_strAuthExpiredUnsecureUrl );
mb.GetStr( L"", MD_AUTH_NOTIFY_PWD_EXP_UNSECUREURL, IIS_MD_UT_SERVER, &m_strAdvNotPwdExpUnsecureUrl );
if ( !mb.GetDword( L"", MD_ADV_NOTIFY_PWD_EXP_IN_DAYS, IIS_MD_UT_SERVER, &m_dwAdvNotPwdExpInDays ) ) { m_dwAdvNotPwdExpInDays = DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS; }
if ( !mb.GetDword( L"", MD_AUTH_CHANGE_FLAGS, IIS_MD_UT_SERVER, &m_dwAuthChangeFlags ) ) { m_dwAuthChangeFlags = DEFAULT_W3_AUTH_CHANGE_FLAGS; }
if ( !mb.GetDword( L"", MD_ADV_CACHE_TTL, IIS_MD_UT_SERVER, &m_dwAdvCacheTTL ) ) { m_dwAdvCacheTTL = DEFAULT_W3_ADV_CACHE_TTL; }
//
// Read the secure bindings.
//
if ( mb.GetMultisz( L"", MD_SECURE_BINDINGS, IIS_MD_UT_SERVER, &mszSecureBindings ) ) { if( !mszSecureBindings.IsEmpty() ) { m_fSSLSupported = TRUE; } }
DBG_REQUIRE( mb.Close() );
//
// Read global properties from the metabase that affect site config
//
if ( !mb.Open(g_pW3Server->QueryMDPath()) ) { return HRESULT_FROM_WIN32(GetLastError()); }
if ( !mb.GetDword( L"", MD_SSL_USE_DS_MAPPER, IIS_MD_UT_SERVER, (DWORD*) &m_fUseDSMapper, 0 )) { m_fUseDSMapper = FALSE; }
DBG_REQUIRE( mb.Close() );
return S_OK; }
HRESULT W3_SITE::HandleMetabaseChange( const MD_CHANGE_OBJECT &ChangeObject, IN W3_SITE_LIST *pTempSiteList ) /*++
Routine Description:
Handle metabase changes. The change may be to either the /LM/W3SVC/ node or they may be changes to this site or one of its children.
This routine needs to perform cache flushes and reget site metadata if necessary.
Arguments: ChangeObject Return Value:
See W3_SERVER_INSTANCE::MDChangeNotify and IIS_SERVER_INSTANCE::MDChangeNotify for implemenation details
--*/ { DBGPRINTF(( DBG_CONTEXT, "W3_SITE Notified - Path(%S) Type(%d) NumIds(%08x)\n", ChangeObject.pszMDPath, ChangeObject.dwMDChangeType, ChangeObject.dwMDNumDataIDs ));
//
// Let the cache manager invalidate the various cache entries dependent
// on metadata
//
W3CacheDoMetadataInvalidation( ChangeObject.pszMDPath, wcslen( ChangeObject.pszMDPath ) );
//
// Handle any site level change
// That means any changes at /LM/w3svc/n or /LM/w3svc/n/Filters
//
if ((_wcsnicmp(ChangeObject.pszMDPath, m_SiteMBPath.QueryStr(), m_SiteMBPath.QueryCCH()) == 0) && ((wcscmp(ChangeObject.pszMDPath + m_SiteMBPath.QueryCCH(), L"/") == 0) || (_wcsicmp(ChangeObject.pszMDPath + m_SiteMBPath.QueryCCH(), L"/Filters/") == 0))) { //
// If the site (or its root application) has been deleted, remove it
// unless we are in the iterator in which case it will anyway be
// removed
//
if (ChangeObject.dwMDChangeType == MD_CHANGE_TYPE_DELETE_OBJECT) { if (pTempSiteList == NULL) { g_pW3Server->RemoveSite(this); }
return S_OK; }
//
// Now handle any property changes.
//
BOOL fLoggingHasChanged = FALSE; BOOL fFiltersHaveChanged = FALSE;
//
// Find out if we would need to handle any logging or filter changes
//
for (DWORD i = 0; i < ChangeObject.dwMDNumDataIDs; i++) { DWORD PropertyID = ChangeObject.pdwMDDataIDs[i];
if (((PropertyID >= IIS_MD_LOG_BASE) && (PropertyID <= IIS_MD_LOG_LAST)) || ((PropertyID >= IIS_MD_LOGCUSTOM_BASE) && (PropertyID <= IIS_MD_LOGCUSTOM_LAST))) { fLoggingHasChanged = TRUE; } else if (PropertyID == MD_FILTER_LOAD_ORDER) { fFiltersHaveChanged = TRUE; } }
//
// Create a new site
//
W3_SITE *site = new W3_SITE(m_SiteId); if (site == NULL) { return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); }
//
// Copy over the cache context, and also logging and filter info
// if applicable
//
HRESULT hr; if (FAILED(hr = site->Initialize( fLoggingHasChanged ? NULL : m_pLogging, fFiltersHaveChanged ? NULL : m_pInstanceFilterList))) { site->Release(); return hr; }
//
// Depending on whether we are in the iterator, either replace the
// site in the site list or add it to the temp list which will replace
// the real list later
//
if (pTempSiteList == NULL) { g_pW3Server->AddSite(site, true); } else { pTempSiteList->InsertRecord(site); }
// Release the extra reference
site->Release(); }
return S_OK; }
HRESULT W3_SITE::GetIISCertificateMapping( IIS_CERTIFICATE_MAPPING ** ppIISCertificateMapping ) /*++
Routine Description:
Arguments: ppIISCertificateMapping - returns found iis cert mapping object
m_pIISCertMap is created on demand. It will not be created when W3_SITE is created, only when first request that requires certificate mappings Return Value:
HRESULT
--*/
{ HRESULT hr = E_FAIL; DBG_ASSERT( ppIISCertificateMapping != NULL ); if ( m_fAlreadyAttemptedToLoadIISCertMap ) { *ppIISCertificateMapping = m_pIISCertMap; hr = S_OK; goto Finished; } else { IIS_CERTIFICATE_MAPPING * pCertMap = NULL;
//
// This lock only applies when certmapping was not yet read
// Global lock will only apply for reading certmapper for site
// on the very first attempt to fetch file that enables
// IIS certmapping
//
GlobalLockIISCertMap();
//
// try again to prevent loading of mapping multiple times
//
if ( m_fAlreadyAttemptedToLoadIISCertMap ) { hr = S_OK; } else { //
// build IIS Certificate mapping structure and
// add update W3_SITE structure
//
if ( m_fUseDSMapper ) { m_pIISCertMap = NULL; hr = S_OK; } else { hr = IIS_CERTIFICATE_MAPPING::GetCertificateMapping( m_SiteId, &pCertMap ); if ( SUCCEEDED( hr ) ) { m_pIISCertMap = pCertMap; } } //
// always set m_fAlreadyAttemptedToLoadIISCertMap to TRUE (regardless of error)
// that would prevent reading mappings for each request in the case of failure
// it is valid for m_pIISCertMap to be NULL (regardless of m_fAlreadyAttemptedToLoadIISCertMap)
//
InterlockedExchange( reinterpret_cast<LONG *>(&m_fAlreadyAttemptedToLoadIISCertMap), TRUE ); } GlobalUnlockIISCertMap(); if ( FAILED( hr ) ) { goto Finished; } } *ppIISCertificateMapping = m_pIISCertMap; hr = S_OK; Finished: return hr; }
|