2025-04-27 07:49:33 -04:00

474 lines
10 KiB
C++

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name :
siteconfig.cxx
Abstract:
SSL configuration for a given site
Author:
Bilal Alam (BAlam) 29-March-2000
Environment:
Win32 - User Mode
Project:
Stream Filter Worker Process
--*/
#include "precomp.hxx"
SITE_CONFIG_HASH * SITE_CONFIG::sm_pSiteConfigHash;
//static
HRESULT
SITE_CONFIG::Initialize(
VOID
)
/*++
Routine Description:
Initialize site configuration globals
Arguments:
None
Return Value:
HRESULT
--*/
{
sm_pSiteConfigHash = new SITE_CONFIG_HASH();
if ( sm_pSiteConfigHash == NULL )
{
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
}
return NO_ERROR;
}
//static
VOID
SITE_CONFIG::Terminate(
VOID
)
/*++
Routine Description:
Cleanup site configuration globals
Arguments:
None
Return Value:
None
--*/
{
if ( sm_pSiteConfigHash != NULL )
{
//
// Clear hash table before deleting it
//
sm_pSiteConfigHash->Clear();
delete sm_pSiteConfigHash;
sm_pSiteConfigHash = NULL;
}
}
//static
HRESULT
SITE_CONFIG::GetSiteConfig(
DWORD dwSiteId,
SITE_CONFIG ** ppSiteConfig
)
/*++
Routine Description:
Lookup site configuration in hash table. If not there then create it
and add it to table
Arguments:
dwSiteId - Site ID to lookup
ppSiteConfig - Filled with pointer to site config on success
Return Value:
HRESULT
--*/
{
LK_RETCODE lkrc;
SITE_CONFIG * pSiteConfig = NULL;
SERVER_CERT * pServerCert = NULL;
HRESULT hr = NO_ERROR;
WCHAR achNum[ 64 ];
STACK_STRU( strMBPath, 64 );
if ( ppSiteConfig == NULL ||
dwSiteId == 0 )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
*ppSiteConfig = NULL;
//
// First lookup in the cache
//
DBG_ASSERT( sm_pSiteConfigHash != NULL );
lkrc = sm_pSiteConfigHash->FindKey( dwSiteId,
&pSiteConfig );
if ( lkrc == LK_SUCCESS )
{
DBG_ASSERT( pSiteConfig != NULL );
*ppSiteConfig = pSiteConfig;
return NO_ERROR;
}
//
// Ok. We will have to make a new config object and add it to cache.
// Start by getting the server certificate.
//
//
// Check if Client certificates are required on the site's root level
//
MB mb( g_pStreamFilter->QueryMDObject() );
WCHAR achMBPath[ 256 ];
DWORD dwSslAccessPerm = 0;
BOOL fRequireClientCert = FALSE;
DWORD dwUseDsMapper = 0;
BOOL fUseDSMapper = FALSE;
DWORD dwCertCheckMode = 0;
DWORD dwRevocationFreshnessTime = 86400; // 1 day in seconds
DWORD dwRevocationUrlRetrievalTimeout = 0; // default timeout
if ( mb.Open( L"/LM/W3SVC/",
METADATA_PERMISSION_READ ) )
{
//
// Lookup SSLUseDsMapper
// SSLUseDsMapper is global setting that is not inherited to sites (IIS5 legacy)
// We have to read it from lm/w3svc
//
mb.GetDword( L"",
MD_SSL_USE_DS_MAPPER,
IIS_MD_UT_SERVER,
&dwUseDsMapper );
fUseDSMapper = !!dwUseDsMapper;
//
// lookup if client certificates are required on site (or site's root level)
//
_snwprintf( achMBPath,
sizeof( achMBPath ) / sizeof( WCHAR ) - 1,
L"/%d/root/",
dwSiteId );
mb.GetDword( achMBPath,
MD_SSL_ACCESS_PERM,
IIS_MD_UT_FILE,
&dwSslAccessPerm );
fRequireClientCert = ( ( dwSslAccessPerm & MD_ACCESS_REQUIRE_CERT ) &&
( dwSslAccessPerm & MD_ACCESS_NEGO_CERT ) );
//
// lookup Certificate revocation related parameters
//
_snwprintf( achMBPath,
sizeof( achMBPath ) / sizeof( WCHAR ) - 1,
L"/%d/",
dwSiteId );
mb.GetDword( achMBPath,
MD_CERT_CHECK_MODE,
IIS_MD_UT_SERVER,
&dwCertCheckMode );
mb.GetDword( achMBPath,
MD_REVOCATION_FRESHNESS_TIME,
IIS_MD_UT_SERVER,
&dwRevocationFreshnessTime );
mb.GetDword( achMBPath,
MD_REVOCATION_URL_RETRIEVAL_TIMEOUT,
IIS_MD_UT_SERVER,
&dwRevocationUrlRetrievalTimeout );
mb.Close();
}
//
// We have enough to lookup in SERVER_CERT cache
//
hr = SERVER_CERT::GetServerCertificate( dwSiteId,
&pServerCert );
if ( FAILED( hr ) )
{
//
// If we couldn't get a server cert, then we're toast and SSL will
// not be enablable for this site.
//
return hr;
}
DBG_ASSERT( pServerCert != NULL );
//
// OK. Create the config and attempt to add it to the cache
//
pSiteConfig = new SITE_CONFIG( dwSiteId,
pServerCert,
fRequireClientCert,
fUseDSMapper,
dwCertCheckMode,
dwRevocationFreshnessTime,
dwRevocationUrlRetrievalTimeout );
if ( pSiteConfig == NULL )
{
pServerCert->DereferenceServerCert();
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
}
//
// Acquire credentials
//
hr = pSiteConfig->AcquireCredentials();
if ( FAILED( hr ) )
{
delete pSiteConfig;
return hr;
}
//
// We don't care what the success of the insertion was. If it failed,
// then the pSiteConfig will not be extra referenced and the caller
// will clean it up when it derefs
//
sm_pSiteConfigHash->InsertRecord( pSiteConfig );
*ppSiteConfig = pSiteConfig;
return NO_ERROR;
}
//static
LK_PREDICATE
SITE_CONFIG::ServerCertPredicate(
SITE_CONFIG * pSiteConfig,
void * pvState
)
/*++
Description:
DeleteIf() predicate used to find items which reference the
SERVER_CERT pointed to by pvState
Arguments:
pSiteConfig - Site config (duh)
pvState - SERVER_CERT to check for
Returns:
LK_PREDICATE - LKP_PERFORM indicates removing the current
token from token cache
LKP_NO_ACTION indicates doing nothing.
--*/
{
LK_PREDICATE lkpAction;
SERVER_CERT * pServerCert;
DBG_ASSERT( pSiteConfig != NULL );
pServerCert = (SERVER_CERT*) pvState;
DBG_ASSERT( pServerCert != NULL );
if ( pSiteConfig->QueryServerCert() == pServerCert )
{
lkpAction = LKP_PERFORM;
}
else
{
lkpAction = LKP_NO_ACTION;
}
return lkpAction;
}
//static
HRESULT
SITE_CONFIG::FlushByServerCert(
SERVER_CERT * pServerCert
)
/*++
Routine Description:
Flush the SITE_CONFIG cache of anything referecing the given server
certificate
Arguments:
pServerCert - Server certificate to reference
Return Value:
HRESULT
--*/
{
DBG_ASSERT( sm_pSiteConfigHash != NULL );
sm_pSiteConfigHash->DeleteIf( SITE_CONFIG::ServerCertPredicate,
pServerCert );
return NO_ERROR;
}
//static
LK_PREDICATE
SITE_CONFIG::SiteIdPredicate(
SITE_CONFIG * pSiteConfig,
void * pvState
)
/*++
Description:
DeleteIf() predicate to delete config specified by site id (pvState)
Arguments:
pSiteConfig - Site config (duh)
pvState - Site ID
Returns:
LK_PREDICATE - LKP_PERFORM indicates removing the current
token from token cache
LKP_NO_ACTION indicates doing nothing.
--*/
{
LK_PREDICATE lkpAction;
DWORD dwSiteId;
DBG_ASSERT( pSiteConfig != NULL );
dwSiteId = PtrToUlong(pvState);
if ( pSiteConfig->QuerySiteId() == dwSiteId ||
dwSiteId == 0 )
{
lkpAction = LKP_PERFORM;
}
else
{
lkpAction = LKP_NO_ACTION;
}
return lkpAction;
}
//static
HRESULT
SITE_CONFIG::FlushBySiteId(
DWORD dwSiteId
)
/*++
Routine Description:
Flush specified site configuration. If dwSiteId is 0, then flush all
Arguments:
dwSiteId - Site ID to flush (0 for all)
Return Value:
HRESULT
--*/
{
DBG_ASSERT( sm_pSiteConfigHash != NULL );
sm_pSiteConfigHash->DeleteIf( SITE_CONFIG::SiteIdPredicate,
(PVOID) UIntToPtr(dwSiteId) );
return NO_ERROR;
}
SITE_CONFIG::~SITE_CONFIG()
{
if ( _pServerCert != NULL )
{
_pServerCert->DereferenceServerCert();
_pServerCert = NULL;
}
_dwSignature = SITE_CONFIG_SIGNATURE_FREE;
}
HRESULT
SITE_CONFIG::AcquireCredentials(
VOID
)
/*++
Routine Description:
To the Schannel thing to get credentials handles representing the
server cert/mapping configuration of this site
Arguments:
None
Return Value:
HRESULT
--*/
{
DBG_ASSERT( _pServerCert != NULL );
return _SiteCreds.AcquireCredentials( _pServerCert,
_fUseDSMapper );
}