Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

484 lines
14 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: pfximpt.cpp
//
// Contents: PFX import dialog
//
// History: 06/98 xtan
//
//----------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include "cscsp.h"
#include "certmsg.h"
#include "initcert.h"
#include "setuput.h"
#include "cspenum.h"
#include "wizpage.h"
#include "usecert.h"
#define __dwFILE__ __dwFILE_OCMSETUP_PFXIMPT_CPP__
typedef struct _certpfximportinfo
{
HINSTANCE hInstance;
BOOL fUnattended;
WCHAR *pwszFileName;
DWORD dwFileNameSize;
WCHAR *pwszPassword;
DWORD dwPasswordSize;
} CERTPFXIMPORTINFO;
HRESULT
CertBrowsePFX(HINSTANCE hInstance, HWND hDlg)
{
HRESULT hr;
WCHAR *pwszFileNameIn = NULL;
WCHAR *pwszFileNameOut = NULL;
HWND hCtrl = GetDlgItem(hDlg, IDC_PFX_FILENAME);
hr = myUIGetWindowText(hCtrl, &pwszFileNameIn);
_JumpIfError(hr, error, "myUIGetWindowText");
hr = myGetOpenFileName(
hDlg,
hInstance,
IDS_IMPORT_PFX_TITLE,
IDS_PFX_FILE_FILTER,
0, // no def ext
OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
pwszFileNameIn,
&pwszFileNameOut);
_JumpIfError(hr, error, "myGetOpenFileName");
if (NULL != pwszFileNameOut)
{
SetWindowText(hCtrl, pwszFileNameOut);
}
hr = S_OK;
error:
if (NULL != pwszFileNameOut)
{
LocalFree(pwszFileNameOut);
}
if (NULL != pwszFileNameIn)
{
LocalFree(pwszFileNameIn);
}
return hr;
}
HRESULT
GetPFXInfo(
HWND hDlg,
CERTPFXIMPORTINFO* pCertPfxImportInfo)
{
HRESULT hr;
GetWindowText(GetDlgItem(hDlg, IDC_PFX_FILENAME),
pCertPfxImportInfo->pwszFileName,
pCertPfxImportInfo->dwFileNameSize);
if (0x0 == pCertPfxImportInfo->pwszFileName[0])
{
// file can't empty
hr = E_INVALIDARG;
CertWarningMessageBox(
pCertPfxImportInfo->hInstance,
pCertPfxImportInfo->fUnattended,
hDlg,
IDS_ERR_EMPTYPFXFILE,
0,
NULL);
SetFocus(GetDlgItem(hDlg, IDC_PFX_FILENAME));
goto error;
}
GetWindowText(GetDlgItem(hDlg, IDC_PFX_PASSWORD),
pCertPfxImportInfo->pwszPassword,
pCertPfxImportInfo->dwPasswordSize);
hr = S_OK;
error:
return hr;
}
INT_PTR CALLBACK
CertPFXFilePasswordProc(
HWND hDlg,
UINT iMsg,
WPARAM wParam,
LPARAM lParam)
{
HRESULT hr;
BOOL ret = FALSE;
int id = IDCANCEL;
static CERTPFXIMPORTINFO *pCertPfxImportInfo = NULL;
switch (iMsg)
{
case WM_INITDIALOG:
pCertPfxImportInfo = (CERTPFXIMPORTINFO*)lParam;
ret = TRUE;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_PFX_FILENAME:
break;
case IDC_PFX_PASSWORD:
break;
case IDC_PFX_BROWSE:
CertBrowsePFX(pCertPfxImportInfo->hInstance, hDlg);
ret = TRUE;
break;
case IDOK:
hr = GetPFXInfo(hDlg, pCertPfxImportInfo);
if (S_OK != hr)
{
break;
}
id = IDOK;
case IDCANCEL:
ret = EndDialog(hDlg, id);
break;
}
break;
default:
ret = FALSE;
}
return ret;
}
int
CertGetPFXFileAndPassword(
IN HWND hwnd,
IN HINSTANCE hInstance,
IN BOOL fUnattended,
IN OUT WCHAR *pwszFileName,
IN DWORD dwFileNameSize,
IN OUT WCHAR *pwszPassword,
IN DWORD dwPasswordSize)
{
CERTPFXIMPORTINFO CertPfxImportInfo =
{hInstance, fUnattended,
pwszFileName, dwFileNameSize,
pwszPassword, dwPasswordSize};
return (int) DialogBoxParam(hInstance,
MAKEINTRESOURCE(IDD_PFXIMPORT),
hwnd,
CertPFXFilePasswordProc,
(LPARAM)&CertPfxImportInfo);
}
//--------------------------------------------------------------------
HRESULT
ImportPFXAndUpdateCSPInfo(
IN const HWND hDlg,
IN OUT PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
int nDlgRet;
BOOL bRetVal;
DWORD dwVerificationFlags;
BOOL bSelfSigned;
CSP_HASH * pHash;
WCHAR wszName[MAX_PATH];
WCHAR wszPassword[MAX_PATH];
CSP_INFO * pCSPInfo;
DWORD dwCSPInfoSize;
CASERVERSETUPINFO * pServer=pComp->CA.pServer;
// variables that must be cleaned up
CRYPT_KEY_PROV_INFO *pCertKeyProvInfo = NULL;
CERT_CONTEXT const *pSavedLeafCert = NULL;
wszName[0] = L'\0';
// get file name & password
if(pComp->fUnattended)
{
CSASSERT(NULL!=pServer->pwszPFXFile);
if(MAX_PATH<=wcslen(pServer->pwszPFXFile)||
NULL!=pServer->pwszPFXPassword &&
MAX_PATH<=wcslen(pServer->pwszPFXPassword))
{
hr = ERROR_BAD_PATHNAME;
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PFX_FILE_OR_PASSWORD_TOO_LONG,
0,
NULL);
_JumpError(hr, error, "PFX file name or password is too long");
}
wcscpy(wszName, pServer->pwszPFXFile);
wcscpy(wszPassword,
pServer->pwszPFXPassword?pServer->pwszPFXPassword:L"");
if (NULL == pServer->pCSPInfoList)
{
hr = GetCSPInfoList(&pServer->pCSPInfoList);
_JumpIfError(hr, error, "GetCSPInfoList");
}
}
else{
nDlgRet = CertGetPFXFileAndPassword(
hDlg,
pComp->hInstance,
pComp->fUnattended,
wszName,
sizeof(wszName)/sizeof(WCHAR),
wszPassword,
sizeof(wszPassword)/sizeof(WCHAR));
if (IDOK != nDlgRet)
{
// cancel
hr=HRESULT_FROM_WIN32(ERROR_CANCELLED);
_JumpError(hr, error, "CertGetPFXFileAndPassword canceled");
}
}
// import pkcs12
hr=myCertServerImportPFX(
wszName,
wszPassword,
FALSE,
NULL,
NULL,
&pSavedLeafCert);
if (S_OK != hr)
{
if (HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD)==hr)
{
// tell the user that their password was invalid
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PFX_INVALID_PASSWORD,
0,
NULL);
_JumpError(hr, error, "myCertServerImportPFX");
}
else if (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)
{
if(pComp->fUnattended)
{
nDlgRet=IDYES;
}
else
{
// confirm from user that they want to overwrite
// the existing key and cert
nDlgRet=CertMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PFX_KEYANDCERTEXIST,
0,
MB_YESNO | MB_ICONWARNING | CMB_NOERRFROMSYS,
NULL);
}
if (IDYES==nDlgRet)
{
hr=myCertServerImportPFX(
wszName,
wszPassword,
TRUE,
NULL,
NULL,
&pSavedLeafCert);
_JumpIfError(hr, errorMsg, "myCertServerImportPFX");
}
else
{
// cancel
hr=HRESULT_FROM_WIN32(ERROR_CANCELLED);
_JumpError(hr, error, "myCertServerImportPFX canceled");
}
}
else if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PFX_PATH_INVALID,
0,
wszName);
_JumpError(hr, error, "myCertServerImportPFX");
}
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PFX_FILE_NOT_FOUND,
0,
wszName);
_JumpError(hr, error, "myCertServerImportPFX");
}
else if (HRESULT_FROM_WIN32(CRYPT_E_SELF_SIGNED) == hr)
{
// this cert is not appropriate for this CA type (no CA certs found at all)
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PFX_WRONG_SELFSIGN_TYPE,
S_OK, // don't show an error number
NULL);
_JumpError(hr, error, "This cert is not appropriate for this CA type");
}
else
{
// import failed for some other reason
_JumpError(hr, errorMsg, "myCertServerImportPFX");
}
}
// PFX import was successful. The cert is in the machine's MY store.
CSASSERT(NULL!=pSavedLeafCert);
// The following things have been verified by myCertServerImportPFX
// * The cert has an AT_SIGNATURE key
// * The key in the store matches the one on the cer
// * The cert is not expired
//
// We still need to check:
// * self-signed or not
// * verify chain
// Note: IT IS VERY IMPORTANT that pfx import maintains all the
// invariants about CSP, key container, hash, cert validity, etc.
// that the rest of the UI maintains.
// get key prov info from cert
bRetVal=myCertGetCertificateContextProperty(
pSavedLeafCert,
CERT_KEY_PROV_INFO_PROP_ID,
CERTLIB_USE_LOCALALLOC,
(void **)&pCertKeyProvInfo,
&dwCSPInfoSize);
if (FALSE==bRetVal) {
hr=myHLastError();
_JumpError(hr, errorMsg, "myCertGetCertificateContextProperty");
}
// find our description of the CSP
pCSPInfo=findCSPInfoFromList(pServer->pCSPInfoList,
pCertKeyProvInfo->pwszProvName,
pCertKeyProvInfo->dwProvType);
CSASSERT(NULL!=pCSPInfo);
if (pCSPInfo == NULL) // we don't have this CSP enumerated in our UI
{
hr = CRYPT_E_NOT_FOUND;
_JumpError(hr, errorMsg, "pCSPInfo NULL");
}
//
// Looks like this key is good. Use it.
//
// Stop using the previous cert and key
// delete previously created key container, if necessary.
ClearKeyContainerName(pServer);
// update the CSP
// note: CSP, key container, and hash must all be consistent!
pServer->pCSPInfo=pCSPInfo;
hr = DetermineDefaultHash(pServer);
_JumpIfError(hr, error, "DetermineDefaultHash");
// save the name of the key container
hr=SetKeyContainerName(pServer, pCertKeyProvInfo->pwszContainerName);
_JumpIfError(hr, error, "SetKeyContainerName");
// See if we can use the cert
// verify to make sure no cert in chain is revoked, but don't kill yourself if offline
hr=myVerifyCertContext(
pSavedLeafCert,
CA_VERIFY_FLAGS_IGNORE_OFFLINE,
0,
NULL,
HCCE_LOCAL_MACHINE,
NULL,
NULL);
_JumpIfError(hr, errorMsg, "myVerifyCertContext");
// See if this cert appropriately is self-signed or not.
// A root CA cert must be self-signed, while
// a subordinate CA cert must not be self-signed.
hr=IsCertSelfSignedForCAType(pServer, pSavedLeafCert, &bRetVal);
_JumpIfError(hr, errorMsg, "IsCertSelfSignedForCAType");
if (FALSE==bRetVal) {
// this cert is not appropriate for this CA type
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PFX_WRONG_SELFSIGN_TYPE,
S_OK, // don't show an error number
NULL);
hr=CRYPT_E_SELF_SIGNED;
_JumpError(hr, error, "This cert is not appropriate for this CA type");
}
//
// Looks like this cert is good. Use it.
//
// save the cert and update the hash algorithm
hr=SetExistingCertToUse(pServer, pSavedLeafCert);
_JumpIfError(hr, error, "SetExistingCertToUse");
pSavedLeafCert=NULL;
hr=S_OK;
errorMsg:
if (FAILED(hr)) {
// an error occurred while trying to import the PFX file
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_ERR_IMPORTPFX,
hr,
NULL);
}
error:
CSILOG(
hr,
IDS_LOG_IMPORTPFX,
L'\0' == wszName[0]? NULL : wszName,
NULL,
NULL);
if (NULL != pSavedLeafCert)
{
CertFreeCertificateContext(pSavedLeafCert);
}
if (NULL != pCertKeyProvInfo)
{
LocalFree(pCertKeyProvInfo);
}
return hr;
}