|
|
/*++
Copyright (c) 1998 Microsoft Corporation
(c) Copyright Schlumberger Technology Corp., unpublished work, created 1999. This computer program includes Confidential, Proprietary Information and is a Trade Secret of Schlumberger Technology Corp. All use, disclosure, and/or reproduction is prohibited unless authorized in writing. All Rights Reserved.
Module Name:
autoreg
Abstract:
This module provides autoregistration capabilities to a CSP. It allows regsvr32 to call the DLL directly to add and remove Registry settings.
Author:
Doug Barlow (dbarlow) 3/11/1998
Environment:
Win32
Notes:
Look for "?vendor?" tags and edit appropriately.
--*/
#if defined(_UNICODE)
#if !defined(UNICODE)
#define UNICODE
#endif //!UNICODE
#endif //_UNICODE
#if defined(UNICODE)
#if !defined(_UNICODE)
#define _UNICODE
#endif //!_UNICODE
#endif //UNICODE
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifdef _AFXDLL
#include "stdafx.h"
#else
#include <windows.h>
#endif
#include <string>
#include <basetsd.h>
#include <wincrypt.h>
#include <cspdk.h> // CRYPT_SIG_RESOURCE_NUMBER
#include <winscard.h>
#include <tchar.h>
#include "CspProfile.h"
#include "Blob.h"
#include "StResource.h"
using namespace std; using namespace ProviderProfile;
namespace { typedef DWORD (*LPSETCARDTYPEPROVIDERNAME)(IN SCARDCONTEXT hContext, IN LPCTSTR szCardName, IN DWORD dwProviderId, IN LPCTSTR szProvider);
LPCTSTR szCardRegPath = TEXT("SOFTWARE\\Microsoft\\Cryptography\\Calais\\SmartCards");
// Remove the legacy Cryptoflex card from the registry. This
// will ease transition of W2K beta users to its commercial
// release as well as Cryptoflex SDK 1.x users. The supported
// cards are added by IntroduceVendorCard.
LPCTSTR aCardsToForget[] = { TEXT("Schlumberger Cryptoflex"), TEXT("Schlumberger Cryptoflex 4k"), TEXT("Schlumberger Cryptoflex 8k"), TEXT("Schlumberger Cryptoflex 8k v2") };
HRESULT ForgetVendorCard(LPCTSTR szCardToForget) { bool fCardIsForgotten = false; HRESULT hReturnStatus = NO_ERROR;
#if !defined(UNICODE)
string #else
wstring #endif // !defined(UNICODE)
sRegCardToForget(szCardRegPath);
sRegCardToForget.append(TEXT("\\")); sRegCardToForget.append(szCardToForget);
for (DWORD dwIndex = 0; !fCardIsForgotten; dwIndex += 1) { HKEY hCalais(0); SCARDCONTEXT hCtx(0); DWORD dwStatus; LONG nStatus;
switch (dwIndex) { case 0: dwStatus = SCardEstablishContext(SCARD_SCOPE_SYSTEM, 0, 0, &hCtx); if (ERROR_SUCCESS != dwStatus) continue; dwStatus = SCardForgetCardType(hCtx, szCardToForget); if (ERROR_SUCCESS != dwStatus) continue; dwStatus = SCardReleaseContext(hCtx); hCtx = NULL; if (ERROR_SUCCESS != dwStatus) { if (0 == (dwStatus & 0xffff0000)) hReturnStatus = HRESULT_FROM_WIN32(dwStatus); else hReturnStatus = (HRESULT)dwStatus; goto ErrorExit; } // Ignore the return code since the previous probably deleted it.
nStatus = RegDeleteKey(HKEY_LOCAL_MACHINE, sRegCardToForget.c_str()); fCardIsForgotten = true; break;
case 1: // Last try, if not successful then it must not exist...
nStatus = RegDeleteKey(HKEY_LOCAL_MACHINE, sRegCardToForget.c_str()); fCardIsForgotten = true; break;
default: hReturnStatus = ERROR_ACCESS_DENIED; goto ErrorExit; }
ErrorExit: if (NULL != hCtx) SCardReleaseContext(hCtx); if (NULL != hCalais) RegCloseKey(hCalais); break; }
return hReturnStatus; }
HRESULT IntroduceVendorCard(CString const &rsCspName, CardProfile const &rcp) { // Try various techniques until one works.
ATR const &ratr = rcp.ATR(); bool fCardIntroduced = false; HRESULT hReturnStatus = NO_ERROR;
for (DWORD dwIndex = 0; !fCardIntroduced; dwIndex += 1) { HKEY hCalais(0); SCARDCONTEXT hCtx(0); DWORD dwDisp; DWORD dwStatus; LONG nStatus; HKEY hVendor(0);
switch (dwIndex) { case 0: { HMODULE hWinSCard = NULL; LPSETCARDTYPEPROVIDERNAME pfSetCardTypeProviderName = NULL;
hWinSCard = GetModuleHandle(TEXT("WinSCard.DLL")); if (NULL == hWinSCard) continue; #if defined(UNICODE)
pfSetCardTypeProviderName = reinterpret_cast<LPSETCARDTYPEPROVIDERNAME>(GetProcAddress(hWinSCard, AsCCharP(TEXT("SCardSetCardTypeProviderNameW"))));
#else
pfSetCardTypeProviderName = reinterpret_cast<LPSETCARDTYPEPROVIDERNAME>(GetProcAddress(hWinSCard, TEXT("SCardSetCardTypeProviderNameA")));
#endif
if (!pfSetCardTypeProviderName) continue; dwStatus = SCardIntroduceCardType(NULL, (LPCTSTR)rcp.csRegistryName(), NULL, NULL, 0, ratr.String(), ratr.Mask(), ratr.Size());
if ((ERROR_SUCCESS != dwStatus) && (ERROR_ALREADY_EXISTS != dwStatus)) continue; dwStatus = (*pfSetCardTypeProviderName)(NULL, (LPCTSTR)rcp.csRegistryName(), SCARD_PROVIDER_CSP, (LPCTSTR)rsCspName); if (ERROR_SUCCESS != dwStatus) { if (0 == (dwStatus & 0xffff0000)) hReturnStatus = HRESULT_FROM_WIN32(dwStatus); else hReturnStatus = (HRESULT)dwStatus; goto ErrorExit; } fCardIntroduced = TRUE; break; }
case 1: dwStatus = SCardEstablishContext(SCARD_SCOPE_SYSTEM, 0, 0, &hCtx); if (ERROR_SUCCESS != dwStatus) continue; dwStatus = SCardIntroduceCardType(hCtx, (LPCTSTR)rcp.csRegistryName(), &rcp.PrimaryProvider(), NULL, 0, ratr.String(), ratr.Mask(), ratr.Size()); if ((ERROR_SUCCESS != dwStatus) && (ERROR_ALREADY_EXISTS != dwStatus)) { if (0 == (dwStatus & 0xffff0000)) hReturnStatus = HRESULT_FROM_WIN32(dwStatus); else hReturnStatus = (HRESULT)dwStatus; goto ErrorExit; } dwStatus = SCardReleaseContext(hCtx); hCtx = NULL; if (ERROR_SUCCESS != dwStatus) { if (0 == (dwStatus & 0xffff0000)) hReturnStatus = HRESULT_FROM_WIN32(dwStatus); else hReturnStatus = (HRESULT)dwStatus; goto ErrorExit; } nStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Cryptography\\Calais\\SmartCards"), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hCalais, &dwDisp); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegCreateKeyEx(hCalais, (LPCTSTR)rcp.csRegistryName(), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hVendor, &dwDisp); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegCloseKey(hCalais); hCalais = NULL; if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; }
nStatus = RegSetValueEx(hVendor, TEXT("Crypto Provider"), 0, REG_SZ, reinterpret_cast<LPCBYTE>((LPCTSTR)rsCspName), (_tcslen((LPCTSTR)rsCspName) + 1) * sizeof TCHAR); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; }
nStatus = RegCloseKey(hVendor); hVendor = NULL; if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } fCardIntroduced = TRUE; break;
case 2: nStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Cryptography\\Calais\\SmartCards"), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hCalais, &dwDisp); if (ERROR_SUCCESS != nStatus) continue; nStatus = RegCreateKeyEx(hCalais, (LPCTSTR)rcp.csRegistryName(), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hVendor, &dwDisp); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegCloseKey(hCalais); hCalais = NULL; if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegSetValueEx(hVendor, TEXT("Primary Provider"), 0, REG_BINARY, (LPCBYTE)&rcp.PrimaryProvider(), sizeof LPCBYTE); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegSetValueEx(hVendor, TEXT("ATR"), 0, REG_BINARY, ratr.String(), ratr.Size()); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegSetValueEx(hVendor, TEXT("ATRMask"), 0, REG_BINARY, ratr.Mask(), ratr.Size()); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegSetValueEx(hVendor, TEXT("Crypto Provider"), 0, REG_SZ, reinterpret_cast<LPCBYTE>((LPCTSTR)rsCspName), (_tcslen((LPCTSTR)rsCspName) + 1) * sizeof TCHAR); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegCloseKey(hVendor); hVendor = NULL; if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } fCardIntroduced = TRUE; break;
default: hReturnStatus = ERROR_ACCESS_DENIED; goto ErrorExit; }
ErrorExit: if (NULL != hCtx) SCardReleaseContext(hCtx); if (NULL != hCalais) RegCloseKey(hCalais); if (NULL != hVendor) RegCloseKey(hVendor); break; }
return hReturnStatus; }
} // namespace
/*++
DllUnregisterServer:
This service removes the registry entries associated with this CSP.
Arguments:
None
Return Value:
Status code as an HRESULT.
Author:
Doug Barlow (dbarlow) 3/11/1998
--*/
STDAPI DllUnregisterServer(void) { LONG nStatus; DWORD dwDisp; HRESULT hReturnStatus = NO_ERROR; HKEY hProviders = NULL; SCARDCONTEXT hCtx = NULL; CString sProvName; #ifdef _AFXDLL
AFX_MANAGE_STATE(AfxGetStaticModuleState()); #endif
CspProfile const &rProfile = CspProfile::Instance(); sProvName = rProfile.Name(); //
// Delete the Registry key for this CSP.
//
nStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider"), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hProviders, &dwDisp); if (ERROR_SUCCESS == nStatus) { RegDeleteKey(hProviders, (LPCTSTR)sProvName); RegCloseKey(hProviders); hProviders = NULL; }
//
// Remove the cards introduced.
//
{ vector<CardProfile> const &rvcp = rProfile.Cards(); for (vector<CardProfile>::const_iterator it = rvcp.begin(); it != rvcp.end(); ++it) { hReturnStatus = ForgetVendorCard((LPCTSTR)(it->csRegistryName())); if (NO_ERROR != hReturnStatus) break; }
if (NO_ERROR != hReturnStatus) goto ErrorExit; }
//
// Forget the card type.
//
hCtx = NULL; SCardEstablishContext(SCARD_SCOPE_SYSTEM, 0, 0, &hCtx); SCardForgetCardType(hCtx, (LPCTSTR)sProvName); if (NULL != hCtx) { SCardReleaseContext(hCtx); hCtx = NULL; }
//
// All done!
//
ErrorExit: return hReturnStatus; }
/*++
DllRegisterServer:
This function installs the proper registry entries to enable this CSP.
Arguments:
None
Return Value:
Status code as an HRESULT.
Author:
Doug Barlow (dbarlow) 3/11/1998
--*/
STDAPI DllRegisterServer(void) { TCHAR szModulePath[MAX_PATH+1]; // Security: Leave room to zero
// terminate the buffer for
// subsequent operations.
BYTE pbSignature[136]; // Room for a 1024 bit signature, with padding.
OSVERSIONINFO osVer; LPTSTR szFileName, szFileExt; HINSTANCE hThisDll; HRSRC hSigResource; DWORD dwStatus; LONG nStatus; BOOL fStatus; DWORD dwDisp; DWORD dwIndex; DWORD dwSigLength = 0; HRESULT hReturnStatus = NO_ERROR; HKEY hProviders = NULL; HKEY hMyCsp = NULL; HKEY hCalais = NULL; HKEY hVendor = NULL; BOOL fSignatureFound = FALSE; HANDLE hSigFile = INVALID_HANDLE_VALUE; SCARDCONTEXT hCtx = NULL; CString sProvName; // TO DO: Card registration should be made by the CCI/IOP, not
// the CSP.
#ifdef _AFXDLL
AFX_MANAGE_STATE(AfxGetStaticModuleState()); #endif
CspProfile const &rProfile = CspProfile::Instance();
//
// Figure out the file name and path.
//
hThisDll = rProfile.DllInstance(); if (NULL == hThisDll) { hReturnStatus = HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE); goto ErrorExit; }
dwStatus = GetModuleFileName(hThisDll, szModulePath, sizeof(szModulePath)/sizeof(TCHAR)); if (0 == dwStatus) { hReturnStatus = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; }
// Zero terminate buffer.
szModulePath[dwStatus] = 0; szFileName = _tcsrchr(szModulePath, TEXT('\\')); if (NULL == szFileName) szFileName = szModulePath; else szFileName += 1; szFileExt = _tcsrchr(szFileName, TEXT('.')); if (NULL == szFileExt) { hReturnStatus = HRESULT_FROM_WIN32(ERROR_INVALID_NAME); goto ErrorExit; } else szFileExt += 1;
//
// Create the Registry key for this CSP.
//
nStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider"), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hProviders, &dwDisp); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; }
sProvName = rProfile.Name(); nStatus = RegCreateKeyEx(hProviders, (LPCTSTR)sProvName, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hMyCsp, &dwDisp); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } nStatus = RegCloseKey(hProviders); hProviders = NULL; if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; }
//
// Install the trivial registry values.
//
// Security/sysprep requirement: the module path must be replaced
// with just the dll name to faclilitate sysprep. Corresponding
// changes to LoadLibrary imply that there are no security risks
// for system processes. The security implications of such
// installation for applications is an open question.
nStatus = RegSetValueEx(hMyCsp, TEXT("Image Path"), 0, REG_SZ, (LPBYTE)szFileName,//szModulePath,
(_tcslen(szFileName/*szModulePath*/) + 1) * sizeof(TCHAR)); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; }
{ DWORD ProviderType = rProfile.Type(); nStatus = RegSetValueEx(hMyCsp, TEXT("Type"), 0, REG_DWORD, (LPBYTE)&ProviderType, sizeof ProviderType); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } }
//
// See if we're self-signed. On NT5, CSP images can carry their own
// signatures.
//
hSigResource = FindResource(hThisDll, MAKEINTRESOURCE(CRYPT_SIG_RESOURCE_NUMBER), RT_RCDATA);
//
// Install the file signature.
//
ZeroMemory(&osVer, sizeof(OSVERSIONINFO)); osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); fStatus = GetVersionEx(&osVer); if (fStatus && (VER_PLATFORM_WIN32_NT == osVer.dwPlatformId) && (5 <= osVer.dwMajorVersion) && (NULL != hSigResource)) {
//
// Signature in file flag is sufficient.
//
dwStatus = 0; nStatus = RegSetValueEx(hMyCsp, TEXT("SigInFile"), 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(DWORD)); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } } else {
//
// We have to install a signature entry.
// Try various techniques until one works.
//
for (dwIndex = 0; !fSignatureFound; dwIndex += 1) { switch (dwIndex) {
//
// Look for an external *.sig file and load that into the registry.
//
case 0: _tcscpy(szFileExt, TEXT("sig")); hSigFile = CreateFile( szModulePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hSigFile) continue; dwSigLength = GetFileSize(hSigFile, NULL); if ((dwSigLength > sizeof(pbSignature)) || (dwSigLength < 72)) // Accept a 512-bit signature
{ hReturnStatus = NTE_BAD_SIGNATURE; goto ErrorExit; }
fStatus = ReadFile( hSigFile, pbSignature, sizeof(pbSignature), &dwSigLength, NULL); if (!fStatus) { hReturnStatus = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; } fStatus = CloseHandle(hSigFile); hSigFile = NULL; if (!fStatus) { hReturnStatus = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; } fSignatureFound = TRUE; break;
//
// Other cases may be added in the future.
//
default: hReturnStatus = NTE_BAD_SIGNATURE; goto ErrorExit; }
if (fSignatureFound) { for (dwIndex = 0; dwIndex < dwSigLength; dwIndex += 1) { if (0 != pbSignature[dwIndex]) break; } if (dwIndex >= dwSigLength) fSignatureFound = FALSE; } }
//
// We've found a signature somewhere! Install it.
//
nStatus = RegSetValueEx( hMyCsp, TEXT("Signature"), 0, REG_BINARY, pbSignature, dwSigLength); if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; } }
nStatus = RegCloseKey(hMyCsp); hMyCsp = NULL; if (ERROR_SUCCESS != nStatus) { hReturnStatus = HRESULT_FROM_WIN32(nStatus); goto ErrorExit; }
for (dwIndex = 0; dwIndex < (sizeof aCardsToForget / sizeof *aCardsToForget); dwIndex++) { hReturnStatus = ForgetVendorCard(aCardsToForget[dwIndex]); if (NO_ERROR != hReturnStatus) goto ErrorExit; }
//
// Introduce the vendor cards. Try various techniques until one works.
//
{ vector<CardProfile> const &rvcp = rProfile.Cards(); for (vector<CardProfile>::const_iterator it = rvcp.begin(); it != rvcp.end(); ++it) { hReturnStatus = IntroduceVendorCard(rProfile.Name(), *it); if (NO_ERROR != hReturnStatus) break; }
if (NO_ERROR != hReturnStatus) goto ErrorExit; }
//
// ?vendor?
// Add any additional initialization required here.
//
//
// All done!
//
return hReturnStatus;
//
// An error was detected. Clean up any outstanding resources and
// return the error.
//
ErrorExit: if (NULL != hCtx) SCardReleaseContext(hCtx); if (NULL != hCalais) RegCloseKey(hCalais); if (NULL != hVendor) RegCloseKey(hVendor); if (INVALID_HANDLE_VALUE != hSigFile) CloseHandle(hSigFile); if (NULL != hMyCsp) RegCloseKey(hMyCsp); if (NULL != hProviders) RegCloseKey(hProviders); DllUnregisterServer(); return hReturnStatus; }
|