cryptui: Ensure a certificate's private key is exportable before allowing it to be selected for export.

This commit is contained in:
Juan Lang 2009-02-06 12:05:30 -08:00 committed by Alexandre Julliard
parent fd3cd61b5d
commit af87814ac6
3 changed files with 95 additions and 2 deletions

View File

@ -166,6 +166,8 @@ STRINGTABLE DISCARDABLE
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
@ -396,6 +398,7 @@ BEGIN
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

View File

@ -165,6 +165,8 @@
#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
@ -262,7 +264,8 @@
#define IDC_EXPORT_SETTINGS 2911
#define IDC_EXPORT_PRIVATE_KEY_YES 2912
#define IDC_EXPORT_PRIVATE_KEY_NO 2913
#define IDC_EXPORT_PASSWORD 2914
#define IDC_EXPORT_PASSWORD_CONFIRM 2915
#define IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE 2914
#define IDC_EXPORT_PASSWORD 2915
#define IDC_EXPORT_PASSWORD_CONFIRM 2916
#endif /* ndef __CRYPTUIRES_H_ */

View File

@ -5518,6 +5518,7 @@ struct ExportWizData
CRYPTUI_WIZ_EXPORT_INFO exportInfo;
CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo;
BOOL freePassword;
PCRYPT_KEY_PROV_INFO keyProvInfo;
LPWSTR fileName;
HANDLE file;
BOOL success;
@ -5567,6 +5568,63 @@ 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)
{
@ -5578,9 +5636,36 @@ static LRESULT CALLBACK export_private_key_dlg_proc(HWND hwnd, UINT 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;
@ -6671,6 +6756,7 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
memcpy(&data.contextInfo, pvoid,
min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO)pvoid)->dwSize,
sizeof(data.contextInfo)));
data.keyProvInfo = NULL;
data.fileName = NULL;
data.file = INVALID_HANDLE_VALUE;
data.success = FALSE;
@ -6785,6 +6871,7 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
if (data.freePassword)
HeapFree(GetProcessHeap(), 0,
(LPWSTR)data.contextInfo.pwszPassword);
HeapFree(GetProcessHeap(), 0, data.keyProvInfo);
CloseHandle(data.file);
HeapFree(GetProcessHeap(), 0, data.fileName);
if (l == 0)