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.
 
 
 
 
 
 

1112 lines
28 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 2001
//
// File: scinfo.cpp
//
// Abstract:
//
// This application is used to provide a snapshot of the Calais (Smart Card
// Resource Manager) service's status, and to display certificates on smart
// cards via the common WinNT UI.
//
// SCInfo -- describes the RM status and displays each available sc cert(s)
//
// The following options are always enabled:
// Readername -- for just one reader
// -sig -- display signature key certs only
// -ex -- display exchange key certs only
// -nocert -- don't look for certs to display
// -key -- verify keyset public key matches cert public key
//
// Author: Amanda Matlosz (AMatlosz) 07/14/1998
//
// Environment: Win32 Console App
//
// Notes: For use in NT5 public key rollout testing
//
// Need to include the following libs:
// winscard.lib
//
//--------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <winscard.h>
#include <winsvc.h>
#include <cryptui.h>
#include "cscsp.h"
#define __dwFILE__ __dwFILE_CERTUTIL_SCINFO_CPP__
#define wszSCARDSERVICE L"SCardSvr"
//+-------------------------------------------------------------------------
// IsSCardSvrRunning checks the registry and queries the service for status
//--------------------------------------------------------------------------
HRESULT
IsSCardSvrRunning()
{
HRESULT hr;
WCHAR const *pwszError = NULL;
UINT idmsg = IDS_SMARTCARD_NOTRUNNING; // "The Microsoft Smart Card Resource Manager is not running."
HANDLE hSCardSvrStarted = NULL;
HMODULE hDll = GetModuleHandle(L"winscard.dll");
typedef HANDLE (WINAPI FNSCARDACCESSSTARTEDEVENT)(VOID);
FNSCARDACCESSSTARTEDEVENT *pfnSCardAccessStartedEvent;
pfnSCardAccessStartedEvent = (FNSCARDACCESSSTARTEDEVENT *)
GetProcAddress(hDll, "SCardAccessStartedEvent");
if (NULL == pfnSCardAccessStartedEvent)
{
hr = myHLastError();
pwszError = L"GetProcAddress";
_JumpErrorStr(hr, error, "GetProcAddress", L"SCardAccessStartedEvent");
}
hSCardSvrStarted = (*pfnSCardAccessStartedEvent)();
if (NULL == hSCardSvrStarted)
{
hr = myHLastError();
if (S_OK == hr)
{
hr = E_HANDLE;
}
pwszError = L"SCardAccessStartedEvent";
_JumpError(hr, error, "SCardAccessStartedEvent");
}
hr = WaitForSingleObject(hSCardSvrStarted, 1000);
if (WAIT_OBJECT_0 != hr)
{
hr = myHError(hr);
pwszError = L"WaitForSingleObject";
_JumpError(hr, error, "WaitForSingleObject");
}
idmsg = IDS_SMARTCARD_RUNNING; // "The Microsoft Smart Card Resource Manager is running."
hr = S_OK;
error:
// Display status
wprintf(myLoadResourceString(idmsg));
wprintf(wszNewLine);
if (S_OK != hr)
{
// IDS_SERVICEPAUSED; // "Service is paused."
// IDS_SERVICESTOPPED; // "Service is stopped."
cuPrintErrorAndString(
pwszError,
IDS_SERVICEUNKNOWNSTATE, // "Service is in an unknown state."
hr,
NULL);
}
return(hr);
}
VOID
FreeReaderList(
IN SCARDCONTEXT hSCard,
IN WCHAR *pwszzReaderNameAlloc,
IN SCARD_READERSTATE *prgReaderState)
{
if (NULL != hSCard)
{
if (NULL != pwszzReaderNameAlloc)
{
SCardFreeMemory(hSCard, pwszzReaderNameAlloc);
}
SCardReleaseContext(hSCard);
}
if (NULL != prgReaderState)
{
LocalFree(prgReaderState);
}
}
//+-------------------------------------------------------------------------
// BuildReaderList tries to set *phSCard and get a list of currently available
// smart card readers.
//--------------------------------------------------------------------------
HRESULT
BuildReaderList(
OPTIONAL IN WCHAR const *pwszReaderName,
OUT SCARDCONTEXT *phSCard,
OUT WCHAR **ppwszzReaderNameAlloc,
OUT SCARD_READERSTATE **pprgReaderState,
OUT DWORD *pcReaders)
{
HRESULT hr;
DWORD i;
DWORD dwAutoAllocate;
SCARDCONTEXT hSCard = NULL;
WCHAR *pwszzReaderNameAlloc = NULL;
SCARD_READERSTATE *prgReaderState = NULL;
DWORD cReaders;
*phSCard = NULL;
*ppwszzReaderNameAlloc = NULL;
*pcReaders = 0;
*pprgReaderState = NULL;
wprintf(myLoadResourceString(IDS_SCREADER_STATUS_COLON));
wprintf(wszNewLine);
// Acquire global SCARDCONTEXT from resource manager if possible
hr = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hSCard);
if (S_OK != hr)
{
cuPrintAPIError(L"SCardEstablishContext", hr);
wprintf(myLoadResourceString(IDS_SC_USER_SCOPE));
wprintf(wszNewLine);
wprintf(myLoadResourceString(IDS_SC_NO_LIST));
wprintf(wszNewLine);
_JumpError(hr, error, "SCardEstablishContext");
}
// Build a readerstatus array from either a list of readers; or use the one
// the user specified
cReaders = 1;
if (NULL == pwszReaderName)
{
dwAutoAllocate = SCARD_AUTOALLOCATE;
hr = SCardListReaders(
hSCard,
SCARD_DEFAULT_READERS,
(WCHAR *) &pwszzReaderNameAlloc,
&dwAutoAllocate);
if (S_OK != hr)
{
cuPrintAPIError(L"SCardListReaders", hr);
wprintf(myLoadResourceString(IDS_SC_LIST_FAILED));
wprintf(wszNewLine);
if (SCARD_E_NO_READERS_AVAILABLE == hr)
{
wprintf(myLoadResourceString(IDS_SC_LIST_FAILED_NO_READERS));
}
else
{
wprintf(myLoadResourceString(IDS_SC_LIST_FAILED_GENERIC));
}
wprintf(wszNewLine);
_JumpError(hr, error, "SCardListReaders");
}
// Build a readerstatus array...
cReaders = 0;
if (NULL != pwszzReaderNameAlloc)
{
for (
pwszReaderName = pwszzReaderNameAlloc;
L'\0' != *pwszReaderName;
pwszReaderName += wcslen(pwszReaderName) + 1)
{
cReaders++;
}
}
pwszReaderName = pwszzReaderNameAlloc;
}
prgReaderState = (SCARD_READERSTATE *) LocalAlloc(
LMEM_FIXED | LMEM_ZEROINIT,
cReaders * sizeof(**pprgReaderState));
if (NULL == prgReaderState)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
wprintf(myLoadResourceString(IDS_SC_READERS_COLON));
wprintf(L" %u\n", cReaders);
for (i = 0; i < cReaders; i++)
{
wprintf(L" %u: %ws\n", i, pwszReaderName);
prgReaderState[i].szReader = const_cast<WCHAR *>(pwszReaderName);
prgReaderState[i].dwCurrentState = SCARD_STATE_UNAWARE;
pwszReaderName += wcslen(pwszReaderName) + 1;
}
// ...And get the reader status from the resource manager
hr = SCardGetStatusChange(
hSCard,
INFINITE, // hardly
prgReaderState,
cReaders);
if (S_OK != hr)
{
cuPrintAPIError(L"SCardGetStatusChange", hr);
_JumpError(hr, error, "SCardGetStatusChange");
}
*phSCard = hSCard;
hSCard = NULL;
*ppwszzReaderNameAlloc = pwszzReaderNameAlloc;
pwszzReaderNameAlloc = NULL;
*pprgReaderState = prgReaderState;
prgReaderState = NULL;
*pcReaders = cReaders;
hr = S_OK;
error:
FreeReaderList(hSCard, pwszzReaderNameAlloc, prgReaderState);
return(hr);
}
//+-------------------------------------------------------------------------
// DisplayReaderList displays the status for a list of readers.
//--------------------------------------------------------------------------
HRESULT
DisplayReaderList(
IN SCARDCONTEXT hSCard,
IN SCARD_READERSTATE const *prgReaderState,
IN DWORD cReaders)
{
HRESULT hr;
DWORD i;
DWORD dwAutoAllocate;
UINT idsMsg;
// Display all reader information
for (i = 0; i < cReaders; i++)
{
DWORD dwState;
WCHAR const *pwszSep;
static WCHAR const s_wszSep[] = L" | ";
//--- reader: readerName
wprintf(myLoadResourceString(IDS_SC_MINUS_READER_COLON));
wprintf(L" %ws\n", prgReaderState[i].szReader);
//--- status: /bits/
wprintf(myLoadResourceString(IDS_SC_MINUS_STATUS_COLON));
dwState = prgReaderState[i].dwEventState;
pwszSep = L" ";
if (SCARD_STATE_UNKNOWN & dwState)
{
wprintf(L"%wsSCARD_STATE_UNKNOWN", pwszSep);
pwszSep = s_wszSep;
}
if (SCARD_STATE_UNAVAILABLE & dwState)
{
wprintf(L"%wsSCARD_STATE_UNAVAILABLE", pwszSep);
pwszSep = s_wszSep;
}
if (SCARD_STATE_EMPTY & dwState)
{
wprintf(L"%wsSCARD_STATE_EMPTY", pwszSep);
pwszSep = s_wszSep;
}
if (SCARD_STATE_PRESENT & dwState)
{
wprintf(L"%wsSCARD_STATE_PRESENT", pwszSep);
pwszSep = s_wszSep;
}
if (SCARD_STATE_EXCLUSIVE & dwState)
{
wprintf(L"%wsSCARD_STATE_EXCLUSIVE", pwszSep);
pwszSep = s_wszSep;
}
if (SCARD_STATE_INUSE & dwState)
{
wprintf(L"%wsSCARD_STATE_INUSE", pwszSep);
pwszSep = s_wszSep;
}
if (SCARD_STATE_MUTE & dwState)
{
wprintf(L"%wsSCARD_STATE_MUTE", pwszSep);
pwszSep = s_wszSep;
}
if (SCARD_STATE_UNPOWERED & dwState)
{
wprintf(L"%wsSCARD_STATE_UNPOWERED", pwszSep);
}
wprintf(wszNewLine);
//--- status: what scstatus would say
// NO CARD
if (SCARD_STATE_EMPTY & dwState) // SC_STATUS_NO_CARD
{
idsMsg = IDS_SC_STATUS_NO_CARD;
}
// CARD in reader: SHARED, EXCLUSIVE, FREE, UNKNOWN ?
else
if (SCARD_STATE_PRESENT & dwState)
{
if (SCARD_STATE_MUTE & dwState) // SC_STATUS_UNKNOWN
{
idsMsg = IDS_SC_STATUS_UNKNOWN;
}
else
if (SCARD_STATE_INUSE & dwState)
{
if (dwState & SCARD_STATE_EXCLUSIVE & dwState)
{
// SC_STATUS_EXCLUSIVE
idsMsg = IDS_SC_STATUS_BUSY;
}
else // SC_STATUS_SHARED
{
idsMsg = IDS_SC_STATUS_SHARED;
}
}
else // SC_SATATUS_AVAILABLE
{
idsMsg = IDS_SC_STATUS_AVAILABLE;
}
}
// READER ERROR: at this point, something's gone wrong
else // SCARD_STATE_UNAVAILABLE & dwState -- SC_STATUS_ERROR
{
idsMsg = IDS_SC_STATUS_NO_RESPONSE;
}
wprintf(myLoadResourceString(IDS_SC_MINUS_STATUS_COLON));
wprintf(L" ");
wprintf(myLoadResourceString(idsMsg));
wprintf(wszNewLine);
// card name(s):
wprintf(myLoadResourceString(IDS_SC_MINUS_CARD_COLON));
if (0 < prgReaderState[i].cbAtr)
{
WCHAR *pwszCardName = NULL;
// Get the name of the card
dwAutoAllocate = SCARD_AUTOALLOCATE;
hr = SCardListCards(
hSCard,
prgReaderState[i].rgbAtr,
NULL,
0,
(WCHAR *) &pwszCardName,
&dwAutoAllocate);
if (S_OK != hr || NULL == pwszCardName)
{
wprintf(L" ");
wprintf(myLoadResourceString(IDS_SC_UNKNOWN_CARD));
}
else
{
WCHAR const *pwszName;
pwszSep = L"";
for (
pwszName = pwszCardName;
L'\0' != *pwszName;
pwszName += wcslen(pwszName) + 1)
{
wprintf(L"%ws %ws", pwszSep, pwszName);
pwszSep = L",";
}
}
if (NULL != pwszCardName)
{
SCardFreeMemory(hSCard, pwszCardName);
}
}
wprintf(wszNewLine);
}
hr = S_OK;
//error:
return(hr);
}
HRESULT
myCryptGetProvParamToUnicode(
IN HCRYPTPROV hProv,
IN DWORD dwParam,
OUT WCHAR **ppwszOut,
IN DWORD dwFlags)
{
HRESULT hr;
char *psz = NULL;
DWORD cb;
*ppwszOut = NULL;
if (!CryptGetProvParam(hProv, dwParam, NULL, &cb, 0))
{
hr = myHLastError();
_JumpError(hr, error, "CryptGetProvParam");
}
psz = (char *) LocalAlloc(LMEM_FIXED, cb);
if (NULL == psz)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
if (!CryptGetProvParam(hProv, dwParam, (BYTE *) psz, &cb, 0))
{
hr = myHLastError();
_JumpError(hr, error, "CryptGetProvParam");
}
if (!myConvertSzToWsz(ppwszOut, psz, -1))
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "myConvertSzToWsz");
}
hr = S_OK;
error:
if (NULL != psz)
{
LocalFree(psz);
}
return(hr);
}
//+-------------------------------------------------------------------------
// GetCertContext -- called by DisplayCerts
//--------------------------------------------------------------------------
HRESULT
GetCertContext(
IN HCRYPTPROV hProv,
IN HCRYPTKEY hKey,
IN DWORD dwKeySpec,
IN WCHAR const *pwszKeyType,
OUT CERT_CONTEXT const **ppCert)
{
HRESULT hr;
CERT_CONTEXT const *pCert = NULL;
CERT_PUBLIC_KEY_INFO *pKey = NULL;
CRYPT_KEY_PROV_INFO KeyProvInfo;
WCHAR *pwszContainerName = NULL;
WCHAR *pwszProvName = NULL;
BYTE *pbCert = NULL;
DWORD cbCert;
DWORD cbKey;
*ppCert = NULL;
// Get the cert from this key
if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &cbCert, 0))
{
hr = myHLastError();
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr)
{
_JumpError(hr, error, "CryptGetKeyParam");
}
}
pbCert = (BYTE *) LocalAlloc(LMEM_FIXED, cbCert);
if (NULL == pbCert)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, pbCert, &cbCert, 0))
{
hr = myHLastError();
_JumpError(hr, error, "CryptGetKeyParam");
}
// Convert the certificate into a Cert Context.
pCert = CertCreateCertificateContext(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
pbCert,
cbCert);
if (NULL == pCert)
{
hr = myHLastError();
_JumpError(hr, error, "CertCreateCertificateContext");
}
// Perform public key check
wprintf(wszNewLine);
wprintf(myLoadResourceString(IDS_FORMAT_SC_TESTING_MATCH), pwszKeyType);
wprintf(wszNewLine);
if (!CryptExportPublicKeyInfo(
hProv,
dwKeySpec,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
&cbKey)) // in, out
{
hr = myHLastError();
cuPrintAPIError(L"CryptExportPublicKeyInfo", hr);
_JumpError(hr, error, "CryptExportPublicKeyInfo");
}
if (0 == cbKey)
{
hr = SCARD_E_UNEXPECTED; // huh?
wprintf(
myLoadResourceString(IDS_SC_SIZE_ZERO),
L"CryptExportPublicKeyInfo");
wprintf(wszNewLine);
_JumpError(hr, error, "zero info size");
}
pKey = (CERT_PUBLIC_KEY_INFO *) LocalAlloc(LMEM_FIXED, cbKey);
if (NULL == pKey)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
if (!CryptExportPublicKeyInfo(
hProv,
dwKeySpec,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
pKey,
&cbKey))
{
hr = myHLastError();
cuPrintAPIError(L"CryptExportPublicKeyInfo", hr);
_JumpError(hr, error, "CryptExportPublicKeyInfo");
}
if (!CertComparePublicKeyInfo(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
pKey, // from the private keyset
&pCert->pCertInfo->SubjectPublicKeyInfo)) // cert public key
{
wprintf(wszNewLine);
wprintf(myLoadResourceString(IDS_SC_KEYPROVINFO_KEY));
wprintf(wszNewLine);
cuDumpPublicKey(pKey);
wprintf(wszNewLine);
wprintf(myLoadResourceString(IDS_SC_CERT_KEY));
wprintf(wszNewLine);
cuDumpPublicKey(&pCert->pCertInfo->SubjectPublicKeyInfo);
// by design, CertComparePublicKeyInfo doesn't set last error!
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
_JumpError(hr, error, "CertComparePublicKeyInfo");
}
wprintf(myLoadResourceString(IDS_SC_KEY_MATCHES));
wprintf(wszNewLine);
// Associate cryptprovider w/ the private key property of this cert
// ... need the container name
hr = myCryptGetProvParamToUnicode(
hProv,
PP_CONTAINER,
&pwszContainerName,
0);
_JumpIfError(hr, error, "myCryptGetProvParamToUnicode");
// ... need the provider name
hr = myCryptGetProvParamToUnicode(hProv, PP_NAME, &pwszProvName, 0);
_JumpIfError(hr, error, "myCryptGetProvParamToUnicode");
// Set the cert context properties to reflect the prov info
KeyProvInfo.pwszContainerName = pwszContainerName;
KeyProvInfo.pwszProvName = pwszProvName;
KeyProvInfo.dwProvType = PROV_RSA_FULL;
KeyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = dwKeySpec;
if (!CertSetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
0,
(VOID *) &KeyProvInfo))
{
hr = myHLastError();
// the cert's been incorrectly created -- scrap it.
_JumpError(hr, error, "CertSetCertificateContextProperty");
}
hr = cuDumpCertKeyProviderInfo(g_wszPad2, pCert, NULL, NULL);
_PrintIfError(hr, "cuDumpCertKeyProviderInfo");
if (!g_fCryptSilent)
{
if (AT_SIGNATURE == dwKeySpec)
{
hr = myValidateKeyForSigning(
hProv,
&pCert->pCertInfo->SubjectPublicKeyInfo,
CALG_SHA1);
}
else
{
hr = myValidateKeyForEncrypting(
hProv,
&pCert->pCertInfo->SubjectPublicKeyInfo,
CALG_RC4);
}
if (S_OK != hr)
{
if (SCARD_W_CANCELLED_BY_USER != hr)
{
wprintf(myLoadResourceString(IDS_ERR_PRIVATEKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match private key"
wprintf(wszNewLine);
//_JumpError(hr, error, "myValidateKeyForEncrypting");
_PrintError(hr, "myValidateKeyForEncrypting");
}
}
else
{
wprintf(myLoadResourceString(IDS_PRIVATEKEY_VERIFIES));
wprintf(wszNewLine);
}
}
*ppCert = pCert;
pCert = NULL;
hr = S_OK;
error:
if (NULL != pbCert)
{
LocalFree(pbCert);
}
if (NULL != pKey)
{
LocalFree(pKey);
}
if (NULL != pwszContainerName)
{
LocalFree(pwszContainerName);
}
if (NULL != pwszProvName)
{
LocalFree(pwszProvName);
}
if (NULL != pCert)
{
CertFreeCertificateContext(pCert);
}
return(hr);
}
//+-------------------------------------------------------------------------
// DisplayChainInfo -- This code verifies that the SC cert is valid.
// Uses identical code to KDC cert chaining engine.
//
// Author: Todds
//--------------------------------------------------------------------------
DWORD
DisplayChainInfo(
IN CERT_CONTEXT const *pCert)
{
HRESULT hr;
CERT_CHAIN_PARA ChainParameters;
char *pszSCUsage = szOID_KP_SMARTCARD_LOGON;
CERT_CHAIN_CONTEXT const *pChainContext = NULL;
DWORD VerifyState;
ZeroMemory(&ChainParameters, sizeof(ChainParameters));
ChainParameters.cbSize = sizeof(ChainParameters);
ChainParameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
ChainParameters.RequestedUsage.Usage.cUsageIdentifier = 1;
ChainParameters.RequestedUsage.Usage.rgpszUsageIdentifier = &pszSCUsage;
if (!CertGetCertificateChain(
HCCE_LOCAL_MACHINE,
pCert,
NULL, // evaluate at current time
NULL, // no additional stores
&ChainParameters,
CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
NULL, // reserved
&pChainContext))
{
hr = myHLastError();
cuPrintAPIError(L"CertGetCertificateChain", hr);
_JumpError(hr, error, "CertGetCertificateChain");
}
if (CERT_TRUST_NO_ERROR != pChainContext->TrustStatus.dwErrorStatus)
{
wprintf(
L"CertGetCertificateChain(dwErrorStatus) = 0x%x\n",
pChainContext->TrustStatus.dwErrorStatus);
wprintf(myLoadResourceString(IDS_SC_BAD_CHAIN));
wprintf(wszNewLine);
}
else
{
wprintf(myLoadResourceString(IDS_SC_GOOD_CHAIN));
wprintf(wszNewLine);
}
hr = cuVerifyCertContext(
pCert, // pCert
NULL, // hStoreCA
1, // cApplicationPolicies
&pszSCUsage, // apszApplicationPolicies
0, // cIssuancePolicies
NULL, // apszIssuancePolicies
TRUE, // fNTAuth
&VerifyState);
_JumpIfError(hr, error, "cuVerifyCertContext");
error:
if (NULL != pChainContext)
{
CertFreeCertificateChain(pChainContext);
}
return(hr);
}
HRESULT
DisplayReaderCertAndKey(
IN SCARD_READERSTATE const *pReaderState,
IN HCRYPTPROV hProv,
IN DWORD dwKeySpec,
IN WCHAR const *pwszKeyType,
IN WCHAR const *pwszCardName,
IN WCHAR const *pwszCSPName)
{
HRESULT hr;
HCRYPTKEY hKey = NULL;
CERT_CONTEXT const *pCert = NULL;
DWORD cwc;
WCHAR *pwszTitle = NULL;
CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewInfo;
// Get the key
if (!CryptGetUserKey(hProv, dwKeySpec, &hKey))
{
hr = myHLastError();
cuPrintAPIError(L"CryptGetUserKey", hr);
if (NTE_NO_KEY == hr)
{
wprintf(
myLoadResourceString(IDS_FORMAT_SC_NO_KEY_COLON),
pwszKeyType);
}
else
{
wprintf(
myLoadResourceString(IDS_FORMAT_SC_CANNOT_OPEN_KEY_COLON),
pwszKeyType);
}
wprintf(L" %ws\n", pReaderState->szReader);
_JumpError2(hr, error, "CryptGetUserKey", NTE_NO_KEY);
}
// Get the cert for this key
hr = GetCertContext(hProv, hKey, dwKeySpec, pwszKeyType, &pCert);
if (S_OK != hr)
{
wprintf(
myLoadResourceString(IDS_FORMAT_SC_NO_CERT_COLON),
pwszKeyType);
wprintf(L" %ws\n", pReaderState->szReader);
_JumpError(hr, error, "GetCertContext");
}
// Attempt to build a certificate chain
wprintf(wszNewLine);
wprintf(myLoadResourceString(IDS_SC_VALIDATING_CHAIN));
wprintf(wszNewLine);
DisplayChainInfo(pCert);
// call common UI to display Cert Context
// (from cryptui.h (cryptui.dll))
if (!g_fCryptSilent)
{
cwc = wcslen(pReaderState->szReader) +
2 +
wcslen(pwszKeyType);
pwszTitle = (WCHAR *) LocalAlloc(
LMEM_FIXED,
(cwc + 1) * sizeof(WCHAR));
if (NULL == pwszTitle)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
swprintf(
pwszTitle,
L"%ws: %ws",
pReaderState->szReader,
pwszKeyType);
ZeroMemory(&CertViewInfo, sizeof(CertViewInfo));
CertViewInfo.dwSize = sizeof(CertViewInfo);
//CertViewInfo.hwndParent = NULL;
CertViewInfo.szTitle = pwszTitle;
CertViewInfo.dwFlags = CRYPTUI_DISABLE_EDITPROPERTIES |
CRYPTUI_DISABLE_ADDTOSTORE |
CRYPTUI_ENABLE_REVOCATION_CHECKING;
CertViewInfo.pCertContext = pCert;
CryptUIDlgViewCertificate(&CertViewInfo, NULL);
CertFreeCertificateContext(pCert);
}
wprintf(
myLoadResourceString(IDS_FORMAT_SC_CERT_DISPLAYED_COLON),
pwszKeyType);
wprintf(L" %ws\n", pReaderState->szReader);
hr = S_OK;
error:
if (NULL != pwszTitle)
{
LocalFree(pwszTitle);
}
if (NULL != hKey)
{
CryptDestroyKey(hKey);
}
return(hr);
}
HRESULT
DisplayReaderCert(
IN SCARDCONTEXT hSCard,
IN SCARD_READERSTATE const *pReaderState)
{
HRESULT hr;
HRESULT hr2;
DWORD dwAutoAllocate;
WCHAR wszFQCN[256];
HCRYPTPROV hProv = NULL;
WCHAR *pwszCardName = NULL;
WCHAR *pwszCSPName = NULL;
if (0 >= pReaderState->cbAtr)
{
hr = S_OK;
goto error; // no point to do any more work on this reader
}
// Inform user of current test
wprintf(L"\n=======================================================\n");
wprintf(myLoadResourceString(IDS_SC_ANALYZING_CARD_COLON));
wprintf(L" %ws\n", pReaderState->szReader);
// Get the name of the card
dwAutoAllocate = SCARD_AUTOALLOCATE;
hr = SCardListCards(
hSCard,
pReaderState->rgbAtr,
NULL, // rgguidInterfaces
0, // cguidInterfaceCount
(WCHAR *) &pwszCardName, // mszCards
&dwAutoAllocate); // pcchCards
_JumpIfError(hr, error, "SCardListCards");
dwAutoAllocate = SCARD_AUTOALLOCATE;
hr = SCardGetCardTypeProviderName(
hSCard,
pwszCardName,
SCARD_PROVIDER_CSP,
(WCHAR *) &pwszCSPName,
&dwAutoAllocate);
if (S_OK != hr)
{
cuPrintAPIError(L"SCardGetCardTypeProviderName", hr);
wprintf(
myLoadResourceString(IDS_FORMAT_SC_CANNOT_GET_CSP),
pwszCardName);
_JumpError(hr, error, "SCardGetCardTypeProviderName");
}
// Prepare FullyQualifiedContainerName for CryptAcquireContext call
swprintf(wszFQCN, L"\\\\.\\%ws\\", pReaderState->szReader);
if (!CryptAcquireContext(
&hProv,
wszFQCN, // default container via reader
pwszCSPName,
PROV_RSA_FULL,
g_fCryptSilent? CRYPT_SILENT : 0))
{
hr = myHLastError();
wprintf(L"%ws:\n", pReaderState->szReader);
wprintf(L"%ws:\n", pwszCSPName);
cuPrintAPIError(L"CryptAcquireContext", hr);
_JumpError(hr, error, "SCardGetCardTypeProviderName");
}
// Enumerate the keys user specified and display the certs...
hr = DisplayReaderCertAndKey(
pReaderState,
hProv,
AT_SIGNATURE,
L"AT_SIGNATURE",
pwszCardName,
pwszCSPName);
_PrintIfError2(hr, "DisplayReaderCertAndKey", NTE_NO_KEY);
hr2 = DisplayReaderCertAndKey(
pReaderState,
hProv,
AT_KEYEXCHANGE,
L"AT_KEYEXCHANGE",
pwszCardName,
pwszCSPName);
_PrintIfError2(hr2, "DisplayReaderCertAndKey", NTE_NO_KEY);
if (S_OK == hr)
{
hr = hr2;
hr2 = S_OK;
}
// ignore NTE_NO_KEY if the other key type exists or has a different error:
if (NTE_NO_KEY == hr)
{
hr = hr2;
_PrintIfError2(hr, "DisplayReaderCertAndKey", NTE_NO_KEY);
}
error:
if (NULL != pwszCSPName)
{
SCardFreeMemory(hSCard, pwszCSPName);
}
if (NULL != pwszCardName)
{
SCardFreeMemory(hSCard, pwszCardName);
}
if (NULL != hProv)
{
CryptReleaseContext(hProv, 0);
}
return(hr);
}
//+-------------------------------------------------------------------------
// DisplayCerts
//--------------------------------------------------------------------------
HRESULT
DisplayCerts(
IN SCARDCONTEXT hSCard,
IN SCARD_READERSTATE const *prgReaderState,
IN DWORD cReaders)
{
HRESULT hr;
HRESULT hr2;
DWORD i;
// For each reader that has a card, load the CSP and display the cert
hr = S_OK;
for (i = 0; i < cReaders; i++)
{
hr2 = DisplayReaderCert(hSCard, &prgReaderState[i]);
_PrintIfError(hr2, "DisplayReaderCert");
if (S_OK == hr)
{
hr = hr2;
}
}
return(hr);
}
//+-------------------------------------------------------------------------
// verbSCInfo -- This is the main entry point for the smart card test program.
// Nice and simple, borrowed from DBarlow
//
// Author: Doug Barlow (dbarlow) 11/10/1997
//
// Revisions:
// AMatlosz 2/26/98
//--------------------------------------------------------------------------
HRESULT
verbSCInfo(
IN WCHAR const *pwszOption,
OPTIONAL IN WCHAR const *pwszReaderName,
IN WCHAR const *pwszArg2,
IN WCHAR const *pwszArg3,
IN WCHAR const *pwszArg4)
{
HRESULT hr;
HRESULT hr2;
SCARDCONTEXT hSCard = NULL;
WCHAR *pwszzReaderNameAlloc = NULL;
SCARD_READERSTATE *prgReaderState = NULL;
DWORD cReaders;
hr = IsSCardSvrRunning();
_JumpIfError(hr, error, "IsSCardSvrRunning");
hr = BuildReaderList(
pwszReaderName,
&hSCard,
&pwszzReaderNameAlloc,
&prgReaderState,
&cReaders);
_PrintIfError(hr, "BuildReaderList");
hr2 = DisplayReaderList(hSCard, prgReaderState, cReaders);
_PrintIfError(hr2, "DisplayReaderList");
if (S_OK == hr)
{
hr = hr2;
}
hr2 = DisplayCerts(hSCard, prgReaderState, cReaders);
_PrintIfError(hr2, "DisplayCerts");
if (S_OK == hr)
{
hr = hr2;
}
wprintf(wszNewLine);
wprintf(myLoadResourceString(IDS_DONE));
wprintf(wszNewLine);
error:
FreeReaderList(hSCard, pwszzReaderNameAlloc, prgReaderState);
return(hr);
}