diff options
author | Kevin Smith <git@kismith.co.uk> | 2012-03-23 16:00:24 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2012-04-12 13:49:48 (GMT) |
commit | 0bf6afc5c01b9eb3024a8cfd04bfd743890db4f6 (patch) | |
tree | ca480f6b8e27afa97ade97ca7a13b11502b21f31 /Swift | |
parent | d5f885dd9aa65d18145a99826a1c30aeb62aca8e (diff) | |
download | swift-contrib-0bf6afc5c01b9eb3024a8cfd04bfd743890db4f6.zip swift-contrib-0bf6afc5c01b9eb3024a8cfd04bfd743890db4f6.tar.bz2 |
Tidy up of assorted Schannel/CAPI stuffs.
Makes Swift disconnect if a smartcard used for auth is removed.
Fixes compilation.
Changes code style in a few places.
Diffstat (limited to 'Swift')
-rw-r--r-- | Swift/Controllers/MainController.cpp | 2 | ||||
-rw-r--r-- | Swift/QtUI/CAPICertificateSelector.cpp | 101 | ||||
-rw-r--r-- | Swift/QtUI/SConscript | 1 |
3 files changed, 59 insertions, 45 deletions
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index b0a1778..28fdb2b 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -550,6 +550,8 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro case ClientError::InvalidCertificateSignatureError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid certificate signature"); break; case ClientError::InvalidCAError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid Certificate Authority"); break; case ClientError::InvalidServerIdentityError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate does not match the host identity"); break; + case ClientError::RevokedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has been revoked"); break; + case ClientError::RevocationCheckFailedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Unable to determine certificate revocation state"); break; } bool forceReconnectAfterCertificateTrust = false; if (!certificateErrorMessage.empty()) { 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) { diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 0622cc6..0971577 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -41,7 +41,6 @@ if myenv.get("HAVE_SNARL", False) : myenv.Append(CPPDEFINES = ["HAVE_SNARL"]) if env["PLATFORM"] == "win32" : myenv.Append(LIBS = ["cryptui"]) - myenv.Append(LIBS = ["Winscard"]) myenv.UseFlags(myenv["PLATFORM_FLAGS"]) myenv.Tool("qt4", toolpath = ["#/BuildTools/SCons/Tools"]) |