#ifndef _SITECONFIG_HXX_ #define _SITECONFIG_HXX_ /*++ Copyright (c) 1998 Microsoft Corporation Module Name : siteconfig.hxx Abstract: SSL configuration for a given site Author: Bilal Alam (BAlam) 29-March-2000 Environment: Win32 - User Mode Project: Stream Filter Worker Process --*/ class ENDPOINT_CONFIG_HASH; class SERVER_CERT; typedef ULONGLONG ENDPOINT_KEY; #define ENDPOINT_CONFIG_SIGNATURE (DWORD)'GFCS' #define ENDPOINT_CONFIG_SIGNATURE_FREE (DWORD)'gfcs' class ENDPOINT_CONFIG { public: const ENDPOINT_KEY* QueryEndpointKey( VOID ) const { return &_EndpointKey; } SERVER_CERT * QueryServerCert( VOID ) const { return _pServerCert; } IIS_CTL * QueryIisCtl( VOID ) const { return _pIisCtl; } BOOL CheckSignature( VOID ) const { return _dwSignature == ENDPOINT_CONFIG_SIGNATURE; } VOID ReferenceEndpointConfig( VOID ) { InterlockedIncrement( &_cRefs ); } VOID DereferenceEndpointConfig( VOID ) { if ( InterlockedDecrement( &_cRefs ) == 0 ) { delete this; } } BOOL QuerySslConfigured( VOID ) { return _SiteCreds.QueryIsAvailable(); } CredHandle * QueryCredentials( VOID ) { return _SiteCreds.QueryCredentials(); } BOOL QueryUseDSMapper( VOID ) { if ( _pEndpointConfigData == NULL ) { return FALSE; } else { return !!(_pEndpointConfigData->ParamDesc.DefaultFlags & HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER); } } BOOL QueryNegotiateClientCert( VOID ) { // // _fRequireClientCert is used for SSL optimization // If RequireClientCert is set on the root level of the site // then IIS will ask for mutual authentication right away // That way the expensive renegotiation when the whole // ssl key exchange must be repeated is eliminated // if ( _pEndpointConfigData == NULL ) { return FALSE; } else { return !!(_pEndpointConfigData->ParamDesc.DefaultFlags & HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT); } } BOOL QueryNoRawFilter( VOID ) { if ( _pEndpointConfigData == NULL ) { return FALSE; } else { return !!(_pEndpointConfigData->ParamDesc.DefaultFlags & HTTP_SERVICE_CONFIG_SSL_FLAG_NO_RAW_FILTER); } } BOOL IsCtlRequired( VOID ) { if ( _pEndpointConfigData == NULL ) { return FALSE; } else { return _pEndpointConfigData->ParamDesc.pDefaultSslCtlIdentifier != NULL && _pEndpointConfigData->ParamDesc.pDefaultSslCtlIdentifier[0] != L'\0'; } } DWORD QueryCertCheckMode( VOID ) { if ( _pEndpointConfigData == NULL ) { return 0; } else { return _pEndpointConfigData->ParamDesc.DefaultCertCheckMode; } } DWORD QueryRevocationFreshnessTime( VOID ) { if ( _pEndpointConfigData == NULL ) { return 0; } else { return _pEndpointConfigData->ParamDesc.DefaultRevocationFreshnessTime; } } DWORD QueryRevocationUrlRetrievalTimeout( VOID ) { if ( _pEndpointConfigData == NULL ) { return 0; } else { return _pEndpointConfigData->ParamDesc.DefaultRevocationUrlRetrievalTimeout; } } HRESULT AcquireCredentials( VOID ); static HRESULT Initialize( VOID ); static VOID Terminate( VOID ); static HRESULT GetEndpointConfig( CONNECTION_INFO * pConnectionInfo, ENDPOINT_CONFIG ** ppEndpointConfig, BOOL fCreateEmptyIfNotFound = FALSE ); static ENDPOINT_KEY GenerateEndpointKey( DWORD LocalAddress, USHORT LocalPort ) { LARGE_INTEGER liKey; // CODEWORK: this will break for IPv6 // Currently only wildcard IPs are supported for IPv6 liKey.HighPart = LocalAddress; liKey.LowPart = LocalPort; return liKey.QuadPart; } static HRESULT FlushByServerCert( SERVER_CERT * pServerCert ); static HRESULT FlushByIisCtl( IIS_CTL * pIisCtl ); static HRESULT FlushByEndpoint( DWORD LocalAddress, USHORT LocalPort ); static VOID Cleanup( VOID ); static VOID WINAPI ConfigStoreChangeCallback( PVOID pParam, BOOL fWaitFired ); private: // Constructor is private // GetEndpointConfig() is to be called to get reference to the object // ENDPOINT_CONFIG( DWORD LocalAddress, USHORT LocalPort, SERVER_CERT * pServerCert, IIS_CTL * pIisCtl, PHTTP_SERVICE_CONFIG_SSL_SET pEndpointConfigData ) { _cRefs = 1; _dwSignature = ENDPOINT_CONFIG_SIGNATURE; _LocalAddress = LocalAddress; _LocalPort = LocalPort; _EndpointKey = GenerateEndpointKey( LocalAddress, LocalPort ); _pServerCert = pServerCert; _pEndpointConfigData = pEndpointConfigData; // takes ownership of the memory _pIisCtl = pIisCtl; } // Destructor is private // DereferenceEndpointConfig() is to be called for cleanup // virtual ~ENDPOINT_CONFIG(); static LK_PREDICATE ServerCertPredicate( ENDPOINT_CONFIG * pEndpointConfig, void * pvState ); static LK_PREDICATE IisCtlPredicate( ENDPOINT_CONFIG * pEndpointConfig, void * pvState ); static LK_PREDICATE SiteIdPredicate( ENDPOINT_CONFIG * pEndpointConfig, void * pvState ); static LK_PREDICATE EndpointPredicate( ENDPOINT_CONFIG * pEndpointConfig, void * pvState ); static HRESULT GetEndpointConfigData( IN DWORD LocalAddress, IN USHORT LocalPort, OUT PHTTP_SERVICE_CONFIG_SSL_SET * ppEndpointConfigData, OUT BOOL * pfWildcardMatch ); private: DWORD _dwSignature; LONG _cRefs; // key representing IP:Port ENDPOINT_KEY _EndpointKey; // // we don't really need to store _LocalAddress and _LocalPort // but for the debugging or logging it may be convenient // to have the info available // DWORD _LocalAddress; USHORT _LocalPort; // // SSL specific objects // SERVER_CERT * _pServerCert; IIS_CTL * _pIisCtl; SITE_CREDENTIALS _SiteCreds; // // SSL config and Enable Raw Filter flag // PHTTP_SERVICE_CONFIG_SSL_SET _pEndpointConfigData; // // Hash table caching endpoint configuration // static ENDPOINT_CONFIG_HASH * sm_pEndpointConfigHash; // // Objects needed to handle persistent endpoint config store // change notification // static HANDLE sm_hHttpApiConfigChangeEvent; static HKEY sm_hHttpApiConfigKey; static HANDLE sm_hWaitHandle; enum INIT_STATE { INIT_NONE, INIT_HTTPAPI, INIT_HASH, INIT_CHANGE_NOTIF }; // Initialization state static INIT_STATE sm_InitState; }; class ENDPOINT_CONFIG_HASH : public CTypedHashTable< ENDPOINT_CONFIG_HASH, ENDPOINT_CONFIG, const ENDPOINT_KEY * > { public: ENDPOINT_CONFIG_HASH() : CTypedHashTable< ENDPOINT_CONFIG_HASH, ENDPOINT_CONFIG, const ENDPOINT_KEY * > ( "ENDPOINT_CONFIG_HASH" ) { } static const ENDPOINT_KEY * ExtractKey( const ENDPOINT_CONFIG * pEndpointConfig ) { return pEndpointConfig->QueryEndpointKey(); } static DWORD CalcKeyHash( const ENDPOINT_KEY * pEndpointKey ) { return HashBlob( pEndpointKey, sizeof( ENDPOINT_KEY ) ); } static bool EqualKeys( const ENDPOINT_KEY * pEndpointKey1, const ENDPOINT_KEY * pEndpointKey2 ) { return *pEndpointKey1 == *pEndpointKey2; } static void AddRefRecord( ENDPOINT_CONFIG * pEndpointConfig, int nIncr ) { if ( nIncr == +1 ) { pEndpointConfig->ReferenceEndpointConfig(); } else if ( nIncr == -1 ) { pEndpointConfig->DereferenceEndpointConfig(); } } private: // // Not implemented methods // Declarations present to prevent compiler // to generate default ones. // ENDPOINT_CONFIG_HASH( const ENDPOINT_CONFIG_HASH& ); ENDPOINT_CONFIG_HASH& operator=( const ENDPOINT_CONFIG_HASH& ); }; #endif