1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/*
* Copyright (c) 2012 Isode Limited, London, England.
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <string>
#include "CAPICertificateSelector.h"
#define SECURITY_WIN32
#include <Windows.h>
#include <WinCrypt.h>
#include <cryptuiapi.h>
#include <Swiften/StringCodecs/Hexify.h>
#include <boost/algorithm/string.hpp>
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
// Size of the SHA1 hash
#define SHA1_HASH_LEN 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:");
ret += cert_store_name;
ret += ":sha1:";
if (CertGetCertificateContextProperty(cert,
CERT_HASH_PROP_ID,
aHash,
&cbHash) == FALSE ) {
return "";
}
ByteArray byteArray = createByteArray((char *)(&aHash[0]), cbHash);
ret += Hexify::hexify(byteArray);
return ret;
}
std::string selectCAPICertificate() {
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;
hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, store_flags, cert_store_name);
if (!hstore) {
return "";
}
////Does this handle need to be freed as well?
hwnd = GetForegroundWindow();
if (!hwnd) {
hwnd = GetActiveWindow();
}
/* Call Windows dialog to select a suitable certificate */
cert = CryptUIDlgSelectCertificateFromStore(hstore,
hwnd,
cert_dlg_title,
cert_dlg_prompt,
exclude_columns,
0,
NULL);
if (hstore) {
CertCloseStore(hstore, 0);
}
if (cert) {
std::string ret = getCertUri(cert, cert_store_name);
CertFreeCertificateContext(cert);
return ret;
} else {
return "";
}
}
bool isCAPIURI(std::string uri) {
return (boost::iequals(uri.substr(0, 10), "certstore:"));
}
}
|