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.

503 lines
13 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: autoenrl.cpp
  7. //
  8. // Contents: Autoenrollment API implementation
  9. //
  10. // History: 3-Apr-98 petesk created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "pch.cpp"
  14. #pragma hdrstop
  15. #include "cainfoc.h"
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. #include <windows.h>
  19. #include <wincrypt.h>
  20. #include <certca.h>
  21. #define SHA_HASH_SIZE 20
  22. //
  23. // Build the CTL_ENTRY structure for
  24. HRESULT BuildCTLEntry(
  25. IN WCHAR ** awszCAs,
  26. OUT PCTL_ENTRY *ppCTLEntry,
  27. OUT DWORD *pcCTLEntry
  28. )
  29. {
  30. HRESULT hr = S_OK;
  31. PCCERT_CONTEXT pCertContext = NULL;
  32. DWORD cbCert;
  33. BYTE *pbCert = NULL;
  34. DWORD cbHash = SHA_HASH_SIZE;
  35. PCTL_ENTRY pCTLEntry = NULL;
  36. HCAINFO hCACurrent = NULL;
  37. DWORD cCA = 0;
  38. PBYTE pbHash;
  39. // Passing in NULL or a zero length list implies that
  40. // we do lazy evaluation of 'pick any'. Therefore, the
  41. // ctl list should be zero size.
  42. if((ppCTLEntry == NULL) ||
  43. (pcCTLEntry == NULL))
  44. {
  45. hr = E_INVALIDARG;
  46. goto error;
  47. }
  48. if((awszCAs == NULL) ||
  49. (awszCAs[0] == NULL))
  50. {
  51. *pcCTLEntry = 0;
  52. *ppCTLEntry = NULL;
  53. goto error;
  54. }
  55. cCA = 0;
  56. while(awszCAs[cCA])
  57. {
  58. cCA++;
  59. }
  60. pCTLEntry = (PCTL_ENTRY)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
  61. sizeof(CTL_ENTRY)*cCA + SHA_HASH_SIZE*cCA);
  62. if(pCTLEntry == NULL)
  63. {
  64. hr = E_OUTOFMEMORY;
  65. goto error;
  66. }
  67. pbHash = (PBYTE)(pCTLEntry + cCA);
  68. cCA=0;
  69. while(awszCAs[cCA])
  70. {
  71. hr = CAFindByName(awszCAs[cCA], NULL, 0, &hCACurrent);
  72. if(hr != S_OK)
  73. {
  74. goto error;
  75. }
  76. hr = CAGetCACertificate(hCACurrent, &pCertContext);
  77. if(hr != S_OK)
  78. {
  79. goto error;
  80. }
  81. cbHash = SHA_HASH_SIZE;
  82. if(!CertGetCertificateContextProperty(pCertContext,
  83. CERT_SHA1_HASH_PROP_ID,
  84. pbHash,
  85. &cbHash))
  86. {
  87. hr = myHLastError();
  88. goto error;
  89. }
  90. pCTLEntry[cCA].SubjectIdentifier.cbData = cbHash;
  91. pCTLEntry[cCA].SubjectIdentifier.pbData = pbHash;
  92. pbHash += cbHash;
  93. CertFreeCertificateContext(pCertContext);
  94. pCertContext = NULL;
  95. cCA++;
  96. CACloseCA(hCACurrent);
  97. }
  98. *pcCTLEntry = cCA;
  99. *ppCTLEntry = pCTLEntry;
  100. pCTLEntry = NULL;
  101. error:
  102. if (pCTLEntry)
  103. {
  104. LocalFree(pCTLEntry);
  105. }
  106. if(pCertContext)
  107. {
  108. CertFreeCertificateContext(pCertContext);
  109. }
  110. return hr;
  111. }
  112. HRESULT
  113. BuildAutoEnrollmentCTL(
  114. IN LPCWSTR pwszCertType,
  115. IN LPCWSTR pwszObjectID,
  116. IN BOOL fMachine,
  117. IN WCHAR ** awszCAs,
  118. IN PCMSG_SIGNED_ENCODE_INFO pSignerInfo,
  119. OUT BYTE **ppbEncodedCTL,
  120. OUT DWORD *pcbEncodedCTL
  121. )
  122. {
  123. HRESULT hr = S_OK;
  124. PCERT_ENHKEY_USAGE pKeyUsage = NULL;
  125. DWORD cbKeyUsage;
  126. CTL_INFO CTLInfo;
  127. BYTE *pbEncodedCTL = NULL;
  128. DWORD cbEncodedCTL;
  129. LPSTR pszUsageIdentifier;
  130. CERT_EXTENSION CertExt;
  131. CMSG_SIGNED_ENCODE_INFO SignerInfo;
  132. PCERT_EXTENSIONS pCertExtensions = NULL;
  133. DWORD cch = 0;
  134. PCMSG_SIGNED_ENCODE_INFO pSigner = NULL;
  135. HCERTTYPE hCertType = NULL;
  136. ZeroMemory(&CTLInfo, sizeof(CTLInfo));
  137. ZeroMemory(&CertExt, sizeof(CertExt));
  138. ZeroMemory(&SignerInfo, sizeof(SignerInfo));
  139. if(pSignerInfo)
  140. {
  141. pSigner = pSignerInfo;
  142. }
  143. else
  144. {
  145. pSigner = &SignerInfo;
  146. }
  147. #if 0
  148. hr = CAFindCertTypeByName(pwszCertType,
  149. NULL,
  150. (fMachine?CT_ENUM_MACHINE_TYPES | CT_FIND_LOCAL_SYSTEM:CT_ENUM_USER_TYPES),
  151. &hCertType);
  152. if (S_OK != hr)
  153. {
  154. goto error;
  155. }
  156. hr = CAGetCertTypeExtensions(hCertType, &pCertExtensions);
  157. if (S_OK != hr)
  158. {
  159. goto error;
  160. }
  161. #endif
  162. // set up the CTL info
  163. CTLInfo.dwVersion = sizeof(CTLInfo);
  164. CTLInfo.SubjectUsage.cUsageIdentifier = 1;
  165. pszUsageIdentifier = szOID_AUTO_ENROLL_CTL_USAGE;
  166. CTLInfo.SubjectUsage.rgpszUsageIdentifier = &pszUsageIdentifier;
  167. CTLInfo.ListIdentifier.cbData = (wcslen(pwszCertType) + 1) * sizeof(WCHAR);
  168. if(pwszObjectID)
  169. {
  170. CTLInfo.ListIdentifier.cbData += (wcslen(pwszObjectID)+1) * sizeof(WCHAR);
  171. }
  172. CTLInfo.ListIdentifier.pbData = (BYTE *)LocalAlloc(LMEM_ZEROINIT, CTLInfo.ListIdentifier.cbData);
  173. if(CTLInfo.ListIdentifier.pbData == NULL)
  174. {
  175. hr = E_OUTOFMEMORY;
  176. goto error;
  177. }
  178. if(pwszObjectID)
  179. {
  180. wcscpy((LPWSTR)CTLInfo.ListIdentifier.pbData, pwszObjectID);
  181. wcscat((LPWSTR)CTLInfo.ListIdentifier.pbData, L"|");
  182. }
  183. // wcscat can be used as the memory is initialized to zero
  184. wcscat((LPWSTR)CTLInfo.ListIdentifier.pbData, pwszCertType);
  185. GetSystemTimeAsFileTime(&CTLInfo.ThisUpdate);
  186. CTLInfo.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1;
  187. hr = BuildCTLEntry(awszCAs,
  188. &CTLInfo.rgCTLEntry,
  189. &CTLInfo.cCTLEntry);
  190. if (S_OK != hr)
  191. {
  192. goto error;
  193. }
  194. #if 0
  195. // add all the reg info as an extension
  196. CTLInfo.cExtension = pCertExtensions->cExtension;
  197. CTLInfo.rgExtension = pCertExtensions->rgExtension;
  198. #endif
  199. CTLInfo.cExtension = 0;
  200. CTLInfo.rgExtension = NULL;
  201. // encode the CTL
  202. *pcbEncodedCTL = 0;
  203. SignerInfo.cbSize = sizeof(SignerInfo);
  204. if (!CryptMsgEncodeAndSignCTL(PKCS_7_ASN_ENCODING,
  205. &CTLInfo, &SignerInfo, 0,
  206. NULL, pcbEncodedCTL))
  207. {
  208. hr = myHLastError();
  209. goto error;
  210. }
  211. if (NULL == (*ppbEncodedCTL =
  212. (BYTE*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, *pcbEncodedCTL)))
  213. {
  214. hr = E_OUTOFMEMORY;
  215. goto error;
  216. }
  217. if (!CryptMsgEncodeAndSignCTL(PKCS_7_ASN_ENCODING,
  218. &CTLInfo, pSigner, 0,
  219. *ppbEncodedCTL,
  220. pcbEncodedCTL))
  221. {
  222. hr = myHLastError();
  223. goto error;
  224. }
  225. error:
  226. if(CTLInfo.rgCTLEntry)
  227. {
  228. LocalFree(CTLInfo.rgCTLEntry);
  229. }
  230. if(CTLInfo.ListIdentifier.pbData)
  231. {
  232. LocalFree(CTLInfo.ListIdentifier.pbData);
  233. }
  234. #if 0
  235. if (pCertExtensions)
  236. {
  237. LocalFree(pCertExtensions);
  238. }
  239. #endif
  240. if(hCertType)
  241. {
  242. CACloseCertType(hCertType);
  243. }
  244. return hr;
  245. }
  246. HRESULT
  247. CACreateAutoEnrollmentObjectEx(
  248. IN LPCWSTR pwszCertType,
  249. IN LPCWSTR wszObjectID,
  250. IN WCHAR ** awszCAs,
  251. IN PCMSG_SIGNED_ENCODE_INFO pSignerInfo,
  252. IN LPCSTR StoreProvider,
  253. IN DWORD dwFlags,
  254. IN const void * pvPara)
  255. {
  256. HRESULT hr = S_OK;
  257. BYTE *pbEncodedCTL = NULL;
  258. DWORD cbEncodedCTL;
  259. HCERTSTORE hStore = 0;
  260. BOOL fMachine = ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) == CERT_SYSTEM_STORE_LOCAL_MACHINE);
  261. hr = BuildAutoEnrollmentCTL(pwszCertType,
  262. wszObjectID,
  263. fMachine,
  264. awszCAs,
  265. pSignerInfo,
  266. &pbEncodedCTL,
  267. &cbEncodedCTL
  268. );
  269. if(hr != S_OK)
  270. {
  271. goto error;
  272. }
  273. // open the Trust store and fine the CTL based on the auto enrollment usage
  274. hStore = CertOpenStore(StoreProvider, 0, NULL, dwFlags, pvPara);
  275. if(hStore == NULL)
  276. {
  277. hr = myHLastError();
  278. goto error;
  279. }
  280. if (!CertAddEncodedCTLToStore(hStore,
  281. X509_ASN_ENCODING,
  282. pbEncodedCTL,
  283. cbEncodedCTL,
  284. CERT_STORE_ADD_REPLACE_EXISTING,
  285. NULL))
  286. {
  287. hr = myHLastError();
  288. goto error;
  289. }
  290. error:
  291. if (pbEncodedCTL)
  292. {
  293. LocalFree(pbEncodedCTL);
  294. }
  295. if (hStore)
  296. {
  297. CertCloseStore(hStore, 0);
  298. }
  299. return hr;
  300. }
  301. HRESULT
  302. CACreateLocalAutoEnrollmentObject(
  303. IN LPCWSTR pwszCertType,
  304. IN WCHAR ** awszCAs,
  305. IN PCMSG_SIGNED_ENCODE_INFO pSignerInfo,
  306. IN DWORD dwFlags)
  307. {
  308. HRESULT hr = S_OK;
  309. BYTE *pbEncodedCTL = NULL;
  310. DWORD cbEncodedCTL;
  311. HCERTSTORE hStore = 0;
  312. BOOL fMachine = ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) == CERT_SYSTEM_STORE_LOCAL_MACHINE);
  313. hr = BuildAutoEnrollmentCTL(pwszCertType,
  314. NULL,
  315. fMachine,
  316. awszCAs,
  317. pSignerInfo,
  318. &pbEncodedCTL,
  319. &cbEncodedCTL
  320. );
  321. if(hr != S_OK)
  322. {
  323. goto error;
  324. }
  325. // open the Trust store and fine the CTL based on the auto enrollment usage
  326. hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, NULL, dwFlags, L"ACRS");
  327. if(hStore == NULL)
  328. {
  329. hr = myHLastError();
  330. goto error;
  331. }
  332. if (!CertAddEncodedCTLToStore(hStore,
  333. X509_ASN_ENCODING,
  334. pbEncodedCTL,
  335. cbEncodedCTL,
  336. CERT_STORE_ADD_REPLACE_EXISTING,
  337. NULL))
  338. {
  339. hr = myHLastError();
  340. goto error;
  341. }
  342. error:
  343. if (pbEncodedCTL)
  344. {
  345. LocalFree(pbEncodedCTL);
  346. }
  347. if (hStore)
  348. {
  349. CertCloseStore(hStore, 0);
  350. }
  351. return hr;
  352. }
  353. //--------------------------------------------------------------------------------
  354. //
  355. // CADeleteLocalAutoEnrollmentObject
  356. //
  357. //---------------------------------------------------------------------------------
  358. HRESULT
  359. CADeleteLocalAutoEnrollmentObject(
  360. IN LPCWSTR pwszCertType,
  361. IN OPTIONAL WCHAR ** awszCAs,
  362. IN OPTIONAL PCMSG_SIGNED_ENCODE_INFO pSignerInfo,
  363. IN DWORD dwFlags)
  364. {
  365. HRESULT hr=E_FAIL;
  366. CTL_FIND_USAGE_PARA CTLFindParam;
  367. LPSTR pszUsageIdentifier=NULL;
  368. HCERTSTORE hCertStore=NULL;
  369. PCCTL_CONTEXT pCTLContext=NULL; //no need to free the CTL since it is freed by the DeleteCTL call
  370. memset(&CTLFindParam, 0, sizeof(CTL_FIND_USAGE_PARA));
  371. if((NULL==pwszCertType)||(NULL!=awszCAs)||(NULL!=pSignerInfo))
  372. {
  373. hr=E_INVALIDARG;
  374. goto error;
  375. }
  376. //open the store based on dwFlags
  377. hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, NULL, dwFlags, L"ACRS");
  378. if(NULL == hCertStore)
  379. {
  380. hr = myHLastError();
  381. goto error;
  382. }
  383. //set up the find parameter
  384. CTLFindParam.cbSize=sizeof(CTLFindParam);
  385. CTLFindParam.SubjectUsage.cUsageIdentifier = 1;
  386. pszUsageIdentifier = szOID_AUTO_ENROLL_CTL_USAGE;
  387. CTLFindParam.SubjectUsage.rgpszUsageIdentifier = &pszUsageIdentifier;
  388. CTLFindParam.ListIdentifier.cbData=(wcslen(pwszCertType) + 1) * sizeof(WCHAR);
  389. CTLFindParam.ListIdentifier.pbData=(BYTE *)(pwszCertType);
  390. //only find CTLs with no signers
  391. CTLFindParam.pSigner=CTL_FIND_NO_SIGNER_PTR;
  392. //find the CTL based on the pwszCertType
  393. if(NULL == (pCTLContext=CertFindCTLInStore(
  394. hCertStore,
  395. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  396. 0,
  397. CTL_FIND_USAGE,
  398. &CTLFindParam,
  399. NULL)))
  400. {
  401. hr=CRYPT_E_NOT_FOUND;
  402. goto error;
  403. }
  404. //delete the CTL. The CTL is automatically freed
  405. if(!CertDeleteCTLFromStore(pCTLContext))
  406. {
  407. hr = myHLastError();
  408. goto error;
  409. }
  410. hr=S_OK;
  411. error:
  412. if(hCertStore)
  413. CertCloseStore(hCertStore, 0);
  414. return hr;
  415. }