p≡p COM server adapter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

676 lines
21 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
3 years ago
6 years ago
3 years ago
6 years ago
3 years ago
6 years ago
3 years ago
3 years ago
3 years ago
6 years ago
3 years ago
6 years ago
6 years ago
6 years ago
6 years ago
3 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. #include "stdafx.h"
  2. #include "GateKeeper.h"
  3. #include "pEpCOMServerAdapter.h"
  4. #include "CMainWindow.h"
  5. using namespace std;
  6. extern CMainWindow mainWindow;
  7. auto r = CMainWindow::r;
  8. // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd388945(v=vs.85).aspx
  9. struct PUBLIC_KEY_VALUES {
  10. BLOBHEADER blobheader;
  11. RSAPUBKEY rsapubkey;
  12. BYTE modulus[4096];
  13. };
  14. static void ReverseMemCopy(
  15. _Out_ BYTE *pbDest,
  16. _In_ BYTE const *pbSource,
  17. _In_ DWORD cb
  18. )
  19. {
  20. for (DWORD i = 0; i < cb; i++) {
  21. pbDest[cb - 1 - i] = pbSource[i];
  22. }
  23. }
  24. static NTSTATUS ImportRsaPublicKey(
  25. _In_ BCRYPT_ALG_HANDLE hAlg, // CNG provider
  26. _In_ PUBLIC_KEY_VALUES *pKey, // Pointer to the RSAPUBKEY blob.
  27. _In_ BCRYPT_KEY_HANDLE *phKey // Receives a handle the imported public key.
  28. )
  29. {
  30. NTSTATUS hr = 0;
  31. BYTE *pbPublicKey = NULL;
  32. DWORD cbKey = 0;
  33. // Layout of the RSA public key blob:
  34. // +----------------------------------------------------------------+
  35. // | BCRYPT_RSAKEY_BLOB | BE( dwExp ) | BE( Modulus ) |
  36. // +----------------------------------------------------------------+
  37. //
  38. // sizeof(BCRYPT_RSAKEY_BLOB) cbExp cbModulus
  39. // <--------------------------><------------><---------------------->
  40. //
  41. // BE = Big Endian Format
  42. DWORD cbModulus = (pKey->rsapubkey.bitlen + 7) / 8;
  43. DWORD dwExp = pKey->rsapubkey.pubexp;
  44. DWORD cbExp = (dwExp & 0xFF000000) ? 4 :
  45. (dwExp & 0x00FF0000) ? 3 :
  46. (dwExp & 0x0000FF00) ? 2 : 1;
  47. BCRYPT_RSAKEY_BLOB *pRsaBlob;
  48. PBYTE pbCurrent;
  49. if (!SUCCEEDED(hr = DWordAdd(cbModulus, sizeof(BCRYPT_RSAKEY_BLOB), &cbKey))) {
  50. goto cleanup;
  51. }
  52. cbKey += cbExp;
  53. pbPublicKey = (PBYTE)CoTaskMemAlloc(cbKey);
  54. if (pbPublicKey == NULL) {
  55. hr = E_OUTOFMEMORY;
  56. goto cleanup;
  57. }
  58. ZeroMemory(pbPublicKey, cbKey);
  59. pRsaBlob = (BCRYPT_RSAKEY_BLOB *)(pbPublicKey);
  60. //
  61. // Make the Public Key Blob Header
  62. //
  63. pRsaBlob->Magic = BCRYPT_RSAPUBLIC_MAGIC;
  64. pRsaBlob->BitLength = pKey->rsapubkey.bitlen;
  65. pRsaBlob->cbPublicExp = cbExp;
  66. pRsaBlob->cbModulus = cbModulus;
  67. pRsaBlob->cbPrime1 = 0;
  68. pRsaBlob->cbPrime2 = 0;
  69. pbCurrent = (PBYTE)(pRsaBlob + 1);
  70. //
  71. // Copy pubExp Big Endian
  72. //
  73. ReverseMemCopy(pbCurrent, (PBYTE)&dwExp, cbExp);
  74. pbCurrent += cbExp;
  75. //
  76. // Copy Modulus Big Endian
  77. //
  78. ReverseMemCopy(pbCurrent, pKey->modulus, cbModulus);
  79. //
  80. // Import the public key
  81. //
  82. hr = BCryptImportKeyPair(hAlg, NULL, BCRYPT_RSAPUBLIC_BLOB, phKey, (PUCHAR)pbPublicKey, cbKey, 0);
  83. cleanup:
  84. CoTaskMemFree(pbPublicKey);
  85. return hr;
  86. }
  87. namespace pEp {
  88. const LPCTSTR GateKeeper::plugin_reg_path = _T("Software\\Microsoft\\Office\\Outlook\\Addins\\pEp");
  89. const LPCTSTR GateKeeper::plugin_reg_value_name = _T("LoadBehavior");
  90. const LPCTSTR GateKeeper::updater_reg_path = _T("Software\\pEp\\Updater");
  91. const time_t GateKeeper::cycle = 7200; // 7200 sec is 2 h
  92. const time_t GateKeeper::fraction = 10; // first update is at 10% of cycle
  93. const DWORD GateKeeper::waiting = 10000; // 10 sec
  94. GateKeeper::GateKeeper(CpEpCOMServerAdapterModule * self)
  95. : _self(self), now(time(NULL)), next(now /*+ time_diff()*/), hkUpdater(NULL),
  96. internet(NULL), hAES(NULL), hRSA(NULL)
  97. {
  98. if (the_gatekeeper)
  99. throw runtime_error("second instance of GateKeeper was initialized");
  100. DeleteFile(get_lockFile().c_str());
  101. LONG lResult = RegOpenCurrentUser(KEY_READ, &cu);
  102. assert(lResult == ERROR_SUCCESS);
  103. if (lResult == ERROR_SUCCESS)
  104. cu_open = true;
  105. else
  106. cu_open = false;
  107. if (cu_open) {
  108. LONG lResult = RegOpenKeyEx(cu, updater_reg_path, 0, KEY_READ, &hkUpdater);
  109. if (lResult != ERROR_SUCCESS)
  110. RegCreateKeyEx(cu, updater_reg_path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hkUpdater, NULL);
  111. }
  112. the_gatekeeper = this;
  113. }
  114. GateKeeper::~GateKeeper()
  115. {
  116. the_gatekeeper = nullptr;
  117. if (cu_open) {
  118. if (hkUpdater)
  119. RegCloseKey(hkUpdater);
  120. RegCloseKey(cu);
  121. }
  122. }
  123. time_t GateKeeper::time_diff()
  124. {
  125. try {
  126. static random_device rd;
  127. static mt19937 gen(rd());
  128. uniform_int_distribution<time_t> dist(0, cycle / fraction);
  129. return dist(gen);
  130. }
  131. catch (exception&) {
  132. assert(0);
  133. return 0;
  134. }
  135. }
  136. void GateKeeper::keep()
  137. {
  138. if (!cu_open)
  139. return;
  140. while (1) {
  141. keep_plugin();
  142. now = time(NULL);
  143. assert(now != -1);
  144. if (now > next) {
  145. next = now + GateKeeper::cycle;
  146. if (update_enabled())
  147. update_now();
  148. }
  149. Sleep(waiting);
  150. }
  151. }
  152. void GateKeeper::keep_plugin()
  153. {
  154. HKEY hkPluginStart = NULL;
  155. LONG lResult = RegOpenKeyEx(cu, plugin_reg_path, 0, KEY_WRITE, &hkPluginStart);
  156. if (lResult != ERROR_SUCCESS)
  157. return;
  158. DWORD v = 3;
  159. lResult = RegSetValueEx(hkPluginStart, plugin_reg_value_name, 0, REG_DWORD, (const BYTE *)&v, sizeof(DWORD));
  160. assert(lResult == ERROR_SUCCESS);
  161. RegCloseKey(hkPluginStart);
  162. }
  163. string GateKeeper::update_key()
  164. {
  165. static string key;
  166. if (key.length() == 0) {
  167. HRSRC res = FindResource(_self->hModule(), MAKEINTRESOURCE(IRD_UPDATEKEY), RT_RCDATA);
  168. assert(res);
  169. if (!res)
  170. throw runtime_error("FindResource: IRD_UPDATEKEY");
  171. HGLOBAL hRes = LoadResource(_self->hModule(), res);
  172. assert(hRes);
  173. if (!hRes)
  174. throw runtime_error("LoadResource: IRD_UPDATEKEY");
  175. key = string((char *)LockResource(hRes), SizeofResource(_self->hModule(), res));
  176. UnlockResource(hRes);
  177. }
  178. return key;
  179. }
  180. BCRYPT_KEY_HANDLE GateKeeper::delivery_key()
  181. {
  182. aeskey_t key;
  183. static random_device rd;
  184. static mt19937 gen(rd());
  185. uniform_int_distribution<int64_t> dist(0, UINT32_MAX);
  186. for (int i = 0; i < 8; i++)
  187. key.dw_key[i] = (uint32_t)dist(gen);
  188. BCRYPT_KEY_HANDLE hKey;
  189. NTSTATUS status = BCryptGenerateSymmetricKey(hAES, &hKey, NULL, 0, (PUCHAR)&key, (ULONG) sizeof(aeskey_t), 0);
  190. assert(status == 0);
  191. if (status)
  192. throw runtime_error("BCryptGenerateSymmetricKey");
  193. #ifndef NDEBUG
  194. DWORD keylength = 0;
  195. ULONG copied = 0;
  196. status = BCryptGetProperty(hKey, BCRYPT_KEY_LENGTH, (PUCHAR)&keylength, sizeof(DWORD), &copied, 0);
  197. assert(keylength == 256);
  198. #endif
  199. return hKey;
  200. }
  201. string GateKeeper::wrapped_delivery_key(BCRYPT_KEY_HANDLE hDeliveryKey)
  202. {
  203. string result;
  204. BCRYPT_KEY_HANDLE hUpdateKey = NULL;
  205. string _update_key = update_key();
  206. PCERT_PUBLIC_KEY_INFO uk = NULL;
  207. DWORD uk_size = 0;
  208. BOOL bResult = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
  209. (const BYTE *)_update_key.data(), _update_key.size(), CRYPT_DECODE_ALLOC_FLAG, NULL, &uk, &uk_size);
  210. if (!bResult)
  211. throw runtime_error("CryptDecodeObjectEx: X509_PUBLIC_KEY_INFO");
  212. PUBLIC_KEY_VALUES *_uk = NULL;
  213. DWORD _uk_size = 0;
  214. bResult = CryptDecodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
  215. uk->PublicKey.pbData, uk->PublicKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &_uk, &_uk_size);
  216. LocalFree(uk);
  217. if (!bResult)
  218. throw runtime_error("CryptDecodeObjectEx: X509_PUBLIC_KEY_INFO");
  219. HRESULT hResult = ImportRsaPublicKey(hRSA, _uk, &hUpdateKey);
  220. LocalFree(_uk);
  221. if (!hUpdateKey)
  222. throw runtime_error("ImportRsaPublicKey");
  223. ULONG psize;
  224. NTSTATUS status = BCryptGetProperty(hUpdateKey, BCRYPT_ALGORITHM_NAME, NULL, 0, &psize, 0);
  225. char *prop = new char[psize];
  226. TCHAR *_prop = (TCHAR *)prop;
  227. status = BCryptGetProperty(hUpdateKey, BCRYPT_ALGORITHM_NAME, (PUCHAR)prop, psize, &psize, 0);
  228. if (status)
  229. throw runtime_error("BCryptGetProperty: BCRYPT_ALGORITHM_NAME");
  230. ULONG export_size;
  231. status = BCryptExportKey(hDeliveryKey, NULL, BCRYPT_KEY_DATA_BLOB, NULL, NULL,
  232. &export_size, 0);
  233. if (status)
  234. throw runtime_error("BCryptExportKey: measuring export size");
  235. PUCHAR _delivery_key = new UCHAR[export_size];
  236. ULONG copied;
  237. status = BCryptExportKey(hDeliveryKey, NULL, BCRYPT_KEY_DATA_BLOB, _delivery_key, export_size,
  238. &copied, 0);
  239. if (status) {
  240. delete[] _delivery_key;
  241. throw runtime_error("BCryptExportKey: delivery_key");
  242. }
  243. BCRYPT_OAEP_PADDING_INFO pi;
  244. memset(&pi, 0, sizeof(BCRYPT_OAEP_PADDING_INFO));
  245. pi.pszAlgId = BCRYPT_SHA256_ALGORITHM;
  246. ULONG result_size = 0;
  247. PUCHAR _result = NULL;
  248. ULONG blob_size = export_size - sizeof(BCRYPT_KEY_DATA_BLOB_HEADER);
  249. PUCHAR blob = _delivery_key + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER);
  250. status = BCryptEncrypt(hUpdateKey, blob, blob_size, &pi, NULL, 0, NULL, 0, &result_size, BCRYPT_PAD_OAEP);
  251. if (status) {
  252. delete[] _delivery_key;
  253. BCryptDestroyKey(hUpdateKey);
  254. throw runtime_error("BCryptEncrypt: calculating result size");
  255. }
  256. _result = new UCHAR[result_size + 1];
  257. status = BCryptEncrypt(hUpdateKey, blob, blob_size, &pi, NULL, 0, _result, result_size, &copied, BCRYPT_PAD_OAEP);
  258. delete[] _delivery_key;
  259. if (status) {
  260. BCryptDestroyKey(hUpdateKey);
  261. delete[] _result;
  262. throw runtime_error("BCryptEncrypt: encrypting using update_key");
  263. }
  264. BCryptDestroyKey(hUpdateKey);
  265. stringstream s;
  266. for (ULONG i = 0; i < copied; i++) {
  267. s << hex << setw(2) << setfill('0');
  268. s << (int)_result[i];
  269. }
  270. delete[] _result;
  271. s >> result;
  272. return result;
  273. }
  274. void GateKeeper::enable_update()
  275. {
  276. LONG lResult = RegOpenKeyEx(cu, updater_reg_path, 0, KEY_WRITE, &hkUpdater);
  277. if (lResult != ERROR_SUCCESS)
  278. return;
  279. lResult = RegSetValueExW(hkUpdater, NULL, 0, REG_SZ, (const BYTE *) _T("1"), sizeof(TCHAR)*2);
  280. }
  281. void GateKeeper::disable_update()
  282. {
  283. LONG lResult = RegOpenKeyEx(cu, updater_reg_path, 0, KEY_WRITE, &hkUpdater);
  284. if (lResult != ERROR_SUCCESS)
  285. return;
  286. lResult = RegSetValueEx(hkUpdater, NULL, 0, REG_SZ, (const BYTE *) _T("0"), sizeof(TCHAR) * 2);
  287. }
  288. bool GateKeeper::update_enabled()
  289. {
  290. bool enabled = true;
  291. DWORD esize;
  292. RegGetValue(cu, updater_reg_path, NULL, RRF_RT_REG_SZ, NULL, NULL, &esize);
  293. if (esize) {
  294. TCHAR* edata = new TCHAR[esize];
  295. RegGetValue(cu, updater_reg_path, NULL, RRF_RT_REG_SZ, NULL, edata, &esize);
  296. if (tstring(edata) == _T("0"))
  297. enabled = false;
  298. delete[] edata;
  299. }
  300. return enabled;
  301. }
  302. GateKeeper::product_list GateKeeper::registered_products()
  303. {
  304. product_list products;
  305. // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
  306. static TCHAR value_name[16384];
  307. DWORD value_name_size;
  308. static TCHAR value[L_MAX_URL_LENGTH + 1];
  309. DWORD value_size;
  310. LONG lResult = ERROR_SUCCESS;
  311. for (DWORD i = 0; lResult == ERROR_SUCCESS; i++) {
  312. value_name_size = 16383;
  313. value_size = L_MAX_URL_LENGTH + 1;
  314. lResult = RegEnumValue(hkUpdater, i, value_name, &value_name_size, NULL, NULL, (LPBYTE)value, &value_size);
  315. if (lResult == ERROR_SUCCESS) {
  316. products.push_back({ value_name, value });
  317. }
  318. }
  319. return products;
  320. }
  321. void GateKeeper::execute_file(tstring filename)
  322. {
  323. HANDLE hMutex = CreateMutex(NULL, TRUE, _T("PEPINSTALLERMUTEX"));
  324. if (hMutex) {
  325. CloseHandle(hMutex);
  326. ShellExecute(NULL, _T("open"), filename.c_str(), NULL, NULL, SW_SHOW);
  327. }
  328. }
  329. tstring GateKeeper::get_lockFile()
  330. {
  331. static const tstring _fileName = _T("\\pEpSetup.lck");
  332. static tstring fileName;
  333. if (fileName.length() == 0) {
  334. unique_ptr < TCHAR[] > _pathName(new TCHAR[MAX_PATH + 1]);
  335. DWORD size = GetTempPath(MAX_PATH, _pathName.get());
  336. if (size > MAX_PATH - _fileName.size())
  337. throw runtime_error("TEMP path too long");
  338. fileName = _pathName.get();
  339. fileName += _fileName;
  340. }
  341. return fileName;
  342. }
  343. // Retrieving Headers Using HTTP_QUERY_CUSTOM
  344. static tstring httpQueryCustom(HINTERNET hHttp, tstring header)
  345. {
  346. DWORD dwResult = 0;
  347. LPTSTR lpOutBuffer = StrDup(header.c_str());
  348. retry:
  349. if (!HttpQueryInfo(hHttp, HTTP_QUERY_CUSTOM, (LPVOID)lpOutBuffer, &dwResult, NULL))
  350. {
  351. if (GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND)
  352. {
  353. // Code to handle the case where the header isn't available.
  354. LocalFree(lpOutBuffer);
  355. throw(runtime_error("ERROR_HTTP_HEADER_NOT_FOUND"));
  356. }
  357. else
  358. {
  359. // Check for an insufficient buffer.
  360. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  361. {
  362. // Allocate the necessary buffer.
  363. LocalFree(lpOutBuffer);
  364. lpOutBuffer = (LPTSTR)LocalAlloc(LMEM_FIXED, dwResult + 1);
  365. // Rewrite the header name in the buffer.
  366. StringCchPrintf(lpOutBuffer, dwResult, header.c_str());
  367. // Retry the call.
  368. goto retry;
  369. }
  370. else
  371. {
  372. // Error handling code.
  373. LocalFree(lpOutBuffer);
  374. // FIXME: Add GetLastError()
  375. throw(runtime_error("Unknown"));
  376. }
  377. }
  378. }
  379. tstring result(lpOutBuffer);
  380. LocalFree(lpOutBuffer);
  381. return result;
  382. }
  383. bool GateKeeper::update_product(product p, DWORD context)
  384. {
  385. {
  386. HANDLE file = CreateFile(get_lockFile().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
  387. if (file == INVALID_HANDLE_VALUE) {
  388. return false;
  389. }
  390. else {
  391. CloseHandle(file);
  392. DeleteFile(get_lockFile().c_str());
  393. }
  394. }
  395. BCRYPT_KEY_HANDLE dk = delivery_key();
  396. #ifdef UNICODE
  397. tstring delivery = utility::utf16_string(wrapped_delivery_key(dk));
  398. #else
  399. tstring delivery = wrapped_delivery_key(delivery_key());
  400. #endif
  401. tstring url = p.second;
  402. url += _T("&challenge=");
  403. url += delivery;
  404. tstring headers;
  405. HINTERNET hUrl = InternetOpenUrl(internet, url.c_str(), headers.c_str(), headers.length(),
  406. INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE, context);
  407. if (hUrl == NULL)
  408. return false;
  409. string crypted;
  410. string unencrypted;
  411. UCHAR iv[12];
  412. UCHAR nonce[sizeof(iv)];
  413. UCHAR tag[16];
  414. tstring filename;
  415. HANDLE hFile = NULL;
  416. char *unencrypted_buffer = NULL;
  417. bool result = false;
  418. try {
  419. DWORD reading;
  420. InternetReadFile(hUrl, iv, sizeof(iv), &reading);
  421. if (reading)
  422. mainWindow.ShowNotificationInfo(r(IDS_DOWNLOADTITLE), r(IDS_DOWNLOADTEXT));
  423. if (reading) do {
  424. static char buffer[1024 * 1024];
  425. BOOL bResult = InternetReadFile(hUrl, buffer, 1024 * 1024, &reading);
  426. if (!bResult || !reading)
  427. break;
  428. crypted += string(buffer, reading);
  429. } while (1);
  430. tstring contentDisposition = httpQueryCustom(hUrl, _T("Content-Disposition"));
  431. tregex filenameRegex(_T("filename=.([^\"]*)"), regex::extended); //FIXME: case insensitive
  432. tsmatch match;
  433. if (regex_search(contentDisposition, match, filenameRegex)) {
  434. filename = match[1];
  435. }
  436. InternetCloseHandle(hUrl);
  437. hUrl = NULL;
  438. memcpy(nonce, iv, sizeof(iv));
  439. BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo;
  440. BCRYPT_INIT_AUTH_MODE_INFO(authInfo);
  441. authInfo.pbNonce = nonce;
  442. authInfo.cbNonce = sizeof(nonce);
  443. authInfo.pbTag = tag;
  444. authInfo.cbTag = sizeof(tag);
  445. ULONG unencrypted_size;
  446. NTSTATUS status = BCryptDecrypt(dk, (PUCHAR)crypted.data(), crypted.size(),
  447. &authInfo, iv, sizeof(iv), NULL, 0, &unencrypted_size, 0);
  448. if (status)
  449. goto closing;
  450. unencrypted_buffer = new char[unencrypted_size];
  451. PUCHAR crypted_data = (PUCHAR)crypted.data();
  452. ULONG crypted_size = (ULONG)crypted.size() - sizeof(tag);
  453. memcpy(tag, crypted_data + crypted_size, sizeof(tag));
  454. status = BCryptDecrypt(dk, crypted_data, crypted_size,
  455. &authInfo, iv, sizeof(iv), (PUCHAR)unencrypted_buffer, unencrypted_size, &unencrypted_size, 0);
  456. if (status)
  457. goto closing;
  458. BCryptDestroyKey(dk);
  459. TCHAR download_path[MAX_PATH + 1];
  460. PWSTR _downloads;
  461. SHGetKnownFolderPath(FOLDERID_Downloads, 0, NULL, &_downloads);
  462. StringCchCopy(download_path, MAX_PATH, _downloads);
  463. CoTaskMemFree(_downloads);
  464. GetTempPath(MAX_PATH, download_path);
  465. if (filename == _T("")) {
  466. filename = download_path;
  467. filename += _T("\\pEp_");
  468. filename += delivery.substr(0, 32);
  469. filename += _T(".msi");
  470. }
  471. else {
  472. filename = tstring(download_path) + _T("\\") + filename;
  473. }
  474. hFile = CreateFile(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  475. if (!hFile)
  476. goto closing;
  477. DWORD writing;
  478. WriteFile(hFile, unencrypted_buffer, unencrypted_size, &writing, NULL);
  479. CloseHandle(hFile);
  480. hFile = NULL;
  481. delete[] unencrypted_buffer;
  482. unencrypted_buffer = nullptr;
  483. }
  484. catch (exception&) {
  485. goto closing;
  486. }
  487. execute_file(filename);
  488. result = true;
  489. closing:
  490. if (unencrypted_buffer)
  491. delete[] unencrypted_buffer;
  492. if (hFile)
  493. CloseHandle(hFile);
  494. if (hUrl)
  495. InternetCloseHandle(hUrl);
  496. BCryptDestroyKey(dk);
  497. return result;
  498. }
  499. void GateKeeper::update_now()
  500. {
  501. NTSTATUS status = BCryptOpenAlgorithmProvider(&hAES, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
  502. assert(status == 0);
  503. if (status)
  504. goto closing;
  505. status = BCryptSetProperty(hAES, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0);
  506. if (status)
  507. goto closing;
  508. status = BCryptOpenAlgorithmProvider(&hRSA, BCRYPT_RSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
  509. assert(status == 0);
  510. if (status)
  511. goto closing;
  512. internet = InternetOpen(_T("pEp"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
  513. if (!internet)
  514. goto closing;
  515. {
  516. product_list products = registered_products();
  517. DWORD context = 0;
  518. for (auto i = products.begin(); i != products.end(); i++) {
  519. try {
  520. update_product(*i, context++);
  521. }
  522. catch (exception&) {
  523. }
  524. }
  525. }
  526. closing:
  527. if (internet)
  528. InternetCloseHandle(internet);
  529. if (hAES)
  530. BCryptCloseAlgorithmProvider(hAES, 0);
  531. if (hRSA)
  532. BCryptCloseAlgorithmProvider(hRSA, 0);
  533. internet = NULL;
  534. hAES = NULL;
  535. hRSA = NULL;
  536. }
  537. void GateKeeper::show_notification(tstring title, tstring text)
  538. {
  539. mainWindow.ShowNotificationInfo(title, text);
  540. }
  541. GateKeeper *GateKeeper::the_gatekeeper = nullptr;
  542. } // namespace pEp