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

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: chPinDlg.cpp
//
//--------------------------------------------------------------------------
// chPinDlg.cpp : implementation file
//
#include "stdafx.h"
#include <winscard.h>
#include <wincrypt.h>
#include <scardlib.h>
#include "chPin.h"
#include "chPinDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static UINT AFX_CDECL WorkThread(LPVOID);
static DWORD CSPType(IN LPCTSTR szProvider);
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChangePinDlg dialog
CChangePinDlg::CChangePinDlg(CWnd* pParent /*=NULL*/)
: CDialog(CChangePinDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CChangePinDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CChangePinDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChangePinDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CChangePinDlg, CDialog)
//{{AFX_MSG_MAP(CChangePinDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_MESSAGE(APP_ALLDONE, OnAllDone)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChangePinDlg message handlers
BOOL CChangePinDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_pThread = AfxBeginThread(WorkThread, this);
return TRUE; // return TRUE unless you set the focus to a control
}
void CChangePinDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CChangePinDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CChangePinDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
static UINT AFX_CDECL
WorkThread(
LPVOID pv)
{
static TCHAR szReader[MAX_PATH];
static TCHAR szCard[MAX_PATH];
static TCHAR szProvider[MAX_PATH];
static BYTE pbSignature[(1024 / 8) + (4 * sizeof(DWORD))];
CChangePinDlg *pDlg = (CChangePinDlg *)pv;
OPENCARDNAME_EX ocn;
OPENCARD_SEARCH_CRITERIA ocsc;
SCARDCONTEXT hCtx = NULL;
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHash = NULL;
DWORD dwSts, dwLen, dwKeyType;
DWORD dwProvType;
BOOL fSts;
CString szFqcn;
dwSts = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hCtx);
if (SCARD_S_SUCCESS != dwSts)
goto ErrorExit;
ZeroMemory(&ocsc, sizeof(ocsc));
ocsc.dwStructSize = sizeof(ocsc);
// LPSTR lpstrGroupNames; // OPTIONAL reader groups to include in
// DWORD nMaxGroupNames; // search. NULL defaults to
// // SCard$DefaultReaders
// LPCGUID rgguidInterfaces; // OPTIONAL requested interfaces
// DWORD cguidInterfaces; // supported by card's SSP
// LPSTR lpstrCardNames; // OPTIONAL requested card names; all cards w/
// DWORD nMaxCardNames; // matching ATRs will be accepted
// LPOCNCHKPROC lpfnCheck; // OPTIONAL if NULL no user check will be performed.
// LPOCNCONNPROCA lpfnConnect; // OPTIONAL if lpfnConnect is provided,
// LPOCNDSCPROC lpfnDisconnect; // lpfnDisconnect must also be set.
// LPVOID pvUserData; // OPTIONAL parameter to callbacks
// DWORD dwShareMode; // OPTIONAL must be set if lpfnCheck is not null
// DWORD dwPreferredProtocols; // OPTIONAL
ZeroMemory(&ocn, sizeof(ocn));
ocn.dwStructSize = sizeof(ocn);
ocn.hSCardContext = hCtx;
ocn.hwndOwner = pDlg->m_hWnd;
ocn.dwFlags = SC_DLG_FORCE_UI;
ocn.lpstrTitle = TEXT("Change PIN Card Selection");
ocn.lpstrSearchDesc = TEXT("Select the Smart Card who's PIN is to be changed.");
// HICON hIcon; // OPTIONAL 32x32 icon for your brand insignia
ocn.pOpenCardSearchCriteria = &ocsc;
// LPOCNCONNPROCA lpfnConnect; // OPTIONAL - performed on successful selection
// LPVOID pvUserData; // OPTIONAL parameter to lpfnConnect
// DWORD dwShareMode; // OPTIONAL - if lpfnConnect is NULL, dwShareMode and
// DWORD dwPreferredProtocols; // OPTIONAL dwPreferredProtocols will be used to
// // connect to the selected card
ocn.lpstrRdr = szReader;
ocn.nMaxRdr = sizeof(szReader) / sizeof(TCHAR);
ocn.lpstrCard = szCard;
ocn.nMaxCard = sizeof(szCard) / sizeof(TCHAR);
// DWORD dwActiveProtocol; // [OUT] set only if dwShareMode not NULL
// SCARDHANDLE hCardHandle; // [OUT] set if a card connection was indicated
dwSts = SCardUIDlgSelectCard(&ocn);
if (NULL != ocn.hCardHandle)
dwSts = SCardDisconnect(ocn.hCardHandle, SCARD_LEAVE_CARD);
if (SCARD_S_SUCCESS != dwSts)
goto ErrorExit;
//
// The user has selected a card. Translate that into a CSP.
//
dwLen = sizeof(szProvider) / sizeof(TCHAR);
dwSts = SCardGetCardTypeProviderName(
hCtx,
szCard,
SCARD_PROVIDER_CSP,
szProvider,
&dwLen);
if (SCARD_S_SUCCESS != dwSts)
goto ErrorExit;
dwSts = SCardReleaseContext(hCtx);
hCtx = NULL;
if (SCARD_S_SUCCESS != dwSts)
goto ErrorExit;
dwProvType = CSPType(szProvider);
if (0 == dwProvType)
{
dwSts = NTE_PROV_TYPE_ENTRY_BAD;
goto ErrorExit;
}
szFqcn = TEXT("\\\\.\\");
szFqcn += szReader;
//
// Activate a Key on the card.
//
fSts = CryptAcquireContext(&hProv, szFqcn, szProvider, dwProvType, 0);
if (!fSts)
{
dwSts = GetLastError();
goto ErrorExit;
}
for (dwKeyType = AT_KEYEXCHANGE; dwKeyType <= AT_SIGNATURE; dwKeyType += 1)
{
fSts = CryptGetUserKey(hProv, dwKeyType, &hKey);
if (fSts)
break;
}
if (!fSts)
{
dwSts = GetLastError();
goto ErrorExit;
}
//
// Use the CSP to force a PIN prompt.
//
fSts = CryptCreateHash(hProv, CALG_SHA, NULL, 0, &hHash);
if (!fSts)
{
dwSts = GetLastError();
goto ErrorExit;
}
fSts = CryptHashData(hHash, (LPBYTE)szProvider, sizeof(szProvider), 0);
if (!fSts)
{
dwSts = GetLastError();
goto ErrorExit;
}
dwLen = sizeof(pbSignature);
fSts = CryptSignHash(hHash, dwKeyType, NULL, 0, pbSignature, &dwLen);
//
// All done. Clean up and notify the main thread that we're done.
//
ErrorExit:
if (NULL != hHash)
CryptDestroyHash(hHash);
if (NULL != hKey)
CryptDestroyKey(hKey);
if (NULL != hProv)
CryptReleaseContext(hProv, 0);
if (NULL != hCtx)
SCardReleaseContext(hCtx);
if (SCARD_S_SUCCESS != dwSts)
AfxMessageBox(ErrorString(dwSts), MB_ICONEXCLAMATION | MB_OK);
pDlg->PostMessage(APP_ALLDONE);
return 0;
}
/*++
CSPType:
This function converts a CSP Name to a CSP Type.
Arguments:
szProvider supplies the name of the CSP.
Return Value:
The CSP type of the given CSP, or zero if no such CSP can be found.
Author:
Doug Barlow (dbarlow) 1/14/1999
--*/
static DWORD
CSPType(
IN LPCTSTR szProvider)
{
LONG nSts;
HKEY hList = NULL;
HKEY hProv = NULL;
DWORD dwProvType, dwValType, dwValLen;
nSts = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider"),
0,
KEY_READ,
&hList);
if (ERROR_SUCCESS != nSts)
goto ErrorExit;
nSts = RegOpenKeyEx(
hList,
szProvider,
0,
KEY_READ,
&hProv);
if (ERROR_SUCCESS != nSts)
goto ErrorExit;
dwValLen = sizeof(DWORD);
dwProvType = 0; // Assumes little endian.
nSts = RegQueryValueEx(
hProv,
TEXT("Type"),
0,
&dwValType,
(LPBYTE)&dwProvType,
&dwValLen);
if (ERROR_SUCCESS != nSts)
goto ErrorExit;
RegCloseKey(hProv);
RegCloseKey(hList);
return dwProvType;
ErrorExit:
if (NULL != hProv)
RegCloseKey(hProv);
if (NULL != hList)
RegCloseKey(hList);
return 0;
}
LRESULT
CChangePinDlg::OnAllDone(
WPARAM wParam,
LPARAM lParam)
{
WaitForSingleObject(m_pThread->m_hThread, INFINITE);
CDialog::OnOK();
return 0;
}