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.

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