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.

1961 lines
46 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: cainfoc.cpp
  7. //
  8. // Contents: CCAInfo implemenation
  9. //
  10. // History: 16-Dec-97 petesk created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "pch.cpp"
  14. #pragma hdrstop
  15. #include "cainfoc.h"
  16. #include "certtype.h"
  17. #include "csldap.h"
  18. #include <lm.h>
  19. #include <certca.h>
  20. #include <polreg.h>
  21. #include <dsgetdc.h>
  22. #include <winldap.h>
  23. #include <cainfop.h>
  24. #include <ntldap.h>
  25. #define __dwFILE__ __dwFILE_CERTCLIB_CAINFOC_CPP__
  26. #define wcLBRACE L'{'
  27. #define wcRBRACE L'}'
  28. LPCWSTR g_wszEnrollmentServiceLocation = L"CN=Enrollment Services,CN=Public Key Services,CN=Services,";
  29. #define LDAP_SECURITY_DESCRIPTOR_NAME L"NTSecurityDescriptor"
  30. #define LDAP_CERTIFICATE_TEMPLATES_NAME L"certificateTemplates"
  31. WCHAR *g_awszCAAttrs[] = {
  32. CA_PROP_NAME,
  33. CA_PROP_DISPLAY_NAME,
  34. CA_PROP_FLAGS,
  35. CA_PROP_DNSNAME,
  36. CA_PROP_DSLOCATION,
  37. CA_PROP_CERT_DN,
  38. CA_PROP_CERT_TYPES,
  39. CA_PROP_SIGNATURE_ALGS,
  40. CA_PROP_DESCRIPTION,
  41. L"cACertificate",
  42. L"objectClass",
  43. LDAP_SECURITY_DESCRIPTOR_NAME,
  44. NULL};
  45. WCHAR *g_awszCANamedProps[] = {
  46. CA_PROP_NAME,
  47. CA_PROP_DISPLAY_NAME,
  48. CA_PROP_DNSNAME,
  49. CA_PROP_DSLOCATION,
  50. CA_PROP_CERT_DN,
  51. CA_PROP_CERT_TYPES,
  52. CA_PROP_SIGNATURE_ALGS,
  53. CA_PROP_DESCRIPTION,
  54. NULL};
  55. LPWSTR g_awszSignatureAlgs[] = {
  56. TEXT(szOID_RSA_MD2RSA),
  57. TEXT(szOID_RSA_MD4RSA),
  58. TEXT(szOID_RSA_MD5RSA),
  59. TEXT(szOID_RSA_SHA1RSA),
  60. NULL
  61. };
  62. //+--------------------------------------------------------------------------
  63. // CCAInfo::~CCAInfo -- destructor
  64. //
  65. // free memory associated with this instance
  66. //+--------------------------------------------------------------------------
  67. CCAInfo::~CCAInfo()
  68. {
  69. _Cleanup();
  70. }
  71. //+--------------------------------------------------------------------------
  72. // CCAInfo::_Cleanup -- free memory
  73. //
  74. // free memory associated with this instance
  75. //+--------------------------------------------------------------------------
  76. HRESULT
  77. CCAInfo::_Cleanup()
  78. {
  79. // Cleanup will only be called if there is no previous element
  80. // to reference this element, and the caller is also releaseing.
  81. // If there is a further element, release it.
  82. if (NULL != m_pNext)
  83. {
  84. m_pNext->Release();
  85. m_pNext = NULL;
  86. }
  87. CCAProperty::DeleteChain(&m_pProperties);
  88. if (NULL != m_pCertificate)
  89. {
  90. CertFreeCertificateContext(m_pCertificate);
  91. m_pCertificate = NULL;
  92. }
  93. if (NULL != m_bstrDN)
  94. {
  95. CertFreeString(m_bstrDN);
  96. m_bstrDN = NULL;
  97. }
  98. if (NULL != m_pSD)
  99. {
  100. LocalFree(m_pSD);
  101. m_pSD = NULL;
  102. }
  103. return(S_OK);
  104. }
  105. //+--------------------------------------------------------------------------
  106. // CCAInfo::_Cleanup -- add reference
  107. //
  108. //
  109. //+--------------------------------------------------------------------------
  110. DWORD
  111. CCAInfo::AddRef()
  112. {
  113. return(InterlockedIncrement(&m_cRef));
  114. }
  115. //+--------------------------------------------------------------------------
  116. // CCAInfo::Release -- release reference
  117. //
  118. //
  119. //+--------------------------------------------------------------------------
  120. DWORD CCAInfo::Release()
  121. {
  122. DWORD cRef;
  123. if (0 == (cRef = InterlockedDecrement(&m_cRef)))
  124. {
  125. delete this;
  126. }
  127. return(cRef);
  128. }
  129. //+--------------------------------------------------------------------------
  130. // CCAInfo::Find -- Find CA Objects in the DS
  131. //
  132. //
  133. //+--------------------------------------------------------------------------
  134. HRESULT
  135. CCAInfo::Find(
  136. LPCWSTR wszQuery,
  137. LPCWSTR wszScope,
  138. DWORD dwFlags,
  139. CCAInfo **ppCAInfo)
  140. {
  141. HRESULT hr = S_OK;
  142. ULONG ldaperr;
  143. LDAP * pld = NULL;
  144. // Initialize LDAP session
  145. WCHAR * wszSearch = L"(objectCategory=pKIEnrollmentService)";
  146. DWORD cSearchParam;
  147. CERTSTR bstrSearchParam = NULL;
  148. CERTSTR bstrScope = NULL;
  149. CERTSTR bstrConfig = NULL;
  150. CERTSTR bstrDomain = NULL;
  151. if (NULL == ppCAInfo)
  152. {
  153. hr = E_POINTER;
  154. _JumpError(hr, error, "NULL parm");
  155. }
  156. // short circuit calls to a nonexistant DS
  157. hr = myDoesDSExist(TRUE);
  158. _JumpIfError4(
  159. hr,
  160. error,
  161. "myDoesDSExist",
  162. HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED),
  163. HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN),
  164. HRESULT_FROM_WIN32(ERROR_NETWORK_UNREACHABLE));
  165. __try
  166. {
  167. if(CA_FLAG_SCOPE_IS_LDAP_HANDLE & dwFlags)
  168. {
  169. pld = (LDAP *)wszScope;
  170. }
  171. else
  172. {
  173. // bind to ds
  174. hr = myRobustLdapBind(&pld, FALSE);
  175. if(hr != S_OK)
  176. {
  177. _LeaveError2(
  178. hr,
  179. "myRobustLdapBind",
  180. HRESULT_FROM_WIN32(ERROR_WRONG_PASSWORD));
  181. }
  182. if(wszScope)
  183. {
  184. bstrScope = CertAllocString((LPWSTR)wszScope);
  185. if(bstrScope == NULL)
  186. {
  187. hr = E_OUTOFMEMORY;
  188. _LeaveError(hr, "CertAllocString");
  189. }
  190. }
  191. }
  192. if(bstrScope == NULL)
  193. {
  194. // If scope is not specified, set it to the
  195. // current domain scope.
  196. hr = CAGetAuthoritativeDomainDn(pld, &bstrDomain, &bstrConfig);
  197. if(S_OK != hr)
  198. {
  199. _LeaveError(hr, "CAGetAuthoritativeDomainDn");
  200. }
  201. bstrScope = CertAllocStringLen(
  202. NULL,
  203. wcslen(bstrConfig) + wcslen(g_wszEnrollmentServiceLocation));
  204. if(bstrScope == NULL)
  205. {
  206. hr = E_OUTOFMEMORY;
  207. _LeaveError(hr, "CertAllocStringLen");
  208. }
  209. wcscpy(bstrScope, g_wszEnrollmentServiceLocation);
  210. wcscat(bstrScope, bstrConfig);
  211. }
  212. if (NULL != wszQuery)
  213. {
  214. // If a query is specified, then combine it with the
  215. // objectCategory=pKIEnrollmentService query
  216. cSearchParam = 2 + wcslen(wszSearch) + wcslen(wszQuery) + 2;
  217. bstrSearchParam = CertAllocStringLen(NULL,cSearchParam);
  218. if(bstrSearchParam == NULL)
  219. {
  220. hr = E_OUTOFMEMORY;
  221. _LeaveError(hr, "CertAllocStringLen");
  222. }
  223. wcscpy(bstrSearchParam, L"(&");
  224. wcscat(bstrSearchParam, wszSearch);
  225. wcscat(bstrSearchParam, wszQuery);
  226. wcscat(bstrSearchParam, L")");
  227. }
  228. hr = _ProcessFind(pld,
  229. (wszQuery? bstrSearchParam : wszSearch),
  230. bstrScope,
  231. dwFlags,
  232. ppCAInfo);
  233. if(hr != S_OK)
  234. {
  235. _LeaveError(hr, "_ProcessFind");
  236. }
  237. }
  238. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  239. {
  240. }
  241. error:
  242. if (NULL != bstrScope)
  243. {
  244. CertFreeString(bstrScope);
  245. }
  246. if( NULL != bstrConfig)
  247. {
  248. CertFreeString(bstrConfig);
  249. }
  250. if( NULL != bstrDomain)
  251. {
  252. CertFreeString(bstrDomain);
  253. }
  254. if (NULL != bstrSearchParam)
  255. {
  256. CertFreeString(bstrSearchParam);
  257. }
  258. if(0 == (CA_FLAG_SCOPE_IS_LDAP_HANDLE & dwFlags))
  259. {
  260. if (NULL != pld)
  261. {
  262. ldap_unbind(pld);
  263. }
  264. }
  265. return(hr);
  266. }
  267. //+--------------------------------------------------------------------------
  268. // CCAInfo::_ProcessFind -- ProcessFind CA Objects in the DS
  269. //
  270. //
  271. //+--------------------------------------------------------------------------
  272. HRESULT
  273. CCAInfo::_ProcessFind(
  274. LDAP * pld,
  275. LPCWSTR wszQuery,
  276. LPCWSTR wszScope,
  277. DWORD dwFlags,
  278. CCAInfo **ppCAInfo)
  279. {
  280. HRESULT hr = S_OK;
  281. ULONG ldaperr;
  282. CCAInfo *pCAFirst = NULL;
  283. CCAInfo *pCACurrent = NULL;
  284. // Initialize LDAP session
  285. CHAR sdBerValue[] = {0x30, 0x03, 0x02, 0x01, DACL_SECURITY_INFORMATION |
  286. OWNER_SECURITY_INFORMATION |
  287. GROUP_SECURITY_INFORMATION};
  288. LDAPControl se_info_control =
  289. {
  290. LDAP_SERVER_SD_FLAGS_OID_W,
  291. {
  292. 5, sdBerValue
  293. },
  294. TRUE
  295. };
  296. PLDAPControl server_controls[2] =
  297. {
  298. &se_info_control,
  299. NULL
  300. };
  301. LDAPMessage *SearchResult = NULL, *Entry;
  302. struct berval **apCerts;
  303. struct berval **apSD;
  304. // Chain verification stuff
  305. CERT_CHAIN_PARA ChainParams;
  306. CERT_CHAIN_POLICY_PARA ChainPolicy;
  307. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  308. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  309. PCCERT_CONTEXT pCert = NULL;
  310. DWORD cEntries;
  311. // search timeout
  312. struct l_timeval timeout;
  313. if (NULL == ppCAInfo)
  314. {
  315. hr = E_POINTER;
  316. _JumpError(hr, error, "NULL parm");
  317. }
  318. *ppCAInfo = NULL;
  319. DBGPRINT((
  320. DBG_SS_CERTLIBI,
  321. "_ProcessFind(Query=%ws, Scope=%ws, Flags=%x)\n",
  322. wszQuery,
  323. wszScope,
  324. dwFlags));
  325. timeout.tv_sec = csecLDAPTIMEOUT;
  326. timeout.tv_usec = 0;
  327. // Perform search.
  328. ldaperr = ldap_search_ext_sW(pld,
  329. (LPWSTR)wszScope,
  330. LDAP_SCOPE_SUBTREE,
  331. (LPWSTR)wszQuery,
  332. g_awszCAAttrs,
  333. 0,
  334. (PLDAPControl *)&server_controls,
  335. NULL,
  336. &timeout,
  337. 10000,
  338. &SearchResult);
  339. if(ldaperr == LDAP_NO_SUCH_OBJECT)
  340. {
  341. // No entries were found.
  342. hr = S_OK;
  343. DBGPRINT((DBG_SS_CERTLIBI, "ldap_search_ext_sW: no entries\n"));
  344. goto error;
  345. }
  346. if(ldaperr != LDAP_SUCCESS)
  347. {
  348. hr = myHLdapError(pld, ldaperr, NULL);
  349. _JumpError(hr, error, "ldap_search_ext_sW");
  350. }
  351. cEntries = ldap_count_entries(pld, SearchResult);
  352. DBGPRINT((DBG_SS_CERTLIBI, "ldap_count_entries: %u entries\n", cEntries));
  353. if (0 == cEntries)
  354. {
  355. // No entries were found.
  356. hr = S_OK;
  357. goto error;
  358. }
  359. hr = S_OK;
  360. for(Entry = ldap_first_entry(pld, SearchResult);
  361. Entry != NULL;
  362. Entry = ldap_next_entry(pld, Entry))
  363. {
  364. CCAProperty *pProp;
  365. WCHAR ** pwszProp;
  366. WCHAR ** wszLdapVal;
  367. DWORD dwCAFlags = 0;
  368. if(pCert)
  369. {
  370. CertFreeCertificateContext(pCert);
  371. pCert = NULL;
  372. }
  373. if(pChainContext)
  374. {
  375. CertFreeCertificateChain(pChainContext);
  376. pChainContext = NULL;
  377. }
  378. wszLdapVal = ldap_get_values(pld, Entry, CA_PROP_FLAGS);
  379. if(wszLdapVal != NULL)
  380. {
  381. if(wszLdapVal[0] != NULL)
  382. {
  383. dwCAFlags = wcstoul(wszLdapVal[0], NULL, 10);
  384. }
  385. ldap_value_free(wszLdapVal);
  386. }
  387. DBGPRINT((DBG_SS_CERTLIBI, "dwCAFlags=%x\n", dwCAFlags));
  388. // Filter of flags
  389. if(( 0 == (dwFlags & CA_FIND_INCLUDE_NON_TEMPLATE_CA)) &&
  390. ( 0 != (dwCAFlags & CA_FLAG_NO_TEMPLATE_SUPPORT)))
  391. {
  392. // Don't include standalone CA's unless instructed to
  393. DBGPRINT((
  394. DBG_SS_CERTLIBI,
  395. "Skipping non-template CA, dwCAFlags=%x\n",
  396. dwCAFlags));
  397. continue;
  398. }
  399. // Get the CA Certificate
  400. apCerts = ldap_get_values_len(pld, Entry, L"cACertificate");
  401. if(apCerts && apCerts[0])
  402. {
  403. pCert = CertCreateCertificateContext(
  404. X509_ASN_ENCODING,
  405. (PBYTE)apCerts[0]->bv_val,
  406. apCerts[0]->bv_len);
  407. ldap_value_free_len(apCerts);
  408. }
  409. if(0 == (CA_FIND_INCLUDE_UNTRUSTED & dwFlags))
  410. {
  411. if (NULL == pCert)
  412. {
  413. DBGPRINT((DBG_SS_CERTLIBI, "Skipping cert-less CA\n"));
  414. continue; // skip this CA
  415. }
  416. // Verify cert and chain...
  417. hr = myVerifyCertContext(
  418. pCert,
  419. CA_VERIFY_FLAGS_IGNORE_OFFLINE |
  420. CA_VERIFY_FLAGS_NO_REVOCATION, // dwFlags
  421. 0, // cUsageOids
  422. NULL, // apszUsageOids
  423. (dwFlags & CA_FIND_LOCAL_SYSTEM)?
  424. HCCE_LOCAL_MACHINE : HCCE_CURRENT_USER,
  425. NULL, // hAdditionalStore
  426. NULL); // ppwszMissingIssuer
  427. if (S_OK != hr)
  428. {
  429. HRESULT hr2;
  430. WCHAR *pwszSubject = NULL;
  431. hr2 = myCertNameToStr(
  432. X509_ASN_ENCODING,
  433. &pCert->pCertInfo->Subject,
  434. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  435. &pwszSubject);
  436. _PrintIfError(hr2, "myCertNameToStr");
  437. _PrintErrorStr(hr, "myVerifyCertContext", pwszSubject);
  438. if (NULL != pwszSubject)
  439. {
  440. LocalFree(pwszSubject);
  441. }
  442. hr = S_OK;
  443. continue; // skip this CA
  444. }
  445. }
  446. // Is this the first one?
  447. if(pCACurrent)
  448. {
  449. pCACurrent->m_pNext = new CCAInfo;
  450. if(pCACurrent->m_pNext == NULL)
  451. {
  452. hr = E_OUTOFMEMORY;
  453. _JumpError(hr, error, "new");
  454. }
  455. pCACurrent = pCACurrent->m_pNext;
  456. }
  457. else
  458. {
  459. pCAFirst = pCACurrent = new CCAInfo;
  460. if(pCAFirst == NULL)
  461. {
  462. hr = E_OUTOFMEMORY;
  463. _JumpError(hr, error, "new");
  464. }
  465. }
  466. pCACurrent->m_pCertificate = pCert;
  467. pCert = NULL;
  468. WCHAR* wszDN = ldap_get_dnW(pld, Entry);
  469. if(NULL == wszDN)
  470. {
  471. hr = myHLdapLastError(pld, NULL);
  472. _JumpError(hr, error, "ldap_get_dnW");
  473. }
  474. pCACurrent->m_bstrDN = CertAllocString(wszDN);
  475. // ldap_get_dnW rtn value should be freed by calling ldap_memfree
  476. ldap_memfree(wszDN);
  477. // check success of CertAllocString
  478. if(pCACurrent->m_bstrDN == NULL)
  479. {
  480. hr = E_OUTOFMEMORY;
  481. _JumpError(hr, error, "CertAllocString");
  482. }
  483. // Add text properties from
  484. // DS lookup.
  485. for (pwszProp = g_awszCANamedProps; *pwszProp != NULL; pwszProp++)
  486. {
  487. pProp = new CCAProperty(*pwszProp);
  488. if(pProp == NULL)
  489. {
  490. hr = E_OUTOFMEMORY;
  491. _JumpError(hr, error, "new");
  492. }
  493. wszLdapVal = ldap_get_values(pld, Entry, *pwszProp);
  494. hr = pProp->SetValue(wszLdapVal);
  495. _PrintIfError(hr, "SetValue");
  496. if(wszLdapVal)
  497. {
  498. ldap_value_free(wszLdapVal);
  499. }
  500. if(hr == S_OK)
  501. {
  502. hr = CCAProperty::Append(&pCACurrent->m_pProperties, pProp);
  503. _PrintIfError(hr, "Append");
  504. }
  505. if(hr != S_OK)
  506. {
  507. CCAProperty::DeleteChain(&pProp);
  508. _JumpError(hr, error, "SetValue or Append");
  509. }
  510. }
  511. pCACurrent->m_dwFlags = dwCAFlags;
  512. // Append the security descriptor...
  513. apSD = ldap_get_values_len(pld, Entry, LDAP_SECURITY_DESCRIPTOR_NAME);
  514. if(apSD != NULL)
  515. {
  516. pCACurrent->m_pSD = LocalAlloc(LMEM_FIXED, (*apSD)->bv_len);
  517. if(pCACurrent->m_pSD == NULL)
  518. {
  519. hr = E_OUTOFMEMORY;
  520. ldap_value_free_len(apSD);
  521. _JumpError(hr, error, "LocalAlloc");
  522. }
  523. CopyMemory(pCACurrent->m_pSD, (*apSD)->bv_val, (*apSD)->bv_len);
  524. ldap_value_free_len(apSD);
  525. }
  526. pCACurrent->m_fNew = FALSE;
  527. }
  528. // May be null if none found.
  529. *ppCAInfo = pCAFirst;
  530. pCAFirst = NULL;
  531. error:
  532. if(SearchResult)
  533. {
  534. ldap_msgfree(SearchResult);
  535. }
  536. if (NULL != pCAFirst)
  537. {
  538. delete pCAFirst;
  539. }
  540. if(pCert)
  541. {
  542. CertFreeCertificateContext(pCert);
  543. }
  544. if(pChainContext)
  545. {
  546. CertFreeCertificateChain(pChainContext);
  547. }
  548. return(hr);
  549. }
  550. //+--------------------------------------------------------------------------
  551. // CCAInfo::Create -- Create CA Object in the DS
  552. //
  553. //
  554. //+--------------------------------------------------------------------------
  555. HRESULT
  556. CCAInfo::Create(
  557. LPCWSTR wszName,
  558. LPCWSTR wszScope,
  559. CCAInfo **ppCAInfo)
  560. {
  561. HRESULT hr = S_OK;
  562. ULONG ldaperr;
  563. CCAInfo *pCACurrent = NULL;
  564. LDAP * pld = NULL;
  565. // Initialize LDAP session
  566. DWORD cFullLocation;
  567. CERTSTR bstrScope = NULL;
  568. LPWSTR cnVals[2];
  569. CCAProperty *pProp;
  570. struct berval **apSD;
  571. if (NULL == ppCAInfo || NULL == wszName)
  572. {
  573. hr = E_POINTER;
  574. _JumpError(hr, error, "NULL parm");
  575. }
  576. // short circuit calls to a nonexistant DS
  577. hr = myDoesDSExist(TRUE);
  578. _JumpIfError(hr, error, "myDoesDSExist");
  579. __try
  580. {
  581. // bind to ds
  582. hr = myRobustLdapBind(&pld, FALSE);
  583. if(hr != S_OK)
  584. {
  585. _LeaveError(hr, "myRobustLdapBind");
  586. }
  587. if(wszScope)
  588. {
  589. bstrScope = CertAllocString(wszScope);
  590. if(bstrScope == NULL)
  591. {
  592. hr = E_OUTOFMEMORY;
  593. _LeaveError(hr, "CertAllocString");
  594. }
  595. }
  596. else
  597. {
  598. // If scope is not specified, set it to the
  599. // current domain scope.
  600. hr = CAGetAuthoritativeDomainDn(pld, NULL, &bstrScope);
  601. if(S_OK != hr)
  602. {
  603. _LeaveError(hr, "CAGetAuthoritativeDomainDn");
  604. }
  605. }
  606. pCACurrent = new CCAInfo;
  607. if(pCACurrent == NULL)
  608. {
  609. hr = E_OUTOFMEMORY;
  610. _LeaveError(hr, "new");
  611. }
  612. cFullLocation = 4 + wcslen(wszName) + wcslen(g_wszEnrollmentServiceLocation) + wcslen(bstrScope);
  613. pCACurrent->m_bstrDN = CertAllocStringLen(NULL, cFullLocation);
  614. if(pCACurrent->m_bstrDN == NULL)
  615. {
  616. hr = E_OUTOFMEMORY;
  617. _LeaveError(hr, "CertAllocStringLen");
  618. }
  619. wcscpy(pCACurrent->m_bstrDN, L"CN=");
  620. wcscat(pCACurrent->m_bstrDN, wszName);
  621. wcscat(pCACurrent->m_bstrDN, L",");
  622. wcscat(pCACurrent->m_bstrDN, g_wszEnrollmentServiceLocation);
  623. wcscat(pCACurrent->m_bstrDN, bstrScope);
  624. pProp = new CCAProperty(CA_PROP_NAME);
  625. if (pProp == NULL)
  626. {
  627. hr = E_OUTOFMEMORY;
  628. _LeaveError(hr, "new");
  629. }
  630. cnVals[0] = (LPWSTR)wszName;
  631. cnVals[1] = NULL;
  632. pProp->SetValue(cnVals);
  633. CCAProperty::Append(&pCACurrent->m_pProperties, pProp);
  634. pCACurrent->m_fNew = TRUE;
  635. *ppCAInfo = pCACurrent;
  636. pCACurrent = NULL;
  637. }
  638. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  639. {
  640. }
  641. error:
  642. if (NULL != bstrScope)
  643. {
  644. CertFreeString(bstrScope);
  645. }
  646. if (NULL != pld)
  647. {
  648. ldap_unbind(pld);
  649. }
  650. if (NULL != pCACurrent)
  651. {
  652. delete pCACurrent;
  653. }
  654. return(hr);
  655. }
  656. HRESULT
  657. CCAInfo::Update(VOID)
  658. {
  659. HRESULT hr = S_OK;
  660. ULONG ldaperr;
  661. LDAP *pld = NULL;
  662. LDAPMod objectClass,
  663. cnmod,
  664. displaymod,
  665. certmod,
  666. certdnmod,
  667. domainidmod,
  668. machinednsmod,
  669. certtypesmod,
  670. sigalgmods,
  671. Flagsmod,
  672. sdmod,
  673. Descriptionmod;
  674. WCHAR *awszNull[1] = { NULL };
  675. DWORD err;
  676. DWORD cName;
  677. TCHAR *objectClassVals[3], *certdnVals[2];
  678. LDAPMod *mods[13];
  679. struct berval certberval;
  680. struct berval sdberval;
  681. struct berval *certVals[2], *sdVals[2];
  682. CHAR sdBerValue[] = {0x30, 0x03, 0x02, 0x01, DACL_SECURITY_INFORMATION|
  683. OWNER_SECURITY_INFORMATION |
  684. GROUP_SECURITY_INFORMATION};
  685. LDAPControl se_info_control =
  686. {
  687. LDAP_SERVER_SD_FLAGS_OID_W,
  688. {
  689. 5, sdBerValue
  690. },
  691. TRUE
  692. };
  693. LDAPControl permissive_modify_control =
  694. {
  695. LDAP_SERVER_PERMISSIVE_MODIFY_OID_W,
  696. {
  697. 0, NULL
  698. },
  699. FALSE
  700. };
  701. PLDAPControl server_controls[3] =
  702. {
  703. &se_info_control,
  704. &permissive_modify_control,
  705. NULL
  706. };
  707. // for now, modifies don't try to update owner/group
  708. CHAR sdBerValueDaclOnly[] = {0x30, 0x03, 0x02, 0x01, DACL_SECURITY_INFORMATION};
  709. LDAPControl se_info_control_dacl_only =
  710. {
  711. LDAP_SERVER_SD_FLAGS_OID_W,
  712. {
  713. 5, sdBerValueDaclOnly
  714. },
  715. TRUE
  716. };
  717. PLDAPControl server_controls_dacl_only[3] =
  718. {
  719. &se_info_control_dacl_only,
  720. &permissive_modify_control,
  721. NULL
  722. };
  723. DWORD cCALocation;
  724. CERTSTR bstrCALocation = NULL;
  725. WCHAR * wszDomainDN, *wszCAs, *wszPKS;
  726. WCHAR wszFlags[16], *awszFlags[2];
  727. DWORD iMod = 0;
  728. CERTSTR bstrDomainDN = NULL;
  729. certdnVals[0] = NULL;
  730. // Things we free and must put into known state
  731. cnmod.mod_values = NULL;
  732. displaymod.mod_values = NULL;
  733. machinednsmod.mod_values = NULL;
  734. certtypesmod.mod_values = NULL;
  735. Descriptionmod.mod_values = NULL;
  736. if (NULL == m_pCertificate)
  737. {
  738. hr = E_POINTER;
  739. _JumpError(hr, error, "NULL parm");
  740. }
  741. // short circuit calls to a nonexistant DS
  742. hr = myDoesDSExist(TRUE);
  743. _JumpIfError(hr, error, "myDoesDSExist");
  744. __try
  745. {
  746. // bind to ds
  747. hr = myRobustLdapBind(&pld, FALSE);
  748. if(hr != S_OK)
  749. {
  750. _LeaveError(hr, "myRobustLdapBind");
  751. }
  752. objectClass.mod_op = LDAP_MOD_REPLACE;
  753. objectClass.mod_type = TEXT("objectclass");
  754. objectClass.mod_values = objectClassVals;
  755. objectClassVals[0] = wszDSTOPCLASSNAME;
  756. objectClassVals[1] = wszDSENROLLMENTSERVICECLASSNAME;
  757. objectClassVals[2] = NULL;
  758. mods[iMod++] = &objectClass;
  759. cnmod.mod_op = LDAP_MOD_REPLACE;
  760. cnmod.mod_type = CA_PROP_NAME;
  761. hr = GetProperty(CA_PROP_NAME, &cnmod.mod_values);
  762. if((hr != S_OK) || (cnmod.mod_values == NULL))
  763. {
  764. cnmod.mod_values = awszNull;
  765. if(!m_fNew)
  766. {
  767. mods[iMod++] = &cnmod;
  768. }
  769. }
  770. else
  771. {
  772. mods[iMod++] = &cnmod;
  773. }
  774. displaymod.mod_op = LDAP_MOD_REPLACE;
  775. displaymod.mod_type = CA_PROP_DISPLAY_NAME;
  776. hr = GetProperty(CA_PROP_DISPLAY_NAME, &displaymod.mod_values);
  777. if((hr != S_OK) || (displaymod.mod_values == NULL))
  778. {
  779. displaymod.mod_values = awszNull;
  780. if(!m_fNew)
  781. {
  782. mods[iMod++] = &displaymod;
  783. }
  784. }
  785. else
  786. {
  787. mods[iMod++] = &displaymod;
  788. }
  789. Flagsmod.mod_op = LDAP_MOD_REPLACE;
  790. Flagsmod.mod_type = CERTTYPE_PROP_FLAGS;
  791. Flagsmod.mod_values = awszFlags;
  792. awszFlags[0] = wszFlags;
  793. awszFlags[1] = NULL;
  794. wsprintf(wszFlags, L"%lu", m_dwFlags);
  795. mods[iMod++] = &Flagsmod;
  796. certmod.mod_op = LDAP_MOD_BVALUES | LDAP_MOD_REPLACE;
  797. certmod.mod_type = TEXT("cACertificate");
  798. certmod.mod_bvalues = certVals;
  799. certVals[0] = &certberval;
  800. certVals[1] = NULL;
  801. certberval.bv_len = m_pCertificate->cbCertEncoded;
  802. certberval.bv_val = (char *)m_pCertificate->pbCertEncoded;
  803. mods[iMod++] = &certmod;
  804. certdnmod.mod_op = LDAP_MOD_REPLACE;
  805. certdnmod.mod_type = TEXT("cACertificateDN");
  806. certdnmod.mod_values = certdnVals;
  807. cName = CertNameToStr(X509_ASN_ENCODING,
  808. &m_pCertificate->pCertInfo->Subject,
  809. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  810. NULL,
  811. 0);
  812. if (0 == cName)
  813. {
  814. hr = myHLastError();
  815. _LeaveError(hr, "CertNameToStr");
  816. }
  817. certdnVals[0] = CertAllocStringLen(NULL, cName);
  818. if( certdnVals[0] == NULL)
  819. {
  820. hr = E_OUTOFMEMORY;
  821. _LeaveError(hr, "CertAllocStringLen");
  822. }
  823. if(0 == CertNameToStr(X509_ASN_ENCODING,
  824. &m_pCertificate->pCertInfo->Subject,
  825. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  826. certdnVals[0],
  827. cName))
  828. {
  829. hr = myHLastError();
  830. _LeaveError(hr, "CertNameToStr");
  831. }
  832. certdnVals[1] = NULL;
  833. mods[iMod++] = &certdnmod;
  834. machinednsmod.mod_op = LDAP_MOD_REPLACE;
  835. machinednsmod.mod_type = CA_PROP_DNSNAME;
  836. hr = GetProperty(CA_PROP_DNSNAME, &machinednsmod.mod_values);
  837. if((hr != S_OK) || (machinednsmod.mod_values == NULL))
  838. {
  839. machinednsmod.mod_values = awszNull;
  840. if(!m_fNew)
  841. {
  842. mods[iMod++] = &machinednsmod;
  843. }
  844. }
  845. else
  846. {
  847. mods[iMod++] = &machinednsmod;
  848. }
  849. certtypesmod.mod_op = LDAP_MOD_REPLACE;
  850. certtypesmod.mod_type = LDAP_CERTIFICATE_TEMPLATES_NAME;
  851. hr = GetProperty(CA_PROP_CERT_TYPES, &certtypesmod.mod_values);
  852. if((hr != S_OK) || (certtypesmod.mod_values == NULL))
  853. {
  854. certtypesmod.mod_values = awszNull;
  855. if(!m_fNew)
  856. {
  857. mods[iMod++] = &certtypesmod;
  858. }
  859. }
  860. else
  861. {
  862. mods[iMod++] = &certtypesmod;
  863. }
  864. sdmod.mod_op = LDAP_MOD_BVALUES | LDAP_MOD_REPLACE;
  865. sdmod.mod_type = LDAP_SECURITY_DESCRIPTOR_NAME;
  866. sdmod.mod_bvalues = sdVals;
  867. sdVals[0] = &sdberval;
  868. sdVals[1] = NULL;
  869. if(IsValidSecurityDescriptor(m_pSD))
  870. {
  871. sdberval.bv_len = GetSecurityDescriptorLength(m_pSD);
  872. sdberval.bv_val = (char *)m_pSD;
  873. }
  874. else
  875. {
  876. sdberval.bv_len = 0;
  877. sdberval.bv_val = NULL;
  878. }
  879. mods[iMod++] = &sdmod;
  880. Descriptionmod.mod_op = LDAP_MOD_REPLACE;
  881. Descriptionmod.mod_type = CA_PROP_DESCRIPTION;
  882. hr = GetProperty(CA_PROP_DESCRIPTION, &Descriptionmod.mod_values);
  883. if((hr != S_OK) || (Descriptionmod.mod_values == NULL))
  884. {
  885. Descriptionmod.mod_values = awszNull;
  886. if(!m_fNew)
  887. {
  888. mods[iMod++] = &Descriptionmod;
  889. }
  890. }
  891. else
  892. {
  893. mods[iMod++] = &Descriptionmod;
  894. }
  895. mods[iMod] = NULL;
  896. CSASSERT(ARRAYSIZE(mods) > iMod);
  897. hr = S_OK;
  898. if(m_fNew)
  899. {
  900. DBGPRINT((DBG_SS_CERTLIBI, "Creating DS PKI Enrollment object: '%ws'\n", m_bstrDN));
  901. ldaperr = ldap_add_ext_sW(pld, m_bstrDN, mods, server_controls, NULL);
  902. }
  903. else
  904. {
  905. // don't attempt to set owner/group for pre-existing objects
  906. DBGPRINT((DBG_SS_CERTLIBI, "Updating DS PKI Enrollment object: '%ws'\n", m_bstrDN));
  907. ldaperr = ldap_modify_ext_sW(pld,
  908. m_bstrDN,
  909. &mods[2],
  910. server_controls_dacl_only,
  911. NULL); // skip past objectClass and cn
  912. if(LDAP_ATTRIBUTE_OR_VALUE_EXISTS == ldaperr)
  913. {
  914. ldaperr = LDAP_SUCCESS;
  915. }
  916. }
  917. if (LDAP_SUCCESS != ldaperr && LDAP_ALREADY_EXISTS != ldaperr)
  918. {
  919. hr = myHLdapError(pld, ldaperr, NULL);
  920. _LeaveError(ldaperr, m_fNew? "ldap_add_s" : "ldap_modify_sW");
  921. }
  922. m_fNew = FALSE;
  923. }
  924. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  925. {
  926. }
  927. error:
  928. if (NULL != certdnVals[0])
  929. {
  930. CertFreeString(certdnVals[0]);
  931. }
  932. if (NULL != certtypesmod.mod_values && awszNull != certtypesmod.mod_values)
  933. {
  934. FreeProperty(certtypesmod.mod_values);
  935. }
  936. if (NULL != machinednsmod.mod_values && awszNull != machinednsmod.mod_values)
  937. {
  938. FreeProperty(machinednsmod.mod_values);
  939. }
  940. if (NULL != cnmod.mod_values && awszNull != cnmod.mod_values)
  941. {
  942. FreeProperty(cnmod.mod_values);
  943. }
  944. if (NULL != displaymod.mod_values && awszNull != displaymod.mod_values)
  945. {
  946. FreeProperty(displaymod.mod_values);
  947. }
  948. if (NULL != Descriptionmod.mod_values && awszNull != Descriptionmod.mod_values)
  949. {
  950. FreeProperty(Descriptionmod.mod_values);
  951. }
  952. if (NULL != pld)
  953. {
  954. ldap_unbind(pld);
  955. }
  956. return(hr);
  957. }
  958. HRESULT
  959. CCAInfo::Delete(VOID)
  960. {
  961. LDAP *pld = NULL;
  962. HRESULT hr = S_OK;
  963. DWORD ldaperr;
  964. // short circuit calls to a nonexistant DS
  965. hr = myDoesDSExist(TRUE);
  966. _JumpIfError(hr, error, "myDoesDSExist");
  967. __try
  968. {
  969. // bind to ds
  970. hr = myRobustLdapBind(&pld, FALSE);
  971. if(hr != S_OK)
  972. {
  973. _LeaveError(hr, "myRobustLdapBind");
  974. }
  975. ldaperr = ldap_delete_s(pld, m_bstrDN);
  976. hr = myHLdapError(pld, ldaperr, NULL);
  977. }
  978. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  979. {
  980. }
  981. error:
  982. if (NULL != pld)
  983. {
  984. ldap_unbind(pld);
  985. }
  986. return (hr);
  987. }
  988. //+--------------------------------------------------------------------------
  989. // CCAInfo::FindDnsDomain -- Find CA Objects in the DS, given a scope specified
  990. // by a dns domain name.
  991. //
  992. //
  993. //+--------------------------------------------------------------------------
  994. HRESULT
  995. CCAInfo::FindDnsDomain(
  996. LPCWSTR wszQuery,
  997. LPCWSTR wszDnsDomain,
  998. DWORD dwFlags,
  999. CCAInfo **ppCAInfo)
  1000. {
  1001. HRESULT hr = S_OK;
  1002. DWORD err;
  1003. WCHAR *wszScope = NULL;
  1004. DWORD cScope;
  1005. if (NULL != wszDnsDomain)
  1006. {
  1007. cScope = 0;
  1008. err = DNStoRFC1779Name(NULL, &cScope, wszDnsDomain);
  1009. if(err != ERROR_INSUFFICIENT_BUFFER)
  1010. {
  1011. hr = myHError(err);
  1012. _JumpError(hr, error, "DNStoRFC1779Name");
  1013. }
  1014. cScope += 1;
  1015. wszScope = (WCHAR *) LocalAlloc(LMEM_FIXED, sizeof(WCHAR)*cScope);
  1016. if (NULL == wszScope)
  1017. {
  1018. hr = E_OUTOFMEMORY;
  1019. _JumpError(hr, error, "LocalAlloc");
  1020. }
  1021. err = DNStoRFC1779Name(wszScope, &cScope, wszDnsDomain);
  1022. if (ERROR_SUCCESS != err)
  1023. {
  1024. hr = myHError(err);
  1025. _JumpError(hr, error, "DNStoRFC1779Name");
  1026. }
  1027. }
  1028. hr = Find(wszQuery, wszScope, dwFlags, ppCAInfo);
  1029. _JumpIfError4(
  1030. hr,
  1031. error,
  1032. "Find",
  1033. HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED),
  1034. HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN),
  1035. HRESULT_FROM_WIN32(ERROR_WRONG_PASSWORD));
  1036. error:
  1037. if (NULL != wszScope)
  1038. {
  1039. LocalFree(wszScope);
  1040. }
  1041. return(hr);
  1042. }
  1043. //+--------------------------------------------------------------------------
  1044. // CCAInfo::CreateDnsDomain -- Find CA Objects in the DS, given a scope specified
  1045. // by a dns domain name.
  1046. //
  1047. //
  1048. //+--------------------------------------------------------------------------
  1049. HRESULT
  1050. CCAInfo::CreateDnsDomain(
  1051. LPCWSTR wszName,
  1052. LPCWSTR wszDnsDomain,
  1053. CCAInfo **ppCAInfo)
  1054. {
  1055. HRESULT hr = S_OK;
  1056. DWORD err;
  1057. WCHAR *wszScope = NULL;
  1058. DWORD cScope;
  1059. if(wszDnsDomain)
  1060. {
  1061. cScope = 0;
  1062. err = DNStoRFC1779Name(NULL, &cScope, wszDnsDomain);
  1063. if(err != ERROR_INSUFFICIENT_BUFFER)
  1064. {
  1065. hr = myHError(err);
  1066. _JumpError(hr, error, "DNStoRFC1779Name");
  1067. }
  1068. cScope += 1;
  1069. wszScope = (WCHAR *) LocalAlloc(LMEM_FIXED, sizeof(WCHAR)*cScope);
  1070. if (NULL == wszScope)
  1071. {
  1072. hr = E_OUTOFMEMORY;
  1073. _JumpError(hr, error, "LocalAlloc");
  1074. }
  1075. err = DNStoRFC1779Name(wszScope, &cScope, wszDnsDomain);
  1076. if (ERROR_SUCCESS != err)
  1077. {
  1078. hr = myHError(err);
  1079. _JumpError(hr, error, "DNStoRFC1779Name");
  1080. }
  1081. }
  1082. hr = Create(wszName, wszScope, ppCAInfo);
  1083. _JumpIfError(hr, error, "Create");
  1084. error:
  1085. if (NULL != wszScope)
  1086. {
  1087. LocalFree(wszScope);
  1088. }
  1089. return(hr);
  1090. }
  1091. //+--------------------------------------------------------------------------
  1092. // CCAInfo::Next -- Returns the next object in the chain of CA objects
  1093. //
  1094. //
  1095. //+--------------------------------------------------------------------------
  1096. HRESULT
  1097. CCAInfo::Next(CCAInfo **ppCAInfo)
  1098. {
  1099. HRESULT hr;
  1100. if (NULL == ppCAInfo)
  1101. {
  1102. hr = E_POINTER;
  1103. _JumpError(hr, error, "NULL parm");
  1104. }
  1105. *ppCAInfo = m_pNext;
  1106. if (NULL != m_pNext)
  1107. {
  1108. m_pNext->AddRef();
  1109. }
  1110. hr = S_OK;
  1111. error:
  1112. return(hr);
  1113. }
  1114. //+--------------------------------------------------------------------------
  1115. // CCAInfo::GetProperty -- Retrieves the values of a property of the CA object
  1116. //
  1117. //
  1118. //+--------------------------------------------------------------------------
  1119. HRESULT
  1120. CCAInfo::GetProperty(
  1121. LPCWSTR wszPropertyName,
  1122. LPWSTR **pawszProperties)
  1123. {
  1124. HRESULT hr;
  1125. DWORD dwChar=0;
  1126. LPWSTR *awszResult = NULL;
  1127. LPWSTR pwszName=NULL;
  1128. CCAProperty *pProp;
  1129. LPCWSTR wszProp = NULL;
  1130. if (NULL == wszPropertyName || NULL == pawszProperties)
  1131. {
  1132. hr = E_POINTER;
  1133. _JumpError(hr, error, "NULL parm");
  1134. }
  1135. if(lstrcmpi(wszPropertyName, L"machineDNSName") == 0)
  1136. {
  1137. wszProp = CA_PROP_DNSNAME;
  1138. }
  1139. else if(lstrcmpi(wszPropertyName, L"supportedCertificateTemplates") == 0)
  1140. {
  1141. wszProp = CA_PROP_CERT_TYPES;
  1142. }
  1143. else if(lstrcmpi(wszPropertyName, L"signatureAlgs") == 0)
  1144. {
  1145. wszProp = CA_PROP_SIGNATURE_ALGS;
  1146. }
  1147. else
  1148. {
  1149. wszProp = wszPropertyName;
  1150. }
  1151. hr = m_pProperties->Find(wszProp, &pProp);
  1152. _JumpIfErrorStr(hr, error, "Find", wszProp);
  1153. if (NULL != pProp)
  1154. {
  1155. hr = pProp->GetValue(pawszProperties);
  1156. _JumpIfError(hr, error, "GetValue");
  1157. }
  1158. else
  1159. {
  1160. *pawszProperties = NULL;
  1161. }
  1162. if((lstrcmpi(wszPropertyName, CA_PROP_DISPLAY_NAME) == 0) &&
  1163. ((*pawszProperties == NULL) || ((*pawszProperties)[0] == NULL)))
  1164. {
  1165. // DISPLAY_NAME is empty, so we try to return the display name
  1166. // of the CA's certificate. if that also failed, just pass back the CN
  1167. if(*pawszProperties != NULL)
  1168. {
  1169. LocalFree(*pawszProperties);
  1170. *pawszProperties = NULL;
  1171. }
  1172. if(m_pCertificate)
  1173. {
  1174. if((dwChar=CertGetNameStringW(
  1175. m_pCertificate,
  1176. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  1177. 0,
  1178. NULL,
  1179. NULL,
  1180. 0)))
  1181. {
  1182. pwszName=(LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (dwChar));
  1183. if(NULL==pwszName)
  1184. {
  1185. hr=E_OUTOFMEMORY;
  1186. _JumpIfError(hr, error, "GetPropertyDisplayName");
  1187. }
  1188. if(dwChar=CertGetNameStringW(
  1189. m_pCertificate,
  1190. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  1191. 0,
  1192. NULL,
  1193. pwszName,
  1194. dwChar))
  1195. {
  1196. awszResult=(WCHAR **)LocalAlloc(LPTR, (UINT)(sizeof(WCHAR *)*2+(wcslen(pwszName)+1)*sizeof(WCHAR)));
  1197. if (NULL==awszResult)
  1198. {
  1199. hr=E_OUTOFMEMORY;
  1200. _JumpIfError(hr, error, "GetPropertyDisplayName");
  1201. }
  1202. awszResult[0]=(WCHAR *)(&awszResult[2]);
  1203. awszResult[1]=NULL;
  1204. wcscpy(awszResult[0], pwszName);
  1205. LocalFree(pwszName);
  1206. *pawszProperties=awszResult;
  1207. return S_OK;
  1208. }
  1209. }
  1210. }
  1211. hr = GetProperty(CA_PROP_NAME, pawszProperties);
  1212. _JumpIfError(hr, error, "GetProperty");
  1213. }
  1214. error:
  1215. if(pwszName)
  1216. LocalFree(pwszName);
  1217. return(hr);
  1218. }
  1219. //+--------------------------------------------------------------------------
  1220. // CCertTypeInfo::SetProperty -- Sets the value of a property
  1221. //
  1222. //
  1223. //+--------------------------------------------------------------------------
  1224. HRESULT
  1225. CCAInfo::SetProperty(
  1226. LPCWSTR wszPropertyName,
  1227. LPWSTR *awszProperties)
  1228. {
  1229. HRESULT hr;
  1230. CCAProperty *pProp;
  1231. CCAProperty *pNewProp = NULL;
  1232. if (NULL == wszPropertyName)
  1233. {
  1234. hr = E_POINTER;
  1235. _JumpError(hr, error, "NULL parm");
  1236. }
  1237. hr = m_pProperties->Find(wszPropertyName, &pProp);
  1238. if (S_OK != hr)
  1239. {
  1240. pNewProp = new CCAProperty(wszPropertyName);
  1241. if (NULL == pNewProp)
  1242. {
  1243. hr = E_OUTOFMEMORY;
  1244. _JumpError(hr, error, "new");
  1245. }
  1246. hr = pNewProp->SetValue(awszProperties);
  1247. _JumpIfError(hr, error, "SetValue");
  1248. hr = CCAProperty::Append(&m_pProperties, pNewProp);
  1249. _JumpIfError(hr, error, "Append");
  1250. pNewProp = NULL; // remove our reference if we gave it to m_pProperties
  1251. }
  1252. else
  1253. {
  1254. hr = pProp->SetValue(awszProperties);
  1255. _JumpIfError(hr, error, "SetValue");
  1256. }
  1257. error:
  1258. if (NULL != pNewProp)
  1259. CCAProperty::DeleteChain(&pNewProp);
  1260. return(hr);
  1261. }
  1262. //+--------------------------------------------------------------------------
  1263. // CCAInfo::FreeProperty -- Free's a previously returned property array
  1264. //
  1265. //
  1266. //+--------------------------------------------------------------------------
  1267. HRESULT
  1268. CCAInfo::FreeProperty(
  1269. LPWSTR *pawszProperties)
  1270. {
  1271. if (NULL != pawszProperties)
  1272. {
  1273. LocalFree(pawszProperties);
  1274. }
  1275. return(S_OK);
  1276. }
  1277. //+--------------------------------------------------------------------------
  1278. // CCAInfo::GetCertificte -- get the CA certificate
  1279. //
  1280. //
  1281. //+--------------------------------------------------------------------------
  1282. HRESULT
  1283. CCAInfo::GetCertificate(
  1284. PCCERT_CONTEXT *ppCert)
  1285. {
  1286. HRESULT hr;
  1287. if (NULL == ppCert)
  1288. {
  1289. hr = E_POINTER;
  1290. _JumpError(hr, error, "NULL parm");
  1291. }
  1292. *ppCert = CertDuplicateCertificateContext(m_pCertificate);
  1293. hr = S_OK;
  1294. error:
  1295. return(hr);
  1296. }
  1297. //+--------------------------------------------------------------------------
  1298. // CCAInfo::SetCertificte -- get the CA certificate
  1299. //
  1300. //
  1301. //+--------------------------------------------------------------------------
  1302. HRESULT
  1303. CCAInfo::SetCertificate(
  1304. PCCERT_CONTEXT pCert)
  1305. {
  1306. if (NULL != m_pCertificate)
  1307. {
  1308. CertFreeCertificateContext(m_pCertificate);
  1309. m_pCertificate = NULL;
  1310. }
  1311. if (NULL != pCert)
  1312. {
  1313. m_pCertificate = CertDuplicateCertificateContext(pCert);
  1314. }
  1315. return S_OK;
  1316. }
  1317. //+--------------------------------------------------------------------------
  1318. // CCAInfo::EnumCertTypesEx -- Enumerate cert types supported by this CA
  1319. //
  1320. //
  1321. //+--------------------------------------------------------------------------
  1322. HRESULT
  1323. CCAInfo::EnumSupportedCertTypesEx(
  1324. LPCWSTR wszScope,
  1325. DWORD dwFlags,
  1326. CCertTypeInfo **ppCertTypes)
  1327. {
  1328. HRESULT hr;
  1329. CCertTypeInfo *pCTFirst = NULL;
  1330. CCertTypeInfo *pCTCurrent = NULL;
  1331. LPWSTR * awszCertTypes = NULL;
  1332. if (NULL == ppCertTypes)
  1333. {
  1334. hr = E_POINTER;
  1335. _JumpError(hr, error, "NULL parm");
  1336. }
  1337. *ppCertTypes = NULL;
  1338. hr = GetProperty(CA_PROP_CERT_TYPES, &awszCertTypes);
  1339. _JumpIfError(hr, error, "GetProperty");
  1340. if (NULL != awszCertTypes)
  1341. {
  1342. // Build a filter based on all of the global
  1343. // entries in the cert list.
  1344. hr = CCertTypeInfo::FindByNames(
  1345. (LPCWSTR *)awszCertTypes,
  1346. wszScope,
  1347. dwFlags,
  1348. ppCertTypes);
  1349. _JumpIfError(hr, error, "FindByNames");
  1350. }
  1351. error:
  1352. if (awszCertTypes)
  1353. {
  1354. FreeProperty(awszCertTypes);
  1355. }
  1356. return(hr);
  1357. }
  1358. //+--------------------------------------------------------------------------
  1359. // CCAInfo::EnumCertTypes -- Enumerate cert types supported by this CA
  1360. //
  1361. //
  1362. //+--------------------------------------------------------------------------
  1363. HRESULT
  1364. CCAInfo::EnumSupportedCertTypes(
  1365. DWORD dwFlags,
  1366. CCertTypeInfo **ppCertTypes)
  1367. {
  1368. return CCAInfo::EnumSupportedCertTypesEx(NULL, dwFlags, ppCertTypes);
  1369. }
  1370. //+--------------------------------------------------------------------------
  1371. // CCAInfo::AddCertType -- Add a cert type to this CA
  1372. //
  1373. //
  1374. //+--------------------------------------------------------------------------
  1375. HRESULT
  1376. CCAInfo::AddCertType(
  1377. CCertTypeInfo *pCertType)
  1378. {
  1379. HRESULT hr;
  1380. LPWSTR *awszCertTypes = NULL;
  1381. LPWSTR *awszCertTypeName = NULL;
  1382. LPWSTR *awszNewTypes = NULL;
  1383. LPWSTR wszCertTypeShortName = NULL;
  1384. LPWSTR awszTypeName;
  1385. DWORD cTypes;
  1386. if (NULL == pCertType)
  1387. {
  1388. hr = E_POINTER;
  1389. _JumpError(hr, error, "NULL parm");
  1390. }
  1391. hr = GetProperty(CA_PROP_CERT_TYPES, &awszCertTypes);
  1392. _JumpIfError(hr, error, "GetProperty");
  1393. hr = pCertType->GetProperty(CERTTYPE_PROP_DN, &awszCertTypeName);
  1394. _JumpIfError(hr, error, "GetProperty");
  1395. if (NULL == awszCertTypeName || NULL == awszCertTypeName[0])
  1396. {
  1397. hr = E_POINTER;
  1398. _JumpError(hr, error, "NULL CertTypeName");
  1399. }
  1400. if((NULL != (wszCertTypeShortName = wcschr(awszCertTypeName[0], L'|'))) ||
  1401. (NULL != (wszCertTypeShortName = wcschr(awszCertTypeName[0], wcRBRACE))))
  1402. {
  1403. wszCertTypeShortName++;
  1404. }
  1405. if (NULL == awszCertTypes || NULL == awszCertTypes[0])
  1406. {
  1407. // no templates on the CA, add the new one and exit
  1408. hr = SetProperty(CA_PROP_CERT_TYPES, awszCertTypeName);
  1409. _JumpIfError(hr, error, "SetProperty");
  1410. }
  1411. else
  1412. {
  1413. // If cert type is already on ca, do nothing
  1414. for (cTypes = 0; awszCertTypes[cTypes] != NULL; cTypes++)
  1415. {
  1416. if (0 == lstrcmpi(awszCertTypes[cTypes], awszCertTypeName[0]))
  1417. {
  1418. hr = S_OK;
  1419. goto error;
  1420. }
  1421. if(wszCertTypeShortName)
  1422. {
  1423. if (0 == lstrcmpi(awszCertTypes[cTypes], wszCertTypeShortName))
  1424. {
  1425. hr = S_OK;
  1426. goto error;
  1427. }
  1428. }
  1429. }
  1430. awszNewTypes = (WCHAR **) LocalAlloc(
  1431. LMEM_FIXED,
  1432. (cTypes + 2) * sizeof(WCHAR *));
  1433. if (NULL == awszNewTypes)
  1434. {
  1435. hr = E_OUTOFMEMORY;
  1436. _JumpError(hr, error, "LocalAlloc");
  1437. }
  1438. CopyMemory(awszNewTypes, awszCertTypes, cTypes * sizeof(WCHAR *));
  1439. awszNewTypes[cTypes] = awszCertTypeName[0];
  1440. awszNewTypes[cTypes + 1] = NULL;
  1441. hr = SetProperty(CA_PROP_CERT_TYPES, awszNewTypes);
  1442. _JumpIfError(hr, error, "SetProperty");
  1443. }
  1444. error:
  1445. if (NULL != awszCertTypes)
  1446. {
  1447. FreeProperty(awszCertTypes);
  1448. }
  1449. if (NULL != awszCertTypeName)
  1450. {
  1451. FreeProperty(awszCertTypeName);
  1452. }
  1453. if (NULL != awszNewTypes)
  1454. {
  1455. LocalFree(awszNewTypes);
  1456. }
  1457. return(hr);
  1458. }
  1459. //+--------------------------------------------------------------------------
  1460. // CCAInfo::RemoveCertType -- Remove a cert type from this CA
  1461. //
  1462. //
  1463. //+--------------------------------------------------------------------------
  1464. HRESULT
  1465. CCAInfo::RemoveCertType(
  1466. CCertTypeInfo *pCertType)
  1467. {
  1468. HRESULT hr;
  1469. WCHAR **awszCertTypes = NULL;
  1470. WCHAR **awszCertTypeName = NULL;
  1471. DWORD cTypes, cTypesNew;
  1472. LPWSTR wszCertTypeName = NULL;
  1473. LPWSTR wszCurrentCertTypeName = NULL;
  1474. if (NULL == pCertType)
  1475. {
  1476. hr = E_POINTER;
  1477. _JumpError(hr, error, "NULL parm");
  1478. }
  1479. hr = GetProperty(CA_PROP_CERT_TYPES, &awszCertTypes);
  1480. _JumpIfError(hr, error, "GetProperty");
  1481. hr = pCertType->GetProperty(CERTTYPE_PROP_CN, &awszCertTypeName);
  1482. _JumpIfError(hr, error, "GetProperty");
  1483. if (NULL == awszCertTypeName || NULL == awszCertTypeName[0])
  1484. {
  1485. hr = E_POINTER;
  1486. _JumpError(hr, error, "NULL CertTypeName");
  1487. }
  1488. if (NULL == awszCertTypes || NULL == awszCertTypes[0])
  1489. {
  1490. hr = S_OK;
  1491. goto error;
  1492. }
  1493. wszCertTypeName = wcschr(awszCertTypeName[0], wcRBRACE);
  1494. if(wszCertTypeName != NULL)
  1495. {
  1496. wszCertTypeName++;
  1497. }
  1498. else
  1499. {
  1500. wszCertTypeName = awszCertTypeName[0];
  1501. }
  1502. cTypesNew = 0;
  1503. // If cert type is already on ca, do nothing
  1504. for (cTypes = 0; awszCertTypes[cTypes] != NULL; cTypes++)
  1505. {
  1506. if((NULL != (wszCurrentCertTypeName = wcschr(awszCertTypes[cTypes], L'|'))) ||
  1507. (NULL != (wszCurrentCertTypeName = wcschr(awszCertTypes[cTypes], wcRBRACE))))
  1508. {
  1509. wszCurrentCertTypeName++;
  1510. }
  1511. else
  1512. {
  1513. wszCurrentCertTypeName = awszCertTypes[cTypes];
  1514. }
  1515. if (0 != lstrcmpi(wszCurrentCertTypeName, wszCertTypeName))
  1516. {
  1517. awszCertTypes[cTypesNew++] = awszCertTypes[cTypes];
  1518. }
  1519. }
  1520. awszCertTypes[cTypesNew] = NULL;
  1521. hr = SetProperty(CA_PROP_CERT_TYPES, awszCertTypes);
  1522. _JumpIfError(hr, error, "SetProperty");
  1523. error:
  1524. if (NULL != awszCertTypes)
  1525. {
  1526. FreeProperty(awszCertTypes);
  1527. }
  1528. if (NULL != awszCertTypeName)
  1529. {
  1530. FreeProperty(awszCertTypeName);
  1531. }
  1532. return(hr);
  1533. }
  1534. //+--------------------------------------------------------------------------
  1535. // CCAInfo::GetExpiration -- Get the expiration period
  1536. //
  1537. //
  1538. //+--------------------------------------------------------------------------
  1539. HRESULT
  1540. CCAInfo::GetExpiration(
  1541. DWORD *pdwExpiration,
  1542. DWORD *pdwUnits)
  1543. {
  1544. HRESULT hr;
  1545. if (NULL == pdwExpiration || NULL == pdwUnits)
  1546. {
  1547. hr = E_POINTER;
  1548. _JumpError(hr, error, "NULL parm");
  1549. }
  1550. *pdwExpiration = m_dwExpiration;
  1551. *pdwUnits = m_dwExpUnits;
  1552. hr = S_OK;
  1553. error:
  1554. return(hr);
  1555. }
  1556. //+--------------------------------------------------------------------------
  1557. // CCAInfo::SetExpiration -- Set the expiration period
  1558. //
  1559. //
  1560. //+--------------------------------------------------------------------------
  1561. HRESULT
  1562. CCAInfo::SetExpiration(
  1563. DWORD dwExpiration,
  1564. DWORD dwUnits)
  1565. {
  1566. m_dwExpiration = dwExpiration;
  1567. m_dwExpUnits = dwUnits;
  1568. return(S_OK);
  1569. }
  1570. //+--------------------------------------------------------------------------
  1571. // CCAInfo::GetSecurity --
  1572. //
  1573. //
  1574. //+--------------------------------------------------------------------------
  1575. HRESULT CCAInfo::GetSecurity(PSECURITY_DESCRIPTOR * ppSD)
  1576. {
  1577. HRESULT hr = S_OK;
  1578. PSECURITY_DESCRIPTOR pResult = NULL;
  1579. DWORD cbSD;
  1580. if(ppSD == NULL)
  1581. {
  1582. return E_POINTER;
  1583. }
  1584. if(m_pSD == NULL)
  1585. {
  1586. *ppSD = NULL;
  1587. return S_OK;
  1588. }
  1589. if(!IsValidSecurityDescriptor(m_pSD))
  1590. {
  1591. return HRESULT_FROM_WIN32(ERROR_INVALID_SECURITY_DESCR);
  1592. }
  1593. cbSD = GetSecurityDescriptorLength(m_pSD);
  1594. pResult = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, cbSD);
  1595. if(pResult == NULL)
  1596. {
  1597. return E_OUTOFMEMORY;
  1598. }
  1599. CopyMemory(pResult, m_pSD, cbSD);
  1600. *ppSD = pResult;
  1601. return S_OK;
  1602. }
  1603. //+--------------------------------------------------------------------------
  1604. // CCAInfo::GetSecurity --
  1605. //
  1606. //
  1607. //+--------------------------------------------------------------------------
  1608. HRESULT CCAInfo::SetSecurity(PSECURITY_DESCRIPTOR pSD)
  1609. {
  1610. HRESULT hr = S_OK;
  1611. PSECURITY_DESCRIPTOR pResult = NULL;
  1612. DWORD cbSD;
  1613. if(pSD == NULL)
  1614. {
  1615. return E_POINTER;
  1616. }
  1617. if(!IsValidSecurityDescriptor(pSD))
  1618. {
  1619. return HRESULT_FROM_WIN32(ERROR_INVALID_SECURITY_DESCR);
  1620. }
  1621. cbSD = GetSecurityDescriptorLength(pSD);
  1622. pResult = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, cbSD);
  1623. if(pResult == NULL)
  1624. {
  1625. return E_OUTOFMEMORY;
  1626. }
  1627. CopyMemory(pResult, pSD, cbSD);
  1628. if(m_pSD)
  1629. {
  1630. LocalFree(m_pSD);
  1631. }
  1632. m_pSD = pResult;
  1633. return S_OK;
  1634. }
  1635. HRESULT CCAInfo::AccessCheck(HANDLE ClientToken, DWORD dwOption)
  1636. {
  1637. return CAAccessCheckpEx(ClientToken, m_pSD, dwOption);
  1638. }