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.
547 lines
13 KiB
547 lines
13 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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 );
|
|
}
|