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.

1924 lines
58 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: tvo.cpp
  7. //
  8. // Contents: Implementation of CryptGetTimeValidObject
  9. //
  10. // History: 25-Sep-97 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <global.hxx>
  14. //+---------------------------------------------------------------------------
  15. //
  16. // Function: CryptGetTimeValidObject
  17. //
  18. // Synopsis: get a time valid CAPI2 object
  19. //
  20. //----------------------------------------------------------------------------
  21. BOOL WINAPI
  22. CryptGetTimeValidObject (
  23. IN LPCSTR pszTimeValidOid,
  24. IN LPVOID pvPara,
  25. IN PCCERT_CONTEXT pIssuer,
  26. IN LPFILETIME pftValidFor,
  27. IN DWORD dwFlags,
  28. IN DWORD dwTimeout,
  29. OUT OPTIONAL LPVOID* ppvObject,
  30. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  31. IN OPTIONAL LPVOID pvReserved
  32. )
  33. {
  34. BOOL fResult;
  35. HCRYPTOIDFUNCADDR hGetTimeValidObject;
  36. PFN_GET_TIME_VALID_OBJECT_FUNC pfnGetTimeValidObject;
  37. DWORD LastError;
  38. FILETIME CurrentTime;
  39. if ( CryptGetOIDFunctionAddress(
  40. hGetTimeValidObjectFuncSet,
  41. X509_ASN_ENCODING,
  42. pszTimeValidOid,
  43. 0,
  44. (LPVOID *)&pfnGetTimeValidObject,
  45. &hGetTimeValidObject
  46. ) == FALSE )
  47. {
  48. return( FALSE );
  49. }
  50. if ( pftValidFor == NULL )
  51. {
  52. GetSystemTimeAsFileTime( &CurrentTime );
  53. pftValidFor = &CurrentTime;
  54. }
  55. fResult = ( *pfnGetTimeValidObject )(
  56. pszTimeValidOid,
  57. pvPara,
  58. pIssuer,
  59. pftValidFor,
  60. dwFlags,
  61. dwTimeout,
  62. ppvObject,
  63. pCredentials,
  64. pvReserved
  65. );
  66. LastError = GetLastError();
  67. CryptFreeOIDFunctionAddress( hGetTimeValidObject, 0 );
  68. SetLastError( LastError );
  69. return( fResult );
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Function: CtlGetTimeValidObject
  74. //
  75. // Synopsis: get a time valid CTL
  76. //
  77. //----------------------------------------------------------------------------
  78. BOOL WINAPI
  79. CtlGetTimeValidObject (
  80. IN LPCSTR pszTimeValidOid,
  81. IN LPVOID pvPara,
  82. IN PCCERT_CONTEXT pIssuer,
  83. IN LPFILETIME pftValidFor,
  84. IN DWORD dwFlags,
  85. IN DWORD dwTimeout,
  86. OUT OPTIONAL LPVOID* ppvObject,
  87. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  88. IN OPTIONAL LPVOID pvReserved
  89. )
  90. {
  91. return( g_pProcessTVOAgent->GetTimeValidObject(
  92. pszTimeValidOid,
  93. pvPara,
  94. CONTEXT_OID_CTL,
  95. pIssuer,
  96. pftValidFor,
  97. dwFlags,
  98. dwTimeout,
  99. ppvObject,
  100. pCredentials,
  101. pvReserved
  102. ) );
  103. }
  104. //+---------------------------------------------------------------------------
  105. //
  106. // Function: CrlGetTimeValidObject
  107. //
  108. // Synopsis: get a time valid CRL
  109. //
  110. //----------------------------------------------------------------------------
  111. BOOL WINAPI
  112. CrlGetTimeValidObject (
  113. IN LPCSTR pszTimeValidOid,
  114. IN LPVOID pvPara,
  115. IN PCCERT_CONTEXT pIssuer,
  116. IN LPFILETIME pftValidFor,
  117. IN DWORD dwFlags,
  118. IN DWORD dwTimeout,
  119. OUT OPTIONAL LPVOID* ppvObject,
  120. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  121. IN OPTIONAL LPVOID pvReserved
  122. )
  123. {
  124. return( g_pProcessTVOAgent->GetTimeValidObject(
  125. pszTimeValidOid,
  126. pvPara,
  127. CONTEXT_OID_CRL,
  128. pIssuer,
  129. pftValidFor,
  130. dwFlags,
  131. dwTimeout,
  132. ppvObject,
  133. pCredentials,
  134. pvReserved
  135. ) );
  136. }
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Function: CrlFromCertGetTimeValidObject
  140. //
  141. // Synopsis: get a time valid CRL from a subject certificate
  142. //
  143. //----------------------------------------------------------------------------
  144. BOOL WINAPI
  145. CrlFromCertGetTimeValidObject (
  146. IN LPCSTR pszTimeValidOid,
  147. IN LPVOID pvPara,
  148. IN PCCERT_CONTEXT pIssuer,
  149. IN LPFILETIME pftValidFor,
  150. IN DWORD dwFlags,
  151. IN DWORD dwTimeout,
  152. OUT OPTIONAL LPVOID* ppvObject,
  153. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  154. IN OPTIONAL LPVOID pvReserved
  155. )
  156. {
  157. return( g_pProcessTVOAgent->GetTimeValidObject(
  158. pszTimeValidOid,
  159. pvPara,
  160. CONTEXT_OID_CRL,
  161. pIssuer,
  162. pftValidFor,
  163. dwFlags,
  164. dwTimeout,
  165. ppvObject,
  166. pCredentials,
  167. pvReserved
  168. ) );
  169. }
  170. //+---------------------------------------------------------------------------
  171. //
  172. // Function: FreshestCrlFromCertGetTimeValidObject
  173. //
  174. // Synopsis: get a time valid freshest, delta CRL from a subject certificate
  175. //
  176. //----------------------------------------------------------------------------
  177. BOOL WINAPI
  178. FreshestCrlFromCertGetTimeValidObject (
  179. IN LPCSTR pszTimeValidOid,
  180. IN LPVOID pvPara,
  181. IN PCCERT_CONTEXT pIssuer,
  182. IN LPFILETIME pftValidFor,
  183. IN DWORD dwFlags,
  184. IN DWORD dwTimeout,
  185. OUT OPTIONAL LPVOID* ppvObject,
  186. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  187. IN OPTIONAL LPVOID pvReserved
  188. )
  189. {
  190. return( g_pProcessTVOAgent->GetTimeValidObject(
  191. pszTimeValidOid,
  192. pvPara,
  193. CONTEXT_OID_CRL,
  194. pIssuer,
  195. pftValidFor,
  196. dwFlags,
  197. dwTimeout,
  198. ppvObject,
  199. pCredentials,
  200. pvReserved
  201. ) );
  202. }
  203. //+---------------------------------------------------------------------------
  204. //
  205. // Function: FreshestCrlFromCrlGetTimeValidObject
  206. //
  207. // Synopsis: get a time valid freshest, delta CRL from a base CRL
  208. //
  209. //----------------------------------------------------------------------------
  210. BOOL WINAPI
  211. FreshestCrlFromCrlGetTimeValidObject (
  212. IN LPCSTR pszTimeValidOid,
  213. IN LPVOID pvPara,
  214. IN PCCERT_CONTEXT pIssuer,
  215. IN LPFILETIME pftValidFor,
  216. IN DWORD dwFlags,
  217. IN DWORD dwTimeout,
  218. OUT OPTIONAL LPVOID* ppvObject,
  219. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  220. IN OPTIONAL LPVOID pvReserved
  221. )
  222. {
  223. return( g_pProcessTVOAgent->GetTimeValidObject(
  224. pszTimeValidOid,
  225. pvPara,
  226. CONTEXT_OID_CRL,
  227. pIssuer,
  228. pftValidFor,
  229. dwFlags,
  230. dwTimeout,
  231. ppvObject,
  232. pCredentials,
  233. pvReserved
  234. ) );
  235. }
  236. //+---------------------------------------------------------------------------
  237. //
  238. // Function: CryptFlushTimeValidObject
  239. //
  240. // Synopsis: flush the object from the "TVO" system
  241. //
  242. //----------------------------------------------------------------------------
  243. BOOL WINAPI
  244. CryptFlushTimeValidObject (
  245. IN LPCSTR pszFlushTimeValidOid,
  246. IN LPVOID pvPara,
  247. IN PCCERT_CONTEXT pIssuer,
  248. IN DWORD dwFlags,
  249. IN LPVOID pvReserved
  250. )
  251. {
  252. BOOL fResult;
  253. HCRYPTOIDFUNCADDR hFlushTimeValidObject;
  254. PFN_FLUSH_TIME_VALID_OBJECT_FUNC pfnFlushTimeValidObject;
  255. DWORD LastError;
  256. if ( CryptGetOIDFunctionAddress(
  257. hFlushTimeValidObjectFuncSet,
  258. X509_ASN_ENCODING,
  259. pszFlushTimeValidOid,
  260. 0,
  261. (LPVOID *)&pfnFlushTimeValidObject,
  262. &hFlushTimeValidObject
  263. ) == FALSE )
  264. {
  265. return( FALSE );
  266. }
  267. fResult = ( *pfnFlushTimeValidObject )(
  268. pszFlushTimeValidOid,
  269. pvPara,
  270. pIssuer,
  271. dwFlags,
  272. pvReserved
  273. );
  274. LastError = GetLastError();
  275. CryptFreeOIDFunctionAddress( hFlushTimeValidObject, 0 );
  276. SetLastError( LastError );
  277. return( fResult );
  278. }
  279. //+---------------------------------------------------------------------------
  280. //
  281. // Function: CtlFlushTimeValidObject
  282. //
  283. // Synopsis: flush a CTL from the "TVO" system
  284. //
  285. //----------------------------------------------------------------------------
  286. BOOL WINAPI
  287. CtlFlushTimeValidObject (
  288. IN LPCSTR pszFlushTimeValidOid,
  289. IN LPVOID pvPara,
  290. IN PCCERT_CONTEXT pIssuer,
  291. IN DWORD dwFlags,
  292. IN LPVOID pvReserved
  293. )
  294. {
  295. return( g_pProcessTVOAgent->FlushTimeValidObject(
  296. pszFlushTimeValidOid,
  297. pvPara,
  298. CONTEXT_OID_CTL,
  299. pIssuer,
  300. dwFlags,
  301. pvReserved
  302. ) );
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // Function: CrlFlushTimeValidObject
  307. //
  308. // Synopsis: flush a CRL from the "TVO" system
  309. //
  310. //----------------------------------------------------------------------------
  311. BOOL WINAPI
  312. CrlFlushTimeValidObject (
  313. IN LPCSTR pszFlushTimeValidOid,
  314. IN LPVOID pvPara,
  315. IN PCCERT_CONTEXT pIssuer,
  316. IN DWORD dwFlags,
  317. IN LPVOID pvReserved
  318. )
  319. {
  320. return( g_pProcessTVOAgent->FlushTimeValidObject(
  321. pszFlushTimeValidOid,
  322. pvPara,
  323. CONTEXT_OID_CRL,
  324. pIssuer,
  325. dwFlags,
  326. pvReserved
  327. ) );
  328. }
  329. //+---------------------------------------------------------------------------
  330. //
  331. // Function: CrlFromCertFlushTimeValidObject
  332. //
  333. // Synopsis: flush a CRL from the "TVO" system given a subject cert
  334. //
  335. //----------------------------------------------------------------------------
  336. BOOL WINAPI
  337. CrlFromCertFlushTimeValidObject (
  338. IN LPCSTR pszFlushTimeValidOid,
  339. IN LPVOID pvPara,
  340. IN PCCERT_CONTEXT pIssuer,
  341. IN DWORD dwFlags,
  342. IN LPVOID pvReserved
  343. )
  344. {
  345. return( g_pProcessTVOAgent->FlushTimeValidObject(
  346. pszFlushTimeValidOid,
  347. pvPara,
  348. CONTEXT_OID_CRL,
  349. pIssuer,
  350. dwFlags,
  351. pvReserved
  352. ) );
  353. }
  354. //+---------------------------------------------------------------------------
  355. //
  356. // Function: FreshedtCrlFromCertFlushTimeValidObject
  357. //
  358. // Synopsis: flush a freshest, delta CRL from the "TVO" system given a
  359. // subject cert
  360. //
  361. //----------------------------------------------------------------------------
  362. BOOL WINAPI
  363. FreshestCrlFromCertFlushTimeValidObject (
  364. IN LPCSTR pszFlushTimeValidOid,
  365. IN LPVOID pvPara,
  366. IN PCCERT_CONTEXT pIssuer,
  367. IN DWORD dwFlags,
  368. IN LPVOID pvReserved
  369. )
  370. {
  371. return( g_pProcessTVOAgent->FlushTimeValidObject(
  372. pszFlushTimeValidOid,
  373. pvPara,
  374. CONTEXT_OID_CRL,
  375. pIssuer,
  376. dwFlags,
  377. pvReserved
  378. ) );
  379. }
  380. //+---------------------------------------------------------------------------
  381. //
  382. // Function: FreshestCrlFromCrlFlushTimeValidObject
  383. //
  384. // Synopsis: flush a freshest, delta CRL from the "TVO" system given a
  385. // base CRL
  386. //
  387. //----------------------------------------------------------------------------
  388. BOOL WINAPI
  389. FreshestCrlFromCrlFlushTimeValidObject (
  390. IN LPCSTR pszFlushTimeValidOid,
  391. IN LPVOID pvPara,
  392. IN PCCERT_CONTEXT pIssuer,
  393. IN DWORD dwFlags,
  394. IN LPVOID pvReserved
  395. )
  396. {
  397. return( g_pProcessTVOAgent->FlushTimeValidObject(
  398. pszFlushTimeValidOid,
  399. pvPara,
  400. CONTEXT_OID_CRL,
  401. pIssuer,
  402. dwFlags,
  403. pvReserved
  404. ) );
  405. }
  406. //+---------------------------------------------------------------------------
  407. //
  408. // Member: CTVOCache::CTVOCache, public
  409. //
  410. // Synopsis: Constructor
  411. //
  412. //----------------------------------------------------------------------------
  413. CTVOCache::CTVOCache (
  414. DWORD cCacheBuckets,
  415. DWORD MaxCacheEntries,
  416. BOOL& rfResult
  417. )
  418. {
  419. LRU_CACHE_CONFIG CacheConfig;
  420. assert( MaxCacheEntries > 0 );
  421. memset( &CacheConfig, 0, sizeof( CacheConfig ) );
  422. CacheConfig.dwFlags = LRU_CACHE_NO_SERIALIZE | LRU_CACHE_NO_COPY_IDENTIFIER;
  423. CacheConfig.cBuckets = cCacheBuckets;
  424. CacheConfig.MaxEntries = MaxCacheEntries;
  425. CacheConfig.pfnHash = TVOCacheHashOriginIdentifier;
  426. CacheConfig.pfnOnRemoval = TVOCacheOnRemoval;
  427. rfResult = I_CryptCreateLruCache( &CacheConfig, &m_hCache );
  428. }
  429. //+---------------------------------------------------------------------------
  430. //
  431. // Member: CTVOCache::~CTVOCache, public
  432. //
  433. // Synopsis: Destructor
  434. //
  435. //----------------------------------------------------------------------------
  436. CTVOCache::~CTVOCache ()
  437. {
  438. I_CryptFreeLruCache( m_hCache, 0, NULL );
  439. }
  440. //+---------------------------------------------------------------------------
  441. //
  442. // Member: CTVOCache::InsertCacheEntry, public
  443. //
  444. // Synopsis: insert entry into cache
  445. //
  446. //----------------------------------------------------------------------------
  447. VOID
  448. CTVOCache::InsertCacheEntry (PTVO_CACHE_ENTRY pEntry)
  449. {
  450. I_CryptInsertLruEntry( pEntry->hLruEntry, NULL );
  451. }
  452. //+---------------------------------------------------------------------------
  453. //
  454. // Member: CTVOCache::RemoveCacheEntry, public
  455. //
  456. // Synopsis: remove entry from cache
  457. //
  458. //----------------------------------------------------------------------------
  459. VOID
  460. CTVOCache::RemoveCacheEntry (PTVO_CACHE_ENTRY pEntry, BOOL fSuppressFree)
  461. {
  462. DWORD dwFlags = 0;
  463. if ( fSuppressFree == TRUE )
  464. {
  465. dwFlags = LRU_SUPPRESS_REMOVAL_NOTIFICATION;
  466. }
  467. I_CryptRemoveLruEntry( pEntry->hLruEntry, dwFlags, NULL );
  468. }
  469. //+---------------------------------------------------------------------------
  470. //
  471. // Member: CTVOCache::TouchCacheEntry, public
  472. //
  473. // Synopsis: touch an entry
  474. //
  475. //----------------------------------------------------------------------------
  476. VOID
  477. CTVOCache::TouchCacheEntry (PTVO_CACHE_ENTRY pEntry)
  478. {
  479. I_CryptTouchLruEntry( pEntry->hLruEntry, 0 );
  480. }
  481. //+---------------------------------------------------------------------------
  482. //
  483. // Member: CTVOCache::FindCacheEntry, public
  484. //
  485. // Synopsis: find an entry in the cache given the origin identifier.
  486. // Skip entries that aren't valid for the subject.
  487. //
  488. //----------------------------------------------------------------------------
  489. PTVO_CACHE_ENTRY
  490. CTVOCache::FindCacheEntry (
  491. CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  492. LPCSTR pszContextOid,
  493. LPVOID pvSubject
  494. )
  495. {
  496. HLRUENTRY hEntry;
  497. CRYPT_DATA_BLOB DataBlob;
  498. PTVO_CACHE_ENTRY pEntry = NULL;
  499. DataBlob.cbData = MD5DIGESTLEN;
  500. DataBlob.pbData = OriginIdentifier;
  501. hEntry = I_CryptFindLruEntry( m_hCache, &DataBlob );
  502. while ( hEntry != NULL )
  503. {
  504. pEntry = (PTVO_CACHE_ENTRY)I_CryptGetLruEntryData( hEntry );
  505. assert(pEntry);
  506. assert(pszContextOid == pEntry->pszContextOid);
  507. if (pszContextOid == pEntry->pszContextOid &&
  508. ObjectContextIsValidForSubject (
  509. pszContextOid,
  510. pEntry->pvContext,
  511. pvSubject,
  512. NULL // pvExtraInfo
  513. ))
  514. {
  515. I_CryptReleaseLruEntry( hEntry );
  516. break;
  517. }
  518. else
  519. {
  520. pEntry = NULL;
  521. hEntry = I_CryptEnumMatchingLruEntries ( hEntry );
  522. }
  523. }
  524. return( pEntry );
  525. }
  526. //+---------------------------------------------------------------------------
  527. //
  528. // Member: CTVOCache::RemoveAllCacheEntries, public
  529. //
  530. // Synopsis: remove all cache entries
  531. //
  532. //----------------------------------------------------------------------------
  533. VOID
  534. CTVOCache::RemoveAllCacheEntries ()
  535. {
  536. I_CryptFlushLruCache( m_hCache, 0, NULL );
  537. }
  538. //+---------------------------------------------------------------------------
  539. //
  540. // Function: TVOCacheHashOriginIdentifier
  541. //
  542. // Synopsis: hash the origin identifier to a DWORD, since the origin
  543. // identifier is already a unique MD5 hash our algorithm is
  544. // to simply use some of the bytes
  545. //
  546. //----------------------------------------------------------------------------
  547. DWORD WINAPI
  548. TVOCacheHashOriginIdentifier (PCRYPT_DATA_BLOB pIdentifier)
  549. {
  550. DWORD Hash;
  551. assert( pIdentifier->cbData == MD5DIGESTLEN );
  552. memcpy( &Hash, pIdentifier->pbData, sizeof( DWORD ) );
  553. return( Hash );
  554. }
  555. //+---------------------------------------------------------------------------
  556. //
  557. // Function: TVOCacheOnRemoval
  558. //
  559. // Synopsis: removal notification callback
  560. //
  561. //----------------------------------------------------------------------------
  562. VOID WINAPI
  563. TVOCacheOnRemoval (LPVOID pvData, LPVOID pvRemovalContext)
  564. {
  565. ObjectContextFreeTVOCacheEntry( (PTVO_CACHE_ENTRY)pvData );
  566. }
  567. //+---------------------------------------------------------------------------
  568. //
  569. // Member: CTVOAgent::CTVOAgent, public
  570. //
  571. // Synopsis: Constructor
  572. //
  573. //----------------------------------------------------------------------------
  574. CTVOAgent::CTVOAgent (
  575. DWORD cCacheBuckets,
  576. DWORD MaxCacheEntries,
  577. BOOL& rfResult
  578. )
  579. : m_Cache( cCacheBuckets, MaxCacheEntries, rfResult )
  580. {
  581. if (!Pki_InitializeCriticalSection( &m_Lock ))
  582. {
  583. rfResult = FALSE;
  584. }
  585. }
  586. //+---------------------------------------------------------------------------
  587. //
  588. // Member: CTVOAgent::~CTVOAgent, public
  589. //
  590. // Synopsis: Destructor
  591. //
  592. //----------------------------------------------------------------------------
  593. CTVOAgent::~CTVOAgent ()
  594. {
  595. m_Cache.RemoveAllCacheEntries();
  596. DeleteCriticalSection( &m_Lock );
  597. }
  598. //+---------------------------------------------------------------------------
  599. //
  600. // Member: CTVOAgent::GetTimeValidObject, public
  601. //
  602. // Synopsis: get a time valid CAPI2 object
  603. //
  604. //----------------------------------------------------------------------------
  605. BOOL
  606. CTVOAgent::GetTimeValidObject (
  607. IN LPCSTR pszTimeValidOid,
  608. IN LPVOID pvPara,
  609. IN LPCSTR pszContextOid,
  610. IN PCCERT_CONTEXT pIssuer,
  611. IN LPFILETIME pftValidFor,
  612. IN DWORD dwFlags,
  613. IN DWORD dwTimeout,
  614. OUT OPTIONAL LPVOID* ppvObject,
  615. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  616. IN OPTIONAL LPVOID pvReserved
  617. )
  618. {
  619. BOOL fResult = TRUE;
  620. CRYPT_ORIGIN_IDENTIFIER OriginIdentifier;
  621. PTVO_CACHE_ENTRY pCacheEntry = NULL;
  622. DWORD PreferredUrlIndex = 0;
  623. PCRYPT_URL_ARRAY pUrlArray = NULL;
  624. DWORD cb = 0;
  625. DWORD cbUrlArray = 0;
  626. PCRYPT_URL_ARRAY pCacheUrlArray = NULL;
  627. LPWSTR pwszUrlHint = NULL;
  628. BOOL fHintInArray = FALSE;
  629. BOOL fArrayOwned = FALSE;
  630. BOOL fCrlFromCert = FALSE;
  631. LPCSTR pszUrlOidCrlFromCert = NULL;
  632. LPVOID pvSubject = NULL;
  633. BOOL fFreshest = FALSE;
  634. if ( pszTimeValidOid == TIME_VALID_OID_GET_CRL_FROM_CERT )
  635. {
  636. fCrlFromCert = TRUE;
  637. pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_CRL_DIST_POINT;
  638. pvSubject = pvPara;
  639. }
  640. else if ( pszTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CERT )
  641. {
  642. fCrlFromCert = TRUE;
  643. pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_FRESHEST_CRL;
  644. pvSubject = pvPara;
  645. fFreshest = TRUE;
  646. }
  647. else if ( pszTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CRL )
  648. {
  649. fCrlFromCert = TRUE;
  650. pszUrlOidCrlFromCert = URL_OID_CRL_FRESHEST_CRL;
  651. pvSubject = (LPVOID) ((PCCERT_CRL_CONTEXT_PAIR)pvPara)->pCertContext;
  652. fFreshest = TRUE;
  653. }
  654. if (fCrlFromCert)
  655. {
  656. if ( CrlGetOriginIdentifierFromSubjectCert(
  657. (PCCERT_CONTEXT)pvSubject,
  658. pIssuer,
  659. fFreshest,
  660. OriginIdentifier
  661. ) == FALSE )
  662. {
  663. return( FALSE );
  664. }
  665. assert( pszContextOid == CONTEXT_OID_CRL );
  666. }
  667. else
  668. {
  669. if ( ObjectContextGetOriginIdentifier(
  670. pszContextOid,
  671. pvPara,
  672. pIssuer,
  673. 0,
  674. OriginIdentifier
  675. ) == FALSE )
  676. {
  677. return( FALSE );
  678. }
  679. }
  680. PreferredUrlIndex = 0;
  681. pUrlArray = NULL;
  682. EnterCriticalSection( &m_Lock );
  683. pCacheEntry = m_Cache.FindCacheEntry(
  684. OriginIdentifier,
  685. pszContextOid,
  686. pvSubject
  687. );
  688. if ( pCacheEntry != NULL )
  689. {
  690. if ( !( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL ) )
  691. {
  692. if ( ( dwFlags & CRYPT_DONT_CHECK_TIME_VALIDITY ) ||
  693. IsValidCreateOrExpireTime (
  694. 0 != (dwFlags & CRYPT_CHECK_FRESHNESS_TIME_VALIDITY),
  695. pftValidFor,
  696. &pCacheEntry->CreateTime,
  697. &pCacheEntry->ExpireTime ) )
  698. {
  699. m_Cache.TouchCacheEntry( pCacheEntry );
  700. if ( ppvObject != NULL )
  701. {
  702. *ppvObject = ObjectContextDuplicate(
  703. pCacheEntry->pszContextOid,
  704. pCacheEntry->pvContext
  705. );
  706. }
  707. LeaveCriticalSection( &m_Lock );
  708. return( TRUE );
  709. }
  710. }
  711. if ( !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
  712. {
  713. if ( GetOfflineUrlTimeStatus(&pCacheEntry->OfflineUrlTimeInfo) < 0
  714. ||
  715. !I_CryptNetIsConnected() )
  716. {
  717. if ( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL )
  718. {
  719. LeaveCriticalSection( &m_Lock );
  720. SetLastError( (DWORD) ERROR_NOT_CONNECTED );
  721. return( FALSE );
  722. }
  723. else
  724. {
  725. dwFlags |= CRYPT_CACHE_ONLY_RETRIEVAL;
  726. }
  727. }
  728. }
  729. if ( pCacheEntry->pUrlArrayNext != NULL )
  730. {
  731. cbUrlArray = pCacheEntry->cbUrlArrayNext;
  732. pCacheUrlArray = pCacheEntry->pUrlArrayNext;
  733. PreferredUrlIndex = pCacheEntry->UrlIndexNext;
  734. }
  735. else
  736. {
  737. cbUrlArray = pCacheEntry->cbUrlArrayThis;
  738. pCacheUrlArray = pCacheEntry->pUrlArrayThis;
  739. PreferredUrlIndex = pCacheEntry->UrlIndexThis;
  740. }
  741. }
  742. else if ( !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
  743. {
  744. if ( !I_CryptNetIsConnected() )
  745. {
  746. if ( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL )
  747. {
  748. LeaveCriticalSection( &m_Lock );
  749. SetLastError( (DWORD) ERROR_NOT_CONNECTED );
  750. return( FALSE );
  751. }
  752. else
  753. {
  754. dwFlags |= CRYPT_CACHE_ONLY_RETRIEVAL;
  755. }
  756. }
  757. }
  758. if ( ( fResult == TRUE ) && ( pUrlArray == NULL ) )
  759. {
  760. if ( pCacheEntry != NULL )
  761. {
  762. pwszUrlHint = pCacheUrlArray->rgwszUrl[ PreferredUrlIndex ];
  763. }
  764. if ( fCrlFromCert )
  765. {
  766. fResult = CertificateGetCrlDistPointUrl(
  767. pszUrlOidCrlFromCert,
  768. pvPara,
  769. pwszUrlHint,
  770. &pUrlArray,
  771. &cb,
  772. &PreferredUrlIndex,
  773. &fHintInArray
  774. );
  775. }
  776. else if ( pszTimeValidOid == TIME_VALID_OID_GET_CTL )
  777. {
  778. fResult = ObjectContextGetNextUpdateUrl(
  779. pszContextOid,
  780. pvPara,
  781. pIssuer,
  782. pwszUrlHint,
  783. &pUrlArray,
  784. &cb,
  785. &PreferredUrlIndex,
  786. &fHintInArray
  787. );
  788. }
  789. else
  790. {
  791. SetLastError( (DWORD) CRYPT_E_NOT_FOUND );
  792. fResult = FALSE;
  793. }
  794. if ( fResult == TRUE )
  795. {
  796. cbUrlArray = cb;
  797. }
  798. else if ( pCacheEntry != NULL )
  799. {
  800. pUrlArray = (PCRYPT_URL_ARRAY)new BYTE [ cbUrlArray ];
  801. if ( pUrlArray != NULL )
  802. {
  803. if (CopyUrlArray( pUrlArray, pCacheUrlArray, cbUrlArray ))
  804. {
  805. fHintInArray = TRUE;
  806. fResult = TRUE;
  807. }
  808. else
  809. {
  810. delete [] (BYTE *) pUrlArray;
  811. pUrlArray = NULL;
  812. SetLastError( (DWORD) E_INVALIDARG );
  813. }
  814. }
  815. else
  816. {
  817. SetLastError( (DWORD) E_OUTOFMEMORY );
  818. }
  819. }
  820. }
  821. LeaveCriticalSection( &m_Lock );
  822. if ( fResult == TRUE )
  823. {
  824. fResult = GetTimeValidObjectByUrl(
  825. cbUrlArray,
  826. pUrlArray,
  827. PreferredUrlIndex,
  828. pszContextOid,
  829. pIssuer,
  830. pvSubject,
  831. OriginIdentifier,
  832. pftValidFor,
  833. dwFlags,
  834. dwTimeout,
  835. ppvObject,
  836. pCredentials,
  837. NULL,
  838. &fArrayOwned,
  839. pvReserved
  840. );
  841. }
  842. if ( fArrayOwned == FALSE )
  843. {
  844. delete [] (BYTE *) pUrlArray;
  845. }
  846. return( fResult );
  847. }
  848. //+---------------------------------------------------------------------------
  849. //
  850. // Member: CTVOAgent::GetTimeValidObjectByUrl, public
  851. //
  852. // Synopsis: get a time valid object using URL
  853. //
  854. //----------------------------------------------------------------------------
  855. BOOL
  856. CTVOAgent::GetTimeValidObjectByUrl (
  857. IN DWORD cbUrlArray,
  858. IN PCRYPT_URL_ARRAY pUrlArray,
  859. IN DWORD PreferredUrlIndex,
  860. IN LPCSTR pszContextOid,
  861. IN PCCERT_CONTEXT pIssuer,
  862. IN LPVOID pvSubject,
  863. IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  864. IN LPFILETIME pftValidFor,
  865. IN DWORD dwFlags,
  866. IN DWORD dwTimeout,
  867. OUT OPTIONAL LPVOID* ppvObject,
  868. IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
  869. IN OPTIONAL LPWSTR pwszUrlExtra,
  870. OUT BOOL* pfArrayOwned,
  871. IN OPTIONAL LPVOID pvReserved
  872. )
  873. {
  874. BOOL fResult = FALSE;
  875. DWORD cCount;
  876. LPWSTR pwsz;
  877. LPVOID pvContext = NULL;
  878. PTVO_CACHE_ENTRY pEntry = NULL;
  879. PTVO_CACHE_ENTRY pFound;
  880. DWORD LastError;
  881. // Following is only used for CRYPT_ACCUMULATIVE_TIMEOUT
  882. FILETIME ftEndUrlRetrieval;
  883. if ( PreferredUrlIndex != 0 )
  884. {
  885. pwsz = pUrlArray->rgwszUrl[PreferredUrlIndex];
  886. pUrlArray->rgwszUrl[PreferredUrlIndex] = pUrlArray->rgwszUrl[0];
  887. pUrlArray->rgwszUrl[0] = pwsz;
  888. }
  889. if (dwFlags & CRYPT_ACCUMULATIVE_TIMEOUT)
  890. {
  891. if (0 == dwTimeout)
  892. {
  893. dwFlags &= ~CRYPT_ACCUMULATIVE_TIMEOUT;
  894. }
  895. else
  896. {
  897. FILETIME ftStartUrlRetrieval;
  898. GetSystemTimeAsFileTime(&ftStartUrlRetrieval);
  899. I_CryptIncrementFileTimeByMilliseconds(
  900. &ftStartUrlRetrieval, dwTimeout,
  901. &ftEndUrlRetrieval);
  902. }
  903. }
  904. for ( cCount = 0; cCount < pUrlArray->cUrl; cCount++ )
  905. {
  906. if (dwFlags & CRYPT_ACCUMULATIVE_TIMEOUT)
  907. {
  908. // Limit each URL timeout to half of the remaining time
  909. dwTimeout = I_CryptRemainingMilliseconds(&ftEndUrlRetrieval) / 2;
  910. if (0 == dwTimeout)
  911. {
  912. dwTimeout = 1;
  913. }
  914. }
  915. fResult = RetrieveTimeValidObjectByUrl(
  916. pUrlArray->rgwszUrl[cCount],
  917. pszContextOid,
  918. pftValidFor,
  919. dwFlags,
  920. dwTimeout,
  921. pCredentials,
  922. pIssuer,
  923. pvSubject,
  924. OriginIdentifier,
  925. &pvContext,
  926. pvReserved
  927. );
  928. if ( fResult == TRUE )
  929. {
  930. fResult = ObjectContextCreateTVOCacheEntry(
  931. m_Cache.LruCacheHandle(),
  932. pszContextOid,
  933. pvContext,
  934. OriginIdentifier,
  935. cbUrlArray,
  936. pUrlArray,
  937. cCount,
  938. pIssuer,
  939. &pEntry
  940. );
  941. *pfArrayOwned = fResult;
  942. break;
  943. }
  944. }
  945. if ( ( PreferredUrlIndex != 0 ) && ( *pfArrayOwned == FALSE ) )
  946. {
  947. pwsz = pUrlArray->rgwszUrl[PreferredUrlIndex];
  948. pUrlArray->rgwszUrl[PreferredUrlIndex] = pUrlArray->rgwszUrl[0];
  949. pUrlArray->rgwszUrl[0] = pwsz;
  950. }
  951. if ( ( fResult == FALSE ) && ( pwszUrlExtra != NULL ) )
  952. {
  953. if (dwFlags & CRYPT_ACCUMULATIVE_TIMEOUT)
  954. {
  955. // Limit each URL timeout to half of the remaining time
  956. dwTimeout = I_CryptRemainingMilliseconds(&ftEndUrlRetrieval) / 2;
  957. if (0 == dwTimeout)
  958. {
  959. dwTimeout = 1;
  960. }
  961. }
  962. fResult = RetrieveTimeValidObjectByUrl(
  963. pwszUrlExtra,
  964. pszContextOid,
  965. pftValidFor,
  966. dwFlags,
  967. dwTimeout,
  968. pCredentials,
  969. pIssuer,
  970. pvSubject,
  971. OriginIdentifier,
  972. &pvContext,
  973. pvReserved
  974. );
  975. if ( fResult == TRUE )
  976. {
  977. CCryptUrlArray cua( pUrlArray->cUrl + 1, 5, fResult );
  978. DWORD cb = 0;
  979. PCRYPT_URL_ARRAY pcua = NULL;
  980. if ( fResult == TRUE )
  981. {
  982. for ( cCount = 0; cCount < pUrlArray->cUrl; cCount++ )
  983. {
  984. fResult = cua.AddUrl( pUrlArray->rgwszUrl[cCount], FALSE );
  985. if ( fResult == FALSE )
  986. {
  987. break;
  988. }
  989. }
  990. }
  991. if ( fResult == TRUE )
  992. {
  993. fResult = cua.GetArrayInSingleBufferEncodedForm(
  994. &pcua,
  995. &cb
  996. );
  997. }
  998. if ( fResult == TRUE )
  999. {
  1000. fResult = ObjectContextCreateTVOCacheEntry(
  1001. m_Cache.LruCacheHandle(),
  1002. pszContextOid,
  1003. pvContext,
  1004. OriginIdentifier,
  1005. cb,
  1006. pcua,
  1007. pUrlArray->cUrl,
  1008. pIssuer,
  1009. &pEntry
  1010. );
  1011. if ( fResult == FALSE )
  1012. {
  1013. CryptMemFree( pcua );
  1014. }
  1015. }
  1016. cua.FreeArray( FALSE );
  1017. }
  1018. }
  1019. LastError = GetLastError();
  1020. EnterCriticalSection( &m_Lock );
  1021. pFound = m_Cache.FindCacheEntry(
  1022. OriginIdentifier,
  1023. pszContextOid,
  1024. pvSubject
  1025. );
  1026. if ( !fResult && pFound && !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
  1027. {
  1028. SetOfflineUrlTime( &pFound->OfflineUrlTimeInfo );
  1029. }
  1030. if ( ( fResult == TRUE ) && !( dwFlags & CRYPT_DONT_VERIFY_SIGNATURE ) )
  1031. {
  1032. if ( ( pFound != NULL ) &&
  1033. ( CompareFileTime(
  1034. &pFound->CreateTime,
  1035. &pEntry->CreateTime
  1036. ) >= 0 ) )
  1037. {
  1038. ObjectContextFree( pszContextOid, pvContext );
  1039. pvContext = ObjectContextDuplicate(
  1040. pFound->pszContextOid,
  1041. pFound->pvContext
  1042. );
  1043. SetOnlineUrlTime( &pFound->OfflineUrlTimeInfo );
  1044. ObjectContextFreeTVOCacheEntry( pEntry );
  1045. }
  1046. else
  1047. {
  1048. if ( pFound != NULL )
  1049. {
  1050. m_Cache.RemoveCacheEntry( pFound );
  1051. }
  1052. m_Cache.InsertCacheEntry( pEntry );
  1053. }
  1054. }
  1055. else if ( pEntry != NULL )
  1056. {
  1057. ObjectContextFreeTVOCacheEntry( pEntry );
  1058. }
  1059. LeaveCriticalSection( &m_Lock );
  1060. if ( pvContext != NULL )
  1061. {
  1062. if ( ( ppvObject != NULL ) && ( fResult == TRUE ) )
  1063. {
  1064. *ppvObject = pvContext;
  1065. }
  1066. else
  1067. {
  1068. ObjectContextFree( pszContextOid, pvContext );
  1069. }
  1070. }
  1071. SetLastError( LastError );
  1072. return( fResult );
  1073. }
  1074. //+---------------------------------------------------------------------------
  1075. //
  1076. // Member: CTVOAgent::FlushTimeValidObject, public
  1077. //
  1078. // Synopsis: flush time valid object
  1079. //
  1080. //----------------------------------------------------------------------------
  1081. BOOL
  1082. CTVOAgent::FlushTimeValidObject (
  1083. IN LPCSTR pszFlushTimeValidOid,
  1084. IN LPVOID pvPara,
  1085. IN LPCSTR pszFlushContextOid,
  1086. IN PCCERT_CONTEXT pIssuer,
  1087. IN DWORD dwFlags,
  1088. IN LPVOID pvReserved
  1089. )
  1090. {
  1091. BOOL fResult = TRUE;
  1092. CRYPT_ORIGIN_IDENTIFIER OriginIdentifier;
  1093. PTVO_CACHE_ENTRY pCacheEntry = NULL;
  1094. PCRYPT_URL_ARRAY pUrlArray = NULL;
  1095. DWORD cbUrlArray;
  1096. DWORD dwError = 0;
  1097. DWORD cCount;
  1098. BOOL fCrlFromCert = FALSE;
  1099. LPCSTR pszUrlOidCrlFromCert = NULL;
  1100. LPVOID pvSubject = NULL;
  1101. BOOL fFreshest = FALSE;
  1102. if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_CRL_FROM_CERT )
  1103. {
  1104. fCrlFromCert = TRUE;
  1105. pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_CRL_DIST_POINT;
  1106. pvSubject = pvPara;
  1107. }
  1108. else if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CERT )
  1109. {
  1110. fCrlFromCert = TRUE;
  1111. pszUrlOidCrlFromCert = URL_OID_CERTIFICATE_FRESHEST_CRL;
  1112. pvSubject = pvPara;
  1113. fFreshest = TRUE;
  1114. }
  1115. else if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CRL )
  1116. {
  1117. fCrlFromCert = TRUE;
  1118. pszUrlOidCrlFromCert = URL_OID_CRL_FRESHEST_CRL;
  1119. pvSubject = (LPVOID) ((PCCERT_CRL_CONTEXT_PAIR)pvPara)->pCertContext;
  1120. fFreshest = TRUE;
  1121. }
  1122. if (fCrlFromCert)
  1123. {
  1124. if ( CrlGetOriginIdentifierFromSubjectCert(
  1125. (PCCERT_CONTEXT)pvSubject,
  1126. pIssuer,
  1127. fFreshest,
  1128. OriginIdentifier
  1129. ) == FALSE )
  1130. {
  1131. return( FALSE );
  1132. }
  1133. assert( pszFlushContextOid == CONTEXT_OID_CRL );
  1134. }
  1135. else
  1136. {
  1137. if ( ObjectContextGetOriginIdentifier(
  1138. pszFlushContextOid,
  1139. pvPara,
  1140. pIssuer,
  1141. 0,
  1142. OriginIdentifier
  1143. ) == FALSE )
  1144. {
  1145. return( FALSE );
  1146. }
  1147. }
  1148. EnterCriticalSection( &m_Lock );
  1149. pCacheEntry = m_Cache.FindCacheEntry(
  1150. OriginIdentifier,
  1151. pszFlushContextOid,
  1152. pvSubject
  1153. );
  1154. if ( pCacheEntry != NULL )
  1155. {
  1156. // Remove the entry but suppress the freeing of it since we are going
  1157. // to use the data structure later
  1158. m_Cache.RemoveCacheEntry( pCacheEntry, TRUE );
  1159. }
  1160. LeaveCriticalSection( &m_Lock );
  1161. if ( pCacheEntry != NULL )
  1162. {
  1163. if ( pCacheEntry->pUrlArrayThis != NULL )
  1164. {
  1165. for ( cCount = 0;
  1166. cCount < pCacheEntry->pUrlArrayThis->cUrl;
  1167. cCount++ )
  1168. {
  1169. if ( ( SchemeDeleteUrlCacheEntry(
  1170. pCacheEntry->pUrlArrayThis->rgwszUrl[cCount]
  1171. ) == FALSE ) &&
  1172. ( GetLastError() != ERROR_FILE_NOT_FOUND ) )
  1173. {
  1174. dwError = GetLastError();
  1175. }
  1176. }
  1177. }
  1178. if ( pCacheEntry->pUrlArrayNext != NULL )
  1179. {
  1180. for ( cCount = 0;
  1181. cCount < pCacheEntry->pUrlArrayNext->cUrl;
  1182. cCount++ )
  1183. {
  1184. if ( ( SchemeDeleteUrlCacheEntry(
  1185. pCacheEntry->pUrlArrayNext->rgwszUrl[cCount]
  1186. ) == FALSE ) &&
  1187. ( GetLastError() != ERROR_FILE_NOT_FOUND ) )
  1188. {
  1189. dwError = GetLastError();
  1190. }
  1191. }
  1192. }
  1193. //
  1194. // Can place optimization here where if the hashes of the
  1195. // cache object and the passed in object are the same,
  1196. // we don't need to do any more work
  1197. //
  1198. ObjectContextFreeTVOCacheEntry( pCacheEntry );
  1199. }
  1200. if ( fCrlFromCert )
  1201. {
  1202. fResult = CertificateGetCrlDistPointUrl(
  1203. pszUrlOidCrlFromCert,
  1204. pvPara,
  1205. NULL, // pwszUrlHint
  1206. &pUrlArray,
  1207. &cbUrlArray,
  1208. NULL, // pPreferredUrlIndex
  1209. NULL // pfHintInArray
  1210. );
  1211. }
  1212. else if ( pszFlushTimeValidOid == TIME_VALID_OID_GET_CTL )
  1213. {
  1214. fResult = ObjectContextGetNextUpdateUrl(
  1215. pszFlushContextOid,
  1216. pvPara,
  1217. pIssuer,
  1218. NULL,
  1219. &pUrlArray,
  1220. &cbUrlArray,
  1221. NULL,
  1222. NULL
  1223. );
  1224. }
  1225. if ( ( fResult == TRUE ) && ( pUrlArray != NULL ) )
  1226. {
  1227. for ( cCount = 0; cCount < pUrlArray->cUrl; cCount++ )
  1228. {
  1229. if ( ( SchemeDeleteUrlCacheEntry(
  1230. pUrlArray->rgwszUrl[cCount]
  1231. ) == FALSE ) &&
  1232. ( GetLastError() != ERROR_FILE_NOT_FOUND ) )
  1233. {
  1234. dwError = GetLastError();
  1235. }
  1236. }
  1237. }
  1238. if ( pUrlArray )
  1239. {
  1240. delete [] (BYTE *) pUrlArray;
  1241. }
  1242. if ( ( fResult == TRUE ) && ( dwError != 0 ) )
  1243. {
  1244. SetLastError( dwError );
  1245. fResult = FALSE;
  1246. }
  1247. return( fResult );
  1248. }
  1249. //+---------------------------------------------------------------------------
  1250. //
  1251. // Function: IsValidCreateOrExpireTime
  1252. //
  1253. // Synopsis: for fCheckFreshnessTime, checks if the
  1254. // specified time is before or the same as the create time.
  1255. // Otherwise, checks if the specified time is before or the
  1256. // same as the expire time. A zero expire time matches any time.
  1257. //
  1258. //----------------------------------------------------------------------------
  1259. BOOL WINAPI
  1260. IsValidCreateOrExpireTime (
  1261. IN BOOL fCheckFreshnessTime,
  1262. IN LPFILETIME pftValidFor,
  1263. IN LPFILETIME pftCreateTime,
  1264. IN LPFILETIME pftExpireTime
  1265. )
  1266. {
  1267. if (fCheckFreshnessTime) {
  1268. if (CompareFileTime(pftValidFor, pftCreateTime) <= 0)
  1269. return TRUE;
  1270. else
  1271. return FALSE;
  1272. } else {
  1273. if (CompareFileTime(pftValidFor, pftExpireTime) <= 0 ||
  1274. I_CryptIsZeroFileTime(pftExpireTime))
  1275. return TRUE;
  1276. else
  1277. return FALSE;
  1278. }
  1279. }
  1280. //+---------------------------------------------------------------------------
  1281. //
  1282. // Function: ObjectContextCreateTVOCacheEntry
  1283. //
  1284. // Synopsis: create a TVO cache entry
  1285. //
  1286. //----------------------------------------------------------------------------
  1287. BOOL WINAPI
  1288. ObjectContextCreateTVOCacheEntry (
  1289. IN HLRUCACHE hCache,
  1290. IN LPCSTR pszContextOid,
  1291. IN LPVOID pvContext,
  1292. IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  1293. IN DWORD cbUrlArrayThis,
  1294. IN PCRYPT_URL_ARRAY pUrlArrayThis,
  1295. IN DWORD UrlIndexThis,
  1296. IN PCCERT_CONTEXT pIssuer,
  1297. OUT PTVO_CACHE_ENTRY* ppEntry
  1298. )
  1299. {
  1300. BOOL fResult = TRUE;
  1301. PTVO_CACHE_ENTRY pEntry;
  1302. CRYPT_DATA_BLOB DataBlob;
  1303. pEntry = new TVO_CACHE_ENTRY;
  1304. if ( pEntry == NULL )
  1305. {
  1306. SetLastError( (DWORD) E_OUTOFMEMORY );
  1307. return( FALSE );
  1308. }
  1309. memset( pEntry, 0, sizeof( TVO_CACHE_ENTRY ) );
  1310. // NOTENOTE: This presumes a predefined context oid constant
  1311. pEntry->pszContextOid = pszContextOid;
  1312. pEntry->pvContext = ObjectContextDuplicate( pszContextOid, pvContext );
  1313. memcpy(pEntry->OriginIdentifier, OriginIdentifier,
  1314. sizeof(pEntry->OriginIdentifier));
  1315. DataBlob.cbData = MD5DIGESTLEN;
  1316. DataBlob.pbData = pEntry->OriginIdentifier;
  1317. fResult = I_CryptCreateLruEntry(
  1318. hCache,
  1319. &DataBlob,
  1320. pEntry,
  1321. &pEntry->hLruEntry
  1322. );
  1323. if ( fResult == TRUE )
  1324. {
  1325. ObjectContextGetNextUpdateUrl(
  1326. pszContextOid,
  1327. pvContext,
  1328. pIssuer,
  1329. pUrlArrayThis->rgwszUrl[UrlIndexThis],
  1330. &pEntry->pUrlArrayNext,
  1331. &pEntry->cbUrlArrayNext,
  1332. &pEntry->UrlIndexNext,
  1333. NULL
  1334. );
  1335. fResult = ObjectContextGetCreateAndExpireTimes(
  1336. pszContextOid,
  1337. pvContext,
  1338. &pEntry->CreateTime,
  1339. &pEntry->ExpireTime
  1340. );
  1341. }
  1342. if ( fResult == TRUE )
  1343. {
  1344. pEntry->cbUrlArrayThis = cbUrlArrayThis;
  1345. pEntry->pUrlArrayThis = pUrlArrayThis;
  1346. pEntry->UrlIndexThis = UrlIndexThis;
  1347. *ppEntry = pEntry;
  1348. }
  1349. else
  1350. {
  1351. ObjectContextFreeTVOCacheEntry( pEntry );
  1352. }
  1353. return( fResult );
  1354. }
  1355. //+---------------------------------------------------------------------------
  1356. //
  1357. // Function: ObjectContextFreeTVOCacheEntry
  1358. //
  1359. // Synopsis: free TVO cache entry
  1360. //
  1361. //----------------------------------------------------------------------------
  1362. VOID WINAPI
  1363. ObjectContextFreeTVOCacheEntry (
  1364. IN PTVO_CACHE_ENTRY pEntry
  1365. )
  1366. {
  1367. if ( pEntry->hLruEntry != NULL )
  1368. {
  1369. I_CryptReleaseLruEntry( pEntry->hLruEntry );
  1370. }
  1371. delete [] (BYTE *) pEntry->pUrlArrayThis;
  1372. delete [] (BYTE *) pEntry->pUrlArrayNext;
  1373. if ( pEntry->pvContext != NULL )
  1374. {
  1375. ObjectContextFree( pEntry->pszContextOid, pEntry->pvContext );
  1376. }
  1377. delete pEntry;
  1378. }
  1379. //+---------------------------------------------------------------------------
  1380. //
  1381. // Function: CertificateGetCrlDistPointUrl
  1382. //
  1383. // Synopsis: get crl dist point URL from certificate
  1384. //
  1385. //----------------------------------------------------------------------------
  1386. BOOL WINAPI
  1387. CertificateGetCrlDistPointUrl (
  1388. IN LPCSTR pszUrlOid,
  1389. IN LPVOID pvPara,
  1390. IN LPWSTR pwszUrlHint,
  1391. OUT PCRYPT_URL_ARRAY* ppUrlArray,
  1392. OUT DWORD* pcbUrlArray,
  1393. OUT DWORD* pPreferredUrlIndex,
  1394. OUT BOOL* pfHintInArray
  1395. )
  1396. {
  1397. BOOL fResult;
  1398. DWORD cbUrlArray;
  1399. PCRYPT_URL_ARRAY pUrlArray = NULL;
  1400. DWORD PreferredUrlIndex;
  1401. fResult = CryptGetObjectUrl(
  1402. pszUrlOid,
  1403. pvPara,
  1404. 0,
  1405. NULL,
  1406. &cbUrlArray,
  1407. NULL,
  1408. NULL,
  1409. NULL
  1410. );
  1411. if ( fResult == TRUE )
  1412. {
  1413. pUrlArray = (PCRYPT_URL_ARRAY)new BYTE [ cbUrlArray ];
  1414. if ( pUrlArray != NULL )
  1415. {
  1416. fResult = CryptGetObjectUrl(
  1417. pszUrlOid,
  1418. pvPara,
  1419. 0,
  1420. pUrlArray,
  1421. &cbUrlArray,
  1422. NULL,
  1423. NULL,
  1424. NULL
  1425. );
  1426. }
  1427. else
  1428. {
  1429. SetLastError( (DWORD) E_OUTOFMEMORY );
  1430. fResult = FALSE;
  1431. }
  1432. }
  1433. if ( fResult == TRUE )
  1434. {
  1435. BOOL fHintInArray = FALSE;
  1436. GetUrlArrayIndex(
  1437. pUrlArray,
  1438. pwszUrlHint,
  1439. 0,
  1440. &PreferredUrlIndex,
  1441. &fHintInArray
  1442. );
  1443. *ppUrlArray = pUrlArray;
  1444. *pcbUrlArray = cbUrlArray;
  1445. if ( pfHintInArray != NULL )
  1446. {
  1447. *pfHintInArray = fHintInArray;
  1448. }
  1449. if ( pPreferredUrlIndex != NULL )
  1450. {
  1451. *pPreferredUrlIndex = PreferredUrlIndex;
  1452. }
  1453. }
  1454. else
  1455. {
  1456. if ( pUrlArray )
  1457. {
  1458. delete [] (BYTE *) pUrlArray;
  1459. }
  1460. }
  1461. return( fResult );
  1462. }
  1463. BOOL WINAPI
  1464. RetrieveObjectByUrlValidForSubject(
  1465. IN LPWSTR pwszUrl,
  1466. IN LPCSTR pszContextOid,
  1467. IN BOOL fCheckFreshnessTime,
  1468. IN LPFILETIME pftValidFor,
  1469. IN DWORD dwRetrievalFlags,
  1470. IN DWORD dwTimeout,
  1471. IN PCRYPT_CREDENTIALS pCredentials,
  1472. IN PCCERT_CONTEXT pSigner,
  1473. IN LPVOID pvSubject,
  1474. IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  1475. OUT LPVOID* ppvObject,
  1476. IN OPTIONAL LPVOID pvReserved
  1477. )
  1478. {
  1479. BOOL fResult;
  1480. HCERTSTORE hUrlStore = NULL;
  1481. LPVOID pvObject;
  1482. fResult = CryptRetrieveObjectByUrlW(
  1483. pwszUrl,
  1484. pszContextOid,
  1485. (dwRetrievalFlags |
  1486. CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
  1487. CRYPT_LDAP_SCOPE_BASE_ONLY_RETRIEVAL) &
  1488. ~CRYPT_VERIFY_CONTEXT_SIGNATURE,
  1489. dwTimeout,
  1490. (LPVOID *) &hUrlStore,
  1491. NULL, // hAsyncRetrieve
  1492. NULL, // pCredentials
  1493. NULL, // pSigner
  1494. NULL // pvReserved
  1495. );
  1496. if (!fResult)
  1497. goto CommonReturn;
  1498. pvObject = NULL;
  1499. while (pvObject = ObjectContextEnumObjectsInStore (
  1500. hUrlStore,
  1501. pszContextOid,
  1502. pvObject
  1503. ))
  1504. {
  1505. CRYPT_ORIGIN_IDENTIFIER ObjectOriginIdentifier;
  1506. if (!ObjectContextGetOriginIdentifier(
  1507. pszContextOid,
  1508. pvObject,
  1509. pSigner,
  1510. 0,
  1511. ObjectOriginIdentifier
  1512. ))
  1513. continue;
  1514. if (0 != memcmp(OriginIdentifier, ObjectOriginIdentifier,
  1515. sizeof(ObjectOriginIdentifier)))
  1516. continue;
  1517. if (dwRetrievalFlags & CRYPT_VERIFY_CONTEXT_SIGNATURE) {
  1518. if (!ObjectContextVerifySignature (
  1519. pszContextOid,
  1520. pvObject,
  1521. pSigner
  1522. ))
  1523. continue;
  1524. }
  1525. if (!ObjectContextIsValidForSubject (
  1526. pszContextOid,
  1527. pvObject,
  1528. pvSubject,
  1529. pvReserved
  1530. ))
  1531. continue;
  1532. if (NULL != pftValidFor) {
  1533. FILETIME CreateTime;
  1534. FILETIME ExpireTime;
  1535. if (!ObjectContextGetCreateAndExpireTimes(
  1536. pszContextOid,
  1537. pvObject,
  1538. &CreateTime,
  1539. &ExpireTime
  1540. ))
  1541. continue;
  1542. if (!IsValidCreateOrExpireTime (
  1543. fCheckFreshnessTime,
  1544. pftValidFor,
  1545. &CreateTime,
  1546. &ExpireTime ) )
  1547. continue;
  1548. }
  1549. *ppvObject = pvObject;
  1550. fResult = TRUE;
  1551. goto CommonReturn;
  1552. }
  1553. // Make sure the error isn't CRYPT_E_NOT_FOUND. msrevoke will
  1554. // return CRYPT_E_NO_REVOCATION_CHECK instead of
  1555. // CRYPT_E_REVOCATION_OFFLINE for CRYPT_E_NOT_FOUND.
  1556. SetLastError(ERROR_FILE_NOT_FOUND);
  1557. fResult = FALSE;
  1558. CommonReturn:
  1559. if (hUrlStore)
  1560. CertCloseStore(hUrlStore, 0);
  1561. return fResult;
  1562. }
  1563. //+---------------------------------------------------------------------------
  1564. //
  1565. // Function: RetrieveTimeValidObjectByUrl
  1566. //
  1567. // Synopsis: retrieve a time valid object given an URL
  1568. //
  1569. //----------------------------------------------------------------------------
  1570. BOOL WINAPI
  1571. RetrieveTimeValidObjectByUrl (
  1572. IN LPWSTR pwszUrl,
  1573. IN LPCSTR pszContextOid,
  1574. IN LPFILETIME pftValidFor,
  1575. IN DWORD dwFlags,
  1576. IN DWORD dwTimeout,
  1577. IN PCRYPT_CREDENTIALS pCredentials,
  1578. IN PCCERT_CONTEXT pSigner,
  1579. IN LPVOID pvSubject,
  1580. IN CRYPT_ORIGIN_IDENTIFIER OriginIdentifier,
  1581. OUT LPVOID* ppvObject,
  1582. IN OPTIONAL LPVOID pvReserved
  1583. )
  1584. {
  1585. BOOL fResult = FALSE;
  1586. LPVOID pvContext = NULL;
  1587. DWORD dwVerifyFlags = 0;
  1588. DWORD dwCacheStoreFlags = CRYPT_DONT_CACHE_RESULT;
  1589. if ( dwFlags & CRYPT_DONT_CHECK_TIME_VALIDITY )
  1590. {
  1591. pftValidFor = NULL;
  1592. }
  1593. if ( !( dwFlags & CRYPT_DONT_VERIFY_SIGNATURE ) )
  1594. {
  1595. dwVerifyFlags |= CRYPT_VERIFY_CONTEXT_SIGNATURE;
  1596. dwCacheStoreFlags &= ~CRYPT_DONT_CACHE_RESULT;
  1597. }
  1598. if ( !( dwFlags & CRYPT_WIRE_ONLY_RETRIEVAL ) )
  1599. {
  1600. fResult = RetrieveObjectByUrlValidForSubject(
  1601. pwszUrl,
  1602. pszContextOid,
  1603. 0 != (dwFlags & CRYPT_CHECK_FRESHNESS_TIME_VALIDITY),
  1604. pftValidFor,
  1605. CRYPT_CACHE_ONLY_RETRIEVAL |
  1606. dwVerifyFlags,
  1607. 0, // dwTimeout
  1608. NULL, // pCredentials
  1609. pSigner,
  1610. pvSubject,
  1611. OriginIdentifier,
  1612. &pvContext,
  1613. pvReserved
  1614. );
  1615. }
  1616. if ( fResult == FALSE )
  1617. {
  1618. if ( !( dwFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
  1619. {
  1620. DWORD dwRetrievalFlags = CRYPT_WIRE_ONLY_RETRIEVAL |
  1621. dwCacheStoreFlags |
  1622. dwVerifyFlags;
  1623. LONG lStatus;
  1624. // +1 - Online
  1625. // 0 - Offline, current time >= earliest online time, hit the wire
  1626. // -1 - Offline, current time < earliest onlime time
  1627. lStatus = GetOriginUrlStatusW(
  1628. OriginIdentifier,
  1629. pwszUrl,
  1630. pszContextOid,
  1631. dwRetrievalFlags
  1632. );
  1633. if (lStatus >= 0)
  1634. {
  1635. fResult = RetrieveObjectByUrlValidForSubject(
  1636. pwszUrl,
  1637. pszContextOid,
  1638. 0 != (dwFlags & CRYPT_CHECK_FRESHNESS_TIME_VALIDITY),
  1639. pftValidFor,
  1640. dwRetrievalFlags,
  1641. dwTimeout,
  1642. pCredentials,
  1643. pSigner,
  1644. pvSubject,
  1645. OriginIdentifier,
  1646. &pvContext,
  1647. pvReserved
  1648. );
  1649. if (!fResult)
  1650. {
  1651. DWORD dwErr = GetLastError();
  1652. SetOfflineOriginUrlW(
  1653. OriginIdentifier,
  1654. pwszUrl,
  1655. pszContextOid,
  1656. dwRetrievalFlags
  1657. );
  1658. SetLastError( dwErr );
  1659. }
  1660. else if (lStatus == 0)
  1661. {
  1662. // Remove from offline list
  1663. SetOnlineOriginUrlW(
  1664. OriginIdentifier,
  1665. pwszUrl,
  1666. pszContextOid,
  1667. dwRetrievalFlags
  1668. );
  1669. }
  1670. }
  1671. }
  1672. }
  1673. *ppvObject = pvContext;
  1674. return( fResult );
  1675. }
  1676. //+---------------------------------------------------------------------------
  1677. //
  1678. // Function: CreateProcessTVOAgent
  1679. //
  1680. // Synopsis: create process TVO agent
  1681. //
  1682. //----------------------------------------------------------------------------
  1683. BOOL WINAPI
  1684. CreateProcessTVOAgent (
  1685. OUT CTVOAgent** ppAgent
  1686. )
  1687. {
  1688. BOOL fResult = FALSE;
  1689. HKEY hKey = NULL;
  1690. DWORD dwType = REG_DWORD;
  1691. DWORD dwSize = sizeof( DWORD );
  1692. DWORD cCacheBuckets;
  1693. DWORD MaxCacheEntries;
  1694. CTVOAgent* pAgent;
  1695. if ( RegOpenKeyA(
  1696. HKEY_LOCAL_MACHINE,
  1697. TVO_KEY_NAME,
  1698. &hKey
  1699. ) == ERROR_SUCCESS )
  1700. {
  1701. if ( RegQueryValueExA(
  1702. hKey,
  1703. TVO_CACHE_BUCKETS_VALUE_NAME,
  1704. NULL,
  1705. &dwType,
  1706. (LPBYTE)&cCacheBuckets,
  1707. &dwSize
  1708. ) != ERROR_SUCCESS )
  1709. {
  1710. cCacheBuckets = TVO_DEFAULT_CACHE_BUCKETS;
  1711. }
  1712. if ( RegQueryValueExA(
  1713. hKey,
  1714. TVO_MAX_CACHE_ENTRIES_VALUE_NAME,
  1715. NULL,
  1716. &dwType,
  1717. (LPBYTE)&MaxCacheEntries,
  1718. &dwSize
  1719. ) != ERROR_SUCCESS )
  1720. {
  1721. MaxCacheEntries = TVO_DEFAULT_MAX_CACHE_ENTRIES;
  1722. }
  1723. RegCloseKey(hKey);
  1724. }
  1725. else
  1726. {
  1727. cCacheBuckets = TVO_DEFAULT_CACHE_BUCKETS;
  1728. MaxCacheEntries = TVO_DEFAULT_MAX_CACHE_ENTRIES;
  1729. }
  1730. pAgent = new CTVOAgent( cCacheBuckets, MaxCacheEntries, fResult );
  1731. if ( pAgent == NULL )
  1732. {
  1733. SetLastError( (DWORD) E_OUTOFMEMORY );
  1734. return( FALSE );
  1735. }
  1736. if ( fResult == TRUE )
  1737. {
  1738. *ppAgent = pAgent;
  1739. }
  1740. else
  1741. {
  1742. delete pAgent;
  1743. }
  1744. return( fResult );
  1745. }