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.
1924 lines
58 KiB
1924 lines
58 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows NT Security
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: tvo.cpp
|
|
//
|
|
// Contents: Implementation of CryptGetTimeValidObject
|
|
//
|
|
// History: 25-Sep-97 kirtd Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include <global.hxx>
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CryptGetTimeValidObject
|
|
//
|
|
// Synopsis: get a time valid CAPI2 object
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CryptGetTimeValidObject (
|
|
IN LPCSTR pszTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
HCRYPTOIDFUNCADDR hGetTimeValidObject;
|
|
PFN_GET_TIME_VALID_OBJECT_FUNC pfnGetTimeValidObject;
|
|
DWORD LastError;
|
|
FILETIME CurrentTime;
|
|
|
|
if ( CryptGetOIDFunctionAddress(
|
|
hGetTimeValidObjectFuncSet,
|
|
X509_ASN_ENCODING,
|
|
pszTimeValidOid,
|
|
0,
|
|
(LPVOID *)&pfnGetTimeValidObject,
|
|
&hGetTimeValidObject
|
|
) == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pftValidFor == NULL )
|
|
{
|
|
GetSystemTimeAsFileTime( &CurrentTime );
|
|
pftValidFor = &CurrentTime;
|
|
}
|
|
|
|
fResult = ( *pfnGetTimeValidObject )(
|
|
pszTimeValidOid,
|
|
pvPara,
|
|
pIssuer,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
ppvObject,
|
|
pCredentials,
|
|
pvReserved
|
|
);
|
|
|
|
LastError = GetLastError();
|
|
CryptFreeOIDFunctionAddress( hGetTimeValidObject, 0 );
|
|
SetLastError( LastError );
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CtlGetTimeValidObject
|
|
//
|
|
// Synopsis: get a time valid CTL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CtlGetTimeValidObject (
|
|
IN LPCSTR pszTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->GetTimeValidObject(
|
|
pszTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CTL,
|
|
pIssuer,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
ppvObject,
|
|
pCredentials,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CrlGetTimeValidObject
|
|
//
|
|
// Synopsis: get a time valid CRL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CrlGetTimeValidObject (
|
|
IN LPCSTR pszTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->GetTimeValidObject(
|
|
pszTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
ppvObject,
|
|
pCredentials,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CrlFromCertGetTimeValidObject
|
|
//
|
|
// Synopsis: get a time valid CRL from a subject certificate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CrlFromCertGetTimeValidObject (
|
|
IN LPCSTR pszTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->GetTimeValidObject(
|
|
pszTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
ppvObject,
|
|
pCredentials,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreshestCrlFromCertGetTimeValidObject
|
|
//
|
|
// Synopsis: get a time valid freshest, delta CRL from a subject certificate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
FreshestCrlFromCertGetTimeValidObject (
|
|
IN LPCSTR pszTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->GetTimeValidObject(
|
|
pszTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
ppvObject,
|
|
pCredentials,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreshestCrlFromCrlGetTimeValidObject
|
|
//
|
|
// Synopsis: get a time valid freshest, delta CRL from a base CRL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
FreshestCrlFromCrlGetTimeValidObject (
|
|
IN LPCSTR pszTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->GetTimeValidObject(
|
|
pszTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
ppvObject,
|
|
pCredentials,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CryptFlushTimeValidObject
|
|
//
|
|
// Synopsis: flush the object from the "TVO" system
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CryptFlushTimeValidObject (
|
|
IN LPCSTR pszFlushTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pvReserved
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
HCRYPTOIDFUNCADDR hFlushTimeValidObject;
|
|
PFN_FLUSH_TIME_VALID_OBJECT_FUNC pfnFlushTimeValidObject;
|
|
DWORD LastError;
|
|
|
|
if ( CryptGetOIDFunctionAddress(
|
|
hFlushTimeValidObjectFuncSet,
|
|
X509_ASN_ENCODING,
|
|
pszFlushTimeValidOid,
|
|
0,
|
|
(LPVOID *)&pfnFlushTimeValidObject,
|
|
&hFlushTimeValidObject
|
|
) == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
fResult = ( *pfnFlushTimeValidObject )(
|
|
pszFlushTimeValidOid,
|
|
pvPara,
|
|
pIssuer,
|
|
dwFlags,
|
|
pvReserved
|
|
);
|
|
|
|
LastError = GetLastError();
|
|
CryptFreeOIDFunctionAddress( hFlushTimeValidObject, 0 );
|
|
SetLastError( LastError );
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CtlFlushTimeValidObject
|
|
//
|
|
// Synopsis: flush a CTL from the "TVO" system
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CtlFlushTimeValidObject (
|
|
IN LPCSTR pszFlushTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->FlushTimeValidObject(
|
|
pszFlushTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CTL,
|
|
pIssuer,
|
|
dwFlags,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CrlFlushTimeValidObject
|
|
//
|
|
// Synopsis: flush a CRL from the "TVO" system
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CrlFlushTimeValidObject (
|
|
IN LPCSTR pszFlushTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->FlushTimeValidObject(
|
|
pszFlushTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
dwFlags,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CrlFromCertFlushTimeValidObject
|
|
//
|
|
// Synopsis: flush a CRL from the "TVO" system given a subject cert
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CrlFromCertFlushTimeValidObject (
|
|
IN LPCSTR pszFlushTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->FlushTimeValidObject(
|
|
pszFlushTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
dwFlags,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreshedtCrlFromCertFlushTimeValidObject
|
|
//
|
|
// Synopsis: flush a freshest, delta CRL from the "TVO" system given a
|
|
// subject cert
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
FreshestCrlFromCertFlushTimeValidObject (
|
|
IN LPCSTR pszFlushTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->FlushTimeValidObject(
|
|
pszFlushTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
dwFlags,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreshestCrlFromCrlFlushTimeValidObject
|
|
//
|
|
// Synopsis: flush a freshest, delta CRL from the "TVO" system given a
|
|
// base CRL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
FreshestCrlFromCrlFlushTimeValidObject (
|
|
IN LPCSTR pszFlushTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pvReserved
|
|
)
|
|
{
|
|
return( g_pProcessTVOAgent->FlushTimeValidObject(
|
|
pszFlushTimeValidOid,
|
|
pvPara,
|
|
CONTEXT_OID_CRL,
|
|
pIssuer,
|
|
dwFlags,
|
|
pvReserved
|
|
) );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOCache::CTVOCache, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTVOCache::CTVOCache (
|
|
DWORD cCacheBuckets,
|
|
DWORD MaxCacheEntries,
|
|
BOOL& rfResult
|
|
)
|
|
{
|
|
LRU_CACHE_CONFIG CacheConfig;
|
|
|
|
assert( MaxCacheEntries > 0 );
|
|
|
|
memset( &CacheConfig, 0, sizeof( CacheConfig ) );
|
|
|
|
CacheConfig.dwFlags = LRU_CACHE_NO_SERIALIZE | LRU_CACHE_NO_COPY_IDENTIFIER;
|
|
CacheConfig.cBuckets = cCacheBuckets;
|
|
CacheConfig.MaxEntries = MaxCacheEntries;
|
|
CacheConfig.pfnHash = TVOCacheHashOriginIdentifier;
|
|
CacheConfig.pfnOnRemoval = TVOCacheOnRemoval;
|
|
|
|
rfResult = I_CryptCreateLruCache( &CacheConfig, &m_hCache );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOCache::~CTVOCache, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTVOCache::~CTVOCache ()
|
|
{
|
|
I_CryptFreeLruCache( m_hCache, 0, NULL );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOCache::InsertCacheEntry, public
|
|
//
|
|
// Synopsis: insert entry into cache
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CTVOCache::InsertCacheEntry (PTVO_CACHE_ENTRY pEntry)
|
|
{
|
|
I_CryptInsertLruEntry( pEntry->hLruEntry, NULL );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOCache::RemoveCacheEntry, public
|
|
//
|
|
// Synopsis: remove entry from cache
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CTVOCache::RemoveCacheEntry (PTVO_CACHE_ENTRY pEntry, BOOL fSuppressFree)
|
|
{
|
|
DWORD dwFlags = 0;
|
|
|
|
if ( fSuppressFree == TRUE )
|
|
{
|
|
dwFlags = LRU_SUPPRESS_REMOVAL_NOTIFICATION;
|
|
}
|
|
|
|
I_CryptRemoveLruEntry( pEntry->hLruEntry, dwFlags, NULL );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOCache::TouchCacheEntry, public
|
|
//
|
|
// Synopsis: touch an entry
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CTVOCache::TouchCacheEntry (PTVO_CACHE_ENTRY pEntry)
|
|
{
|
|
I_CryptTouchLruEntry( pEntry->hLruEntry, 0 );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOCache::FindCacheEntry, public
|
|
//
|
|
// Synopsis: find an entry in the cache given the origin identifier.
|
|
// Skip entries that aren't valid for the subject.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
PTVO_CACHE_ENTRY
|
|
CTVOCache::FindCacheEntry (
|
|
CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
|
|
LPCSTR pszContextOid,
|
|
LPVOID pvSubject
|
|
)
|
|
{
|
|
HLRUENTRY hEntry;
|
|
CRYPT_DATA_BLOB DataBlob;
|
|
PTVO_CACHE_ENTRY pEntry = NULL;
|
|
|
|
DataBlob.cbData = MD5DIGESTLEN;
|
|
DataBlob.pbData = OriginIdentifier;
|
|
|
|
hEntry = I_CryptFindLruEntry( m_hCache, &DataBlob );
|
|
while ( hEntry != NULL )
|
|
{
|
|
pEntry = (PTVO_CACHE_ENTRY)I_CryptGetLruEntryData( hEntry );
|
|
assert(pEntry);
|
|
assert(pszContextOid == pEntry->pszContextOid);
|
|
if (pszContextOid == pEntry->pszContextOid &&
|
|
ObjectContextIsValidForSubject (
|
|
pszContextOid,
|
|
pEntry->pvContext,
|
|
pvSubject,
|
|
NULL // pvExtraInfo
|
|
))
|
|
{
|
|
I_CryptReleaseLruEntry( hEntry );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pEntry = NULL;
|
|
hEntry = I_CryptEnumMatchingLruEntries ( hEntry );
|
|
}
|
|
}
|
|
|
|
return( pEntry );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOCache::RemoveAllCacheEntries, public
|
|
//
|
|
// Synopsis: remove all cache entries
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CTVOCache::RemoveAllCacheEntries ()
|
|
{
|
|
I_CryptFlushLruCache( m_hCache, 0, NULL );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TVOCacheHashOriginIdentifier
|
|
//
|
|
// Synopsis: hash the origin identifier to a DWORD, since the origin
|
|
// identifier is already a unique MD5 hash our algorithm is
|
|
// to simply use some of the bytes
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD WINAPI
|
|
TVOCacheHashOriginIdentifier (PCRYPT_DATA_BLOB pIdentifier)
|
|
{
|
|
DWORD Hash;
|
|
|
|
assert( pIdentifier->cbData == MD5DIGESTLEN );
|
|
|
|
memcpy( &Hash, pIdentifier->pbData, sizeof( DWORD ) );
|
|
|
|
return( Hash );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TVOCacheOnRemoval
|
|
//
|
|
// Synopsis: removal notification callback
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID WINAPI
|
|
TVOCacheOnRemoval (LPVOID pvData, LPVOID pvRemovalContext)
|
|
{
|
|
ObjectContextFreeTVOCacheEntry( (PTVO_CACHE_ENTRY)pvData );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOAgent::CTVOAgent, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTVOAgent::CTVOAgent (
|
|
DWORD cCacheBuckets,
|
|
DWORD MaxCacheEntries,
|
|
BOOL& rfResult
|
|
)
|
|
: m_Cache( cCacheBuckets, MaxCacheEntries, rfResult )
|
|
{
|
|
if (!Pki_InitializeCriticalSection( &m_Lock ))
|
|
{
|
|
rfResult = FALSE;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOAgent::~CTVOAgent, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTVOAgent::~CTVOAgent ()
|
|
{
|
|
m_Cache.RemoveAllCacheEntries();
|
|
|
|
DeleteCriticalSection( &m_Lock );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOAgent::GetTimeValidObject, public
|
|
//
|
|
// Synopsis: get a time valid CAPI2 object
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CTVOAgent::GetTimeValidObject (
|
|
IN LPCSTR pszTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN LPCSTR pszContextOid,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
CRYPT_ORIGIN_IDENTIFIER OriginIdentifier;
|
|
PTVO_CACHE_ENTRY pCacheEntry = NULL;
|
|
DWORD PreferredUrlIndex = 0;
|
|
PCRYPT_URL_ARRAY pUrlArray = NULL;
|
|
DWORD cb = 0;
|
|
DWORD cbUrlArray = 0;
|
|
PCRYPT_URL_ARRAY pCacheUrlArray = NULL;
|
|
LPWSTR pwszUrlHint = NULL;
|
|
BOOL fHintInArray = FALSE;
|
|
BOOL fArrayOwned = FALSE;
|
|
|
|
BOOL fCrlFromCert = FALSE;
|
|
LPCSTR pszUrlOidCrlFromCert = NULL;
|
|
LPVOID pvSubject = NULL;
|
|
BOOL fFreshest = FALSE;
|
|
|
|
if ( pszTimeValidOid == TIME_VALID_OID_GET_CRL_FROM_CERT )
|
|
{
|
|
fCrlFromCert = TRUE;
|
|
pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_CRL_DIST_POINT;
|
|
pvSubject = pvPara;
|
|
}
|
|
else if ( pszTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CERT )
|
|
{
|
|
fCrlFromCert = TRUE;
|
|
pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_FRESHEST_CRL;
|
|
pvSubject = pvPara;
|
|
fFreshest = TRUE;
|
|
}
|
|
else if ( pszTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CRL )
|
|
{
|
|
fCrlFromCert = TRUE;
|
|
pszUrlOidCrlFromCert = URL_OID_CRL_FRESHEST_CRL;
|
|
pvSubject = (LPVOID) ((PCCERT_CRL_CONTEXT_PAIR)pvPara)->pCertContext;
|
|
fFreshest = TRUE;
|
|
}
|
|
|
|
if (fCrlFromCert)
|
|
{
|
|
if ( CrlGetOriginIdentifierFromSubjectCert(
|
|
(PCCERT_CONTEXT)pvSubject,
|
|
pIssuer,
|
|
fFreshest,
|
|
OriginIdentifier
|
|
) == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
assert( pszContextOid == CONTEXT_OID_CRL );
|
|
}
|
|
else
|
|
{
|
|
if ( ObjectContextGetOriginIdentifier(
|
|
pszContextOid,
|
|
pvPara,
|
|
pIssuer,
|
|
0,
|
|
OriginIdentifier
|
|
) == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
PreferredUrlIndex = 0;
|
|
pUrlArray = NULL;
|
|
|
|
EnterCriticalSection( &m_Lock );
|
|
|
|
pCacheEntry = m_Cache.FindCacheEntry(
|
|
OriginIdentifier,
|
|
pszContextOid,
|
|
pvSubject
|
|
);
|
|
|
|
if ( pCacheEntry != NULL )
|
|
{
|
|
if ( !( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL ) )
|
|
{
|
|
if ( ( dwFlags & CRYPT_DONT_CHECK_TIME_VALIDITY ) ||
|
|
IsValidCreateOrExpireTime (
|
|
0 != (dwFlags & CRYPT_CHECK_FRESHNESS_TIME_VALIDITY),
|
|
pftValidFor,
|
|
&pCacheEntry->CreateTime,
|
|
&pCacheEntry->ExpireTime ) )
|
|
{
|
|
m_Cache.TouchCacheEntry( pCacheEntry );
|
|
|
|
if ( ppvObject != NULL )
|
|
{
|
|
*ppvObject = ObjectContextDuplicate(
|
|
pCacheEntry->pszContextOid,
|
|
pCacheEntry->pvContext
|
|
);
|
|
}
|
|
|
|
LeaveCriticalSection( &m_Lock );
|
|
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
if ( !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
|
|
{
|
|
if ( GetOfflineUrlTimeStatus(&pCacheEntry->OfflineUrlTimeInfo) < 0
|
|
||
|
|
!I_CryptNetIsConnected() )
|
|
{
|
|
if ( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL )
|
|
{
|
|
LeaveCriticalSection( &m_Lock );
|
|
SetLastError( (DWORD) ERROR_NOT_CONNECTED );
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
dwFlags |= CRYPT_CACHE_ONLY_RETRIEVAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pCacheEntry->pUrlArrayNext != NULL )
|
|
{
|
|
cbUrlArray = pCacheEntry->cbUrlArrayNext;
|
|
pCacheUrlArray = pCacheEntry->pUrlArrayNext;
|
|
PreferredUrlIndex = pCacheEntry->UrlIndexNext;
|
|
}
|
|
else
|
|
{
|
|
cbUrlArray = pCacheEntry->cbUrlArrayThis;
|
|
pCacheUrlArray = pCacheEntry->pUrlArrayThis;
|
|
PreferredUrlIndex = pCacheEntry->UrlIndexThis;
|
|
}
|
|
}
|
|
else if ( !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
|
|
{
|
|
if ( !I_CryptNetIsConnected() )
|
|
{
|
|
if ( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL )
|
|
{
|
|
LeaveCriticalSection( &m_Lock );
|
|
SetLastError( (DWORD) ERROR_NOT_CONNECTED );
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
dwFlags |= CRYPT_CACHE_ONLY_RETRIEVAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ( fResult == TRUE ) && ( pUrlArray == NULL ) )
|
|
{
|
|
if ( pCacheEntry != NULL )
|
|
{
|
|
pwszUrlHint = pCacheUrlArray->rgwszUrl[ PreferredUrlIndex ];
|
|
}
|
|
|
|
if ( fCrlFromCert )
|
|
{
|
|
fResult = CertificateGetCrlDistPointUrl(
|
|
pszUrlOidCrlFromCert,
|
|
pvPara,
|
|
pwszUrlHint,
|
|
&pUrlArray,
|
|
&cb,
|
|
&PreferredUrlIndex,
|
|
&fHintInArray
|
|
);
|
|
}
|
|
else if ( pszTimeValidOid == TIME_VALID_OID_GET_CTL )
|
|
{
|
|
fResult = ObjectContextGetNextUpdateUrl(
|
|
pszContextOid,
|
|
pvPara,
|
|
pIssuer,
|
|
pwszUrlHint,
|
|
&pUrlArray,
|
|
&cb,
|
|
&PreferredUrlIndex,
|
|
&fHintInArray
|
|
);
|
|
}
|
|
else
|
|
{
|
|
SetLastError( (DWORD) CRYPT_E_NOT_FOUND );
|
|
fResult = FALSE;
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
cbUrlArray = cb;
|
|
}
|
|
else if ( pCacheEntry != NULL )
|
|
{
|
|
pUrlArray = (PCRYPT_URL_ARRAY)new BYTE [ cbUrlArray ];
|
|
if ( pUrlArray != NULL )
|
|
{
|
|
if (CopyUrlArray( pUrlArray, pCacheUrlArray, cbUrlArray ))
|
|
{
|
|
fHintInArray = TRUE;
|
|
fResult = TRUE;
|
|
}
|
|
else
|
|
{
|
|
delete [] (BYTE *) pUrlArray;
|
|
pUrlArray = NULL;
|
|
SetLastError( (DWORD) E_INVALIDARG );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError( (DWORD) E_OUTOFMEMORY );
|
|
}
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection( &m_Lock );
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
fResult = GetTimeValidObjectByUrl(
|
|
cbUrlArray,
|
|
pUrlArray,
|
|
PreferredUrlIndex,
|
|
pszContextOid,
|
|
pIssuer,
|
|
pvSubject,
|
|
OriginIdentifier,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
ppvObject,
|
|
pCredentials,
|
|
NULL,
|
|
&fArrayOwned,
|
|
pvReserved
|
|
);
|
|
}
|
|
|
|
if ( fArrayOwned == FALSE )
|
|
{
|
|
delete [] (BYTE *) pUrlArray;
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOAgent::GetTimeValidObjectByUrl, public
|
|
//
|
|
// Synopsis: get a time valid object using URL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CTVOAgent::GetTimeValidObjectByUrl (
|
|
IN DWORD cbUrlArray,
|
|
IN PCRYPT_URL_ARRAY pUrlArray,
|
|
IN DWORD PreferredUrlIndex,
|
|
IN LPCSTR pszContextOid,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN LPVOID pvSubject,
|
|
IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT OPTIONAL LPVOID* ppvObject,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPWSTR pwszUrlExtra,
|
|
OUT BOOL* pfArrayOwned,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
DWORD cCount;
|
|
LPWSTR pwsz;
|
|
LPVOID pvContext = NULL;
|
|
PTVO_CACHE_ENTRY pEntry = NULL;
|
|
PTVO_CACHE_ENTRY pFound;
|
|
DWORD LastError;
|
|
|
|
// Following is only used for CRYPT_ACCUMULATIVE_TIMEOUT
|
|
FILETIME ftEndUrlRetrieval;
|
|
|
|
if ( PreferredUrlIndex != 0 )
|
|
{
|
|
pwsz = pUrlArray->rgwszUrl[PreferredUrlIndex];
|
|
pUrlArray->rgwszUrl[PreferredUrlIndex] = pUrlArray->rgwszUrl[0];
|
|
pUrlArray->rgwszUrl[0] = pwsz;
|
|
}
|
|
|
|
if (dwFlags & CRYPT_ACCUMULATIVE_TIMEOUT)
|
|
{
|
|
if (0 == dwTimeout)
|
|
{
|
|
dwFlags &= ~CRYPT_ACCUMULATIVE_TIMEOUT;
|
|
}
|
|
else
|
|
{
|
|
FILETIME ftStartUrlRetrieval;
|
|
|
|
GetSystemTimeAsFileTime(&ftStartUrlRetrieval);
|
|
I_CryptIncrementFileTimeByMilliseconds(
|
|
&ftStartUrlRetrieval, dwTimeout,
|
|
&ftEndUrlRetrieval);
|
|
}
|
|
}
|
|
|
|
for ( cCount = 0; cCount < pUrlArray->cUrl; cCount++ )
|
|
{
|
|
if (dwFlags & CRYPT_ACCUMULATIVE_TIMEOUT)
|
|
{
|
|
// Limit each URL timeout to half of the remaining time
|
|
dwTimeout = I_CryptRemainingMilliseconds(&ftEndUrlRetrieval) / 2;
|
|
if (0 == dwTimeout)
|
|
{
|
|
dwTimeout = 1;
|
|
}
|
|
}
|
|
|
|
fResult = RetrieveTimeValidObjectByUrl(
|
|
pUrlArray->rgwszUrl[cCount],
|
|
pszContextOid,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
pCredentials,
|
|
pIssuer,
|
|
pvSubject,
|
|
OriginIdentifier,
|
|
&pvContext,
|
|
pvReserved
|
|
);
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
fResult = ObjectContextCreateTVOCacheEntry(
|
|
m_Cache.LruCacheHandle(),
|
|
pszContextOid,
|
|
pvContext,
|
|
OriginIdentifier,
|
|
cbUrlArray,
|
|
pUrlArray,
|
|
cCount,
|
|
pIssuer,
|
|
&pEntry
|
|
);
|
|
|
|
*pfArrayOwned = fResult;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ( PreferredUrlIndex != 0 ) && ( *pfArrayOwned == FALSE ) )
|
|
{
|
|
pwsz = pUrlArray->rgwszUrl[PreferredUrlIndex];
|
|
pUrlArray->rgwszUrl[PreferredUrlIndex] = pUrlArray->rgwszUrl[0];
|
|
pUrlArray->rgwszUrl[0] = pwsz;
|
|
}
|
|
|
|
if ( ( fResult == FALSE ) && ( pwszUrlExtra != NULL ) )
|
|
{
|
|
if (dwFlags & CRYPT_ACCUMULATIVE_TIMEOUT)
|
|
{
|
|
// Limit each URL timeout to half of the remaining time
|
|
dwTimeout = I_CryptRemainingMilliseconds(&ftEndUrlRetrieval) / 2;
|
|
if (0 == dwTimeout)
|
|
{
|
|
dwTimeout = 1;
|
|
}
|
|
}
|
|
|
|
fResult = RetrieveTimeValidObjectByUrl(
|
|
pwszUrlExtra,
|
|
pszContextOid,
|
|
pftValidFor,
|
|
dwFlags,
|
|
dwTimeout,
|
|
pCredentials,
|
|
pIssuer,
|
|
pvSubject,
|
|
OriginIdentifier,
|
|
&pvContext,
|
|
pvReserved
|
|
);
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
CCryptUrlArray cua( pUrlArray->cUrl + 1, 5, fResult );
|
|
DWORD cb = 0;
|
|
PCRYPT_URL_ARRAY pcua = NULL;
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
for ( cCount = 0; cCount < pUrlArray->cUrl; cCount++ )
|
|
{
|
|
fResult = cua.AddUrl( pUrlArray->rgwszUrl[cCount], FALSE );
|
|
if ( fResult == FALSE )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
fResult = cua.GetArrayInSingleBufferEncodedForm(
|
|
&pcua,
|
|
&cb
|
|
);
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
fResult = ObjectContextCreateTVOCacheEntry(
|
|
m_Cache.LruCacheHandle(),
|
|
pszContextOid,
|
|
pvContext,
|
|
OriginIdentifier,
|
|
cb,
|
|
pcua,
|
|
pUrlArray->cUrl,
|
|
pIssuer,
|
|
&pEntry
|
|
);
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
CryptMemFree( pcua );
|
|
}
|
|
}
|
|
|
|
cua.FreeArray( FALSE );
|
|
}
|
|
}
|
|
|
|
LastError = GetLastError();
|
|
|
|
EnterCriticalSection( &m_Lock );
|
|
|
|
pFound = m_Cache.FindCacheEntry(
|
|
OriginIdentifier,
|
|
pszContextOid,
|
|
pvSubject
|
|
);
|
|
|
|
if ( !fResult && pFound && !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
|
|
{
|
|
SetOfflineUrlTime( &pFound->OfflineUrlTimeInfo );
|
|
}
|
|
|
|
if ( ( fResult == TRUE ) && !( dwFlags & CRYPT_DONT_VERIFY_SIGNATURE ) )
|
|
{
|
|
if ( ( pFound != NULL ) &&
|
|
( CompareFileTime(
|
|
&pFound->CreateTime,
|
|
&pEntry->CreateTime
|
|
) >= 0 ) )
|
|
{
|
|
ObjectContextFree( pszContextOid, pvContext );
|
|
|
|
pvContext = ObjectContextDuplicate(
|
|
pFound->pszContextOid,
|
|
pFound->pvContext
|
|
);
|
|
|
|
SetOnlineUrlTime( &pFound->OfflineUrlTimeInfo );
|
|
|
|
ObjectContextFreeTVOCacheEntry( pEntry );
|
|
}
|
|
else
|
|
{
|
|
if ( pFound != NULL )
|
|
{
|
|
m_Cache.RemoveCacheEntry( pFound );
|
|
}
|
|
|
|
m_Cache.InsertCacheEntry( pEntry );
|
|
}
|
|
|
|
}
|
|
else if ( pEntry != NULL )
|
|
{
|
|
ObjectContextFreeTVOCacheEntry( pEntry );
|
|
}
|
|
|
|
LeaveCriticalSection( &m_Lock );
|
|
|
|
if ( pvContext != NULL )
|
|
{
|
|
if ( ( ppvObject != NULL ) && ( fResult == TRUE ) )
|
|
{
|
|
*ppvObject = pvContext;
|
|
}
|
|
else
|
|
{
|
|
ObjectContextFree( pszContextOid, pvContext );
|
|
}
|
|
}
|
|
|
|
SetLastError( LastError );
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CTVOAgent::FlushTimeValidObject, public
|
|
//
|
|
// Synopsis: flush time valid object
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CTVOAgent::FlushTimeValidObject (
|
|
IN LPCSTR pszFlushTimeValidOid,
|
|
IN LPVOID pvPara,
|
|
IN LPCSTR pszFlushContextOid,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pvReserved
|
|
)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
CRYPT_ORIGIN_IDENTIFIER OriginIdentifier;
|
|
PTVO_CACHE_ENTRY pCacheEntry = NULL;
|
|
PCRYPT_URL_ARRAY pUrlArray = NULL;
|
|
DWORD cbUrlArray;
|
|
DWORD dwError = 0;
|
|
DWORD cCount;
|
|
|
|
BOOL fCrlFromCert = FALSE;
|
|
LPCSTR pszUrlOidCrlFromCert = NULL;
|
|
LPVOID pvSubject = NULL;
|
|
BOOL fFreshest = FALSE;
|
|
|
|
if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_CRL_FROM_CERT )
|
|
{
|
|
fCrlFromCert = TRUE;
|
|
pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_CRL_DIST_POINT;
|
|
pvSubject = pvPara;
|
|
}
|
|
else if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CERT )
|
|
{
|
|
fCrlFromCert = TRUE;
|
|
pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_FRESHEST_CRL;
|
|
pvSubject = pvPara;
|
|
fFreshest = TRUE;
|
|
}
|
|
else if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CRL )
|
|
{
|
|
fCrlFromCert = TRUE;
|
|
pszUrlOidCrlFromCert = URL_OID_CRL_FRESHEST_CRL;
|
|
pvSubject = (LPVOID) ((PCCERT_CRL_CONTEXT_PAIR)pvPara)->pCertContext;
|
|
fFreshest = TRUE;
|
|
}
|
|
|
|
if (fCrlFromCert)
|
|
{
|
|
if ( CrlGetOriginIdentifierFromSubjectCert(
|
|
(PCCERT_CONTEXT)pvSubject,
|
|
pIssuer,
|
|
fFreshest,
|
|
OriginIdentifier
|
|
) == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
assert( pszFlushContextOid == CONTEXT_OID_CRL );
|
|
}
|
|
else
|
|
{
|
|
if ( ObjectContextGetOriginIdentifier(
|
|
pszFlushContextOid,
|
|
pvPara,
|
|
pIssuer,
|
|
0,
|
|
OriginIdentifier
|
|
) == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
EnterCriticalSection( &m_Lock );
|
|
|
|
pCacheEntry = m_Cache.FindCacheEntry(
|
|
OriginIdentifier,
|
|
pszFlushContextOid,
|
|
pvSubject
|
|
);
|
|
|
|
if ( pCacheEntry != NULL )
|
|
{
|
|
// Remove the entry but suppress the freeing of it since we are going
|
|
// to use the data structure later
|
|
m_Cache.RemoveCacheEntry( pCacheEntry, TRUE );
|
|
}
|
|
|
|
LeaveCriticalSection( &m_Lock );
|
|
|
|
if ( pCacheEntry != NULL )
|
|
{
|
|
if ( pCacheEntry->pUrlArrayThis != NULL )
|
|
{
|
|
for ( cCount = 0;
|
|
cCount < pCacheEntry->pUrlArrayThis->cUrl;
|
|
cCount++ )
|
|
{
|
|
if ( ( SchemeDeleteUrlCacheEntry(
|
|
pCacheEntry->pUrlArrayThis->rgwszUrl[cCount]
|
|
) == FALSE ) &&
|
|
( GetLastError() != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pCacheEntry->pUrlArrayNext != NULL )
|
|
{
|
|
for ( cCount = 0;
|
|
cCount < pCacheEntry->pUrlArrayNext->cUrl;
|
|
cCount++ )
|
|
{
|
|
if ( ( SchemeDeleteUrlCacheEntry(
|
|
pCacheEntry->pUrlArrayNext->rgwszUrl[cCount]
|
|
) == FALSE ) &&
|
|
( GetLastError() != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Can place optimization here where if the hashes of the
|
|
// cache object and the passed in object are the same,
|
|
// we don't need to do any more work
|
|
//
|
|
|
|
ObjectContextFreeTVOCacheEntry( pCacheEntry );
|
|
}
|
|
|
|
if ( fCrlFromCert )
|
|
{
|
|
fResult = CertificateGetCrlDistPointUrl(
|
|
pszUrlOidCrlFromCert,
|
|
pvPara,
|
|
NULL, // pwszUrlHint
|
|
&pUrlArray,
|
|
&cbUrlArray,
|
|
NULL, // pPreferredUrlIndex
|
|
NULL // pfHintInArray
|
|
);
|
|
}
|
|
else if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_CTL )
|
|
{
|
|
fResult = ObjectContextGetNextUpdateUrl(
|
|
pszFlushContextOid,
|
|
pvPara,
|
|
pIssuer,
|
|
NULL,
|
|
&pUrlArray,
|
|
&cbUrlArray,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if ( ( fResult == TRUE ) && ( pUrlArray != NULL ) )
|
|
{
|
|
for ( cCount = 0; cCount < pUrlArray->cUrl; cCount++ )
|
|
{
|
|
if ( ( SchemeDeleteUrlCacheEntry(
|
|
pUrlArray->rgwszUrl[cCount]
|
|
) == FALSE ) &&
|
|
( GetLastError() != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pUrlArray )
|
|
{
|
|
delete [] (BYTE *) pUrlArray;
|
|
}
|
|
|
|
if ( ( fResult == TRUE ) && ( dwError != 0 ) )
|
|
{
|
|
SetLastError( dwError );
|
|
fResult = FALSE;
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IsValidCreateOrExpireTime
|
|
//
|
|
// Synopsis: for fCheckFreshnessTime, checks if the
|
|
// specified time is before or the same as the create time.
|
|
// Otherwise, checks if the specified time is before or the
|
|
// same as the expire time. A zero expire time matches any time.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
IsValidCreateOrExpireTime (
|
|
IN BOOL fCheckFreshnessTime,
|
|
IN LPFILETIME pftValidFor,
|
|
IN LPFILETIME pftCreateTime,
|
|
IN LPFILETIME pftExpireTime
|
|
)
|
|
{
|
|
if (fCheckFreshnessTime) {
|
|
if (CompareFileTime(pftValidFor, pftCreateTime) <= 0)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
} else {
|
|
if (CompareFileTime(pftValidFor, pftExpireTime) <= 0 ||
|
|
I_CryptIsZeroFileTime(pftExpireTime))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ObjectContextCreateTVOCacheEntry
|
|
//
|
|
// Synopsis: create a TVO cache entry
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
ObjectContextCreateTVOCacheEntry (
|
|
IN HLRUCACHE hCache,
|
|
IN LPCSTR pszContextOid,
|
|
IN LPVOID pvContext,
|
|
IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
|
|
IN DWORD cbUrlArrayThis,
|
|
IN PCRYPT_URL_ARRAY pUrlArrayThis,
|
|
IN DWORD UrlIndexThis,
|
|
IN PCCERT_CONTEXT pIssuer,
|
|
OUT PTVO_CACHE_ENTRY* ppEntry
|
|
)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
PTVO_CACHE_ENTRY pEntry;
|
|
CRYPT_DATA_BLOB DataBlob;
|
|
|
|
pEntry = new TVO_CACHE_ENTRY;
|
|
if ( pEntry == NULL )
|
|
{
|
|
SetLastError( (DWORD) E_OUTOFMEMORY );
|
|
return( FALSE );
|
|
}
|
|
|
|
memset( pEntry, 0, sizeof( TVO_CACHE_ENTRY ) );
|
|
|
|
// NOTENOTE: This presumes a predefined context oid constant
|
|
pEntry->pszContextOid = pszContextOid;
|
|
pEntry->pvContext = ObjectContextDuplicate( pszContextOid, pvContext );
|
|
memcpy(pEntry->OriginIdentifier, OriginIdentifier,
|
|
sizeof(pEntry->OriginIdentifier));
|
|
|
|
DataBlob.cbData = MD5DIGESTLEN;
|
|
DataBlob.pbData = pEntry->OriginIdentifier;
|
|
|
|
fResult = I_CryptCreateLruEntry(
|
|
hCache,
|
|
&DataBlob,
|
|
pEntry,
|
|
&pEntry->hLruEntry
|
|
);
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
ObjectContextGetNextUpdateUrl(
|
|
pszContextOid,
|
|
pvContext,
|
|
pIssuer,
|
|
pUrlArrayThis->rgwszUrl[UrlIndexThis],
|
|
&pEntry->pUrlArrayNext,
|
|
&pEntry->cbUrlArrayNext,
|
|
&pEntry->UrlIndexNext,
|
|
NULL
|
|
);
|
|
|
|
fResult = ObjectContextGetCreateAndExpireTimes(
|
|
pszContextOid,
|
|
pvContext,
|
|
&pEntry->CreateTime,
|
|
&pEntry->ExpireTime
|
|
);
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
pEntry->cbUrlArrayThis = cbUrlArrayThis;
|
|
pEntry->pUrlArrayThis = pUrlArrayThis;
|
|
pEntry->UrlIndexThis = UrlIndexThis;
|
|
|
|
*ppEntry = pEntry;
|
|
}
|
|
else
|
|
{
|
|
ObjectContextFreeTVOCacheEntry( pEntry );
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ObjectContextFreeTVOCacheEntry
|
|
//
|
|
// Synopsis: free TVO cache entry
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID WINAPI
|
|
ObjectContextFreeTVOCacheEntry (
|
|
IN PTVO_CACHE_ENTRY pEntry
|
|
)
|
|
{
|
|
if ( pEntry->hLruEntry != NULL )
|
|
{
|
|
I_CryptReleaseLruEntry( pEntry->hLruEntry );
|
|
}
|
|
|
|
delete [] (BYTE *) pEntry->pUrlArrayThis;
|
|
delete [] (BYTE *) pEntry->pUrlArrayNext;
|
|
|
|
if ( pEntry->pvContext != NULL )
|
|
{
|
|
ObjectContextFree( pEntry->pszContextOid, pEntry->pvContext );
|
|
}
|
|
|
|
delete pEntry;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CertificateGetCrlDistPointUrl
|
|
//
|
|
// Synopsis: get crl dist point URL from certificate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CertificateGetCrlDistPointUrl (
|
|
IN LPCSTR pszUrlOid,
|
|
IN LPVOID pvPara,
|
|
IN LPWSTR pwszUrlHint,
|
|
OUT PCRYPT_URL_ARRAY* ppUrlArray,
|
|
OUT DWORD* pcbUrlArray,
|
|
OUT DWORD* pPreferredUrlIndex,
|
|
OUT BOOL* pfHintInArray
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
DWORD cbUrlArray;
|
|
PCRYPT_URL_ARRAY pUrlArray = NULL;
|
|
DWORD PreferredUrlIndex;
|
|
|
|
fResult = CryptGetObjectUrl(
|
|
pszUrlOid,
|
|
pvPara,
|
|
0,
|
|
NULL,
|
|
&cbUrlArray,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
pUrlArray = (PCRYPT_URL_ARRAY)new BYTE [ cbUrlArray ];
|
|
if ( pUrlArray != NULL )
|
|
{
|
|
fResult = CryptGetObjectUrl(
|
|
pszUrlOid,
|
|
pvPara,
|
|
0,
|
|
pUrlArray,
|
|
&cbUrlArray,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
else
|
|
{
|
|
SetLastError( (DWORD) E_OUTOFMEMORY );
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
BOOL fHintInArray = FALSE;
|
|
|
|
GetUrlArrayIndex(
|
|
pUrlArray,
|
|
pwszUrlHint,
|
|
0,
|
|
&PreferredUrlIndex,
|
|
&fHintInArray
|
|
);
|
|
|
|
*ppUrlArray = pUrlArray;
|
|
*pcbUrlArray = cbUrlArray;
|
|
|
|
if ( pfHintInArray != NULL )
|
|
{
|
|
*pfHintInArray = fHintInArray;
|
|
}
|
|
|
|
if ( pPreferredUrlIndex != NULL )
|
|
{
|
|
*pPreferredUrlIndex = PreferredUrlIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pUrlArray )
|
|
{
|
|
delete [] (BYTE *) pUrlArray;
|
|
}
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
BOOL WINAPI
|
|
RetrieveObjectByUrlValidForSubject(
|
|
IN LPWSTR pwszUrl,
|
|
IN LPCSTR pszContextOid,
|
|
IN BOOL fCheckFreshnessTime,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwRetrievalFlags,
|
|
IN DWORD dwTimeout,
|
|
IN PCRYPT_CREDENTIALS pCredentials,
|
|
IN PCCERT_CONTEXT pSigner,
|
|
IN LPVOID pvSubject,
|
|
IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
|
|
OUT LPVOID* ppvObject,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
HCERTSTORE hUrlStore = NULL;
|
|
LPVOID pvObject;
|
|
|
|
fResult = CryptRetrieveObjectByUrlW(
|
|
pwszUrl,
|
|
pszContextOid,
|
|
(dwRetrievalFlags |
|
|
CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
|
|
CRYPT_LDAP_SCOPE_BASE_ONLY_RETRIEVAL) &
|
|
~CRYPT_VERIFY_CONTEXT_SIGNATURE,
|
|
dwTimeout,
|
|
(LPVOID *) &hUrlStore,
|
|
NULL, // hAsyncRetrieve
|
|
NULL, // pCredentials
|
|
NULL, // pSigner
|
|
NULL // pvReserved
|
|
);
|
|
|
|
if (!fResult)
|
|
goto CommonReturn;
|
|
|
|
pvObject = NULL;
|
|
while (pvObject = ObjectContextEnumObjectsInStore (
|
|
hUrlStore,
|
|
pszContextOid,
|
|
pvObject
|
|
))
|
|
{
|
|
CRYPT_ORIGIN_IDENTIFIER ObjectOriginIdentifier;
|
|
|
|
if (!ObjectContextGetOriginIdentifier(
|
|
pszContextOid,
|
|
pvObject,
|
|
pSigner,
|
|
0,
|
|
ObjectOriginIdentifier
|
|
))
|
|
continue;
|
|
|
|
if (0 != memcmp(OriginIdentifier, ObjectOriginIdentifier,
|
|
sizeof(ObjectOriginIdentifier)))
|
|
continue;
|
|
|
|
if (dwRetrievalFlags & CRYPT_VERIFY_CONTEXT_SIGNATURE) {
|
|
if (!ObjectContextVerifySignature (
|
|
pszContextOid,
|
|
pvObject,
|
|
pSigner
|
|
))
|
|
continue;
|
|
}
|
|
|
|
if (!ObjectContextIsValidForSubject (
|
|
pszContextOid,
|
|
pvObject,
|
|
pvSubject,
|
|
pvReserved
|
|
))
|
|
continue;
|
|
|
|
if (NULL != pftValidFor) {
|
|
FILETIME CreateTime;
|
|
FILETIME ExpireTime;
|
|
|
|
if (!ObjectContextGetCreateAndExpireTimes(
|
|
pszContextOid,
|
|
pvObject,
|
|
&CreateTime,
|
|
&ExpireTime
|
|
))
|
|
continue;
|
|
|
|
if (!IsValidCreateOrExpireTime (
|
|
fCheckFreshnessTime,
|
|
pftValidFor,
|
|
&CreateTime,
|
|
&ExpireTime ) )
|
|
continue;
|
|
}
|
|
|
|
*ppvObject = pvObject;
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
// Make sure the error isn't CRYPT_E_NOT_FOUND. msrevoke will
|
|
// return CRYPT_E_NO_REVOCATION_CHECK instead of
|
|
// CRYPT_E_REVOCATION_OFFLINE for CRYPT_E_NOT_FOUND.
|
|
SetLastError(ERROR_FILE_NOT_FOUND);
|
|
fResult = FALSE;
|
|
|
|
CommonReturn:
|
|
if (hUrlStore)
|
|
CertCloseStore(hUrlStore, 0);
|
|
return fResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RetrieveTimeValidObjectByUrl
|
|
//
|
|
// Synopsis: retrieve a time valid object given an URL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
RetrieveTimeValidObjectByUrl (
|
|
IN LPWSTR pwszUrl,
|
|
IN LPCSTR pszContextOid,
|
|
IN LPFILETIME pftValidFor,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwTimeout,
|
|
IN PCRYPT_CREDENTIALS pCredentials,
|
|
IN PCCERT_CONTEXT pSigner,
|
|
IN LPVOID pvSubject,
|
|
IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
|
|
OUT LPVOID* ppvObject,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
LPVOID pvContext = NULL;
|
|
DWORD dwVerifyFlags = 0;
|
|
DWORD dwCacheStoreFlags = CRYPT_DONT_CACHE_RESULT;
|
|
|
|
if ( dwFlags & CRYPT_DONT_CHECK_TIME_VALIDITY )
|
|
{
|
|
pftValidFor = NULL;
|
|
}
|
|
|
|
if ( !( dwFlags & CRYPT_DONT_VERIFY_SIGNATURE ) )
|
|
{
|
|
dwVerifyFlags |= CRYPT_VERIFY_CONTEXT_SIGNATURE;
|
|
dwCacheStoreFlags &= ~CRYPT_DONT_CACHE_RESULT;
|
|
}
|
|
|
|
if ( !( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL ) )
|
|
{
|
|
fResult = RetrieveObjectByUrlValidForSubject(
|
|
pwszUrl,
|
|
pszContextOid,
|
|
0 != (dwFlags & CRYPT_CHECK_FRESHNESS_TIME_VALIDITY),
|
|
pftValidFor,
|
|
CRYPT_CACHE_ONLY_RETRIEVAL |
|
|
dwVerifyFlags,
|
|
0, // dwTimeout
|
|
NULL, // pCredentials
|
|
pSigner,
|
|
pvSubject,
|
|
OriginIdentifier,
|
|
&pvContext,
|
|
pvReserved
|
|
);
|
|
}
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
if ( !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
|
|
{
|
|
DWORD dwRetrievalFlags = CRYPT_WIRE_ONLY_RETRIEVAL |
|
|
dwCacheStoreFlags |
|
|
dwVerifyFlags;
|
|
|
|
LONG lStatus;
|
|
|
|
// +1 - Online
|
|
// 0 - Offline, current time >= earliest online time, hit the wire
|
|
// -1 - Offline, current time < earliest onlime time
|
|
lStatus = GetOriginUrlStatusW(
|
|
OriginIdentifier,
|
|
pwszUrl,
|
|
pszContextOid,
|
|
dwRetrievalFlags
|
|
);
|
|
|
|
if (lStatus >= 0)
|
|
{
|
|
fResult = RetrieveObjectByUrlValidForSubject(
|
|
pwszUrl,
|
|
pszContextOid,
|
|
0 != (dwFlags & CRYPT_CHECK_FRESHNESS_TIME_VALIDITY),
|
|
pftValidFor,
|
|
dwRetrievalFlags,
|
|
dwTimeout,
|
|
pCredentials,
|
|
pSigner,
|
|
pvSubject,
|
|
OriginIdentifier,
|
|
&pvContext,
|
|
pvReserved
|
|
);
|
|
if (!fResult)
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
SetOfflineOriginUrlW(
|
|
OriginIdentifier,
|
|
pwszUrl,
|
|
pszContextOid,
|
|
dwRetrievalFlags
|
|
);
|
|
|
|
SetLastError( dwErr );
|
|
}
|
|
else if (lStatus == 0)
|
|
{
|
|
// Remove from offline list
|
|
SetOnlineOriginUrlW(
|
|
OriginIdentifier,
|
|
pwszUrl,
|
|
pszContextOid,
|
|
dwRetrievalFlags
|
|
);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
*ppvObject = pvContext;
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateProcessTVOAgent
|
|
//
|
|
// Synopsis: create process TVO agent
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI
|
|
CreateProcessTVOAgent (
|
|
OUT CTVOAgent** ppAgent
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hKey = NULL;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwSize = sizeof( DWORD );
|
|
DWORD cCacheBuckets;
|
|
DWORD MaxCacheEntries;
|
|
CTVOAgent* pAgent;
|
|
|
|
if ( RegOpenKeyA(
|
|
HKEY_LOCAL_MACHINE,
|
|
TVO_KEY_NAME,
|
|
&hKey
|
|
) == ERROR_SUCCESS )
|
|
{
|
|
if ( RegQueryValueExA(
|
|
hKey,
|
|
TVO_CACHE_BUCKETS_VALUE_NAME,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&cCacheBuckets,
|
|
&dwSize
|
|
) != ERROR_SUCCESS )
|
|
{
|
|
cCacheBuckets = TVO_DEFAULT_CACHE_BUCKETS;
|
|
}
|
|
|
|
if ( RegQueryValueExA(
|
|
hKey,
|
|
TVO_MAX_CACHE_ENTRIES_VALUE_NAME,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&MaxCacheEntries,
|
|
&dwSize
|
|
) != ERROR_SUCCESS )
|
|
{
|
|
MaxCacheEntries = TVO_DEFAULT_MAX_CACHE_ENTRIES;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
cCacheBuckets = TVO_DEFAULT_CACHE_BUCKETS;
|
|
MaxCacheEntries = TVO_DEFAULT_MAX_CACHE_ENTRIES;
|
|
}
|
|
|
|
pAgent = new CTVOAgent( cCacheBuckets, MaxCacheEntries, fResult );
|
|
if ( pAgent == NULL )
|
|
{
|
|
SetLastError( (DWORD) E_OUTOFMEMORY );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
*ppAgent = pAgent;
|
|
}
|
|
else
|
|
{
|
|
delete pAgent;
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
|