Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

609 lines
13 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name :
sslconfigprovclient.cxx
Abstract:
SSL CONFIG PROV client
Client provides easy way of retrieving SSL related parameters
through named pipes.
Only one pipe connection is currently supported and
all client threads have to share it
( exclusive access is maintained by locking )
Client side is guaranteed not to use any COM stuff.
Not using COM was requirement from NT Security folks
to enable HTTPFilter be hosted in lsass
Author:
Jaroslav Dunajsky April-24-2001
Environment:
Win32 - User Mode
Project:
Stream Filter Worker Process
--*/
#include "precomp.hxx"
HRESULT
SSL_CONFIG_PROV_CLIENT::Initialize(
IN SSL_CONFIG_CHANGE_CALLBACK * pSslConfigChangeCallback,
IN OPTIONAL PVOID pvParam
)
/*++
Routine Description:
Connect to SSL_CONFIG_PIPE
Arguments:
Return Value:
HRESULT
--*/
{
HRESULT hr = E_FAIL;
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"SSL_CONFIG_PROV_CLIENT::Initialize()\n"
));
}
//
// store the callback function pointer, and first parameter
//
_pSslConfigChangeCallback = pSslConfigChangeCallback;
_pSslConfigChangeCallbackParameter = pvParam;
//
// Initialize parent (it will handle all the pipe initialization)
//
return SSL_CONFIG_PIPE::PipeInitializeClient( WSZ_SSL_CONFIG_PIPE );
}
HRESULT
SSL_CONFIG_PROV_CLIENT::Terminate(
VOID
)
/*++
Routine Description:
Cleanup
Arguments:
Return Value:
HRESULT
--*/
{
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"SSL_CONFIG_PROV_CLIENT::Terminate()\n"
));
}
_SslConfigChangeProvClient.StopListeningForChanges();
SSL_CONFIG_PIPE::PipeDisconnect();
return SSL_CONFIG_PIPE::PipeTerminate();
}
HRESULT
SSL_CONFIG_PROV_CLIENT::MaintainPipeConnection(
VOID
)
/*++
Routine Description:
Maintain pipe connection. If connection is not opened
then reopen it
Caller must assure that Pipe is locked when this call is made
Arguments:
Return Value:
HRESULT
--*/
{
HRESULT hr = E_FAIL;
//
// Config change provider has easy way to find out
// if pipe was disconnected because it is actively listening on it
// we assume that if config change provider is connected already, then
// the config provider is connected as well
//
if ( !_SslConfigChangeProvClient.IsConnected() )
{
//
// Check if config provider was ever connected
// If previous connection failed
// (the reason would most likely be crash of inetinfo)
// it is safer to terminate all connections and
// then try to reconnect
//
DBG_ASSERT( IsPipeLocked() );
_SslConfigChangeProvClient.StopListeningForChanges();
SSL_CONFIG_PIPE::PipeDisconnect();
//
// Connect to change notification pipe
//
hr = _SslConfigChangeProvClient.StartListeningForChanges(
_pSslConfigChangeCallback,
_pSslConfigChangeCallbackParameter );
if ( FAILED( hr ) )
{
return hr;
}
//
// Connect to ssl config pipe
//
hr = SSL_CONFIG_PIPE::PipeConnect();
if (FAILED( hr ) )
{
_SslConfigChangeProvClient.StopListeningForChanges();
return hr;
}
//
// Notify user of the config provider
// that all data received so far that may be cached
// should be flushed
//
DBG_ASSERT( _pSslConfigChangeCallback != NULL );
(* _pSslConfigChangeCallback) (
_pSslConfigChangeCallbackParameter,
CMD_CHANGED_ALL,
0 );
return hr;
}
return S_OK;
}
HRESULT
SSL_CONFIG_PROV_CLIENT::GetOneSiteSecureBindings(
IN DWORD dwSiteId,
OUT MULTISZ * pSecureBindings
)
/*++
Routine Description:
Retrieve secure bindings for specified site
Arguments:
Return Value:
HRESULT
--*/
{
DWORD dwReturnedSiteId = 0;
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"GetOneSiteSecureBindings( %d )\n",
dwSiteId ));
}
SSL_CONFIG_PIPE_COMMAND Command;
HRESULT hr = E_FAIL;
DBG_ASSERT( pSecureBindings != NULL );
Command.dwCommandId = CMD_GET_ONE_SITE_SECURE_BINDINGS;
Command.dwParameter1 = dwSiteId;
PipeLock();
//
// assure that pipe will be open
//
hr = MaintainPipeConnection();
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = PipeSendCommand( &Command );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = ReceiveOneSiteSecureBindings( &dwReturnedSiteId ,
pSecureBindings );
Cleanup:
if( FAILED( hr ) )
{
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"GetOneSiteSecureBindings( %d ) leaving with error. hr = 0x%x\n",
hr ));
}
}
PipeUnlock();
return hr;
}
HRESULT
SSL_CONFIG_PROV_CLIENT::ReceiveOneSiteSecureBindings(
OUT DWORD * pdwSiteId,
OUT MULTISZ * pSecureBindings
)
/*++
Routine Description:
read secure bindings from pipe
Note: it's caller's responsibility to have pipe access locked
Arguments:
Return Value:
HRESULT
--*/
{
SSL_CONFIG_PIPE_RESPONSE_HEADER ResponseHeader;
HRESULT hr = E_FAIL;
DBG_ASSERT( pSecureBindings != NULL );
DBG_ASSERT( pdwSiteId != NULL );
DBG_ASSERT( IsPipeLocked() );
hr = PipeReceiveResponseHeader( &ResponseHeader );
if ( FAILED( hr ) )
{
goto failed;
}
DBG_ASSERT( ResponseHeader.dwCommandId == CMD_GET_ONE_SITE_SECURE_BINDINGS );
*pdwSiteId = ResponseHeader.dwParameter1;
if ( FAILED ( ResponseHeader.hrErrorCode ) )
{
//
// return error reported by ssl configuration info provider
//
//BUGBUG always read data to clean up pipe
hr = ResponseHeader.hrErrorCode;
goto failed;
}
if ( !pSecureBindings->Resize( ResponseHeader.dwResponseSize ) )
{
hr = HRESULT_FROM_WIN32( GetLastError());
goto failed;
}
hr = PipeReceiveData( ResponseHeader.dwResponseSize,
reinterpret_cast<BYTE *>(pSecureBindings->QueryPtr()) );
if ( FAILED( hr ) )
{
goto failed;
}
return S_OK;
failed:
DBG_ASSERT( FAILED( hr ) );
return hr;
}
HRESULT
SSL_CONFIG_PROV_CLIENT::StartAllSitesSecureBindingsEnumeration(
VOID
)
/*++
Routine Description:
Lock named pipe for exclusive access
Send command over named pipe to read all secure bindings
Note: StopSiteSecureBindingsEnumeration() must be called
to unlock named pipe (after successfull
StartAllSitesSecureBindingsEnumeration() call )
Arguments:
Return Value:
HRESULT
--*/
{
SSL_CONFIG_PIPE_COMMAND Command;
SSL_CONFIG_PIPE_RESPONSE_HEADER ResponseHeader;
HRESULT hr = E_FAIL;
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"StartAllSitesSecureBindingsEnumeration\n",
hr ));
}
Command.dwCommandId = CMD_GET_ALL_SITES_SECURE_BINDINGS;
Command.dwParameter1 = 0;
PipeLock();
//
// assure that pipe will be open
//
hr = MaintainPipeConnection();
if ( FAILED( hr ) )
{
goto Failure;
}
hr = PipeSendCommand( &Command );
if ( FAILED( hr ) )
{
goto Failure;
}
hr = PipeReceiveResponseHeader( &ResponseHeader );
if ( FAILED( hr ) )
{
goto Failure;
}
DBG_ASSERT( ResponseHeader.dwCommandId == Command.dwCommandId );
//
// Response size 0 means that reponse will be terminated by
// special termination record
//
DBG_ASSERT( ResponseHeader.dwResponseSize == 0 );
if ( FAILED( ResponseHeader.hrErrorCode ) )
{
hr = ResponseHeader.hrErrorCode;
goto Failure;
}
hr = S_OK;
return hr;
Failure:
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"StartAllSitesSecureBindingsEnumeration() leaving with error. hr = 0x%x\n",
hr ));
}
PipeUnlock();
return hr;
}
HRESULT
SSL_CONFIG_PROV_CLIENT::StopAllSitesSecureBindingsEnumeration(
VOID
)
/*++
Routine Description:
If all enumerated data was not read using GetNextSiteSecureBindings()
it will read the leftover. Then unlock access to named pipe
Note: call only after successful StartAllSitesSecureBindingsEnumeration()
Arguments:
Return Value:
HRESULT
--*/
{
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"StopAllSitesSecureBindingsEnumeration\n"
));
}
PipeUnlock();
return S_OK;
}
HRESULT
SSL_CONFIG_PROV_CLIENT::GetNextSiteSecureBindings(
OUT DWORD * pdwId,
OUT MULTISZ * pSecureBindings
)
/*++
Routine Description:
Enumerate all Secure Bindings after StartSiteSecureBindingsEnumeration()
was called
Note: StopSiteSecureBindingsEnumeration() must always be called
afterwards to unlock named pipe
Note: only those sites that contain secure bindings will be enumerated
Arguments:
pdwId - ID of the enumerated site
pSecureBindings - secure bindings
Return Value:
HRESULT
HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) means that all Sites
have been enumerated already. This signals the end of enumeration
--*/
{
return ReceiveOneSiteSecureBindings ( pdwId,
pSecureBindings );
}
HRESULT
SSL_CONFIG_PROV_CLIENT::GetOneSiteSslConfiguration(
IN DWORD dwSiteId,
OUT SITE_SSL_CONFIGURATION * pSiteSslConfiguration
)
/*++
Routine Description:
Get all SSL configuration parameters for specified site
Arguments:
dwSiteId
SiteSslConfiguration
Return Value:
HRESULT
--*/
{
SSL_CONFIG_PIPE_COMMAND Command;
SSL_CONFIG_PIPE_RESPONSE_HEADER ResponseHeader;
HRESULT hr = E_FAIL;
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"GetOneSiteSslConfiguration( %d )\n",
dwSiteId ));
}
Command.dwCommandId = CMD_GET_SSL_CONFIGURATION;
Command.dwParameter1 = dwSiteId;
//
// Get exclusive access to pipe
//
PipeLock();
//
// assure that pipe will be open
//
hr = MaintainPipeConnection();
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Send command to request SSL CONFIGURATION
//
hr = PipeSendCommand( &Command );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Receive response header and later addition response data if available
//
hr = PipeReceiveResponseHeader( &ResponseHeader );
if ( FAILED( hr ) )
{
goto Cleanup;
}
if ( ResponseHeader.dwCommandId != CMD_GET_SSL_CONFIGURATION ||
ResponseHeader.dwResponseSize != sizeof(*pSiteSslConfiguration) )
{
DBG_ASSERT( FALSE );
hr = E_FAIL;
goto Cleanup;
}
if ( FAILED ( ResponseHeader.hrErrorCode ) )
{
//
// return error reported by ssl configuration info provider
//
hr = ResponseHeader.hrErrorCode;
//
// Read data to cleanup the pipe
//
PipeReceiveData( sizeof(*pSiteSslConfiguration),
reinterpret_cast<BYTE *>(pSiteSslConfiguration) );
goto Cleanup;
}
//
// Receive additional data
//
hr = PipeReceiveData( sizeof(*pSiteSslConfiguration),
reinterpret_cast<BYTE *>(pSiteSslConfiguration) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = S_OK;
Cleanup:
if ( FAILED( hr ) )
{
IF_DEBUG( TRACE )
{
DBGPRINTF(( DBG_CONTEXT,
"GetOneSiteSslConfiguration( %d ) leaving with error. hr = 0x%x\n",
dwSiteId,
hr ));
}
}
//
// Done with pipe
//
PipeUnlock();
return hr;
}