GateKeeper.cpp
author Volker Birk <vb@pep-project.org>
Tue, 21 Jun 2016 22:54:19 +0200
changeset 112 288c0ee0d916
parent 111 b89e8368e968
child 113 b1bcfae25d26
permissions -rw-r--r--
delivery key
     1 #include "stdafx.h"
     2 
     3 #include "GateKeeper.h"
     4 #include "pEpCOMServerAdapter.h"
     5 
     6 using namespace std;
     7 
     8 namespace pEp {
     9 
    10     const LPCTSTR GateKeeper::plugin_reg_path = _T("Software\\Microsoft\\Office\\Outlook\\Addins\\pEp");
    11     const LPCTSTR GateKeeper::plugin_reg_value_name = _T("LoadBehavior");
    12     const LPCTSTR GateKeeper::updater_reg_path = _T("Software\\pEp\\Updater";)
    13 
    14     const time_t GateKeeper::cycle = 7200;   // 7200 sec is 2 h
    15     const DWORD GateKeeper::waiting = 10000; // 10000 ms is 10 sec
    16 
    17     GateKeeper::GateKeeper(CpEpCOMServerAdapterModule * const self)
    18         : _self(self), now(time(NULL)), next(now + time_diff()), hkUpdater(NULL), internet(NULL)
    19     {
    20         LONG lResult = RegOpenCurrentUser(KEY_READ, &cu);
    21         assert(lResult == ERROR_SUCCESS);
    22         if (lResult == ERROR_SUCCESS)
    23             cu_open = true;
    24         else
    25             cu_open = false;
    26 
    27         if (cu_open) {
    28             LONG lResult = RegOpenKeyEx(cu, updater_reg_path, 0, KEY_READ, &hkUpdater);
    29             assert(lResult == ERROR_SUCCESS);
    30             if (lResult != ERROR_SUCCESS)
    31                 return;
    32         }
    33     }
    34     
    35     GateKeeper::~GateKeeper()
    36     {
    37         if (cu_open) {
    38             if (hkUpdater)
    39                 RegCloseKey(hkUpdater);
    40             RegCloseKey(cu);
    41         }
    42     }
    43 
    44     time_t GateKeeper::time_diff()
    45     {
    46         try {
    47             static random_device rd;
    48             static mt19937 gen(rd());
    49 
    50             uniform_int_distribution<time_t> dist(0, cycle);
    51 
    52             return dist(gen);
    53         }
    54         catch (exception&) {
    55             assert(0);
    56             return 0;
    57         }
    58     }
    59 
    60     void GateKeeper::keep()
    61     {
    62         if (!cu_open)
    63             return;
    64 
    65         while (1) {
    66             keep_plugin();
    67 
    68             now = time(NULL);
    69             assert(now != -1);
    70 
    71             if (now > next) {
    72                 next = now + GateKeeper::cycle;
    73                 keep_updated();
    74             }
    75 
    76             Sleep(waiting);
    77         }
    78     }
    79 
    80     void GateKeeper::keep_plugin()
    81     {
    82         while (!_self->m_bComInitialized)
    83             Sleep(1);
    84 
    85         MessageBox(NULL, _T("test"), _T("keep_plugin"), MB_ICONINFORMATION | MB_TOPMOST);
    86 
    87         DWORD value;
    88         DWORD size;
    89 
    90         LONG lResult = RegGetValue(cu, plugin_reg_path, plugin_reg_value_name, RRF_RT_REG_DWORD, NULL, &value, &size);
    91         if (lResult != ERROR_SUCCESS)
    92             return;
    93 
    94         if (value != 3) {
    95             lResult = RegSetValue(cu, plugin_reg_path, RRF_RT_REG_DWORD, plugin_reg_value_name, 3);
    96             assert(lResult == ERROR_SUCCESS);
    97         }
    98     }
    99 
   100     string GateKeeper::update_key()
   101     {
   102         static string key;
   103 
   104         if (key.length() == 0) {
   105             HRSRC res = FindResource(_self->hModule(), MAKEINTRESOURCE(IRD_UPDATEKEY), RT_RCDATA);
   106             assert(res);
   107             if (!res)
   108                 throw runtime_error("FindResource: IRD_UPDATEKEY");
   109 
   110             HGLOBAL hRes = LoadResource(_self->hModule(), res);
   111             assert(hRes);
   112             if (!hRes)
   113                 throw runtime_error("LoadResource: IRD_UPDATEKEY");
   114 
   115             key = string((char *)LockResource(hRes), SizeofResource(_self->hModule(), res));
   116             UnlockResource(hRes);
   117         }
   118 
   119         return key;
   120     }
   121 
   122     GateKeeper::aeskey_t GateKeeper::delivery_key()
   123     {
   124         aeskey_t key;
   125 
   126         static random_device rd;
   127         static mt19937 gen(rd());
   128 
   129         uniform_int_distribution<time_t> dist(0, UINT64_MAX);
   130 
   131         key.ll_key[0] = dist(gen);
   132         key.ll_key[1] = dist(gen);
   133     }
   134 
   135     GateKeeper::product_list& GateKeeper::registered_products()
   136     {
   137         static product_list products;
   138 
   139         // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
   140         static TCHAR value_name[16384];
   141         DWORD value_name_size;
   142         static TCHAR value[L_MAX_URL_LENGTH + 1];
   143         DWORD value_size;
   144 
   145         products.empty();
   146 
   147         LONG lResult = ERROR_SUCCESS;
   148         for (DWORD i = 0; lResult == ERROR_SUCCESS; i++) {
   149             value_size = L_MAX_URL_LENGTH + 1;
   150             lResult = RegEnumValue(hkUpdater, 0, value_name, &value_name_size, NULL, NULL, (LPBYTE) value, &value_size);
   151             if (lResult == ERROR_SUCCESS)
   152                 products.push_back({ value_name, value });
   153         }
   154 
   155         return products;
   156     }
   157 
   158     void GateKeeper::update_product(product p, DWORD context)
   159     {
   160         HINTERNET hUrl = InternetOpenUrl(internet, p.second.c_str(), NULL, 0,
   161                 INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE, context);
   162         if (hUrl == NULL)
   163             return;
   164 
   165         // update
   166         PCTSTR rgpszAcceptTypes[] = { _T("text/plain"), NULL };
   167         HINTERNET hRequest = HttpOpenRequest(hUrl, NULL, _T("challenge"), NULL, NULL, rgpszAcceptTypes, INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE, context);
   168 
   169 
   170         InternetCloseHandle(hUrl);
   171     }
   172 
   173     void GateKeeper::keep_updated()
   174     {
   175         return; // disabled for now
   176 
   177         internet = InternetOpen(_T("pEp"), INTERNET_OPEN_TYPE_PROXY, NULL, NULL, 0);
   178 
   179         product_list& products = registered_products();
   180         DWORD context = 0;
   181         for (auto i = products.begin(); i != products.end(); i++) {
   182             update_product(*i, context++);
   183         }
   184 
   185         InternetCloseHandle(internet);
   186         internet = NULL;
   187     }
   188 
   189 } // namespace pEp