580 lines
14 KiB
C++
580 lines
14 KiB
C++
|
/*++
|
||
|
|
||
|
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;
|
||
|
}
|