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.

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