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

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: offurl.cpp
  7. //
  8. // Contents: Offline URL Caching
  9. //
  10. // History: 19-Jan-00 philh Created
  11. // 01-Jan-02 philh Changed to internally use UNICODE Urls
  12. //----------------------------------------------------------------------------
  13. #include <global.hxx>
  14. //
  15. // Offline URL Cache Entry.
  16. //
  17. // The earliest wire retrieval is delayed according to the number of
  18. // offline failures.
  19. //
  20. // For a successful wire URL retrieval, the entry is removed and deleted.
  21. //
  22. // Assumption: the number of offline entries is small, less than 20.
  23. //
  24. typedef struct _OFFLINE_URL_CACHE_ENTRY
  25. OFFLINE_URL_CACHE_ENTRY, *POFFLINE_URL_CACHE_ENTRY;
  26. struct _OFFLINE_URL_CACHE_ENTRY {
  27. CRYPT_DATA_BLOB UrlBlob;
  28. CRYPT_DATA_BLOB ExtraBlob;
  29. DWORD dwContextOid;
  30. OFFLINE_URL_TIME_INFO OfflineUrlTimeInfo;
  31. POFFLINE_URL_CACHE_ENTRY pNext;
  32. POFFLINE_URL_CACHE_ENTRY pPrev;
  33. };
  34. CRITICAL_SECTION OfflineUrlCacheCriticalSection;
  35. POFFLINE_URL_CACHE_ENTRY pOfflineUrlCacheHead;
  36. //
  37. // Local Functions (Forward Reference)
  38. //
  39. // Assumption: OfflineUrlCache is locked
  40. POFFLINE_URL_CACHE_ENTRY
  41. WINAPI
  42. CreateAndAddOfflineUrlCacheEntry(
  43. IN PCRYPT_DATA_BLOB pUrlBlob,
  44. IN PCRYPT_DATA_BLOB pExtraBlob,
  45. IN LPCSTR pszContextOid,
  46. IN DWORD dwRetrievalFlags
  47. );
  48. // Assumption: OfflineUrlCache is locked
  49. VOID
  50. WINAPI
  51. RemoveAndFreeOfflineUrlCacheEntry(
  52. IN OUT POFFLINE_URL_CACHE_ENTRY pEntry
  53. );
  54. // Assumption: OfflineUrlCache is locked
  55. POFFLINE_URL_CACHE_ENTRY
  56. WINAPI
  57. FindOfflineUrlCacheEntry(
  58. IN PCRYPT_DATA_BLOB pUrlBlob,
  59. IN PCRYPT_DATA_BLOB pExtraBlob,
  60. IN LPCSTR pszContextOid,
  61. IN DWORD dwRetrievalFlags
  62. );
  63. VOID
  64. WINAPI
  65. InitializeOfflineUrlCache()
  66. {
  67. Pki_InitializeCriticalSection(&OfflineUrlCacheCriticalSection);
  68. }
  69. VOID
  70. WINAPI
  71. DeleteOfflineUrlCache()
  72. {
  73. while (pOfflineUrlCacheHead)
  74. RemoveAndFreeOfflineUrlCacheEntry(pOfflineUrlCacheHead);
  75. DeleteCriticalSection(&OfflineUrlCacheCriticalSection);
  76. }
  77. //
  78. // Return status:
  79. // +1 - Online
  80. // 0 - Offline, current time >= earliest online time, hit the wire
  81. // -1 - Offline, current time < earliest onlime time
  82. //
  83. LONG
  84. WINAPI
  85. GetOfflineUrlTimeStatus(
  86. IN POFFLINE_URL_TIME_INFO pInfo
  87. )
  88. {
  89. FILETIME CurrentTime;
  90. if (0 == pInfo->dwOfflineCnt)
  91. {
  92. return 1;
  93. }
  94. GetSystemTimeAsFileTime(&CurrentTime);
  95. if (0 <= CompareFileTime(&CurrentTime, &pInfo->EarliestOnlineTime))
  96. {
  97. return 0;
  98. }
  99. else
  100. {
  101. return -1;
  102. }
  103. }
  104. const DWORD rgdwOfflineUrlDeltaSeconds[] = {
  105. 15, // 15 seconds
  106. 15, // 15 seconds
  107. 60, // 1 minute
  108. 60 * 5, // 5 minutes
  109. 60 * 10, // 10 minutes
  110. 60 * 30, // 30 minutes
  111. };
  112. #define OFFLINE_URL_DELTA_SECONDS_CNT \
  113. (sizeof(rgdwOfflineUrlDeltaSeconds) / \
  114. sizeof(rgdwOfflineUrlDeltaSeconds[0]))
  115. VOID
  116. WINAPI
  117. SetOfflineUrlTime(
  118. IN OUT POFFLINE_URL_TIME_INFO pInfo
  119. )
  120. {
  121. DWORD dwOfflineCnt;
  122. FILETIME CurrentTime;
  123. dwOfflineCnt = ++pInfo->dwOfflineCnt;
  124. if (OFFLINE_URL_DELTA_SECONDS_CNT < dwOfflineCnt)
  125. {
  126. dwOfflineCnt = OFFLINE_URL_DELTA_SECONDS_CNT;
  127. }
  128. GetSystemTimeAsFileTime( &CurrentTime );
  129. I_CryptIncrementFileTimeBySeconds(
  130. &CurrentTime,
  131. rgdwOfflineUrlDeltaSeconds[dwOfflineCnt - 1],
  132. &pInfo->EarliestOnlineTime
  133. );
  134. }
  135. VOID
  136. WINAPI
  137. SetOnlineUrlTime(
  138. IN OUT POFFLINE_URL_TIME_INFO pInfo
  139. )
  140. {
  141. pInfo->dwOfflineCnt = 0;
  142. }
  143. //
  144. // Return status:
  145. // +1 - Online
  146. // 0 - Offline, current time >= earliest online time, hit the wire
  147. // -1 - Offline, current time < earliest onlime time
  148. //
  149. LONG
  150. WINAPI
  151. GetOriginUrlStatusW(
  152. IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  153. IN LPCWSTR pwszUrl,
  154. IN LPCSTR pszContextOid,
  155. IN DWORD dwRetrievalFlags
  156. )
  157. {
  158. LONG lStatus;
  159. POFFLINE_URL_CACHE_ENTRY pEntry;
  160. CRYPT_DATA_BLOB UrlBlob;
  161. CRYPT_DATA_BLOB ExtraBlob;
  162. UrlBlob.pbData = (BYTE *) pwszUrl;
  163. UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR);
  164. ExtraBlob.pbData = OriginIdentifier;
  165. ExtraBlob.cbData = MD5DIGESTLEN;
  166. EnterCriticalSection(&OfflineUrlCacheCriticalSection);
  167. pEntry = FindOfflineUrlCacheEntry(
  168. &UrlBlob,
  169. &ExtraBlob,
  170. pszContextOid,
  171. dwRetrievalFlags
  172. );
  173. if (pEntry)
  174. lStatus = GetOfflineUrlTimeStatus(&pEntry->OfflineUrlTimeInfo);
  175. else
  176. lStatus = 1;
  177. LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
  178. return lStatus;
  179. }
  180. VOID
  181. WINAPI
  182. SetOnlineOriginUrlW(
  183. IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  184. IN LPCWSTR pwszUrl,
  185. IN LPCSTR pszContextOid,
  186. IN DWORD dwRetrievalFlags
  187. )
  188. {
  189. POFFLINE_URL_CACHE_ENTRY pEntry;
  190. CRYPT_DATA_BLOB UrlBlob;
  191. CRYPT_DATA_BLOB ExtraBlob;
  192. UrlBlob.pbData = (BYTE *) pwszUrl;
  193. UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR);
  194. ExtraBlob.pbData = OriginIdentifier;
  195. ExtraBlob.cbData = MD5DIGESTLEN;
  196. EnterCriticalSection(&OfflineUrlCacheCriticalSection);
  197. pEntry = FindOfflineUrlCacheEntry(
  198. &UrlBlob,
  199. &ExtraBlob,
  200. pszContextOid,
  201. dwRetrievalFlags
  202. );
  203. if (pEntry)
  204. RemoveAndFreeOfflineUrlCacheEntry(pEntry);
  205. LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
  206. }
  207. VOID
  208. WINAPI
  209. SetOfflineOriginUrlW(
  210. IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  211. IN LPCWSTR pwszUrl,
  212. IN LPCSTR pszContextOid,
  213. IN DWORD dwRetrievalFlags
  214. )
  215. {
  216. POFFLINE_URL_CACHE_ENTRY pEntry;
  217. CRYPT_DATA_BLOB UrlBlob;
  218. CRYPT_DATA_BLOB ExtraBlob;
  219. UrlBlob.pbData = (BYTE *) pwszUrl;
  220. UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR);
  221. ExtraBlob.pbData = OriginIdentifier;
  222. ExtraBlob.cbData = MD5DIGESTLEN;
  223. EnterCriticalSection(&OfflineUrlCacheCriticalSection);
  224. pEntry = FindOfflineUrlCacheEntry(
  225. &UrlBlob,
  226. &ExtraBlob,
  227. pszContextOid,
  228. dwRetrievalFlags
  229. );
  230. if (NULL == pEntry)
  231. pEntry = CreateAndAddOfflineUrlCacheEntry(
  232. &UrlBlob,
  233. &ExtraBlob,
  234. pszContextOid,
  235. dwRetrievalFlags
  236. );
  237. if (pEntry)
  238. SetOfflineUrlTime(&pEntry->OfflineUrlTimeInfo);
  239. LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
  240. }
  241. //
  242. // Return status:
  243. // +1 - Online
  244. // 0 - Offline, current time >= earliest online time, hit the wire
  245. // -1 - Offline, current time < earliest onlime time
  246. //
  247. LONG
  248. WINAPI
  249. GetUrlStatusW(
  250. IN LPCWSTR pwszUrl,
  251. IN LPCSTR pszContextOid,
  252. IN DWORD dwRetrievalFlags
  253. )
  254. {
  255. LONG lStatus;
  256. POFFLINE_URL_CACHE_ENTRY pEntry;
  257. CRYPT_DATA_BLOB UrlBlob;
  258. CRYPT_DATA_BLOB ExtraBlob;
  259. UrlBlob.pbData = (BYTE *) pwszUrl;
  260. UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR);
  261. ExtraBlob.pbData = NULL;
  262. ExtraBlob.cbData = 0;
  263. EnterCriticalSection(&OfflineUrlCacheCriticalSection);
  264. pEntry = FindOfflineUrlCacheEntry(
  265. &UrlBlob,
  266. &ExtraBlob,
  267. pszContextOid,
  268. dwRetrievalFlags
  269. );
  270. if (pEntry)
  271. lStatus = GetOfflineUrlTimeStatus(&pEntry->OfflineUrlTimeInfo);
  272. else
  273. lStatus = 1;
  274. LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
  275. return lStatus;
  276. }
  277. VOID
  278. WINAPI
  279. SetOnlineUrlW(
  280. IN LPCWSTR pwszUrl,
  281. IN LPCSTR pszContextOid,
  282. IN DWORD dwRetrievalFlags
  283. )
  284. {
  285. POFFLINE_URL_CACHE_ENTRY pEntry;
  286. CRYPT_DATA_BLOB UrlBlob;
  287. CRYPT_DATA_BLOB ExtraBlob;
  288. UrlBlob.pbData = (BYTE *) pwszUrl;
  289. UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR);
  290. ExtraBlob.pbData = NULL;
  291. ExtraBlob.cbData = 0;
  292. EnterCriticalSection(&OfflineUrlCacheCriticalSection);
  293. pEntry = FindOfflineUrlCacheEntry(
  294. &UrlBlob,
  295. &ExtraBlob,
  296. pszContextOid,
  297. dwRetrievalFlags
  298. );
  299. if (pEntry)
  300. RemoveAndFreeOfflineUrlCacheEntry(pEntry);
  301. LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
  302. }
  303. VOID
  304. WINAPI
  305. SetOfflineUrlW(
  306. IN LPCWSTR pwszUrl,
  307. IN LPCSTR pszContextOid,
  308. IN DWORD dwRetrievalFlags
  309. )
  310. {
  311. POFFLINE_URL_CACHE_ENTRY pEntry;
  312. CRYPT_DATA_BLOB UrlBlob;
  313. CRYPT_DATA_BLOB ExtraBlob;
  314. UrlBlob.pbData = (BYTE *) pwszUrl;
  315. UrlBlob.cbData = wcslen(pwszUrl) * sizeof(WCHAR);
  316. ExtraBlob.pbData = NULL;
  317. ExtraBlob.cbData = 0;
  318. EnterCriticalSection(&OfflineUrlCacheCriticalSection);
  319. pEntry = FindOfflineUrlCacheEntry(
  320. &UrlBlob,
  321. &ExtraBlob,
  322. pszContextOid,
  323. dwRetrievalFlags
  324. );
  325. if (NULL == pEntry)
  326. pEntry = CreateAndAddOfflineUrlCacheEntry(
  327. &UrlBlob,
  328. &ExtraBlob,
  329. pszContextOid,
  330. dwRetrievalFlags
  331. );
  332. if (pEntry)
  333. SetOfflineUrlTime(&pEntry->OfflineUrlTimeInfo);
  334. LeaveCriticalSection(&OfflineUrlCacheCriticalSection);
  335. }
  336. inline
  337. DWORD
  338. GetOfflineUrlCacheContextOid(
  339. IN LPCSTR pszContextOid,
  340. IN DWORD dwRetrievalFlags
  341. )
  342. {
  343. DWORD dwContextOid;
  344. if (0xFFFF >= (DWORD) ((DWORD_PTR) pszContextOid))
  345. dwContextOid = (DWORD) ((DWORD_PTR) pszContextOid);
  346. else
  347. dwContextOid = 0x10000;
  348. if (dwRetrievalFlags & CRYPT_WIRE_ONLY_RETRIEVAL)
  349. dwContextOid |= 0x20000;
  350. return dwContextOid;
  351. }
  352. // Assumption: OfflineUrlCache is locked
  353. POFFLINE_URL_CACHE_ENTRY
  354. WINAPI
  355. CreateAndAddOfflineUrlCacheEntry(
  356. IN PCRYPT_DATA_BLOB pUrlBlob,
  357. IN PCRYPT_DATA_BLOB pExtraBlob,
  358. IN LPCSTR pszContextOid,
  359. IN DWORD dwRetrievalFlags
  360. )
  361. {
  362. POFFLINE_URL_CACHE_ENTRY pEntry;
  363. DWORD cbEntry;
  364. BYTE *pb;
  365. cbEntry = sizeof(OFFLINE_URL_CACHE_ENTRY) +
  366. pUrlBlob->cbData + pExtraBlob->cbData;
  367. pEntry = (POFFLINE_URL_CACHE_ENTRY) new BYTE [cbEntry];
  368. if (pEntry == NULL)
  369. {
  370. SetLastError( (DWORD) E_OUTOFMEMORY );
  371. return( NULL );
  372. }
  373. memset( pEntry, 0, sizeof( OFFLINE_URL_CACHE_ENTRY ) );
  374. pb = (BYTE *) &pEntry[1];
  375. if (pUrlBlob->cbData) {
  376. pEntry->UrlBlob.pbData = pb;
  377. pEntry->UrlBlob.cbData = pUrlBlob->cbData;
  378. memcpy(pb, pUrlBlob->pbData, pUrlBlob->cbData);
  379. pb += pUrlBlob->cbData;
  380. }
  381. if (pExtraBlob->cbData) {
  382. pEntry->ExtraBlob.pbData = pb;
  383. pEntry->ExtraBlob.cbData = pExtraBlob->cbData;
  384. memcpy(pb, pExtraBlob->pbData, pExtraBlob->cbData);
  385. }
  386. pEntry->dwContextOid =
  387. GetOfflineUrlCacheContextOid(pszContextOid, dwRetrievalFlags);
  388. if (pOfflineUrlCacheHead) {
  389. assert(NULL == pOfflineUrlCacheHead->pPrev);
  390. pOfflineUrlCacheHead->pPrev = pEntry;
  391. pEntry->pNext = pOfflineUrlCacheHead;
  392. }
  393. // else
  394. // pEntry->pNext = NULL; // already zeroed above
  395. // pEntry->pPrev = NULL; // already zeroed above
  396. pOfflineUrlCacheHead = pEntry;
  397. return pEntry;
  398. }
  399. // Assumption: OfflineUrlCache is locked
  400. VOID
  401. WINAPI
  402. RemoveAndFreeOfflineUrlCacheEntry(
  403. IN OUT POFFLINE_URL_CACHE_ENTRY pEntry
  404. )
  405. {
  406. if (pEntry->pNext)
  407. {
  408. pEntry->pNext->pPrev = pEntry->pPrev;
  409. }
  410. if (pEntry->pPrev)
  411. {
  412. pEntry->pPrev->pNext = pEntry->pNext;
  413. }
  414. else
  415. {
  416. assert(pOfflineUrlCacheHead == pEntry);
  417. pOfflineUrlCacheHead = pEntry->pNext;
  418. }
  419. delete (LPBYTE) pEntry;
  420. }
  421. // Assumption: OfflineUrlCache is locked
  422. POFFLINE_URL_CACHE_ENTRY
  423. WINAPI
  424. FindOfflineUrlCacheEntry(
  425. IN PCRYPT_DATA_BLOB pUrlBlob,
  426. IN PCRYPT_DATA_BLOB pExtraBlob,
  427. IN LPCSTR pszContextOid,
  428. IN DWORD dwRetrievalFlags
  429. )
  430. {
  431. DWORD cbUrl = pUrlBlob->cbData;
  432. BYTE *pbUrl = pUrlBlob->pbData;
  433. DWORD cbExtra = pExtraBlob->cbData;
  434. BYTE *pbExtra = pExtraBlob->pbData;
  435. DWORD dwContextOid;
  436. POFFLINE_URL_CACHE_ENTRY pEntry;
  437. dwContextOid =
  438. GetOfflineUrlCacheContextOid(pszContextOid, dwRetrievalFlags);
  439. for (pEntry = pOfflineUrlCacheHead; pEntry; pEntry = pEntry->pNext)
  440. {
  441. if (pEntry->dwContextOid == dwContextOid
  442. &&
  443. pEntry->UrlBlob.cbData == cbUrl
  444. &&
  445. pEntry->ExtraBlob.cbData == cbExtra
  446. &&
  447. (0 == cbExtra || 0 == memcmp(
  448. pEntry->ExtraBlob.pbData, pbExtra, cbExtra))
  449. &&
  450. (0 == cbUrl || 0 == memcmp(
  451. pEntry->UrlBlob.pbData, pbUrl, cbUrl))
  452. )
  453. {
  454. return pEntry;
  455. }
  456. }
  457. return ( NULL );
  458. }