|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows NT Security
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: offurl.cpp
//
// Contents: Offline URL Caching
//
// History: 19-Jan-00 philh Created
// 01-Jan-02 philh Changed to internally use UNICODE Urls
//----------------------------------------------------------------------------
#include <global.hxx>
//
// Offline URL Cache Entry.
//
// The earliest wire retrieval is delayed according to the number of
// offline failures.
//
// For a successful wire URL retrieval, the entry is removed and deleted.
//
// Assumption: the number of offline entries is small, less than 20.
//
typedef struct _OFFLINE_URL_CACHE_ENTRY OFFLINE_URL_CACHE_ENTRY, *POFFLINE_URL_CACHE_ENTRY; struct _OFFLINE_URL_CACHE_ENTRY { CRYPT_DATA_BLOB UrlBlob; CRYPT_DATA_BLOB ExtraBlob; DWORD dwContextOid; OFFLINE_URL_TIME_INFO OfflineUrlTimeInfo; POFFLINE_URL_CACHE_ENTRY pNext; POFFLINE_URL_CACHE_ENTRY pPrev; };
CRITICAL_SECTION OfflineUrlCacheCriticalSection; POFFLINE_URL_CACHE_ENTRY pOfflineUrlCacheHead;
//
// Local Functions (Forward Reference)
//
// Assumption: OfflineUrlCache is locked
POFFLINE_URL_CACHE_ENTRY WINAPI CreateAndAddOfflineUrlCacheEntry( IN PCRYPT_DATA_BLOB pUrlBlob, IN PCRYPT_DATA_BLOB pExtraBlob, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags );
// Assumption: OfflineUrlCache is locked
VOID WINAPI RemoveAndFreeOfflineUrlCacheEntry( IN OUT POFFLINE_URL_CACHE_ENTRY pEntry );
// Assumption: OfflineUrlCache is locked
POFFLINE_URL_CACHE_ENTRY WINAPI FindOfflineUrlCacheEntry( IN PCRYPT_DATA_BLOB pUrlBlob, IN PCRYPT_DATA_BLOB pExtraBlob, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags );
VOID WINAPI InitializeOfflineUrlCache() { Pki_InitializeCriticalSection(&OfflineUrlCacheCriticalSection); }
VOID WINAPI DeleteOfflineUrlCache() { while (pOfflineUrlCacheHead) RemoveAndFreeOfflineUrlCacheEntry(pOfflineUrlCacheHead);
DeleteCriticalSection(&OfflineUrlCacheCriticalSection); }
//
// Return status:
// +1 - Online
// 0 - Offline, current time >= earliest online time, hit the wire
// -1 - Offline, current time < earliest onlime time
//
LONG WINAPI GetOfflineUrlTimeStatus( IN POFFLINE_URL_TIME_INFO pInfo ) { FILETIME CurrentTime;
if (0 == pInfo->dwOfflineCnt) { return 1; }
GetSystemTimeAsFileTime(&CurrentTime); if (0 <= CompareFileTime(&CurrentTime, &pInfo->EarliestOnlineTime)) { return 0; } else { return -1; } }
const DWORD rgdwOfflineUrlDeltaSeconds[] = { 15, // 15 seconds
15, // 15 seconds
60, // 1 minute
60 * 5, // 5 minutes
60 * 10, // 10 minutes
60 * 30, // 30 minutes
};
#define OFFLINE_URL_DELTA_SECONDS_CNT \
(sizeof(rgdwOfflineUrlDeltaSeconds) / \ sizeof(rgdwOfflineUrlDeltaSeconds[0]))
VOID WINAPI SetOfflineUrlTime( IN OUT POFFLINE_URL_TIME_INFO pInfo ) { DWORD dwOfflineCnt; FILETIME CurrentTime;
dwOfflineCnt = ++pInfo->dwOfflineCnt;
if (OFFLINE_URL_DELTA_SECONDS_CNT < dwOfflineCnt) { dwOfflineCnt = OFFLINE_URL_DELTA_SECONDS_CNT; }
GetSystemTimeAsFileTime( &CurrentTime ); I_CryptIncrementFileTimeBySeconds( &CurrentTime, rgdwOfflineUrlDeltaSeconds[dwOfflineCnt - 1], &pInfo->EarliestOnlineTime ); }
VOID WINAPI SetOnlineUrlTime( IN OUT POFFLINE_URL_TIME_INFO pInfo ) { pInfo->dwOfflineCnt = 0; }
//
// Return status:
// +1 - Online
// 0 - Offline, current time >= earliest online time, hit the wire
// -1 - Offline, current time < earliest onlime time
//
LONG WINAPI GetOriginUrlStatusW( IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier, IN LPCWSTR pwszUrl, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { LONG lStatus; POFFLINE_URL_CACHE_ENTRY pEntry; CRYPT_DATA_BLOB UrlBlob; CRYPT_DATA_BLOB ExtraBlob;
UrlBlob.pbData = (BYTE *) pwszUrl; UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR); ExtraBlob.pbData = OriginIdentifier; ExtraBlob.cbData = MD5DIGESTLEN;
EnterCriticalSection(&OfflineUrlCacheCriticalSection);
pEntry = FindOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags ); if (pEntry) lStatus = GetOfflineUrlTimeStatus(&pEntry->OfflineUrlTimeInfo); else lStatus = 1;
LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
return lStatus; }
VOID WINAPI SetOnlineOriginUrlW( IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier, IN LPCWSTR pwszUrl, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { POFFLINE_URL_CACHE_ENTRY pEntry; CRYPT_DATA_BLOB UrlBlob; CRYPT_DATA_BLOB ExtraBlob;
UrlBlob.pbData = (BYTE *) pwszUrl; UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR); ExtraBlob.pbData = OriginIdentifier; ExtraBlob.cbData = MD5DIGESTLEN;
EnterCriticalSection(&OfflineUrlCacheCriticalSection);
pEntry = FindOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags ); if (pEntry) RemoveAndFreeOfflineUrlCacheEntry(pEntry);
LeaveCriticalSection(&OfflineUrlCacheCriticalSection); }
VOID WINAPI SetOfflineOriginUrlW( IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier, IN LPCWSTR pwszUrl, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { POFFLINE_URL_CACHE_ENTRY pEntry; CRYPT_DATA_BLOB UrlBlob; CRYPT_DATA_BLOB ExtraBlob;
UrlBlob.pbData = (BYTE *) pwszUrl; UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR); ExtraBlob.pbData = OriginIdentifier; ExtraBlob.cbData = MD5DIGESTLEN;
EnterCriticalSection(&OfflineUrlCacheCriticalSection);
pEntry = FindOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags );
if (NULL == pEntry) pEntry = CreateAndAddOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags );
if (pEntry) SetOfflineUrlTime(&pEntry->OfflineUrlTimeInfo);
LeaveCriticalSection(&OfflineUrlCacheCriticalSection); }
//
// Return status:
// +1 - Online
// 0 - Offline, current time >= earliest online time, hit the wire
// -1 - Offline, current time < earliest onlime time
//
LONG WINAPI GetUrlStatusW( IN LPCWSTR pwszUrl, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { LONG lStatus; POFFLINE_URL_CACHE_ENTRY pEntry; CRYPT_DATA_BLOB UrlBlob; CRYPT_DATA_BLOB ExtraBlob;
UrlBlob.pbData = (BYTE *) pwszUrl; UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR); ExtraBlob.pbData = NULL; ExtraBlob.cbData = 0;
EnterCriticalSection(&OfflineUrlCacheCriticalSection);
pEntry = FindOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags ); if (pEntry) lStatus = GetOfflineUrlTimeStatus(&pEntry->OfflineUrlTimeInfo); else lStatus = 1;
LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
return lStatus; }
VOID WINAPI SetOnlineUrlW( IN LPCWSTR pwszUrl, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { POFFLINE_URL_CACHE_ENTRY pEntry; CRYPT_DATA_BLOB UrlBlob; CRYPT_DATA_BLOB ExtraBlob;
UrlBlob.pbData = (BYTE *) pwszUrl; UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR); ExtraBlob.pbData = NULL; ExtraBlob.cbData = 0;
EnterCriticalSection(&OfflineUrlCacheCriticalSection);
pEntry = FindOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags ); if (pEntry) RemoveAndFreeOfflineUrlCacheEntry(pEntry);
LeaveCriticalSection(&OfflineUrlCacheCriticalSection); }
VOID WINAPI SetOfflineUrlW( IN LPCWSTR pwszUrl, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { POFFLINE_URL_CACHE_ENTRY pEntry; CRYPT_DATA_BLOB UrlBlob; CRYPT_DATA_BLOB ExtraBlob;
UrlBlob.pbData = (BYTE *) pwszUrl; UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR); ExtraBlob.pbData = NULL; ExtraBlob.cbData = 0;
EnterCriticalSection(&OfflineUrlCacheCriticalSection);
pEntry = FindOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags );
if (NULL == pEntry) pEntry = CreateAndAddOfflineUrlCacheEntry( &UrlBlob, &ExtraBlob, pszContextOid, dwRetrievalFlags );
if (pEntry) SetOfflineUrlTime(&pEntry->OfflineUrlTimeInfo);
LeaveCriticalSection(&OfflineUrlCacheCriticalSection); }
inline DWORD GetOfflineUrlCacheContextOid( IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { DWORD dwContextOid;
if (0xFFFF >= (DWORD) ((DWORD_PTR) pszContextOid)) dwContextOid = (DWORD) ((DWORD_PTR) pszContextOid); else dwContextOid = 0x10000;
if (dwRetrievalFlags & CRYPT_WIRE_ONLY_RETRIEVAL) dwContextOid |= 0x20000;
return dwContextOid; }
// Assumption: OfflineUrlCache is locked
POFFLINE_URL_CACHE_ENTRY WINAPI CreateAndAddOfflineUrlCacheEntry( IN PCRYPT_DATA_BLOB pUrlBlob, IN PCRYPT_DATA_BLOB pExtraBlob, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { POFFLINE_URL_CACHE_ENTRY pEntry; DWORD cbEntry; BYTE *pb;
cbEntry = sizeof(OFFLINE_URL_CACHE_ENTRY) + pUrlBlob->cbData + pExtraBlob->cbData;
pEntry = (POFFLINE_URL_CACHE_ENTRY) new BYTE [cbEntry];
if (pEntry == NULL) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( NULL ); }
memset( pEntry, 0, sizeof( OFFLINE_URL_CACHE_ENTRY ) ); pb = (BYTE *) &pEntry[1];
if (pUrlBlob->cbData) { pEntry->UrlBlob.pbData = pb; pEntry->UrlBlob.cbData = pUrlBlob->cbData; memcpy(pb, pUrlBlob->pbData, pUrlBlob->cbData); pb += pUrlBlob->cbData; }
if (pExtraBlob->cbData) { pEntry->ExtraBlob.pbData = pb; pEntry->ExtraBlob.cbData = pExtraBlob->cbData; memcpy(pb, pExtraBlob->pbData, pExtraBlob->cbData); }
pEntry->dwContextOid = GetOfflineUrlCacheContextOid(pszContextOid, dwRetrievalFlags);
if (pOfflineUrlCacheHead) { assert(NULL == pOfflineUrlCacheHead->pPrev); pOfflineUrlCacheHead->pPrev = pEntry; pEntry->pNext = pOfflineUrlCacheHead; } // else
// pEntry->pNext = NULL; // already zeroed above
// pEntry->pPrev = NULL; // already zeroed above
pOfflineUrlCacheHead = pEntry;
return pEntry; }
// Assumption: OfflineUrlCache is locked
VOID WINAPI RemoveAndFreeOfflineUrlCacheEntry( IN OUT POFFLINE_URL_CACHE_ENTRY pEntry ) { if (pEntry->pNext) { pEntry->pNext->pPrev = pEntry->pPrev; }
if (pEntry->pPrev) { pEntry->pPrev->pNext = pEntry->pNext; } else { assert(pOfflineUrlCacheHead == pEntry); pOfflineUrlCacheHead = pEntry->pNext; }
delete (LPBYTE) pEntry; }
// Assumption: OfflineUrlCache is locked
POFFLINE_URL_CACHE_ENTRY WINAPI FindOfflineUrlCacheEntry( IN PCRYPT_DATA_BLOB pUrlBlob, IN PCRYPT_DATA_BLOB pExtraBlob, IN LPCSTR pszContextOid, IN DWORD dwRetrievalFlags ) { DWORD cbUrl = pUrlBlob->cbData; BYTE *pbUrl = pUrlBlob->pbData; DWORD cbExtra = pExtraBlob->cbData; BYTE *pbExtra = pExtraBlob->pbData; DWORD dwContextOid; POFFLINE_URL_CACHE_ENTRY pEntry;
dwContextOid = GetOfflineUrlCacheContextOid(pszContextOid, dwRetrievalFlags);
for (pEntry = pOfflineUrlCacheHead; pEntry; pEntry = pEntry->pNext) { if (pEntry->dwContextOid == dwContextOid && pEntry->UrlBlob.cbData == cbUrl && pEntry->ExtraBlob.cbData == cbExtra && (0 == cbExtra || 0 == memcmp( pEntry->ExtraBlob.pbData, pbExtra, cbExtra)) && (0 == cbUrl || 0 == memcmp( pEntry->UrlBlob.pbData, pbUrl, cbUrl)) ) { return pEntry; } }
return ( NULL ); }
|