Source code of Windows XP (NT5)
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.

1205 lines
34 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: initpki.cpp
  7. //
  8. // Contents: migrates Bob Store to SPC store and adds root certificates
  9. //
  10. // History: 03-Jun-97 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "global.hxx"
  14. #include "cryptreg.h"
  15. #include "..\mscat32\mscatprv.h"
  16. HMODULE hModule = NULL;
  17. //////////////////////////////////////////////////////////////////
  18. #define INITPKI_HRESULT_FROM_WIN32(a) ((a >= 0x80000000) ? a : HRESULT_FROM_WIN32(a))
  19. #define SHA1_HASH_LENGTH 20
  20. #define wsz_ROOT_STORE L"Root"
  21. #define wsz_TRUST_STORE L"Trust"
  22. #define wsz_CA_STORE L"CA"
  23. #define wsz_TRUST_PUB_STORE L"TrustedPublisher"
  24. #define wsz_DISALLOWED_STORE L"Disallowed"
  25. static LPCWSTR rgpwszPredefinedEnterpriseStore[] = {
  26. wsz_ROOT_STORE,
  27. wsz_TRUST_STORE,
  28. wsz_CA_STORE,
  29. wsz_TRUST_PUB_STORE,
  30. wsz_DISALLOWED_STORE
  31. };
  32. #define NUM_PREDEFINED_ENTERPRISE_STORE \
  33. (sizeof(rgpwszPredefinedEnterpriseStore) / \
  34. sizeof(rgpwszPredefinedEnterpriseStore[0]))
  35. void RegisterEnterpriseStores()
  36. {
  37. DWORD i;
  38. for (i = 0; i < NUM_PREDEFINED_ENTERPRISE_STORE; i++) {
  39. CertRegisterSystemStore(
  40. rgpwszPredefinedEnterpriseStore[i],
  41. CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
  42. NULL, // pSystemStoreInfo
  43. NULL // pvReserved
  44. );
  45. }
  46. }
  47. void RemoveCert(HCERTSTORE hStore, BYTE *pThumbPrint)
  48. {
  49. PCERT_CONTEXT pCertContext;
  50. CRYPT_HASH_BLOB CryptHashBlob;
  51. CryptHashBlob.cbData = SHA1_HASH_LENGTH;
  52. CryptHashBlob.pbData = pThumbPrint;
  53. pCertContext = (PCERT_CONTEXT)CertFindCertificateInStore( hStore,
  54. X509_ASN_ENCODING,
  55. 0,
  56. CERT_FIND_SHA1_HASH,
  57. &CryptHashBlob,
  58. NULL);
  59. if (pCertContext)
  60. {
  61. CertDeleteCertificateFromStore(pCertContext);
  62. }
  63. }
  64. //
  65. // if byte 0 is null, make sure to change while loop below!
  66. //
  67. BYTE CertRemoveList[][SHA1_HASH_LENGTH] =
  68. {
  69. { 0x4B, 0x33, 0x8D, 0xCD, 0x50, 0x18, 0x10, 0xB9, 0x36, 0xA0,
  70. 0x63, 0x61, 0x4C, 0x3C, 0xDD, 0x3F, 0xC2, 0xC4, 0x88, 0x55 }, // GTE Glue - '96
  71. { 0x56, 0xB0, 0x65, 0xA7, 0x4B, 0xDC, 0xE3, 0x7C, 0x96, 0xD3,
  72. 0xBA, 0x69, 0x81, 0x08, 0x02, 0xD5, 0x87, 0x03, 0xC0, 0xBD }, // Verisign Comm Glue - '96
  73. { 0x13, 0x39, 0x72, 0xAA, 0x97, 0xD3, 0x65, 0xFB, 0x6A, 0x1D,
  74. 0x47, 0xA5, 0xC7, 0x7A, 0x5C, 0x03, 0x94, 0xBD, 0xB9, 0xED }, // Verisign Indv Glue - '96
  75. { 0x69, 0xD0, 0x4F, 0xFB, 0x62, 0xE1, 0xC9, 0xAE, 0x30, 0x76,
  76. 0x99, 0x2A, 0xE7, 0x46, 0xFD, 0x69, 0x08, 0x3A, 0xBD, 0xE9 }, // MS Root cert - '96
  77. { 0xA7, 0xD7, 0xD5, 0xFD, 0xBB, 0x26, 0xB4, 0x10, 0xC1, 0xD6,
  78. 0x7A, 0xFB, 0xF5, 0xC9, 0x05, 0x39, 0x42, 0xDE, 0xE0, 0xEF }, // MS SGC Root Authority - '99
  79. // { 0xCC, 0x7E, 0xD0, 0x77, 0xF0, 0xF2, 0x92, 0x59, 0x5A, 0x81,
  80. // 0x66, 0xB0, 0x17, 0x09, 0xE2, 0x0C, 0x08, 0x84, 0xA5, 0xF8 }, // verisign "Class1" - '97
  81. //
  82. // { 0xD4, 0x73, 0x5D, 0x8A, 0x9A, 0xE5, 0xBC, 0x4B, 0x0A, 0x0D,
  83. // 0xC2, 0x70, 0xD6, 0xA6, 0x25, 0x38, 0xA5, 0x87, 0xD3, 0x2F }, // verisign "timestamp" - '97
  84. //
  85. // { 0x68, 0x8B, 0x6E, 0xB8, 0x07, 0xE8, 0xED, 0xA5, 0xC7, 0xB1,
  86. // 0x7C, 0x43, 0x93, 0xD0, 0x79, 0x5F, 0x0F, 0xAE, 0x15, 0x5F }, // verisign "commercial" - '97
  87. //
  88. // { 0xB1, 0x9D, 0xD0, 0x96, 0xDC, 0xD4, 0xE3, 0xE0, 0xFD, 0x67,
  89. // 0x68, 0x85, 0x50, 0x5A, 0x67, 0x2C, 0x43, 0x8D, 0x4E, 0x9C }, // verisign "individual" - '97
  90. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  91. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // term
  92. };
  93. //+---------------------------------------------------------------------------
  94. //
  95. // Function: PurgeExpiringCertsFromStores
  96. //
  97. // Synopsis: blech!
  98. //
  99. //----------------------------------------------------------------------------
  100. HRESULT PurgeExpiringCertsFromStores ()
  101. {
  102. DWORD cRemove;
  103. DWORD cStores;
  104. HCERTSTORE hStore = NULL;
  105. HKEY hKey = NULL;
  106. char *pszStores[] = { "SPC", "ROOT", "CU_ROOT", NULL };
  107. //
  108. // HACKHACK! no crypt32 UI about the root store.
  109. //
  110. if (RegCreateHKCUKeyExU(HKEY_CURRENT_USER, ROOT_STORE_REGPATH,
  111. 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS)
  112. {
  113. hKey = NULL;
  114. }
  115. cStores = 0;
  116. while (pszStores[cStores])
  117. {
  118. if (strcmp(pszStores[cStores], "CU_ROOT") == 0)
  119. {
  120. if (hKey)
  121. hStore = CertOpenStore(CERT_STORE_PROV_REG, 0, NULL, 0, (LPVOID)hKey);
  122. else
  123. hStore = NULL;
  124. }
  125. else
  126. {
  127. hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL,
  128. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  129. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  130. pszStores[cStores]);
  131. }
  132. if (hStore)
  133. {
  134. cRemove = 0;
  135. while (CertRemoveList[cRemove][0] != 0x00)
  136. {
  137. if (hStore)
  138. {
  139. RemoveCert(hStore, &CertRemoveList[cRemove][0]);
  140. }
  141. cRemove++;
  142. }
  143. CertCloseStore(hStore, 0);
  144. }
  145. cStores++;
  146. }
  147. if (hKey)
  148. RegCloseKey(hKey);
  149. return( S_OK );
  150. }
  151. PCCERT_CONTEXT FindCertificateInOtherStore(
  152. IN HCERTSTORE hOtherStore,
  153. IN PCCERT_CONTEXT pCert
  154. )
  155. {
  156. BYTE rgbHash[SHA1_HASH_LENGTH];
  157. CRYPT_DATA_BLOB HashBlob;
  158. HashBlob.pbData = rgbHash;
  159. HashBlob.cbData = SHA1_HASH_LENGTH;
  160. if (!CertGetCertificateContextProperty(
  161. pCert,
  162. CERT_SHA1_HASH_PROP_ID,
  163. rgbHash,
  164. &HashBlob.cbData
  165. ) || SHA1_HASH_LENGTH != HashBlob.cbData)
  166. return NULL;
  167. return CertFindCertificateInStore(
  168. hOtherStore,
  169. 0, // dwCertEncodingType
  170. 0, // dwFindFlags
  171. CERT_FIND_SHA1_HASH,
  172. (const void *) &HashBlob,
  173. NULL //pPrevCertContext
  174. );
  175. }
  176. BOOL IsCertificateInOtherStore(
  177. IN HCERTSTORE hOtherStore,
  178. IN PCCERT_CONTEXT pCert
  179. )
  180. {
  181. PCCERT_CONTEXT pOtherCert;
  182. if (pOtherCert = FindCertificateInOtherStore(hOtherStore, pCert)) {
  183. CertFreeCertificateContext(pOtherCert);
  184. return TRUE;
  185. } else
  186. return FALSE;
  187. }
  188. void DeleteCertificateFromOtherStore(
  189. IN HCERTSTORE hOtherStore,
  190. IN PCCERT_CONTEXT pCert
  191. )
  192. {
  193. PCCERT_CONTEXT pOtherCert;
  194. if (pOtherCert = FindCertificateInOtherStore(hOtherStore, pCert))
  195. CertDeleteCertificateFromStore(pOtherCert);
  196. }
  197. //+-------------------------------------------------------------------------
  198. // Read a SignedData message consisting of certificates and
  199. // CRLs from memory and copy to the specified cert store.
  200. //
  201. // Except for the SPC being loaded from memory, identical to SpcReadSpcFile.
  202. //
  203. // For hLMStore != NULL: if the certificate or CRL already exists in the
  204. // LocalMachine store don't add it. Also if it exists in hCertstore,
  205. // delete it.
  206. //--------------------------------------------------------------------------
  207. HRESULT
  208. SpcReadSpcFromMemory(
  209. IN BYTE *pbData,
  210. IN DWORD cbData,
  211. IN HCERTSTORE hCertStore,
  212. IN DWORD dwMsgAndCertEncodingType,
  213. IN DWORD dwFlags,
  214. IN OPTIONAL HCERTSTORE hLMStore
  215. )
  216. {
  217. HRESULT hr = S_OK;
  218. HCERTSTORE hSpcStore = NULL;
  219. CRYPT_DATA_BLOB sSpcBlob;
  220. HCRYPTPROV hCryptProv = NULL;
  221. PCCERT_CONTEXT pCert = NULL;
  222. PCCRL_CONTEXT pCrl = NULL;
  223. if (!(hCertStore))
  224. {
  225. goto InvalidArg;
  226. }
  227. // Set the blob data.
  228. sSpcBlob.pbData = pbData;
  229. sSpcBlob.cbData = cbData;
  230. // Open up the spc store
  231. hSpcStore = CertOpenStore(CERT_STORE_PROV_SERIALIZED, //CERT_STORE_PROV_PKCS7,
  232. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  233. hCryptProv,
  234. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  235. &sSpcBlob);
  236. if (!hSpcStore)
  237. {
  238. goto CertStoreError;
  239. }
  240. // Copy in the certificates from the caller.
  241. while (pCert = CertEnumCertificatesInStore(hSpcStore, pCert))
  242. {
  243. if (hLMStore && IsCertificateInOtherStore(hLMStore, pCert))
  244. // Certificate exists in LocalMachine. Delete it from
  245. // CurrentUser if it already exists there.
  246. DeleteCertificateFromOtherStore(hCertStore, pCert);
  247. else
  248. CertAddCertificateContextToStore(hCertStore,
  249. pCert,
  250. CERT_STORE_ADD_REPLACE_EXISTING,
  251. NULL);
  252. }
  253. while (pCrl = CertEnumCRLsInStore(hSpcStore, pCrl))
  254. {
  255. CertAddCRLContextToStore(hCertStore,
  256. pCrl,
  257. CERT_STORE_ADD_NEWER,
  258. NULL);
  259. if (hLMStore) {
  260. // Check if newer or same CRL exists in the hLMStore
  261. PCCRL_CONTEXT pLMCrl;
  262. pLMCrl = CertFindCRLInStore(
  263. hLMStore,
  264. pCrl->dwCertEncodingType,
  265. 0, // dwFindFlags
  266. CRL_FIND_EXISTING,
  267. (const void *) pCrl,
  268. NULL // pPrevCrlContext
  269. );
  270. if (NULL != pLMCrl) {
  271. PCCRL_CONTEXT pCUCrl;
  272. pCUCrl = CertFindCRLInStore(
  273. hCertStore,
  274. pCrl->dwCertEncodingType,
  275. 0, // dwFindFlags
  276. CRL_FIND_EXISTING,
  277. (const void *) pCrl,
  278. NULL // pPrevCrlContext
  279. );
  280. if (NULL != pCUCrl) {
  281. if (0 <= CompareFileTime(
  282. &pLMCrl->pCrlInfo->ThisUpdate,
  283. &pCUCrl->pCrlInfo->ThisUpdate
  284. ))
  285. CertDeleteCRLFromStore(pCUCrl);
  286. else
  287. CertFreeCRLContext(pCUCrl);
  288. }
  289. CertFreeCRLContext(pLMCrl);
  290. }
  291. }
  292. }
  293. CommonReturn:
  294. if (hSpcStore)
  295. {
  296. CertCloseStore(hSpcStore, 0);
  297. }
  298. return(hr);
  299. ErrorReturn:
  300. SetLastError((DWORD)hr);
  301. goto CommonReturn;
  302. SET_HRESULT_EX(DBG_SS, InvalidArg, E_INVALIDARG);
  303. SET_HRESULT_EX(DBG_SS, CertStoreError, GetLastError());
  304. }
  305. // For nonNULL pszLMStoreName, doesn't add certificates if already in
  306. // pszLMStoreName store.
  307. HRESULT AddCertificates2(
  308. IN LPCSTR pszStoreName,
  309. IN OPTIONAL LPCSTR pszLMStoreName,
  310. IN DWORD dwOpenStoreFlags,
  311. IN LPCSTR pszResourceName,
  312. IN LPCSTR pszResourceType
  313. )
  314. {
  315. HRESULT hr = S_OK;
  316. HCERTSTORE hCertStore = NULL;
  317. HCERTSTORE hLMStore = NULL;
  318. LPBYTE pb = NULL;
  319. DWORD cb;
  320. HRSRC hrsrc;
  321. hCertStore = CertOpenStore(
  322. CERT_STORE_PROV_SYSTEM_REGISTRY_A,
  323. 0, // dwEncodingType
  324. NULL, // hCryptProv
  325. dwOpenStoreFlags |
  326. CERT_SYSTEM_STORE_UNPROTECTED_FLAG,
  327. (const void *) pszStoreName
  328. );
  329. if (!(hCertStore))
  330. {
  331. return(GetLastError());
  332. }
  333. if (NULL != pszLMStoreName)
  334. {
  335. hLMStore = CertOpenStore(
  336. CERT_STORE_PROV_SYSTEM_REGISTRY_A,
  337. 0, // dwEncodingType
  338. NULL, // hCryptProv
  339. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  340. CERT_STORE_READONLY_FLAG |
  341. CERT_SYSTEM_STORE_UNPROTECTED_FLAG,
  342. (const void *) pszLMStoreName
  343. );
  344. }
  345. hrsrc = FindResourceA(hModule, pszResourceName, pszResourceType);
  346. if ( hrsrc != NULL )
  347. {
  348. HGLOBAL hglobRes;
  349. hglobRes = LoadResource(hModule, hrsrc);
  350. if ( hglobRes != NULL )
  351. {
  352. ULONG cbRes;
  353. BYTE* pbRes;
  354. cbRes = SizeofResource(hModule, hrsrc);
  355. pbRes = (BYTE *)LockResource(hglobRes);
  356. hr = SpcReadSpcFromMemory( pbRes,
  357. cbRes,
  358. hCertStore,
  359. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  360. 0,
  361. hLMStore);
  362. UnlockResource(hglobRes);
  363. FreeResource(hglobRes);
  364. }
  365. else
  366. {
  367. hr = HRESULT_FROM_WIN32(GetLastError());
  368. }
  369. }
  370. else
  371. {
  372. hr = HRESULT_FROM_WIN32(GetLastError());
  373. }
  374. if ( hCertStore != NULL )
  375. {
  376. CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
  377. }
  378. if ( hLMStore != NULL )
  379. {
  380. CertCloseStore(hLMStore, CERT_CLOSE_STORE_FORCE_FLAG);
  381. }
  382. return( hr );
  383. }
  384. // For non-LocalMachine store, doesn't add certificates if already in
  385. // corresponding LocalMachine store.
  386. HRESULT AddCertificates(
  387. IN LPCSTR pszStoreName,
  388. IN DWORD dwOpenStoreFlags,
  389. IN LPCSTR pszResourceName,
  390. IN LPCSTR pszResourceType
  391. )
  392. {
  393. LPCSTR pszLMStoreName;
  394. if (CERT_SYSTEM_STORE_LOCAL_MACHINE !=
  395. (dwOpenStoreFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  396. pszLMStoreName = pszStoreName;
  397. else
  398. pszLMStoreName = NULL;
  399. return AddCertificates2(
  400. pszStoreName,
  401. pszLMStoreName,
  402. dwOpenStoreFlags,
  403. pszResourceName,
  404. pszResourceType
  405. );
  406. }
  407. HRESULT AddCurrentUserCACertificates()
  408. {
  409. return AddCertificates(
  410. "CA",
  411. CERT_SYSTEM_STORE_CURRENT_USER,
  412. MAKEINTRESOURCE(IDR_CAS),
  413. "CAS"
  414. );
  415. }
  416. HRESULT AddLocalMachineCACertificates()
  417. {
  418. return AddCertificates(
  419. "CA",
  420. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  421. MAKEINTRESOURCE(IDR_CAS),
  422. "CAS"
  423. );
  424. }
  425. HRESULT AddCurrentUserDisallowedCertificates()
  426. {
  427. return AddCertificates(
  428. "Disallowed",
  429. CERT_SYSTEM_STORE_CURRENT_USER,
  430. MAKEINTRESOURCE(IDR_DISALLOW),
  431. "DISALLOW"
  432. );
  433. }
  434. HRESULT AddLocalMachineDisallowedCertificates()
  435. {
  436. return AddCertificates(
  437. "Disallowed",
  438. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  439. MAKEINTRESOURCE(IDR_DISALLOW),
  440. "DISALLOW"
  441. );
  442. }
  443. HRESULT AddCurrentUserRootCertificates()
  444. {
  445. HRESULT hr;
  446. HRESULT hr2;
  447. hr = AddCertificates(
  448. "Root",
  449. CERT_SYSTEM_STORE_CURRENT_USER,
  450. MAKEINTRESOURCE(IDR_ROOTS),
  451. "ROOTS"
  452. );
  453. hr2 = AddCertificates2(
  454. "Root",
  455. "AuthRoot", // check if already in LM AuthRoot store
  456. CERT_SYSTEM_STORE_CURRENT_USER,
  457. MAKEINTRESOURCE(IDR_AUTHROOTS),
  458. "AUTHROOTS"
  459. );
  460. if (hr == ERROR_SUCCESS)
  461. hr = hr2;
  462. return hr;
  463. }
  464. HRESULT AddLocalMachineRootCertificates()
  465. {
  466. HRESULT hr;
  467. HRESULT hr2;
  468. HRESULT hr3;
  469. HRESULT hr4;
  470. hr = AddCertificates(
  471. "AuthRoot",
  472. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  473. MAKEINTRESOURCE(IDR_AUTHROOTS),
  474. "AUTHROOTS"
  475. );
  476. // Remove all the AuthRoots from the "Root" store
  477. hr2 = AddCertificates2(
  478. "Root",
  479. "AuthRoot", // check if already in LM AuthRoot store
  480. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  481. MAKEINTRESOURCE(IDR_AUTHROOTS),
  482. "AUTHROOTS"
  483. );
  484. hr3 = AddCertificates(
  485. "Root",
  486. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  487. MAKEINTRESOURCE(IDR_ROOTS),
  488. "ROOTS"
  489. );
  490. // Remove all the Roots from the "AuthRoot" store
  491. hr4 = AddCertificates2(
  492. "AuthRoot",
  493. "Root", // check if already in LM Root store
  494. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  495. MAKEINTRESOURCE(IDR_ROOTS),
  496. "ROOTS"
  497. );
  498. if (hr == ERROR_SUCCESS)
  499. hr = hr2;
  500. if (hr == ERROR_SUCCESS)
  501. hr = hr3;
  502. if (hr == ERROR_SUCCESS)
  503. hr = hr4;
  504. return hr;
  505. }
  506. void CreateKey(
  507. IN HKEY hKey,
  508. IN LPCWSTR pwszSubKey
  509. )
  510. {
  511. LONG err;
  512. DWORD dwDisposition;
  513. HKEY hSubKey;
  514. if (ERROR_SUCCESS != (err = RegCreateKeyExU(
  515. hKey,
  516. pwszSubKey,
  517. 0, // dwReserved
  518. NULL, // lpClass
  519. REG_OPTION_NON_VOLATILE,
  520. MAXIMUM_ALLOWED,
  521. NULL, // lpSecurityAttributes
  522. &hSubKey,
  523. &dwDisposition))) {
  524. #if DBG
  525. DbgPrintf(DBG_SS_CRYPT32,
  526. "RegCreateKeyEx(%S) returned error: %d 0x%x\n",
  527. pwszSubKey, err, err);
  528. #endif
  529. } else {
  530. RegCloseKey(hSubKey);
  531. }
  532. }
  533. // Loop through the certificates in the "My" store and get their
  534. // KeyIdentifier property. If the certificate also has a KEY_PROV_INFO,
  535. // then, this will cause its KeyIdentifier to be created.
  536. void UpdateMyKeyIdentifiers(
  537. IN DWORD dwOpenStoreFlags
  538. )
  539. {
  540. HCERTSTORE hStore;
  541. if (hStore = CertOpenStore(
  542. CERT_STORE_PROV_SYSTEM_A,
  543. 0, // dwEncodingType
  544. NULL, // hCryptProv
  545. dwOpenStoreFlags | CERT_STORE_ENUM_ARCHIVED_FLAG,
  546. (const void *) "My"
  547. )) {
  548. PCCERT_CONTEXT pCert = NULL;
  549. while (pCert = CertEnumCertificatesInStore(hStore, pCert)) {
  550. DWORD cbData = 0;
  551. // Dummy get to force the KeyIdentifer property to be created
  552. // if it doesn't already exist.
  553. CertGetCertificateContextProperty(
  554. pCert,
  555. CERT_KEY_IDENTIFIER_PROP_ID,
  556. NULL, // pvData
  557. &cbData
  558. );
  559. }
  560. CertCloseStore(hStore, 0);
  561. }
  562. }
  563. //---------------------------------------------------------------------------
  564. // Set Software Publisher State Key Value
  565. //
  566. //---------------------------------------------------------------------------
  567. BOOL SetSoftPubKey(DWORD dwMask, BOOL fOn)
  568. {
  569. DWORD dwState=0;
  570. DWORD dwDisposition=0;
  571. DWORD dwType=0;
  572. DWORD cbData=0;
  573. LPWSTR wszState=REGNAME_WINTRUST_POLICY_FLAGS;
  574. BOOL fResult=FALSE;
  575. HKEY hKey=NULL;
  576. // Set the State in the registry
  577. if (ERROR_SUCCESS != RegCreateKeyExU(
  578. HKEY_CURRENT_USER,
  579. REGPATH_WINTRUST_POLICY_FLAGS,
  580. 0, // dwReserved
  581. NULL, // lpszClass
  582. REG_OPTION_NON_VOLATILE,
  583. KEY_ALL_ACCESS,
  584. NULL, // lpSecurityAttributes
  585. &hKey,
  586. &dwDisposition))
  587. goto RegErr;
  588. dwState = 0;
  589. cbData = sizeof(dwState);
  590. if(ERROR_SUCCESS != RegQueryValueExU
  591. ( hKey,
  592. wszState,
  593. NULL, // lpReserved
  594. &dwType,
  595. (BYTE *) &dwState,
  596. &cbData
  597. ))
  598. goto RegErr;
  599. if ((dwType != REG_DWORD) && (dwType != REG_BINARY))
  600. goto UnexpectedErr;
  601. switch(dwMask)
  602. {
  603. case WTPF_IGNOREREVOCATIONONTS:
  604. case WTPF_IGNOREREVOKATION:
  605. case WTPF_IGNOREEXPIRATION:
  606. // Revocation and expiration are a double negative so the bit set
  607. // means revocation and expriation checking is off.
  608. fOn = !fOn;
  609. break;
  610. default:
  611. break;
  612. };
  613. if (fOn)
  614. dwState |= dwMask;
  615. else
  616. dwState &= ~dwMask;
  617. if(ERROR_SUCCESS != RegSetValueExU(
  618. hKey,
  619. wszState,
  620. 0, // dwReserved
  621. REG_DWORD,
  622. (BYTE *) &dwState,
  623. sizeof(dwState)
  624. ))
  625. goto SetValueErr;
  626. fResult=TRUE;
  627. CommonReturn:
  628. if(hKey)
  629. RegCloseKey(hKey);
  630. return fResult;
  631. ErrorReturn:
  632. goto CommonReturn;
  633. TRACE_ERROR(RegErr);
  634. SET_ERROR(UnexpectedErr, E_UNEXPECTED);
  635. TRACE_ERROR(SetValueErr);
  636. }
  637. //+---------------------------------------------------------------------------
  638. //
  639. // Function: GetNextRegToken
  640. //
  641. // Synopsis:
  642. // Find the next token with space as the deliminator
  643. //----------------------------------------------------------------------------
  644. LPWSTR GetNextRegToken(LPWSTR pwsz, LPWSTR pwszPreToken, BOOL *pfEnd)
  645. {
  646. LPWSTR pwszStart=NULL;
  647. LPWSTR pwszSearch=NULL;
  648. if(NULL == pwsz)
  649. return NULL;
  650. if(TRUE == (*pfEnd))
  651. return NULL;
  652. pwszStart=pwsz;
  653. if(pwszPreToken)
  654. pwszStart=pwszPreToken + wcslen(pwszPreToken) + 1;
  655. //skip the spaces
  656. while((*pwszStart)==L' ')
  657. pwszStart++;
  658. //check for NULL
  659. if(*pwszStart==L'\0')
  660. return NULL;
  661. pwszSearch=pwszStart;
  662. while(((*pwszSearch) != L'\0') && ((*pwszSearch) !=L' ') )
  663. pwszSearch++;
  664. if(*pwszSearch == L'\0')
  665. {
  666. *pfEnd=TRUE;
  667. return pwszStart;
  668. }
  669. *pwszSearch=L'\0';
  670. *pfEnd=FALSE;
  671. return pwszStart;
  672. }
  673. //+---------------------------------------------------------------------------
  674. //
  675. // Function: InitRegistryValue
  676. //
  677. // Synopsis: This function replace SetReg.exe. The expected
  678. // command line would be: 1 TRUE 3 FALSE 9 TRUE 4 FALSE ....
  679. //
  680. //----------------------------------------------------------------------------
  681. HRESULT InitRegistryValue(LPWSTR pwszCommand)
  682. {
  683. HRESULT hr= E_FAIL;
  684. DWORD SoftPubFlags[] =
  685. {
  686. WTPF_TRUSTTEST | WTPF_TESTCANBEVALID,
  687. WTPF_IGNOREEXPIRATION,
  688. WTPF_IGNOREREVOKATION,
  689. WTPF_OFFLINEOK_IND,
  690. WTPF_OFFLINEOK_COM,
  691. WTPF_OFFLINEOKNBU_IND,
  692. WTPF_OFFLINEOKNBU_COM,
  693. WTPF_VERIFY_V1_OFF,
  694. WTPF_IGNOREREVOCATIONONTS,
  695. WTPF_ALLOWONLYPERTRUST
  696. };
  697. LPWSTR pwszNextToken=NULL;
  698. int iIndex=-1;
  699. BOOL fOn=FALSE;
  700. int cFlags=sizeof(SoftPubFlags)/sizeof(SoftPubFlags[0]);
  701. DWORD cParam=0;
  702. LPWSTR pwszCopy=NULL;
  703. BOOL fPassThrough=FALSE;
  704. //make a copy of the command line since we will change it
  705. pwszCopy=(LPWSTR)LocalAlloc(LPTR, (1+wcslen(pwszCommand)) * sizeof(WCHAR));
  706. if(NULL== pwszCopy)
  707. goto MemoryErr;
  708. wcscpy(pwszCopy, pwszCommand);
  709. while(pwszNextToken=GetNextRegToken(pwszCopy, pwszNextToken, &fPassThrough))
  710. {
  711. if(-1 == iIndex)
  712. {
  713. iIndex=_wtoi(pwszNextToken);
  714. if((iIndex <= 0) || (iIndex > cFlags))
  715. goto InvalidArgErr;
  716. cParam++;
  717. }
  718. else
  719. {
  720. if(0 == _wcsicmp(pwszNextToken, L"true"))
  721. fOn=TRUE;
  722. else
  723. {
  724. if(0 == _wcsicmp(pwszNextToken, L"false"))
  725. fOn=FALSE;
  726. else
  727. goto InvalidArgErr;
  728. }
  729. cParam++;
  730. //set the registry value
  731. if(!SetSoftPubKey(SoftPubFlags[iIndex-1],
  732. fOn))
  733. {
  734. hr=INITPKI_HRESULT_FROM_WIN32(GetLastError());
  735. goto SetKeyErr;
  736. }
  737. //reset the value for dwIndex
  738. iIndex=-1;
  739. }
  740. }
  741. //we have to have even number of parameters
  742. if( (0 != (cParam %2)) || (0 == cParam))
  743. goto InvalidArgErr;
  744. hr=S_OK;
  745. CommonReturn:
  746. if(pwszCopy)
  747. LocalFree((HLOCAL)pwszCopy);
  748. return hr;
  749. ErrorReturn:
  750. goto CommonReturn;
  751. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  752. SET_ERROR_VAR(SetKeyErr, hr);
  753. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  754. }
  755. //+---------------------------------------------------------------------------
  756. //
  757. // Function: DllMain
  758. //
  759. // Synopsis:
  760. //
  761. //----------------------------------------------------------------------------
  762. BOOL WINAPI DllMain(HMODULE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
  763. {
  764. switch ( fdwReason )
  765. {
  766. case DLL_PROCESS_ATTACH:
  767. hModule = hInstDLL;
  768. break;
  769. }
  770. return( TRUE );
  771. }
  772. //+---------------------------------------------------------------------------
  773. //
  774. // Function: DllInstall
  775. //
  776. // Synopsis: dll installation entry point
  777. //
  778. //----------------------------------------------------------------------------
  779. STDAPI DllInstall (BOOL fRegister, LPCSTR pszCommand)
  780. {
  781. HRESULT hr = S_OK;
  782. HRESULT hr2;
  783. LPWSTR pwszCommand=NULL;
  784. if ( fRegister == FALSE )
  785. {
  786. return( E_NOTIMPL );
  787. }
  788. switch ( *pszCommand )
  789. {
  790. //letter S stands for setreg input parameters
  791. //the command line should look like following:
  792. //S 1 TRUE 2 FALSE 3 FALSE ...
  793. //pszCommand is ACTUALLY LPWSTR for BOTH
  794. //NT5, NT4 and Win95.
  795. case 'S':
  796. case 's':
  797. pwszCommand=(LPWSTR)pszCommand;
  798. if(wcslen(pwszCommand) <= 2)
  799. {
  800. hr=E_INVALIDARG;
  801. }
  802. else
  803. {
  804. hr=InitRegistryValue((LPWSTR)(&(pwszCommand[1])));
  805. }
  806. break;
  807. case 'M':
  808. case 'm':
  809. MoveCertificates( TRUE );
  810. PurgeExpiringCertsFromStores();
  811. break;
  812. case 'U':
  813. case 'u':
  814. _AdjustPolicyFlags(psPolicySettings);
  815. PurgeExpiringCertsFromStores();
  816. // Ensure we have a registry entry for the Group Policy
  817. // SystemCertificates. On NT 4.0 or Win98, we emulate NT 5.0 GPT
  818. // notification by doing a RegNotifyChangeKeyValue on this
  819. // registry key.
  820. CreateKey(HKEY_CURRENT_USER, GROUP_POLICY_STORE_REGPATH);
  821. // Before adding to CurrentUser, will check if the root or CA
  822. // already exists in LocalMachine. If it exists in
  823. // LocalMachine and also exists in CurrentUser, will delete it
  824. // from CurrentUser instead of adding.
  825. hr = AddCurrentUserRootCertificates();
  826. hr2 = AddCurrentUserCACertificates();
  827. if (hr == ERROR_SUCCESS)
  828. hr = hr2;
  829. hr2 = AddCurrentUserDisallowedCertificates();
  830. if (hr == ERROR_SUCCESS)
  831. hr = hr2;
  832. // Protect the CurrentUser roots and purge any existing
  833. // protected CurrentUser roots also in LocalMachine
  834. //
  835. // Note, once the roots are protected, all subsequent adds are
  836. // done by a special service executing with System privileges.
  837. // This special service does secure attention sequence (SAS) UI
  838. // before doing the add.
  839. //
  840. // Note, subsequent purges are exempt from UI. ie, this function
  841. // doesn't do any SAS UI.
  842. I_CertProtectFunction(
  843. CERT_PROT_PURGE_LM_ROOTS_FUNC_ID,
  844. 0, // dwFlags
  845. NULL, // pwszIn
  846. NULL, // pbIn
  847. 0, // cbIn
  848. NULL, // ppbOut
  849. NULL // pcbOut
  850. );
  851. UpdateMyKeyIdentifiers(CERT_SYSTEM_STORE_CURRENT_USER);
  852. break;
  853. case 'B':
  854. case 'b':
  855. case 'R':
  856. case 'r':
  857. case 'A':
  858. case 'a':
  859. // Initialize HKLM registry locations used by PKI to
  860. // only give Everyone KEY_READ access. Also gives the
  861. // IEDirtyFlags registry key KEY_SET_VALUE access for
  862. // Everyone.
  863. InitializeHKLMAcls();
  864. // Ensure we have a registry entry for the IEDirtyFlags
  865. // This key should have already been created
  866. // by InitializeHKLMAcls() for NT. Ensure its also there
  867. // for Win95 and Win98
  868. CreateKey(HKEY_LOCAL_MACHINE, CERT_IE_DIRTY_FLAGS_REGPATH);
  869. MoveCertificates(TRUE);
  870. PurgeExpiringCertsFromStores();
  871. // Ensure we have a registry entry for the Group Policy
  872. // SystemCertificates. On NT 4.0 or Win98, we emulate NT 5.0 GPT
  873. // notification by doing a RegNotifyChangeKeyValue on this
  874. // registry key.
  875. CreateKey(HKEY_LOCAL_MACHINE, GROUP_POLICY_STORE_REGPATH);
  876. CreateKey(HKEY_CURRENT_USER, GROUP_POLICY_STORE_REGPATH);
  877. // Ensure we have existing predefined stores for the LocalMachine
  878. // Enterprise system stores. These stores are periodically updated
  879. // from the DS by a system service. RegNotifyChangeKeyValue is
  880. // used to signal clients about Enterprise store changes.
  881. RegisterEnterpriseStores();
  882. // Our goal is to get the roots and CAs into LocalMachine.
  883. // Note previously, they were only copied to CurrentUser.
  884. AddLocalMachineRootCertificates();
  885. AddLocalMachineCACertificates();
  886. AddLocalMachineDisallowedCertificates();
  887. // If the above adds to LocalMachine failed, then, add
  888. // to CurrentUser.
  889. //
  890. // Before adding to CurrentUser, will check if the root or CA
  891. // already exists in LocalMachine. If it exists in
  892. // LocalMachine and also exists in CurrentUser, will delete it
  893. // from CurrentUser instead of adding.
  894. hr = AddCurrentUserRootCertificates();
  895. hr2 = AddCurrentUserCACertificates();
  896. if (hr == ERROR_SUCCESS)
  897. hr = hr2;
  898. hr2 = AddCurrentUserDisallowedCertificates();
  899. if (hr == ERROR_SUCCESS)
  900. hr = hr2;
  901. // Protect the CurrentUser roots and purge any existing
  902. // protected CurrentUser roots also in LocalMachine
  903. //
  904. // Note, once the roots are protected, all subsequent adds are
  905. // done by a special service executing with System privileges.
  906. // This special service does secure attention sequence (SAS) UI
  907. // before doing the add.
  908. //
  909. // Note, subsequent purges are exempt from UI. ie, this function
  910. // doesn't do any SAS UI.
  911. I_CertProtectFunction(
  912. CERT_PROT_PURGE_LM_ROOTS_FUNC_ID,
  913. 0, // dwFlags
  914. NULL, // pwszIn
  915. NULL, // pbIn
  916. 0, // cbIn
  917. NULL, // ppbOut
  918. NULL // pcbOut
  919. );
  920. UpdateMyKeyIdentifiers(CERT_SYSTEM_STORE_CURRENT_USER);
  921. UpdateMyKeyIdentifiers(CERT_SYSTEM_STORE_LOCAL_MACHINE);
  922. CleanupRegistry();
  923. hr2 = RegisterCryptoDlls(TRUE);
  924. if (hr == ERROR_SUCCESS)
  925. hr = hr2;
  926. if (!I_CryptCatAdminMigrateToNewCatDB())
  927. {
  928. hr2 = HRESULT_FROM_WIN32(GetLastError());
  929. }
  930. else
  931. {
  932. hr2 = ERROR_SUCCESS;
  933. }
  934. if (hr == ERROR_SUCCESS)
  935. hr = hr2;
  936. break;
  937. case 'C':
  938. case 'c':
  939. // Win9x migration post setup cleanup. Remove any migrated
  940. // roots that exist in the AuthRoot store.
  941. AddLocalMachineRootCertificates();
  942. AddCurrentUserRootCertificates();
  943. break;
  944. case 'Z':
  945. case 'z':
  946. //
  947. // This is for componentization install
  948. //
  949. pwszCommand=(LPWSTR)pszCommand;
  950. if (_wcsicmp(pwszCommand, L"z CoreCertificateServices") == 0)
  951. {
  952. InitializeHKLMAcls();
  953. AddLocalMachineRootCertificates();
  954. AddLocalMachineCACertificates();
  955. AddLocalMachineDisallowedCertificates();
  956. if (!_LoadAndRegister("wintrust.dll", FALSE) ||
  957. !_LoadAndRegister("mssign32.dll", FALSE) ||
  958. !_LoadAndRegister("xenroll.dll", FALSE) ||
  959. !_AdjustPolicyFlags(psPolicySettings))
  960. {
  961. hr = S_FALSE;
  962. }
  963. RegisterWinlogonExtension("crypt32chain", "crypt32.dll",
  964. "ChainWlxLogoffEvent");
  965. RegisterWinlogonExtension("cryptnet", "cryptnet.dll",
  966. "CryptnetWlxLogoffEvent");
  967. RegisterCrypt32EventSource();
  968. }
  969. else if (_wcsicmp(pwszCommand, L"z CertificateUIServices") == 0)
  970. {
  971. if (!_LoadAndRegister("cryptui.dll", FALSE))
  972. {
  973. hr = S_FALSE;
  974. }
  975. }
  976. else if (_wcsicmp(pwszCommand, L"z CryptographicNetworkServices") == 0)
  977. {
  978. if (!_LoadAndRegister("cryptnet.dll", FALSE))
  979. {
  980. hr = S_FALSE;
  981. }
  982. }
  983. else if (_wcsicmp(pwszCommand, L"z CertificateUIExtensions") == 0)
  984. {
  985. if (!_LoadAndRegister("cryptext.dll", FALSE))
  986. {
  987. hr = S_FALSE;
  988. }
  989. }
  990. else
  991. {
  992. hr = E_INVALIDARG;
  993. }
  994. break;
  995. default:
  996. hr = E_INVALIDARG;
  997. }
  998. return( hr );
  999. }
  1000. STDAPI DllRegisterServer(void)
  1001. {
  1002. return(DllInstall(TRUE, "A"));
  1003. }
  1004. STDAPI DllUnregisterServer(void)
  1005. {
  1006. return(UnregisterCryptoDlls());
  1007. }
  1008. BOOL WINAPI InitializePKI(void)
  1009. {
  1010. if (RegisterCryptoDlls(TRUE) != S_OK)
  1011. {
  1012. return(FALSE);
  1013. }
  1014. return(TRUE);
  1015. }