- Sync crypt32 and cryptui with Wine head

svn path=/trunk/; revision=39760
This commit is contained in:
Dmitry Chapyshev 2009-02-26 10:21:59 +00:00
parent b6bab62a3b
commit 81ccdcd42b
6 changed files with 802 additions and 79 deletions

View file

@ -28,6 +28,7 @@
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
WINE_DECLARE_DEBUG_CHANNEL(chain);
#define DEFAULT_CYCLE_MODULUS 7
@ -355,7 +356,7 @@ static void CRYPT_CheckRootCert(HCERTCHAINENGINE hRoot,
CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, (void *)root,
CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)root, 0, NULL))
{
TRACE("Last certificate's signature is invalid\n");
TRACE_(chain)("Last certificate's signature is invalid\n");
rootElement->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_SIGNATURE_VALID;
}
@ -411,8 +412,12 @@ static BOOL CRYPT_DecodeBasicConstraints(PCCERT_CONTEXT cert,
}
/* Checks element's basic constraints to see if it can act as a CA, with
* remainingCAs CAs left in this chain. Updates chainConstraints with the
* element's constraints, if:
* remainingCAs CAs left in this chain. A root certificate is assumed to be
* allowed to be a CA whether or not the basic constraints extension is present,
* whereas an intermediate CA cert is not. This matches the expected usage in
* RFC 3280: a conforming intermediate CA MUST contain the basic constraints
* extension. It also appears to match Microsoft's implementation.
* Updates chainConstraints with the element's constraints, if:
* 1. chainConstraints doesn't have a path length constraint, or
* 2. element's path length constraint is smaller than chainConstraints's
* Sets *pathLengthConstraintViolated to TRUE if a path length violation
@ -422,17 +427,17 @@ static BOOL CRYPT_DecodeBasicConstraints(PCCERT_CONTEXT cert,
*/
static BOOL CRYPT_CheckBasicConstraintsForCA(PCCERT_CONTEXT cert,
CERT_BASIC_CONSTRAINTS2_INFO *chainConstraints, DWORD remainingCAs,
BOOL *pathLengthConstraintViolated)
BOOL isRoot, BOOL *pathLengthConstraintViolated)
{
BOOL validBasicConstraints;
CERT_BASIC_CONSTRAINTS2_INFO constraints;
if ((validBasicConstraints = CRYPT_DecodeBasicConstraints(cert,
&constraints, TRUE)))
&constraints, isRoot)))
{
if (!constraints.fCA)
{
TRACE("chain element %d can't be a CA\n", remainingCAs + 1);
TRACE_(chain)("chain element %d can't be a CA\n", remainingCAs + 1);
validBasicConstraints = FALSE;
}
else if (constraints.fPathLenConstraint)
@ -444,7 +449,7 @@ static BOOL CRYPT_CheckBasicConstraintsForCA(PCCERT_CONTEXT cert,
constraints.dwPathLenConstraint <
chainConstraints->dwPathLenConstraint)
{
TRACE("setting path length constraint to %d\n",
TRACE_(chain)("setting path length constraint to %d\n",
chainConstraints->dwPathLenConstraint);
chainConstraints->fPathLenConstraint = TRUE;
chainConstraints->dwPathLenConstraint =
@ -455,8 +460,8 @@ static BOOL CRYPT_CheckBasicConstraintsForCA(PCCERT_CONTEXT cert,
if (chainConstraints->fPathLenConstraint &&
remainingCAs > chainConstraints->dwPathLenConstraint)
{
TRACE("remaining CAs %d exceed max path length %d\n", remainingCAs,
chainConstraints->dwPathLenConstraint);
TRACE_(chain)("remaining CAs %d exceed max path length %d\n",
remainingCAs, chainConstraints->dwPathLenConstraint);
validBasicConstraints = FALSE;
*pathLengthConstraintViolated = TRUE;
}
@ -709,6 +714,100 @@ static void CRYPT_CheckChainNameConstraints(PCERT_SIMPLE_CHAIN chain)
}
}
static void dump_basic_constraints(PCERT_EXTENSION ext)
{
CERT_BASIC_CONSTRAINTS_INFO *info;
DWORD size = 0;
if (CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS,
ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG,
NULL, &info, &size))
{
TRACE_(chain)("SubjectType: %02x\n", info->SubjectType.pbData[0]);
TRACE_(chain)("%s path length constraint\n",
info->fPathLenConstraint ? "has" : "doesn't have");
TRACE_(chain)("path length=%d\n", info->dwPathLenConstraint);
LocalFree(info);
}
}
static void dump_basic_constraints2(PCERT_EXTENSION ext)
{
CERT_BASIC_CONSTRAINTS2_INFO constraints;
DWORD size = sizeof(CERT_BASIC_CONSTRAINTS2_INFO);
if (CryptDecodeObjectEx(X509_ASN_ENCODING,
szOID_BASIC_CONSTRAINTS2, ext->Value.pbData, ext->Value.cbData,
0, NULL, &constraints, &size))
{
TRACE_(chain)("basic constraints:\n");
TRACE_(chain)("can%s be a CA\n", constraints.fCA ? "" : "not");
TRACE_(chain)("%s path length constraint\n",
constraints.fPathLenConstraint ? "has" : "doesn't have");
TRACE_(chain)("path length=%d\n", constraints.dwPathLenConstraint);
}
}
static void dump_extension(PCERT_EXTENSION ext)
{
TRACE_(chain)("%s (%scritical)\n", debugstr_a(ext->pszObjId),
ext->fCritical ? "" : "not ");
if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS))
dump_basic_constraints(ext);
else if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS2))
dump_basic_constraints2(ext);
}
static LPCWSTR filetime_to_str(const FILETIME *time)
{
static WCHAR date[80];
WCHAR dateFmt[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
SYSTEMTIME sysTime;
if (!time) return NULL;
GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, dateFmt,
sizeof(dateFmt) / sizeof(dateFmt[0]));
FileTimeToSystemTime(time, &sysTime);
GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, dateFmt, date,
sizeof(date) / sizeof(date[0]));
return date;
}
static void dump_element(PCCERT_CONTEXT cert)
{
LPWSTR name = NULL;
DWORD len, i;
TRACE_(chain)("%p\n", cert);
len = CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
name = CryptMemAlloc(len * sizeof(WCHAR));
if (name)
{
CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, NULL, name, len);
TRACE_(chain)("issued by %s\n", debugstr_w(name));
CryptMemFree(name);
}
len = CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL,
NULL, 0);
name = CryptMemAlloc(len * sizeof(WCHAR));
if (name)
{
CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL,
name, len);
TRACE_(chain)("issued to %s\n", debugstr_w(name));
CryptMemFree(name);
}
TRACE_(chain)("valid from %s to %s\n",
debugstr_w(filetime_to_str(&cert->pCertInfo->NotBefore)),
debugstr_w(filetime_to_str(&cert->pCertInfo->NotAfter)));
TRACE_(chain)("%d extensions\n", cert->pCertInfo->cExtension);
for (i = 0; i < cert->pCertInfo->cExtension; i++)
dump_extension(&cert->pCertInfo->rgExtension[i]);
}
static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
PCERT_SIMPLE_CHAIN chain, LPFILETIME time)
{
@ -717,14 +816,25 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
BOOL pathLengthConstraintViolated = FALSE;
CERT_BASIC_CONSTRAINTS2_INFO constraints = { TRUE, FALSE, 0 };
TRACE_(chain)("checking chain with %d elements for time %s\n",
chain->cElement, debugstr_w(filetime_to_str(time)));
for (i = chain->cElement - 1; i >= 0; i--)
{
if (TRACE_ON(chain))
dump_element(chain->rgpElement[i]->pCertContext);
if (CertVerifyTimeValidity(time,
chain->rgpElement[i]->pCertContext->pCertInfo) != 0)
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_TIME_VALID;
if (i != 0)
{
BOOL isRoot;
if (i == chain->cElement - 1)
isRoot = CRYPT_IsCertificateSelfSigned(
chain->rgpElement[i]->pCertContext);
else
isRoot = FALSE;
/* Check the signature of the cert this issued */
if (!CryptVerifyCertificateSignatureEx(0, X509_ASN_ENCODING,
CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
@ -741,7 +851,7 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
else if (!CRYPT_CheckBasicConstraintsForCA(
chain->rgpElement[i]->pCertContext, &constraints, i - 1,
&pathLengthConstraintViolated))
isRoot, &pathLengthConstraintViolated))
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
else if (constraints.fPathLenConstraint &&
@ -884,8 +994,7 @@ static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
issuer = CertFindCertificateInStore(store,
subject->dwCertEncodingType, 0, CERT_FIND_SUBJECT_NAME,
&subject->pCertInfo->Issuer, prevIssuer);
if (issuer)
*infoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
*infoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
}
return issuer;
}
@ -902,12 +1011,13 @@ static BOOL CRYPT_BuildSimpleChain(PCertificateChainEngine engine,
while (ret && !CRYPT_IsSimpleChainCyclic(chain) &&
!CRYPT_IsCertificateSelfSigned(cert))
{
DWORD infoStatus;
PCCERT_CONTEXT issuer = CRYPT_GetIssuer(world, cert, NULL, &infoStatus);
PCCERT_CONTEXT issuer = CRYPT_GetIssuer(world, cert, NULL,
&chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
if (issuer)
{
ret = CRYPT_AddCertToSimpleChain(engine, chain, issuer, infoStatus);
ret = CRYPT_AddCertToSimpleChain(engine, chain, issuer,
chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
/* CRYPT_AddCertToSimpleChain add-ref's the issuer, so free it to
* close the enumeration that found it
*/
@ -916,7 +1026,7 @@ static BOOL CRYPT_BuildSimpleChain(PCertificateChainEngine engine,
}
else
{
TRACE("Couldn't find issuer, halting chain creation\n");
TRACE_(chain)("Couldn't find issuer, halting chain creation\n");
chain->TrustStatus.dwErrorStatus |= CERT_TRUST_IS_PARTIAL_CHAIN;
break;
}

View file

@ -172,6 +172,7 @@ STRINGTABLE DISCARDABLE
IDS_LOCALIZEDNAME_MY "개인"
IDS_LOCALIZEDNAME_CA "중개 검증 기관"
IDS_LOCALIZEDNAME_ADDRESSBOOK "다른 사람"
IDS_LOCALIZEDNAME_TRUSTEDPUBLISHER "신뢰할 수 있는 발행자"
}
STRINGTABLE DISCARDABLE

View file

@ -102,8 +102,8 @@ STRINGTABLE DISCARDABLE
IDS_FRIENDLY_NAME_COLUMN "Friendly Name"
IDS_ALLOWED_PURPOSE_ALL "<All>"
IDS_ALLOWED_PURPOSE_NONE "<None>"
IDS_WARN_REMOVE_MY "You will no longer be able to decrypt mesages with this certificate, or sign messages with it.\nAre you sure you want to remove this certificate?"
IDS_WARN_REMOVE_PLURAL_MY "You will no longer be able to decrypt mesages with these certificate, or sign messages with them.\nAre you sure you want to remove these certificates?"
IDS_WARN_REMOVE_MY "You will no longer be able to decrypt messages with this certificate, or sign messages with it.\nAre you sure you want to remove this certificate?"
IDS_WARN_REMOVE_PLURAL_MY "You will no longer be able to decrypt messages with these certificates, or sign messages with them.\nAre you sure you want to remove these certificates?"
IDS_WARN_REMOVE_ADDRESSBOOK "You will no longer be able to encrypt messages with this certificate, or verify messages signed with it.\nAre you sure you want to remove this certificate?"
IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK "You will no longer be able to encrypt messages with these certificates, or verify messages signed with it.\nAre you sure you want to remove these certificates?"
IDS_WARN_REMOVE_CA "Certificates issued by this certification authority will no longer be trusted.\nAre you sure you want to remove this certificate?"
@ -161,6 +161,13 @@ STRINGTABLE DISCARDABLE
IDS_NO "No"
IDS_EXPORT_SUCCEEDED "The export was successful."
IDS_EXPORT_FAILED "The export failed."
IDS_EXPORT_PRIVATE_KEY_TITLE "Export Private Key"
IDS_EXPORT_PRIVATE_KEY_SUBTITLE "The certificate contains a private key which may be exported along with the certificate."
IDS_EXPORT_PASSWORD_TITLE "Enter Password"
IDS_EXPORT_PASSWORD_SUBTITLE "You may password-protect a private key."
IDS_EXPORT_PASSWORD_MISMATCH "The passwords do not match."
IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE "Note: The private key for this certificate could not be opened."
IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE "Note: The private key for this certificate is not exportable."
}
IDD_GENERAL DIALOG DISCARDABLE 0, 0, 255, 236
@ -381,6 +388,29 @@ BEGIN
-1, 115,103,195,8
END
IDD_EXPORT_PRIVATE_KEY DIALOG DISCARDABLE 0,0,317,143
CAPTION "Certificate Export Wizard"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "If you choose to export the private key, you will be prompted for a password to protect the private key on a later page.", -1, 21,1,195,23
LTEXT "Do you wish to export the private key?", -1, 21,24,195,15
AUTORADIOBUTTON "&Yes, export the private key",
IDC_EXPORT_PRIVATE_KEY_YES, 31,36,200,12, BS_AUTORADIOBUTTON|WS_TABSTOP
AUTORADIOBUTTON "N&o, do not export the private key",
IDC_EXPORT_PRIVATE_KEY_NO, 31,48,200,12, BS_AUTORADIOBUTTON
LTEXT "", IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE, 21,60,200,24
END
IDD_EXPORT_PASSWORD DIALOG DISCARDABLE 0,0,317,143
CAPTION "Certificate Export Wizard"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "&Password:", -1, 21,1,195,10
EDITTEXT IDC_EXPORT_PASSWORD, 21,11,208,14, ES_AUTOHSCROLL|WS_TABSTOP
LTEXT "&Confirm password:", -1, 21,35,195,10
EDITTEXT IDC_EXPORT_PASSWORD_CONFIRM, 21,45,208,14, ES_AUTOHSCROLL|WS_TABSTOP
END
IDD_EXPORT_FORMAT DIALOG DISCARDABLE 0,0,317,143
CAPTION "Certificate Export Wizard"
FONT 8, "MS Shell Dlg"

View file

@ -143,6 +143,34 @@ STRINGTABLE DISCARDABLE
IDS_PURPOSE_CA_EXCHANGE "사적 키 보관소"
IDS_PURPOSE_KEY_RECOVERY_AGENT "키 복구 에이전트"
IDS_PURPOSE_DS_EMAIL_REPLICATION "디렉토리 서비스 전자우편 복제"
IDS_EXPORT_WIZARD "인증서 내보내기 마법사"
IDS_EXPORT_FORMAT_TITLE "내보낼 형식"
IDS_EXPORT_FORMAT_SUBTITLE "내용을 저장할 형식 선택."
IDS_EXPORT_FILE_TITLE "내보낼 파일이름"
IDS_EXPORT_FILE_SUBTITLE "내용을 저장할 파일 이름 지정."
IDS_EXPORT_FILE_EXISTS "지정된 파일은 이미 존재합니다.덮어 쓰시겠습니까?"
IDS_EXPORT_FILTER_CERT "DER-암호화된 바이너리 X.509 (*.cer)"
IDS_EXPORT_FILTER_BASE64_CERT "Base64-암호화된 X.509 (*.cer)"
IDS_EXPORT_FILTER_CRL "인증서 폐기 목록 (*.crl)"
IDS_EXPORT_FILTER_CTL "인증서 신뢰 목록 (*.stl)"
IDS_EXPORT_FILTER_CMS "CMS/PKCS #7 메세지 (*.p7b)"
IDS_EXPORT_FILTER_PFX "개인 정보 교환 (*.pfx)"
IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE "나열된 인증서 저장소 (*.sst)"
IDS_EXPORT_FORMAT "파일 형식"
IDS_EXPORT_INCLUDE_CHAIN "인증 경로에 있는 모든 인증서 포함"
IDS_EXPORT_KEYS "내보낼 키"
IDS_YES "예"
IDS_NO "아니오"
IDS_EXPORT_SUCCEEDED "내보내기 성공."
IDS_EXPORT_FAILED "내보내기 실패."
IDS_EXPORT_PRIVATE_KEY_TITLE "내보낼 개인 키"
IDS_EXPORT_PRIVATE_KEY_SUBTITLE "이 인증서는 인증서를 내보낼 때 같이 나갈 개인키를 포함하고 있습니다."
IDS_EXPORT_PASSWORD_TITLE "암호 입력"
IDS_EXPORT_PASSWORD_SUBTITLE "이 개인키는 아마도 암호로 보호되어있는 것 같습니다."
IDS_EXPORT_PASSWORD_MISMATCH "이 암호는 맞지 않습니다."
IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE "주의: 이 인증서를 위한 개인 키를 열 수 없습니다."
IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE "주의: 이 인증서를 위한 개인 키를 내보낼 수 없습니다."
}
IDD_GENERAL DIALOG DISCARDABLE 0, 0, 255, 236
@ -330,3 +358,90 @@ BEGIN
PUSHBUTTON "확인", IDOK, 132,155,51,14, BS_DEFPUSHBUTTON
PUSHBUTTON "취소", IDCANCEL, 190,155,51,14
END
IDD_EXPORT_WELCOME DIALOG DISCARDABLE 0,0,317,143
CAPTION "인증서 내보내기 마법사"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "인증서 내보내기 마법사에 오신 것을 환영합니다", IDC_EXPORT_TITLE,
115,1,195,40
LTEXT "이 마법사는 인증서,인증서 폐기 목록,인증서 신뢰 목록을 인증서 저장소로부터 파일로 내보내는 것을 도와줄겁니다.",
-1, 115,33,195,16
LTEXT " 인증서는 당신이나 당신이 통신에 사용하는 컴퓨터를 신원보증하는 데 사용됩니다. 또한 메세지에 사인하고 인증하는 데도 사용됩니다. 인증서 보관소는 인증서, 인증서 파기 목록, 인증서 신뢰 목록의 저장소입니다..",
-1, 115,56,195,40
LTEXT "계속 하실려면, <다음>을 클릭하십시오.",
-1, 115,103,195,8
END
IDD_EXPORT_PRIVATE_KEY DIALOG DISCARDABLE 0,0,317,143
CAPTION "인증서 내보내기 마법사"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "당신이 개인 키를 내보내기를 선택하면, 당신은 다음 페이지에서 개인 키를 보호할 암호를 입력하게 될 것입니다.", -1, 21,1,195,23
LTEXT "개인 키를 내보내기를 원합니까?", -1, 21,24,195,15
AUTORADIOBUTTON "예(&Y), 개인 키 내보내기",
IDC_EXPORT_PRIVATE_KEY_YES, 31,36,200,12, BS_AUTORADIOBUTTON|WS_TABSTOP
AUTORADIOBUTTON "아니오(&O), 개인 키 안 내보내기",
IDC_EXPORT_PRIVATE_KEY_NO, 31,48,200,12, BS_AUTORADIOBUTTON
LTEXT "", IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE, 21,60,200,24
END
IDD_EXPORT_PASSWORD DIALOG DISCARDABLE 0,0,317,143
CAPTION "인증서 내보내기 마법사"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "암호(&P):", -1, 21,1,195,10
EDITTEXT IDC_EXPORT_PASSWORD, 21,11,208,14, ES_AUTOHSCROLL|WS_TABSTOP
LTEXT "암호 확인(&C):", -1, 21,35,195,10
EDITTEXT IDC_EXPORT_PASSWORD_CONFIRM, 21,45,208,14, ES_AUTOHSCROLL|WS_TABSTOP
END
IDD_EXPORT_FORMAT DIALOG DISCARDABLE 0,0,317,143
CAPTION "인증서 내보내기 마법사"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "사용할 파일 형식 선택:", -1, 21,1,195,10
AUTORADIOBUTTON "&DER-암호화된 X.509 (.cer)",
IDC_EXPORT_FORMAT_DER, 31,18,200,12, BS_AUTORADIOBUTTON|WS_TABSTOP
AUTORADIOBUTTON "Ba&se64-암호화된 X.509 (.cer):",
IDC_EXPORT_FORMAT_BASE64, 31,30,200,12, BS_AUTORADIOBUTTON
AUTORADIOBUTTON "암호 메시지 문법 표준/PKCS #7 메시지(&C) (.p7b)",
IDC_EXPORT_FORMAT_CMS, 31,42,200,12, BS_AUTORADIOBUTTON
CHECKBOX "가능한 인증서 경로에 있는 모든 인증서 포함(&I)",
IDC_EXPORT_CMS_INCLUDE_CHAIN, 44,57,200,8, BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
AUTORADIOBUTTON "개인 정보 교환(&P)/PKCS #12 (.pfx)",
IDC_EXPORT_FORMAT_PFX, 31,72,200,12, BS_AUTORADIOBUTTON|WS_DISABLED
CHECKBOX "가능한 인증서 경로에 있는 모든 인증서 포함(&U)",
IDC_EXPORT_PFX_INCLUDE_CHAIN, 44,87,200,8, BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
CHECKBOX "강한 암호화 가능(&E)",
IDC_EXPORT_PFX_STRONG_ENCRYPTION, 44,102,200,8,
BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
CHECKBOX "내보내기가 성공하면 개인 키 지우기(&K)",
IDC_EXPORT_PFX_DELETE_PRIVATE_KEY, 44,117,200,8,
BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
END
IDD_EXPORT_FILE DIALOG DISCARDABLE 0,0,317,143
CAPTION "인증서 내보내기 마법사"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "파일 이름(&F):", -1, 21,1,195,10
EDITTEXT IDC_EXPORT_FILENAME, 21,11,208,14, ES_AUTOHSCROLL|WS_TABSTOP
PUSHBUTTON "찾기(&R)...", IDC_EXPORT_BROWSE_FILE, 236,11,60,14
END
IDD_EXPORT_FINISH DIALOG DISCARDABLE 0,0,317,143
CAPTION "인증서 내보내기 마법사"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "인증서 내보내기 마법서 완료하는 중", IDC_EXPORT_TITLE,
115,1,195,40
LTEXT "당신은 인증서 내보내기 마법를 완료하는 데 성공하였습니다.",
-1, 115,33,195,24
LTEXT "당신은 다음 설정을 지정했습니다:",
-1, 115,57,195,12
CONTROL "", IDC_EXPORT_SETTINGS, "SysListView32",
LVS_REPORT|LVS_NOCOLUMNHEADER|LVS_SINGLESEL|WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER,
115,67,174,100
END

View file

@ -160,6 +160,13 @@
#define IDS_NO 1217
#define IDS_EXPORT_SUCCEEDED 1218
#define IDS_EXPORT_FAILED 1219
#define IDS_EXPORT_PRIVATE_KEY_TITLE 1220
#define IDS_EXPORT_PRIVATE_KEY_SUBTITLE 1221
#define IDS_EXPORT_PASSWORD_TITLE 1222
#define IDS_EXPORT_PASSWORD_SUBTITLE 1223
#define IDS_EXPORT_PASSWORD_MISMATCH 1224
#define IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE 1225
#define IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE 1226
#define IDD_GENERAL 100
#define IDD_DETAIL 101
@ -175,9 +182,11 @@
#define IDD_CERT_MGR 111
#define IDD_CERT_MGR_ADVANCED 112
#define IDD_EXPORT_WELCOME 113
#define IDD_EXPORT_FORMAT 114
#define IDD_EXPORT_FILE 115
#define IDD_EXPORT_FINISH 116
#define IDD_EXPORT_PRIVATE_KEY 114
#define IDD_EXPORT_PASSWORD 115
#define IDD_EXPORT_FORMAT 116
#define IDD_EXPORT_FILE 117
#define IDD_EXPORT_FINISH 118
#define IDB_SMALL_ICONS 200
#define IDB_CERT 201
@ -253,5 +262,10 @@
#define IDC_EXPORT_FILENAME 2909
#define IDC_EXPORT_BROWSE_FILE 2910
#define IDC_EXPORT_SETTINGS 2911
#define IDC_EXPORT_PRIVATE_KEY_YES 2912
#define IDC_EXPORT_PRIVATE_KEY_NO 2913
#define IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE 2914
#define IDC_EXPORT_PASSWORD 2915
#define IDC_EXPORT_PASSWORD_CONFIRM 2916
#endif /* ndef __CRYPTUIRES_H_ */

View file

@ -1076,25 +1076,24 @@ static LRESULT CALLBACK cert_mgr_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
HWND tab = GetDlgItem(hwnd, IDC_MGR_STORES);
data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData));
if (data)
if (!data)
return 0;
data->imageList = ImageList_Create(16, 16, ILC_COLOR4 | ILC_MASK, 2, 0);
if (data->imageList)
{
data->imageList = ImageList_Create(16, 16, ILC_COLOR4 | ILC_MASK,
2, 0);
if (data->imageList)
{
HBITMAP bmp;
COLORREF backColor = RGB(255, 0, 255);
HBITMAP bmp;
COLORREF backColor = RGB(255, 0, 255);
bmp = LoadBitmapW(hInstance, MAKEINTRESOURCEW(IDB_SMALL_ICONS));
ImageList_AddMasked(data->imageList, bmp, backColor);
DeleteObject(bmp);
ImageList_SetBkColor(data->imageList, CLR_NONE);
SendMessageW(GetDlgItem(hwnd, IDC_MGR_CERTS), LVM_SETIMAGELIST,
LVSIL_SMALL, (LPARAM)data->imageList);
}
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
data->title = pCryptUICertMgr->pwszTitle;
bmp = LoadBitmapW(hInstance, MAKEINTRESOURCEW(IDB_SMALL_ICONS));
ImageList_AddMasked(data->imageList, bmp, backColor);
DeleteObject(bmp);
ImageList_SetBkColor(data->imageList, CLR_NONE);
SendMessageW(GetDlgItem(hwnd, IDC_MGR_CERTS), LVM_SETIMAGELIST,
LVSIL_SMALL, (LPARAM)data->imageList);
}
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
data->title = pCryptUICertMgr->pwszTitle;
initialize_purpose_selection(hwnd);
add_cert_columns(hwnd);
if (pCryptUICertMgr->pwszTitle)
@ -5516,8 +5515,11 @@ struct ExportWizData
HFONT titleFont;
DWORD dwFlags;
LPCWSTR pwszWizardTitle;
PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo;
CRYPTUI_WIZ_EXPORT_INFO exportInfo;
CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo;
BOOL freePassword;
PCRYPT_KEY_PROV_INFO keyProvInfo;
BOOL deleteKeys;
LPWSTR fileName;
HANDLE file;
BOOL success;
@ -5567,6 +5569,141 @@ static LRESULT CALLBACK export_welcome_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
return ret;
}
static PCRYPT_KEY_PROV_INFO export_get_private_key_info(PCCERT_CONTEXT cert)
{
PCRYPT_KEY_PROV_INFO info = NULL;
DWORD size;
if (CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
NULL, &size))
{
info = HeapAlloc(GetProcessHeap(), 0, size);
if (info)
{
if (!CertGetCertificateContextProperty(cert,
CERT_KEY_PROV_INFO_PROP_ID, info, &size))
{
HeapFree(GetProcessHeap(), 0, info);
info = NULL;
}
}
}
return info;
}
static BOOL export_acquire_private_key(PCRYPT_KEY_PROV_INFO info,
HCRYPTPROV *phProv)
{
BOOL ret;
ret = CryptAcquireContextW(phProv, info->pwszContainerName,
info->pwszProvName, info->dwProvType, 0);
if (ret)
{
DWORD i;
for (i = 0; i < info->cProvParam; i++)
CryptSetProvParam(*phProv, info->rgProvParam[i].dwParam,
info->rgProvParam[i].pbData, info->rgProvParam[i].dwFlags);
}
return ret;
}
static BOOL export_is_key_exportable(HCRYPTPROV hProv, DWORD keySpec)
{
BOOL ret;
HCRYPTKEY key;
if ((ret = CryptGetUserKey(hProv, keySpec, &key)))
{
DWORD permissions, size = sizeof(permissions);
if ((ret = CryptGetKeyParam(key, KP_PERMISSIONS, (BYTE *)&permissions,
&size, 0)) && !(permissions & CRYPT_EXPORT))
ret = FALSE;
CryptDestroyKey(key);
}
return ret;
}
static LRESULT CALLBACK export_private_key_dlg_proc(HWND hwnd, UINT msg,
WPARAM wp, LPARAM lp)
{
LRESULT ret = 0;
struct ExportWizData *data;
switch (msg)
{
case WM_INITDIALOG:
{
PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
PCRYPT_KEY_PROV_INFO info;
HCRYPTPROV hProv = 0;
int errorID = 0;
data = (struct ExportWizData *)page->lParam;
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
/* Get enough information about a key to see whether it's exportable.
*/
if (!(info = export_get_private_key_info(
data->exportInfo.u.pCertContext)))
errorID = IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE;
else if (!export_acquire_private_key(info, &hProv))
errorID = IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE;
else if (!export_is_key_exportable(hProv, info->dwKeySpec))
errorID = IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE;
if (errorID)
{
WCHAR error[MAX_STRING_LEN];
LoadStringW(hInstance, errorID, error,
sizeof(error) / sizeof(error[0]));
SendMessageW(GetDlgItem(hwnd, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE),
WM_SETTEXT, 0, (LPARAM)error);
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_PRIVATE_KEY_YES), FALSE);
}
else
data->keyProvInfo = info;
if (hProv)
CryptReleaseContext(hProv, 0);
SendMessageW(GetDlgItem(hwnd, IDC_EXPORT_PRIVATE_KEY_NO), BM_CLICK,
0, 0);
break;
}
case WM_NOTIFY:
{
NMHDR *hdr = (NMHDR *)lp;
switch (hdr->code)
{
case PSN_SETACTIVE:
PostMessageW(GetParent(hwnd), PSM_SETWIZBUTTONS, 0,
PSWIZB_BACK | PSWIZB_NEXT);
ret = TRUE;
break;
case PSN_WIZNEXT:
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
if (IsDlgButtonChecked(hwnd, IDC_EXPORT_PRIVATE_KEY_NO))
{
data->contextInfo.dwExportFormat =
CRYPTUI_WIZ_EXPORT_FORMAT_DER;
data->contextInfo.fExportPrivateKeys = FALSE;
}
else
{
data->contextInfo.dwExportFormat =
CRYPTUI_WIZ_EXPORT_FORMAT_PFX;
data->contextInfo.fExportPrivateKeys = TRUE;
}
break;
}
break;
}
}
return ret;
}
static BOOL export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo)
{
BOOL ret = FALSE;
@ -5585,6 +5722,41 @@ static BOOL export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo)
return ret;
}
static void export_format_enable_controls(HWND hwnd, struct ExportWizData *data)
{
int defaultFormatID;
switch (data->contextInfo.dwExportFormat)
{
case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64:
defaultFormatID = IDC_EXPORT_FORMAT_BASE64;
break;
case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7:
defaultFormatID = IDC_EXPORT_FORMAT_CMS;
break;
case CRYPTUI_WIZ_EXPORT_FORMAT_PFX:
defaultFormatID = IDC_EXPORT_FORMAT_PFX;
break;
default:
defaultFormatID = IDC_EXPORT_FORMAT_DER;
}
SendMessageW(GetDlgItem(hwnd, defaultFormatID), BM_CLICK, 0, 0);
if (defaultFormatID == IDC_EXPORT_FORMAT_PFX)
{
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_DER), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_BASE64), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_CMS), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_PFX), TRUE);
}
else
{
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_DER), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_BASE64), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_CMS), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_PFX), FALSE);
}
}
static LRESULT CALLBACK export_format_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
LPARAM lp)
{
@ -5596,32 +5768,10 @@ static LRESULT CALLBACK export_format_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
case WM_INITDIALOG:
{
PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
int defaultFormatID;
BOOL hasPrivateKey;
data = (struct ExportWizData *)page->lParam;
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
hasPrivateKey = export_info_has_private_key(data->pExportInfo);
if (hasPrivateKey)
EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_PFX), TRUE);
switch (data->contextInfo.dwExportFormat)
{
case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64:
defaultFormatID = IDC_EXPORT_FORMAT_BASE64;
break;
case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7:
defaultFormatID = IDC_EXPORT_FORMAT_CMS;
break;
case CRYPTUI_WIZ_EXPORT_FORMAT_PFX:
if (hasPrivateKey)
defaultFormatID = IDC_EXPORT_FORMAT_PFX;
else
defaultFormatID = IDC_EXPORT_FORMAT_DER;
break;
default:
defaultFormatID = IDC_EXPORT_FORMAT_DER;
}
SendMessageW(GetDlgItem(hwnd, defaultFormatID), BM_CLICK, 0, 0);
export_format_enable_controls(hwnd, data);
break;
}
case WM_NOTIFY:
@ -5633,10 +5783,14 @@ static LRESULT CALLBACK export_format_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
case PSN_SETACTIVE:
PostMessageW(GetParent(hwnd), PSM_SETWIZBUTTONS, 0,
PSWIZB_BACK | PSWIZB_NEXT);
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
export_format_enable_controls(hwnd, data);
ret = TRUE;
break;
case PSN_WIZNEXT:
{
BOOL skipPasswordPage = TRUE;
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
if (IsDlgButtonChecked(hwnd, IDC_EXPORT_FORMAT_DER))
data->contextInfo.dwExportFormat =
@ -5661,8 +5815,12 @@ static LRESULT CALLBACK export_format_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
if (IsDlgButtonChecked(hwnd, IDC_EXPORT_PFX_STRONG_ENCRYPTION))
data->contextInfo.fStrongEncryption = TRUE;
if (IsDlgButtonChecked(hwnd, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY))
data->contextInfo.fExportPrivateKeys = TRUE;
data->deleteKeys = TRUE;
skipPasswordPage = FALSE;
}
SetWindowLongPtrW(hwnd, DWLP_MSGRESULT,
skipPasswordPage ? IDD_EXPORT_FILE : 0);
ret = 1;
break;
}
}
@ -5705,6 +5863,111 @@ static LRESULT CALLBACK export_format_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
return ret;
}
static void export_password_mismatch(HWND hwnd, struct ExportWizData *data)
{
WCHAR title[MAX_STRING_LEN], error[MAX_STRING_LEN];
LPCWSTR pTitle;
if (data->pwszWizardTitle)
pTitle = data->pwszWizardTitle;
else
{
LoadStringW(hInstance, IDS_EXPORT_WIZARD, title,
sizeof(title) / sizeof(title[0]));
pTitle = title;
}
LoadStringW(hInstance, IDS_EXPORT_PASSWORD_MISMATCH, error,
sizeof(error) / sizeof(error[0]));
MessageBoxW(hwnd, error, pTitle, MB_ICONERROR | MB_OK);
SetFocus(GetDlgItem(hwnd, IDC_EXPORT_PASSWORD));
}
static LRESULT CALLBACK export_password_dlg_proc(HWND hwnd, UINT msg,
WPARAM wp, LPARAM lp)
{
LRESULT ret = 0;
struct ExportWizData *data;
switch (msg)
{
case WM_INITDIALOG:
{
PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
data = (struct ExportWizData *)page->lParam;
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
break;
}
case WM_NOTIFY:
{
NMHDR *hdr = (NMHDR *)lp;
switch (hdr->code)
{
case PSN_SETACTIVE:
PostMessageW(GetParent(hwnd), PSM_SETWIZBUTTONS, 0,
PSWIZB_BACK | PSWIZB_NEXT);
ret = TRUE;
break;
case PSN_WIZNEXT:
{
HWND passwordEdit = GetDlgItem(hwnd, IDC_EXPORT_PASSWORD);
HWND passwordConfirmEdit = GetDlgItem(hwnd,
IDC_EXPORT_PASSWORD_CONFIRM);
DWORD passwordLen = SendMessageW(passwordEdit, WM_GETTEXTLENGTH,
0, 0);
DWORD passwordConfirmLen = SendMessageW(passwordConfirmEdit,
WM_GETTEXTLENGTH, 0, 0);
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
if (!passwordLen && !passwordConfirmLen)
data->contextInfo.pwszPassword = NULL;
else if (passwordLen != passwordConfirmLen)
{
export_password_mismatch(hwnd, data);
SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, 1);
ret = 1;
}
else
{
LPWSTR password = HeapAlloc(GetProcessHeap(), 0,
(passwordLen + 1) * sizeof(WCHAR));
LPWSTR passwordConfirm = HeapAlloc(GetProcessHeap(), 0,
(passwordConfirmLen + 1) * sizeof(WCHAR));
BOOL freePassword = TRUE;
if (password && passwordConfirm)
{
SendMessageW(passwordEdit, WM_GETTEXT, passwordLen + 1,
(LPARAM)password);
SendMessageW(passwordConfirmEdit, WM_GETTEXT,
passwordConfirmLen + 1, (LPARAM)passwordConfirm);
if (strcmpW(password, passwordConfirm))
{
export_password_mismatch(hwnd, data);
SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, 1);
ret = 1;
}
else
{
data->contextInfo.pwszPassword = password;
freePassword = FALSE;
data->freePassword = TRUE;
}
}
if (freePassword)
HeapFree(GetProcessHeap(), 0, password);
HeapFree(GetProcessHeap(), 0, passwordConfirm);
}
break;
}
}
break;
}
}
return ret;
}
static LPWSTR export_append_extension(struct ExportWizData *data,
LPWSTR fileName)
{
@ -5727,7 +5990,7 @@ static LPWSTR export_append_extension(struct ExportWizData *data,
extension = pfx;
break;
default:
switch (data->pExportInfo->dwSubjectChoice)
switch (data->exportInfo.dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
extension = crl;
@ -5926,9 +6189,9 @@ static LRESULT CALLBACK export_file_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
data = (struct ExportWizData *)page->lParam;
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
if (data->pExportInfo->pwszExportFileName)
if (data->exportInfo.pwszExportFileName)
SendMessageW(GetDlgItem(hwnd, IDC_EXPORT_FILENAME), WM_SETTEXT, 0,
(LPARAM)data->pExportInfo->pwszExportFileName);
(LPARAM)data->exportInfo.pwszExportFileName);
break;
}
case WM_NOTIFY:
@ -5937,6 +6200,15 @@ static LRESULT CALLBACK export_file_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
switch (hdr->code)
{
case PSN_WIZBACK:
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
if (data->contextInfo.dwExportFormat !=
CRYPTUI_WIZ_EXPORT_FORMAT_PFX)
{
SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, IDD_EXPORT_FORMAT);
ret = 1;
}
break;
case PSN_WIZNEXT:
{
HWND fileNameEdit = GetDlgItem(hwnd, IDC_EXPORT_FILENAME);
@ -6006,7 +6278,7 @@ static LRESULT CALLBACK export_file_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = make_export_file_filter(
data->contextInfo.dwExportFormat,
data->pExportInfo->dwSubjectChoice);
data->exportInfo.dwSubjectChoice);
ofn.lpstrFile = fileBuf;
ofn.nMaxFile = sizeof(fileBuf) / sizeof(fileBuf[0]);
fileBuf[0] = 0;
@ -6043,7 +6315,7 @@ static void show_export_details(HWND lv, struct ExportWizData *data)
}
item.pszText = text;
switch (data->pExportInfo->dwSubjectChoice)
switch (data->exportInfo.dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT:
@ -6084,7 +6356,7 @@ static void show_export_details(HWND lv, struct ExportWizData *data)
SendMessageW(lv, LVM_INSERTITEMW, 0, (LPARAM)&item);
item.iSubItem = 1;
switch (data->pExportInfo->dwSubjectChoice)
switch (data->exportInfo.dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
contentID = IDS_EXPORT_FILTER_CRL;
@ -6227,8 +6499,140 @@ static BOOL save_serialized_store(HANDLE file, HCERTSTORE store)
CERT_STORE_SAVE_AS_STORE, CERT_STORE_SAVE_TO_FILE, file, 0);
}
static BOOL save_pfx(HANDLE file, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo,
PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo,
PCRYPT_KEY_PROV_INFO keyProvInfo, BOOL deleteKeys)
{
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING,
0, CERT_STORE_CREATE_NEW_FLAG, NULL);
BOOL ret = FALSE;
if (store)
{
CRYPT_DATA_BLOB pfxBlob = { 0, NULL };
PCCERT_CONTEXT cert = NULL;
BOOL freeKeyProvInfo = FALSE;
if (pContextInfo->fExportChain)
{
HCERTCHAINENGINE engine = NULL;
if (pExportInfo->cStores)
{
CERT_CHAIN_ENGINE_CONFIG config;
memset(&config, 0, sizeof(config));
config.cbSize = sizeof(config);
config.cAdditionalStore = pExportInfo->cStores;
config.rghAdditionalStore = pExportInfo->rghStores;
ret = CertCreateCertificateChainEngine(&config, &engine);
}
else
ret = TRUE;
if (ret)
{
CERT_CHAIN_PARA chainPara;
PCCERT_CHAIN_CONTEXT chain;
memset(&chainPara, 0, sizeof(chainPara));
chainPara.cbSize = sizeof(chainPara);
ret = CertGetCertificateChain(engine,
pExportInfo->u.pCertContext, NULL, NULL, &chainPara, 0, NULL,
&chain);
if (ret)
{
DWORD i, j;
for (i = 0; ret && i < chain->cChain; i++)
for (j = 0; ret && j < chain->rgpChain[i]->cElement;
j++)
{
if (i == 0 && j == 0)
ret = CertAddCertificateContextToStore(store,
chain->rgpChain[i]->rgpElement[j]->pCertContext,
CERT_STORE_ADD_ALWAYS, &cert);
else
ret = CertAddCertificateContextToStore(store,
chain->rgpChain[i]->rgpElement[j]->pCertContext,
CERT_STORE_ADD_ALWAYS, NULL);
}
CertFreeCertificateChain(chain);
}
}
if (engine)
CertFreeCertificateChainEngine(engine);
}
else
ret = CertAddCertificateContextToStore(store,
pExportInfo->u.pCertContext, CERT_STORE_ADD_ALWAYS, &cert);
/* Copy private key info to newly created cert, so it'll get exported
* along with the cert.
*/
if (ret && pContextInfo->fExportPrivateKeys)
{
if (keyProvInfo)
ret = CertSetCertificateContextProperty(cert,
CERT_KEY_PROV_INFO_PROP_ID, 0, keyProvInfo);
else
{
if (!(keyProvInfo = export_get_private_key_info(cert)))
ret = FALSE;
else
{
ret = CertSetCertificateContextProperty(cert,
CERT_KEY_PROV_INFO_PROP_ID, 0, keyProvInfo);
freeKeyProvInfo = TRUE;
}
}
}
if (ret)
{
DWORD exportFlags =
REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | EXPORT_PRIVATE_KEYS;
ret = PFXExportCertStore(store, &pfxBlob,
pContextInfo->pwszPassword, exportFlags);
if (ret)
{
pfxBlob.pbData = HeapAlloc(GetProcessHeap(), 0, pfxBlob.cbData);
if (pfxBlob.pbData)
{
ret = PFXExportCertStore(store, &pfxBlob,
pContextInfo->pwszPassword, exportFlags);
if (ret)
{
DWORD bytesWritten;
ret = WriteFile(file, pfxBlob.pbData, pfxBlob.cbData,
&bytesWritten, NULL);
}
}
else
{
SetLastError(ERROR_OUTOFMEMORY);
ret = FALSE;
}
}
}
if (ret && deleteKeys)
{
HCRYPTPROV prov;
CryptAcquireContextW(&prov, keyProvInfo->pwszContainerName,
keyProvInfo->pwszProvName, keyProvInfo->dwProvType,
CRYPT_DELETEKEYSET);
}
if (freeKeyProvInfo)
HeapFree(GetProcessHeap(), 0, keyProvInfo);
CertFreeCertificateContext(cert);
CertCloseStore(store, 0);
}
return ret;
}
static BOOL do_export(HANDLE file, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo,
PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo)
PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo,
PCRYPT_KEY_PROV_INFO keyProvInfo, BOOL deleteKeys)
{
BOOL ret;
@ -6272,8 +6676,8 @@ static BOOL do_export(HANDLE file, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo,
pContextInfo->fExportChain);
break;
case CRYPTUI_WIZ_EXPORT_FORMAT_PFX:
FIXME("unimplemented for PFX\n");
ret = FALSE;
ret = save_pfx(file, pExportInfo, pContextInfo, keyProvInfo,
deleteKeys);
break;
default:
SetLastError(E_FAIL);
@ -6336,8 +6740,8 @@ static LRESULT CALLBACK export_finish_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
DWORD mbFlags;
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
if ((data->success = do_export(data->file, data->pExportInfo,
&data->contextInfo)))
if ((data->success = do_export(data->file, &data->exportInfo,
&data->contextInfo, data->keyProvInfo, data->deleteKeys)))
{
messageID = IDS_EXPORT_SUCCEEDED;
mbFlags = MB_OK;
@ -6371,24 +6775,33 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
LPCWSTR pwszWizardTitle, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo, void *pvoid)
{
PROPSHEETHEADERW hdr;
PROPSHEETPAGEW pages[4];
PROPSHEETPAGEW pages[6];
struct ExportWizData data;
int nPages = 0;
BOOL showFormatPage = TRUE;
BOOL hasPrivateKey, showFormatPage = TRUE;
INT_PTR l;
data.dwFlags = dwFlags;
data.pwszWizardTitle = pwszWizardTitle;
data.pExportInfo = pExportInfo;
memset(&data.exportInfo, 0, sizeof(data.exportInfo));
memcpy(&data.exportInfo, pExportInfo,
min(sizeof(data.exportInfo), pExportInfo->dwSize));
if (pExportInfo->dwSize > sizeof(data.exportInfo))
data.exportInfo.dwSize = sizeof(data.exportInfo);
data.contextInfo.dwSize = sizeof(data.contextInfo);
data.contextInfo.dwExportFormat = CRYPTUI_WIZ_EXPORT_FORMAT_DER;
data.contextInfo.fExportChain = FALSE;
data.contextInfo.fStrongEncryption = FALSE;
data.contextInfo.fExportPrivateKeys = FALSE;
data.contextInfo.pwszPassword = NULL;
data.freePassword = FALSE;
if (pExportInfo->dwSubjectChoice == CRYPTUI_WIZ_EXPORT_CERT_CONTEXT &&
pvoid)
memcpy(&data.contextInfo, pvoid,
min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO)pvoid)->dwSize,
sizeof(data.contextInfo)));
data.keyProvInfo = NULL;
data.deleteKeys = FALSE;
data.fileName = NULL;
data.file = INVALID_HANDLE_VALUE;
data.success = FALSE;
@ -6403,6 +6816,7 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
pages[nPages].lParam = (LPARAM)&data;
nPages++;
hasPrivateKey = export_info_has_private_key(pExportInfo);
switch (pExportInfo->dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
@ -6420,6 +6834,21 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
data.contextInfo.dwExportFormat = CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7;
break;
}
if (hasPrivateKey && showFormatPage)
{
pages[nPages].dwSize = sizeof(pages[0]);
pages[nPages].hInstance = hInstance;
pages[nPages].u.pszTemplate = MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY);
pages[nPages].pfnDlgProc = export_private_key_dlg_proc;
pages[nPages].dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
pages[nPages].pszHeaderTitle =
MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE);
pages[nPages].pszHeaderSubTitle =
MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE);
pages[nPages].lParam = (LPARAM)&data;
nPages++;
}
if (showFormatPage)
{
pages[nPages].dwSize = sizeof(pages[0]);
@ -6434,6 +6863,20 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
pages[nPages].lParam = (LPARAM)&data;
nPages++;
}
if (hasPrivateKey && showFormatPage)
{
pages[nPages].dwSize = sizeof(pages[0]);
pages[nPages].hInstance = hInstance;
pages[nPages].u.pszTemplate = MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD);
pages[nPages].pfnDlgProc = export_password_dlg_proc;
pages[nPages].dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
pages[nPages].pszHeaderTitle =
MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE);
pages[nPages].pszHeaderSubTitle =
MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE);
pages[nPages].lParam = (LPARAM)&data;
nPages++;
}
pages[nPages].dwSize = sizeof(pages[0]);
pages[nPages].hInstance = hInstance;
@ -6468,11 +6911,21 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
hdr.nPages = nPages;
hdr.u4.pszbmWatermark = MAKEINTRESOURCEW(IDB_CERT_WATERMARK);
hdr.u5.pszbmHeader = MAKEINTRESOURCEW(IDB_CERT_HEADER);
PropertySheetW(&hdr);
l = PropertySheetW(&hdr);
DeleteObject(data.titleFont);
if (data.freePassword)
HeapFree(GetProcessHeap(), 0,
(LPWSTR)data.contextInfo.pwszPassword);
HeapFree(GetProcessHeap(), 0, data.keyProvInfo);
CloseHandle(data.file);
HeapFree(GetProcessHeap(), 0, data.fileName);
return data.success;
if (l == 0)
{
SetLastError(ERROR_CANCELLED);
return FALSE;
}
else
return data.success;
}
BOOL WINAPI CryptUIWizExport(DWORD dwFlags, HWND hwndParent,
@ -6494,7 +6947,7 @@ BOOL WINAPI CryptUIWizExport(DWORD dwFlags, HWND hwndParent,
if (file != INVALID_HANDLE_VALUE)
{
ret = do_export(file, pExportInfo, pvoid);
ret = do_export(file, pExportInfo, pvoid, NULL, FALSE);
CloseHandle(file);
}
else