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.

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