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.

613 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: msctl.cpp
  7. //
  8. // Contents: Default version of CertDllVerifyCTLUsage.
  9. //
  10. // Default implementation:
  11. // - If CtlStores are specified, then, only those stores are
  12. // searched to find a CTL with the specified usage and optional
  13. // ListIdentifier. Otherwise, the "Trust" system store is
  14. // searched to find a CTL.
  15. // - If CERT_VERIFY_TRUSTED_SIGNERS_FLAG is set, then, only the
  16. // SignerStores are searched to find the certificate
  17. // corresponding to the signer's issuer and serial number.
  18. // Otherwise, the CTL message's store, SignerStores,
  19. // "Trust" system store, "CA" system store, "ROOT" and "SPC"
  20. // system stores are searched to find the signer's certificate.
  21. // In either case, the public key in the found
  22. // certificate is used to verify the CTL's signature.
  23. // - If the CTL has a NextUpdate and
  24. // CERT_VERIFY_NO_TIME_CHECK_FLAG isn't set, then its
  25. // verified for time validity.
  26. // - If the CTL is time invalid, then, attempts to
  27. // get a time valid version. Uses either the CTL's
  28. // NextUpdateLocation property or CTL's NextUpdateLocation
  29. // extension or searches the signer's info for a
  30. // NextUpdateLocation attribute. The NextUpdateLocation
  31. // is encoded as a GeneralNames. Any non-URL name choices are
  32. // skipped.
  33. //
  34. // Functions: DllMain
  35. // DllRegisterServer
  36. // DllUnregisterServer
  37. // CertDllVerifyCTLUsage
  38. //
  39. // History: 29-Apr-97 philh created
  40. // 09-Oct-97 kirtd simplification, use CryptGetTimeValidObject
  41. //--------------------------------------------------------------------------
  42. #include <global.hxx>
  43. #include <dbgdef.h>
  44. #define MSCTL_TIMEOUT 15000
  45. //+-------------------------------------------------------------------------
  46. // Default stores searched to find a CTL or signer
  47. //--------------------------------------------------------------------------
  48. // The CTL stores must be at the beginning. CTL stores are opened as
  49. // READ/WRITE. Remaining stores are opened READONLY.
  50. //
  51. // CTL stores are also searched for signers.
  52. static const struct {
  53. LPCWSTR pwszStore;
  54. DWORD dwFlags;
  55. } rgDefaultStoreInfo[] = {
  56. L"TRUST", CERT_SYSTEM_STORE_CURRENT_USER,
  57. L"CA", CERT_SYSTEM_STORE_CURRENT_USER,
  58. L"ROOT", CERT_SYSTEM_STORE_CURRENT_USER,
  59. L"SPC", CERT_SYSTEM_STORE_LOCAL_MACHINE
  60. };
  61. #define NUM_DEFAULT_STORES (sizeof(rgDefaultStoreInfo) / \
  62. sizeof(rgDefaultStoreInfo[0]))
  63. #define NUM_DEFAULT_CTL_STORES 1
  64. #define NUM_DEFAULT_SIGNER_STORES NUM_DEFAULT_STORES
  65. //+-------------------------------------------------------------------------
  66. // The following HCERTSTORE handles once opened, remain open until
  67. // ProcessDetach
  68. //--------------------------------------------------------------------------
  69. static HCERTSTORE rghDefaultStore[NUM_DEFAULT_STORES];
  70. static BOOL fOpenedDefaultStores;
  71. extern CRITICAL_SECTION MSCtlDefaultStoresCriticalSection;
  72. //+-------------------------------------------------------------------------
  73. // Close the default stores that might have been opened
  74. //--------------------------------------------------------------------------
  75. void MSCtlCloseDefaultStores()
  76. {
  77. if (fOpenedDefaultStores) {
  78. DWORD i;
  79. for (i = 0; i < NUM_DEFAULT_STORES; i++) {
  80. HCERTSTORE hStore = rghDefaultStore[i];
  81. if (hStore)
  82. CertCloseStore(hStore, 0);
  83. }
  84. fOpenedDefaultStores = FALSE;
  85. }
  86. }
  87. //+-------------------------------------------------------------------------
  88. // Returns TRUE if the CTL is still time valid.
  89. //
  90. // A CTL without a NextUpdate is considered time valid.
  91. //--------------------------------------------------------------------------
  92. static BOOL IsTimeValidCtl(
  93. IN LPFILETIME pTimeToVerify,
  94. IN PCCTL_CONTEXT pCtl
  95. )
  96. {
  97. PCTL_INFO pCtlInfo = pCtl->pCtlInfo;
  98. // Note, NextUpdate is optional. When not present, its set to 0
  99. if ((0 == pCtlInfo->NextUpdate.dwLowDateTime &&
  100. 0 == pCtlInfo->NextUpdate.dwHighDateTime) ||
  101. CompareFileTime(&pCtlInfo->NextUpdate, pTimeToVerify) >= 0)
  102. return TRUE;
  103. else
  104. return FALSE;
  105. }
  106. //+-------------------------------------------------------------------------
  107. // Local functions called by CertDllVerifyCTLUsage
  108. //--------------------------------------------------------------------------
  109. static void MSCtlOpenDefaultStores();
  110. static BOOL VerifyCtl(
  111. IN PCCTL_CONTEXT pCtl,
  112. IN DWORD dwFlags,
  113. IN PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  114. OUT PCCERT_CONTEXT *ppSigner,
  115. OUT DWORD *pdwSignerIndex
  116. );
  117. static BOOL GetTimeValidCtl(
  118. IN LPFILETIME pCurrentTime,
  119. IN PCCTL_CONTEXT pCtl,
  120. IN DWORD dwFlags,
  121. IN PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  122. OUT PCCTL_CONTEXT *ppValidCtl,
  123. IN OUT PCCERT_CONTEXT *ppSigner,
  124. IN OUT DWORD *pdwSignerIndex
  125. );
  126. static PCCTL_CONTEXT ReplaceCtl(
  127. IN HCERTSTORE hStore,
  128. IN PCCTL_CONTEXT pOrigCtl,
  129. IN PCCTL_CONTEXT pValidCtl
  130. );
  131. static BOOL CompareCtlUsage(
  132. IN DWORD dwFindFlags,
  133. IN PCTL_FIND_USAGE_PARA pPara,
  134. IN PCCTL_CONTEXT pCtl
  135. )
  136. {
  137. PCTL_INFO pInfo = pCtl->pCtlInfo;
  138. if ((CTL_FIND_SAME_USAGE_FLAG & dwFindFlags) &&
  139. pPara->SubjectUsage.cUsageIdentifier !=
  140. pInfo->SubjectUsage.cUsageIdentifier)
  141. return FALSE;
  142. if (pPara->SubjectUsage.cUsageIdentifier) {
  143. DWORD cId1 = pPara->SubjectUsage.cUsageIdentifier;
  144. LPSTR *ppszId1 = pPara->SubjectUsage.rgpszUsageIdentifier;
  145. for ( ; cId1 > 0; cId1--, ppszId1++) {
  146. DWORD cId2 = pInfo->SubjectUsage.cUsageIdentifier;
  147. LPSTR *ppszId2 = pInfo->SubjectUsage.rgpszUsageIdentifier;
  148. for ( ; cId2 > 0; cId2--, ppszId2++) {
  149. if (0 == strcmp(*ppszId1, *ppszId2))
  150. break;
  151. }
  152. if (0 == cId2)
  153. return FALSE;
  154. }
  155. }
  156. if (pPara->ListIdentifier.cbData) {
  157. DWORD cb = pPara->ListIdentifier.cbData;
  158. if (CTL_FIND_NO_LIST_ID_CBDATA == cb)
  159. cb = 0;
  160. if (cb != pInfo->ListIdentifier.cbData)
  161. return FALSE;
  162. if (0 != cb && 0 != memcmp(pPara->ListIdentifier.pbData,
  163. pInfo->ListIdentifier.pbData, cb))
  164. return FALSE;
  165. }
  166. return TRUE;
  167. }
  168. //+-------------------------------------------------------------------------
  169. // Default version of CertDllVerifyCTLUsage
  170. //--------------------------------------------------------------------------
  171. BOOL
  172. WINAPI
  173. CertDllVerifyCTLUsage(
  174. IN DWORD dwEncodingType,
  175. IN DWORD dwSubjectType,
  176. IN void *pvSubject,
  177. IN PCTL_USAGE pSubjectUsage,
  178. IN DWORD dwFlags,
  179. IN OPTIONAL PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  180. IN OUT PCTL_VERIFY_USAGE_STATUS pVerifyUsageStatus
  181. )
  182. {
  183. BOOL fResult = FALSE;
  184. DWORD dwError = (DWORD) CRYPT_E_NO_VERIFY_USAGE_CHECK;
  185. DWORD cCtlStore;
  186. HCERTSTORE *phCtlStore; // not allocated or reference counted
  187. FILETIME CurrentTime;
  188. CTL_FIND_USAGE_PARA FindUsagePara;
  189. DWORD dwFindFlags;
  190. PCCTL_CONTEXT pValidCtl;
  191. PCCERT_CONTEXT pSigner;
  192. PCTL_ENTRY pEntry;
  193. DWORD dwSignerIndex;
  194. assert(NULL == pVerifyUsagePara || pVerifyUsagePara->cbSize >=
  195. sizeof(CTL_VERIFY_USAGE_PARA));
  196. assert(pVerifyUsageStatus && pVerifyUsageStatus->cbSize >=
  197. sizeof(CTL_VERIFY_USAGE_STATUS));
  198. if (pVerifyUsagePara && pVerifyUsagePara->cCtlStore > 0) {
  199. cCtlStore = pVerifyUsagePara->cCtlStore;
  200. phCtlStore = pVerifyUsagePara->rghCtlStore;
  201. } else {
  202. MSCtlOpenDefaultStores();
  203. dwFlags &= ~CERT_VERIFY_INHIBIT_CTL_UPDATE_FLAG;
  204. cCtlStore = NUM_DEFAULT_CTL_STORES;
  205. phCtlStore = rghDefaultStore;
  206. }
  207. // Get current time to be used to determine if CTLs are time valid
  208. {
  209. SYSTEMTIME SystemTime;
  210. GetSystemTime(&SystemTime);
  211. SystemTimeToFileTime(&SystemTime, &CurrentTime);
  212. }
  213. memset(&FindUsagePara, 0, sizeof(FindUsagePara));
  214. FindUsagePara.cbSize = sizeof(FindUsagePara);
  215. dwFindFlags = 0;
  216. if (pSubjectUsage) {
  217. FindUsagePara.SubjectUsage = *pSubjectUsage;
  218. if (0 == (CERT_VERIFY_ALLOW_MORE_USAGE_FLAG & dwFlags))
  219. dwFindFlags = CTL_FIND_SAME_USAGE_FLAG;
  220. }
  221. if (pVerifyUsagePara)
  222. FindUsagePara.ListIdentifier = pVerifyUsagePara->ListIdentifier;
  223. for ( ; ( cCtlStore > 0 ) && ( dwError != 0 ); cCtlStore--, phCtlStore++)
  224. {
  225. HCERTSTORE hCtlStore = *phCtlStore;
  226. PCCTL_CONTEXT pCtl;
  227. if (NULL == hCtlStore)
  228. continue;
  229. pCtl = NULL;
  230. while ( ( pCtl = CertFindCTLInStore(
  231. hCtlStore,
  232. dwEncodingType,
  233. dwFindFlags,
  234. CTL_FIND_USAGE,
  235. &FindUsagePara,
  236. pCtl
  237. ) ) )
  238. {
  239. pValidCtl = NULL;
  240. pSigner = NULL;
  241. pEntry = NULL;
  242. dwSignerIndex = 0;
  243. if ( ( fResult = VerifyCtl(
  244. pCtl,
  245. dwFlags,
  246. pVerifyUsagePara,
  247. &pSigner,
  248. &dwSignerIndex
  249. ) ) == TRUE )
  250. {
  251. if ( !( dwFlags & CERT_VERIFY_NO_TIME_CHECK_FLAG ) &&
  252. ( IsTimeValidCtl( &CurrentTime, pCtl ) == FALSE ) )
  253. {
  254. fResult = GetTimeValidCtl(
  255. &CurrentTime,
  256. pCtl,
  257. dwFlags,
  258. pVerifyUsagePara,
  259. &pValidCtl,
  260. &pSigner,
  261. &dwSignerIndex
  262. );
  263. if ( fResult == TRUE )
  264. {
  265. if ( !( dwFlags & CERT_VERIFY_INHIBIT_CTL_UPDATE_FLAG ) )
  266. {
  267. pValidCtl = ReplaceCtl( hCtlStore, pCtl, pValidCtl );
  268. pVerifyUsageStatus->dwFlags |= CERT_VERIFY_UPDATED_CTL_FLAG;
  269. }
  270. fResult = CompareCtlUsage(
  271. dwFindFlags,
  272. &FindUsagePara,
  273. pValidCtl
  274. );
  275. }
  276. else
  277. {
  278. dwError = (DWORD) CRYPT_E_VERIFY_USAGE_OFFLINE;
  279. }
  280. }
  281. if ( fResult == TRUE )
  282. {
  283. PCCTL_CONTEXT pCtlToUse;
  284. if ( pValidCtl != NULL )
  285. {
  286. pCtlToUse = CertDuplicateCTLContext( pValidCtl );
  287. }
  288. else
  289. {
  290. pCtlToUse = CertDuplicateCTLContext( pCtl );
  291. }
  292. pEntry = CertFindSubjectInCTL(
  293. dwEncodingType,
  294. dwSubjectType,
  295. pvSubject,
  296. pCtlToUse,
  297. 0
  298. );
  299. if ( pEntry != NULL )
  300. {
  301. pVerifyUsageStatus->dwCtlEntryIndex =
  302. (DWORD)(pEntry - pCtlToUse->pCtlInfo->rgCTLEntry);
  303. if ( pVerifyUsageStatus->ppCtl != NULL )
  304. {
  305. *pVerifyUsageStatus->ppCtl = pCtlToUse;
  306. }
  307. else
  308. {
  309. CertFreeCTLContext( pCtlToUse );
  310. }
  311. pVerifyUsageStatus->dwSignerIndex = dwSignerIndex;
  312. if ( pVerifyUsageStatus->ppSigner != NULL )
  313. {
  314. *pVerifyUsageStatus->ppSigner =
  315. CertDuplicateCertificateContext( pSigner );
  316. }
  317. dwError = 0;
  318. }
  319. else
  320. {
  321. dwError = (DWORD) CRYPT_E_NOT_IN_CTL;
  322. CertFreeCTLContext( pCtlToUse );
  323. }
  324. }
  325. }
  326. else
  327. {
  328. dwError = (DWORD) CRYPT_E_NO_TRUSTED_SIGNER;
  329. }
  330. if ( pValidCtl != NULL )
  331. {
  332. CertFreeCTLContext( pValidCtl );
  333. }
  334. if ( pSigner != NULL )
  335. {
  336. CertFreeCertificateContext( pSigner );
  337. }
  338. if ( dwError == 0 ) {
  339. CertFreeCTLContext(pCtl);
  340. break;
  341. }
  342. }
  343. }
  344. if ( dwError != 0 )
  345. {
  346. fResult = FALSE;
  347. }
  348. pVerifyUsageStatus->dwError = dwError;
  349. SetLastError( dwError );
  350. return fResult;
  351. }
  352. //+=========================================================================
  353. // Open default stores functions
  354. //==========================================================================
  355. static const CRYPT_OID_FUNC_ENTRY UsageFuncTable[] = {
  356. CRYPT_DEFAULT_OID, CertDllVerifyCTLUsage
  357. };
  358. #define USAGE_FUNC_COUNT (sizeof(UsageFuncTable) / sizeof(UsageFuncTable[0]))
  359. //+-------------------------------------------------------------------------
  360. // Open the default stores used to find the CTL or signer. Also, install
  361. // ourself so we aren't unloaded.
  362. //
  363. // Open and install are only done once.
  364. //--------------------------------------------------------------------------
  365. static void MSCtlOpenDefaultStores()
  366. {
  367. if (fOpenedDefaultStores)
  368. return;
  369. assert(NUM_DEFAULT_STORES >= NUM_DEFAULT_CTL_STORES);
  370. assert(NUM_DEFAULT_STORES >= NUM_DEFAULT_SIGNER_STORES);
  371. EnterCriticalSection(&MSCtlDefaultStoresCriticalSection);
  372. if (!fOpenedDefaultStores) {
  373. DWORD i;
  374. for (i = 0; i < NUM_DEFAULT_STORES; i++) {
  375. DWORD dwFlags;
  376. dwFlags = rgDefaultStoreInfo[i].dwFlags;
  377. if (i >= NUM_DEFAULT_CTL_STORES)
  378. dwFlags |= CERT_STORE_READONLY_FLAG;
  379. rghDefaultStore[i] = CertOpenStore(
  380. CERT_STORE_PROV_SYSTEM_W,
  381. 0, // dwEncodingType
  382. 0, // hCryptProv
  383. dwFlags,
  384. (const void *) rgDefaultStoreInfo[i].pwszStore
  385. );
  386. }
  387. fOpenedDefaultStores = TRUE;
  388. }
  389. LeaveCriticalSection(&MSCtlDefaultStoresCriticalSection);
  390. }
  391. //+=========================================================================
  392. // Verify and replace CTL functions
  393. //==========================================================================
  394. //+-------------------------------------------------------------------------
  395. // Verifies the signature of the CTL.
  396. //--------------------------------------------------------------------------
  397. static BOOL VerifyCtl(
  398. IN PCCTL_CONTEXT pCtl,
  399. IN DWORD dwFlags,
  400. IN PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  401. OUT PCCERT_CONTEXT *ppSigner,
  402. OUT DWORD *pdwSignerIndex
  403. )
  404. {
  405. BOOL fResult;
  406. DWORD cParaStore;
  407. HCERTSTORE *phParaStore; // not allocated or reference counted
  408. DWORD cStore;
  409. HCERTSTORE *phStore = NULL;
  410. HCERTSTORE *phAllocStore = NULL;
  411. DWORD dwGetFlags;
  412. if (pVerifyUsagePara) {
  413. cParaStore = pVerifyUsagePara->cSignerStore;
  414. phParaStore = pVerifyUsagePara->rghSignerStore;
  415. } else {
  416. cParaStore = 0;
  417. phParaStore = NULL;
  418. }
  419. if (dwFlags & CERT_VERIFY_TRUSTED_SIGNERS_FLAG) {
  420. cStore = cParaStore;
  421. phStore = phParaStore;
  422. dwGetFlags = CMSG_TRUSTED_SIGNER_FLAG;
  423. } else {
  424. MSCtlOpenDefaultStores();
  425. if (cParaStore) {
  426. cStore = cParaStore + NUM_DEFAULT_SIGNER_STORES;
  427. if (NULL == (phAllocStore = (HCERTSTORE *) PkiNonzeroAlloc(
  428. cStore * sizeof(HCERTSTORE))))
  429. goto OutOfMemory;
  430. phStore = phAllocStore;
  431. memcpy(phStore, phParaStore, cParaStore * sizeof(HCERTSTORE));
  432. memcpy(&phStore[cParaStore], rghDefaultStore,
  433. NUM_DEFAULT_SIGNER_STORES * sizeof(HCERTSTORE));
  434. } else {
  435. cStore = NUM_DEFAULT_SIGNER_STORES;
  436. phStore = rghDefaultStore;
  437. }
  438. dwGetFlags = 0;
  439. }
  440. fResult = CryptMsgGetAndVerifySigner(
  441. pCtl->hCryptMsg,
  442. cStore,
  443. phStore,
  444. dwGetFlags,
  445. ppSigner,
  446. pdwSignerIndex);
  447. CommonReturn:
  448. PkiFree(phAllocStore);
  449. return fResult;
  450. ErrorReturn:
  451. *ppSigner = NULL;
  452. *pdwSignerIndex = 0;
  453. fResult = FALSE;
  454. goto CommonReturn;
  455. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  456. }
  457. //+-------------------------------------------------------------------------
  458. // Replaces the CTL in the store. Copies over any original properties.
  459. //--------------------------------------------------------------------------
  460. static PCCTL_CONTEXT ReplaceCtl(
  461. IN HCERTSTORE hStore,
  462. IN PCCTL_CONTEXT pOrigCtl,
  463. IN PCCTL_CONTEXT pValidCtl
  464. )
  465. {
  466. PCCTL_CONTEXT pNewCtl;
  467. if (CertAddCTLContextToStore(
  468. hStore,
  469. pValidCtl,
  470. CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES,
  471. &pNewCtl))
  472. CertFreeCTLContext(pValidCtl);
  473. else
  474. pNewCtl = pValidCtl;
  475. return pNewCtl;
  476. }
  477. //+=========================================================================
  478. // Get time valid CTL via URL obtained from old CTL's NextUpdateLocation
  479. // property, extension or signer attribute.
  480. //==========================================================================
  481. static BOOL GetTimeValidCtl(
  482. IN LPFILETIME pCurrentTime,
  483. IN PCCTL_CONTEXT pCtl,
  484. IN DWORD dwFlags,
  485. IN PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  486. OUT PCCTL_CONTEXT *ppValidCtl,
  487. IN OUT PCCERT_CONTEXT *ppSigner,
  488. IN OUT DWORD *pdwSignerIndex
  489. )
  490. {
  491. BOOL fResult;
  492. *ppValidCtl = NULL;
  493. fResult = CryptGetTimeValidObject(
  494. TIME_VALID_OID_GET_CTL,
  495. (LPVOID)pCtl,
  496. *ppSigner,
  497. pCurrentTime,
  498. 0,
  499. MSCTL_TIMEOUT,
  500. (LPVOID *)ppValidCtl,
  501. NULL,
  502. NULL
  503. );
  504. if ( fResult == FALSE )
  505. {
  506. fResult = CryptGetTimeValidObject(
  507. TIME_VALID_OID_GET_CTL,
  508. (LPVOID)pCtl,
  509. *ppSigner,
  510. pCurrentTime,
  511. CRYPT_DONT_VERIFY_SIGNATURE,
  512. MSCTL_TIMEOUT,
  513. (LPVOID *)ppValidCtl,
  514. NULL,
  515. NULL
  516. );
  517. if ( fResult == TRUE )
  518. {
  519. DWORD dwSignerIndex = *pdwSignerIndex;
  520. PCCERT_CONTEXT pSigner = *ppSigner;
  521. fResult = VerifyCtl(
  522. *ppValidCtl,
  523. dwFlags,
  524. pVerifyUsagePara,
  525. ppSigner,
  526. pdwSignerIndex
  527. );
  528. if ( fResult == TRUE )
  529. {
  530. CertFreeCertificateContext( pSigner );
  531. }
  532. else
  533. {
  534. *pdwSignerIndex = dwSignerIndex;
  535. *ppSigner = pSigner;
  536. CertFreeCTLContext( *ppValidCtl );
  537. SetLastError( (DWORD) CRYPT_E_NO_TRUSTED_SIGNER );
  538. }
  539. }
  540. }
  541. return( fResult );
  542. }