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.

426 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: chPinDlg.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // chPinDlg.cpp : implementation file
  11. //
  12. #include "stdafx.h"
  13. #include <winscard.h>
  14. #include <wincrypt.h>
  15. #include <scardlib.h>
  16. #include "chPin.h"
  17. #include "chPinDlg.h"
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. static UINT AFX_CDECL WorkThread(LPVOID);
  24. static DWORD CSPType(IN LPCTSTR szProvider);
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CAboutDlg dialog used for App About
  27. class CAboutDlg : public CDialog
  28. {
  29. public:
  30. CAboutDlg();
  31. // Dialog Data
  32. //{{AFX_DATA(CAboutDlg)
  33. enum { IDD = IDD_ABOUTBOX };
  34. //}}AFX_DATA
  35. // ClassWizard generated virtual function overrides
  36. //{{AFX_VIRTUAL(CAboutDlg)
  37. protected:
  38. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  39. //}}AFX_VIRTUAL
  40. // Implementation
  41. protected:
  42. //{{AFX_MSG(CAboutDlg)
  43. //}}AFX_MSG
  44. DECLARE_MESSAGE_MAP()
  45. };
  46. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  47. {
  48. //{{AFX_DATA_INIT(CAboutDlg)
  49. //}}AFX_DATA_INIT
  50. }
  51. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  52. {
  53. CDialog::DoDataExchange(pDX);
  54. //{{AFX_DATA_MAP(CAboutDlg)
  55. //}}AFX_DATA_MAP
  56. }
  57. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  58. //{{AFX_MSG_MAP(CAboutDlg)
  59. // No message handlers
  60. //}}AFX_MSG_MAP
  61. END_MESSAGE_MAP()
  62. /////////////////////////////////////////////////////////////////////////////
  63. // CChangePinDlg dialog
  64. CChangePinDlg::CChangePinDlg(CWnd* pParent /*=NULL*/)
  65. : CDialog(CChangePinDlg::IDD, pParent)
  66. {
  67. //{{AFX_DATA_INIT(CChangePinDlg)
  68. // NOTE: the ClassWizard will add member initialization here
  69. //}}AFX_DATA_INIT
  70. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  71. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  72. }
  73. void CChangePinDlg::DoDataExchange(CDataExchange* pDX)
  74. {
  75. CDialog::DoDataExchange(pDX);
  76. //{{AFX_DATA_MAP(CChangePinDlg)
  77. // NOTE: the ClassWizard will add DDX and DDV calls here
  78. //}}AFX_DATA_MAP
  79. }
  80. BEGIN_MESSAGE_MAP(CChangePinDlg, CDialog)
  81. //{{AFX_MSG_MAP(CChangePinDlg)
  82. ON_WM_SYSCOMMAND()
  83. ON_WM_PAINT()
  84. ON_WM_QUERYDRAGICON()
  85. ON_MESSAGE(APP_ALLDONE, OnAllDone)
  86. //}}AFX_MSG_MAP
  87. END_MESSAGE_MAP()
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CChangePinDlg message handlers
  90. BOOL CChangePinDlg::OnInitDialog()
  91. {
  92. CDialog::OnInitDialog();
  93. // Add "About..." menu item to system menu.
  94. // IDM_ABOUTBOX must be in the system command range.
  95. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  96. ASSERT(IDM_ABOUTBOX < 0xF000);
  97. CMenu* pSysMenu = GetSystemMenu(FALSE);
  98. if (pSysMenu != NULL)
  99. {
  100. CString strAboutMenu;
  101. strAboutMenu.LoadString(IDS_ABOUTBOX);
  102. if (!strAboutMenu.IsEmpty())
  103. {
  104. pSysMenu->AppendMenu(MF_SEPARATOR);
  105. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  106. }
  107. }
  108. // Set the icon for this dialog. The framework does this automatically
  109. // when the application's main window is not a dialog
  110. SetIcon(m_hIcon, TRUE); // Set big icon
  111. SetIcon(m_hIcon, FALSE); // Set small icon
  112. // TODO: Add extra initialization here
  113. m_pThread = AfxBeginThread(WorkThread, this);
  114. return TRUE; // return TRUE unless you set the focus to a control
  115. }
  116. void CChangePinDlg::OnSysCommand(UINT nID, LPARAM lParam)
  117. {
  118. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  119. {
  120. CAboutDlg dlgAbout;
  121. dlgAbout.DoModal();
  122. }
  123. else
  124. {
  125. CDialog::OnSysCommand(nID, lParam);
  126. }
  127. }
  128. // If you add a minimize button to your dialog, you will need the code below
  129. // to draw the icon. For MFC applications using the document/view model,
  130. // this is automatically done for you by the framework.
  131. void CChangePinDlg::OnPaint()
  132. {
  133. if (IsIconic())
  134. {
  135. CPaintDC dc(this); // device context for painting
  136. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  137. // Center icon in client rectangle
  138. int cxIcon = GetSystemMetrics(SM_CXICON);
  139. int cyIcon = GetSystemMetrics(SM_CYICON);
  140. CRect rect;
  141. GetClientRect(&rect);
  142. int x = (rect.Width() - cxIcon + 1) / 2;
  143. int y = (rect.Height() - cyIcon + 1) / 2;
  144. // Draw the icon
  145. dc.DrawIcon(x, y, m_hIcon);
  146. }
  147. else
  148. {
  149. CDialog::OnPaint();
  150. }
  151. }
  152. // The system calls this to obtain the cursor to display while the user drags
  153. // the minimized window.
  154. HCURSOR CChangePinDlg::OnQueryDragIcon()
  155. {
  156. return (HCURSOR) m_hIcon;
  157. }
  158. static UINT AFX_CDECL
  159. WorkThread(
  160. LPVOID pv)
  161. {
  162. static TCHAR szReader[MAX_PATH];
  163. static TCHAR szCard[MAX_PATH];
  164. static TCHAR szProvider[MAX_PATH];
  165. static BYTE pbSignature[(1024 / 8) + (4 * sizeof(DWORD))];
  166. CChangePinDlg *pDlg = (CChangePinDlg *)pv;
  167. OPENCARDNAME_EX ocn;
  168. OPENCARD_SEARCH_CRITERIA ocsc;
  169. SCARDCONTEXT hCtx = NULL;
  170. HCRYPTPROV hProv = NULL;
  171. HCRYPTKEY hKey = NULL;
  172. HCRYPTHASH hHash = NULL;
  173. DWORD dwSts, dwLen, dwKeyType;
  174. DWORD dwProvType;
  175. BOOL fSts;
  176. CString szFqcn;
  177. dwSts = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hCtx);
  178. if (SCARD_S_SUCCESS != dwSts)
  179. goto ErrorExit;
  180. ZeroMemory(&ocsc, sizeof(ocsc));
  181. ocsc.dwStructSize = sizeof(ocsc);
  182. // LPSTR lpstrGroupNames; // OPTIONAL reader groups to include in
  183. // DWORD nMaxGroupNames; // search. NULL defaults to
  184. // // SCard$DefaultReaders
  185. // LPCGUID rgguidInterfaces; // OPTIONAL requested interfaces
  186. // DWORD cguidInterfaces; // supported by card's SSP
  187. // LPSTR lpstrCardNames; // OPTIONAL requested card names; all cards w/
  188. // DWORD nMaxCardNames; // matching ATRs will be accepted
  189. // LPOCNCHKPROC lpfnCheck; // OPTIONAL if NULL no user check will be performed.
  190. // LPOCNCONNPROCA lpfnConnect; // OPTIONAL if lpfnConnect is provided,
  191. // LPOCNDSCPROC lpfnDisconnect; // lpfnDisconnect must also be set.
  192. // LPVOID pvUserData; // OPTIONAL parameter to callbacks
  193. // DWORD dwShareMode; // OPTIONAL must be set if lpfnCheck is not null
  194. // DWORD dwPreferredProtocols; // OPTIONAL
  195. ZeroMemory(&ocn, sizeof(ocn));
  196. ocn.dwStructSize = sizeof(ocn);
  197. ocn.hSCardContext = hCtx;
  198. ocn.hwndOwner = pDlg->m_hWnd;
  199. ocn.dwFlags = SC_DLG_FORCE_UI;
  200. ocn.lpstrTitle = TEXT("Change PIN Card Selection");
  201. ocn.lpstrSearchDesc = TEXT("Select the Smart Card who's PIN is to be changed.");
  202. // HICON hIcon; // OPTIONAL 32x32 icon for your brand insignia
  203. ocn.pOpenCardSearchCriteria = &ocsc;
  204. // LPOCNCONNPROCA lpfnConnect; // OPTIONAL - performed on successful selection
  205. // LPVOID pvUserData; // OPTIONAL parameter to lpfnConnect
  206. // DWORD dwShareMode; // OPTIONAL - if lpfnConnect is NULL, dwShareMode and
  207. // DWORD dwPreferredProtocols; // OPTIONAL dwPreferredProtocols will be used to
  208. // // connect to the selected card
  209. ocn.lpstrRdr = szReader;
  210. ocn.nMaxRdr = sizeof(szReader) / sizeof(TCHAR);
  211. ocn.lpstrCard = szCard;
  212. ocn.nMaxCard = sizeof(szCard) / sizeof(TCHAR);
  213. // DWORD dwActiveProtocol; // [OUT] set only if dwShareMode not NULL
  214. // SCARDHANDLE hCardHandle; // [OUT] set if a card connection was indicated
  215. dwSts = SCardUIDlgSelectCard(&ocn);
  216. if (NULL != ocn.hCardHandle)
  217. dwSts = SCardDisconnect(ocn.hCardHandle, SCARD_LEAVE_CARD);
  218. if (SCARD_S_SUCCESS != dwSts)
  219. goto ErrorExit;
  220. //
  221. // The user has selected a card. Translate that into a CSP.
  222. //
  223. dwLen = sizeof(szProvider) / sizeof(TCHAR);
  224. dwSts = SCardGetCardTypeProviderName(
  225. hCtx,
  226. szCard,
  227. SCARD_PROVIDER_CSP,
  228. szProvider,
  229. &dwLen);
  230. if (SCARD_S_SUCCESS != dwSts)
  231. goto ErrorExit;
  232. dwSts = SCardReleaseContext(hCtx);
  233. hCtx = NULL;
  234. if (SCARD_S_SUCCESS != dwSts)
  235. goto ErrorExit;
  236. dwProvType = CSPType(szProvider);
  237. if (0 == dwProvType)
  238. {
  239. dwSts = NTE_PROV_TYPE_ENTRY_BAD;
  240. goto ErrorExit;
  241. }
  242. szFqcn = TEXT("\\\\.\\");
  243. szFqcn += szReader;
  244. //
  245. // Activate a Key on the card.
  246. //
  247. fSts = CryptAcquireContext(&hProv, szFqcn, szProvider, dwProvType, 0);
  248. if (!fSts)
  249. {
  250. dwSts = GetLastError();
  251. goto ErrorExit;
  252. }
  253. for (dwKeyType = AT_KEYEXCHANGE; dwKeyType <= AT_SIGNATURE; dwKeyType += 1)
  254. {
  255. fSts = CryptGetUserKey(hProv, dwKeyType, &hKey);
  256. if (fSts)
  257. break;
  258. }
  259. if (!fSts)
  260. {
  261. dwSts = GetLastError();
  262. goto ErrorExit;
  263. }
  264. //
  265. // Use the CSP to force a PIN prompt.
  266. //
  267. fSts = CryptCreateHash(hProv, CALG_SHA, NULL, 0, &hHash);
  268. if (!fSts)
  269. {
  270. dwSts = GetLastError();
  271. goto ErrorExit;
  272. }
  273. fSts = CryptHashData(hHash, (LPBYTE)szProvider, sizeof(szProvider), 0);
  274. if (!fSts)
  275. {
  276. dwSts = GetLastError();
  277. goto ErrorExit;
  278. }
  279. dwLen = sizeof(pbSignature);
  280. fSts = CryptSignHash(hHash, dwKeyType, NULL, 0, pbSignature, &dwLen);
  281. //
  282. // All done. Clean up and notify the main thread that we're done.
  283. //
  284. ErrorExit:
  285. if (NULL != hHash)
  286. CryptDestroyHash(hHash);
  287. if (NULL != hKey)
  288. CryptDestroyKey(hKey);
  289. if (NULL != hProv)
  290. CryptReleaseContext(hProv, 0);
  291. if (NULL != hCtx)
  292. SCardReleaseContext(hCtx);
  293. if (SCARD_S_SUCCESS != dwSts)
  294. AfxMessageBox(ErrorString(dwSts), MB_ICONEXCLAMATION | MB_OK);
  295. pDlg->PostMessage(APP_ALLDONE);
  296. return 0;
  297. }
  298. /*++
  299. CSPType:
  300. This function converts a CSP Name to a CSP Type.
  301. Arguments:
  302. szProvider supplies the name of the CSP.
  303. Return Value:
  304. The CSP type of the given CSP, or zero if no such CSP can be found.
  305. Author:
  306. Doug Barlow (dbarlow) 1/14/1999
  307. --*/
  308. static DWORD
  309. CSPType(
  310. IN LPCTSTR szProvider)
  311. {
  312. LONG nSts;
  313. HKEY hList = NULL;
  314. HKEY hProv = NULL;
  315. DWORD dwProvType, dwValType, dwValLen;
  316. nSts = RegOpenKeyEx(
  317. HKEY_LOCAL_MACHINE,
  318. TEXT("SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider"),
  319. 0,
  320. KEY_READ,
  321. &hList);
  322. if (ERROR_SUCCESS != nSts)
  323. goto ErrorExit;
  324. nSts = RegOpenKeyEx(
  325. hList,
  326. szProvider,
  327. 0,
  328. KEY_READ,
  329. &hProv);
  330. if (ERROR_SUCCESS != nSts)
  331. goto ErrorExit;
  332. dwValLen = sizeof(DWORD);
  333. dwProvType = 0; // Assumes little endian.
  334. nSts = RegQueryValueEx(
  335. hProv,
  336. TEXT("Type"),
  337. 0,
  338. &dwValType,
  339. (LPBYTE)&dwProvType,
  340. &dwValLen);
  341. if (ERROR_SUCCESS != nSts)
  342. goto ErrorExit;
  343. RegCloseKey(hProv);
  344. RegCloseKey(hList);
  345. return dwProvType;
  346. ErrorExit:
  347. if (NULL != hProv)
  348. RegCloseKey(hProv);
  349. if (NULL != hList)
  350. RegCloseKey(hList);
  351. return 0;
  352. }
  353. LRESULT
  354. CChangePinDlg::OnAllDone(
  355. WPARAM wParam,
  356. LPARAM lParam)
  357. {
  358. WaitForSingleObject(m_pThread->m_hThread, INFINITE);
  359. CDialog::OnOK();
  360. return 0;
  361. }