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