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

353 lines
7.0 KiB
C++

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name :
certstore.cxx
Abstract:
Wrapper of a certificate store
Author:
Bilal Alam (BAlam) 29-March-2000
Environment:
Win32 - User Mode
Project:
Stream Filter Worker Process
--*/
#include "precomp.hxx"
CERT_STORE_HASH * CERT_STORE::sm_pCertStoreHash;
CERT_STORE::CERT_STORE()
: _cRefs( 1 ),
_hStore( NULL ),
_hWaitHandle( NULL ),
_hStoreChangeEvent( NULL )
{
_dwSignature = CERT_STORE_SIGNATURE;
}
CERT_STORE::~CERT_STORE()
{
_dwSignature = CERT_STORE_SIGNATURE_FREE;
if ( _hWaitHandle != NULL )
{
UnregisterWait( _hWaitHandle );
_hWaitHandle = NULL;
}
if ( _hStoreChangeEvent != NULL )
{
CloseHandle( _hStoreChangeEvent );
_hStoreChangeEvent = NULL;
}
if ( _hStore != NULL )
{
CertCloseStore( _hStore, 0 );
_hStore = NULL;
}
}
//static
VOID
WINAPI
CERT_STORE::CertStoreChangeRoutine(
VOID * pvContext,
BOOLEAN fTimedOut
)
/*++
Routine Description:
Called when a certificate store has changed
Arguments:
pvContext - Points to CERT_STORE which changed
fTimedOut - Should always be FALSE since our wait is INFINITE
Return Value:
HRESULT
--*/
{
CERT_STORE * pCertStore;
HRESULT hr;
DBG_ASSERT( pvContext != NULL );
DBG_ASSERT( fTimedOut == FALSE );
pCertStore = (CERT_STORE*) pvContext;
DBG_ASSERT( pCertStore->CheckSignature() );
//
// Reference before we calling to DeleteRecord() so that we maintain
// a record for use with flushing the server cert cache
//
pCertStore->ReferenceStore();
//
// Remove the thing from the hash table for one
//
sm_pCertStoreHash->DeleteRecord( pCertStore );
//
// Instruct the server certificate cache to flush any certs which
// were referencing this cert store.
//
// That will, in turn, flush any site configurations which were referencing
// the given server cert
//
SERVER_CERT::FlushByStore( pCertStore );
//
// Should be the last dereference of the object
//
pCertStore->DereferenceStore();
}
HRESULT
CERT_STORE::Open(
STRU & strStoreName
)
/*++
Routine Description:
Open specified certificate store
Arguments:
strStoreName - name of certificate store to open
Return Value:
HRESULT
--*/
{
HRESULT hr = NO_ERROR;
BOOL fRet = TRUE;
DBG_ASSERT( CheckSignature() );
//
// Remember the name
//
hr = _strStoreName.Copy( strStoreName );
if ( FAILED( hr ) )
{
return hr;
}
DBG_ASSERT( _hStore == NULL );
//
// Get the handle
//
_hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
strStoreName.QueryStr() );
if ( _hStore == NULL )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
//
// Setup a change notification so that we are informed the cert store
// has changed
//
_hStoreChangeEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if ( _hStoreChangeEvent == NULL )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
fRet = RegisterWaitForSingleObject( &_hWaitHandle,
_hStoreChangeEvent,
CERT_STORE::CertStoreChangeRoutine,
this,
INFINITE,
WT_EXECUTEONLYONCE );
if ( !fRet )
{
DBG_ASSERT( _hWaitHandle == NULL );
return HRESULT_FROM_WIN32( GetLastError() );
}
fRet = CertControlStore( _hStore,
0,
CERT_STORE_CTRL_NOTIFY_CHANGE,
&_hStoreChangeEvent );
if ( !fRet )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
return NO_ERROR;
}
//static
HRESULT
CERT_STORE::Initialize(
VOID
)
/*++
Routine Description:
Initialize CERT_STORE globals
Arguments:
None
Return Value:
HRESULT
--*/
{
DBG_ASSERT( sm_pCertStoreHash == NULL );
sm_pCertStoreHash = new CERT_STORE_HASH();
if ( sm_pCertStoreHash == NULL )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
return NO_ERROR;
}
//static
VOID
CERT_STORE::Terminate(
VOID
)
/*++
Routine Description:
Terminate CERT_STORE globals
Arguments:
None
Return Value:
None
--*/
{
if ( sm_pCertStoreHash != NULL )
{
delete sm_pCertStoreHash;
sm_pCertStoreHash = NULL;
}
}
//static
HRESULT
CERT_STORE::OpenStore(
STRU & strStoreName,
CERT_STORE ** ppStore
)
/*++
Routine Description:
Open certificate store from cache
Arguments:
strStoreName - Store name to open
ppStore - Filled with store on success
Return Value:
HRESULT
--*/
{
HRESULT hr = NO_ERROR;
CERT_STORE * pCertStore = NULL;
LK_RETCODE lkrc;
if ( ppStore == NULL )
{
DBG_ASSERT( FALSE );
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Finished;
}
*ppStore = NULL;
//
// Lookup in cache first
//
DBG_ASSERT( sm_pCertStoreHash != NULL );
lkrc = sm_pCertStoreHash->FindKey( strStoreName.QueryStr(),
&pCertStore );
if ( lkrc != LK_SUCCESS )
{
//
// OK. Create one and add to cache
//
pCertStore = new CERT_STORE();
if ( pCertStore == NULL )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Finished;
}
hr = pCertStore->Open( strStoreName );
if ( FAILED( hr ) )
{
goto Finished;
}
lkrc = sm_pCertStoreHash->InsertRecord( pCertStore );
//
// Ignore the error. We will do the right thing if we couldn't
// add to hash (i.e. no extra reference happens and callers deref
// will delete the object as desired)
//
}
DBG_ASSERT( pCertStore != NULL );
*ppStore = pCertStore;
return NO_ERROR;
Finished:
if ( pCertStore != NULL )
{
pCertStore->DereferenceStore();
pCertStore = NULL;
}
return hr;
}