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.

1169 lines
26 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. CheckSC
  5. Abstract:
  6. This application is used to provide a snapshot of the Calais (Smart Card
  7. Resource Manager) service's status, and to display certificates on smart
  8. cards via the common WinNT UI.
  9. CheckSC -- describes the RM status and displays each available sc cert(s)
  10. -r Readername -- for just one reader
  11. -sig -- display signature key certs only
  12. -ex -- display exchange key certs only
  13. -nocert -- don't look for certs to display
  14. -key -- verify keyset public key matches cert public key
  15. Author:
  16. Amanda Matlosz (AMatlosz) 07/14/1998
  17. Environment:
  18. Win32 Console App
  19. Notes:
  20. For use in NT5 public key rollout testing
  21. --*/
  22. /*++
  23. need to include the following libs:
  24. calaislb.lib (unicode build: calaislbw.lib)
  25. winscard.lib
  26. --*/
  27. #include <iostream.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. // #include <string.h>
  31. // #include <stdarg.h>
  32. #include <winscard.h>
  33. #include <SCardLib.h>
  34. #include <winsvc.h>
  35. #include <scEvents.h>
  36. #include <cryptui.h>
  37. #ifndef SCARD_PROVIDER_CSP
  38. #define SCARD_PROVIDER_CSP 2
  39. #endif
  40. #define KERB_PKINIT_CLIENT_CERT_TYPE szOID_PKIX_KP_CLIENT_AUTH
  41. //
  42. // Globals
  43. //
  44. int g_nKeys;
  45. DWORD g_rgKeySet[2]; // { AT_KEYEXCHANGE , AT_SIGNATURE };
  46. SCARDCONTEXT g_hSCardCtx;
  47. LPTSTR g_szReaderName;
  48. DWORD g_dwNumReaders;
  49. BOOL g_fReaderNameAllocd;
  50. BOOL g_fChain = FALSE;
  51. BOOL g_fPublicKeyCheck = FALSE;
  52. SCARD_READERSTATE* g_pReaderStatusArray;
  53. const char* g_szEx = TEXT("exchange");
  54. const char* g_szSig = TEXT("signature");
  55. //
  56. // Functions
  57. //
  58. ///////////////////////////////////////////////////////////////////////////////
  59. // DisplayUsage does easy UI
  60. void DisplayUsage()
  61. {
  62. cout << "\n"
  63. << "CheckSC [-sig|-ex|-nocert|-chain|-key] [-r \"Readername\"]\n"
  64. << " -sig Displays only signature key certificates.\n"
  65. << " -ex Displays only signature key certificates.\n"
  66. << " -nocert Does not display smart card certificates.\n"
  67. << " -chain Check trust status.\n"
  68. << " -key Verify keyset public key matches certificate public key.\n"
  69. << endl;
  70. }
  71. ///////////////////////////////////////////////////////////////////////////////
  72. // ProcessCommandLine does the dirty work, sets behavior globals
  73. bool ProcessCommandLine(DWORD cArgs, LPCTSTR rgszArgs[])
  74. {
  75. // set everything to default
  76. g_szReaderName = NULL; // no reader
  77. g_rgKeySet[0] = AT_KEYEXCHANGE; // certs for both kinds of keys
  78. g_rgKeySet[1] = AT_SIGNATURE;
  79. g_nKeys = 2;
  80. if (cArgs == 1)
  81. {
  82. return true;
  83. }
  84. // For each arg, verify that it's a real arg and deal with it
  85. bool fLookForReader = false;
  86. bool fCertOptionSpecified = false;
  87. bool fBogus = FALSE;
  88. for (DWORD n=1; n<cArgs; n++)
  89. {
  90. if ('/' == *rgszArgs[n] || '-' == *rgszArgs[n])
  91. {
  92. if (0 == _stricmp("r", rgszArgs[n]+1*sizeof(TCHAR))) // reader
  93. {
  94. fLookForReader = true;
  95. }
  96. else if (0 == _stricmp("sig",rgszArgs[n]+1*sizeof(TCHAR))) // signature cert only
  97. {
  98. if (true == fCertOptionSpecified)
  99. {
  100. // bogus!
  101. fBogus = true;
  102. break;
  103. }
  104. g_rgKeySet[0] = AT_SIGNATURE;
  105. g_nKeys = 1;
  106. }
  107. else if (0 == _stricmp("ex",rgszArgs[n]+1*sizeof(TCHAR))) // exchange cert only
  108. {
  109. if (true == fCertOptionSpecified)
  110. {
  111. // bogus!
  112. fBogus = true;
  113. break;
  114. }
  115. g_rgKeySet[0] = AT_KEYEXCHANGE;
  116. g_nKeys = 1;
  117. }
  118. else if (0 == _stricmp("nocert",rgszArgs[n]+1*sizeof(TCHAR))) // no certs
  119. {
  120. if (true == fCertOptionSpecified)
  121. {
  122. // bogus!
  123. fBogus = true;
  124. break;
  125. }
  126. g_nKeys = 0;
  127. }
  128. else if (0 == _stricmp("chain",rgszArgs[n]+1*sizeof(TCHAR))) // verify chain
  129. {
  130. g_fChain = TRUE;
  131. }
  132. else if (0 == _stricmp("key",rgszArgs[n]+1*sizeof(TCHAR))) // verify cert & keyset
  133. {
  134. g_fPublicKeyCheck = TRUE;
  135. }
  136. else
  137. {
  138. // bogus!!
  139. fBogus = true;
  140. break;
  141. }
  142. }
  143. else if (fLookForReader)
  144. {
  145. fLookForReader = false;
  146. g_szReaderName = (LPTSTR)rgszArgs[n];
  147. }
  148. else
  149. {
  150. // Bogus!
  151. fBogus = true;
  152. break;
  153. }
  154. }
  155. if (!fLookForReader && !fBogus)
  156. {
  157. // All's well, we're set to go
  158. return true;
  159. }
  160. //
  161. // educate user when args incorrect
  162. //
  163. DisplayUsage();
  164. return false;
  165. }
  166. ///////////////////////////////////////////////////////////////////////////////
  167. bool IsCalaisRunning()
  168. {
  169. bool fCalaisUp = false;
  170. HANDLE hCalaisStarted = NULL;
  171. HMODULE hDll = GetModuleHandle( TEXT("WINSCARD.DLL") );
  172. typedef HANDLE (WINAPI *PFN_SCARDACCESSSTARTEDEVENT)(VOID);
  173. PFN_SCARDACCESSSTARTEDEVENT pSCardAccessStartedEvent;
  174. pSCardAccessStartedEvent = (PFN_SCARDACCESSSTARTEDEVENT) GetProcAddress(hDll, "SCardAccessStartedEvent");
  175. if (pSCardAccessStartedEvent)
  176. {
  177. hCalaisStarted = pSCardAccessStartedEvent();
  178. }
  179. if (hCalaisStarted)
  180. {
  181. if (WAIT_OBJECT_0 == WaitForSingleObject(hCalaisStarted, 1000))
  182. {
  183. fCalaisUp = true;
  184. }
  185. }
  186. //
  187. // Display status
  188. //
  189. if (fCalaisUp)
  190. {
  191. cout << "\n"
  192. << "The Microsoft Smart Card Resource Manager is running.\n"
  193. << endl;
  194. }
  195. else
  196. {
  197. cout << "\n"
  198. << "The Microsoft Smart Card Resource Manager is not running.\n"
  199. << endl;
  200. }
  201. //
  202. // Clean up
  203. //
  204. return fCalaisUp;
  205. }
  206. ///////////////////////////////////////////////////////////////////////////////
  207. // DisplayReaderList tries to set g_hSCardCtx, get a list of currently available
  208. // smart card readers, and display their status
  209. void DisplayReaderList()
  210. {
  211. long lReturn = SCARD_S_SUCCESS;
  212. cout << "Current reader/card status:\n" << endl;
  213. // Acquire global SCARDCONTEXT from resource manager if possible
  214. lReturn = SCardEstablishContext(SCARD_SCOPE_USER,
  215. NULL,
  216. NULL,
  217. &g_hSCardCtx);
  218. if (SCARD_S_SUCCESS != lReturn)
  219. {
  220. cout << "SCardEstablishContext failed for user scope.\n"
  221. << "A list of smart card readers cannot be determined.\n"
  222. << endl;
  223. return;
  224. }
  225. // Build a readerstatus array from either a list of readers; or use the one the user specified
  226. g_dwNumReaders = 0;
  227. if (NULL == g_szReaderName)
  228. {
  229. DWORD dwAutoAllocate = SCARD_AUTOALLOCATE;
  230. g_fReaderNameAllocd = true;
  231. lReturn = SCardListReaders(g_hSCardCtx,
  232. SCARD_DEFAULT_READERS,
  233. (LPTSTR)&g_szReaderName,
  234. &dwAutoAllocate);
  235. if (SCARD_S_SUCCESS != lReturn)
  236. {
  237. TCHAR szMsg[128]; // %Xx
  238. sprintf(szMsg,
  239. "SCardListReaders failed for SCARD_ALL_READERS with: 0x%X.\n",
  240. lReturn);
  241. cout << szMsg;
  242. if (SCARD_E_NO_READERS_AVAILABLE == lReturn)
  243. {
  244. cout << "No smart card readers are currently available.\n";
  245. }
  246. else
  247. {
  248. cout << "A list of smart card readers could not be determined.\n";
  249. }
  250. cout << endl;
  251. return;
  252. }
  253. // Build a readerstatus array...
  254. LPCTSTR szReaderName = g_szReaderName;
  255. g_dwNumReaders = MStringCount(szReaderName);
  256. g_pReaderStatusArray = new SCARD_READERSTATE[g_dwNumReaders];
  257. ::ZeroMemory((LPVOID)g_pReaderStatusArray, sizeof(g_pReaderStatusArray));
  258. szReaderName = FirstString(szReaderName);
  259. for (DWORD dwRdr = 0; NULL != szReaderName && dwRdr < g_dwNumReaders; szReaderName = NextString(szReaderName), dwRdr++)
  260. {
  261. g_pReaderStatusArray[dwRdr].szReader = (LPCTSTR)szReaderName;
  262. g_pReaderStatusArray[dwRdr].dwCurrentState = SCARD_STATE_UNAWARE;
  263. }
  264. }
  265. else
  266. {
  267. g_dwNumReaders = 1;
  268. g_pReaderStatusArray = new SCARD_READERSTATE;
  269. g_pReaderStatusArray->szReader = (LPCTSTR)g_szReaderName;
  270. g_pReaderStatusArray->dwCurrentState = SCARD_STATE_UNAWARE;
  271. }
  272. // ...And get the reader status from the resource manager
  273. lReturn = SCardGetStatusChange(g_hSCardCtx,
  274. INFINITE, // hardly
  275. g_pReaderStatusArray,
  276. g_dwNumReaders);
  277. if (SCARD_S_SUCCESS != lReturn)
  278. {
  279. TCHAR szMsg[128]; // %Xx
  280. sprintf(szMsg,
  281. "SCardGetStatusChange failed with: 0x%X.\n",
  282. lReturn);
  283. cout << szMsg << endl;
  284. sprintf(szMsg,
  285. "MStringCount returned %d readers.\n",
  286. g_dwNumReaders);
  287. cout << szMsg << endl;
  288. return;
  289. }
  290. // Finally, display all reader information
  291. DWORD dwState = 0;
  292. for (DWORD dwRdrSt = 0; dwRdrSt < g_dwNumReaders; dwRdrSt++)
  293. {
  294. //--- reader: readerName\n
  295. cout << TEXT("--- reader: ")
  296. << g_pReaderStatusArray[dwRdrSt].szReader
  297. << TEXT("\n");
  298. //--- status: /bits/\n
  299. bool fOr = false;
  300. cout << TEXT("--- status: ");
  301. dwState = g_pReaderStatusArray[dwRdrSt].dwEventState;
  302. if (0 != (dwState & SCARD_STATE_UNKNOWN))
  303. {
  304. cout << TEXT("SCARD_STATE_UNKNOWN ");
  305. fOr = true;
  306. }
  307. if (0 != (dwState & SCARD_STATE_UNAVAILABLE))
  308. {
  309. if (fOr)
  310. {
  311. cout << TEXT("| ");
  312. }
  313. cout << TEXT("SCARD_STATE_UNAVAILABLE ");
  314. fOr = true;
  315. }
  316. if (0 != (dwState & SCARD_STATE_EMPTY))
  317. {
  318. if (fOr)
  319. {
  320. cout << TEXT("| ");
  321. }
  322. cout << TEXT("SCARD_STATE_EMPTY ");
  323. fOr = true;
  324. }
  325. if (0 != (dwState & SCARD_STATE_PRESENT))
  326. {
  327. if (fOr)
  328. {
  329. cout << TEXT("| ");
  330. }
  331. cout << TEXT("SCARD_STATE_PRESENT ";)
  332. fOr = true;
  333. }
  334. if (0 != (dwState & SCARD_STATE_EXCLUSIVE))
  335. {
  336. if (fOr)
  337. {
  338. cout << TEXT("| ";)
  339. }
  340. cout << TEXT("SCARD_STATE_EXCLUSIVE ");
  341. fOr = true;
  342. }
  343. if (0 != (dwState & SCARD_STATE_INUSE))
  344. {
  345. if (fOr)
  346. {
  347. cout << TEXT("| ");
  348. }
  349. cout << TEXT("SCARD_STATE_INUSE ");
  350. fOr = true;
  351. }
  352. if (0 != (dwState & SCARD_STATE_MUTE))
  353. {
  354. if (fOr)
  355. {
  356. cout << TEXT("| ");
  357. }
  358. cout << TEXT("SCARD_STATE_MUTE ");
  359. fOr = true;
  360. }
  361. if (0 != (dwState & SCARD_STATE_UNPOWERED))
  362. {
  363. if (fOr)
  364. {
  365. cout << TEXT("| ");
  366. }
  367. cout << TEXT("SCARD_STATE_UNPOWERED");
  368. fOr = true;
  369. }
  370. cout << TEXT("\n");
  371. //--- status: what scstatus would say\n
  372. cout << TEXT("--- status: ");
  373. // NO CARD
  374. if(dwState & SCARD_STATE_EMPTY)
  375. {
  376. cout << TEXT("No card.");// SC_STATUS_NO_CARD;
  377. }
  378. // CARD in reader: SHARED, EXCLUSIVE, FREE, UNKNOWN ?
  379. else if(dwState & SCARD_STATE_PRESENT)
  380. {
  381. if (dwState & SCARD_STATE_MUTE)
  382. {
  383. cout << TEXT("The card is unrecognized or not responding.");// SC_STATUS_UNKNOWN;
  384. }
  385. else if (dwState & SCARD_STATE_INUSE)
  386. {
  387. if(dwState & SCARD_STATE_EXCLUSIVE)
  388. {
  389. cout << TEXT("Card is in use exclusively by another process.");// SC_STATUS_EXCLUSIVE;
  390. }
  391. else
  392. {
  393. cout << TEXT("The card is being shared by a process.");// SC_STATUS_SHARED;
  394. }
  395. }
  396. else
  397. {
  398. cout << TEXT("The card is available for use.");// SC_SATATUS_AVAILABLE;
  399. }
  400. }
  401. // READER ERROR: at this point, something's gone wrong
  402. else // dwState & SCARD_STATE_UNAVAILABLE
  403. {
  404. cout << TEXT("Card/Reader not responding.");// SC_STATUS_ERROR;
  405. }
  406. cout << TEXT("\n");
  407. //- card name(s):\n\n
  408. cout << TEXT("--- card: ");
  409. if (0 < g_pReaderStatusArray[dwRdrSt].cbAtr)
  410. {
  411. //
  412. // Get the name of the card
  413. //
  414. LPTSTR szCardName = NULL;
  415. DWORD dwAutoAllocate = SCARD_AUTOALLOCATE;
  416. lReturn = SCardListCards(g_hSCardCtx,
  417. g_pReaderStatusArray[dwRdrSt].rgbAtr,
  418. NULL,
  419. 0,
  420. (LPTSTR)&szCardName,
  421. &dwAutoAllocate);
  422. if (SCARD_S_SUCCESS != lReturn || NULL == szCardName)
  423. {
  424. cout << TEXT("Unknown Card.");
  425. }
  426. else
  427. {
  428. LPCTSTR szName = szCardName;
  429. bool fNotFirst = false;
  430. for (szName = FirstString(szName); NULL != szName; szName = NextString(szName))
  431. {
  432. if (fNotFirst) cout << TEXT(", ");
  433. cout << szName;
  434. fNotFirst = true;
  435. }
  436. }
  437. if (NULL != szCardName)
  438. {
  439. SCardFreeMemory(g_hSCardCtx, (PVOID)szCardName);
  440. }
  441. }
  442. cout << TEXT("\n") << endl;
  443. }
  444. }
  445. ///////////////////////////////////////////////////////////////////////////////
  446. // GetCertContext -- called by DisplayCerts
  447. PCCERT_CONTEXT GetCertContext(HCRYPTPROV* phProv, HCRYPTKEY* phKey, DWORD dwKeySpec)
  448. {
  449. PCCERT_CONTEXT pCertCtx = NULL;
  450. LONG lResult = SCARD_S_SUCCESS;
  451. BOOL fSts = FALSE;
  452. PCERT_PUBLIC_KEY_INFO pInfo = NULL;
  453. CRYPT_KEY_PROV_INFO KeyProvInfo;
  454. LPSTR szContainerName = NULL;
  455. LPSTR szProvName = NULL;
  456. LPWSTR wszContainerName = NULL;
  457. LPWSTR wszProvName = NULL;
  458. DWORD cbContainerName, cbProvName;
  459. LPBYTE pbCert = NULL;
  460. DWORD cbCertLen;
  461. int nLen = 0;
  462. //
  463. // Get the cert from this key
  464. //
  465. fSts = CryptGetKeyParam(
  466. *phKey,
  467. KP_CERTIFICATE,
  468. NULL,
  469. &cbCertLen,
  470. 0);
  471. if (!fSts)
  472. {
  473. lResult = GetLastError();
  474. if (ERROR_MORE_DATA != lResult)
  475. {
  476. return NULL;
  477. }
  478. }
  479. lResult = SCARD_S_SUCCESS;
  480. pbCert = (LPBYTE)LocalAlloc(LPTR, cbCertLen);
  481. if (NULL == pbCert)
  482. {
  483. return NULL;
  484. }
  485. fSts = CryptGetKeyParam(
  486. *phKey,
  487. KP_CERTIFICATE,
  488. pbCert,
  489. &cbCertLen,
  490. 0);
  491. if (!fSts)
  492. {
  493. return NULL;
  494. }
  495. //
  496. // Convert the certificate into a Cert Context.
  497. //
  498. pCertCtx = CertCreateCertificateContext(
  499. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  500. pbCert,
  501. cbCertLen);
  502. if (NULL == pCertCtx)
  503. {
  504. lResult = GetLastError();
  505. goto ErrorExit;
  506. }
  507. //
  508. // Perform public key check
  509. //
  510. if (g_fPublicKeyCheck) // -key
  511. {
  512. cout << "\nPerforming public key matching test...\n";
  513. DWORD dwPCBsize = 0;
  514. fSts = CryptExportPublicKeyInfo(
  515. *phProv, // in
  516. dwKeySpec, // in
  517. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, // in
  518. NULL,
  519. &dwPCBsize // in, out
  520. );
  521. if (!fSts)
  522. {
  523. lResult = GetLastError();
  524. TCHAR sz[256];
  525. sprintf(sz,"CryptExportPublicKeyInfo failed: 0x%x\n ", lResult);
  526. cout << sz;
  527. goto ErrorExit;
  528. }
  529. if (dwPCBsize == 0)
  530. {
  531. lResult = SCARD_E_UNEXPECTED; // huh?
  532. cout << "CryptExportPublicKeyInfo succeeded but returned size==0\n";
  533. goto ErrorExit;
  534. }
  535. pInfo = (PCERT_PUBLIC_KEY_INFO)LocalAlloc(LPTR, dwPCBsize);
  536. if (NULL == pInfo)
  537. {
  538. lResult = E_OUTOFMEMORY;
  539. cout << "Could not complete key test; out of memory.\n";
  540. goto ErrorExit;
  541. }
  542. fSts = CryptExportPublicKeyInfo(
  543. *phProv,
  544. dwKeySpec,
  545. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  546. pInfo,
  547. &dwPCBsize
  548. );
  549. if (!fSts)
  550. {
  551. lResult = GetLastError();
  552. TCHAR sz[256];
  553. sprintf(sz,"CryptExportPublicKeyInfo failed: 0x%x\n ", lResult);
  554. cout << sz;
  555. goto ErrorExit;
  556. }
  557. fSts = CertComparePublicKeyInfo(
  558. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  559. pInfo, // from the private keyset
  560. &(pCertCtx->pCertInfo->SubjectPublicKeyInfo) // public key from cert
  561. );
  562. if (!fSts)
  563. {
  564. lResult = GetLastError();
  565. goto ErrorExit;
  566. }
  567. cout << "Public key matching test succeeded.\n";
  568. }
  569. //
  570. // Associate cryptprovider w/ the private key property of this cert
  571. //
  572. // ... need the container name
  573. fSts = CryptGetProvParam(
  574. *phProv,
  575. PP_CONTAINER,
  576. NULL, // out
  577. &cbContainerName, // in/out
  578. 0);
  579. if (!fSts)
  580. {
  581. lResult = GetLastError();
  582. goto ErrorExit;
  583. }
  584. szContainerName = (LPSTR)LocalAlloc(LPTR, cbContainerName);
  585. fSts = CryptGetProvParam(
  586. *phProv,
  587. PP_CONTAINER,
  588. (PBYTE)szContainerName,
  589. &cbContainerName,
  590. 0);
  591. if (!fSts)
  592. {
  593. lResult = GetLastError();
  594. goto ErrorExit;
  595. }
  596. nLen = MultiByteToWideChar(
  597. GetACP(),
  598. MB_PRECOMPOSED,
  599. szContainerName,
  600. -1,
  601. NULL,
  602. 0);
  603. if (0 < nLen)
  604. {
  605. wszContainerName = (LPWSTR)LocalAlloc(LPTR, nLen*sizeof(WCHAR));
  606. nLen = MultiByteToWideChar(
  607. GetACP(),
  608. MB_PRECOMPOSED,
  609. szContainerName,
  610. -1,
  611. wszContainerName,
  612. nLen);
  613. if (0 == nLen)
  614. {
  615. lResult = GetLastError();
  616. goto ErrorExit;
  617. }
  618. }
  619. // ... need the provider name
  620. fSts = CryptGetProvParam(
  621. *phProv,
  622. PP_NAME,
  623. NULL, // out
  624. &cbProvName, // in/out
  625. 0);
  626. if (!fSts)
  627. {
  628. lResult = GetLastError();
  629. goto ErrorExit;
  630. }
  631. szProvName = (LPSTR)LocalAlloc(LPTR, cbProvName);
  632. fSts = CryptGetProvParam(
  633. *phProv,
  634. PP_NAME,
  635. (PBYTE)szProvName, // out
  636. &cbProvName, // in/out
  637. 0);
  638. if (!fSts)
  639. {
  640. lResult = GetLastError();
  641. goto ErrorExit;
  642. }
  643. nLen = MultiByteToWideChar(
  644. GetACP(),
  645. MB_PRECOMPOSED,
  646. szProvName,
  647. -1,
  648. NULL,
  649. 0);
  650. if (0 < nLen)
  651. {
  652. wszProvName = (LPWSTR)LocalAlloc(LPTR, nLen*sizeof(WCHAR));
  653. nLen = MultiByteToWideChar(
  654. GetACP(),
  655. MB_PRECOMPOSED,
  656. szProvName,
  657. -1,
  658. wszProvName,
  659. nLen);
  660. if (0 == nLen)
  661. {
  662. lResult = GetLastError();
  663. goto ErrorExit;
  664. }
  665. }
  666. //
  667. // Set the cert context properties to reflect the prov info
  668. //
  669. KeyProvInfo.pwszContainerName = wszContainerName;
  670. KeyProvInfo.pwszProvName = wszProvName;
  671. KeyProvInfo.dwProvType = PROV_RSA_FULL;
  672. KeyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
  673. KeyProvInfo.cProvParam = 0;
  674. KeyProvInfo.rgProvParam = NULL;
  675. KeyProvInfo.dwKeySpec = dwKeySpec;
  676. fSts = CertSetCertificateContextProperty(
  677. pCertCtx,
  678. CERT_KEY_PROV_INFO_PROP_ID,
  679. 0,
  680. (void *)&KeyProvInfo);
  681. if (!fSts)
  682. {
  683. lResult = GetLastError();
  684. // the cert's been incorrectly created -- scrap it.
  685. CertFreeCertificateContext(pCertCtx);
  686. pCertCtx = NULL;
  687. goto ErrorExit;
  688. }
  689. ErrorExit:
  690. if (NULL != pInfo)
  691. {
  692. LocalFree(pInfo);
  693. }
  694. if(NULL != szContainerName)
  695. {
  696. LocalFree(szContainerName);
  697. }
  698. if(NULL != szProvName)
  699. {
  700. LocalFree(szProvName);
  701. }
  702. if(NULL != wszContainerName)
  703. {
  704. LocalFree(wszContainerName);
  705. }
  706. if(NULL != wszProvName)
  707. {
  708. LocalFree(wszProvName);
  709. }
  710. return pCertCtx;
  711. }
  712. /*++
  713. DisplayChainInfo:
  714. This code verifies that the SC cert is valid.
  715. Uses identical code to KDC cert chaining engine.
  716. Author:
  717. Todds
  718. --*/
  719. DWORD
  720. DisplayChainInfo(PCCERT_CONTEXT pCert)
  721. {
  722. BOOL fRet = FALSE;
  723. DWORD dwErr = 0;
  724. TCHAR sz[256];
  725. CERT_CHAIN_PARA ChainParameters = {0};
  726. LPSTR ClientAuthUsage = KERB_PKINIT_CLIENT_CERT_TYPE;
  727. PCCERT_CHAIN_CONTEXT ChainContext = NULL;
  728. ChainParameters.cbSize = sizeof(CERT_CHAIN_PARA);
  729. ChainParameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  730. ChainParameters.RequestedUsage.Usage.cUsageIdentifier = 1;
  731. ChainParameters.RequestedUsage.Usage.rgpszUsageIdentifier = &ClientAuthUsage;
  732. if (!CertGetCertificateChain(
  733. HCCE_LOCAL_MACHINE,
  734. pCert,
  735. NULL, // evaluate at current time
  736. NULL, // no additional stores
  737. &ChainParameters,
  738. CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
  739. NULL, // reserved
  740. &ChainContext
  741. ))
  742. {
  743. dwErr = GetLastError();
  744. sprintf(sz,"CertGetCertificateChain failed: 0x%x\n ", dwErr);
  745. cout << sz;
  746. }
  747. else
  748. {
  749. if (ChainContext->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR)
  750. {
  751. dwErr = ChainContext->TrustStatus.dwErrorStatus;
  752. sprintf(sz,"CertGetCertificateChain TrustStatus failed, see wincrypt.h: 0x%x\n ", dwErr);
  753. cout << sz;
  754. }
  755. }
  756. if (ChainContext != NULL)
  757. {
  758. CertFreeCertificateChain(ChainContext);
  759. }
  760. return dwErr;
  761. }
  762. ///////////////////////////////////////////////////////////////////////////////
  763. // DisplayCerts
  764. void DisplayCerts()
  765. {
  766. _ASSERTE(0 < g_nKeys);
  767. // For each reader that has a card, load the CSP and display the cert
  768. for (DWORD dw = 0; dw < g_dwNumReaders; dw++)
  769. {
  770. LPTSTR szCardName = NULL;
  771. LPTSTR szCSPName = NULL;
  772. if(0 >= g_pReaderStatusArray[dw].cbAtr)
  773. {
  774. // no point to do anymore work in this iteration
  775. continue;
  776. }
  777. //
  778. // Inform user of current test
  779. //
  780. cout << TEXT("\n=======================================================\n")
  781. << TEXT("Analyzing card in reader: ")
  782. << g_pReaderStatusArray[dw].szReader
  783. << TEXT("\n");
  784. // Get the name of the card
  785. DWORD dwAutoAllocate = SCARD_AUTOALLOCATE;
  786. LONG lReturn = SCardListCards(g_hSCardCtx,
  787. g_pReaderStatusArray[dw].rgbAtr,
  788. NULL,
  789. 0,
  790. (LPTSTR)&szCardName,
  791. &dwAutoAllocate);
  792. if (SCARD_S_SUCCESS == lReturn)
  793. {
  794. dwAutoAllocate = SCARD_AUTOALLOCATE;
  795. lReturn = SCardGetCardTypeProviderName(
  796. g_hSCardCtx,
  797. szCardName,
  798. SCARD_PROVIDER_CSP,
  799. (LPTSTR)&szCSPName,
  800. &dwAutoAllocate);
  801. if (SCARD_S_SUCCESS != lReturn)
  802. {
  803. TCHAR szErr[16];
  804. sprintf(szErr, "0x%X", lReturn);
  805. cout << TEXT("Error on SCardGetCardTypeProviderName for ")
  806. << szCardName
  807. << TEXT(": ")
  808. << szErr
  809. << TEXT("\n");
  810. }
  811. }
  812. // Prepare FullyQualifiedContainerName for CryptAcCntx call
  813. TCHAR szFQCN[256];
  814. sprintf(szFQCN, "\\\\.\\%s\\", g_pReaderStatusArray[dw].szReader);
  815. HCRYPTPROV hProv = NULL;
  816. if (SCARD_S_SUCCESS == lReturn)
  817. {
  818. BOOL fSts = CryptAcquireContext(
  819. &hProv,
  820. szFQCN, // default container via reader
  821. szCSPName,
  822. PROV_RSA_FULL,
  823. CRYPT_SILENT);
  824. // Enumerate the keys user specified and display the certs...
  825. if (fSts)
  826. {
  827. for (int n=0; n<g_nKeys; n++)
  828. {
  829. // Which keyset is this?
  830. LPCTSTR szKeyset = AT_KEYEXCHANGE==g_rgKeySet[n]?g_szEx:g_szSig;
  831. HCRYPTKEY hKey = NULL;
  832. // Get the key
  833. fSts = CryptGetUserKey(
  834. hProv,
  835. g_rgKeySet[n],
  836. &hKey);
  837. if (!fSts)
  838. {
  839. lReturn = GetLastError();
  840. if (NTE_NO_KEY == lReturn)
  841. {
  842. cout << TEXT("No ")
  843. << szKeyset
  844. << TEXT(" cert for reader: ")
  845. << g_pReaderStatusArray[dw].szReader
  846. << TEXT("\n");
  847. }
  848. else
  849. {
  850. TCHAR sz[256];
  851. sprintf(sz,"An error (0x%X) occurred opening the ", lReturn);
  852. cout << sz
  853. << szKeyset
  854. << TEXT(" key for reader: ")
  855. << g_pReaderStatusArray[dw].szReader
  856. << TEXT("\n");
  857. }
  858. // No point to work on this keyset anymore
  859. continue;
  860. }
  861. // Get the cert for this key
  862. PCCERT_CONTEXT pCertCtx = NULL;
  863. pCertCtx = GetCertContext(&hProv, &hKey, g_rgKeySet[n]);
  864. if (NULL != pCertCtx)
  865. {
  866. //
  867. // If desired, attempt to build a certificate chain
  868. //
  869. if (g_fChain)
  870. {
  871. cout << TEXT("\nPerforming cert chain verification...\n");
  872. if (S_OK != DisplayChainInfo(pCertCtx)) {
  873. cout << TEXT("Cert did not chain!\n") << endl;
  874. } else {
  875. cout << TEXT("--- chain: Chain verifies.\n") << endl;
  876. }
  877. }
  878. // call common UI to display m_pCertContext
  879. // ( from cryptui.h ( cryptui.dll ) )
  880. TCHAR szTitle[300];
  881. sprintf(szTitle,
  882. "%s : %s",
  883. g_pReaderStatusArray[dw].szReader,
  884. szKeyset);
  885. CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewInfo;
  886. memset( &CertViewInfo, 0, sizeof( CertViewInfo ) );
  887. CertViewInfo.dwSize = (sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
  888. CertViewInfo.hwndParent = NULL;
  889. CertViewInfo.szTitle = szTitle;
  890. CertViewInfo.dwFlags = CRYPTUI_DISABLE_EDITPROPERTIES |
  891. CRYPTUI_DISABLE_ADDTOSTORE;
  892. CertViewInfo.pCertContext = pCertCtx;
  893. BOOL fThrowAway = FALSE;
  894. fSts = CryptUIDlgViewCertificate(&CertViewInfo, &fThrowAway);
  895. // clean up certcontext
  896. CertFreeCertificateContext(pCertCtx);
  897. cout << TEXT("Displayed ")
  898. << szKeyset
  899. << TEXT(" cert for reader: ")
  900. << g_pReaderStatusArray[dw].szReader
  901. << TEXT("\n");
  902. }
  903. else
  904. {
  905. cout << TEXT("No cert retrieved for reader: ")
  906. << g_pReaderStatusArray[dw].szReader
  907. << TEXT("\n");
  908. }
  909. // clean up stuff
  910. if (NULL != hKey)
  911. {
  912. CryptDestroyKey(hKey);
  913. hKey = NULL;
  914. }
  915. }
  916. }
  917. else
  918. {
  919. TCHAR szErr[16];
  920. sprintf(szErr, "0x%X", GetLastError());
  921. cout << TEXT("Error on CryptAcquireContext for ")
  922. << szCSPName
  923. << TEXT(": ")
  924. << szErr
  925. << TEXT("\n");
  926. }
  927. }
  928. // Clean up
  929. if (NULL != szCSPName)
  930. {
  931. SCardFreeMemory(g_hSCardCtx, (PVOID)szCSPName);
  932. szCSPName = NULL;
  933. }
  934. if (NULL != szCardName)
  935. {
  936. SCardFreeMemory(g_hSCardCtx, (PVOID)szCardName);
  937. szCardName = NULL;
  938. }
  939. if (NULL != hProv)
  940. {
  941. CryptReleaseContext(hProv, 0);
  942. hProv = NULL;
  943. }
  944. } // end for
  945. }
  946. /*++
  947. main:
  948. This is the main entry point for the test program.
  949. It runs the test. Nice and simple, borrowed from DBarlow
  950. Author:
  951. Doug Barlow (dbarlow) 11/10/1997
  952. Revisions:
  953. AMatlosz 2/26/98
  954. --*/
  955. void __cdecl
  956. main(DWORD cArgs,LPCTSTR rgszArgs[])
  957. {
  958. //init globals & locals
  959. g_nKeys = 0;
  960. g_rgKeySet[0] = g_rgKeySet[1] = 0;
  961. g_hSCardCtx = NULL;
  962. g_szReaderName = NULL;
  963. g_fReaderNameAllocd = false;
  964. g_dwNumReaders = 0;
  965. g_pReaderStatusArray = NULL;
  966. if (!ProcessCommandLine(cArgs, rgszArgs))
  967. {
  968. return;
  969. }
  970. if (IsCalaisRunning())
  971. {
  972. DisplayReaderList();
  973. if (0 < g_nKeys)
  974. {
  975. DisplayCerts();
  976. }
  977. }
  978. cout << TEXT("\ndone.") << endl;
  979. // clean up globals
  980. if (g_fReaderNameAllocd && NULL != g_szReaderName)
  981. {
  982. SCardFreeMemory(g_hSCardCtx, (PVOID)g_szReaderName);
  983. }
  984. if (NULL != g_hSCardCtx)
  985. {
  986. SCardReleaseContext(g_hSCardCtx);
  987. }
  988. }