forked from Mirrors/wine-wine
cryptui: Ensure a certificate's private key is exportable before allowing it to be selected for export.
parent
fd3cd61b5d
commit
af87814ac6
|
@ -166,6 +166,8 @@ STRINGTABLE DISCARDABLE
|
||||||
IDS_EXPORT_PASSWORD_TITLE "Enter Password"
|
IDS_EXPORT_PASSWORD_TITLE "Enter Password"
|
||||||
IDS_EXPORT_PASSWORD_SUBTITLE "You may password-protect a private key."
|
IDS_EXPORT_PASSWORD_SUBTITLE "You may password-protect a private key."
|
||||||
IDS_EXPORT_PASSWORD_MISMATCH "The passwords do not match."
|
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
|
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
|
IDC_EXPORT_PRIVATE_KEY_YES, 31,36,200,12, BS_AUTORADIOBUTTON|WS_TABSTOP
|
||||||
AUTORADIOBUTTON "N&o, do not export the private key",
|
AUTORADIOBUTTON "N&o, do not export the private key",
|
||||||
IDC_EXPORT_PRIVATE_KEY_NO, 31,48,200,12, BS_AUTORADIOBUTTON
|
IDC_EXPORT_PRIVATE_KEY_NO, 31,48,200,12, BS_AUTORADIOBUTTON
|
||||||
|
LTEXT "", IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE, 21,60,200,24
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_EXPORT_PASSWORD DIALOG DISCARDABLE 0,0,317,143
|
IDD_EXPORT_PASSWORD DIALOG DISCARDABLE 0,0,317,143
|
||||||
|
|
|
@ -165,6 +165,8 @@
|
||||||
#define IDS_EXPORT_PASSWORD_TITLE 1222
|
#define IDS_EXPORT_PASSWORD_TITLE 1222
|
||||||
#define IDS_EXPORT_PASSWORD_SUBTITLE 1223
|
#define IDS_EXPORT_PASSWORD_SUBTITLE 1223
|
||||||
#define IDS_EXPORT_PASSWORD_MISMATCH 1224
|
#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_GENERAL 100
|
||||||
#define IDD_DETAIL 101
|
#define IDD_DETAIL 101
|
||||||
|
@ -262,7 +264,8 @@
|
||||||
#define IDC_EXPORT_SETTINGS 2911
|
#define IDC_EXPORT_SETTINGS 2911
|
||||||
#define IDC_EXPORT_PRIVATE_KEY_YES 2912
|
#define IDC_EXPORT_PRIVATE_KEY_YES 2912
|
||||||
#define IDC_EXPORT_PRIVATE_KEY_NO 2913
|
#define IDC_EXPORT_PRIVATE_KEY_NO 2913
|
||||||
#define IDC_EXPORT_PASSWORD 2914
|
#define IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE 2914
|
||||||
#define IDC_EXPORT_PASSWORD_CONFIRM 2915
|
#define IDC_EXPORT_PASSWORD 2915
|
||||||
|
#define IDC_EXPORT_PASSWORD_CONFIRM 2916
|
||||||
|
|
||||||
#endif /* ndef __CRYPTUIRES_H_ */
|
#endif /* ndef __CRYPTUIRES_H_ */
|
||||||
|
|
|
@ -5518,6 +5518,7 @@ struct ExportWizData
|
||||||
CRYPTUI_WIZ_EXPORT_INFO exportInfo;
|
CRYPTUI_WIZ_EXPORT_INFO exportInfo;
|
||||||
CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo;
|
CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo;
|
||||||
BOOL freePassword;
|
BOOL freePassword;
|
||||||
|
PCRYPT_KEY_PROV_INFO keyProvInfo;
|
||||||
LPWSTR fileName;
|
LPWSTR fileName;
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
BOOL success;
|
BOOL success;
|
||||||
|
@ -5567,6 +5568,63 @@ static LRESULT CALLBACK export_welcome_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
|
||||||
return ret;
|
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,
|
static LRESULT CALLBACK export_private_key_dlg_proc(HWND hwnd, UINT msg,
|
||||||
WPARAM wp, LPARAM lp)
|
WPARAM wp, LPARAM lp)
|
||||||
{
|
{
|
||||||
|
@ -5578,9 +5636,36 @@ static LRESULT CALLBACK export_private_key_dlg_proc(HWND hwnd, UINT msg,
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
{
|
{
|
||||||
PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
|
PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
|
||||||
|
PCRYPT_KEY_PROV_INFO info;
|
||||||
|
HCRYPTPROV hProv = 0;
|
||||||
|
int errorID = 0;
|
||||||
|
|
||||||
data = (struct ExportWizData *)page->lParam;
|
data = (struct ExportWizData *)page->lParam;
|
||||||
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
|
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,
|
SendMessageW(GetDlgItem(hwnd, IDC_EXPORT_PRIVATE_KEY_NO), BM_CLICK,
|
||||||
0, 0);
|
0, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -6671,6 +6756,7 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
|
||||||
memcpy(&data.contextInfo, pvoid,
|
memcpy(&data.contextInfo, pvoid,
|
||||||
min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO)pvoid)->dwSize,
|
min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO)pvoid)->dwSize,
|
||||||
sizeof(data.contextInfo)));
|
sizeof(data.contextInfo)));
|
||||||
|
data.keyProvInfo = NULL;
|
||||||
data.fileName = NULL;
|
data.fileName = NULL;
|
||||||
data.file = INVALID_HANDLE_VALUE;
|
data.file = INVALID_HANDLE_VALUE;
|
||||||
data.success = FALSE;
|
data.success = FALSE;
|
||||||
|
@ -6785,6 +6871,7 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent,
|
||||||
if (data.freePassword)
|
if (data.freePassword)
|
||||||
HeapFree(GetProcessHeap(), 0,
|
HeapFree(GetProcessHeap(), 0,
|
||||||
(LPWSTR)data.contextInfo.pwszPassword);
|
(LPWSTR)data.contextInfo.pwszPassword);
|
||||||
|
HeapFree(GetProcessHeap(), 0, data.keyProvInfo);
|
||||||
CloseHandle(data.file);
|
CloseHandle(data.file);
|
||||||
HeapFree(GetProcessHeap(), 0, data.fileName);
|
HeapFree(GetProcessHeap(), 0, data.fileName);
|
||||||
if (l == 0)
|
if (l == 0)
|
||||||
|
|
Loading…
Reference in New Issue