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.

1318 lines
33 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 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
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. // CpEpEngine.cpp : Implementation of CpEpEngine
  2. #include "stdafx.h"
  3. #include "CpEpEngine.h"
  4. using namespace std;
  5. using namespace pEp::utility;
  6. // CpEpEngine
  7. STDMETHODIMP CpEpEngine::InterfaceSupportsErrorInfo(REFIID riid)
  8. {
  9. static const IID* const arr[] =
  10. {
  11. &IID_IpEpEngine
  12. };
  13. for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
  14. {
  15. if (InlineIsEqualGUID(*arr[i],riid))
  16. return S_OK;
  17. }
  18. return S_FALSE;
  19. }
  20. #define FAIL(msg) error(msg)
  21. STDMETHODIMP CpEpEngine::verbose_logging(VARIANT_BOOL enable)
  22. {
  23. verbose_mode = enable != VARIANT_FALSE;
  24. return S_OK;
  25. }
  26. STDMETHODIMP CpEpEngine::passive_mode(VARIANT_BOOL enable)
  27. {
  28. ::config_passive_mode(get_session(), enable != VARIANT_FALSE);
  29. return S_OK;
  30. }
  31. STDMETHODIMP CpEpEngine::unencrypted_subject(VARIANT_BOOL enable)
  32. {
  33. ::config_unencrypted_subject(get_session(), enable != VARIANT_FALSE);
  34. return S_OK;
  35. }
  36. STDMETHODIMP CpEpEngine::log(BSTR title, BSTR entity, BSTR description, BSTR comment)
  37. {
  38. string _title;
  39. string _entity;
  40. string _description;
  41. string _comment;
  42. HRESULT result = S_OK;
  43. assert(title);
  44. if (title)
  45. _title = utf8_string(title);
  46. else
  47. result = E_INVALIDARG;
  48. assert(entity);
  49. if (entity)
  50. _entity = utf8_string(entity);
  51. else
  52. result = E_INVALIDARG;
  53. if (description)
  54. _description = utf8_string(description);
  55. if (comment)
  56. _comment = utf8_string(comment);
  57. if (result != S_OK)
  58. return result;
  59. PEP_STATUS _status = ::log_event(get_session(), _title.c_str(), _entity.c_str(), _description.c_str(), _comment.c_str());
  60. assert(_status == PEP_STATUS_OK);
  61. if (_status != PEP_STATUS_OK)
  62. return FAIL(L"log_event");
  63. else
  64. return S_OK;
  65. }
  66. STDMETHODIMP CpEpEngine::decrypt(BSTR ctext, BSTR * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
  67. {
  68. assert(ctext);
  69. assert(ptext);
  70. assert(key_list);
  71. assert(status);
  72. if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
  73. if (ptext)
  74. *ptext = NULL;
  75. if (key_list)
  76. *key_list = NULL;
  77. if (status)
  78. *status = pEp_UNENCRYPTED;
  79. return E_INVALIDARG;
  80. }
  81. string _ctext = utf8_string(ctext);
  82. char *_ptext = NULL;
  83. size_t _psize = 0;
  84. ::stringlist_t *_keylist = NULL;
  85. PEP_STATUS _status;
  86. _status = ::decrypt_and_verify(get_session(), _ctext.c_str(), _ctext.size(), &_ptext, &_psize, &_keylist);
  87. assert(_status != PEP_OUT_OF_MEMORY);
  88. if (_status == PEP_OUT_OF_MEMORY)
  89. return E_OUTOFMEMORY;
  90. *status = (pEp_STATUS) _status;
  91. if (_ptext == NULL) {
  92. if (_keylist) {
  93. string msg;
  94. if (_keylist->value[0] != 0) {
  95. msg = _keylist->value;
  96. }
  97. else {
  98. for (::stringlist_t *s = _keylist->next; s != NULL; s = s->next) {
  99. if (s->value) {
  100. msg += s->value;
  101. msg += ";";
  102. }
  103. }
  104. }
  105. ::free_stringlist(_keylist);
  106. return FAIL(utf16_bstr(msg));
  107. }
  108. else
  109. return FAIL(L"cannot decrypt");
  110. }
  111. *ptext = utf16_bstr(_ptext);
  112. pEp_free(_ptext);
  113. if (_keylist && _keylist->value)
  114. *key_list = string_array(_keylist);
  115. else
  116. *key_list = NULL;
  117. ::free_stringlist(_keylist);
  118. return S_OK;
  119. }
  120. STDMETHODIMP CpEpEngine::decrypt_b(BSTR ctext, LPSAFEARRAY * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
  121. {
  122. assert(ctext);
  123. assert(ptext);
  124. assert(key_list);
  125. assert(status);
  126. if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
  127. if (ptext)
  128. *ptext = NULL;
  129. if (key_list)
  130. *key_list = NULL;
  131. if (status)
  132. *status = pEp_UNENCRYPTED;
  133. return E_INVALIDARG;
  134. }
  135. // Welcome to Windoze string hell!
  136. char *_ctext = NULL;
  137. _bstr_t bstr_ctext(ctext, true);
  138. int w_csize = bstr_ctext.length() + 1;
  139. int _csize = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, NULL, 0, NULL, NULL);
  140. if (_csize) {
  141. _ctext = new char[_csize];
  142. WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, _ctext, _csize, NULL, NULL);
  143. }
  144. char *_ptext = NULL;
  145. size_t _psize = 0;
  146. ::stringlist_t *_keylist = NULL;
  147. PEP_STATUS _status;
  148. _status = ::decrypt_and_verify(get_session(), _ctext, _csize, &_ptext, &_psize, &_keylist);
  149. assert(_status != PEP_OUT_OF_MEMORY);
  150. delete[] _ctext;
  151. if (_status == PEP_OUT_OF_MEMORY) {
  152. ::free_stringlist(_keylist);
  153. return E_OUTOFMEMORY;
  154. }
  155. *status = (pEp_STATUS) _status;
  156. if (_ptext == NULL) {
  157. ::free_stringlist(_keylist);
  158. return FAIL(L"decrypt_and_verify");
  159. }
  160. CComSafeArray<BYTE> sa_ptext;
  161. HRESULT _result = sa_ptext.Create(_psize, 0);
  162. assert(_result == S_OK);
  163. if (_result == E_OUTOFMEMORY) {
  164. pEp_free(_ptext);
  165. ::free_stringlist(_keylist);
  166. return E_OUTOFMEMORY;
  167. }
  168. else if (_result != S_OK) {
  169. pEp_free(_ptext);
  170. ::free_stringlist(_keylist);
  171. return FAIL(L"CComSafeArray<BYTE>::Create");
  172. }
  173. memcpy(sa_ptext.m_psa->pvData, _ptext, _psize);
  174. *ptext = sa_ptext.Detach();
  175. ::pEp_free(_ptext);
  176. if (_keylist && _keylist->value)
  177. *key_list = string_array(_keylist);
  178. else
  179. *key_list = NULL;
  180. ::free_stringlist(_keylist);
  181. return S_OK;
  182. }
  183. STDMETHODIMP CpEpEngine::verify(BSTR text, BSTR signature, LPSAFEARRAY * key_list, pEp_STATUS * verify_status)
  184. {
  185. assert(text);
  186. assert(signature);
  187. assert(key_list);
  188. if (text == NULL || signature == NULL || key_list == NULL)
  189. return E_INVALIDARG;
  190. string _text = utf8_string(text);
  191. string _signature = utf8_string(signature);
  192. ::stringlist_t *_keylist = NULL;
  193. PEP_STATUS _status;
  194. _status = ::verify_text(get_session(), _text.c_str(), _text.size(), _signature.c_str(), _signature.size(), &_keylist);
  195. assert(_status != PEP_OUT_OF_MEMORY);
  196. if (_status == PEP_OUT_OF_MEMORY)
  197. return E_OUTOFMEMORY;
  198. if (_status == PEP_DECRYPT_WRONG_FORMAT || _status == PEP_UNKNOWN_ERROR)
  199. return FAIL(L"verify_text");
  200. *verify_status = (pEp_STATUS) _status;
  201. if (_keylist && _keylist->value)
  202. *key_list = string_array(_keylist);
  203. else
  204. *key_list = NULL;
  205. ::free_stringlist(_keylist);
  206. return S_OK;
  207. }
  208. STDMETHODIMP CpEpEngine::encrypt(SAFEARRAY * key_list, BSTR ptext, BSTR * ctext, pEp_STATUS * status)
  209. {
  210. assert(key_list);
  211. assert(ptext);
  212. assert(ctext);
  213. assert(status);
  214. if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
  215. if (ctext)
  216. *ctext = NULL;
  217. if (status)
  218. *status = pEp_UNKNOWN_ERROR;
  219. return E_INVALIDARG;
  220. }
  221. HRESULT result = S_OK;
  222. ::stringlist_t *_keylist = new_stringlist(key_list);
  223. string _ptext = utf8_string(ptext);
  224. char *_ctext = NULL;
  225. size_t _csize = 0;
  226. PEP_STATUS _status;
  227. _status = ::encrypt_and_sign(get_session(), _keylist, _ptext.c_str(), _ptext.size(), &_ctext, &_csize);
  228. assert(_status != PEP_OUT_OF_MEMORY);
  229. ::free_stringlist(_keylist);
  230. if (_status == PEP_OUT_OF_MEMORY)
  231. return E_OUTOFMEMORY;
  232. *status = (pEp_STATUS) _status;
  233. if (_ctext == NULL)
  234. return FAIL(L"encrypt_and_sign");
  235. *ctext = utf16_bstr(_ctext);
  236. pEp_free(_ctext);
  237. return S_OK;
  238. }
  239. STDMETHODIMP CpEpEngine::encrypt_b(SAFEARRAY * key_list, SAFEARRAY * ptext, BSTR * ctext, pEp_STATUS * status)
  240. {
  241. assert(key_list);
  242. assert(ptext);
  243. assert(ctext);
  244. assert(status);
  245. if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
  246. if (ctext)
  247. *ctext = NULL;
  248. if (status)
  249. *status = pEp_UNKNOWN_ERROR;
  250. return E_INVALIDARG;
  251. }
  252. HRESULT result = S_OK;
  253. ::stringlist_t *_keylist = new_stringlist(key_list);
  254. char *_ctext = NULL;
  255. size_t _csize = 0;
  256. ::PEP_STATUS _status;
  257. _status = ::encrypt_and_sign(get_session(), _keylist, (const char *) ptext->pvData, ptext->rgsabound[0].cElements, &_ctext, &_csize);
  258. assert(_status != PEP_OUT_OF_MEMORY);
  259. ::free_stringlist(_keylist);
  260. if (_status == PEP_OUT_OF_MEMORY)
  261. return E_OUTOFMEMORY;
  262. *status = (pEp_STATUS) _status;
  263. if (_ctext == NULL)
  264. return FAIL(L"encrypt_and_sign");
  265. *status = (pEp_STATUS) _status;
  266. wchar_t *w_ctext = NULL;
  267. int w_csize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, NULL, 0);
  268. if (w_csize) {
  269. w_ctext = new wchar_t[w_csize + 1];
  270. MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, w_ctext, w_csize);
  271. w_ctext[w_csize] = 0; // this is for debugging; Visual Studio will crash without that if you're unlucky
  272. }
  273. *ctext = ::SysAllocStringLen(w_ctext, w_csize);
  274. assert(ctext);
  275. delete[] w_ctext;
  276. pEp_free(_ctext);
  277. if (ctext == NULL)
  278. return E_OUTOFMEMORY;
  279. return S_OK;
  280. }
  281. STDMETHODIMP CpEpEngine::trustword(LONG value, BSTR lang, BSTR * word)
  282. {
  283. assert(value >= 0 && value <= 65535);
  284. assert(word);
  285. HRESULT result = S_OK;
  286. uint16_t _value = 0;
  287. if (value < 0 || value > 65535)
  288. result = E_INVALIDARG;
  289. else
  290. _value = (uint16_t) value;
  291. string _lang = "en";
  292. if (lang) {
  293. _lang = utf8_string(lang);
  294. if (_lang.length() != 2)
  295. result = E_INVALIDARG;
  296. }
  297. if (word == NULL)
  298. result = E_INVALIDARG;
  299. if (result != S_OK)
  300. return result;
  301. char *_word = NULL;
  302. size_t _wsize = 0;
  303. PEP_STATUS status = ::trustword(get_session(), _value, _lang.c_str(), &_word, &_wsize);
  304. assert(status != PEP_OUT_OF_MEMORY);
  305. if (status == PEP_OUT_OF_MEMORY)
  306. return E_OUTOFMEMORY;
  307. if (_word == NULL) {
  308. *word = NULL;
  309. return FAIL(L"trustword");
  310. }
  311. else {
  312. *word = utf16_bstr(_word);
  313. pEp_free(_word);
  314. return S_OK;
  315. }
  316. }
  317. STDMETHODIMP CpEpEngine::trustwords(BSTR fpr, BSTR lang, LONG max_words, BSTR * words)
  318. {
  319. assert(fpr);
  320. assert(max_words >= 0);
  321. assert(words);
  322. HRESULT result = S_OK;
  323. string _fpr;
  324. if (fpr)
  325. _fpr = utf8_string(fpr);
  326. else
  327. result = E_INVALIDARG;
  328. string _lang;
  329. if (lang) {
  330. _lang = utf8_string(lang);
  331. if (_lang.length()) {
  332. if (_lang.length() != 2)
  333. result = E_INVALIDARG;
  334. }
  335. else
  336. _lang = "en";
  337. }
  338. else
  339. _lang = "en";
  340. if (max_words < 0)
  341. result = E_INVALIDARG;
  342. if (words == NULL)
  343. result = E_INVALIDARG;
  344. if (result != S_OK)
  345. return result;
  346. char *_words = NULL;
  347. size_t _wsize = 0;
  348. PEP_STATUS status = ::trustwords(get_session(), _fpr.c_str(), _lang.c_str(), &_words, &_wsize, max_words);
  349. assert(status != PEP_OUT_OF_MEMORY);
  350. if (status == PEP_OUT_OF_MEMORY)
  351. return E_OUTOFMEMORY;
  352. if (_words == NULL) {
  353. *words = NULL;
  354. return FAIL(L"trustwords");
  355. }
  356. else {
  357. *words = utf16_bstr(_words);
  358. pEp_free(_words);
  359. return S_OK;
  360. }
  361. }
  362. STDMETHODIMP CpEpEngine::get_crashdump_log(LONG maxlines, BSTR * log)
  363. {
  364. assert(maxlines >= 0);
  365. assert(log);
  366. if (!(maxlines >= 0 && log))
  367. return E_INVALIDARG;
  368. char *_log;
  369. PEP_STATUS status = ::get_crashdump_log(get_session(), (int) maxlines, &_log);
  370. assert(status == PEP_STATUS_OK);
  371. if (status == PEP_OUT_OF_MEMORY)
  372. return E_OUTOFMEMORY;
  373. if (status != PEP_STATUS_OK || _log == NULL)
  374. return FAIL(L"get_crashdump_log");
  375. *log = utf16_bstr(_log);
  376. pEp_free(_log);
  377. return S_OK;
  378. }
  379. STDMETHODIMP CpEpEngine::get_languagelist(BSTR * languages)
  380. {
  381. assert(languages);
  382. if (!languages)
  383. return E_INVALIDARG;
  384. char *_languages;
  385. PEP_STATUS status = ::get_languagelist(get_session(), &_languages);
  386. assert(status == PEP_STATUS_OK);
  387. if (status == PEP_OUT_OF_MEMORY)
  388. return E_OUTOFMEMORY;
  389. if (status != PEP_STATUS_OK || _languages == NULL)
  390. return FAIL(L"get_languagelist");
  391. *languages = utf16_bstr(_languages);
  392. pEp_free(_languages);
  393. return S_OK;
  394. }
  395. STDMETHODIMP CpEpEngine::get_phrase(BSTR lang, LONG phrase_id, BSTR * phrase)
  396. {
  397. assert(lang && phrase_id >= 0 && phrase);
  398. if (!(lang && phrase_id >= 0 && phrase))
  399. return E_INVALIDARG;
  400. string _lang = utf8_string(lang);
  401. assert(_lang.length() == 2);
  402. if (_lang.length() != 2)
  403. return E_INVALIDARG;
  404. char *_phrase;
  405. PEP_STATUS status = ::get_phrase(get_session(), _lang.c_str(), (int) phrase_id, &_phrase);
  406. assert(status == PEP_STATUS_OK);
  407. if (status == PEP_OUT_OF_MEMORY)
  408. return E_OUTOFMEMORY;
  409. if (status != PEP_STATUS_OK || _phrase == NULL)
  410. return FAIL(L"get_phrase");
  411. *phrase = utf16_bstr(_phrase);
  412. pEp_free(_phrase);
  413. return S_OK;
  414. }
  415. STDMETHODIMP CpEpEngine::get_identity(BSTR address, BSTR user_id, pEp_identity_s * ident)
  416. {
  417. assert(address);
  418. assert(user_id);
  419. assert(ident);
  420. if (address == NULL)
  421. return E_INVALIDARG;
  422. if (user_id == NULL)
  423. return E_INVALIDARG;
  424. if (ident == NULL)
  425. return E_INVALIDARG;
  426. string _address = utf8_string(address);
  427. string _user_id = utf8_string(user_id);
  428. ::pEp_identity *_ident = NULL;
  429. PEP_STATUS status = ::get_identity(get_session(), _address.c_str(), _user_id.c_str(), &_ident);
  430. assert(status != PEP_OUT_OF_MEMORY);
  431. if (status == PEP_OUT_OF_MEMORY)
  432. return E_OUTOFMEMORY;
  433. if (_ident == NULL) {
  434. return FAIL(L"get_identity");
  435. }
  436. copy_identity(ident, _ident);
  437. ::free_identity(_ident);
  438. return S_OK;
  439. }
  440. STDMETHODIMP CpEpEngine::set_identity(pEp_identity_s * ident)
  441. {
  442. assert(ident);
  443. assert(ident->address);
  444. assert(ident->fpr);
  445. assert(ident->username);
  446. assert(ident->user_id);
  447. if (ident == NULL || ident->address == NULL || ident->fpr == NULL
  448. || ident->username == NULL || ident->user_id == NULL)
  449. return E_INVALIDARG;
  450. ::pEp_identity *_ident = new_identity(ident);
  451. ::PEP_STATUS status = ::set_identity(get_session(), _ident);
  452. ::free_identity(_ident);
  453. if (status != ::PEP_STATUS_OK)
  454. return FAIL(L"set_identity");
  455. else
  456. return S_OK;
  457. }
  458. STDMETHODIMP CpEpEngine::generate_keypair(pEp_identity_s * ident, BSTR * fpr)
  459. {
  460. assert(ident);
  461. assert(ident->address);
  462. assert(ident->username);
  463. assert(fpr);
  464. if (ident == NULL || ident->address == NULL || ident->username == NULL || fpr == NULL)
  465. return E_INVALIDARG;
  466. ::pEp_identity *_ident = new_identity(ident);
  467. ::pEp_free(_ident->fpr);
  468. _ident->fpr = NULL;
  469. ::PEP_STATUS status = ::generate_keypair(get_session(), _ident);
  470. assert(status != ::PEP_OUT_OF_MEMORY);
  471. if (status == ::PEP_OUT_OF_MEMORY) {
  472. ::free_identity(_ident);
  473. return E_OUTOFMEMORY;
  474. }
  475. if (_ident->fpr)
  476. *fpr = utf16_bstr(_ident->fpr);
  477. ::free_identity(_ident);
  478. if (status != ::PEP_STATUS_OK)
  479. return FAIL(L"generate_keypair");
  480. return S_OK;
  481. }
  482. STDMETHODIMP CpEpEngine::delete_keypair(BSTR fpr)
  483. {
  484. assert(fpr);
  485. if (fpr == NULL)
  486. return E_INVALIDARG;
  487. string _fpr = utf8_string(fpr);
  488. ::PEP_STATUS status = ::delete_keypair(get_session(), _fpr.c_str());
  489. assert(status != PEP_OUT_OF_MEMORY);
  490. if (status == PEP_OUT_OF_MEMORY)
  491. return E_OUTOFMEMORY;
  492. if (status != ::PEP_STATUS_OK)
  493. return FAIL(L"delete_keypair");
  494. else
  495. return S_OK;
  496. }
  497. STDMETHODIMP CpEpEngine::import_key(BSTR key_data)
  498. {
  499. assert(key_data);
  500. if (key_data == NULL)
  501. return E_INVALIDARG;
  502. string _key_data = utf8_string(key_data);
  503. PEP_STATUS status = ::import_key(get_session(), _key_data.c_str(), _key_data.length(), NULL);
  504. assert(status != PEP_OUT_OF_MEMORY);
  505. if (status == PEP_OUT_OF_MEMORY)
  506. return E_OUTOFMEMORY;
  507. if (status != pEp_STATUS_OK)
  508. return FAIL(L"import_key");
  509. else
  510. return S_OK;
  511. }
  512. STDMETHODIMP CpEpEngine::import_key_b(SAFEARRAY * key_data)
  513. {
  514. assert(key_data);
  515. if (key_data == NULL)
  516. return E_INVALIDARG;
  517. ::PEP_STATUS status = ::import_key(get_session(), (const char *) key_data->pvData, key_data->rgsabound[0].cElements, NULL);
  518. assert(status != ::PEP_OUT_OF_MEMORY);
  519. if (status == ::PEP_OUT_OF_MEMORY)
  520. return E_OUTOFMEMORY;
  521. if (status != ::PEP_STATUS_OK)
  522. return FAIL(L"import_key");
  523. else
  524. return S_OK;
  525. }
  526. STDMETHODIMP CpEpEngine::export_key(BSTR fpr, BSTR * key_data)
  527. {
  528. assert(fpr);
  529. assert(key_data);
  530. if (fpr == NULL || key_data == NULL)
  531. return E_INVALIDARG;
  532. string _fpr = utf8_string(fpr);
  533. char *_key_data = NULL;
  534. size_t _size = 0;
  535. ::PEP_STATUS status = ::export_key(get_session(), _fpr.c_str(), &_key_data, &_size);
  536. assert(status != ::PEP_OUT_OF_MEMORY);
  537. if (status == ::PEP_OUT_OF_MEMORY)
  538. return E_OUTOFMEMORY;
  539. if (status != ::PEP_STATUS_OK)
  540. return FAIL(L"export_key");
  541. _bstr_t b_key_data(utf16_string(_key_data).c_str());
  542. pEp_free(_key_data);
  543. *key_data = b_key_data.Detach();
  544. return S_OK;
  545. }
  546. STDMETHODIMP CpEpEngine::recv_key(BSTR pattern)
  547. {
  548. assert(pattern);
  549. if (pattern == NULL)
  550. return E_INVALIDARG;
  551. string _pattern = utf8_string(pattern);
  552. PEP_STATUS status = ::recv_key(get_session(), _pattern.c_str());
  553. assert(status != PEP_OUT_OF_MEMORY);
  554. if (status == PEP_OUT_OF_MEMORY)
  555. return E_OUTOFMEMORY;
  556. if (status != ::PEP_STATUS_OK)
  557. return FAIL(L"recv_key");
  558. else
  559. return S_OK;
  560. }
  561. STDMETHODIMP CpEpEngine::find_keys(BSTR pattern, LPSAFEARRAY * key_list)
  562. {
  563. assert(pattern);
  564. assert(key_list);
  565. if (pattern == NULL || key_list == NULL)
  566. return E_INVALIDARG;
  567. string _pattern = utf8_string(pattern);
  568. ::stringlist_t *_keylist = NULL;
  569. PEP_STATUS status = ::find_keys(get_session(), _pattern.c_str(), &_keylist);
  570. assert(status != PEP_OUT_OF_MEMORY);
  571. if (status == PEP_OUT_OF_MEMORY)
  572. return E_OUTOFMEMORY;
  573. if (status != ::PEP_STATUS_OK)
  574. return FAIL(L"find_keys");
  575. if (_keylist && _keylist->value) {
  576. *key_list = string_array(_keylist);
  577. }
  578. else {
  579. ::free_stringlist(_keylist);
  580. return FAIL(L"find_keys: no keys found");
  581. }
  582. ::free_stringlist(_keylist);
  583. return S_OK;
  584. }
  585. STDMETHODIMP CpEpEngine::send_key(BSTR pattern)
  586. {
  587. assert(pattern);
  588. if (pattern == NULL)
  589. return E_INVALIDARG;
  590. string _pattern = utf8_string(pattern);
  591. ::PEP_STATUS status = ::send_key(get_session(), _pattern.c_str());
  592. if (status != ::PEP_STATUS_OK)
  593. return FAIL(L"send_key");
  594. else
  595. return S_OK;
  596. }
  597. STDMETHODIMP CpEpEngine::start_keyserver_lookup()
  598. {
  599. if (identity_queue.load())
  600. return S_OK;
  601. identity_queue.store(new identity_queue_t());
  602. keymanagement_thread = new thread(::do_keymanagement, retrieve_next_identity, (void *) identity_queue.load());
  603. return S_OK;
  604. }
  605. STDMETHODIMP CpEpEngine::stop_keyserver_lookup()
  606. {
  607. if (identity_queue.load() == NULL)
  608. return S_OK;
  609. identity_queue_t *_iq = identity_queue.load();
  610. identity_queue.store(NULL);
  611. pEp_identity_cpp shutdown;
  612. _iq->push_front(shutdown);
  613. keymanagement_thread->join();
  614. delete keymanagement_thread;
  615. keymanagement_thread = NULL;
  616. delete _iq;
  617. return S_OK;
  618. }
  619. STDMETHODIMP CpEpEngine::examine_identity(pEp_identity_s * ident)
  620. {
  621. assert(ident);
  622. if (ident == NULL)
  623. return E_INVALIDARG;
  624. if (identity_queue.load() == NULL) {
  625. try {
  626. identity_queue.load()->push_back(ident);
  627. }
  628. catch (bad_alloc) {
  629. return E_OUTOFMEMORY;
  630. }
  631. }
  632. return S_OK;
  633. }
  634. STDMETHODIMP CpEpEngine::myself(struct pEp_identity_s *ident, struct pEp_identity_s *result)
  635. {
  636. assert(ident);
  637. assert(result);
  638. if (ident == NULL || result == NULL)
  639. return E_INVALIDARG;
  640. ::pEp_identity *_ident = new_identity(ident);
  641. assert(_ident);
  642. if (_ident == NULL)
  643. return E_OUTOFMEMORY;
  644. // DEBUG CODE - REMOVE BEFORE RELEASE!
  645. // sync_handshake_result_s handshakeResult;
  646. //
  647. // HRESULT res = Fire_ShowHandshake(ident, result, &handshakeResult);
  648. //
  649. // HRESULT res2 = Fire_TestEvent(15, _bstr_t( "hallo"));
  650. PEP_STATUS status = ::myself(get_session(), _ident);
  651. if (status == PEP_STATUS_OK) {
  652. assert(_ident->fpr);
  653. copy_identity(result, _ident);
  654. ::free_identity(_ident);
  655. return S_OK;
  656. }
  657. else {
  658. ::free_identity(_ident);
  659. if (status == PEP_OUT_OF_MEMORY)
  660. return E_OUTOFMEMORY;
  661. else
  662. return FAIL(L"myself");
  663. }
  664. }
  665. STDMETHODIMP CpEpEngine::update_identity(struct pEp_identity_s *ident, struct pEp_identity_s *result)
  666. {
  667. assert(ident);
  668. assert(result);
  669. if (ident == NULL || result == NULL)
  670. return E_INVALIDARG;
  671. ::pEp_identity *_ident = new_identity(ident);
  672. assert(_ident);
  673. if (_ident == NULL)
  674. return E_OUTOFMEMORY;
  675. PEP_STATUS status = ::update_identity(get_session(), _ident);
  676. if (status == PEP_STATUS_OK) {
  677. assert(_ident->fpr);
  678. copy_identity(result, _ident);
  679. ::free_identity(_ident);
  680. return S_OK;
  681. }
  682. else {
  683. ::free_identity(_ident);
  684. if (status == PEP_OUT_OF_MEMORY)
  685. return E_OUTOFMEMORY;
  686. else
  687. return FAIL(L"update_identity");
  688. }
  689. }
  690. STDMETHODIMP CpEpEngine::key_compromized(struct pEp_identity_s *ident)
  691. {
  692. ::pEp_identity *_ident;
  693. assert(ident);
  694. try {
  695. _ident = new_identity(ident);
  696. }
  697. catch (bad_alloc&) {
  698. return E_OUTOFMEMORY;
  699. }
  700. catch (exception&) {
  701. return E_FAIL;
  702. }
  703. PEP_STATUS status = ::key_compromized(get_session(), _ident);
  704. free_identity(_ident);
  705. if (status == PEP_OUT_OF_MEMORY)
  706. return E_OUTOFMEMORY;
  707. if (status == PEP_KEY_NOT_FOUND)
  708. return FAIL(L"key not found");
  709. if (status != ::PEP_STATUS_OK)
  710. return FAIL(L"cannot revoke compromized key");
  711. return S_OK;
  712. }
  713. STDMETHODIMP CpEpEngine::key_reset_trust(struct pEp_identity_s *ident)
  714. {
  715. ::pEp_identity *_ident;
  716. assert(ident);
  717. try {
  718. _ident = new_identity(ident);
  719. }
  720. catch (bad_alloc&) {
  721. return E_OUTOFMEMORY;
  722. }
  723. catch (exception&) {
  724. return E_FAIL;
  725. }
  726. PEP_STATUS status = ::key_reset_trust(get_session(), _ident);
  727. free_identity(_ident);
  728. if (status == PEP_OUT_OF_MEMORY)
  729. return E_OUTOFMEMORY;
  730. if (status == PEP_KEY_NOT_FOUND)
  731. return FAIL(L"key not found");
  732. if (status != ::PEP_STATUS_OK)
  733. return FAIL(L"cannot reset trust");
  734. return S_OK;
  735. }
  736. int CpEpEngine::examine_identity(pEp_identity *ident, void *management)
  737. {
  738. assert(ident);
  739. assert(management);
  740. if (!(ident && management))
  741. return -1;
  742. CpEpEngine *me = (CpEpEngine *) management;
  743. if (me->identity_queue.load() == NULL)
  744. return 0;
  745. try {
  746. me->identity_queue.load()->push_back(ident);
  747. }
  748. catch (exception&) {
  749. return -1;
  750. }
  751. return 0;
  752. }
  753. ::pEp_identity * CpEpEngine::retrieve_next_identity(void *management)
  754. {
  755. assert(management);
  756. identity_queue_t *iq = (identity_queue_t *) management;
  757. do /* poll queue */ {
  758. if (iq->size())
  759. break;
  760. ::Sleep(100);
  761. } while (true);
  762. ::pEp_identity *_ident;
  763. pEp_identity_cpp& ident = iq->front();
  764. if (ident.address.size() == 0)
  765. return NULL;
  766. _ident = ident.to_pEp_identity();
  767. iq->pop_front();
  768. return _ident;
  769. }
  770. PEP_STATUS CpEpEngine::messageToSend(void * obj, const message *msg)
  771. {
  772. assert(msg);
  773. if (msg == NULL)
  774. return PEP_ILLEGAL_VALUE;
  775. text_message _msg;
  776. memset(&_msg, 0, sizeof(text_message));
  777. text_message_from_C(&_msg, msg);
  778. CpEpEngine *me = (CpEpEngine *) obj;
  779. HRESULT r = me->Fire_MessageToSend(&_msg);
  780. assert(r == S_OK);
  781. clear_text_message(&_msg);
  782. if (r == E_OUTOFMEMORY)
  783. return PEP_OUT_OF_MEMORY;
  784. if (r != S_OK)
  785. return PEP_UNKNOWN_ERROR;
  786. return PEP_STATUS_OK;
  787. }
  788. PEP_STATUS CpEpEngine::showHandshake(void * obj, const pEp_identity *self, const pEp_identity *partner)
  789. {
  790. assert(self && partner);
  791. if (!(self && partner))
  792. return PEP_ILLEGAL_VALUE;
  793. pEp_identity_s _self;
  794. copy_identity(&_self, self);
  795. pEp_identity_s _partner;
  796. copy_identity(&_partner, partner);
  797. CpEpEngine *me = (CpEpEngine *) obj;
  798. sync_handshake_result_s _result;
  799. HRESULT r = me->Fire_ShowHandshake(&_self, &_partner, &_result);
  800. assert(r == S_OK);
  801. clear_identity_s(_self);
  802. clear_identity_s(_partner);
  803. if (r == E_OUTOFMEMORY)
  804. return PEP_OUT_OF_MEMORY;
  805. if (r != S_OK)
  806. return PEP_UNKNOWN_ERROR;
  807. PEP_STATUS status = deliverHandshakeResult(me->get_session(), (sync_handshake_result) (int) _result);
  808. return status;
  809. }
  810. STDMETHODIMP CpEpEngine::blacklist_add(BSTR fpr)
  811. {
  812. assert(fpr);
  813. string _fpr = utf8_string(fpr);
  814. PEP_STATUS status = ::blacklist_add(get_session(), _fpr.c_str());
  815. assert(status == PEP_STATUS_OK);
  816. if (status != PEP_STATUS_OK)
  817. return FAIL(L"blacklist_add failed in pEp engine");
  818. return S_OK;
  819. }
  820. STDMETHODIMP CpEpEngine::blacklist_delete(BSTR fpr)
  821. {
  822. assert(fpr);
  823. string _fpr = utf8_string(fpr);
  824. PEP_STATUS status = ::blacklist_delete(get_session(), _fpr.c_str());
  825. assert(status == PEP_STATUS_OK);
  826. if (status != PEP_STATUS_OK)
  827. return FAIL(L"blacklist_delete failed in pEp engine");
  828. return S_OK;
  829. }
  830. STDMETHODIMP CpEpEngine::blacklist_is_listed(BSTR fpr, VARIANT_BOOL *listed)
  831. {
  832. assert(fpr);
  833. assert(listed);
  834. string _fpr = utf8_string(fpr);
  835. bool result;
  836. PEP_STATUS status = ::blacklist_is_listed(get_session(), _fpr.c_str(), &result);
  837. assert(status == PEP_STATUS_OK);
  838. if (status != PEP_STATUS_OK)
  839. return FAIL(L"blacklist_is_listed failed in pEp engine");
  840. *listed = result ? VARIANT_TRUE : VARIANT_FALSE;
  841. return S_OK;
  842. }
  843. STDMETHODIMP CpEpEngine::blacklist_retrieve(SAFEARRAY **blacklist)
  844. {
  845. assert(blacklist);
  846. ::stringlist_t *_blacklist = NULL;
  847. PEP_STATUS status = ::blacklist_retrieve(get_session(), &_blacklist);
  848. assert(status == PEP_STATUS_OK);
  849. if (status != PEP_STATUS_OK)
  850. return FAIL(L"blacklist_retrieve failed in pEp engine");
  851. assert(_blacklist);
  852. *blacklist = string_array(_blacklist);
  853. return S_OK;
  854. }
  855. HRESULT CpEpEngine::error(_bstr_t msg)
  856. {
  857. _bstr_t helpFile = L"";
  858. _bstr_t source = L"pEp COM Adapter";
  859. ICreateErrorInfo *cei;
  860. if (SUCCEEDED(CreateErrorInfo(&cei))) {
  861. cei->SetDescription(msg);
  862. cei->SetGUID(__uuidof(IpEpEngine));
  863. cei->SetHelpContext(0);
  864. cei->SetHelpFile(helpFile);
  865. cei->SetSource(source);
  866. IErrorInfo *errinfo;
  867. if (SUCCEEDED(cei->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &errinfo))) {
  868. SetErrorInfo(0, errinfo);
  869. errinfo->Release();
  870. }
  871. cei->Release();
  872. }
  873. return E_FAIL;
  874. }
  875. STDMETHODIMP CpEpEngine::encrypt_message(text_message * src, text_message * dst, SAFEARRAY * extra)
  876. {
  877. assert(src);
  878. assert(dst);
  879. ::message *_src = text_message_to_C(src);
  880. ::message *msg_dst;
  881. ::stringlist_t *_extra = new_stringlist(extra);
  882. PEP_STATUS status = ::encrypt_message(get_session(), _src, _extra, &msg_dst, PEP_enc_pieces);
  883. ::free_stringlist(_extra);
  884. if (status == PEP_STATUS_OK)
  885. text_message_from_C(dst, msg_dst);
  886. else
  887. text_message_from_C(dst, _src);
  888. ::free_message(msg_dst);
  889. ::free_message(_src);
  890. if (status == PEP_OUT_OF_MEMORY)
  891. return E_OUTOFMEMORY;
  892. return S_OK;
  893. }
  894. STDMETHODIMP CpEpEngine::decrypt_message(text_message * src, text_message * dst, SAFEARRAY ** keylist, pEp_color *rating)
  895. {
  896. assert(src);
  897. assert(dst);
  898. assert(keylist);
  899. assert(rating);
  900. *keylist = NULL;
  901. *rating = pEp_rating_undefined;
  902. ::message *_src = text_message_to_C(src);
  903. ::message *msg_dst = NULL;
  904. ::stringlist_t *_keylist;
  905. ::PEP_color _rating;
  906. PEP_decrypt_flags_t flags = 0;
  907. PEP_STATUS status = ::decrypt_message(get_session(), _src, &msg_dst, &_keylist, &_rating, &flags);
  908. // TODO : output decrypt flags.
  909. if (msg_dst)
  910. text_message_from_C(dst, msg_dst);
  911. ::free_message(_src);
  912. ::free_message(msg_dst);
  913. if (_keylist) {
  914. *keylist = string_array(_keylist);
  915. free_stringlist(_keylist);
  916. }
  917. *rating = (pEp_color) _rating;
  918. return S_OK;
  919. }
  920. STDMETHODIMP CpEpEngine::outgoing_message_color(text_message *msg, pEp_color * pVal)
  921. {
  922. assert(msg);
  923. assert(pVal);
  924. ::message *_msg = text_message_to_C(msg);
  925. PEP_color _color;
  926. PEP_STATUS status = ::outgoing_message_color(get_session(), _msg, &_color);
  927. if (status != PEP_STATUS_OK)
  928. return FAIL(L"cannot get message color");
  929. *pVal = (pEp_color) _color;
  930. return S_OK;
  931. }
  932. STDMETHODIMP CpEpEngine::identity_color(struct pEp_identity_s *ident, pEp_color * pVal)
  933. {
  934. ::pEp_identity *_ident;
  935. assert(ident);
  936. assert(pVal);
  937. try {
  938. _ident = new_identity(ident);
  939. }
  940. catch (bad_alloc&) {
  941. return E_OUTOFMEMORY;
  942. }
  943. catch (exception&) {
  944. return E_FAIL;
  945. }
  946. PEP_color _color;
  947. PEP_STATUS status = ::identity_color(get_session(), _ident, &_color);
  948. free_identity(_ident);
  949. if (status != PEP_STATUS_OK)
  950. return FAIL(L"cannot get message color");
  951. *pVal = (pEp_color) _color;
  952. return S_OK;
  953. }
  954. STDMETHODIMP CpEpEngine::trust_personal_key(struct pEp_identity_s *ident, struct pEp_identity_s *result)
  955. {
  956. ::pEp_identity *_ident;
  957. assert(ident);
  958. assert(result);
  959. try {
  960. _ident = new_identity(ident);
  961. }
  962. catch (bad_alloc&) {
  963. return E_OUTOFMEMORY;
  964. }
  965. catch (exception&) {
  966. return E_FAIL;
  967. }
  968. if (verbose_mode) {
  969. stringstream ss;
  970. ss << "trust_personal_key called with ";
  971. ss << utf8_string(ident->address);
  972. ss << L": ";
  973. ss << ident->comm_type;
  974. verbose(ss.str());
  975. }
  976. PEP_STATUS status = ::trust_personal_key(get_session(), _ident);
  977. if (verbose_mode) {
  978. stringstream ss;
  979. ss << "result ";
  980. ss << status;
  981. ss << " for ";
  982. ss << _ident->address;
  983. ss << L": ";
  984. ss << _ident->comm_type;
  985. verbose(ss.str());
  986. }
  987. if (status == PEP_STATUS_OK)
  988. copy_identity(result, _ident);
  989. free_identity(_ident);
  990. if (status == PEP_OUT_OF_MEMORY)
  991. return E_OUTOFMEMORY;
  992. else if (status != PEP_STATUS_OK)
  993. return FAIL(L"failure while executing trust_personal_key()");
  994. return S_OK;
  995. }
  996. // Event callbacks
  997. STDMETHODIMP CpEpEngine::register_callbacks(IpEpEngineCallbacks* new_callbacks)
  998. {
  999. callbacks cbs = get_callbacks();
  1000. vector<IpEpEngineCallbacks*>& vec = cbs;
  1001. vec.push_back(new_callbacks);
  1002. new_callbacks->AddRef();
  1003. return S_OK;
  1004. }
  1005. STDMETHODIMP CpEpEngine::unregister_callbacks(IpEpEngineCallbacks* obsolete_callbacks)
  1006. {
  1007. callbacks cbs = get_callbacks();
  1008. vector<IpEpEngineCallbacks*>& vec = cbs;
  1009. auto position = std::find(vec.begin(), vec.end(), obsolete_callbacks);
  1010. if (position != vec.end()) {
  1011. vec.erase(position);
  1012. obsolete_callbacks->Release();
  1013. return S_OK;
  1014. }
  1015. return S_FALSE;
  1016. }
  1017. HRESULT CpEpEngine::Fire_MessageToSend(text_message * msg)
  1018. {
  1019. callbacks cbs = get_callbacks();
  1020. vector<IpEpEngineCallbacks*>& vec = cbs;
  1021. assert(msg);
  1022. for (auto it = vec.begin(); it != vec.end(); ++it)
  1023. {
  1024. auto res = (*it)->MessageToSend(msg);
  1025. if (res != S_OK)
  1026. return res;
  1027. }
  1028. return S_OK;
  1029. }
  1030. HRESULT CpEpEngine::Fire_ShowHandshake(pEp_identity_s * self, pEp_identity_s * partner, sync_handshake_result_s * result)
  1031. {
  1032. callbacks cbs = get_callbacks();
  1033. vector<IpEpEngineCallbacks*>& vec = cbs;
  1034. assert(self);
  1035. assert(partner);
  1036. assert(result);
  1037. for (auto it = vec.begin(); it != vec.end(); ++it)
  1038. {
  1039. auto res = (*it)->ShowHandshake(self, partner, result);
  1040. if (res != S_OK)
  1041. return res;
  1042. }
  1043. return S_OK;
  1044. }