Juan Lang : cryptui: Ensure a certificate' s private key is exportable before allowing it to be selected for export.
Alexandre Julliard
julliard at winehq.org
Mon Feb 9 10:29:21 CST 2009
Module: wine
Branch: master
Commit: af87814ac6552a2358e9df4a439bea765b4305be
URL: http://source.winehq.org/git/wine.git/?a=commit;h=af87814ac6552a2358e9df4a439bea765b4305be
Author: Juan Lang <juan.lang at gmail.com>
Date: Fri Feb 6 12:05:30 2009 -0800
cryptui: Ensure a certificate's private key is exportable before allowing it to be selected for export.
---
dlls/cryptui/cryptui_En.rc | 3 ++
dlls/cryptui/cryptuires.h | 7 +++-
dlls/cryptui/main.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/dlls/cryptui/cryptui_En.rc b/dlls/cryptui/cryptui_En.rc
index 8cabea4..c6d6559 100644
--- a/dlls/cryptui/cryptui_En.rc
+++ b/dlls/cryptui/cryptui_En.rc
@@ -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
diff --git a/dlls/cryptui/cryptuires.h b/dlls/cryptui/cryptuires.h
index e16bb21..b46ea4e 100644
--- a/dlls/cryptui/cryptuires.h
+++ b/dlls/cryptui/cryptuires.h
@@ -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_ */
diff --git a/dlls/cryptui/main.c b/dlls/cryptui/main.c
index 677bee4..620f53f 100644
--- a/dlls/cryptui/main.c
+++ b/dlls/cryptui/main.c
@@ -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)
More information about the wine-cvs
mailing list