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.

1759 lines
38 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 2000
  6. //
  7. // File: tcainfo.cpp
  8. //
  9. // This code contains tests to exercise the functionality of the certcli
  10. // "CA" interfaces, detailed in certca.h
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <pch.cpp>
  14. #pragma hdrstop
  15. #include <certca.h>
  16. #include <winldap.h>
  17. #include <csldap.h>
  18. #define __dwFILE__ __dwFILE_CERTUTIL_TCAINFO_CPP__
  19. #define wszREGADMINALIAS L"Software\\Policies\\Microsoft\\CertificateTemplates\\Aliases\\Administrator"
  20. #define wszREGPOLICYHISTORY L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History"
  21. WCHAR const g_wszSep[] = L"================================================================";
  22. #define TE_USER 0
  23. #define TE_MACHINE 1
  24. //
  25. // CheckSupportedCertTypes()
  26. //
  27. // This function checks the certificate types enumerated through the property
  28. // API, and compares them to the types enumerated by the cert type API.
  29. //
  30. // Params:
  31. // hCA - IN Handle to CA
  32. // papwszProperty - IN String array w/ present values
  33. //
  34. // Returns:
  35. // HRESULT from CAINFO calls.
  36. //
  37. HRESULT
  38. CheckSupportedCertTypes(
  39. IN HCAINFO hCA,
  40. IN WCHAR const * const *papwszTemplate)
  41. {
  42. HRESULT hr;
  43. DWORD dwCT;
  44. DWORD dwCT2;
  45. DWORD cTemplate;
  46. DWORD i;
  47. DWORD *rgIndex = NULL;
  48. HCERTTYPE hCT = NULL;
  49. WCHAR **papwszCTFriendlyName = NULL;
  50. WCHAR **papwszCTCN = NULL;
  51. BOOL fFirst;
  52. // First, find out how many cert types there are according to
  53. // value returned from property array...
  54. for (cTemplate = 0; NULL != papwszTemplate[cTemplate]; cTemplate++)
  55. ;
  56. // alloc bool array for testing
  57. rgIndex = (DWORD *) LocalAlloc(
  58. LMEM_FIXED | LMEM_ZEROINIT,
  59. sizeof(DWORD) * cTemplate);
  60. if (NULL == rgIndex)
  61. {
  62. hr = E_OUTOFMEMORY;
  63. _JumpError(hr, error, "LocalAlloc");
  64. }
  65. memset(rgIndex, 0xff, sizeof(DWORD) * cTemplate);
  66. CSASSERT(MAXDWORD == rgIndex[0]);
  67. // Let's try out the enumeration of cert types on the CA object,
  68. // just as a sanity check... we'll then compare them against
  69. // the values stored in the property array.
  70. hr = CAEnumCertTypesForCA(
  71. hCA,
  72. CT_ENUM_USER_TYPES | CT_ENUM_MACHINE_TYPES,
  73. &hCT);
  74. if (S_OK != hr)
  75. {
  76. cuPrintAPIError(L"CAEnumCertTypesForCA", hr);
  77. _JumpError(hr, error, "CAEnumCertTypesForCA");
  78. }
  79. if (NULL == hCT) // no cert types for CA
  80. {
  81. // Should be at least one, according to property enumeration
  82. if (NULL != papwszTemplate[0])
  83. {
  84. wprintf(myLoadResourceString(IDS_NO_CT_BUT_EXISTS));
  85. wprintf(wszNewLine);
  86. hr = CRYPT_E_NOT_FOUND;
  87. _JumpError(hr, error, "CAEnumCertTypesForCA");
  88. }
  89. wprintf(myLoadResourceString(IDS_NO_CT_FOR_CA));
  90. wprintf(wszNewLine);
  91. }
  92. dwCT = 0;
  93. dwCT2 = CACountCertTypes(hCT);
  94. // Enumerate remaining certificate types for CA
  95. while (NULL != hCT)
  96. {
  97. HCERTTYPE hPrevCT;
  98. // Mark bool...
  99. hr = CAGetCertTypeProperty(
  100. hCT,
  101. CERTTYPE_PROP_FRIENDLY_NAME,
  102. &papwszCTFriendlyName);
  103. if (S_OK != hr)
  104. {
  105. cuPrintAPIError(L"CAGetCertTypeProperty", hr);
  106. _JumpError(hr, error, "CAGetCertTypeProperty");
  107. }
  108. hr = CAGetCertTypeProperty(
  109. hCT,
  110. CERTTYPE_PROP_CN,
  111. &papwszCTCN);
  112. if (S_OK != hr)
  113. {
  114. cuPrintAPIError(L"CAGetCertTypeProperty", hr);
  115. _JumpError(hr, error, "CAGetCertTypeProperty");
  116. }
  117. wprintf(
  118. L"%ws[%u]: %ws (%ws)",
  119. myLoadResourceString(IDS_CERT_TYPE),
  120. dwCT,
  121. NULL != papwszCTCN? papwszCTCN[0] : NULL,
  122. NULL != papwszCTFriendlyName? papwszCTFriendlyName[0] : NULL);
  123. hr = CACertTypeAccessCheck(hCT, NULL);
  124. if (S_OK != hr)
  125. {
  126. if (hr != E_ACCESSDENIED)
  127. {
  128. wprintf(wszNewLine);
  129. cuPrintAPIError(L"CACertTypeAccessCheck", hr);
  130. _JumpError(hr, error, "CACertTypeAccessCheck");
  131. }
  132. wprintf(L" -- %ws", myLoadResourceString(IDS_NO_ACCESS));
  133. hr = S_OK;
  134. }
  135. wprintf(wszNewLine);
  136. if (NULL != papwszCTCN)
  137. {
  138. for (i = 0; i < cTemplate; i++)
  139. {
  140. if (0 == mylstrcmpiL(papwszTemplate[i], papwszCTCN[0]))
  141. {
  142. rgIndex[i] = dwCT;
  143. break;
  144. }
  145. }
  146. CAFreeCertTypeProperty(hCT, papwszCTCN);
  147. papwszCTCN = NULL;
  148. }
  149. if (NULL != papwszCTFriendlyName)
  150. {
  151. CAFreeCertTypeProperty(hCT, papwszCTFriendlyName);
  152. papwszCTFriendlyName = NULL;
  153. }
  154. dwCT++; // CACountCertTypes checking
  155. // set up enumeration object
  156. hPrevCT = hCT;
  157. hCT = NULL;
  158. hr = CAEnumNextCertType(hPrevCT, &hCT);
  159. CACloseCertType(hPrevCT);
  160. hPrevCT = hCT;
  161. if (S_OK != hr)
  162. {
  163. cuPrintAPIError(L"CAEnumNextCertType", hr);
  164. _JumpError(hr, error, "CAEnumNextCertType");
  165. }
  166. if (NULL == hCT)
  167. {
  168. break;
  169. }
  170. }
  171. wprintf(L"%ws: %u\n", myLoadResourceString(IDS_CERT_TYPES), dwCT);
  172. fFirst = TRUE;
  173. for (i = 0; i < cTemplate; i++)
  174. {
  175. //wprintf(L"ct[%u]: %ws\n", i, papwszTemplate[i]);
  176. if (MAXDWORD == rgIndex[i])
  177. {
  178. if (fFirst)
  179. {
  180. wprintf(wszNewLine);
  181. fFirst = FALSE;
  182. }
  183. wprintf(
  184. L"%ws: %ws\n",
  185. papwszTemplate[i],
  186. myLoadResourceString(IDS_CERT_TYPE_MISSING));
  187. }
  188. }
  189. hr = S_OK;
  190. error:
  191. if (NULL != rgIndex)
  192. {
  193. LocalFree(rgIndex);
  194. }
  195. if (NULL != papwszCTFriendlyName)
  196. {
  197. CAFreeCertTypeProperty(hCT, papwszCTFriendlyName);
  198. }
  199. if (NULL != papwszCTCN)
  200. {
  201. CAFreeCertTypeProperty(hCT, papwszCTCN);
  202. }
  203. if (NULL != hCT)
  204. {
  205. CACloseCertType(hCT);
  206. }
  207. return(hr);
  208. }
  209. //
  210. // ShowExpirationTime()
  211. //
  212. // This function simply displays the expiration time.
  213. //
  214. // Parameters:
  215. //
  216. // hCA - IN Handle to CA
  217. //
  218. // Returns:
  219. //
  220. // HRESULT from APIs, or S_OK
  221. //
  222. HRESULT
  223. ShowExpirationTime(
  224. IN HCAINFO hCA)
  225. {
  226. HRESULT hr;
  227. DWORD dwExp;
  228. DWORD dwUnits;
  229. DWORD ardwUnits[] = {CA_UNITS_DAYS,
  230. CA_UNITS_WEEKS,
  231. CA_UNITS_MONTHS,
  232. CA_UNITS_YEARS};
  233. WCHAR *arwszDisplay[] = {L"Days",
  234. L"Weeks",
  235. L"Months",
  236. L"Years"};
  237. // Retrieve and display expiration data
  238. hr = CAGetCAExpiration(hCA, &dwExp, &dwUnits);
  239. if (S_OK != hr)
  240. {
  241. cuPrintAPIError(L"CAGetCAExpiration", hr);
  242. _JumpError(hr, error, "CAGetCAExpiration");
  243. }
  244. for (DWORD i = 0; i < ARRAYSIZE(ardwUnits); i++)
  245. {
  246. if (dwUnits == ardwUnits[i])
  247. {
  248. wprintf(wszNewLine);
  249. wprintf(myLoadResourceString(IDS_FORMAT_CA_EXPIRATION), arwszDisplay[i], dwExp);
  250. break;
  251. }
  252. }
  253. wprintf(wszNewLine);
  254. wprintf(wszNewLine);
  255. error:
  256. return(hr);
  257. }
  258. //
  259. // DisplaySupportedCertTypes()
  260. //
  261. // Returns:
  262. //
  263. // hr from CAINFO API, fills array of cert types, for use in -addct flag
  264. //
  265. HRESULT
  266. DisplaySupportedCertTypes(
  267. IN HCAINFO hCA)
  268. {
  269. HRESULT hr;
  270. WCHAR **papwszCertTypes = NULL;
  271. DWORD i;
  272. hr = CAGetCAProperty(hCA, CA_PROP_CERT_TYPES, &papwszCertTypes);
  273. _JumpIfErrorStr(hr, error, "CAGetCAProperty", CA_PROP_CERT_TYPES);
  274. wprintf(myLoadResourceString(IDS_SUPPORTED_TEMPLATE));
  275. wprintf(wszNewLine);
  276. // Prepare certificate types in tab delimited format
  277. if (NULL == papwszCertTypes || NULL == papwszCertTypes[0])
  278. {
  279. wprintf(myLoadResourceString(IDS_NO_SUPPORTED_TEMPLATE));
  280. wprintf(wszNewLine);
  281. hr = S_FALSE;
  282. _JumpErrorStr(hr, error, "CAGetCAProperty", CA_PROP_CERT_TYPES);
  283. }
  284. if (g_fVerbose)
  285. {
  286. for (i = 0; NULL != papwszCertTypes[i]; i++)
  287. {
  288. wprintf(L"%ws\n", papwszCertTypes[i]);
  289. }
  290. wprintf(L":::::::::::::::::::::::::::::::::::\n");
  291. }
  292. // This compares the values returned from the property enumeration
  293. // to the values returned by enumerating the cert types
  294. hr = CheckSupportedCertTypes(hCA, papwszCertTypes);
  295. _JumpIfError(hr, error, "CheckSupportedCertTypes");
  296. error:
  297. if (NULL != papwszCertTypes)
  298. {
  299. HRESULT hr2 = CAFreeCAProperty(hCA, papwszCertTypes);
  300. if (S_OK != hr2)
  301. {
  302. if (S_OK == hr)
  303. {
  304. hr = hr2;
  305. }
  306. cuPrintAPIError(L"CAFreeCAProperty", hr2);
  307. _PrintError(hr2, "CAFreeCAProperty");
  308. }
  309. }
  310. return(hr);
  311. }
  312. HRESULT
  313. PingCA(
  314. IN WCHAR const *pwszCAName,
  315. IN WCHAR const *pwszServer,
  316. OUT ENUM_CATYPES *pCAType)
  317. {
  318. HRESULT hr;
  319. WCHAR *pwszConfig = NULL;
  320. CAINFO *pCAInfo = NULL;
  321. hr = myFormConfigString(pwszServer, pwszCAName, &pwszConfig);
  322. _JumpIfError(hr, error, "myFormConfigString");
  323. hr = cuPingCertSrv(pwszConfig, &pCAInfo);
  324. _JumpIfError(hr, error, "cuPingCertSrv");
  325. *pCAType = pCAInfo->CAType;
  326. error:
  327. if (NULL != pCAInfo)
  328. {
  329. LocalFree(pCAInfo);
  330. }
  331. if (NULL != pwszConfig)
  332. {
  333. LocalFree(pwszConfig);
  334. }
  335. return(hr);
  336. }
  337. HRESULT
  338. DisplayCAProperty(
  339. IN HCAINFO hCA,
  340. IN WCHAR const *pwszProperty,
  341. IN UINT idsFail,
  342. IN UINT idsDisplay,
  343. IN BOOL fIgnoreEmpty,
  344. OPTIONAL OUT WCHAR **ppwszOut)
  345. {
  346. HRESULT hr;
  347. WCHAR **papwszProperty = NULL;
  348. WCHAR const *pwsz;
  349. if (NULL != ppwszOut)
  350. {
  351. *ppwszOut = NULL;
  352. }
  353. hr = CAGetCAProperty(hCA, pwszProperty, &papwszProperty);
  354. if (S_OK != hr)
  355. {
  356. wprintf(myLoadResourceString(idsFail), hr);
  357. wprintf(wszNewLine);
  358. _JumpError(hr, error, "CAGetCAProperty");
  359. }
  360. if (NULL != papwszProperty && NULL != papwszProperty[0])
  361. {
  362. pwsz = papwszProperty[0];
  363. }
  364. else
  365. {
  366. if (fIgnoreEmpty)
  367. {
  368. hr = S_OK;
  369. goto error;
  370. }
  371. pwsz = L"";
  372. }
  373. wprintf(wszNewLine);
  374. wprintf(myLoadResourceString(idsDisplay), pwsz);
  375. wprintf(wszNewLine);
  376. if (NULL != ppwszOut)
  377. {
  378. hr = myDupString(pwsz, ppwszOut);
  379. _JumpIfError(hr, error, "myDupString");
  380. }
  381. hr = S_OK;
  382. error:
  383. if (NULL != papwszProperty)
  384. {
  385. HRESULT hr2 = CAFreeCAProperty(hCA, papwszProperty);
  386. if (S_OK != hr2)
  387. {
  388. if (S_OK == hr)
  389. {
  390. hr = hr2;
  391. }
  392. cuPrintAPIError(L"CAFreeCAProperty", hr2);
  393. _PrintError(hr2, "CAFreeCAProperty");
  394. }
  395. }
  396. return(hr);
  397. }
  398. #define CASMF_ONLINE 0x00000001
  399. class CASummary
  400. {
  401. public:
  402. CASummary()
  403. {
  404. m_pwszMachine = NULL;
  405. m_pwszCA = NULL;
  406. m_CAType = ENUM_UNKNOWN_CA;
  407. m_dwFlags = 0;
  408. m_hrCACert = S_OK;
  409. m_hrAccess = S_OK;
  410. }
  411. ~CASummary()
  412. {
  413. if (NULL != m_pwszMachine)
  414. {
  415. LocalFree(m_pwszMachine);
  416. }
  417. if (NULL != m_pwszCA)
  418. {
  419. LocalFree(m_pwszCA);
  420. }
  421. }
  422. public:
  423. WCHAR *m_pwszMachine;
  424. WCHAR *m_pwszCA;
  425. ENUM_CATYPES m_CAType;
  426. DWORD m_dwFlags;
  427. HRESULT m_hrCACert;
  428. HRESULT m_hrAccess;
  429. };
  430. HRESULT
  431. DisplayCAInfo(
  432. IN HCAINFO hCA,
  433. IN BOOL fPing,
  434. IN OUT CASummary *pCA)
  435. {
  436. HRESULT hr;
  437. CERT_CONTEXT const *pccCA = NULL;
  438. DWORD VerifyState;
  439. wprintf(g_wszSep);
  440. // CA Name
  441. hr = DisplayCAProperty(
  442. hCA,
  443. CA_PROP_NAME,
  444. IDS_FORMAT_CA_NAME_PROP_FAILED,
  445. IDS_FORMAT_CA_NAME_LIST,
  446. FALSE,
  447. &pCA->m_pwszCA);
  448. _JumpIfErrorStr(hr, error, "DisplayCAProperty", CA_PROP_NAME);
  449. // Machine name for CA
  450. hr = DisplayCAProperty(
  451. hCA,
  452. CA_PROP_DNSNAME,
  453. IDS_FORMAT_CA_DNS_PROP_FAILED,
  454. IDS_FORMAT_CA_MACHINE_LIST,
  455. FALSE,
  456. &pCA->m_pwszMachine);
  457. _JumpIfErrorStr(hr, error, "DisplayCAProperty", CA_PROP_DNSNAME);
  458. // DN of CA Object on DS
  459. hr = DisplayCAProperty(
  460. hCA,
  461. CA_PROP_DSLOCATION,
  462. IDS_FORMAT_CA_NAME_PROP_FAILED,
  463. IDS_FORMAT_CA_DS_LIST,
  464. FALSE,
  465. NULL);
  466. _JumpIfErrorStr(hr, error, "DisplayCAProperty", CA_PROP_DSLOCATION);
  467. // DN of CA certificate
  468. hr = DisplayCAProperty(
  469. hCA,
  470. CA_PROP_CERT_DN,
  471. IDS_FORMAT_CERT_DN_PROP_FAILED,
  472. IDS_FORMAT_CERT_DN_LIST,
  473. FALSE,
  474. NULL);
  475. _JumpIfErrorStr(hr, error, "DisplayCAProperty", CA_PROP_DSLOCATION);
  476. // Signature algs
  477. hr = DisplayCAProperty(
  478. hCA,
  479. CA_PROP_SIGNATURE_ALGS,
  480. IDS_FORMAT_CA_ALG_PROP_FAILED,
  481. IDS_FORMAT_CA_ALG_LIST,
  482. TRUE,
  483. NULL);
  484. _JumpIfErrorStr(hr, error, "DisplayCAProperty", CA_PROP_SIGNATURE_ALGS);
  485. pCA->m_hrAccess = CAAccessCheck(hCA, NULL);
  486. if (S_OK != pCA->m_hrAccess)
  487. {
  488. _PrintError(pCA->m_hrAccess, "CAAccessCheck");
  489. wprintf(wszNewLine);
  490. cuPrintError(0, pCA->m_hrAccess);
  491. }
  492. // Get the expiration date/time/... for an individual CA
  493. hr = ShowExpirationTime(hCA);
  494. _JumpIfError(hr, error, "ShowExpirationTime");
  495. if (fPing)
  496. {
  497. hr = PingCA(pCA->m_pwszCA, pCA->m_pwszMachine, &pCA->m_CAType);
  498. _PrintIfError(hr, "PingCA");
  499. if (S_OK == hr)
  500. {
  501. wprintf(wszNewLine);
  502. wprintf(g_wszPad2);
  503. cuDisplayCAType(pCA->m_CAType);
  504. pCA->m_dwFlags |= CASMF_ONLINE;
  505. }
  506. }
  507. hr = CAGetCACertificate(hCA, &pccCA);
  508. _JumpIfError(hr, error, "CAGetCACertificate");
  509. wprintf(wszNewLine);
  510. pCA->m_hrCACert = cuVerifyCertContext(
  511. pccCA, // pCert
  512. NULL, // hStoreCA
  513. 0, // cApplicationPolicies
  514. 0, // apszApplicationPolicies
  515. 0, // cIssuancePolicies
  516. 0, // apszIssuancePolicies
  517. IsEnterpriseCA(pCA->m_CAType), // fNTAuth
  518. &VerifyState);
  519. _PrintIfError(pCA->m_hrCACert, "cuVerifyCertContext");
  520. // Cert Types for CA == Multi valued property
  521. wprintf(wszNewLine);
  522. hr = DisplaySupportedCertTypes(hCA);
  523. if (S_FALSE == hr)
  524. {
  525. hr = S_OK;
  526. }
  527. _JumpIfError(hr, error, "DisplaySupportedCertTypes");
  528. error:
  529. wprintf(wszNewLine);
  530. return(hr);
  531. }
  532. VOID
  533. DisplayCASummary(
  534. IN CASummary const *pCA)
  535. {
  536. wprintf(L"%ws\\%ws:\n", pCA->m_pwszMachine, pCA->m_pwszCA);
  537. if (ENUM_UNKNOWN_CA != pCA->m_CAType)
  538. {
  539. wprintf(g_wszPad2);
  540. cuDisplayCAType(pCA->m_CAType);
  541. }
  542. if (S_OK != pCA->m_hrCACert)
  543. {
  544. wprintf(g_wszPad2);
  545. cuPrintError(0, pCA->m_hrCACert);
  546. }
  547. wprintf(
  548. L" %ws\n",
  549. myLoadResourceString((CASMF_ONLINE & pCA->m_dwFlags)?
  550. IDS_ONLINE : IDS_OFFLINE));
  551. if (S_OK != pCA->m_hrAccess)
  552. {
  553. wprintf(g_wszPad2);
  554. cuPrintError(0, pCA->m_hrAccess);
  555. }
  556. wprintf(wszNewLine);
  557. }
  558. // EnumCAs()
  559. //
  560. // We've got to assume that this works. Enumerates CAs on the DS.
  561. //
  562. // Returns:
  563. // Number of CA's on DS.
  564. //
  565. HRESULT
  566. EnumCAs(
  567. IN WCHAR const *pwszDomain,
  568. IN DWORD dwFlags,
  569. IN BOOL fPing)
  570. {
  571. HRESULT hr;
  572. DWORD i;
  573. DWORD cCA;
  574. HCAINFO hCA = NULL;
  575. CASummary *prgCAList = NULL;
  576. // Enumerate all of the CA's on the DS
  577. hr = CAEnumFirstCA(pwszDomain, dwFlags, &hCA);
  578. if (S_OK != hr)
  579. {
  580. cuPrintAPIError(L"CAEnumFirstCA", hr);
  581. _JumpError(hr, error, "CAEnumFirstCA");
  582. }
  583. if (NULL == hCA)
  584. {
  585. wprintf(myLoadResourceString(IDS_NO_CA_ON_DOMAIN));
  586. wprintf(wszNewLine);
  587. hr = CRYPT_E_NOT_FOUND;
  588. _JumpError(hr, error, "CAEnumFirstCA");
  589. }
  590. // Make sure that the counting function works at this stage.
  591. cCA = CACountCAs(hCA);
  592. prgCAList = new CASummary[cCA];
  593. if (NULL == prgCAList)
  594. {
  595. hr = E_OUTOFMEMORY;
  596. _JumpError(hr, error, "new");
  597. }
  598. for (i = 0; i < cCA; i++)
  599. {
  600. HCAINFO hNextCA;
  601. if (0 != i)
  602. {
  603. hr = CAEnumNextCA(hCA, &hNextCA);
  604. if (S_OK != hr)
  605. {
  606. cuPrintAPIError(L"CAEnumNextCA", hr);
  607. _JumpError(hr, error, "CAEnumNextCA");
  608. }
  609. if (NULL == hNextCA)
  610. {
  611. wprintf(
  612. myLoadResourceString(IDS_FORMAT_CAS_ON_DOMAIN),
  613. i,
  614. pwszDomain);
  615. wprintf(wszNewLine);
  616. break;
  617. }
  618. // It is difficult to determine the desired behavior for this API.
  619. hr = CACloseCA(hCA);
  620. if (S_OK != hr)
  621. {
  622. cuPrintAPIError(L"CACloseCA", hr);
  623. _JumpError(hr, error, "CACloseCA");
  624. }
  625. hCA = hNextCA;
  626. }
  627. hr = DisplayCAInfo(hCA, fPing, &prgCAList[i]);
  628. _JumpIfError(hr, error, "DisplayCAInfo");
  629. }
  630. // check the count in the enumeration, and verify the results
  631. if (cCA != i)
  632. {
  633. cuPrintAPIError(myLoadResourceString(IDS_CAENUMNEXTCA), cCA);
  634. hr = E_FAIL;
  635. _JumpError(hr, error, "cCA != i");
  636. }
  637. wprintf(g_wszSep);
  638. wprintf(wszNewLine);
  639. for (i = 0; i < cCA; i++)
  640. {
  641. DisplayCASummary(&prgCAList[i]);
  642. }
  643. error:
  644. delete [] prgCAList;
  645. if (NULL != hCA)
  646. {
  647. CACloseCA(hCA);
  648. }
  649. return(hr);
  650. }
  651. //
  652. // TestDFSPath()
  653. //
  654. // Verifies that the DFS on this machine can access the SYSVOL share
  655. //
  656. HRESULT
  657. TestDFSPath(
  658. IN WCHAR const *pwszDFSPath)
  659. {
  660. HRESULT hr;
  661. DWORD dwDate = 0;
  662. DWORD dwTime = 0;
  663. WIN32_FILE_ATTRIBUTE_DATA sFileData;
  664. if (!GetFileAttributesEx(
  665. pwszDFSPath,
  666. GetFileExInfoStandard,
  667. (VOID *) &sFileData))
  668. {
  669. hr = myHLastError();
  670. cuPrintAPIError(myLoadResourceString(IDS_NO_DFS), hr);
  671. _JumpError(hr, error, "GetFileAttributesEx");
  672. // To do... Add diagnostics here
  673. }
  674. wprintf(myLoadResourceString(IDS_DFS_DATA_ACCESS));
  675. wprintf(wszNewLine);
  676. hr = S_OK;
  677. error:
  678. return(hr);
  679. }
  680. //
  681. // TestLdapPath()
  682. //
  683. // This function verifies that LDAP connectivity is still there for a given
  684. // ldap URL
  685. //
  686. HRESULT
  687. TestLdapPath(
  688. IN WCHAR const *pwszLdapURL)
  689. {
  690. HRESULT hr;
  691. ULONG ldaperr;
  692. WCHAR *pwszError = NULL;
  693. LDAP *pldapbind = NULL;
  694. WCHAR *rgwszSearchAttribute[2] = {L"CN", NULL};
  695. WCHAR *pwszSearchParam = L"(&(objectClass=*))";
  696. LDAPMessage *SearchResult = NULL;
  697. WCHAR *pwszTmpUrl = NULL;
  698. // Parse URL, and do the search thing.
  699. pwszTmpUrl = wcsstr(pwszLdapURL, L"//");
  700. if (NULL == pwszTmpUrl) // not a URL
  701. {
  702. hr = S_OK;
  703. goto error;
  704. }
  705. pwszTmpUrl += 2;
  706. pldapbind = ldap_init(NULL, LDAP_PORT);
  707. if (NULL == pldapbind)
  708. {
  709. hr = myHLdapLastError(NULL, &pwszError);
  710. cuPrintAPIError(L"ldap_init", hr);
  711. _JumpError(hr, error, "ldap_init");
  712. }
  713. // This gives the IP address of the Cached LDAP DC from binding handle.
  714. // Resolve the name?
  715. ldaperr = ldap_bind_s(pldapbind, NULL, NULL, LDAP_AUTH_NEGOTIATE);
  716. if (ldaperr != LDAP_SUCCESS)
  717. {
  718. hr = myHLdapError(pldapbind, ldaperr, &pwszError);
  719. cuPrintAPIError(L"ldap_bind_s", hr);
  720. _JumpError(hr, error, "ldap_bind_s");
  721. }
  722. wprintf(
  723. L"%ws: %hs\n",
  724. myLoadResourceString(IDS_CACHED_LDAP_DC),
  725. pldapbind->ld_host);
  726. ldaperr = ldap_search_s(
  727. pldapbind,
  728. pwszTmpUrl,
  729. LDAP_SCOPE_SUBTREE,
  730. pwszSearchParam,
  731. rgwszSearchAttribute,
  732. 0,
  733. &SearchResult);
  734. if (ldaperr != LDAP_SUCCESS)
  735. {
  736. // we can't be 100% sure that this attribute is on the objec
  737. // for example, user UPN, so don't log to event log
  738. hr = myHLdapError(pldapbind, ldaperr, &pwszError);
  739. cuPrintAPIError(L"ldap_search_s", hr);
  740. _JumpError(hr, error, "ldap_search_s");
  741. }
  742. if (0 == ldap_count_entries(pldapbind, SearchResult))
  743. {
  744. wprintf(myLoadResourceString(IDS_NO_ENTRY_IN_PING));
  745. wprintf(wszNewLine);
  746. hr = CRYPT_E_NOT_FOUND;
  747. _JumpError(hr, error, "ldap_search_s");
  748. }
  749. hr = S_OK;
  750. error:
  751. if (NULL != pwszError)
  752. {
  753. wprintf(L"%ws\n", pwszError);
  754. LocalFree(pwszError);
  755. }
  756. if (NULL != SearchResult)
  757. {
  758. ldap_msgfree(SearchResult);
  759. }
  760. if (NULL != pldapbind)
  761. {
  762. ldap_unbind(pldapbind);
  763. }
  764. return(hr);
  765. }
  766. //
  767. // DisplayHistoryData()
  768. //
  769. // This function takes a key name, hkey, and value, and prints the value string.
  770. //
  771. #define wszREGDISPLAYNAME L"DisplayName"
  772. #define wszREGGPONAME L"GPOName"
  773. #define wszREGDSPATH L"DSPath"
  774. #define wszREGFILESYSPATH L"FileSysPath"
  775. HRESULT
  776. DisplayHistoryData(
  777. IN WCHAR const *pwszKeyName,
  778. IN WCHAR const *pwszSubKeyName,
  779. IN HKEY hKeyPolicy)
  780. {
  781. HRESULT hr;
  782. HRESULT hr2;
  783. HKEY hKeyNew = NULL;
  784. WCHAR buff[512];
  785. DWORD cwc;
  786. DWORD dwType;
  787. // Get #'d history key handle
  788. hr = RegOpenKeyEx(
  789. hKeyPolicy,
  790. pwszSubKeyName,
  791. 0,
  792. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  793. &hKeyNew);
  794. if (S_OK != hr)
  795. {
  796. cuPrintAPIError(L"RegOpenKeyEx", hr);
  797. _JumpErrorStr(hr, error, "RegOpenKeyEx", pwszSubKeyName);
  798. }
  799. // Get GPO Values
  800. cwc = ARRAYSIZE(buff);
  801. hr = RegQueryValueEx(
  802. hKeyNew,
  803. wszREGDISPLAYNAME,
  804. 0,
  805. &dwType,
  806. (BYTE *) buff,
  807. &cwc);
  808. if (S_OK != hr)
  809. {
  810. cuPrintAPIError(L"RegQueryValueEx", hr);
  811. _JumpErrorStr(hr, error, "RegQueryValueEx", wszREGDISPLAYNAME);
  812. }
  813. wprintf(myLoadResourceString(IDS_KEY_COLON));
  814. wprintf(L" %ws\\%ws\n", pwszKeyName, pwszSubKeyName);
  815. wprintf(myLoadResourceString(IDS_DISPLAYNAME_COLON));
  816. wprintf(L" %ws\n", buff);
  817. cwc = ARRAYSIZE(buff);
  818. hr = RegQueryValueEx(
  819. hKeyNew,
  820. wszREGGPONAME,
  821. 0,
  822. &dwType,
  823. (BYTE *) buff,
  824. &cwc);
  825. if (S_OK != hr)
  826. {
  827. cuPrintAPIError(L"RegQueryValueEx", hr);
  828. _JumpErrorStr(hr, error, "RegQueryValueEx", wszREGGPONAME);
  829. }
  830. wprintf(myLoadResourceString(IDS_FORMAT_GPO_NAME), buff);
  831. wprintf(wszNewLine);
  832. // See if LDAP can hit this policy
  833. cwc = ARRAYSIZE(buff);
  834. hr = RegQueryValueEx(
  835. hKeyNew,
  836. wszREGDSPATH,
  837. 0,
  838. &dwType,
  839. (BYTE *) buff,
  840. &cwc);
  841. if (hr == S_OK)
  842. {
  843. wprintf(L"%ws\n", buff);
  844. hr = TestLdapPath(buff);
  845. _PrintIfError(hr, "TestLdapPath");
  846. }
  847. else if (hr == ERROR_FILE_NOT_FOUND)
  848. {
  849. wprintf(myLoadResourceString(IDS_NO_DSPATH));
  850. wprintf(wszNewLine);
  851. hr = S_OK;
  852. }
  853. else
  854. {
  855. wprintf(myLoadResourceString(IDS_FORMAT_REG_QUERY_VALUE_FAILED), hr);
  856. wprintf(wszNewLine);
  857. _JumpErrorStr(hr, error, "RegQueryValueEx", wszREGDSPATH);
  858. }
  859. // See if DFS can get the data..
  860. cwc = ARRAYSIZE(buff);
  861. hr2 = RegQueryValueEx(
  862. hKeyNew,
  863. wszREGFILESYSPATH,
  864. 0,
  865. &dwType,
  866. (BYTE *) buff,
  867. &cwc);
  868. if (hr2 == S_OK)
  869. {
  870. wprintf(L"%ws\n", buff);
  871. hr2 = TestDFSPath(buff);
  872. _PrintIfErrorStr(hr2, "TestDFSPath", buff);
  873. }
  874. else if (hr2 == ERROR_FILE_NOT_FOUND)
  875. {
  876. wprintf(myLoadResourceString(IDS_NO_FILE_SYS_PATH));
  877. wprintf(wszNewLine);
  878. hr2 = S_OK;
  879. }
  880. else
  881. {
  882. wprintf(myLoadResourceString(IDS_FORMAT_REG_QUERY_VALUE_FAILED), hr2);
  883. wprintf(wszNewLine);
  884. if (S_OK == hr)
  885. {
  886. hr = hr2;
  887. }
  888. _JumpErrorStr(hr2, error, "RegQueryValueEx", wszREGFILESYSPATH);
  889. }
  890. if (S_OK == hr)
  891. {
  892. hr = hr2;
  893. }
  894. error:
  895. wprintf(wszNewLine);
  896. if (NULL != hKeyNew)
  897. {
  898. RegCloseKey(hKeyNew);
  899. }
  900. return(hr);
  901. }
  902. //
  903. // ResultFree()
  904. //
  905. // Frees results copied from LDAP search
  906. //
  907. VOID
  908. ResultFree(
  909. IN OUT WCHAR **rgwszRes)
  910. {
  911. DWORD i = 0;
  912. if (NULL != rgwszRes)
  913. {
  914. while (NULL != rgwszRes[i])
  915. {
  916. LocalFree(rgwszRes[i]);
  917. i++;
  918. }
  919. LocalFree(rgwszRes);
  920. }
  921. }
  922. HRESULT
  923. ResultAlloc(
  924. IN WCHAR const * const *rgpwszLdapRes,
  925. OUT WCHAR ***prgpwszOut)
  926. {
  927. HRESULT hr;
  928. DWORD cValue;
  929. DWORD i;
  930. WCHAR **rgpwszOut = NULL;
  931. for (cValue = 0; NULL != rgpwszLdapRes[cValue]; cValue++)
  932. ;
  933. rgpwszOut = (WCHAR **) LocalAlloc(
  934. LMEM_FIXED | LMEM_ZEROINIT,
  935. (cValue + 1) * sizeof(WCHAR *));
  936. if (NULL == rgpwszOut)
  937. {
  938. hr = E_OUTOFMEMORY;
  939. _JumpError(hr, error, "LocalAlloc");
  940. }
  941. for (i = 0; i < cValue; i++)
  942. {
  943. hr = myDupString(rgpwszLdapRes[i], &rgpwszOut[i]);
  944. _JumpIfError(hr, error, "myDupString");
  945. }
  946. rgpwszOut[i] = NULL;
  947. *prgpwszOut = rgpwszOut;
  948. rgpwszOut = NULL;
  949. hr = S_OK;
  950. error:
  951. if (NULL != rgpwszOut)
  952. {
  953. ResultFree(rgpwszOut);
  954. }
  955. return(hr);
  956. }
  957. //
  958. // GetPropertyFromDSObject()
  959. //
  960. // This function calls the DS to get a property of the user or machine object,
  961. // mimicing the call made by the CA.
  962. //
  963. // Params:
  964. //
  965. // rgwszSearchAttribute - IN NULL Terminated WCHAR *array. Only coded for 1
  966. // value retrieval at a time
  967. //
  968. // Returns:
  969. //
  970. // Pointer to string array that must be freed by call to LocalFree(), and
  971. // wszDN, if User specified
  972. //
  973. HRESULT
  974. GetPropertyFromDSObject(
  975. IN WCHAR **rgwszSearchAttribute,
  976. IN BOOL fMachine,
  977. OPTIONAL OUT WCHAR **ppwszUserDN,
  978. OUT WCHAR ***prgwszDSSearchRes)
  979. {
  980. HRESULT hr;
  981. ULONG ldaperr;
  982. WCHAR *pwszError = NULL;
  983. LDAP *pldapbind = NULL;
  984. WCHAR *pwszEmail = NULL;
  985. WCHAR *pwszCNName = NULL;
  986. DWORD cwc;
  987. WCHAR wszNTLM[MAX_PATH];
  988. WCHAR wszDN[MAX_PATH];
  989. WCHAR *pwszSearchUser = L"(&(objectClass=user)";
  990. WCHAR *pwszSearchComputer = L"(&(objectClass=computer)(cn=";
  991. WCHAR wszSearchParam[MAX_PATH];
  992. WCHAR *pwszAttName = NULL;
  993. WCHAR **rgwszValues = NULL;
  994. LDAPMessage *SearchResult = NULL;
  995. LDAPMessage *Attributes = NULL;
  996. DWORD dwValCount;
  997. *prgwszDSSearchRes = NULL;
  998. if (fMachine)
  999. {
  1000. // Get CN
  1001. cwc = ARRAYSIZE(wszNTLM);
  1002. if (!GetComputerName(wszNTLM, &cwc))
  1003. {
  1004. hr = myHLastError();
  1005. cuPrintAPIError(L"GetComputerName", hr);
  1006. _JumpError(hr, error, "GetComputerName");
  1007. }
  1008. // Get DN
  1009. cwc = ARRAYSIZE(wszDN);
  1010. if (!GetComputerObjectName(NameFullyQualifiedDN, wszDN, &cwc))
  1011. {
  1012. hr = myHLastError();
  1013. cuPrintAPIError(L"GetComputerName", hr);
  1014. _JumpError(hr, error, "GetComputerObjectName");
  1015. }
  1016. pwszCNName = wszNTLM;
  1017. }
  1018. else // User
  1019. {
  1020. // Get the SAM name..
  1021. cwc = ARRAYSIZE(wszNTLM);
  1022. if (!GetUserNameEx(NameSamCompatible, wszNTLM, &cwc))
  1023. {
  1024. hr = myHLastError();
  1025. cuPrintAPIError(L"GetUserNameEx", hr);
  1026. _JumpError(hr, error, "GetUserNameEx");
  1027. }
  1028. // Parse off user name...
  1029. pwszCNName = wcschr(wszNTLM, L'\\');
  1030. if (NULL == pwszCNName)
  1031. {
  1032. pwszCNName = wszNTLM;
  1033. }
  1034. else
  1035. {
  1036. pwszCNName++;
  1037. }
  1038. cwc = ARRAYSIZE(wszDN);
  1039. if (!TranslateName(
  1040. wszNTLM,
  1041. NameSamCompatible,
  1042. NameFullyQualifiedDN,
  1043. wszDN,
  1044. &cwc))
  1045. {
  1046. hr = myHLastError();
  1047. cuPrintAPIError(L"TranslateName", hr);
  1048. _JumpErrorStr(hr, error, "TranslateName", wszNTLM);
  1049. }
  1050. }
  1051. if (!fMachine && NULL != ppwszUserDN)
  1052. {
  1053. hr = myDupString(wszDN, ppwszUserDN);
  1054. _JumpIfError(hr, error, "myDupString");
  1055. }
  1056. // Init LDAP calls
  1057. pldapbind = ldap_init(NULL, LDAP_PORT);
  1058. if (NULL == pldapbind)
  1059. {
  1060. hr = myHLastError();
  1061. cuPrintAPIError(L"ldap_init", hr);
  1062. _JumpError(hr, error, "ldap_init");
  1063. }
  1064. ldaperr = ldap_bind_s(pldapbind, NULL, NULL, LDAP_AUTH_NEGOTIATE);
  1065. if (ldaperr != LDAP_SUCCESS)
  1066. {
  1067. hr = myHLdapError(pldapbind, ldaperr, &pwszError);
  1068. cuPrintAPIError(L"ldap_bind_s", hr);
  1069. _JumpError(hr, error, "ldap_bind_s");
  1070. }
  1071. // Compose search string
  1072. if (fMachine)
  1073. {
  1074. swprintf(wszSearchParam, L"%ws%ws))", pwszSearchComputer, pwszCNName);
  1075. }
  1076. else
  1077. {
  1078. swprintf(wszSearchParam, L"%ws)", pwszSearchUser);
  1079. }
  1080. // Do the search
  1081. ldaperr = ldap_search_s(
  1082. pldapbind,
  1083. wszDN,
  1084. LDAP_SCOPE_SUBTREE,
  1085. wszSearchParam,
  1086. rgwszSearchAttribute,
  1087. 0,
  1088. &SearchResult);
  1089. if (ldaperr != LDAP_SUCCESS)
  1090. {
  1091. // we can't be 100% sure that this attribute is on the objec
  1092. // for example, user UPN, so don't log to event log
  1093. hr = myHLdapError(pldapbind, ldaperr, &pwszError);
  1094. cuPrintAPIError(L"ldap_search_s", hr);
  1095. _JumpError(hr, error, "ldap_search_s");
  1096. }
  1097. if (0 == ldap_count_entries(pldapbind, SearchResult))
  1098. {
  1099. wprintf(myLoadResourceString(IDS_FORMAT_LDAP_NO_ENTRY), rgwszSearchAttribute[0]);
  1100. wprintf(wszNewLine);
  1101. hr = CRYPT_E_NOT_FOUND;
  1102. _JumpError(hr, error, "ldap_search_s");
  1103. }
  1104. // Make assumption that only one value will be returned for a user.
  1105. Attributes = ldap_first_entry(pldapbind, SearchResult);
  1106. if (NULL == Attributes)
  1107. {
  1108. hr = myHLastError();
  1109. cuPrintAPIError(L"ldap_first_entry", hr);
  1110. _JumpError(hr, error, "ldap_first_entry");
  1111. }
  1112. rgwszValues = ldap_get_values(
  1113. pldapbind,
  1114. Attributes,
  1115. rgwszSearchAttribute[0]); // remember, only one search
  1116. if (NULL == rgwszValues)
  1117. {
  1118. // we can't be 100% sure that this attribute is on the object
  1119. // for example, user UPN, so don't log to event log
  1120. // wprintf(L"ldap_get_values failed! %x", hr);
  1121. hr = S_OK;
  1122. goto error;
  1123. }
  1124. // ok, we've got the required attributes off of the user object..
  1125. // Let's return the proper strings, which must be freed by ResultFree()
  1126. hr = ResultAlloc(rgwszValues, prgwszDSSearchRes);
  1127. _JumpIfError(hr, error, "ResultAlloc");
  1128. error:
  1129. if (NULL != pwszError)
  1130. {
  1131. wprintf(L"%ws\n", pwszError);
  1132. LocalFree(pwszError);
  1133. }
  1134. if (NULL != SearchResult)
  1135. {
  1136. ldap_msgfree(SearchResult);
  1137. }
  1138. if (NULL != rgwszValues)
  1139. {
  1140. ldap_value_free(rgwszValues);
  1141. }
  1142. if (NULL != pldapbind)
  1143. {
  1144. ldap_unbind(pldapbind);
  1145. }
  1146. return(hr);
  1147. }
  1148. //
  1149. // DisplayLMGPRoot()
  1150. //
  1151. // This function uses CAPI2 api to enumerate roots in group policy root store
  1152. //
  1153. HRESULT
  1154. DisplayLMGPRoot()
  1155. {
  1156. HRESULT hr;
  1157. HCERTSTORE hStore = NULL;
  1158. DWORD cCert;
  1159. CERT_CONTEXT const *pcc = NULL;
  1160. CERT_CONTEXT const *pccPrev;
  1161. // Open local machine GP store
  1162. hStore = CertOpenStore(
  1163. CERT_STORE_PROV_SYSTEM_W,
  1164. 0,
  1165. NULL,
  1166. CERT_STORE_OPEN_EXISTING_FLAG |
  1167. CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
  1168. (VOID const *) wszROOT_CERTSTORE);
  1169. if (NULL == hStore)
  1170. {
  1171. hr = myHLastError();
  1172. cuPrintAPIError(L"CertOpenStore", hr);
  1173. _JumpError(hr, error, "CertOpenStore");
  1174. }
  1175. wprintf(myLoadResourceString(IDS_ROOT_CERT_IN_POLICY));
  1176. wprintf(wszNewLine);
  1177. // Enumerate certificates in store, giving subject, and thumbprint
  1178. cCert = 0;
  1179. pccPrev = NULL;
  1180. while (TRUE)
  1181. {
  1182. pcc = CertEnumCertificatesInStore(hStore, pccPrev);
  1183. if (NULL == pcc)
  1184. {
  1185. break;
  1186. }
  1187. // Output info
  1188. wprintf(myLoadResourceString(IDS_FORMAT_CERT_COLON), cCert);
  1189. wprintf(wszNewLine);
  1190. hr = cuDumpSerial(g_wszPad2, IDS_SERIAL, &pcc->pCertInfo->SerialNumber);
  1191. _PrintIfError(hr, "cuDumpSerial");
  1192. hr = cuDisplayCertNames(FALSE, g_wszPad2, pcc->pCertInfo);
  1193. _PrintIfError(hr, "cuDisplayCertNames");
  1194. hr = cuDumpCertType(g_wszPad2, pcc->pCertInfo);
  1195. _PrintIfError2(hr, "cuDumpCertType", CRYPT_E_NOT_FOUND);
  1196. hr = cuDisplayHash(
  1197. g_wszPad2,
  1198. pcc,
  1199. NULL,
  1200. CERT_SHA1_HASH_PROP_ID,
  1201. L"sha1");
  1202. _PrintIfError(hr, "cuDisplayHash");
  1203. wprintf(wszNewLine);
  1204. // Prepare for next cert
  1205. pccPrev = pcc;
  1206. cCert++;
  1207. }
  1208. if (0 == cCert)
  1209. {
  1210. wprintf(myLoadResourceString(IDS_NO_ROOT_IN_POLICY));
  1211. wprintf(wszNewLine);
  1212. wprintf(myLoadResourceString(IDS_CHECK_EVENT_LOG));
  1213. wprintf(wszNewLine);
  1214. }
  1215. hr = S_OK;
  1216. error:
  1217. return(hr);
  1218. }
  1219. //
  1220. // DisplayPolicyList()
  1221. //
  1222. // This function displays the GPOs applied to a machine / user
  1223. //
  1224. HRESULT
  1225. DisplayPolicyList(
  1226. IN DWORD dwFlags)
  1227. {
  1228. HRESULT hr;
  1229. HRESULT hr2;
  1230. HKEY hKeyPolicy = NULL;
  1231. HKEY hKeyPolicySub = NULL;
  1232. DWORD iPolicy;
  1233. DWORD cwc;
  1234. WCHAR wszKey[512];
  1235. WCHAR wszKeySub[512];
  1236. WCHAR **rgszValues = NULL;
  1237. FILETIME ft;
  1238. // Output
  1239. switch (dwFlags)
  1240. {
  1241. case TE_MACHINE:
  1242. wprintf(myLoadResourceString(IDS_POLICY_MACHINE));
  1243. wprintf(wszNewLine);
  1244. break;
  1245. default:
  1246. wprintf(myLoadResourceString(IDS_POLICY_USER));
  1247. wprintf(wszNewLine);
  1248. break;
  1249. }
  1250. // Open history key for enumeration
  1251. hr = RegOpenKeyEx(
  1252. (TE_MACHINE & dwFlags)? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
  1253. wszREGPOLICYHISTORY,
  1254. 0,
  1255. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  1256. &hKeyPolicy);
  1257. if (S_OK != hr)
  1258. {
  1259. cuPrintErrorAndString(L"RegOpenKeyEx", 0, hr, wszREGPOLICYHISTORY);
  1260. wprintf(myLoadResourceString(IDS_POSSIBLE_NO_POLICY));
  1261. wprintf(wszNewLine);
  1262. _PrintErrorStr(hr, "RegOpenKeyEx", wszREGPOLICYHISTORY);
  1263. if (hr == ERROR_FILE_NOT_FOUND)
  1264. {
  1265. hr = S_OK;
  1266. }
  1267. goto error;
  1268. }
  1269. for (iPolicy = 0; ; iPolicy++)
  1270. {
  1271. DWORD iPolicySub;
  1272. cwc = ARRAYSIZE(wszKey);
  1273. hr2 = RegEnumKeyEx(
  1274. hKeyPolicy,
  1275. iPolicy,
  1276. wszKey,
  1277. &cwc,
  1278. NULL,
  1279. NULL,
  1280. NULL,
  1281. &ft);
  1282. if (S_OK != hr2)
  1283. {
  1284. if (hr2 == ERROR_NO_MORE_ITEMS)
  1285. {
  1286. break;
  1287. }
  1288. cuPrintAPIError(L"RegEnumKeyEx", hr2);
  1289. if (S_OK == hr)
  1290. {
  1291. hr = hr2;
  1292. }
  1293. _JumpError(hr2, error, "RegEnumKeyEx");
  1294. }
  1295. hr2 = RegOpenKeyEx(
  1296. hKeyPolicy,
  1297. wszKey,
  1298. 0,
  1299. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  1300. &hKeyPolicySub);
  1301. if (S_OK != hr2)
  1302. {
  1303. cuPrintAPIError(L"RegOpenKeyEx", hr2);
  1304. if (S_OK == hr)
  1305. {
  1306. hr = hr2;
  1307. }
  1308. _JumpErrorStr(hr2, error, "RegOpenKeyEx", wszKey);
  1309. }
  1310. for (iPolicySub = 0; ; iPolicySub++)
  1311. {
  1312. cwc = ARRAYSIZE(wszKeySub);
  1313. hr2 = RegEnumKeyEx(
  1314. hKeyPolicySub,
  1315. iPolicySub,
  1316. wszKeySub,
  1317. &cwc,
  1318. NULL,
  1319. NULL,
  1320. NULL,
  1321. &ft);
  1322. if (S_OK != hr2)
  1323. {
  1324. if (hr2 == ERROR_NO_MORE_ITEMS)
  1325. {
  1326. break;
  1327. }
  1328. cuPrintAPIError(L"RegEnumKeyEx", hr2);
  1329. if (S_OK == hr)
  1330. {
  1331. hr = hr2;
  1332. }
  1333. _JumpError(hr2, error, "RegEnumKeyEx");
  1334. }
  1335. hr2 = DisplayHistoryData(wszKey, wszKeySub, hKeyPolicySub);
  1336. _PrintIfError(hr2, "DisplayHistoryData");
  1337. if (S_OK == hr)
  1338. {
  1339. hr = hr2;
  1340. }
  1341. }
  1342. RegCloseKey(hKeyPolicySub);
  1343. hKeyPolicySub = NULL;
  1344. }
  1345. error:
  1346. if (NULL != hKeyPolicySub)
  1347. {
  1348. RegCloseKey(hKeyPolicySub);
  1349. }
  1350. if (NULL != hKeyPolicy)
  1351. {
  1352. RegCloseKey(hKeyPolicy);
  1353. }
  1354. return(hr);
  1355. }
  1356. //
  1357. // ShowUserAndComputerInfo()
  1358. //
  1359. // GetUserName and GetComputerName()
  1360. //
  1361. HRESULT
  1362. ShowUserAndComputerInfo()
  1363. {
  1364. HRESULT hr;
  1365. WCHAR buff[256];
  1366. DWORD cwc;
  1367. cwc = ARRAYSIZE(buff);
  1368. if (!GetComputerNameEx(ComputerNamePhysicalNetBIOS, buff, &cwc))
  1369. {
  1370. hr = myHLastError();
  1371. _PrintError(hr, "GetComputerNameEx");
  1372. cuPrintAPIError(L"GetComputerNameEx", hr);
  1373. }
  1374. else
  1375. {
  1376. wprintf(myLoadResourceString(IDS_FORMAT_COMPUTER_NAME), buff);
  1377. wprintf(wszNewLine);
  1378. hr = S_OK;
  1379. }
  1380. cwc = ARRAYSIZE(buff);
  1381. if (!GetUserNameEx(NameSamCompatible, buff, &cwc))
  1382. {
  1383. HRESULT hr2 = myHLastError();
  1384. _PrintError(hr, "GetUserNameEx");
  1385. cuPrintAPIError(L"GetUserNameEx", hr2);
  1386. if (S_OK == hr)
  1387. {
  1388. hr = hr2;
  1389. }
  1390. }
  1391. else
  1392. {
  1393. wprintf(myLoadResourceString(IDS_FORMAT_USER_NAME), buff);
  1394. wprintf(wszNewLine);
  1395. wprintf(wszNewLine);
  1396. }
  1397. //error:
  1398. return(hr);
  1399. }
  1400. //
  1401. // Display Client Info
  1402. //
  1403. // This function is responsible for printing out the certificate template
  1404. // alias information, as well as any policies downloaded for an individual
  1405. // machine.
  1406. //
  1407. HRESULT
  1408. DisplayClientInfo()
  1409. {
  1410. HRESULT hr = S_OK;
  1411. HRESULT hr2;
  1412. WCHAR **rgwszDSSearchRes = NULL;
  1413. WCHAR *rgwszSearch[] = { L"mail", NULL };
  1414. // Show user and computer name *including domain*
  1415. hr2 = ShowUserAndComputerInfo();
  1416. _PrintIfError(hr2, "ShowUserAndComputerInfo");
  1417. if (S_OK == hr)
  1418. {
  1419. hr = hr2;
  1420. }
  1421. // Then, display all of the policies downloaded
  1422. hr2 = DisplayPolicyList(TE_USER);
  1423. _PrintIfError(hr2, "DisplayPolicyList");
  1424. if (S_OK == hr)
  1425. {
  1426. hr = hr2;
  1427. }
  1428. hr2 = DisplayPolicyList(TE_MACHINE);
  1429. _PrintIfError(hr2, "DisplayPolicyList");
  1430. if (S_OK == hr)
  1431. {
  1432. hr = hr2;
  1433. }
  1434. // Show the root certificates in the LMGP store
  1435. hr2 = DisplayLMGPRoot();
  1436. _PrintIfError(hr2, "DisplayLMGPRoot");
  1437. if (S_OK == hr)
  1438. {
  1439. hr = hr2;
  1440. }
  1441. // Display autoenrollment object(s)
  1442. #if 0
  1443. hr2 = DisplayAutoenrollmentObjects();
  1444. _PrintIfError(hr2, "DisplayAutoenrollmentObjects");
  1445. if (S_OK == hr)
  1446. {
  1447. hr = hr2;
  1448. }
  1449. #endif
  1450. // Verify DC LDAP connectivity
  1451. // PingDC();
  1452. hr2 = GetPropertyFromDSObject(rgwszSearch, FALSE, NULL, &rgwszDSSearchRes);
  1453. _PrintIfError(hr2, "GetPropertyFromDSObject");
  1454. if (S_OK == hr)
  1455. {
  1456. hr = hr2;
  1457. }
  1458. if (NULL != rgwszDSSearchRes)
  1459. {
  1460. ResultFree(rgwszDSSearchRes);
  1461. }
  1462. //error:
  1463. return(hr);
  1464. }
  1465. HRESULT
  1466. verbTCAInfo(
  1467. IN WCHAR const *pwszOption,
  1468. OPTIONAL IN WCHAR const *pwszDomain,
  1469. IN WCHAR const *pwszArg2,
  1470. IN WCHAR const *pwszArg3,
  1471. IN WCHAR const *pwszArg4)
  1472. {
  1473. HRESULT hr;
  1474. BSTR strDomainDN = NULL;
  1475. BSTR strConfigDN = NULL;
  1476. LDAP *pld = NULL;
  1477. if (myIsMinusSignString(pwszDomain))
  1478. {
  1479. hr = DisplayClientInfo();
  1480. _JumpIfError(hr, error, "DisplayClientInfo");
  1481. }
  1482. else
  1483. {
  1484. DWORD dwFlags = 0;
  1485. BOOL fForceOld;
  1486. if (NULL == pwszDomain)
  1487. {
  1488. if (NULL != g_pwszDC)
  1489. {
  1490. pwszDomain = g_pwszDC;
  1491. dwFlags |= CA_FLAG_SCOPE_DNS;
  1492. }
  1493. else
  1494. {
  1495. hr = myLdapOpen(NULL, 0, &pld, &strDomainDN, &strConfigDN);
  1496. _JumpIfError(hr, error, "myLdapOpen");
  1497. pwszDomain = strDomainDN;
  1498. }
  1499. }
  1500. fForceOld = g_fForce;
  1501. if (g_fForce)
  1502. {
  1503. g_fForce--;
  1504. dwFlags |= CA_FIND_INCLUDE_NON_TEMPLATE_CA | CA_FIND_INCLUDE_UNTRUSTED;
  1505. }
  1506. hr = EnumCAs(pwszDomain, dwFlags, TRUE);
  1507. g_fForce = fForceOld;
  1508. _JumpIfError(hr, error, "EnumCAs");
  1509. }
  1510. hr = S_OK;
  1511. error:
  1512. myLdapClose(pld, strDomainDN, strConfigDN);
  1513. return(hr);
  1514. }