cryptui: Ensure a certificate's private key is exportable before allowing it to be selected for export.
This commit is contained in:
parent
fd3cd61b5d
commit
af87814ac6
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue