vb@88
|
1 |
#include "stdafx.h"
|
vb@88
|
2 |
|
vb@88
|
3 |
#include "GateKeeper.h"
|
vb@110
|
4 |
#include "pEpCOMServerAdapter.h"
|
vb@123
|
5 |
#include "utf8_helper.h"
|
vb@88
|
6 |
|
vb@88
|
7 |
using namespace std;
|
vb@88
|
8 |
|
vb@123
|
9 |
// https://gist.github.com/mcdurdin/5626617
|
vb@123
|
10 |
|
vb@123
|
11 |
struct PUBLIC_KEY_VALUES {
|
vb@123
|
12 |
BLOBHEADER blobheader;
|
vb@123
|
13 |
RSAPUBKEY rsapubkey;
|
vb@123
|
14 |
BYTE modulus[4096];
|
vb@123
|
15 |
};
|
vb@123
|
16 |
|
vb@123
|
17 |
static void ReverseMemCopy(
|
vb@123
|
18 |
_Out_ BYTE *pbDest,
|
vb@123
|
19 |
_In_ BYTE const *pbSource,
|
vb@123
|
20 |
_In_ DWORD cb
|
vb@123
|
21 |
)
|
vb@123
|
22 |
{
|
vb@123
|
23 |
for (DWORD i = 0; i < cb; i++) {
|
vb@123
|
24 |
pbDest[cb - 1 - i] = pbSource[i];
|
vb@123
|
25 |
}
|
vb@123
|
26 |
}
|
vb@123
|
27 |
|
vb@123
|
28 |
static NTSTATUS ImportRsaPublicKey(
|
vb@123
|
29 |
_In_ BCRYPT_ALG_HANDLE hAlg, // CNG provider
|
vb@123
|
30 |
_In_ PUBLIC_KEY_VALUES *pKey, // Pointer to the RSAPUBKEY blob.
|
vb@123
|
31 |
_In_ BCRYPT_KEY_HANDLE *phKey // Receives a handle the imported public key.
|
vb@123
|
32 |
)
|
vb@123
|
33 |
{
|
vb@123
|
34 |
NTSTATUS hr = 0;
|
vb@123
|
35 |
|
vb@123
|
36 |
BYTE *pbPublicKey = NULL;
|
vb@123
|
37 |
DWORD cbKey = 0;
|
vb@123
|
38 |
|
vb@123
|
39 |
// Layout of the RSA public key blob:
|
vb@123
|
40 |
|
vb@123
|
41 |
// +----------------------------------------------------------------+
|
vb@123
|
42 |
// | BCRYPT_RSAKEY_BLOB | BE( dwExp ) | BE( Modulus ) |
|
vb@123
|
43 |
// +----------------------------------------------------------------+
|
vb@123
|
44 |
//
|
vb@123
|
45 |
// sizeof(BCRYPT_RSAKEY_BLOB) cbExp cbModulus
|
vb@123
|
46 |
// <--------------------------><------------><---------------------->
|
vb@123
|
47 |
//
|
vb@123
|
48 |
// BE = Big Endian Format
|
vb@123
|
49 |
|
vb@123
|
50 |
DWORD cbModulus = (pKey->rsapubkey.bitlen + 7) / 8;
|
vb@123
|
51 |
DWORD dwExp = pKey->rsapubkey.pubexp;
|
vb@123
|
52 |
DWORD cbExp = (dwExp & 0xFF000000) ? 4 :
|
vb@123
|
53 |
(dwExp & 0x00FF0000) ? 3 :
|
vb@123
|
54 |
(dwExp & 0x0000FF00) ? 2 : 1;
|
vb@123
|
55 |
|
vb@123
|
56 |
BCRYPT_RSAKEY_BLOB *pRsaBlob;
|
vb@123
|
57 |
PBYTE pbCurrent;
|
vb@123
|
58 |
|
vb@123
|
59 |
if (!SUCCEEDED(hr = DWordAdd(cbModulus, sizeof(BCRYPT_RSAKEY_BLOB), &cbKey))) {
|
vb@123
|
60 |
goto cleanup;
|
vb@123
|
61 |
}
|
vb@123
|
62 |
|
vb@123
|
63 |
cbKey += cbExp;
|
vb@123
|
64 |
|
vb@123
|
65 |
pbPublicKey = (PBYTE) CoTaskMemAlloc(cbKey);
|
vb@123
|
66 |
if (pbPublicKey == NULL) {
|
vb@123
|
67 |
hr = E_OUTOFMEMORY;
|
vb@123
|
68 |
goto cleanup;
|
vb@123
|
69 |
}
|
vb@123
|
70 |
|
vb@123
|
71 |
ZeroMemory(pbPublicKey, cbKey);
|
vb@123
|
72 |
pRsaBlob = (BCRYPT_RSAKEY_BLOB *) (pbPublicKey);
|
vb@123
|
73 |
|
vb@123
|
74 |
//
|
vb@123
|
75 |
// Make the Public Key Blob Header
|
vb@123
|
76 |
//
|
vb@123
|
77 |
|
vb@123
|
78 |
pRsaBlob->Magic = BCRYPT_RSAPUBLIC_MAGIC;
|
vb@123
|
79 |
pRsaBlob->BitLength = pKey->rsapubkey.bitlen;
|
vb@123
|
80 |
pRsaBlob->cbPublicExp = cbExp;
|
vb@123
|
81 |
pRsaBlob->cbModulus = cbModulus;
|
vb@123
|
82 |
pRsaBlob->cbPrime1 = 0;
|
vb@123
|
83 |
pRsaBlob->cbPrime2 = 0;
|
vb@123
|
84 |
|
vb@123
|
85 |
pbCurrent = (PBYTE) (pRsaBlob + 1);
|
vb@123
|
86 |
|
vb@123
|
87 |
//
|
vb@123
|
88 |
// Copy pubExp Big Endian
|
vb@123
|
89 |
//
|
vb@123
|
90 |
|
vb@123
|
91 |
ReverseMemCopy(pbCurrent, (PBYTE) &dwExp, cbExp);
|
vb@123
|
92 |
pbCurrent += cbExp;
|
vb@123
|
93 |
|
vb@123
|
94 |
//
|
vb@123
|
95 |
// Copy Modulus Big Endian
|
vb@123
|
96 |
//
|
vb@123
|
97 |
|
vb@123
|
98 |
ReverseMemCopy(pbCurrent, pKey->modulus, cbModulus);
|
vb@123
|
99 |
|
vb@123
|
100 |
//
|
vb@123
|
101 |
// Import the public key
|
vb@123
|
102 |
//
|
vb@123
|
103 |
|
vb@123
|
104 |
hr = BCryptImportKeyPair(hAlg, NULL, BCRYPT_RSAPUBLIC_BLOB, phKey, (PUCHAR) pbPublicKey, cbKey, 0);
|
vb@123
|
105 |
|
vb@123
|
106 |
cleanup:
|
vb@123
|
107 |
CoTaskMemFree(pbPublicKey);
|
vb@123
|
108 |
return hr;
|
vb@123
|
109 |
}
|
vb@123
|
110 |
|
vb@96
|
111 |
namespace pEp {
|
vb@96
|
112 |
|
vb@96
|
113 |
const LPCTSTR GateKeeper::plugin_reg_path = _T("Software\\Microsoft\\Office\\Outlook\\Addins\\pEp");
|
vb@96
|
114 |
const LPCTSTR GateKeeper::plugin_reg_value_name = _T("LoadBehavior");
|
vb@96
|
115 |
const LPCTSTR GateKeeper::updater_reg_path = _T("Software\\pEp\\Updater";)
|
vb@96
|
116 |
|
vb@96
|
117 |
const time_t GateKeeper::cycle = 7200; // 7200 sec is 2 h
|
vb@96
|
118 |
const DWORD GateKeeper::waiting = 10000; // 10000 ms is 10 sec
|
vb@88
|
119 |
|
vb@117
|
120 |
GateKeeper::GateKeeper(CpEpCOMServerAdapterModule * self)
|
vb@116
|
121 |
: _self(self), now(time(NULL)), next(now + time_diff()), hkUpdater(NULL), internet(NULL), hAES(NULL), hRSA(NULL)
|
vb@96
|
122 |
{
|
vb@96
|
123 |
LONG lResult = RegOpenCurrentUser(KEY_READ, &cu);
|
vb@96
|
124 |
assert(lResult == ERROR_SUCCESS);
|
vb@96
|
125 |
if (lResult == ERROR_SUCCESS)
|
vb@96
|
126 |
cu_open = true;
|
vb@96
|
127 |
else
|
vb@96
|
128 |
cu_open = false;
|
vb@88
|
129 |
|
vb@96
|
130 |
if (cu_open) {
|
vb@96
|
131 |
LONG lResult = RegOpenKeyEx(cu, updater_reg_path, 0, KEY_READ, &hkUpdater);
|
vb@96
|
132 |
assert(lResult == ERROR_SUCCESS);
|
vb@96
|
133 |
if (lResult != ERROR_SUCCESS)
|
vb@96
|
134 |
return;
|
vb@96
|
135 |
}
|
vb@96
|
136 |
}
|
vb@96
|
137 |
|
vb@96
|
138 |
GateKeeper::~GateKeeper()
|
vb@96
|
139 |
{
|
vb@96
|
140 |
if (cu_open) {
|
vb@96
|
141 |
if (hkUpdater)
|
vb@96
|
142 |
RegCloseKey(hkUpdater);
|
vb@96
|
143 |
RegCloseKey(cu);
|
vb@96
|
144 |
}
|
vb@96
|
145 |
}
|
vb@88
|
146 |
|
vb@96
|
147 |
time_t GateKeeper::time_diff()
|
vb@96
|
148 |
{
|
vb@96
|
149 |
try {
|
vb@96
|
150 |
static random_device rd;
|
vb@96
|
151 |
static mt19937 gen(rd());
|
vb@88
|
152 |
|
vb@96
|
153 |
uniform_int_distribution<time_t> dist(0, cycle);
|
vb@96
|
154 |
|
vb@96
|
155 |
return dist(gen);
|
vb@96
|
156 |
}
|
vb@96
|
157 |
catch (exception&) {
|
vb@96
|
158 |
assert(0);
|
vb@96
|
159 |
return 0;
|
vb@96
|
160 |
}
|
vb@88
|
161 |
}
|
vb@96
|
162 |
|
vb@96
|
163 |
void GateKeeper::keep()
|
vb@96
|
164 |
{
|
vb@96
|
165 |
if (!cu_open)
|
vb@96
|
166 |
return;
|
vb@96
|
167 |
|
vb@96
|
168 |
while (1) {
|
vb@96
|
169 |
keep_plugin();
|
vb@96
|
170 |
|
vb@96
|
171 |
now = time(NULL);
|
vb@96
|
172 |
assert(now != -1);
|
vb@96
|
173 |
|
vb@96
|
174 |
if (now > next) {
|
vb@96
|
175 |
next = now + GateKeeper::cycle;
|
vb@96
|
176 |
keep_updated();
|
vb@96
|
177 |
}
|
vb@96
|
178 |
|
vb@96
|
179 |
Sleep(waiting);
|
vb@96
|
180 |
}
|
vb@88
|
181 |
}
|
vb@96
|
182 |
|
vb@96
|
183 |
void GateKeeper::keep_plugin()
|
vb@96
|
184 |
{
|
vb@110
|
185 |
while (!_self->m_bComInitialized)
|
vb@110
|
186 |
Sleep(1);
|
vb@110
|
187 |
|
vb@123
|
188 |
//MessageBox(NULL, _T("test"), _T("keep_plugin"), MB_ICONINFORMATION | MB_TOPMOST);
|
vb@110
|
189 |
|
vb@96
|
190 |
DWORD value;
|
vb@96
|
191 |
DWORD size;
|
vb@88
|
192 |
|
vb@96
|
193 |
LONG lResult = RegGetValue(cu, plugin_reg_path, plugin_reg_value_name, RRF_RT_REG_DWORD, NULL, &value, &size);
|
vb@96
|
194 |
if (lResult != ERROR_SUCCESS)
|
vb@96
|
195 |
return;
|
vb@96
|
196 |
|
vb@96
|
197 |
if (value != 3) {
|
vb@96
|
198 |
lResult = RegSetValue(cu, plugin_reg_path, RRF_RT_REG_DWORD, plugin_reg_value_name, 3);
|
vb@96
|
199 |
assert(lResult == ERROR_SUCCESS);
|
vb@96
|
200 |
}
|
vb@96
|
201 |
}
|
vb@96
|
202 |
|
vb@111
|
203 |
string GateKeeper::update_key()
|
vb@110
|
204 |
{
|
vb@110
|
205 |
static string key;
|
vb@110
|
206 |
|
vb@110
|
207 |
if (key.length() == 0) {
|
vb@110
|
208 |
HRSRC res = FindResource(_self->hModule(), MAKEINTRESOURCE(IRD_UPDATEKEY), RT_RCDATA);
|
vb@110
|
209 |
assert(res);
|
vb@110
|
210 |
if (!res)
|
vb@110
|
211 |
throw runtime_error("FindResource: IRD_UPDATEKEY");
|
vb@110
|
212 |
|
vb@110
|
213 |
HGLOBAL hRes = LoadResource(_self->hModule(), res);
|
vb@110
|
214 |
assert(hRes);
|
vb@110
|
215 |
if (!hRes)
|
vb@110
|
216 |
throw runtime_error("LoadResource: IRD_UPDATEKEY");
|
vb@110
|
217 |
|
vb@110
|
218 |
key = string((char *)LockResource(hRes), SizeofResource(_self->hModule(), res));
|
vb@110
|
219 |
UnlockResource(hRes);
|
vb@110
|
220 |
}
|
vb@110
|
221 |
|
vb@110
|
222 |
return key;
|
vb@110
|
223 |
}
|
vb@110
|
224 |
|
vb@116
|
225 |
BCRYPT_KEY_HANDLE GateKeeper::delivery_key()
|
vb@112
|
226 |
{
|
vb@112
|
227 |
aeskey_t key;
|
vb@112
|
228 |
|
vb@112
|
229 |
static random_device rd;
|
vb@112
|
230 |
static mt19937 gen(rd());
|
vb@112
|
231 |
|
vb@123
|
232 |
uniform_int_distribution<int64_t> dist(0, UINT32_MAX);
|
vb@112
|
233 |
|
vb@123
|
234 |
for (int i = 0; i < 8; i++)
|
vb@123
|
235 |
key.dw_key[i] = (uint32_t) dist(gen);
|
vb@113
|
236 |
|
vb@116
|
237 |
BCRYPT_KEY_HANDLE hKey;
|
vb@116
|
238 |
NTSTATUS status = BCryptGenerateSymmetricKey(hAES, &hKey, NULL, 0, (PUCHAR) &key, (ULONG) sizeof(aeskey_t), 0);
|
vb@116
|
239 |
assert(status == 0);
|
vb@116
|
240 |
if (status)
|
vb@116
|
241 |
throw runtime_error("BCryptGenerateSymmetricKey");
|
vb@116
|
242 |
|
vb@116
|
243 |
return hKey;
|
vb@113
|
244 |
}
|
vb@113
|
245 |
|
vb@121
|
246 |
string GateKeeper::wrapped_delivery_key(BCRYPT_KEY_HANDLE hDeliveryKey)
|
vb@113
|
247 |
{
|
vb@113
|
248 |
string result;
|
vb@113
|
249 |
|
vb@116
|
250 |
BCRYPT_KEY_HANDLE hUpdateKey;
|
vb@117
|
251 |
string _update_key = update_key();
|
vb@113
|
252 |
|
vb@123
|
253 |
PCERT_PUBLIC_KEY_INFO uk;
|
vb@123
|
254 |
DWORD uk_size;
|
vb@123
|
255 |
BOOL bResult = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
|
vb@123
|
256 |
(const BYTE *) _update_key.data(), _update_key.size(), CRYPT_DECODE_ALLOC_FLAG, NULL, &uk, &uk_size);
|
vb@123
|
257 |
if (!bResult)
|
vb@123
|
258 |
throw runtime_error("CryptDecodeObjectEx: X509_PUBLIC_KEY_INFO");
|
vb@123
|
259 |
|
vb@123
|
260 |
PUBLIC_KEY_VALUES *_uk;
|
vb@123
|
261 |
DWORD _uk_size;
|
vb@123
|
262 |
bResult = CryptDecodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
|
vb@123
|
263 |
uk->PublicKey.pbData, uk->PublicKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &_uk, &_uk_size);
|
vb@123
|
264 |
LocalFree(uk);
|
vb@123
|
265 |
if (!bResult)
|
vb@123
|
266 |
throw runtime_error("CryptDecodeObjectEx: X509_PUBLIC_KEY_INFO");
|
vb@123
|
267 |
|
vb@123
|
268 |
HRESULT hResult = ImportRsaPublicKey(hRSA, _uk, &hUpdateKey);
|
vb@123
|
269 |
LocalFree(_uk);
|
vb@123
|
270 |
if (hResult)
|
vb@123
|
271 |
throw runtime_error("ImportRsaPublicKey");
|
vb@117
|
272 |
|
vb@129
|
273 |
ULONG psize;
|
vb@129
|
274 |
NTSTATUS status = BCryptGetProperty(hUpdateKey, BCRYPT_ALGORITHM_NAME, NULL, 0, &psize, 0);
|
vb@129
|
275 |
char *prop = new char[psize];
|
vb@129
|
276 |
TCHAR *_prop = (TCHAR *) prop;
|
vb@129
|
277 |
BCryptGetProperty(hUpdateKey, BCRYPT_ALGORITHM_NAME, (PUCHAR) prop, psize, &psize, 0);
|
vb@129
|
278 |
|
vb@129
|
279 |
ULONG export_size;
|
vb@129
|
280 |
status = BCryptExportKey(hDeliveryKey, NULL, BCRYPT_KEY_DATA_BLOB, NULL, NULL,
|
vb@129
|
281 |
&export_size, 0);
|
vb@129
|
282 |
if (status)
|
vb@129
|
283 |
throw runtime_error("BCryptExportKey: measuring export size");
|
vb@129
|
284 |
|
vb@129
|
285 |
PUCHAR _delivery_key = new UCHAR[export_size];
|
vb@120
|
286 |
ULONG copied;
|
vb@129
|
287 |
status = BCryptExportKey(hDeliveryKey, NULL, BCRYPT_KEY_DATA_BLOB, _delivery_key, export_size,
|
vb@123
|
288 |
&copied, 0);
|
vb@129
|
289 |
if (status) {
|
vb@129
|
290 |
delete[] _delivery_key;
|
vb@120
|
291 |
throw runtime_error("BCryptExportKey: delivery_key");
|
vb@129
|
292 |
}
|
vb@120
|
293 |
|
vb@117
|
294 |
static random_device rd;
|
vb@117
|
295 |
static mt19937 gen(rd());
|
vb@123
|
296 |
uniform_int_distribution<int64_t> dist(0, UINT32_MAX);
|
vb@123
|
297 |
uint32_t r[64];
|
vb@123
|
298 |
for (int i = 0; i < 64; i++)
|
vb@123
|
299 |
r[i] = (uint32_t) dist(gen);
|
vb@117
|
300 |
|
vb@117
|
301 |
BCRYPT_OAEP_PADDING_INFO pi;
|
vb@119
|
302 |
memset(&pi, 0, sizeof(BCRYPT_OAEP_PADDING_INFO));
|
vb@117
|
303 |
pi.pszAlgId = BCRYPT_SHA256_ALGORITHM;
|
vb@117
|
304 |
pi.pbLabel = (PUCHAR) r;
|
vb@117
|
305 |
pi.cbLabel = sizeof(r);
|
vb@117
|
306 |
|
vb@117
|
307 |
ULONG result_size;
|
vb@118
|
308 |
PUCHAR _result = NULL;
|
vb@129
|
309 |
ULONG blob_size = export_size - sizeof(BCRYPT_KEY_DATA_BLOB_HEADER);
|
vb@129
|
310 |
PUCHAR blob = _delivery_key + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER);
|
vb@129
|
311 |
status = BCryptEncrypt(hUpdateKey, blob, blob_size, &pi, NULL, 0, NULL, 0, &result_size, BCRYPT_PAD_OAEP);
|
vb@119
|
312 |
if (status) {
|
vb@129
|
313 |
delete[] _delivery_key;
|
vb@119
|
314 |
BCryptDestroyKey(hUpdateKey);
|
vb@117
|
315 |
throw runtime_error("BCryptEncrypt: calculating result size");
|
vb@119
|
316 |
}
|
vb@117
|
317 |
|
vb@117
|
318 |
_result = new UCHAR[result_size];
|
vb@129
|
319 |
status = BCryptEncrypt(hUpdateKey, blob, blob_size, &pi, NULL, 0, _result, result_size, &copied, BCRYPT_PAD_OAEP);
|
vb@129
|
320 |
delete[] _delivery_key;
|
vb@119
|
321 |
if (status) {
|
vb@119
|
322 |
BCryptDestroyKey(hUpdateKey);
|
vb@119
|
323 |
delete[] _result;
|
vb@118
|
324 |
throw runtime_error("BCryptEncrypt: encrypting using update_key");
|
vb@119
|
325 |
}
|
vb@117
|
326 |
|
vb@120
|
327 |
BCryptDestroyKey(hUpdateKey);
|
vb@120
|
328 |
|
vb@117
|
329 |
stringstream s;
|
vb@129
|
330 |
for (ULONG i = 0; i < copied; i++) {
|
vb@129
|
331 |
s << hex << setw(2) << setfill('0');
|
vb@118
|
332 |
s << (int) _result[i];
|
vb@129
|
333 |
}
|
vb@117
|
334 |
delete[] _result;
|
vb@117
|
335 |
s >> result;
|
vb@117
|
336 |
|
vb@113
|
337 |
return result;
|
vb@112
|
338 |
}
|
vb@112
|
339 |
|
vb@96
|
340 |
GateKeeper::product_list& GateKeeper::registered_products()
|
vb@96
|
341 |
{
|
vb@96
|
342 |
static product_list products;
|
vb@88
|
343 |
|
vb@96
|
344 |
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
|
vb@96
|
345 |
static TCHAR value_name[16384];
|
vb@96
|
346 |
DWORD value_name_size;
|
vb@96
|
347 |
static TCHAR value[L_MAX_URL_LENGTH + 1];
|
vb@96
|
348 |
DWORD value_size;
|
vb@88
|
349 |
|
vb@96
|
350 |
products.empty();
|
vb@96
|
351 |
|
vb@96
|
352 |
LONG lResult = ERROR_SUCCESS;
|
vb@96
|
353 |
for (DWORD i = 0; lResult == ERROR_SUCCESS; i++) {
|
vb@96
|
354 |
value_size = L_MAX_URL_LENGTH + 1;
|
vb@96
|
355 |
lResult = RegEnumValue(hkUpdater, 0, value_name, &value_name_size, NULL, NULL, (LPBYTE) value, &value_size);
|
vb@96
|
356 |
if (lResult == ERROR_SUCCESS)
|
vb@96
|
357 |
products.push_back({ value_name, value });
|
vb@88
|
358 |
}
|
vb@88
|
359 |
|
vb@96
|
360 |
return products;
|
vb@88
|
361 |
}
|
vb@88
|
362 |
|
vb@126
|
363 |
void GateKeeper::install_msi(tstring filename)
|
vb@126
|
364 |
{
|
vb@126
|
365 |
|
vb@126
|
366 |
}
|
vb@126
|
367 |
|
vb@97
|
368 |
void GateKeeper::update_product(product p, DWORD context)
|
vb@96
|
369 |
{
|
vb@127
|
370 |
BCRYPT_KEY_HANDLE dk = delivery_key();
|
vb@126
|
371 |
#ifdef UNICODE
|
vb@127
|
372 |
tstring delivery = utility::utf16_string(wrapped_delivery_key(dk));
|
vb@126
|
373 |
#else
|
vb@126
|
374 |
tstring delivery = wrapped_delivery_key(delivery_key());
|
vb@126
|
375 |
#endif
|
vb@124
|
376 |
tstring url = p.second;
|
vb@124
|
377 |
url += _T("&challenge=");
|
vb@124
|
378 |
url += delivery;
|
vb@124
|
379 |
tstring headers;
|
vb@124
|
380 |
HINTERNET hUrl = InternetOpenUrl(internet, url.c_str(), headers.c_str(), headers.length(),
|
vb@97
|
381 |
INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE, context);
|
vb@97
|
382 |
if (hUrl == NULL)
|
vb@97
|
383 |
return;
|
vb@94
|
384 |
|
vb@127
|
385 |
string crypted;
|
vb@127
|
386 |
string unencrypted;
|
vb@107
|
387 |
|
vb@126
|
388 |
do {
|
vb@126
|
389 |
static char buffer[32768];
|
vb@126
|
390 |
DWORD reading;
|
vb@126
|
391 |
BOOL bResult = InternetReadFile(hUrl, buffer, 32768, &reading);
|
vb@126
|
392 |
if (!bResult || !reading)
|
vb@126
|
393 |
break;
|
vb@127
|
394 |
crypted += string(buffer, reading);
|
vb@126
|
395 |
} while (1);
|
vb@97
|
396 |
|
vb@97
|
397 |
InternetCloseHandle(hUrl);
|
vb@126
|
398 |
hUrl = NULL;
|
vb@126
|
399 |
|
vb@127
|
400 |
tstring filename;
|
vb@127
|
401 |
HANDLE hFile = NULL;
|
vb@127
|
402 |
char *unencrypted_buffer = NULL;
|
vb@127
|
403 |
|
vb@128
|
404 |
char nonce[12];
|
vb@128
|
405 |
|
vb@127
|
406 |
ULONG unencrypted_size;
|
vb@127
|
407 |
NTSTATUS status = BCryptDecrypt(dk, (PUCHAR) crypted.data(), crypted.size(),
|
vb@127
|
408 |
NULL, NULL, 0, NULL, 0, &unencrypted_size, 0);
|
vb@127
|
409 |
if (status)
|
vb@127
|
410 |
goto closing;
|
vb@127
|
411 |
|
vb@127
|
412 |
unencrypted_buffer = new char[unencrypted_size];
|
vb@127
|
413 |
|
vb@127
|
414 |
status = BCryptDecrypt(dk, (PUCHAR) crypted.data(), crypted.size(),
|
vb@127
|
415 |
NULL, NULL, 0, (PUCHAR) unencrypted_buffer, unencrypted_size, &unencrypted_size, 0);
|
vb@129
|
416 |
if (status)
|
vb@127
|
417 |
goto closing;
|
vb@127
|
418 |
|
vb@127
|
419 |
TCHAR temp_path[MAX_PATH + 1];
|
vb@127
|
420 |
GetTempPath(MAX_PATH, temp_path);
|
vb@127
|
421 |
filename = temp_path;
|
vb@127
|
422 |
filename += _T("\\pEp_");
|
vb@127
|
423 |
filename += delivery.substr(0, 32);
|
vb@127
|
424 |
filename += _T(".msi");
|
vb@127
|
425 |
|
vb@127
|
426 |
hFile = CreateFile(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
vb@127
|
427 |
if (!hFile)
|
vb@127
|
428 |
goto closing;
|
vb@127
|
429 |
DWORD writing;
|
vb@127
|
430 |
WriteFile(hFile, unencrypted_buffer, unencrypted_size, &writing, NULL);
|
vb@127
|
431 |
CloseHandle(hFile);
|
vb@127
|
432 |
|
vb@126
|
433 |
install_msi(filename);
|
vb@127
|
434 |
|
vb@126
|
435 |
DeleteFile(filename.c_str());
|
vb@127
|
436 |
BCryptDestroyKey(dk);
|
vb@126
|
437 |
return;
|
vb@126
|
438 |
|
vb@126
|
439 |
closing:
|
vb@127
|
440 |
if (unencrypted_buffer)
|
vb@127
|
441 |
delete[] unencrypted_buffer;
|
vb@126
|
442 |
if (hFile)
|
vb@126
|
443 |
CloseHandle(hFile);
|
vb@126
|
444 |
if (hUrl)
|
vb@126
|
445 |
InternetCloseHandle(hUrl);
|
vb@127
|
446 |
if (filename.length())
|
vb@127
|
447 |
DeleteFile(filename.c_str());
|
vb@127
|
448 |
BCryptDestroyKey(dk);
|
vb@96
|
449 |
}
|
vb@88
|
450 |
|
vb@96
|
451 |
void GateKeeper::keep_updated()
|
vb@96
|
452 |
{
|
vb@107
|
453 |
return; // disabled for now
|
vb@107
|
454 |
|
vb@116
|
455 |
NTSTATUS status = BCryptOpenAlgorithmProvider(&hAES, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
|
vb@116
|
456 |
assert(status == 0);
|
vb@116
|
457 |
if (status)
|
vb@116
|
458 |
goto closing;
|
vb@128
|
459 |
status = BCryptSetProperty(hAES, BCRYPT_CHAINING_MODE, (PUCHAR) BCRYPT_CHAIN_MODE_CCM, sizeof(BCRYPT_CHAIN_MODE_CCM), 0);
|
vb@128
|
460 |
if (status)
|
vb@128
|
461 |
goto closing;
|
vb@116
|
462 |
|
vb@116
|
463 |
status = BCryptOpenAlgorithmProvider(&hRSA, BCRYPT_RSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
|
vb@116
|
464 |
assert(status == 0);
|
vb@116
|
465 |
if (status)
|
vb@116
|
466 |
goto closing;
|
vb@116
|
467 |
|
vb@124
|
468 |
internet = InternetOpen(_T("pEp"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
vb@124
|
469 |
if (!internet)
|
vb@124
|
470 |
goto closing;
|
vb@97
|
471 |
|
vb@96
|
472 |
product_list& products = registered_products();
|
vb@97
|
473 |
DWORD context = 0;
|
vb@96
|
474 |
for (auto i = products.begin(); i != products.end(); i++) {
|
vb@126
|
475 |
try {
|
vb@126
|
476 |
update_product(*i, context++);
|
vb@126
|
477 |
}
|
vb@126
|
478 |
catch (exception&) {
|
vb@126
|
479 |
|
vb@126
|
480 |
}
|
vb@96
|
481 |
}
|
vb@97
|
482 |
|
vb@116
|
483 |
closing:
|
vb@116
|
484 |
if (internet)
|
vb@116
|
485 |
InternetCloseHandle(internet);
|
vb@116
|
486 |
if (hAES)
|
vb@116
|
487 |
BCryptCloseAlgorithmProvider(hAES, 0);
|
vb@116
|
488 |
if (hRSA)
|
vb@116
|
489 |
BCryptCloseAlgorithmProvider(hRSA, 0);
|
vb@97
|
490 |
internet = NULL;
|
vb@116
|
491 |
hAES = NULL;
|
vb@116
|
492 |
hRSA = NULL;
|
vb@96
|
493 |
}
|
vb@88
|
494 |
|
vb@96
|
495 |
} // namespace pEp
|