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.

504 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1998
  6. //
  7. // File: cepca.cpp
  8. //
  9. // Contents: Cisco enrollment protocal implementation.
  10. // This file has CA specific code.
  11. //
  12. //
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "global.hxx"
  16. #include <dbgdef.h>
  17. //--------------------------------------------------------------------------
  18. //
  19. // InitCAInformation
  20. //
  21. //--------------------------------------------------------------------------
  22. BOOL InitCAInformation(CEP_CA_INFO *pCAInfo)
  23. {
  24. BOOL fResult = FALSE;
  25. long nCount=0;
  26. long nIndex=0;
  27. WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  28. DWORD dwSize=MAX_COMPUTERNAME_LENGTH + 1;
  29. HRESULT hr = E_FAIL;
  30. DWORD cbData=0;
  31. DWORD dwData=0;
  32. DWORD dwType=0;
  33. long dwErr=0;
  34. ICertConfig *pICertConfig=NULL;
  35. BSTR bstrFieldName=NULL;
  36. BSTR bstrFieldValue=NULL;
  37. HKEY hKeyCAType=NULL;
  38. HKEY hKeyCEP=NULL;
  39. memset(pCAInfo, 0, sizeof(CEP_CA_INFO));
  40. //we should only worry about the NetBois name. Do not care about the DNS
  41. //GetComputerNameW in Win2K only returns NetBois name
  42. if(!GetComputerNameW(wszComputerName, &dwSize))
  43. goto TraceErr;
  44. if(S_OK != (hr=CoCreateInstance(CLSID_CCertConfig,
  45. NULL,
  46. CLSCTX_INPROC_SERVER,
  47. IID_ICertConfig,
  48. (void **)&pICertConfig)))
  49. goto CertSrvErr;
  50. if(S_OK != (hr=pICertConfig->Reset(nIndex, &nCount)))
  51. goto CertSrvErr;
  52. if(0==nCount)
  53. goto NoSrvErr;
  54. if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_SERVER)))
  55. goto MemoryErr;
  56. while(nIndex != -1)
  57. {
  58. //find the configuration that matches the current machine's name
  59. if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &bstrFieldValue)))
  60. goto CertSrvErr;
  61. if(0==_wcsnicmp(bstrFieldValue, wszComputerName, wcslen(wszComputerName)))
  62. {
  63. if(NULL == ((pCAInfo->bstrCAMachine)=SysAllocString(bstrFieldValue)))
  64. goto MemoryErr;
  65. //CA name
  66. SysFreeString(bstrFieldName);
  67. bstrFieldName=NULL;
  68. if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_AUTHORITY)))
  69. goto MemoryErr;
  70. if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &(pCAInfo->bstrCAName))))
  71. goto CertSrvErr;
  72. if(NULL == pCAInfo->bstrCAName)
  73. goto FailErr;
  74. //CA config
  75. SysFreeString(bstrFieldName);
  76. bstrFieldName=NULL;
  77. if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_CONFIG)))
  78. goto MemoryErr;
  79. if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &(pCAInfo->bstrCAConfig))))
  80. goto CertSrvErr;
  81. if(NULL == pCAInfo->bstrCAConfig)
  82. goto FailErr;
  83. //DSName
  84. SysFreeString(bstrFieldName);
  85. bstrFieldName=NULL;
  86. if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_SANITIZEDSHORTNAME)))
  87. goto MemoryErr;
  88. if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &(pCAInfo->bstrDSName))))
  89. goto CertSrvErr;
  90. if(NULL == pCAInfo->bstrDSName)
  91. goto FailErr;
  92. //ICertRequest
  93. if(S_OK != (hr=CoCreateInstance(CLSID_CCertRequest,
  94. NULL,
  95. CLSCTX_INPROC_SERVER,
  96. IID_ICertRequest,
  97. (void **)&(pCAInfo->pICertRequest))))
  98. goto CertSrvErr;
  99. //success
  100. break;
  101. }
  102. SysFreeString(bstrFieldValue);
  103. bstrFieldValue=NULL;
  104. hr = pICertConfig->Next(&nIndex);
  105. if( (S_OK != hr) && (-1 != nIndex))
  106. goto CertSrvErr;
  107. }
  108. if(-1 == nIndex)
  109. goto NoSrvErr;
  110. //get the CA's type from the registry
  111. cbData=sizeof(dwData);
  112. //we have to have the knowledge of the ca type
  113. if(ERROR_SUCCESS != (dwErr = RegOpenKeyExU(
  114. HKEY_LOCAL_MACHINE,
  115. MSCEP_CATYPE_LOCATION,
  116. 0,
  117. KEY_READ,
  118. &hKeyCAType)))
  119. goto RegErr;
  120. if(ERROR_SUCCESS != (dwErr = RegQueryValueExU(
  121. hKeyCAType,
  122. MSCEP_KEY_CATYPE,
  123. NULL,
  124. &dwType,
  125. (BYTE *)&dwData,
  126. &cbData)))
  127. goto RegErr;
  128. if ((dwType != REG_DWORD) &&
  129. (dwType != REG_BINARY))
  130. goto RegErr;
  131. if(0 == dwData)
  132. pCAInfo->fEnterpriseCA=FALSE;
  133. else
  134. pCAInfo->fEnterpriseCA=TRUE;
  135. if(pCAInfo->fEnterpriseCA)
  136. {
  137. //get the template name for key usage requests
  138. if(ERROR_SUCCESS != (dwErr = RegOpenKeyExU(
  139. HKEY_LOCAL_MACHINE,
  140. MSCEP_LOCATION,
  141. 0,
  142. KEY_READ,
  143. &hKeyCEP)))
  144. goto RegErr;
  145. //signature template
  146. cbData=0;
  147. if(ERROR_SUCCESS == (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_SIG_TEMPLATE,
  148. NULL, &dwType, NULL, &cbData)))
  149. {
  150. if((REG_SZ == dwType) && (1 < cbData))
  151. {
  152. pCAInfo->pwszTemplateSig=(LPWSTR)malloc(cbData);
  153. if(NULL == pCAInfo->pwszTemplateSig)
  154. goto MemoryErr;
  155. if(ERROR_SUCCESS != (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_SIG_TEMPLATE,
  156. NULL, &dwType, (BYTE *)(pCAInfo->pwszTemplateSig), &cbData)))
  157. goto RegErr;
  158. }
  159. }
  160. //encryption template
  161. cbData=0;
  162. if(ERROR_SUCCESS == (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_ENCYPT_TEMPLATE,
  163. NULL, &dwType, NULL, &cbData)))
  164. {
  165. if((REG_SZ == dwType) && (1 < cbData))
  166. {
  167. pCAInfo->pwszTemplateEnt=(LPWSTR)malloc(cbData);
  168. if(NULL == pCAInfo->pwszTemplateEnt)
  169. goto MemoryErr;
  170. if(ERROR_SUCCESS != (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_ENCYPT_TEMPLATE,
  171. NULL, &dwType, (BYTE *)(pCAInfo->pwszTemplateEnt), &cbData)))
  172. goto RegErr;
  173. }
  174. }
  175. //make sure both templates are present in the DS
  176. //make sure the CA does issue the template
  177. if(pCAInfo->pwszTemplateSig)
  178. {
  179. if(S_OK != (hr=CheckACLOnCertTemplate(FALSE, pCAInfo->bstrDSName, pCAInfo->pwszTemplateSig)))
  180. {
  181. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_NO_ENROLL, 3, g_pwszComputerName, pCAInfo->pwszTemplateSig, pCAInfo->bstrDSName);
  182. goto CertSrvErr;
  183. }
  184. }
  185. if(pCAInfo->pwszTemplateEnt)
  186. {
  187. if(S_OK != (hr=CheckACLOnCertTemplate(FALSE, pCAInfo->bstrDSName, pCAInfo->pwszTemplateEnt)))
  188. {
  189. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_NO_ENROLL, 3, g_pwszComputerName, pCAInfo->pwszTemplateEnt, pCAInfo->bstrDSName);
  190. goto CertSrvErr;
  191. }
  192. }
  193. if(S_OK != (hr=CheckACLOnCertTemplate(FALSE, pCAInfo->bstrDSName, wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE)))
  194. {
  195. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_NO_ENROLL, 3, g_pwszComputerName, wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE, pCAInfo->bstrDSName);
  196. goto CertSrvErr;
  197. }
  198. }
  199. //get the hProv to generate the random password
  200. if(!CryptAcquireContextU(&(pCAInfo->hProv),
  201. NULL,
  202. MS_DEF_PROV_W,
  203. PROV_RSA_FULL,
  204. CRYPT_VERIFYCONTEXT))
  205. goto TraceErr;
  206. fResult = TRUE;
  207. CommonReturn:
  208. if(hKeyCEP)
  209. RegCloseKey(hKeyCEP);
  210. if(hKeyCAType)
  211. RegCloseKey(hKeyCAType);
  212. if(bstrFieldName)
  213. SysFreeString(bstrFieldName);
  214. if(bstrFieldValue)
  215. SysFreeString(bstrFieldValue);
  216. if(pICertConfig)
  217. pICertConfig->Release();
  218. return fResult;
  219. ErrorReturn:
  220. FreeCAInformation(pCAInfo);
  221. fResult=FALSE;
  222. goto CommonReturn;
  223. SET_ERROR_VAR(CertSrvErr, hr);
  224. SET_ERROR(NoSrvErr, E_FAIL);
  225. TRACE_ERROR(TraceErr);
  226. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  227. SET_ERROR(FailErr, E_FAIL);
  228. SET_ERROR_VAR(RegErr, dwErr);
  229. }
  230. //--------------------------------------------------------------------------
  231. //
  232. // GetCACertFromInfo
  233. //
  234. //--------------------------------------------------------------------------
  235. BOOL GetCACertFromInfo(CEP_CA_INFO *pCAInfo, HCERTSTORE *pHCACertStore)
  236. {
  237. BOOL fResult = FALSE;
  238. HRESULT hr = S_OK;
  239. CERT_BLOB CertBlob;
  240. DWORD dwFlags=0;
  241. PCCERT_CONTEXT pPreCert=NULL;
  242. DWORD cbData=0;
  243. BSTR bstrCACert=NULL;
  244. PCCERT_CONTEXT pCurCert=NULL;
  245. BYTE *pbData=NULL;
  246. if(NULL == (pCAInfo->pICertRequest))
  247. goto InvalidArgErr;
  248. //NT5 SPECIFIC: fExchangeCertificate can only be FALSE
  249. if(S_OK != (hr=(pCAInfo->pICertRequest)->GetCACertificate(
  250. FALSE,
  251. pCAInfo->bstrCAConfig,
  252. CR_OUT_BINARY | CR_OUT_CHAIN,
  253. &bstrCACert)))
  254. goto CAErr;
  255. if(NULL == bstrCACert)
  256. goto UnexpectedErr;
  257. CertBlob.cbData = (DWORD)SysStringByteLen(bstrCACert);
  258. CertBlob.pbData = (BYTE *)bstrCACert;
  259. if(NULL == (*pHCACertStore = CertOpenStore(
  260. CERT_STORE_PROV_PKCS7,
  261. ENCODE_TYPE,
  262. NULL,
  263. 0,
  264. &CertBlob)))
  265. goto TraceErr;
  266. //we now need to get the CA's certificate's MD5 hash
  267. while(pCurCert=CertEnumCertificatesInStore(*pHCACertStore,
  268. pPreCert))
  269. {
  270. dwFlags = CERT_STORE_SIGNATURE_FLAG;
  271. if(CertVerifySubjectCertificateContext(pCurCert,
  272. pCurCert,
  273. &dwFlags) && (0==dwFlags))
  274. break;
  275. pPreCert=pCurCert;
  276. }
  277. if(NULL==pCurCert)
  278. goto InvalidArgErr;
  279. //get the MD5 hash
  280. if(!CertGetCertificateContextProperty(pCurCert,
  281. CERT_MD5_HASH_PROP_ID,
  282. NULL,
  283. &cbData))
  284. goto TraceErr;
  285. pbData=(BYTE *)malloc(cbData);
  286. if(NULL==pbData)
  287. goto MemoryErr;
  288. if(!CertGetCertificateContextProperty(pCurCert,
  289. CERT_MD5_HASH_PROP_ID,
  290. pbData,
  291. &cbData))
  292. goto TraceErr;
  293. if(!ConvertByteToWstr(pbData, cbData, &(pCAInfo->pwszCAHash), TRUE))
  294. goto TraceErr;
  295. fResult = TRUE;
  296. CommonReturn:
  297. if(pbData)
  298. free(pbData);
  299. if(pCurCert)
  300. CertFreeCertificateContext(pCurCert);
  301. if(bstrCACert)
  302. SysFreeString(bstrCACert);
  303. return fResult;
  304. ErrorReturn:
  305. fResult=FALSE;
  306. goto CommonReturn;
  307. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  308. SET_ERROR_VAR(CAErr, hr);
  309. TRACE_ERROR(TraceErr);
  310. SET_ERROR(UnexpectedErr, E_UNEXPECTED);
  311. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  312. }
  313. //--------------------------------------------------------------------------
  314. //
  315. // FreeCAInformation
  316. //
  317. //--------------------------------------------------------------------------
  318. BOOL FreeCAInformation(CEP_CA_INFO *pCAInfo)
  319. {
  320. if(pCAInfo)
  321. {
  322. if(pCAInfo->bstrCAMachine)
  323. SysFreeString(pCAInfo->bstrCAMachine);
  324. if(pCAInfo->bstrCAName)
  325. SysFreeString(pCAInfo->bstrCAName);
  326. if(pCAInfo->bstrCAConfig)
  327. SysFreeString(pCAInfo->bstrCAConfig);
  328. if(pCAInfo->bstrDSName)
  329. SysFreeString(pCAInfo->bstrDSName);
  330. if(pCAInfo->pwszCAHash)
  331. free(pCAInfo->pwszCAHash);
  332. if(pCAInfo->hProv)
  333. CryptReleaseContext(pCAInfo->hProv, 0);
  334. if(pCAInfo->pICertRequest)
  335. (pCAInfo->pICertRequest)->Release();
  336. if(pCAInfo->pwszTemplateSig)
  337. free(pCAInfo->pwszTemplateSig);
  338. if(pCAInfo->pwszTemplateEnt)
  339. free(pCAInfo->pwszTemplateEnt);
  340. //reset the data
  341. memset(pCAInfo, 0, sizeof(CEP_CA_INFO));
  342. }
  343. return TRUE;
  344. }
  345. //--------------------------------------------------------------------------
  346. //
  347. // OperationGetCACert
  348. //
  349. //--------------------------------------------------------------------------
  350. BOOL OperationGetCACert(HCERTSTORE hCACertStore,
  351. LPSTR szMsg,
  352. BYTE **ppbData,
  353. DWORD *pcbData)
  354. {
  355. BOOL fResult = FALSE;
  356. CERT_BLOB CertBlob;
  357. CertBlob.cbData=0;
  358. CertBlob.pbData=NULL;
  359. if(!CertSaveStore(hCACertStore,
  360. ENCODE_TYPE,
  361. CERT_STORE_SAVE_AS_PKCS7,
  362. CERT_STORE_SAVE_TO_MEMORY,
  363. &CertBlob,
  364. 0))
  365. goto CertErr;
  366. CertBlob.pbData = (BYTE *)malloc(CertBlob.cbData);
  367. if(NULL == CertBlob.pbData)
  368. goto MemoryErr;
  369. if(!CertSaveStore(hCACertStore,
  370. ENCODE_TYPE,
  371. CERT_STORE_SAVE_AS_PKCS7,
  372. CERT_STORE_SAVE_TO_MEMORY,
  373. &CertBlob,
  374. 0))
  375. goto CertErr;
  376. //copy the memory
  377. *ppbData=CertBlob.pbData;
  378. *pcbData=CertBlob.cbData;
  379. CertBlob.pbData=NULL;
  380. fResult = TRUE;
  381. CommonReturn:
  382. if(CertBlob.pbData)
  383. free(CertBlob.pbData);
  384. return fResult;
  385. ErrorReturn:
  386. fResult=FALSE;
  387. goto CommonReturn;
  388. TRACE_ERROR(CertErr);
  389. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  390. }