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.

1577 lines
44 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: ssctl.cpp
  7. //
  8. // Contents: Self Signed Certificate Trust List Subsystem used by the
  9. // Certificate Chaining Infrastructure for building complex
  10. // chains
  11. //
  12. // History: 11-Feb-98 kirtd Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <global.hxx>
  16. #include <dbgdef.h>
  17. //+-------------------------------------------------------------------------
  18. // Attempt to get and allocate the CTL NextUpdate location Url array.
  19. //--------------------------------------------------------------------------
  20. BOOL
  21. WINAPI
  22. SSCtlGetNextUpdateUrl(
  23. IN PCCTL_CONTEXT pCtl,
  24. OUT PCRYPT_URL_ARRAY *ppUrlArray
  25. )
  26. {
  27. #if 1
  28. // On 03-May-02 REMOVE_CTL_UPDATE_SUPPORT
  29. *ppUrlArray = NULL;
  30. SetLastError((DWORD) CRYPT_E_NOT_FOUND);
  31. return FALSE;
  32. #else
  33. BOOL fResult;
  34. PCRYPT_URL_ARRAY pUrlArray = NULL;
  35. DWORD cbUrlArray = 0;
  36. LPVOID apv[2];
  37. apv[0] = (LPVOID) pCtl;
  38. apv[1] = (LPVOID)(UINT_PTR)(0); // Signer Index
  39. if (!ChainGetObjectUrl(
  40. URL_OID_CTL_NEXT_UPDATE,
  41. apv,
  42. 0, // dwFlags
  43. NULL, // pUrlArray
  44. &cbUrlArray,
  45. NULL, // pUrlInfo
  46. NULL, // cbUrlInfo,
  47. NULL // pvReserved
  48. ))
  49. goto GetObjectUrlError;
  50. pUrlArray = (PCRYPT_URL_ARRAY) new BYTE [cbUrlArray];
  51. if (NULL == pUrlArray)
  52. goto OutOfMemory;
  53. if (!ChainGetObjectUrl(
  54. URL_OID_CTL_NEXT_UPDATE,
  55. apv,
  56. 0, // dwFlags
  57. pUrlArray,
  58. &cbUrlArray,
  59. NULL, // pUrlInfo
  60. NULL, // cbUrlInfo,
  61. NULL // pvReserved
  62. ))
  63. goto GetObjectUrlError;
  64. if (0 == pUrlArray->cUrl)
  65. goto NoNextUpdateUrls;
  66. fResult = TRUE;
  67. CommonReturn:
  68. *ppUrlArray = pUrlArray;
  69. return fResult;
  70. ErrorReturn:
  71. if (pUrlArray) {
  72. delete (LPBYTE) pUrlArray;
  73. pUrlArray = NULL;
  74. }
  75. fResult = FALSE;
  76. goto CommonReturn;
  77. TRACE_ERROR(GetObjectUrlError)
  78. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  79. SET_ERROR(NoNextUpdateUrls, CRYPT_E_NOT_FOUND)
  80. #endif
  81. }
  82. //+---------------------------------------------------------------------------
  83. //
  84. // Member: CSSCtlObject::CSSCtlObject, public
  85. //
  86. // Synopsis: Constructor
  87. //
  88. //----------------------------------------------------------------------------
  89. CSSCtlObject::CSSCtlObject (
  90. IN PCCERTCHAINENGINE pChainEngine,
  91. IN PCCTL_CONTEXT pCtlContext,
  92. IN BOOL fAdditionalStore,
  93. OUT BOOL& rfResult
  94. )
  95. {
  96. DWORD cbData;
  97. CRYPT_DATA_BLOB DataBlob;
  98. rfResult = TRUE;
  99. m_cRefs = 1;
  100. m_pCtlContext = CertDuplicateCTLContext( pCtlContext );
  101. m_fHasSignatureBeenVerified = FALSE;
  102. m_fSignatureValid = FALSE;
  103. m_hMessageStore = NULL;
  104. m_hHashEntry = NULL;
  105. m_pChainEngine = pChainEngine;
  106. m_pNextUpdateUrlArray = NULL;
  107. m_dwOfflineCnt = 0;
  108. I_CryptZeroFileTime(&m_OfflineUpdateTime);
  109. memset( &m_SignerInfo, 0, sizeof( m_SignerInfo ) );
  110. cbData = CHAINHASHLEN;
  111. rfResult = CertGetCTLContextProperty(
  112. pCtlContext,
  113. CERT_MD5_HASH_PROP_ID,
  114. m_rgbCtlHash,
  115. &cbData
  116. );
  117. if ( rfResult && CHAINHASHLEN != cbData)
  118. {
  119. rfResult = FALSE;
  120. SetLastError( (DWORD) E_UNEXPECTED);
  121. }
  122. if (!fAdditionalStore)
  123. {
  124. if ( rfResult == TRUE )
  125. {
  126. DataBlob.cbData = CHAINHASHLEN;
  127. DataBlob.pbData = m_rgbCtlHash;
  128. rfResult = I_CryptCreateLruEntry(
  129. pChainEngine->SSCtlObjectCache()->HashIndex(),
  130. &DataBlob,
  131. this,
  132. &m_hHashEntry
  133. );
  134. }
  135. if ( rfResult == TRUE )
  136. {
  137. m_hMessageStore = CertOpenStore(
  138. CERT_STORE_PROV_MSG,
  139. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  140. NULL,
  141. 0,
  142. pCtlContext->hCryptMsg
  143. );
  144. if ( m_hMessageStore == NULL )
  145. {
  146. rfResult = FALSE;
  147. }
  148. }
  149. }
  150. if ( rfResult == TRUE )
  151. {
  152. rfResult = SSCtlGetSignerInfo( pCtlContext, &m_SignerInfo );
  153. }
  154. #if 0
  155. // On 03-May-02 REMOVE_CTL_UPDATE_SUPPORT
  156. if (!fAdditionalStore)
  157. {
  158. if ( rfResult == TRUE )
  159. {
  160. if (!I_CryptIsZeroFileTime(&m_pCtlContext->pCtlInfo->NextUpdate))
  161. {
  162. // Ignore any errors
  163. SSCtlGetNextUpdateUrl(m_pCtlContext, &m_pNextUpdateUrlArray);
  164. }
  165. }
  166. }
  167. #endif
  168. assert( m_pChainEngine != NULL );
  169. assert( m_pCtlContext != NULL );
  170. }
  171. //+---------------------------------------------------------------------------
  172. //
  173. // Member: CSSCtlObject::~CSSCtlObject, public
  174. //
  175. // Synopsis: Destructor
  176. //
  177. //----------------------------------------------------------------------------
  178. CSSCtlObject::~CSSCtlObject ()
  179. {
  180. SSCtlFreeSignerInfo( &m_SignerInfo );
  181. if ( m_hMessageStore != NULL )
  182. {
  183. CertCloseStore( m_hMessageStore, 0 );
  184. }
  185. if ( m_pNextUpdateUrlArray != NULL )
  186. {
  187. delete (LPBYTE) m_pNextUpdateUrlArray;
  188. }
  189. if ( m_hHashEntry != NULL )
  190. {
  191. I_CryptReleaseLruEntry( m_hHashEntry );
  192. }
  193. CertFreeCTLContext( m_pCtlContext );
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Member: CSSCtlObject::GetSigner, public
  198. //
  199. // Synopsis: get the certificate object of the signer
  200. //
  201. //----------------------------------------------------------------------------
  202. BOOL
  203. CSSCtlObject::GetSigner (
  204. IN PCCHAINPATHOBJECT pSubject,
  205. IN PCCHAINCALLCONTEXT pCallContext,
  206. IN HCERTSTORE hAdditionalStore,
  207. OUT PCCHAINPATHOBJECT* ppSigner,
  208. OUT BOOL* pfCtlSignatureValid
  209. )
  210. {
  211. BOOL fResult;
  212. PCCHAINPATHOBJECT pSigner = NULL;
  213. BOOL fNewSigner = TRUE;
  214. fResult = SSCtlGetSignerChainPathObject(
  215. pSubject,
  216. pCallContext,
  217. &m_SignerInfo,
  218. hAdditionalStore,
  219. &pSigner,
  220. &fNewSigner
  221. );
  222. if (fResult)
  223. {
  224. if ( !m_fHasSignatureBeenVerified || fNewSigner )
  225. {
  226. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA CtrlPara;
  227. memset(&CtrlPara, 0, sizeof(CtrlPara));
  228. CtrlPara.cbSize = sizeof(CtrlPara);
  229. // CtrlPara.hCryptProv =
  230. // This needs to be updated when chain building
  231. // supports CTLs with more than one signer.
  232. CtrlPara.dwSignerIndex = 0;
  233. CtrlPara.dwSignerType = CMSG_VERIFY_SIGNER_CERT;
  234. CtrlPara.pvSigner = (void *) pSigner->CertObject()->CertContext();
  235. m_fSignatureValid = CryptMsgControl(
  236. m_pCtlContext->hCryptMsg,
  237. 0,
  238. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  239. &CtrlPara
  240. );
  241. m_fHasSignatureBeenVerified = TRUE;
  242. CertPerfIncrementChainVerifyCtlSignatureCount();
  243. }
  244. else
  245. {
  246. CertPerfIncrementChainBeenVerifiedCtlSignatureCount();
  247. }
  248. *ppSigner = pSigner;
  249. }
  250. *pfCtlSignatureValid = m_fSignatureValid;
  251. return fResult;
  252. }
  253. //+---------------------------------------------------------------------------
  254. //
  255. // Member: CSSCtlObject::GetTrustListInfo, public
  256. //
  257. // Synopsis: get the trust list information relative to a particular cert
  258. // object
  259. //
  260. //----------------------------------------------------------------------------
  261. BOOL
  262. CSSCtlObject::GetTrustListInfo (
  263. IN PCCERT_CONTEXT pCertContext,
  264. OUT PCERT_TRUST_LIST_INFO* ppTrustListInfo
  265. )
  266. {
  267. PCTL_ENTRY pCtlEntry;
  268. PCERT_TRUST_LIST_INFO pTrustListInfo;
  269. pCtlEntry = CertFindSubjectInCTL(
  270. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  271. CTL_CERT_SUBJECT_TYPE,
  272. (LPVOID)pCertContext,
  273. m_pCtlContext,
  274. 0
  275. );
  276. if ( pCtlEntry == NULL )
  277. {
  278. SetLastError( (DWORD) CRYPT_E_NOT_FOUND );
  279. return( FALSE );
  280. }
  281. pTrustListInfo = new CERT_TRUST_LIST_INFO;
  282. if ( pTrustListInfo == NULL )
  283. {
  284. SetLastError( (DWORD) E_OUTOFMEMORY );
  285. return( FALSE );
  286. }
  287. pTrustListInfo->cbSize = sizeof( CERT_TRUST_LIST_INFO );
  288. pTrustListInfo->pCtlEntry = pCtlEntry;
  289. pTrustListInfo->pCtlContext = CertDuplicateCTLContext( m_pCtlContext );
  290. *ppTrustListInfo = pTrustListInfo;
  291. return( TRUE );
  292. }
  293. //+---------------------------------------------------------------------------
  294. //
  295. // Member: CSSCtlObject::CalculateStatus, public
  296. //
  297. // Synopsis: calculate the status
  298. //
  299. //----------------------------------------------------------------------------
  300. VOID
  301. CSSCtlObject::CalculateStatus (
  302. IN LPFILETIME pTime,
  303. IN PCERT_USAGE_MATCH pRequestedUsage,
  304. IN OUT PCERT_TRUST_STATUS pStatus
  305. )
  306. {
  307. assert( m_fHasSignatureBeenVerified == TRUE );
  308. SSCtlGetCtlTrustStatus(
  309. m_pCtlContext,
  310. m_fSignatureValid,
  311. pTime,
  312. pRequestedUsage,
  313. pStatus
  314. );
  315. }
  316. //+---------------------------------------------------------------------------
  317. //
  318. // Member: CSSCtlObject::HasNextUpdateUrl, public
  319. //
  320. // Synopsis: returns TRUE if the Ctl has a NextUpdate time and location Url
  321. //
  322. //----------------------------------------------------------------------------
  323. BOOL CSSCtlObject::HasNextUpdateUrl (
  324. OUT LPFILETIME pUpdateTime
  325. )
  326. {
  327. #if 1
  328. // On 03-May-02 REMOVE_CTL_UPDATE_SUPPORT
  329. return FALSE;
  330. #else
  331. if ( m_pNextUpdateUrlArray != NULL )
  332. {
  333. assert(!I_CryptIsZeroFileTime(&m_pCtlContext->pCtlInfo->NextUpdate));
  334. if (0 != m_dwOfflineCnt) {
  335. assert(!I_CryptIsZeroFileTime(&m_OfflineUpdateTime));
  336. *pUpdateTime = m_OfflineUpdateTime;
  337. } else
  338. *pUpdateTime = m_pCtlContext->pCtlInfo->NextUpdate;
  339. return TRUE;
  340. }
  341. else
  342. {
  343. return FALSE;
  344. }
  345. #endif
  346. }
  347. //+---------------------------------------------------------------------------
  348. //
  349. // Member: CSSCtlObject::SetOffline, public
  350. //
  351. // Synopsis: called when offline
  352. //
  353. //----------------------------------------------------------------------------
  354. void CSSCtlObject::SetOffline (
  355. IN LPFILETIME pCurrentTime,
  356. OUT LPFILETIME pUpdateTime
  357. )
  358. {
  359. m_dwOfflineCnt++;
  360. I_CryptIncrementFileTimeBySeconds(
  361. pCurrentTime,
  362. ChainGetOfflineUrlDeltaSeconds(m_dwOfflineCnt),
  363. &m_OfflineUpdateTime
  364. );
  365. *pUpdateTime = m_OfflineUpdateTime;
  366. }
  367. //+---------------------------------------------------------------------------
  368. //
  369. // Member: CSSCtlObjectCache::CSSCtlObjectCache, public
  370. //
  371. // Synopsis: Constructor
  372. //
  373. //----------------------------------------------------------------------------
  374. CSSCtlObjectCache::CSSCtlObjectCache (
  375. OUT BOOL& rfResult
  376. )
  377. {
  378. LRU_CACHE_CONFIG Config;
  379. memset( &Config, 0, sizeof( Config ) );
  380. Config.dwFlags = LRU_CACHE_NO_SERIALIZE | LRU_CACHE_NO_COPY_IDENTIFIER;
  381. Config.pfnHash = CertObjectCacheHashMd5Identifier;
  382. Config.cBuckets = DEFAULT_CERT_OBJECT_CACHE_BUCKETS;
  383. Config.pfnOnRemoval = SSCtlOnRemovalFromCache;
  384. m_hHashIndex = NULL;
  385. rfResult = I_CryptCreateLruCache( &Config, &m_hHashIndex );
  386. I_CryptZeroFileTime(&m_UpdateTime);
  387. m_fFirstUpdate = FALSE;
  388. }
  389. //+---------------------------------------------------------------------------
  390. //
  391. // Member: CSSCtlObjectCache::~CSSCtlObjectCache, public
  392. //
  393. // Synopsis: Destructor
  394. //
  395. //----------------------------------------------------------------------------
  396. CSSCtlObjectCache::~CSSCtlObjectCache ()
  397. {
  398. I_CryptFreeLruCache( m_hHashIndex, 0, NULL );
  399. }
  400. //+---------------------------------------------------------------------------
  401. //
  402. // Member: CSSCtlObjectCache::PopulateCache, public
  403. //
  404. // Synopsis: populate the cache
  405. //
  406. //----------------------------------------------------------------------------
  407. BOOL
  408. CSSCtlObjectCache::PopulateCache (
  409. IN PCCERTCHAINENGINE pChainEngine
  410. )
  411. {
  412. assert( pChainEngine->SSCtlObjectCache() == this );
  413. return( SSCtlPopulateCacheFromCertStore( pChainEngine, NULL ) );
  414. }
  415. //+---------------------------------------------------------------------------
  416. //
  417. // Member: CSSCtlObjectCache::AddObject, public
  418. //
  419. // Synopsis: add an object to the cache
  420. //
  421. //----------------------------------------------------------------------------
  422. BOOL
  423. CSSCtlObjectCache::AddObject (
  424. IN PCSSCTLOBJECT pSSCtlObject,
  425. IN BOOL fCheckForDuplicate
  426. )
  427. {
  428. FILETIME UpdateTime;
  429. if ( fCheckForDuplicate == TRUE )
  430. {
  431. PCSSCTLOBJECT pDuplicate;
  432. pDuplicate = FindObjectByHash( pSSCtlObject->CtlHash() );
  433. if ( pDuplicate != NULL )
  434. {
  435. pDuplicate->Release();
  436. SetLastError( (DWORD) CRYPT_E_EXISTS );
  437. return( FALSE );
  438. }
  439. }
  440. pSSCtlObject->AddRef();
  441. if (pSSCtlObject->HasNextUpdateUrl(&UpdateTime))
  442. {
  443. // Set earliest update time
  444. if (I_CryptIsZeroFileTime(&m_UpdateTime) ||
  445. 0 > CompareFileTime(&UpdateTime, &m_UpdateTime))
  446. {
  447. m_UpdateTime = UpdateTime;
  448. }
  449. m_fFirstUpdate = TRUE;
  450. }
  451. I_CryptInsertLruEntry( pSSCtlObject->HashIndexEntry(), NULL );
  452. if (pSSCtlObject->MessageStore() )
  453. {
  454. CertAddStoreToCollection(
  455. pSSCtlObject->ChainEngine()->OtherStore(),
  456. pSSCtlObject->MessageStore(),
  457. 0,
  458. 0
  459. );
  460. }
  461. CertPerfIncrementChainCtlCacheCount();
  462. return( TRUE );
  463. }
  464. //+---------------------------------------------------------------------------
  465. //
  466. // Member: CSSCtlObjectCache::RemoveObject, public
  467. //
  468. // Synopsis: remove object from cache
  469. //
  470. //----------------------------------------------------------------------------
  471. VOID
  472. CSSCtlObjectCache::RemoveObject (
  473. IN PCSSCTLOBJECT pSSCtlObject
  474. )
  475. {
  476. I_CryptRemoveLruEntry( pSSCtlObject->HashIndexEntry(), 0, NULL );
  477. }
  478. //+---------------------------------------------------------------------------
  479. //
  480. // Member: CSSCtlObjectCache::FindObjectByHash, public
  481. //
  482. // Synopsis: find object with given hash
  483. //
  484. //----------------------------------------------------------------------------
  485. PCSSCTLOBJECT
  486. CSSCtlObjectCache::FindObjectByHash (
  487. IN BYTE rgbHash [ CHAINHASHLEN ]
  488. )
  489. {
  490. HLRUENTRY hFound;
  491. PCSSCTLOBJECT pFound = NULL;
  492. CRYPT_HASH_BLOB HashBlob;
  493. HashBlob.cbData = CHAINHASHLEN;
  494. HashBlob.pbData = rgbHash;
  495. hFound = I_CryptFindLruEntry( m_hHashIndex, &HashBlob );
  496. if ( hFound != NULL )
  497. {
  498. pFound = (PCSSCTLOBJECT)I_CryptGetLruEntryData( hFound );
  499. pFound->AddRef();
  500. I_CryptReleaseLruEntry( hFound );
  501. }
  502. return( pFound );
  503. }
  504. //+---------------------------------------------------------------------------
  505. //
  506. // Member: CSSCtlObjectCache::EnumObjects, public
  507. //
  508. // Synopsis: enumerate objects
  509. //
  510. //----------------------------------------------------------------------------
  511. VOID
  512. CSSCtlObjectCache::EnumObjects (
  513. IN PFN_ENUM_SSCTLOBJECTS pfnEnum,
  514. IN LPVOID pvParameter
  515. )
  516. {
  517. SSCTL_ENUM_OBJECTS_DATA EnumData;
  518. EnumData.pfnEnumObjects = pfnEnum;
  519. EnumData.pvEnumParameter = pvParameter;
  520. I_CryptWalkAllLruCacheEntries(
  521. m_hHashIndex,
  522. SSCtlEnumObjectsWalkFn,
  523. &EnumData
  524. );
  525. }
  526. //+---------------------------------------------------------------------------
  527. //
  528. // Member: CSSCtlObjectCache::Resync, public
  529. //
  530. // Synopsis: resync the cache
  531. //
  532. //----------------------------------------------------------------------------
  533. BOOL
  534. CSSCtlObjectCache::Resync (IN PCCERTCHAINENGINE pChainEngine)
  535. {
  536. I_CryptFlushLruCache( m_hHashIndex, 0, NULL );
  537. I_CryptZeroFileTime(&m_UpdateTime);
  538. m_fFirstUpdate = FALSE;
  539. return( PopulateCache( pChainEngine ) );
  540. }
  541. //+---------------------------------------------------------------------------
  542. //
  543. // Member: CSSCtlObjectCache::UpdateCache, public
  544. //
  545. // Synopsis: update the cache
  546. //
  547. // Leaves the engine's critical section to do the URL
  548. // fetching. If the engine was touched by another thread,
  549. // it fails with LastError set to ERROR_CAN_NOT_COMPLETE.
  550. //
  551. // If the CTL is updated, increments the engine's touch count
  552. // and flushes issuer and end cert object caches.
  553. //
  554. // Assumption: Chain engine is locked once in the calling thread.
  555. //
  556. //----------------------------------------------------------------------------
  557. BOOL
  558. CSSCtlObjectCache::UpdateCache (
  559. IN PCCERTCHAINENGINE pChainEngine,
  560. IN PCCHAINCALLCONTEXT pCallContext
  561. )
  562. {
  563. #if 1
  564. // On 03-May-02 REMOVE_CTL_UPDATE_SUPPORT
  565. return TRUE;
  566. #else
  567. FILETIME CurrentTime;
  568. SSCTL_UPDATE_CTL_OBJ_PARA Para;
  569. assert( pChainEngine->SSCtlObjectCache() == this );
  570. // Check if we have any CTLs needing to be updated
  571. if (I_CryptIsZeroFileTime(&m_UpdateTime))
  572. return TRUE;
  573. pCallContext->CurrentTime(&CurrentTime);
  574. if (0 < CompareFileTime(&m_UpdateTime, &CurrentTime))
  575. return TRUE;
  576. if (!m_fFirstUpdate && !pCallContext->IsOnline())
  577. return TRUE;
  578. memset(&Para, 0, sizeof(Para));
  579. Para.pChainEngine = pChainEngine;
  580. Para.pCallContext = pCallContext;
  581. EnumObjects(SSCtlUpdateCtlObjectEnumFn, &Para);
  582. if (pCallContext->IsTouchedEngine()) {
  583. PSSCTL_UPDATE_CTL_OBJ_ENTRY pEntry;
  584. pEntry = Para.pEntry;
  585. while (pEntry) {
  586. PSSCTL_UPDATE_CTL_OBJ_ENTRY pDeleteEntry;
  587. pEntry->pSSCtlObjectAdd->Release();
  588. pDeleteEntry = pEntry;
  589. pEntry = pEntry->pNext;
  590. delete pDeleteEntry;
  591. }
  592. return FALSE;
  593. }
  594. m_UpdateTime = Para.UpdateTime;
  595. m_fFirstUpdate = FALSE;
  596. if (Para.pEntry) {
  597. HCERTSTORE hTrustStore;
  598. PSSCTL_UPDATE_CTL_OBJ_ENTRY pEntry;
  599. hTrustStore = pChainEngine->OpenTrustStore();
  600. pChainEngine->CertObjectCache()->FlushObjects( pCallContext );
  601. pCallContext->TouchEngine();
  602. pEntry = Para.pEntry;
  603. while (pEntry) {
  604. PSSCTL_UPDATE_CTL_OBJ_ENTRY pDeleteEntry;
  605. RemoveObject(pEntry->pSSCtlObjectRemove);
  606. if (AddObject(pEntry->pSSCtlObjectAdd, TRUE)) {
  607. if (hTrustStore) {
  608. // Persist the newer CTL to the trust store
  609. CertAddCTLContextToStore(
  610. hTrustStore,
  611. pEntry->pSSCtlObjectAdd->CtlContext(),
  612. CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES,
  613. NULL
  614. );
  615. }
  616. }
  617. pEntry->pSSCtlObjectAdd->Release();
  618. pDeleteEntry = pEntry;
  619. pEntry = pEntry->pNext;
  620. delete pDeleteEntry;
  621. }
  622. if (hTrustStore)
  623. CertCloseStore(hTrustStore, 0);
  624. }
  625. return TRUE;
  626. #endif
  627. }
  628. //+---------------------------------------------------------------------------
  629. //
  630. // Function: SSCtlOnRemovalFromCache
  631. //
  632. // Synopsis: SS CTL removal notification used when the cache is destroyed
  633. // or an object is explicitly removed. Note that this cache
  634. // does not LRU remove objects
  635. //
  636. //----------------------------------------------------------------------------
  637. VOID WINAPI
  638. SSCtlOnRemovalFromCache (
  639. IN LPVOID pv,
  640. IN OPTIONAL LPVOID pvRemovalContext
  641. )
  642. {
  643. PCSSCTLOBJECT pSSCtlObject = (PCSSCTLOBJECT) pv;
  644. CertPerfDecrementChainCtlCacheCount();
  645. assert( pvRemovalContext == NULL );
  646. if (pSSCtlObject->MessageStore() )
  647. {
  648. CertRemoveStoreFromCollection(
  649. pSSCtlObject->ChainEngine()->OtherStore(),
  650. pSSCtlObject->MessageStore()
  651. );
  652. }
  653. pSSCtlObject->Release();
  654. }
  655. //+---------------------------------------------------------------------------
  656. //
  657. // Function: SSCtlGetSignerInfo
  658. //
  659. // Synopsis: get the signer info
  660. //
  661. //----------------------------------------------------------------------------
  662. BOOL WINAPI
  663. SSCtlGetSignerInfo (
  664. IN PCCTL_CONTEXT pCtlContext,
  665. OUT PSSCTL_SIGNER_INFO pSignerInfo
  666. )
  667. {
  668. BOOL fResult;
  669. PCERT_INFO pMessageSignerCertInfo = NULL;
  670. DWORD cbData = 0;
  671. fResult = CryptMsgGetParam(
  672. pCtlContext->hCryptMsg,
  673. CMSG_SIGNER_CERT_INFO_PARAM,
  674. 0,
  675. NULL,
  676. &cbData
  677. );
  678. if ( fResult == TRUE )
  679. {
  680. pMessageSignerCertInfo = (PCERT_INFO)new BYTE [ cbData ];
  681. if ( pMessageSignerCertInfo != NULL )
  682. {
  683. fResult = CryptMsgGetParam(
  684. pCtlContext->hCryptMsg,
  685. CMSG_SIGNER_CERT_INFO_PARAM,
  686. 0,
  687. pMessageSignerCertInfo,
  688. &cbData
  689. );
  690. }
  691. else
  692. {
  693. SetLastError( (DWORD) E_OUTOFMEMORY );
  694. fResult = FALSE;
  695. }
  696. }
  697. if ( fResult == TRUE )
  698. {
  699. pSignerInfo->pMessageSignerCertInfo = pMessageSignerCertInfo;
  700. pSignerInfo->fSignerHashAvailable = FALSE;
  701. }
  702. else
  703. {
  704. delete pMessageSignerCertInfo;
  705. }
  706. return( fResult );
  707. }
  708. //+---------------------------------------------------------------------------
  709. //
  710. // Function: SSCtlFreeSignerInfo
  711. //
  712. // Synopsis: free the data in the signer info
  713. //
  714. //----------------------------------------------------------------------------
  715. VOID WINAPI
  716. SSCtlFreeSignerInfo (
  717. IN PSSCTL_SIGNER_INFO pSignerInfo
  718. )
  719. {
  720. delete (LPBYTE)pSignerInfo->pMessageSignerCertInfo;
  721. }
  722. //+---------------------------------------------------------------------------
  723. //
  724. // Function: SSCtlGetSignerChainPathObject
  725. //
  726. // Synopsis: get the signer chain path object
  727. //
  728. //----------------------------------------------------------------------------
  729. BOOL WINAPI
  730. SSCtlGetSignerChainPathObject (
  731. IN PCCHAINPATHOBJECT pSubject,
  732. IN PCCHAINCALLCONTEXT pCallContext,
  733. IN PSSCTL_SIGNER_INFO pSignerInfo,
  734. IN HCERTSTORE hAdditionalStore,
  735. OUT PCCHAINPATHOBJECT* ppSigner,
  736. OUT BOOL *pfNewSigner
  737. )
  738. {
  739. BOOL fResult = TRUE;
  740. PCCERTCHAINENGINE pChainEngine = pSubject->CertObject()->ChainEngine();
  741. PCCERTOBJECTCACHE pCertObjectCache = pChainEngine->CertObjectCache();
  742. PCCERTOBJECT pCertObject = NULL;
  743. PCCERT_CONTEXT pCertContext = NULL;
  744. PCCHAINPATHOBJECT pSigner = NULL;
  745. BOOL fAdditionalStoreUsed = FALSE;
  746. BYTE rgbCertHash[ CHAINHASHLEN ];
  747. *pfNewSigner = FALSE;
  748. if ( pSignerInfo->fSignerHashAvailable == TRUE )
  749. {
  750. pCertObject = pCertObjectCache->FindIssuerObjectByHash(
  751. pSignerInfo->rgbSignerCertHash );
  752. }
  753. if ( pCertObject == NULL )
  754. {
  755. if ( pSignerInfo->fSignerHashAvailable == TRUE )
  756. {
  757. pCertContext = SSCtlFindCertificateInStoreByHash(
  758. pChainEngine->OtherStore(),
  759. pSignerInfo->rgbSignerCertHash
  760. );
  761. if ( ( pCertContext == NULL ) && ( hAdditionalStore != NULL ) )
  762. {
  763. fAdditionalStoreUsed = TRUE;
  764. pCertContext = SSCtlFindCertificateInStoreByHash(
  765. hAdditionalStore,
  766. pSignerInfo->rgbSignerCertHash
  767. );
  768. }
  769. }
  770. if ( pCertContext == NULL )
  771. {
  772. *pfNewSigner = TRUE;
  773. fAdditionalStoreUsed = FALSE;
  774. pCertContext = CertGetSubjectCertificateFromStore(
  775. pChainEngine->OtherStore(),
  776. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  777. pSignerInfo->pMessageSignerCertInfo
  778. );
  779. }
  780. if ( ( pCertContext == NULL ) && ( hAdditionalStore != NULL ) )
  781. {
  782. fAdditionalStoreUsed = TRUE;
  783. pCertContext = CertGetSubjectCertificateFromStore(
  784. hAdditionalStore,
  785. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  786. pSignerInfo->pMessageSignerCertInfo
  787. );
  788. }
  789. if ( pCertContext != NULL )
  790. {
  791. DWORD cbData = CHAINHASHLEN;
  792. fResult = CertGetCertificateContextProperty(
  793. pCertContext,
  794. CERT_MD5_HASH_PROP_ID,
  795. rgbCertHash,
  796. &cbData
  797. );
  798. if ( fResult && CHAINHASHLEN != cbData)
  799. {
  800. fResult = FALSE;
  801. SetLastError( (DWORD) E_UNEXPECTED);
  802. }
  803. if ( fResult == TRUE )
  804. {
  805. fResult = ChainCreateCertObject (
  806. fAdditionalStoreUsed ?
  807. CERT_EXTERNAL_ISSUER_OBJECT_TYPE :
  808. CERT_CACHED_ISSUER_OBJECT_TYPE,
  809. pCallContext,
  810. pCertContext,
  811. rgbCertHash,
  812. &pCertObject
  813. );
  814. }
  815. CertFreeCertificateContext( pCertContext );
  816. }
  817. else
  818. {
  819. fResult = FALSE;
  820. SetLastError((DWORD) CRYPT_E_NOT_FOUND);
  821. }
  822. }
  823. if ( fResult )
  824. {
  825. assert(pCertObject);
  826. fResult = ChainCreatePathObject(
  827. pCallContext,
  828. pCertObject,
  829. hAdditionalStore,
  830. &pSigner
  831. );
  832. }
  833. if ( fResult )
  834. {
  835. assert(pSigner);
  836. if ( !pSignerInfo->fSignerHashAvailable || *pfNewSigner )
  837. {
  838. memcpy(
  839. pSignerInfo->rgbSignerCertHash,
  840. rgbCertHash,
  841. CHAINHASHLEN
  842. );
  843. pSignerInfo->fSignerHashAvailable = TRUE;
  844. }
  845. }
  846. if ( pCertObject != NULL )
  847. {
  848. pCertObject->Release();
  849. }
  850. *ppSigner = pSigner;
  851. return( fResult );
  852. }
  853. //+---------------------------------------------------------------------------
  854. //
  855. // Function: SSCtlFindCertificateInStoreByHash
  856. //
  857. // Synopsis: find certificate in store by hash
  858. //
  859. //----------------------------------------------------------------------------
  860. PCCERT_CONTEXT WINAPI
  861. SSCtlFindCertificateInStoreByHash (
  862. IN HCERTSTORE hStore,
  863. IN BYTE rgbHash [ CHAINHASHLEN]
  864. )
  865. {
  866. CRYPT_HASH_BLOB HashBlob;
  867. HashBlob.cbData = CHAINHASHLEN;
  868. HashBlob.pbData = rgbHash;
  869. return( CertFindCertificateInStore(
  870. hStore,
  871. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  872. 0,
  873. CERT_FIND_MD5_HASH,
  874. &HashBlob,
  875. NULL
  876. ) );
  877. }
  878. //+---------------------------------------------------------------------------
  879. //
  880. // Function: SSCtlGetCtlTrustStatus
  881. //
  882. // Synopsis: get the trust status for the CTL
  883. //
  884. //----------------------------------------------------------------------------
  885. VOID WINAPI
  886. SSCtlGetCtlTrustStatus (
  887. IN PCCTL_CONTEXT pCtlContext,
  888. IN BOOL fSignatureValid,
  889. IN LPFILETIME pTime,
  890. IN PCERT_USAGE_MATCH pRequestedUsage,
  891. IN OUT PCERT_TRUST_STATUS pStatus
  892. )
  893. {
  894. FILETIME NoTime;
  895. CERT_TRUST_STATUS UsageStatus;
  896. memset( &NoTime, 0, sizeof( NoTime ) );
  897. if ( fSignatureValid == FALSE )
  898. {
  899. pStatus->dwErrorStatus |= CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID;
  900. }
  901. if ( ( CompareFileTime(
  902. pTime,
  903. &pCtlContext->pCtlInfo->ThisUpdate
  904. ) < 0 ) ||
  905. ( ( ( CompareFileTime(
  906. &NoTime,
  907. &pCtlContext->pCtlInfo->NextUpdate
  908. ) != 0 ) &&
  909. ( CompareFileTime(
  910. pTime,
  911. &pCtlContext->pCtlInfo->NextUpdate
  912. ) > 0 ) ) ) )
  913. {
  914. pStatus->dwErrorStatus |= CERT_TRUST_CTL_IS_NOT_TIME_VALID;
  915. }
  916. memset( &UsageStatus, 0, sizeof( UsageStatus ) );
  917. ChainGetUsageStatus(
  918. (PCERT_ENHKEY_USAGE)&pRequestedUsage->Usage,
  919. (PCERT_ENHKEY_USAGE)&pCtlContext->pCtlInfo->SubjectUsage,
  920. pRequestedUsage->dwType,
  921. &UsageStatus
  922. );
  923. if ( UsageStatus.dwErrorStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE )
  924. {
  925. pStatus->dwErrorStatus |= CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
  926. }
  927. }
  928. //+---------------------------------------------------------------------------
  929. //
  930. // Function: SSCtlPopulateCacheFromCertStore
  931. //
  932. // Synopsis: populate the SS CTL object cache from certificate store CTLs
  933. //
  934. //----------------------------------------------------------------------------
  935. BOOL WINAPI
  936. SSCtlPopulateCacheFromCertStore (
  937. IN PCCERTCHAINENGINE pChainEngine,
  938. IN OPTIONAL HCERTSTORE hStore
  939. )
  940. {
  941. BOOL fResult;
  942. BOOL fAdditionalStore = TRUE;
  943. PCCTL_CONTEXT pCtlContext = NULL;
  944. BYTE rgbCtlHash[ CHAINHASHLEN ];
  945. PCSSCTLOBJECT pSSCtlObject;
  946. PCSSCTLOBJECTCACHE pSSCtlObjectCache;
  947. pSSCtlObjectCache = pChainEngine->SSCtlObjectCache();
  948. if ( hStore == NULL )
  949. {
  950. hStore = pChainEngine->TrustStore();
  951. fAdditionalStore = FALSE;
  952. }
  953. while ( ( pCtlContext = CertEnumCTLsInStore(
  954. hStore,
  955. pCtlContext
  956. ) ) != NULL )
  957. {
  958. DWORD cbData = CHAINHASHLEN;
  959. fResult = CertGetCTLContextProperty(
  960. pCtlContext,
  961. CERT_MD5_HASH_PROP_ID,
  962. rgbCtlHash,
  963. &cbData
  964. );
  965. if ( fResult && CHAINHASHLEN != cbData)
  966. {
  967. fResult = FALSE;
  968. SetLastError( (DWORD) E_UNEXPECTED);
  969. }
  970. if ( fResult == TRUE )
  971. {
  972. pSSCtlObject = pSSCtlObjectCache->FindObjectByHash( rgbCtlHash );
  973. if ( pSSCtlObject == NULL )
  974. {
  975. fResult = SSCtlCreateCtlObject(
  976. pChainEngine,
  977. pCtlContext,
  978. FALSE, // fAdditionalStore
  979. &pSSCtlObject
  980. );
  981. }
  982. else
  983. {
  984. pSSCtlObject->Release();
  985. fResult = FALSE;
  986. }
  987. if ( fResult == TRUE )
  988. {
  989. fResult = pSSCtlObjectCache->AddObject( pSSCtlObject, FALSE );
  990. // NOTE: Since fDuplicate == FALSE this should never fail
  991. assert( fResult == TRUE );
  992. pSSCtlObject->Release();
  993. }
  994. }
  995. }
  996. return( TRUE );
  997. }
  998. //+---------------------------------------------------------------------------
  999. //
  1000. // Function: SSCtlCreateCtlObject
  1001. //
  1002. // Synopsis: create an SS CTL Object
  1003. //
  1004. //----------------------------------------------------------------------------
  1005. BOOL WINAPI
  1006. SSCtlCreateCtlObject (
  1007. IN PCCERTCHAINENGINE pChainEngine,
  1008. IN PCCTL_CONTEXT pCtlContext,
  1009. IN BOOL fAdditionalStore,
  1010. OUT PCSSCTLOBJECT* ppSSCtlObject
  1011. )
  1012. {
  1013. BOOL fResult = TRUE;
  1014. PCSSCTLOBJECT pSSCtlObject;
  1015. pSSCtlObject = new CSSCtlObject(
  1016. pChainEngine, pCtlContext, fAdditionalStore, fResult );
  1017. if ( pSSCtlObject == NULL )
  1018. {
  1019. SetLastError( (DWORD) E_OUTOFMEMORY );
  1020. fResult = FALSE;
  1021. }
  1022. else if ( fResult == TRUE )
  1023. {
  1024. *ppSSCtlObject = pSSCtlObject;
  1025. }
  1026. else
  1027. {
  1028. delete pSSCtlObject;
  1029. }
  1030. return( fResult );
  1031. }
  1032. //+---------------------------------------------------------------------------
  1033. //
  1034. // Function: SSCtlEnumObjectsWalkFn
  1035. //
  1036. // Synopsis: object enumerator walk function
  1037. //
  1038. //----------------------------------------------------------------------------
  1039. BOOL WINAPI
  1040. SSCtlEnumObjectsWalkFn (
  1041. IN LPVOID pvParameter,
  1042. IN HLRUENTRY hEntry
  1043. )
  1044. {
  1045. PSSCTL_ENUM_OBJECTS_DATA pEnumData = (PSSCTL_ENUM_OBJECTS_DATA)pvParameter;
  1046. return( ( *pEnumData->pfnEnumObjects )(
  1047. pEnumData->pvEnumParameter,
  1048. (PCSSCTLOBJECT)I_CryptGetLruEntryData( hEntry )
  1049. ) );
  1050. }
  1051. //+---------------------------------------------------------------------------
  1052. //
  1053. // Function: SSCtlCreateObjectCache
  1054. //
  1055. // Synopsis: create the SS CTL object cache
  1056. //
  1057. //----------------------------------------------------------------------------
  1058. BOOL WINAPI
  1059. SSCtlCreateObjectCache (
  1060. OUT PCSSCTLOBJECTCACHE* ppSSCtlObjectCache
  1061. )
  1062. {
  1063. BOOL fResult = TRUE;
  1064. PCSSCTLOBJECTCACHE pSSCtlObjectCache;
  1065. pSSCtlObjectCache = new CSSCtlObjectCache( fResult );
  1066. if ( pSSCtlObjectCache == NULL )
  1067. {
  1068. SetLastError( (DWORD) E_OUTOFMEMORY );
  1069. fResult = FALSE;
  1070. }
  1071. else if ( fResult == TRUE )
  1072. {
  1073. *ppSSCtlObjectCache = pSSCtlObjectCache;
  1074. }
  1075. else
  1076. {
  1077. delete pSSCtlObjectCache;
  1078. }
  1079. return( fResult );
  1080. }
  1081. //+---------------------------------------------------------------------------
  1082. //
  1083. // Function: SSCtlFreeObjectCache
  1084. //
  1085. // Synopsis: free the object cache
  1086. //
  1087. //----------------------------------------------------------------------------
  1088. VOID WINAPI
  1089. SSCtlFreeObjectCache (
  1090. IN PCSSCTLOBJECTCACHE pSSCtlObjectCache
  1091. )
  1092. {
  1093. delete pSSCtlObjectCache;
  1094. }
  1095. //+---------------------------------------------------------------------------
  1096. //
  1097. // Function: SSCtlFreeTrustListInfo
  1098. //
  1099. // Synopsis: free the trust list info
  1100. //
  1101. //----------------------------------------------------------------------------
  1102. VOID WINAPI
  1103. SSCtlFreeTrustListInfo (
  1104. IN PCERT_TRUST_LIST_INFO pTrustListInfo
  1105. )
  1106. {
  1107. CertFreeCTLContext( pTrustListInfo->pCtlContext );
  1108. delete pTrustListInfo;
  1109. }
  1110. //+---------------------------------------------------------------------------
  1111. //
  1112. // Function: SSCtlAllocAndCopyTrustListInfo
  1113. //
  1114. // Synopsis: allocate and copy the trust list info
  1115. //
  1116. //----------------------------------------------------------------------------
  1117. BOOL WINAPI
  1118. SSCtlAllocAndCopyTrustListInfo (
  1119. IN PCERT_TRUST_LIST_INFO pTrustListInfo,
  1120. OUT PCERT_TRUST_LIST_INFO* ppTrustListInfo
  1121. )
  1122. {
  1123. PCERT_TRUST_LIST_INFO pCopyTrustListInfo;
  1124. pCopyTrustListInfo = new CERT_TRUST_LIST_INFO;
  1125. if ( pCopyTrustListInfo == NULL )
  1126. {
  1127. SetLastError( (DWORD) E_OUTOFMEMORY );
  1128. return( FALSE );
  1129. }
  1130. pCopyTrustListInfo->cbSize = sizeof( CERT_TRUST_LIST_INFO );
  1131. pCopyTrustListInfo->pCtlContext = CertDuplicateCTLContext(
  1132. pTrustListInfo->pCtlContext
  1133. );
  1134. pCopyTrustListInfo->pCtlEntry = pTrustListInfo->pCtlEntry;
  1135. *ppTrustListInfo = pCopyTrustListInfo;
  1136. return( TRUE );
  1137. }
  1138. //+-------------------------------------------------------------------------
  1139. // Retrieve a newer and time valid CTL at one of the NextUpdate Urls
  1140. //
  1141. // Leaves the engine's critical section to do the URL
  1142. // fetching. If the engine was touched by another thread,
  1143. // it fails with LastError set to ERROR_CAN_NOT_COMPLETE.
  1144. //
  1145. // Assumption: Chain engine is locked once in the calling thread.
  1146. //--------------------------------------------------------------------------
  1147. BOOL
  1148. WINAPI
  1149. SSCtlRetrieveCtlUrl(
  1150. IN PCCERTCHAINENGINE pChainEngine,
  1151. IN PCCHAINCALLCONTEXT pCallContext,
  1152. IN OUT PCRYPT_URL_ARRAY pNextUpdateUrlArray,
  1153. IN DWORD dwRetrievalFlags,
  1154. IN OUT PCCTL_CONTEXT *ppCtl,
  1155. IN OUT BOOL *pfNewerCtl,
  1156. IN OUT BOOL *pfTimeValid
  1157. )
  1158. {
  1159. #if 1
  1160. // On 03-May-02 REMOVE_CTL_UPDATE_SUPPORT
  1161. return TRUE;
  1162. #else
  1163. BOOL fResult;
  1164. DWORD i;
  1165. // Loop through Urls and try to retrieve a newer and time valid CTL
  1166. for (i = 0; i < pNextUpdateUrlArray->cUrl; i++) {
  1167. PCCTL_CONTEXT pNewCtl = NULL;
  1168. LPWSTR pwszUrl = NULL;
  1169. DWORD cbUrl;
  1170. // Do URL fetching outside of the engine's critical section
  1171. // Need to make a copy of the Url string. pNextUpdateUrlArray
  1172. // can be modified by another thread outside of the critical section.
  1173. cbUrl = (wcslen(pNextUpdateUrlArray->rgwszUrl[i]) + 1) * sizeof(WCHAR);
  1174. pwszUrl = (LPWSTR) PkiNonzeroAlloc(cbUrl);
  1175. if (NULL == pwszUrl)
  1176. goto OutOfMemory;
  1177. memcpy(pwszUrl, pNextUpdateUrlArray->rgwszUrl[i], cbUrl);
  1178. pCallContext->ChainEngine()->UnlockEngine();
  1179. fResult = ChainRetrieveObjectByUrlW(
  1180. pwszUrl,
  1181. CONTEXT_OID_CTL,
  1182. dwRetrievalFlags |
  1183. CRYPT_LDAP_SCOPE_BASE_ONLY_RETRIEVAL |
  1184. CRYPT_STICKY_CACHE_RETRIEVAL,
  1185. pCallContext->ChainPara()->dwUrlRetrievalTimeout,
  1186. (LPVOID *) &pNewCtl,
  1187. NULL, // hAsyncRetrieve
  1188. NULL, // pCredentials
  1189. NULL, // pvVerify
  1190. NULL // pAuxInfo
  1191. );
  1192. pCallContext->ChainEngine()->LockEngine();
  1193. PkiFree(pwszUrl);
  1194. if (pCallContext->IsTouchedEngine()) {
  1195. if (pNewCtl)
  1196. CertFreeCTLContext(pNewCtl);
  1197. goto TouchedDuringUrlRetrieval;
  1198. }
  1199. if (fResult) {
  1200. PCCTL_CONTEXT pOldCtl;
  1201. assert(pNewCtl);
  1202. pOldCtl = *ppCtl;
  1203. if (0 < CompareFileTime(&pNewCtl->pCtlInfo->ThisUpdate,
  1204. &pOldCtl->pCtlInfo->ThisUpdate)) {
  1205. FILETIME CurrentTime;
  1206. // Move us to the head of the Url list
  1207. DWORD j;
  1208. LPWSTR pwszUrl = pNextUpdateUrlArray->rgwszUrl[i];
  1209. for (j = i; 0 < j; j--) {
  1210. pNextUpdateUrlArray->rgwszUrl[j] =
  1211. pNextUpdateUrlArray->rgwszUrl[j - 1];
  1212. }
  1213. pNextUpdateUrlArray->rgwszUrl[0] = pwszUrl;
  1214. *pfNewerCtl = TRUE;
  1215. CertFreeCTLContext(pOldCtl);
  1216. *ppCtl = pNewCtl;
  1217. pCallContext->CurrentTime(&CurrentTime);
  1218. if (I_CryptIsZeroFileTime(&pNewCtl->pCtlInfo->NextUpdate) ||
  1219. 0 < CompareFileTime(&pNewCtl->pCtlInfo->NextUpdate,
  1220. &CurrentTime)) {
  1221. *pfTimeValid = TRUE;
  1222. break;
  1223. }
  1224. } else
  1225. CertFreeCTLContext(pNewCtl);
  1226. }
  1227. }
  1228. fResult = TRUE;
  1229. CommonReturn:
  1230. return fResult;
  1231. ErrorReturn:
  1232. fResult = FALSE;
  1233. goto CommonReturn;
  1234. SET_ERROR(TouchedDuringUrlRetrieval, ERROR_CAN_NOT_COMPLETE)
  1235. TRACE_ERROR(OutOfMemory)
  1236. #endif
  1237. }
  1238. //+-------------------------------------------------------------------------
  1239. // Update Ctl Object Enum Function
  1240. //
  1241. // Leaves the engine's critical section to do the URL
  1242. // fetching. If the engine was touched by another thread,
  1243. // it fails with LastError set to ERROR_CAN_NOT_COMPLETE.
  1244. //
  1245. // Assumption: Chain engine is locked once in the calling thread.
  1246. //--------------------------------------------------------------------------
  1247. BOOL
  1248. WINAPI
  1249. SSCtlUpdateCtlObjectEnumFn(
  1250. IN LPVOID pvPara,
  1251. IN PCSSCTLOBJECT pSSCtlObject
  1252. )
  1253. {
  1254. #if 1
  1255. // On 03-May-02 REMOVE_CTL_UPDATE_SUPPORT
  1256. return TRUE;
  1257. #else
  1258. BOOL fTouchResult = TRUE;
  1259. PSSCTL_UPDATE_CTL_OBJ_PARA pPara = (PSSCTL_UPDATE_CTL_OBJ_PARA) pvPara;
  1260. FILETIME CurrentTime;
  1261. FILETIME UpdateTime;
  1262. PCCTL_CONTEXT pRetrieveCtl = NULL;
  1263. BOOL fTimeValid = FALSE;
  1264. BOOL fNewerCtl = FALSE;
  1265. PCRYPT_URL_ARRAY pNextUpdateUrlArray;
  1266. if (!pSSCtlObject->HasNextUpdateUrl(&UpdateTime))
  1267. return TRUE;
  1268. pPara->pCallContext->CurrentTime(&CurrentTime);
  1269. if (0 < CompareFileTime(&UpdateTime, &CurrentTime))
  1270. goto CommonReturn;
  1271. pRetrieveCtl = CertDuplicateCTLContext(pSSCtlObject->CtlContext());
  1272. pNextUpdateUrlArray = pSSCtlObject->NextUpdateUrlArray();
  1273. SSCtlRetrieveCtlUrl(
  1274. pPara->pChainEngine,
  1275. pPara->pCallContext,
  1276. pNextUpdateUrlArray,
  1277. CRYPT_CACHE_ONLY_RETRIEVAL,
  1278. &pRetrieveCtl,
  1279. &fNewerCtl,
  1280. &fTimeValid
  1281. );
  1282. if (pPara->pCallContext->IsTouchedEngine()) {
  1283. fTouchResult = FALSE;
  1284. goto TouchedDuringUrlRetrieval;
  1285. }
  1286. if (!fTimeValid && pPara->pCallContext->IsOnline()) {
  1287. SSCtlRetrieveCtlUrl(
  1288. pPara->pChainEngine,
  1289. pPara->pCallContext,
  1290. pNextUpdateUrlArray,
  1291. CRYPT_WIRE_ONLY_RETRIEVAL,
  1292. &pRetrieveCtl,
  1293. &fNewerCtl,
  1294. &fTimeValid
  1295. );
  1296. if (pPara->pCallContext->IsTouchedEngine()) {
  1297. fTouchResult = FALSE;
  1298. goto TouchedDuringUrlRetrieval;
  1299. }
  1300. if (!fNewerCtl)
  1301. pSSCtlObject->SetOffline(&CurrentTime, &UpdateTime);
  1302. }
  1303. if (fNewerCtl) {
  1304. PSSCTL_UPDATE_CTL_OBJ_ENTRY pEntry;
  1305. pSSCtlObject->SetOnline();
  1306. pEntry = new SSCTL_UPDATE_CTL_OBJ_ENTRY;
  1307. if (NULL == pEntry)
  1308. goto OutOfMemory;
  1309. if (!SSCtlCreateCtlObject(
  1310. pPara->pChainEngine,
  1311. pRetrieveCtl,
  1312. FALSE, // fAdditionalStore
  1313. &pEntry->pSSCtlObjectAdd
  1314. )) {
  1315. delete pEntry;
  1316. goto CreateCtlObjectError;
  1317. }
  1318. pEntry->pSSCtlObjectRemove = pSSCtlObject;
  1319. pEntry->pNext = pPara->pEntry;
  1320. pPara->pEntry = pEntry;
  1321. }
  1322. CommonReturn:
  1323. if (!fNewerCtl) {
  1324. if (I_CryptIsZeroFileTime(&pPara->UpdateTime) ||
  1325. 0 > CompareFileTime(&UpdateTime, &pPara->UpdateTime))
  1326. pPara->UpdateTime = UpdateTime;
  1327. }
  1328. if (pRetrieveCtl)
  1329. CertFreeCTLContext(pRetrieveCtl);
  1330. return fTouchResult;
  1331. ErrorReturn:
  1332. fNewerCtl = FALSE;
  1333. goto CommonReturn;
  1334. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  1335. TRACE_ERROR(CreateCtlObjectError)
  1336. SET_ERROR(TouchedDuringUrlRetrieval, ERROR_CAN_NOT_COMPLETE)
  1337. #endif
  1338. }