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) { | 
 Swift
 Swift