diff options
Diffstat (limited to 'Swift/QtUI/CAPICertificateSelector.cpp')
-rw-r--r-- | Swift/QtUI/CAPICertificateSelector.cpp | 101 |
1 files changed, 57 insertions, 44 deletions
diff --git a/Swift/QtUI/CAPICertificateSelector.cpp b/Swift/QtUI/CAPICertificateSelector.cpp index 0d4768c..cc69956 100644 --- a/Swift/QtUI/CAPICertificateSelector.cpp +++ b/Swift/QtUI/CAPICertificateSelector.cpp @@ -6,94 +6,107 @@ #include <string> -#include "CAPICertificateSelector.h" +#include <Swift/QtUI/CAPICertificateSelector.h> #define SECURITY_WIN32 #include <Windows.h> #include <WinCrypt.h> #include <cryptuiapi.h> + #include <Swiften/StringCodecs/Hexify.h> #include <boost/algorithm/string.hpp> +#include <Swift/Controllers/Intl.h> +#include <Swift/QtUI/QtSwiftUtil.h> +#include <Swiften/Base/Log.h> namespace Swift { -#define cert_dlg_title L"TLS Client Certificate Selection" -#define cert_dlg_prompt L"Select a certificate to use for authentication" /////Hmm, maybe we should not exlude the "location" column -#define exclude_columns CRYPTUI_SELECT_LOCATION_COLUMN \ - |CRYPTUI_SELECT_INTENDEDUSE_COLUMN +#define exclude_columns CRYPTUI_SELECT_LOCATION_COLUMN | CRYPTUI_SELECT_INTENDEDUSE_COLUMN -// Size of the SHA1 hash -#define SHA1_HASH_LEN 20 +#define SHA1_HASH_LENGTH 20 static std::string getCertUri(PCCERT_CONTEXT cert, const char * cert_store_name) { - DWORD cbHash = SHA1_HASH_LEN; - BYTE aHash[SHA1_HASH_LEN]; - std::string ret("certstore:"); + DWORD cbHash = SHA1_HASH_LENGTH; + BYTE aHash[SHA1_HASH_LENGTH]; + std::string result("certstore:"); - ret += cert_store_name; - ret += ":sha1:"; + result += cert_store_name; + result += ":sha1:"; - if (CertGetCertificateContextProperty(cert, - CERT_HASH_PROP_ID, - aHash, - &cbHash) == FALSE ) { + if (CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID, aHash, &cbHash) == FALSE ) { return ""; } ByteArray byteArray = createByteArray((char *)(&aHash[0]), cbHash); - ret += Hexify::hexify(byteArray); + result += Hexify::hexify(byteArray); - return ret; + return result; } std::string selectCAPICertificate() { + const char* certStoreName = "MY"; - const char * cert_store_name = "MY"; - PCCERT_CONTEXT cert; - DWORD store_flags; - HCERTSTORE hstore; - HWND hwnd; - - store_flags = CERT_STORE_OPEN_EXISTING_FLAG | - CERT_STORE_READONLY_FLAG | - CERT_SYSTEM_STORE_CURRENT_USER; + DWORD storeFlags = CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER; - hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, store_flags, cert_store_name); + HCERTSTORE hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, storeFlags, certStoreName); if (!hstore) { return ""; } - -////Does this handle need to be freed as well? - hwnd = GetForegroundWindow(); + HWND hwnd = GetForegroundWindow(); if (!hwnd) { hwnd = GetActiveWindow(); } + std::string certificateDialogTitle = QT_TRANSLATE_NOOP("", "TLS Client Certificate Selection"); + std::string certificateDialogPrompt = QT_TRANSLATE_NOOP("", "Select a certificate to use for authentication"); + + int titleLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogTitle.c_str(), -1, NULL, 0); + int promptLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogPrompt.c_str(), -1, NULL, 0); + + wchar_t* titleChars = new wchar_t[titleLength]; + wchar_t* promptChars = new wchar_t[promptLength]; + + //titleChars[titleLength] = '\0'; + //promptChars[promptLength] = '\0'; + + titleLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogTitle.c_str(), -1, titleChars, titleLength); + promptLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogPrompt.c_str(), -1, promptChars, promptLength); + + if (titleLength == 0 || promptLength == 0) { + int error = GetLastError(); + switch (error) { + case ERROR_INSUFFICIENT_BUFFER: SWIFT_LOG("error") << "Insufficient buffer for rendering cert dialog" << std::endl;break; + case ERROR_INVALID_FLAGS: SWIFT_LOG("error") << "Invalid flags for rendering cert dialog" << std::endl;break; + case ERROR_INVALID_PARAMETER: SWIFT_LOG("error") << "Invalid parameter for rendering cert dialog" << std::endl;break; + case ERROR_NO_UNICODE_TRANSLATION: SWIFT_LOG("error") << "Invalid unicode for rendering cert dialog" << std::endl;break; + default: SWIFT_LOG("error") << "Unexpected multibyte conversion errorcode" << std::endl; + + } + } + + + /* Call Windows dialog to select a suitable certificate */ - cert = CryptUIDlgSelectCertificateFromStore(hstore, - hwnd, - cert_dlg_title, - cert_dlg_prompt, - exclude_columns, - 0, - NULL); + PCCERT_CONTEXT cert = CryptUIDlgSelectCertificateFromStore(hstore, hwnd, titleChars, promptChars, exclude_columns, 0, NULL); + + delete[] titleChars; + delete[] promptChars; if (hstore) { CertCloseStore(hstore, 0); } - if (cert) { - std::string ret = getCertUri(cert, cert_store_name); + std::string result; + if (cert) { + result = getCertUri(cert, certStoreName); CertFreeCertificateContext(cert); - - return ret; - } else { - return ""; } + + return result; } bool isCAPIURI(std::string uri) { |