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.
 
 
 
 
 
 

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 );
}