src/pEpEngine.c
author vb
Fri, 11 Jul 2014 17:43:11 +0200
changeset 8 26cc9f0228f4
parent 0 16f27efbef98
child 9 41e66a54f03e
permissions -rw-r--r--
moving functionality into pEpEngine
vb@0
     1
#define PEP_ENGINE_VERSION "0.4.0"
vb@0
     2
vb@0
     3
// this is 20 safewords with 79 chars max
vb@0
     4
#define MAX_SAFEWORDS_SPACE (20 * 80)
vb@0
     5
vb@0
     6
// XML parameters string
vb@0
     7
#define PARMS_MAX 32768
vb@0
     8
vb@0
     9
// maximum busy wait time in ms
vb@0
    10
#define BUSY_WAIT_TIME 5000
vb@0
    11
vb@0
    12
// maximum line length for reading gpg.conf
vb@0
    13
#define MAX_LINELENGTH 1024
vb@0
    14
vb@0
    15
// default keyserver
vb@0
    16
#define DEFAULT_KEYSERVER "hkp://keys.gnupg.net"
vb@0
    17
vb@0
    18
#ifdef WIN32
vb@0
    19
#include "platform_windows.h"
vb@0
    20
#define LOCAL_DB windoze_local_db()
vb@0
    21
#define SYSTEM_DB windoze_system_db()
vb@0
    22
#define LIBGPGME "libgpgme-11.dll"
vb@0
    23
#else // UNIX
vb@0
    24
#define _POSIX_C_SOURCE 200809L
vb@0
    25
#include <dlfcn.h>
vb@0
    26
#include "platform_unix.h"
vb@0
    27
#define LOCAL_DB unix_local_db()
vb@0
    28
#ifndef SYSTEM_DB
vb@0
    29
#define SYSTEM_DB "/usr/share/pEp/system.db"
vb@0
    30
#endif
vb@0
    31
#ifndef LIBGPGME
vb@0
    32
#define LIBGPGME "libgpgme-pthread.so"
vb@0
    33
#endif
vb@0
    34
#endif
vb@0
    35
vb@0
    36
#include <locale.h>
vb@0
    37
#include <stdlib.h>
vb@0
    38
#include <string.h>
vb@0
    39
#include <assert.h>
vb@0
    40
#include <stdio.h>
vb@0
    41
vb@0
    42
#ifndef NDEBUG
vb@0
    43
#include <stdio.h>
vb@0
    44
#endif
vb@0
    45
vb@0
    46
#include <gpgme.h>
vb@0
    47
#include "sqlite3.h"
vb@0
    48
vb@0
    49
#define _EXPORT_PEP_ENGINE_DLL
vb@0
    50
#include "pEpEngine.h"
vb@0
    51
vb@0
    52
#define NOT_IMPLEMENTED assert(0)
vb@0
    53
vb@0
    54
// init
vb@0
    55
vb@0
    56
typedef const char * (*gpgme_check_version_t)(const char*);
vb@0
    57
typedef gpgme_error_t (*gpgme_set_locale_t)(gpgme_ctx_t CTX, int CATEGORY,
vb@0
    58
        const char *VALUE);
vb@0
    59
typedef gpgme_error_t (*gpgme_new_t)(gpgme_ctx_t *CTX);
vb@0
    60
typedef void (*gpgme_release_t)(gpgme_ctx_t CTX);
vb@0
    61
typedef gpgme_error_t (*gpgme_set_protocol_t)(gpgme_ctx_t CTX,
vb@0
    62
        gpgme_protocol_t PROTO);
vb@0
    63
typedef void (*gpgme_set_armor_t)(gpgme_ctx_t CTX, int YES);
vb@0
    64
vb@0
    65
// data
vb@0
    66
vb@0
    67
typedef gpgme_error_t (*gpgme_data_new_t)(gpgme_data_t *DH);
vb@0
    68
typedef gpgme_error_t (*gpgme_data_new_from_mem_t)(gpgme_data_t *DH,
vb@0
    69
        const char *BUFFER, size_t SIZE, int COPY);
vb@0
    70
typedef void (*gpgme_data_release_t)(gpgme_data_t DH);
vb@0
    71
typedef gpgme_data_type_t (*gpgme_data_identify_t)(gpgme_data_t DH);
vb@0
    72
typedef size_t (*gpgme_data_seek_t)(gpgme_data_t DH, size_t OFFSET,
vb@0
    73
        int WHENCE);
vb@0
    74
typedef size_t (*gpgme_data_read_t)(gpgme_data_t DH, void *BUFFER,
vb@0
    75
        size_t LENGTH);
vb@0
    76
vb@0
    77
// encrypt and decrypt
vb@0
    78
vb@0
    79
typedef gpgme_error_t (*gpgme_op_decrypt_t)(gpgme_ctx_t CTX,
vb@0
    80
        gpgme_data_t CIPHER, gpgme_data_t PLAIN);
vb@0
    81
typedef gpgme_error_t (*gpgme_op_verify_t)(gpgme_ctx_t CTX, gpgme_data_t SIG,
vb@0
    82
        gpgme_data_t SIGNED_TEXT, gpgme_data_t PLAIN);
vb@0
    83
typedef gpgme_error_t (*gpgme_op_decrypt_verify_t)(gpgme_ctx_t CTX,
vb@0
    84
        gpgme_data_t CIPHER, gpgme_data_t PLAIN);
vb@0
    85
typedef gpgme_decrypt_result_t (*gpgme_op_decrypt_result_t)(gpgme_ctx_t CTX);
vb@0
    86
typedef gpgme_error_t (*gpgme_op_encrypt_sign_t)(gpgme_ctx_t CTX,
vb@0
    87
        gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
vb@0
    88
        gpgme_data_t CIPHER);
vb@0
    89
typedef gpgme_verify_result_t (*gpgme_op_verify_result_t)(gpgme_ctx_t CTX);
vb@0
    90
vb@0
    91
// keys
vb@0
    92
vb@0
    93
typedef gpgme_error_t (*gpgme_get_key_t)(gpgme_ctx_t CTX, const char *FPR,
vb@0
    94
        gpgme_key_t *R_KEY, int SECRET);
vb@0
    95
typedef gpgme_error_t (*gpgme_op_genkey_t)(gpgme_ctx_t CTX, const char *PARMS,
vb@0
    96
        gpgme_data_t PUBLIC, gpgme_data_t SECRET);
vb@0
    97
typedef gpgme_genkey_result_t (*gpgme_op_genkey_result_t)(gpgme_ctx_t CTX);
vb@0
    98
typedef gpgme_error_t (*gpgme_op_delete_t)(gpgme_ctx_t CTX,
vb@0
    99
        const gpgme_key_t KEY, int ALLOW_SECRET);
vb@0
   100
typedef gpgme_error_t (*gpgme_op_import_t)(gpgme_ctx_t CTX,
vb@0
   101
        gpgme_data_t KEYDATA);
vb@0
   102
typedef gpgme_error_t (*gpgme_op_export_t)(gpgme_ctx_t CTX,
vb@0
   103
        const char *PATTERN, gpgme_export_mode_t MODE, gpgme_data_t KEYDATA);
vb@0
   104
typedef gpgme_error_t (*gpgme_set_keylist_mode_t)(gpgme_ctx_t CTX,
vb@0
   105
        gpgme_keylist_mode_t MODE);
vb@0
   106
typedef gpgme_keylist_mode_t (*gpgme_get_keylist_mode_t)(gpgme_ctx_t CTX);
vb@0
   107
typedef gpgme_error_t (*gpgme_op_keylist_start_t)(gpgme_ctx_t CTX,
vb@0
   108
        const char *PATTERN, int SECRET_ONLY);
vb@0
   109
typedef gpgme_error_t (*gpgme_op_keylist_next_t)(gpgme_ctx_t CTX,
vb@0
   110
        gpgme_key_t *R_KEY);
vb@0
   111
typedef gpgme_error_t (*gpgme_op_keylist_end_t)(gpgme_ctx_t CTX);
vb@0
   112
typedef gpgme_error_t (*gpgme_op_import_keys_t)(gpgme_ctx_t CTX,
vb@0
   113
        gpgme_key_t *KEYS);
vb@0
   114
typedef void (*gpgme_key_ref_t)(gpgme_key_t KEY);
vb@0
   115
typedef void (*gpgme_key_unref_t)(gpgme_key_t KEY);
vb@0
   116
vb@0
   117
typedef struct {
vb@0
   118
	const char *version;
vb@0
   119
    const char *passphrase;
vb@0
   120
	void * gpgme;
vb@0
   121
	gpgme_ctx_t ctx;
vb@0
   122
vb@0
   123
	sqlite3 *db;
vb@0
   124
	sqlite3 *system_db;
vb@0
   125
vb@0
   126
	sqlite3_stmt *log;
vb@0
   127
	sqlite3_stmt *safeword;
vb@0
   128
	sqlite3_stmt *get_identity;
vb@0
   129
	sqlite3_stmt *set_person;
vb@0
   130
	sqlite3_stmt *set_pgp_keypair;
vb@0
   131
	sqlite3_stmt *set_identity;
vb@0
   132
	sqlite3_stmt *set_trust;
vb@8
   133
    sqlite3_stmt *get_trust;
vb@0
   134
vb@0
   135
	gpgme_check_version_t gpgme_check;
vb@0
   136
	gpgme_set_locale_t gpgme_set_locale;
vb@0
   137
	gpgme_new_t gpgme_new;
vb@0
   138
	gpgme_release_t gpgme_release;
vb@0
   139
	gpgme_set_protocol_t gpgme_set_protocol;
vb@0
   140
	gpgme_set_armor_t gpgme_set_armor;
vb@0
   141
vb@0
   142
	gpgme_data_new_t gpgme_data_new;
vb@0
   143
	gpgme_data_new_from_mem_t gpgme_data_new_from_mem;
vb@0
   144
	gpgme_data_release_t gpgme_data_release;
vb@0
   145
	gpgme_data_identify_t gpgme_data_identify;
vb@0
   146
	gpgme_data_seek_t gpgme_data_seek;
vb@0
   147
	gpgme_data_read_t gpgme_data_read;
vb@0
   148
vb@0
   149
	gpgme_op_decrypt_t gpgme_op_decrypt;
vb@0
   150
	gpgme_op_verify_t gpgme_op_verify;
vb@0
   151
	gpgme_op_decrypt_verify_t gpgme_op_decrypt_verify;
vb@0
   152
	gpgme_op_decrypt_result_t gpgme_op_decrypt_result;
vb@0
   153
	gpgme_op_encrypt_sign_t gpgme_op_encrypt_sign;
vb@0
   154
	gpgme_op_verify_result_t gpgme_op_verify_result;
vb@0
   155
vb@0
   156
	gpgme_get_key_t gpgme_get_key;
vb@0
   157
	gpgme_op_genkey_t gpgme_op_genkey;
vb@0
   158
    gpgme_op_genkey_result_t gpgme_op_genkey_result;
vb@0
   159
    gpgme_op_delete_t gpgme_op_delete;
vb@0
   160
    gpgme_op_import_t gpgme_op_import;
vb@0
   161
    gpgme_op_export_t gpgme_op_export;
vb@0
   162
    gpgme_set_keylist_mode_t gpgme_set_keylist_mode;
vb@0
   163
    gpgme_get_keylist_mode_t gpgme_get_keylist_mode;
vb@0
   164
    gpgme_op_keylist_start_t gpgme_op_keylist_start;
vb@0
   165
    gpgme_op_keylist_next_t gpgme_op_keylist_next;
vb@0
   166
    gpgme_op_keylist_end_t gpgme_op_keylist_end;
vb@0
   167
    gpgme_op_import_keys_t gpgme_op_import_keys;
vb@0
   168
    gpgme_key_ref_t gpgme_key_ref;
vb@0
   169
    gpgme_key_unref_t gpgme_key_unref;
vb@0
   170
} pEpSession;
vb@0
   171
vb@0
   172
static bool ensure_keyserver()
vb@0
   173
{
vb@0
   174
    static char buf[MAX_LINELENGTH];
vb@0
   175
    int n;
vb@0
   176
    FILE *f = fopen(gpg_conf(), "r");
vb@0
   177
vb@0
   178
    if (f != NULL) {
vb@0
   179
        while (!feof(f)) {
vb@0
   180
            char * s = fgets(buf, MAX_LINELENGTH, f);
vb@0
   181
            if (s && !feof(f)) {
vb@0
   182
                char * t = strtok(s, " ");
vb@0
   183
                if (t && strcmp(t, "keyserver") == 0)
vb@0
   184
                {
vb@0
   185
                    fclose(f);
vb@0
   186
                    return true;
vb@0
   187
                }
vb@0
   188
            }
vb@0
   189
        }
vb@0
   190
        f = freopen(gpg_conf(), "a", f);
vb@0
   191
    }
vb@0
   192
    else {
vb@0
   193
        f = fopen(gpg_conf(), "w");
vb@0
   194
    }
vb@0
   195
vb@0
   196
    assert(f);
vb@0
   197
    if (f == NULL)
vb@0
   198
        return false;
vb@0
   199
vb@0
   200
    n = fprintf(f, "keyserver %s\n", DEFAULT_KEYSERVER);
vb@0
   201
    assert(n >= 0);
vb@0
   202
    fclose(f);
vb@0
   203
vb@0
   204
    return true;
vb@0
   205
}
vb@0
   206
vb@0
   207
DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
vb@0
   208
{
vb@0
   209
	gpgme_error_t gpgme_error;
vb@0
   210
	int int_result;
vb@0
   211
	const char *sql_log;
vb@0
   212
	const char *sql_safeword;
vb@0
   213
	const char *sql_get_identity;
vb@0
   214
	const char *sql_set_person;
vb@0
   215
	const char *sql_set_pgp_keypair;
vb@0
   216
	const char *sql_set_identity;
vb@0
   217
	const char *sql_set_trust;
vb@8
   218
    const char *sql_get_trust;
vb@8
   219
vb@0
   220
    bool bResult;
vb@0
   221
vb@0
   222
	assert(sqlite3_threadsafe());
vb@0
   223
	if (!sqlite3_threadsafe())
vb@0
   224
		return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
vb@0
   225
vb@0
   226
	assert(session);
vb@0
   227
	*session = NULL;
vb@0
   228
vb@0
   229
    pEpSession *_session = (pEpSession *) calloc(1, sizeof(pEpSession));
vb@0
   230
	assert(_session);
vb@0
   231
	if (_session == NULL)
vb@0
   232
		return PEP_OUT_OF_MEMORY;
vb@0
   233
	
vb@0
   234
	_session->version = PEP_ENGINE_VERSION;
vb@0
   235
vb@0
   236
    bResult = ensure_keyserver();
vb@0
   237
    assert(bResult);
vb@0
   238
vb@0
   239
    // to do: implement something useful
vb@0
   240
    _session->passphrase = "";
vb@0
   241
vb@0
   242
	_session->gpgme = dlopen(LIBGPGME, RTLD_LAZY);
vb@0
   243
	if (_session->gpgme == NULL) {
vb@0
   244
		free(_session);
vb@0
   245
		return PEP_INIT_CANNOT_LOAD_GPGME;
vb@0
   246
	}
vb@0
   247
vb@0
   248
	_session->gpgme_set_locale
vb@0
   249
        = (gpgme_set_locale_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   250
                "gpgme_set_locale");
vb@0
   251
	assert(_session->gpgme_set_locale);
vb@0
   252
vb@0
   253
	_session->gpgme_check
vb@0
   254
        = (gpgme_check_version_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   255
                "gpgme_check_version");
vb@0
   256
	assert(_session->gpgme_check);
vb@0
   257
vb@0
   258
	_session->gpgme_new
vb@0
   259
        = (gpgme_new_t) (intptr_t) dlsym(_session->gpgme, "gpgme_new");
vb@0
   260
	assert(_session->gpgme_new);
vb@0
   261
vb@0
   262
	_session->gpgme_release
vb@0
   263
        = (gpgme_release_t) (intptr_t) dlsym(_session->gpgme, "gpgme_release");
vb@0
   264
	assert(_session->gpgme_release);
vb@0
   265
vb@0
   266
	_session->gpgme_set_protocol
vb@0
   267
        = (gpgme_set_protocol_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   268
                "gpgme_set_protocol");
vb@0
   269
	assert(_session->gpgme_set_protocol);
vb@0
   270
vb@0
   271
	_session->gpgme_set_armor
vb@0
   272
        = (gpgme_set_armor_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   273
                "gpgme_set_armor");
vb@0
   274
	assert(_session->gpgme_set_armor);
vb@0
   275
vb@0
   276
	_session->gpgme_data_new
vb@0
   277
        = (gpgme_data_new_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   278
                "gpgme_data_new");
vb@0
   279
	assert(_session->gpgme_data_new);
vb@0
   280
vb@0
   281
	_session->gpgme_data_new_from_mem
vb@0
   282
        = (gpgme_data_new_from_mem_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   283
                "gpgme_data_new_from_mem");
vb@0
   284
	assert(_session->gpgme_data_new_from_mem);
vb@0
   285
vb@0
   286
	_session->gpgme_data_release
vb@0
   287
        = (gpgme_data_release_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   288
                "gpgme_data_release");
vb@0
   289
	assert(_session->gpgme_data_release);
vb@0
   290
vb@0
   291
	_session->gpgme_data_identify
vb@0
   292
        = (gpgme_data_identify_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   293
                "gpgme_data_identify");
vb@0
   294
	assert(_session->gpgme_data_identify);
vb@0
   295
vb@0
   296
	_session->gpgme_data_seek
vb@0
   297
        = (gpgme_data_seek_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   298
                "gpgme_data_seek");
vb@0
   299
	assert(_session->gpgme_data_seek);
vb@0
   300
vb@0
   301
	_session->gpgme_data_read
vb@0
   302
        = (gpgme_data_read_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   303
                "gpgme_data_read");
vb@0
   304
	assert(_session->gpgme_data_read);
vb@0
   305
vb@0
   306
	_session->gpgme_op_decrypt
vb@0
   307
        = (gpgme_op_decrypt_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   308
                "gpgme_op_decrypt");
vb@0
   309
	assert(_session->gpgme_op_decrypt);
vb@0
   310
vb@0
   311
	_session->gpgme_op_verify
vb@0
   312
        = (gpgme_op_verify_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   313
                "gpgme_op_verify");
vb@0
   314
	assert(_session->gpgme_op_verify);
vb@0
   315
vb@0
   316
	_session->gpgme_op_decrypt_verify
vb@0
   317
        = (gpgme_op_decrypt_verify_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   318
                "gpgme_op_decrypt_verify");
vb@0
   319
	assert(_session->gpgme_op_decrypt_verify);
vb@0
   320
vb@0
   321
	_session->gpgme_op_decrypt_result
vb@0
   322
        = (gpgme_op_decrypt_result_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   323
                "gpgme_op_decrypt_result");
vb@0
   324
	assert(_session->gpgme_op_decrypt_result);
vb@0
   325
vb@0
   326
	_session->gpgme_op_encrypt_sign
vb@0
   327
        = (gpgme_op_encrypt_sign_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   328
                "gpgme_op_encrypt_sign");
vb@0
   329
	assert(_session->gpgme_op_encrypt_sign);
vb@0
   330
vb@0
   331
	_session->gpgme_op_verify_result
vb@0
   332
        = (gpgme_op_verify_result_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   333
                "gpgme_op_verify_result");
vb@0
   334
	assert(_session->gpgme_op_verify_result);
vb@0
   335
	
vb@0
   336
	_session->gpgme_get_key
vb@0
   337
        = (gpgme_get_key_t) (intptr_t) dlsym(_session->gpgme, "gpgme_get_key");
vb@0
   338
	assert(_session->gpgme_get_key);
vb@0
   339
vb@0
   340
	_session->gpgme_op_genkey
vb@0
   341
        = (gpgme_op_genkey_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   342
                "gpgme_op_genkey");
vb@0
   343
	assert(_session->gpgme_op_genkey);
vb@0
   344
vb@0
   345
	_session->gpgme_op_genkey_result
vb@0
   346
        = (gpgme_op_genkey_result_t) (intptr_t) dlsym(_session->gpgme,
vb@0
   347
                "gpgme_op_genkey_result");
vb@0
   348
	assert(_session->gpgme_op_genkey_result);
vb@0
   349
vb@0
   350
    _session->gpgme_op_delete = (gpgme_op_delete_t) (intptr_t)
vb@0
   351
        dlsym(_session->gpgme, "gpgme_op_delete");
vb@0
   352
	assert(_session->gpgme_op_delete);
vb@0
   353
vb@0
   354
    _session->gpgme_op_import = (gpgme_op_import_t) (intptr_t)
vb@0
   355
        dlsym(_session->gpgme, "gpgme_op_import");
vb@0
   356
	assert(_session->gpgme_op_import);
vb@0
   357
vb@0
   358
    _session->gpgme_op_export = (gpgme_op_export_t) (intptr_t)
vb@0
   359
        dlsym(_session->gpgme, "gpgme_op_export");
vb@0
   360
	assert(_session->gpgme_op_export);
vb@0
   361
vb@0
   362
    _session->gpgme_set_keylist_mode = (gpgme_set_keylist_mode_t) (intptr_t)
vb@0
   363
        dlsym(_session->gpgme, "gpgme_set_keylist_mode");
vb@0
   364
	assert(_session->gpgme_set_keylist_mode);
vb@0
   365
vb@0
   366
    _session->gpgme_get_keylist_mode = (gpgme_get_keylist_mode_t) (intptr_t)
vb@0
   367
        dlsym(_session->gpgme, "gpgme_get_keylist_mode");
vb@0
   368
	assert(_session->gpgme_get_keylist_mode);
vb@0
   369
vb@0
   370
    _session->gpgme_op_keylist_start = (gpgme_op_keylist_start_t) (intptr_t)
vb@0
   371
        dlsym(_session->gpgme, "gpgme_op_keylist_start");
vb@0
   372
	assert(_session->gpgme_op_keylist_start);
vb@0
   373
vb@0
   374
    _session->gpgme_op_keylist_next = (gpgme_op_keylist_next_t) (intptr_t)
vb@0
   375
        dlsym(_session->gpgme, "gpgme_op_keylist_next");
vb@0
   376
	assert(_session->gpgme_op_keylist_next);
vb@0
   377
vb@0
   378
    _session->gpgme_op_keylist_end = (gpgme_op_keylist_end_t) (intptr_t)
vb@0
   379
        dlsym(_session->gpgme, "gpgme_op_keylist_end");
vb@0
   380
	assert(_session->gpgme_op_keylist_end);
vb@0
   381
vb@0
   382
    _session->gpgme_op_import_keys = (gpgme_op_import_keys_t) (intptr_t)
vb@0
   383
        dlsym(_session->gpgme, "gpgme_op_import_keys");
vb@0
   384
	assert(_session->gpgme_op_import_keys);
vb@0
   385
vb@0
   386
    _session->gpgme_key_ref = (gpgme_key_ref_t) (intptr_t)
vb@0
   387
        dlsym(_session->gpgme, "gpgme_key_ref");
vb@0
   388
	assert(_session->gpgme_key_ref);
vb@0
   389
vb@0
   390
    _session->gpgme_key_unref = (gpgme_key_unref_t) (intptr_t)
vb@0
   391
        dlsym(_session->gpgme, "gpgme_key_unref");
vb@0
   392
	assert(_session->gpgme_key_unref);
vb@0
   393
vb@0
   394
	setlocale(LC_ALL, "");
vb@0
   395
	_session->version = _session->gpgme_check(NULL);
vb@0
   396
	_session->gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
vb@0
   397
vb@0
   398
	gpgme_error = _session->gpgme_new(&_session->ctx);
vb@0
   399
	if (gpgme_error != GPG_ERR_NO_ERROR) {
vb@0
   400
		dlclose(_session->gpgme);
vb@0
   401
		free(_session);
vb@0
   402
		return PEP_INIT_GPGME_INIT_FAILED;
vb@0
   403
	}
vb@0
   404
vb@0
   405
    gpgme_error = _session->gpgme_set_protocol(_session->ctx,
vb@0
   406
            GPGME_PROTOCOL_OpenPGP);
vb@0
   407
	assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
   408
vb@0
   409
	_session->gpgme_set_armor(_session->ctx, 1);
vb@0
   410
vb@0
   411
    assert(LOCAL_DB);
vb@0
   412
    if (LOCAL_DB == NULL) {
vb@0
   413
		_session->gpgme_release(_session->ctx);
vb@0
   414
		dlclose(_session->gpgme);
vb@0
   415
        free(_session);
vb@0
   416
        return PEP_INIT_CANNOT_OPEN_DB;
vb@0
   417
    }
vb@0
   418
vb@0
   419
	int_result = sqlite3_open_v2(
vb@0
   420
			LOCAL_DB,
vb@0
   421
			&_session->db,
vb@0
   422
			SQLITE_OPEN_READWRITE
vb@0
   423
				| SQLITE_OPEN_CREATE
vb@0
   424
				| SQLITE_OPEN_FULLMUTEX
vb@0
   425
				| SQLITE_OPEN_PRIVATECACHE,
vb@0
   426
			NULL 
vb@0
   427
		);
vb@0
   428
vb@0
   429
	if (int_result != SQLITE_OK) {
vb@0
   430
		sqlite3_close_v2(_session->db);
vb@0
   431
		_session->gpgme_release(_session->ctx);
vb@0
   432
		dlclose(_session->gpgme);
vb@0
   433
		free(_session);
vb@0
   434
		return PEP_INIT_CANNOT_OPEN_DB;
vb@0
   435
	}
vb@0
   436
vb@0
   437
	sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
vb@0
   438
vb@0
   439
    assert(SYSTEM_DB);
vb@0
   440
    if (SYSTEM_DB == NULL) {
vb@0
   441
		sqlite3_close_v2(_session->db);
vb@0
   442
		_session->gpgme_release(_session->ctx);
vb@0
   443
		dlclose(_session->gpgme);
vb@0
   444
		free(_session);
vb@0
   445
		return PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
vb@0
   446
    }
vb@0
   447
vb@0
   448
	int_result = sqlite3_open_v2(
vb@0
   449
			SYSTEM_DB, &_session->system_db,
vb@0
   450
			SQLITE_OPEN_READONLY
vb@0
   451
				| SQLITE_OPEN_FULLMUTEX
vb@0
   452
				| SQLITE_OPEN_SHAREDCACHE,
vb@0
   453
			NULL
vb@0
   454
		);
vb@0
   455
vb@0
   456
	if (int_result != SQLITE_OK) {
vb@0
   457
		sqlite3_close_v2(_session->system_db);
vb@0
   458
		sqlite3_close_v2(_session->db);
vb@0
   459
		_session->gpgme_release(_session->ctx);
vb@0
   460
		dlclose(_session->gpgme);
vb@0
   461
		free(_session);
vb@0
   462
		return PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
vb@0
   463
	}
vb@0
   464
vb@0
   465
	sqlite3_busy_timeout(_session->system_db, 1000);
vb@0
   466
vb@0
   467
	int_result = sqlite3_exec(
vb@0
   468
		_session->db,
vb@0
   469
			"create table if not exists version_info ("
vb@0
   470
			"	id integer primary key,"
vb@0
   471
			"	timestamp integer default (datetime('now')) ,"
vb@0
   472
			"	version text,"
vb@0
   473
			"	comment text"
vb@0
   474
			");"
vb@0
   475
			"create table if not exists log ("
vb@0
   476
			"	timestamp integer default (datetime('now')) ,"
vb@0
   477
			"	title text not null,"
vb@0
   478
			"	entity text not null,"
vb@0
   479
			"	description text,"
vb@0
   480
			"	comment text"
vb@0
   481
			");"
vb@0
   482
			"create index if not exists log_timestamp on log ("
vb@0
   483
			"	timestamp"
vb@0
   484
			");"
vb@0
   485
			"create table if not exists pgp_keypair ("
vb@0
   486
			"	fpr text primary key,"
vb@0
   487
			"	public_id text unique,"
vb@0
   488
			"   private_id text,"
vb@0
   489
			"	created integer,"
vb@0
   490
			"	expires integer,"
vb@0
   491
			"	comment text"
vb@0
   492
			");"
vb@0
   493
            "create index if not exists pgp_keypair_expires on pgp_keypair ("
vb@0
   494
			"	expires"
vb@0
   495
			");"
vb@0
   496
			"create table if not exists person ("
vb@0
   497
			"	id text primary key,"
vb@0
   498
			"	username text not null,"
vb@0
   499
			"	main_key_id text"
vb@0
   500
			"		references pgp_keypair (fpr)"
vb@0
   501
			"		on delete set null,"
vb@0
   502
			"   lang text,"
vb@0
   503
			"	comment text"
vb@0
   504
			");"
vb@0
   505
			"create table if not exists identity ("
vb@0
   506
			"	address text primary key,"
vb@0
   507
			"	user_id text"
vb@0
   508
			"		references person (id)"
vb@0
   509
			"		on delete cascade,"
vb@0
   510
			"	main_key_id text"
vb@0
   511
			"		references pgp_keypair (fpr)"
vb@0
   512
			"		on delete set null,"
vb@0
   513
			"	comment text"
vb@0
   514
			");"
vb@0
   515
            "create table if not exists trust ("
vb@0
   516
            "   user_id text not null"
vb@0
   517
            "       references person (id)"
vb@0
   518
			"		on delete cascade,"
vb@0
   519
            "   pgp_keypair_fpr text not null"
vb@0
   520
            "       references pgp_keypair (fpr)"
vb@0
   521
            "       on delete cascade,"
vb@0
   522
            "   comm_type integer not null,"
vb@0
   523
			"	comment text"
vb@0
   524
            ");"
vb@0
   525
            "create unique index if not exists trust_index on trust ("
vb@0
   526
            "   user_id,"
vb@0
   527
            "   pgp_keypair_fpr"
vb@0
   528
            ");",
vb@0
   529
		NULL,
vb@0
   530
		NULL,
vb@0
   531
		NULL
vb@0
   532
	);
vb@0
   533
	assert(int_result == SQLITE_OK);
vb@0
   534
vb@0
   535
	int_result = sqlite3_exec(
vb@0
   536
		_session->db,
vb@0
   537
        "insert or replace into version_info (id, version) values (1, '1.0');",
vb@0
   538
		NULL,
vb@0
   539
		NULL,
vb@0
   540
		NULL
vb@0
   541
	);
vb@0
   542
	assert(int_result == SQLITE_OK);
vb@0
   543
vb@0
   544
	sql_log = "insert into log (title, entity, description, comment)"
vb@0
   545
			  "values (?1, ?2, ?3, ?4);";
vb@0
   546
    int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
vb@0
   547
            &_session->log, NULL);
vb@0
   548
	assert(int_result == SQLITE_OK);
vb@0
   549
vb@0
   550
	sql_safeword = "select id, word from wordlist where lang = lower(?1)"
vb@0
   551
                   "and id = ?2 ;";
vb@0
   552
    int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
vb@0
   553
            strlen(sql_safeword), &_session->safeword, NULL);
vb@0
   554
	assert(int_result == SQLITE_OK);
vb@0
   555
vb@0
   556
	sql_get_identity =	"select fpr, identity.user_id, username, comm_type, lang"
vb@0
   557
                        "   from identity"
vb@0
   558
						"   join person on id = identity.user_id"
vb@0
   559
						"   join pgp_keypair on fpr = identity.main_key_id"
vb@0
   560
                        "   join trust on id = trust.user_id"
vb@0
   561
                        "       and pgp_keypair_fpr = identity.main_key_id"
vb@0
   562
						"   where address = ?1 ;";
vb@0
   563
vb@0
   564
    int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
vb@0
   565
            strlen(sql_get_identity), &_session->get_identity, NULL);
vb@0
   566
	assert(int_result == SQLITE_OK);
vb@0
   567
vb@0
   568
	sql_set_person = "insert or replace into person (id, username, lang)"
vb@0
   569
                     "values (?1, ?2, ?3) ;";
vb@0
   570
	sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr)"
vb@0
   571
                          "values (?1) ;";
vb@0
   572
    sql_set_identity = "insert or replace into identity (address, main_key_id,"
vb@0
   573
                       "user_id) values (?1, ?2, ?3) ;";
vb@0
   574
    sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type)"
vb@0
   575
                        "values (?1, ?2, ?3) ;";
vb@0
   576
	
vb@8
   577
    sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 and pgp_keypair_fpr = ?2 ;";
vb@8
   578
vb@0
   579
    int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
vb@0
   580
            strlen(sql_set_person), &_session->set_person, NULL);
vb@0
   581
    assert(int_result == SQLITE_OK);
vb@0
   582
    int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
vb@0
   583
            strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
vb@0
   584
	assert(int_result == SQLITE_OK);
vb@0
   585
    int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
vb@0
   586
            strlen(sql_set_identity), &_session->set_identity, NULL);
vb@0
   587
	assert(int_result == SQLITE_OK);
vb@0
   588
    int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
vb@0
   589
            strlen(sql_set_trust), &_session->set_trust, NULL);
vb@0
   590
	assert(int_result == SQLITE_OK);
vb@8
   591
    int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
vb@8
   592
            strlen(sql_get_trust), &_session->get_trust, NULL);
vb@8
   593
    assert(int_result == SQLITE_OK);
vb@0
   594
vb@0
   595
	sqlite3_reset(_session->log);
vb@0
   596
    sqlite3_bind_text(_session->log, 1, "init", -1, SQLITE_STATIC);
vb@0
   597
    sqlite3_bind_text(_session->log, 2, "pEp " PEP_ENGINE_VERSION, -1,
vb@0
   598
            SQLITE_STATIC);
vb@0
   599
	do {
vb@0
   600
		int_result = sqlite3_step(_session->log);
vb@0
   601
		assert(int_result == SQLITE_DONE || int_result == SQLITE_BUSY);
vb@0
   602
	} while (int_result == SQLITE_BUSY);
vb@0
   603
    sqlite3_reset(_session->log);
vb@0
   604
vb@0
   605
	*session = (void *) _session;
vb@0
   606
	return PEP_STATUS_OK;
vb@0
   607
}
vb@0
   608
vb@0
   609
DYNAMIC_API void release(PEP_SESSION session)
vb@0
   610
{
vb@0
   611
	assert(session);
vb@0
   612
	pEpSession *_session = (pEpSession *) session;
vb@0
   613
vb@0
   614
	if (_session) {
vb@0
   615
		if (_session->db) {
vb@0
   616
			sqlite3_finalize(_session->safeword);
vb@0
   617
			sqlite3_finalize(_session->log);
vb@0
   618
			sqlite3_finalize(_session->get_identity);
vb@0
   619
			sqlite3_finalize(_session->set_identity);
vb@0
   620
			sqlite3_close_v2(_session->db);
vb@0
   621
			sqlite3_close_v2(_session->system_db);
vb@0
   622
		}
vb@0
   623
		if (_session->ctx)
vb@0
   624
			_session->gpgme_release(_session->ctx);
vb@0
   625
		dlclose(_session->gpgme);
vb@0
   626
	}
vb@0
   627
	free(_session);
vb@0
   628
}
vb@0
   629
vb@0
   630
stringlist_t *new_stringlist(const char *value)
vb@0
   631
{
vb@0
   632
    stringlist_t *result = (stringlist_t *) calloc(1, sizeof(stringlist_t));
vb@0
   633
    if (result && value) {
vb@0
   634
        result->value = strdup(value);
vb@0
   635
        assert(result->value);
vb@0
   636
        if (result->value == 0) {
vb@0
   637
            free(result);
vb@0
   638
            return NULL;
vb@0
   639
        }
vb@0
   640
    }
vb@0
   641
    return result;
vb@0
   642
}
vb@0
   643
vb@0
   644
stringlist_t *stringlist_add(stringlist_t *stringlist, const char *value)
vb@0
   645
{
vb@0
   646
    assert(value);
vb@0
   647
vb@0
   648
    if (stringlist == NULL)
vb@0
   649
        return new_stringlist(value);
vb@0
   650
vb@0
   651
    if (stringlist->next != NULL)
vb@0
   652
        return stringlist_add(stringlist->next, value);
vb@0
   653
vb@0
   654
    if (stringlist->value == NULL) {
vb@0
   655
        stringlist->value = strdup(value);
vb@0
   656
        assert(stringlist->value);
vb@0
   657
        if (stringlist->value == NULL)
vb@0
   658
            return NULL;
vb@0
   659
        return stringlist;
vb@0
   660
    }
vb@0
   661
vb@0
   662
    stringlist->next = new_stringlist(value);
vb@0
   663
    assert(stringlist->next);
vb@0
   664
    if (stringlist->next == NULL)
vb@0
   665
        return NULL;
vb@0
   666
vb@0
   667
    return stringlist->next;
vb@0
   668
}
vb@0
   669
vb@0
   670
int stringlist_length(const stringlist_t *stringlist)
vb@0
   671
{
vb@0
   672
    int len = 1;
vb@0
   673
    stringlist_t *_stringlist;
vb@0
   674
vb@0
   675
    assert(stringlist);
vb@0
   676
vb@0
   677
    if (stringlist->value == NULL)
vb@0
   678
        return 0;
vb@0
   679
vb@0
   680
    for (_stringlist=stringlist->next; _stringlist!=NULL; _stringlist=_stringlist->next)
vb@0
   681
        len += 1;
vb@0
   682
vb@0
   683
    return len;
vb@0
   684
}
vb@0
   685
vb@0
   686
void free_stringlist(stringlist_t *stringlist)
vb@0
   687
{
vb@0
   688
    if (stringlist) {
vb@0
   689
        free_stringlist(stringlist->next);
vb@0
   690
        free(stringlist->value);
vb@0
   691
        free(stringlist);
vb@0
   692
    }
vb@0
   693
}
vb@0
   694
vb@0
   695
DYNAMIC_API PEP_STATUS decrypt_and_verify(
vb@0
   696
        PEP_SESSION session, const char *ctext, size_t csize,
vb@0
   697
        char **ptext, size_t *psize, stringlist_t **keylist
vb@0
   698
    )
vb@0
   699
{
vb@0
   700
	pEpSession *_session = (pEpSession *) session;
vb@0
   701
vb@0
   702
	PEP_STATUS result;
vb@0
   703
	gpgme_error_t gpgme_error;
vb@0
   704
	gpgme_data_t cipher, plain;
vb@0
   705
	gpgme_data_type_t dt;
vb@0
   706
vb@0
   707
	stringlist_t *_keylist = NULL;
vb@0
   708
	int i_key = 0;
vb@0
   709
vb@0
   710
	assert(_session);
vb@0
   711
	assert(ctext);
vb@0
   712
	assert(csize);
vb@0
   713
	assert(ptext);
vb@0
   714
	assert(psize);
vb@0
   715
	assert(keylist);
vb@0
   716
vb@0
   717
	*ptext = NULL;
vb@0
   718
	*psize = 0;
vb@0
   719
	*keylist = NULL;
vb@0
   720
vb@0
   721
    gpgme_error = _session->gpgme_data_new_from_mem(&cipher, ctext, csize, 0);
vb@0
   722
	assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
   723
	if (gpgme_error != GPG_ERR_NO_ERROR) {
vb@0
   724
		if (gpgme_error == GPG_ERR_ENOMEM)
vb@0
   725
			return PEP_OUT_OF_MEMORY;
vb@0
   726
		else
vb@0
   727
			return PEP_UNKNOWN_ERROR;
vb@0
   728
	}
vb@0
   729
vb@0
   730
	gpgme_error = _session->gpgme_data_new(&plain);
vb@0
   731
	assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
   732
	if (gpgme_error != GPG_ERR_NO_ERROR) {
vb@0
   733
		_session->gpgme_data_release(cipher);
vb@0
   734
		if (gpgme_error == GPG_ERR_ENOMEM)
vb@0
   735
			return PEP_OUT_OF_MEMORY;
vb@0
   736
		else
vb@0
   737
			return PEP_UNKNOWN_ERROR;
vb@0
   738
	}
vb@0
   739
vb@0
   740
	dt = _session->gpgme_data_identify(cipher);
vb@0
   741
	switch (dt) {
vb@0
   742
	case GPGME_DATA_TYPE_PGP_SIGNED:
vb@0
   743
	case GPGME_DATA_TYPE_PGP_OTHER:
vb@0
   744
        gpgme_error = _session->gpgme_op_decrypt_verify(_session->ctx, cipher,
vb@0
   745
                plain);
vb@0
   746
		assert(gpgme_error != GPG_ERR_INV_VALUE);
vb@0
   747
		assert(gpgme_error != GPG_ERR_NO_DATA);
vb@0
   748
vb@0
   749
		switch (gpgme_error) {
vb@0
   750
		case GPG_ERR_NO_ERROR:
vb@0
   751
			{
vb@0
   752
				gpgme_verify_result_t gpgme_verify_result;
vb@0
   753
                char *_buffer = NULL;
vb@0
   754
				size_t reading;
vb@0
   755
                size_t length = _session->gpgme_data_seek(plain, 0, SEEK_END);
vb@0
   756
                gpgme_signature_t gpgme_signature;
vb@0
   757
vb@0
   758
				assert(length != -1);
vb@0
   759
				_session->gpgme_data_seek(plain, 0, SEEK_SET);
vb@0
   760
vb@0
   761
				// TODO: make things less memory consuming
vb@0
   762
                // the following algorithm allocates memory for the complete
vb@0
   763
                // text
vb@0
   764
vb@0
   765
                _buffer = malloc(length + 1);
vb@0
   766
                assert(_buffer);
vb@0
   767
                if (_buffer == NULL) {
vb@0
   768
                    _session->gpgme_data_release(plain);
vb@0
   769
                    _session->gpgme_data_release(cipher);
vb@0
   770
                    return PEP_OUT_OF_MEMORY;
vb@0
   771
                }
vb@0
   772
vb@0
   773
                reading = _session->gpgme_data_read(plain, _buffer, length);
vb@0
   774
				assert(length == reading);
vb@0
   775
vb@0
   776
                gpgme_verify_result =
vb@0
   777
                    _session->gpgme_op_verify_result(_session->ctx);
vb@0
   778
				assert(gpgme_verify_result);
vb@0
   779
                gpgme_signature = gpgme_verify_result->signatures;
vb@0
   780
vb@0
   781
				if (gpgme_signature) {
vb@0
   782
                    stringlist_t *k;
vb@0
   783
                    _keylist = new_stringlist(NULL);
vb@0
   784
                    assert(_keylist);
vb@0
   785
                    if (_keylist == NULL) {
vb@0
   786
						_session->gpgme_data_release(plain);
vb@0
   787
						_session->gpgme_data_release(cipher);
vb@0
   788
                        free(_buffer);
vb@0
   789
                        return PEP_OUT_OF_MEMORY;
vb@0
   790
                    }
vb@0
   791
                    k = _keylist;
vb@0
   792
vb@0
   793
                    result = PEP_DECRYPTED_AND_VERIFIED;
vb@0
   794
					do {
vb@0
   795
                        switch (gpgme_signature->status) {
vb@0
   796
                        case GPG_ERR_NO_ERROR:
vb@0
   797
                            k = stringlist_add(k, gpgme_signature->fpr);
vb@0
   798
                            break;
vb@0
   799
                        case GPG_ERR_CERT_REVOKED:
vb@0
   800
                        case GPG_ERR_BAD_SIGNATURE:
vb@0
   801
                            result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
vb@0
   802
                            break;
vb@0
   803
                        case GPG_ERR_SIG_EXPIRED:
vb@0
   804
                        case GPG_ERR_KEY_EXPIRED:
vb@0
   805
                        case GPG_ERR_NO_PUBKEY:
vb@0
   806
                            k = stringlist_add(k, gpgme_signature->fpr);
vb@0
   807
                            if (result == PEP_DECRYPTED_AND_VERIFIED)
vb@0
   808
                                result = PEP_DECRYPTED;
vb@0
   809
                            break;
vb@0
   810
                        case GPG_ERR_GENERAL:
vb@0
   811
                            break;
vb@0
   812
                        default:
vb@0
   813
                            if (result == PEP_DECRYPTED_AND_VERIFIED)
vb@0
   814
                                result = PEP_DECRYPTED;
vb@0
   815
                            break;
vb@0
   816
                        }
vb@0
   817
					} while ((gpgme_signature = gpgme_signature->next));
vb@0
   818
				} else {
vb@0
   819
					result = PEP_DECRYPTED;
vb@0
   820
				}
vb@0
   821
vb@0
   822
				if (result == PEP_DECRYPTED_AND_VERIFIED
vb@0
   823
                        || result == PEP_DECRYPTED) {
vb@0
   824
					*ptext = _buffer;
vb@0
   825
					*psize = reading;
vb@0
   826
                    (*ptext)[*psize] = 0; // safeguard for naive users
vb@0
   827
					*keylist = _keylist;
vb@0
   828
				}
vb@0
   829
                else {
vb@0
   830
                    free_stringlist(_keylist);
vb@0
   831
                    free(_buffer);
vb@0
   832
	            }
vb@0
   833
				break;
vb@0
   834
			}
vb@0
   835
		case GPG_ERR_DECRYPT_FAILED:
vb@0
   836
			result = PEP_DECRYPT_WRONG_FORMAT;
vb@0
   837
			break;
vb@0
   838
		case GPG_ERR_BAD_PASSPHRASE:
vb@0
   839
			NOT_IMPLEMENTED;
vb@0
   840
		default:
vb@0
   841
			result = PEP_CANNOT_DECRYPT_UNKNOWN;
vb@0
   842
		}
vb@0
   843
		break;
vb@0
   844
vb@0
   845
	default:
vb@0
   846
		result = PEP_DECRYPT_WRONG_FORMAT;
vb@0
   847
	}
vb@0
   848
vb@0
   849
	_session->gpgme_data_release(plain);
vb@0
   850
	_session->gpgme_data_release(cipher);
vb@0
   851
	return result;
vb@0
   852
}
vb@0
   853
vb@0
   854
DYNAMIC_API PEP_STATUS verify_text(
vb@0
   855
        PEP_SESSION session, const char *text, size_t size,
vb@0
   856
        const char *signature, size_t sig_size, stringlist_t **keylist
vb@0
   857
    )
vb@0
   858
{
vb@0
   859
	pEpSession *_session = (pEpSession *) session;
vb@0
   860
vb@0
   861
	PEP_STATUS result;
vb@0
   862
	gpgme_error_t gpgme_error;
vb@0
   863
	gpgme_data_t d_text, d_sig;
vb@0
   864
    stringlist_t *_keylist;
vb@0
   865
vb@0
   866
    assert(session);
vb@0
   867
    assert(text);
vb@0
   868
    assert(size);
vb@0
   869
    assert(signature);
vb@0
   870
    assert(sig_size);
vb@0
   871
    assert(keylist);
vb@0
   872
vb@0
   873
    *keylist = NULL;
vb@0
   874
vb@0
   875
    gpgme_error = _session->gpgme_data_new_from_mem(&d_text, text, size, 0);
vb@0
   876
	assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
   877
	if (gpgme_error != GPG_ERR_NO_ERROR) {
vb@0
   878
		if (gpgme_error == GPG_ERR_ENOMEM)
vb@0
   879
			return PEP_OUT_OF_MEMORY;
vb@0
   880
		else
vb@0
   881
			return PEP_UNKNOWN_ERROR;
vb@0
   882
	}
vb@0
   883
vb@0
   884
    gpgme_error = _session->gpgme_data_new_from_mem(&d_sig, signature, sig_size, 0);
vb@0
   885
	assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
   886
	if (gpgme_error != GPG_ERR_NO_ERROR) {
vb@0
   887
		_session->gpgme_data_release(d_text);
vb@0
   888
		if (gpgme_error == GPG_ERR_ENOMEM)
vb@0
   889
			return PEP_OUT_OF_MEMORY;
vb@0
   890
		else
vb@0
   891
			return PEP_UNKNOWN_ERROR;
vb@0
   892
	}
vb@0
   893
vb@0
   894
    gpgme_error = _session->gpgme_op_verify(_session->ctx, d_sig, d_text, NULL);
vb@0
   895
    assert(gpgme_error != GPG_ERR_INV_VALUE);
vb@0
   896
vb@0
   897
    switch (gpgme_error) {
vb@0
   898
    case GPG_ERR_NO_ERROR:
vb@0
   899
        {
vb@0
   900
            gpgme_verify_result_t gpgme_verify_result;
vb@0
   901
            gpgme_signature_t gpgme_signature;
vb@0
   902
vb@0
   903
            gpgme_verify_result =
vb@0
   904
                _session->gpgme_op_verify_result(_session->ctx);
vb@0
   905
            assert(gpgme_verify_result);
vb@0
   906
            gpgme_signature = gpgme_verify_result->signatures;
vb@0
   907
vb@0
   908
            if (gpgme_signature) {
vb@0
   909
                stringlist_t *k;
vb@0
   910
                _keylist = new_stringlist(NULL);
vb@0
   911
                assert(_keylist);
vb@0
   912
                if (_keylist == NULL) {
vb@0
   913
                    _session->gpgme_data_release(d_text);
vb@0
   914
                    _session->gpgme_data_release(d_sig);
vb@0
   915
                    return PEP_OUT_OF_MEMORY;
vb@0
   916
                }
vb@0
   917
                k = _keylist;
vb@0
   918
vb@0
   919
                result = PEP_VERIFIED;
vb@0
   920
                do {
vb@0
   921
                    k = stringlist_add(k, gpgme_signature->fpr);
vb@0
   922
                    if (k == NULL) {
vb@0
   923
                        free_stringlist(_keylist);
vb@0
   924
                        _session->gpgme_data_release(d_text);
vb@0
   925
                        _session->gpgme_data_release(d_sig);
vb@0
   926
                        return PEP_OUT_OF_MEMORY;
vb@0
   927
                    }
vb@0
   928
                    if (gpgme_signature->summary & GPGME_SIGSUM_RED) {
vb@0
   929
                        if (gpgme_signature->summary & GPGME_SIGSUM_KEY_EXPIRED
vb@0
   930
                                || gpgme_signature->summary & GPGME_SIGSUM_SIG_EXPIRED) {
vb@0
   931
                            if (result == PEP_VERIFIED
vb@0
   932
                                    || result == PEP_VERIFIED_AND_TRUSTED)
vb@0
   933
                                result = PEP_UNENCRYPTED;
vb@0
   934
                        }
vb@0
   935
                        else {
vb@0
   936
                            result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
vb@0
   937
                            break;
vb@0
   938
                        }
vb@0
   939
                    }
vb@0
   940
                    else {
vb@0
   941
                        if (gpgme_signature->summary & GPGME_SIGSUM_VALID) {
vb@0
   942
                            if (result == PEP_VERIFIED)
vb@0
   943
                                result = PEP_VERIFIED_AND_TRUSTED;
vb@0
   944
                        }
vb@0
   945
                        if (gpgme_signature->summary & GPGME_SIGSUM_GREEN) {
vb@0
   946
                            // good
vb@0
   947
                        }
vb@0
   948
                        else if (gpgme_signature->summary & GPGME_SIGSUM_KEY_MISSING) {
vb@0
   949
                            result = PEP_VERIFY_NO_KEY;
vb@0
   950
                        }
vb@0
   951
                        else if (gpgme_signature->summary & GPGME_SIGSUM_SYS_ERROR) {
vb@0
   952
                            if (result == PEP_VERIFIED
vb@0
   953
                                    || result == PEP_VERIFIED_AND_TRUSTED)
vb@0
   954
                                result = PEP_UNENCRYPTED;
vb@0
   955
                        }
vb@0
   956
                        else {
vb@0
   957
                            // do nothing
vb@0
   958
                        }
vb@0
   959
                    }
vb@0
   960
                } while ((gpgme_signature = gpgme_signature->next));
vb@0
   961
                *keylist = _keylist;
vb@0
   962
            } else {
vb@0
   963
                result = PEP_UNENCRYPTED;
vb@0
   964
            }
vb@0
   965
            break;
vb@0
   966
        }
vb@0
   967
        break;
vb@0
   968
    case GPG_ERR_NO_DATA:
vb@0
   969
        result = PEP_DECRYPT_WRONG_FORMAT;
vb@0
   970
        break;
vb@0
   971
    case GPG_ERR_INV_VALUE:
vb@0
   972
    default:
vb@0
   973
        result = PEP_UNKNOWN_ERROR;
vb@0
   974
        break;
vb@0
   975
    }
vb@0
   976
vb@0
   977
    _session->gpgme_data_release(d_text);
vb@0
   978
    _session->gpgme_data_release(d_sig);
vb@0
   979
vb@0
   980
    return result;
vb@0
   981
}
vb@0
   982
vb@0
   983
DYNAMIC_API PEP_STATUS encrypt_and_sign(
vb@0
   984
        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
vb@0
   985
        size_t psize, char **ctext, size_t *csize
vb@0
   986
    )
vb@0
   987
{
vb@0
   988
	pEpSession *_session = (pEpSession *) session;
vb@0
   989
vb@0
   990
	PEP_STATUS result;
vb@0
   991
	gpgme_error_t gpgme_error;
vb@0
   992
	gpgme_data_t plain, cipher;
vb@0
   993
	gpgme_key_t *rcpt;
vb@0
   994
	gpgme_encrypt_flags_t flags;
vb@0
   995
	const stringlist_t *_keylist;
vb@0
   996
    int i, j;
vb@0
   997
vb@0
   998
	assert(_session);
vb@0
   999
	assert(keylist);
vb@0
  1000
	assert(ptext);
vb@0
  1001
	assert(psize);
vb@0
  1002
	assert(ctext);
vb@0
  1003
	assert(csize);
vb@0
  1004
vb@0
  1005
	*ctext = NULL;
vb@0
  1006
	*csize = 0;
vb@0
  1007
vb@0
  1008
    gpgme_error = _session->gpgme_data_new_from_mem(&plain, ptext, psize, 0);
vb@0
  1009
	assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
  1010
	if (gpgme_error != GPG_ERR_NO_ERROR) {
vb@0
  1011
		if (gpgme_error == GPG_ERR_ENOMEM)
vb@0
  1012
			return PEP_OUT_OF_MEMORY;
vb@0
  1013
		else
vb@0
  1014
			return PEP_UNKNOWN_ERROR;
vb@0
  1015
	}
vb@0
  1016
vb@0
  1017
	gpgme_error = _session->gpgme_data_new(&cipher);
vb@0
  1018
	assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
  1019
	if (gpgme_error != GPG_ERR_NO_ERROR) {
vb@0
  1020
		_session->gpgme_data_release(plain);
vb@0
  1021
		if (gpgme_error == GPG_ERR_ENOMEM)
vb@0
  1022
			return PEP_OUT_OF_MEMORY;
vb@0
  1023
		else
vb@0
  1024
			return PEP_UNKNOWN_ERROR;
vb@0
  1025
	}
vb@0
  1026
vb@0
  1027
    rcpt = (gpgme_key_t *) calloc(stringlist_length(keylist) + 1,
vb@0
  1028
            sizeof(gpgme_key_t));
vb@0
  1029
	assert(rcpt);
vb@0
  1030
	if (rcpt == NULL) {
vb@0
  1031
		_session->gpgme_data_release(plain);
vb@0
  1032
		_session->gpgme_data_release(cipher);
vb@0
  1033
		return PEP_OUT_OF_MEMORY;
vb@0
  1034
	}
vb@0
  1035
vb@0
  1036
    for (_keylist=keylist, i=0; _keylist!=NULL; _keylist=_keylist->next, i++) {
vb@0
  1037
		assert(_keylist->value);
vb@0
  1038
        gpgme_error = _session->gpgme_get_key(_session->ctx, _keylist->value,
vb@0
  1039
                &rcpt[i], 0);
vb@0
  1040
		assert(gpgme_error != GPG_ERR_ENOMEM);
vb@0
  1041
vb@0
  1042
		switch (gpgme_error) {
vb@0
  1043
		case GPG_ERR_ENOMEM:
vb@0
  1044
            for (j=0; j<i; j++)
vb@0
  1045
                _session->gpgme_key_unref(rcpt[j]);
vb@0
  1046
			free(rcpt);
vb@0
  1047
			_session->gpgme_data_release(plain);
vb@0
  1048
			_session->gpgme_data_release(cipher);
vb@0
  1049
			return PEP_OUT_OF_MEMORY;
vb@0
  1050
		case GPG_ERR_NO_ERROR:
vb@0
  1051
			break;
vb@0
  1052
		case GPG_ERR_EOF:
vb@0
  1053
            for (j=0; j<i; j++)
vb@0
  1054
                _session->gpgme_key_unref(rcpt[j]);
vb@0
  1055
			free(rcpt);
vb@0
  1056
			_session->gpgme_data_release(plain);
vb@0
  1057
			_session->gpgme_data_release(cipher);
vb@0
  1058
			return PEP_KEY_NOT_FOUND;
vb@0
  1059
		case GPG_ERR_AMBIGUOUS_NAME:
vb@0
  1060
            for (j=0; j<i; j++)
vb@0
  1061
                _session->gpgme_key_unref(rcpt[j]);
vb@0
  1062
			free(rcpt);
vb@0
  1063
			_session->gpgme_data_release(plain);
vb@0
  1064
			_session->gpgme_data_release(cipher);
vb@0
  1065
			return PEP_KEY_HAS_AMBIG_NAME;
vb@0
  1066
        default: // GPG_ERR_INV_VALUE if CTX or R_KEY is not a valid pointer or
vb@0
  1067
                 // FPR is not a fingerprint or key ID
vb@0
  1068
            for (j=0; j<i; j++)
vb@0
  1069
                _session->gpgme_key_unref(rcpt[j]);
vb@0
  1070
			free(rcpt);
vb@0
  1071
			_session->gpgme_data_release(plain);
vb@0
  1072
			_session->gpgme_data_release(cipher);
vb@0
  1073
			return PEP_GET_KEY_FAILED;
vb@0
  1074
		}
vb@0
  1075
	}
vb@0
  1076
vb@0
  1077
	// TODO: remove that and replace with proper key management
vb@0
  1078
	flags  = GPGME_ENCRYPT_ALWAYS_TRUST;
vb@0
  1079
vb@0
  1080
    gpgme_error = _session->gpgme_op_encrypt_sign(_session->ctx, rcpt, flags,
vb@0
  1081
            plain, cipher);
vb@0
  1082
	switch (gpgme_error) {
vb@0
  1083
	case GPG_ERR_NO_ERROR:
vb@0
  1084
		{
vb@0
  1085
            char *_buffer = NULL;
vb@0
  1086
			size_t reading;
vb@0
  1087
            size_t length = _session->gpgme_data_seek(cipher, 0, SEEK_END);
vb@0
  1088
            assert(length != -1);
vb@0
  1089
			_session->gpgme_data_seek(cipher, 0, SEEK_SET);
vb@0
  1090
vb@0
  1091
			// TODO: make things less memory consuming
vb@0
  1092
            // the following algorithm allocates a buffer for the complete text
vb@0
  1093
vb@0
  1094
            _buffer = (char *) malloc(length + 1);
vb@0
  1095
            assert(_buffer);
vb@0
  1096
            if (_buffer == NULL) {
vb@0
  1097
                for (j=0; j<stringlist_length(keylist); j++)
vb@0
  1098
                    _session->gpgme_key_unref(rcpt[j]);
vb@0
  1099
                free(rcpt);
vb@0
  1100
                _session->gpgme_data_release(plain);
vb@0
  1101
                _session->gpgme_data_release(cipher);
vb@0
  1102
                return PEP_OUT_OF_MEMORY;
vb@0
  1103
            }
vb@0
  1104
vb@0
  1105
            reading = _session->gpgme_data_read(cipher, _buffer, length);
vb@0
  1106
			assert(length == reading);
vb@0
  1107
vb@0
  1108
			*ctext = _buffer;
vb@0
  1109
			*csize = reading;
vb@0
  1110
			(*ctext)[*csize] = 0; // safeguard for naive users
vb@0
  1111
			result = PEP_STATUS_OK;
vb@0
  1112
			break;
vb@0
  1113
		}
vb@0
  1114
	default:
vb@0
  1115
		result = PEP_UNKNOWN_ERROR;
vb@0
  1116
	}
vb@0
  1117
vb@0
  1118
    for (j=0; j<stringlist_length(keylist); j++)
vb@0
  1119
        _session->gpgme_key_unref(rcpt[j]);
vb@0
  1120
	free(rcpt);
vb@0
  1121
	_session->gpgme_data_release(plain);
vb@0
  1122
	_session->gpgme_data_release(cipher);
vb@0
  1123
	return result;
vb@0
  1124
}
vb@0
  1125
vb@0
  1126
DYNAMIC_API PEP_STATUS log_event(
vb@0
  1127
        PEP_SESSION session, const char *title, const char *entity,
vb@0
  1128
        const char *description, const char *comment
vb@0
  1129
    )
vb@0
  1130
{
vb@0
  1131
	pEpSession *_session = (pEpSession *) session;
vb@0
  1132
	PEP_STATUS status = PEP_STATUS_OK;
vb@0
  1133
	int result;
vb@0
  1134
vb@0
  1135
	assert(_session);
vb@0
  1136
	assert(title);
vb@0
  1137
	assert(entity);
vb@0
  1138
vb@0
  1139
	sqlite3_reset(_session->log);
vb@0
  1140
	sqlite3_bind_text(_session->log, 1, title, -1, SQLITE_STATIC);
vb@0
  1141
	sqlite3_bind_text(_session->log, 2, entity, -1, SQLITE_STATIC);
vb@0
  1142
	if (description)
vb@0
  1143
        sqlite3_bind_text(_session->log, 3, description, -1, SQLITE_STATIC);
vb@0
  1144
	else
vb@0
  1145
		sqlite3_bind_null(_session->log, 3);
vb@0
  1146
	if (comment)
vb@0
  1147
		sqlite3_bind_text(_session->log, 4, comment, -1, SQLITE_STATIC);
vb@0
  1148
	else
vb@0
  1149
		sqlite3_bind_null(_session->log, 4);
vb@0
  1150
	do {
vb@0
  1151
		result = sqlite3_step(_session->log);
vb@0
  1152
		assert(result == SQLITE_DONE || result == SQLITE_BUSY);
vb@0
  1153
		if (result != SQLITE_DONE && result != SQLITE_BUSY)
vb@0
  1154
			status = PEP_UNKNOWN_ERROR;
vb@0
  1155
	} while (result == SQLITE_BUSY);
vb@0
  1156
	sqlite3_reset(_session->log);
vb@0
  1157
vb@0
  1158
	return status;
vb@0
  1159
}
vb@0
  1160
vb@0
  1161
DYNAMIC_API PEP_STATUS safeword(
vb@0
  1162
            PEP_SESSION session, uint16_t value, const char *lang,
vb@0
  1163
            char **word, size_t *wsize
vb@0
  1164
        )
vb@0
  1165
{
vb@0
  1166
	pEpSession *_session = (pEpSession *) session;
vb@0
  1167
	PEP_STATUS status = PEP_STATUS_OK;
vb@0
  1168
	int result;
vb@0
  1169
vb@0
  1170
	assert(_session);
vb@0
  1171
	assert(word);
vb@0
  1172
	assert(wsize);
vb@0
  1173
vb@0
  1174
	*word = NULL;
vb@0
  1175
	*wsize = 0;
vb@0
  1176
vb@0
  1177
	if (lang == NULL)
vb@0
  1178
		lang = "en";
vb@0
  1179
vb@0
  1180
	assert((lang[0] >= 'A' && lang[0] <= 'Z')
vb@0
  1181
            || (lang[0] >= 'a' && lang[0] <= 'z'));
vb@0
  1182
	assert((lang[1] >= 'A' && lang[1] <= 'Z')
vb@0
  1183
            || (lang[1] >= 'a' && lang[1] <= 'z'));
vb@0
  1184
	assert(lang[2] == 0);
vb@0
  1185
vb@0
  1186
	sqlite3_reset(_session->safeword);
vb@0
  1187
    sqlite3_bind_text(_session->safeword, 1, lang, -1, SQLITE_STATIC);
vb@0
  1188
	sqlite3_bind_int(_session->safeword, 2, value);
vb@0
  1189
vb@0
  1190
	result = sqlite3_step(_session->safeword);
vb@0
  1191
	if (result == SQLITE_ROW) {
vb@0
  1192
        *word = strdup((const char *) sqlite3_column_text(_session->safeword,
vb@0
  1193
                    1));
vb@0
  1194
		if (*word)
vb@0
  1195
            *wsize = sqlite3_column_bytes(_session->safeword, 1);
vb@0
  1196
		else
vb@0
  1197
			status = PEP_SAFEWORD_NOT_FOUND;
vb@0
  1198
	} else
vb@0
  1199
		status = PEP_SAFEWORD_NOT_FOUND;
vb@0
  1200
vb@0
  1201
	sqlite3_reset(_session->safeword);
vb@0
  1202
	return status;
vb@0
  1203
}
vb@0
  1204
vb@0
  1205
DYNAMIC_API PEP_STATUS safewords(
vb@0
  1206
        PEP_SESSION session, const char *fingerprint, const char *lang,
vb@0
  1207
        char **words, size_t *wsize, int max_words
vb@0
  1208
    )
vb@0
  1209
{
vb@0
  1210
	const char *source = fingerprint;
vb@0
  1211
	char *buffer = calloc(1, MAX_SAFEWORDS_SPACE);
vb@0
  1212
	char *dest = buffer;
vb@0
  1213
	size_t fsize;
vb@0
  1214
    PEP_STATUS _status;
vb@0
  1215
vb@0
  1216
	assert(session);
vb@0
  1217
	assert(fingerprint);
vb@0
  1218
	assert(words);
vb@0
  1219
	assert(wsize);
vb@0
  1220
	assert(max_words >= 0);
vb@0
  1221
vb@0
  1222
	*words = NULL;
vb@0
  1223
	*wsize = 0;
vb@0
  1224
vb@0
  1225
    assert(buffer);
vb@0
  1226
    if (buffer == NULL)
vb@0
  1227
        return PEP_OUT_OF_MEMORY;
vb@0
  1228
vb@0
  1229
	fsize = strlen(fingerprint);
vb@0
  1230
vb@0
  1231
	if (lang == NULL)
vb@0
  1232
		lang = "en";
vb@0
  1233
vb@0
  1234
	assert((lang[0] >= 'A' && lang[0] <= 'Z')
vb@0
  1235
            || (lang[0] >= 'a' && lang[0] <= 'z'));
vb@0
  1236
	assert((lang[1] >= 'A' && lang[1] <= 'Z')
vb@0
  1237
            || (lang[1] >= 'a' && lang[1] <= 'z'));
vb@0
  1238
	assert(lang[2] == 0);
vb@0
  1239
vb@0
  1240
	int n_words = 0;
vb@0
  1241
	while (source < fingerprint + fsize) {
vb@0
  1242
		uint16_t value;
vb@0
  1243
		char *word;
vb@0
  1244
		size_t _wsize;
vb@0
  1245
		int j;
vb@0
  1246
vb@0
  1247
        for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
vb@0
  1248
			if (*source >= 'a' && *source <= 'f')
vb@0
  1249
				value += (*source - 'a' + 10) << (3 - j++) * 4;
vb@0
  1250
			else if (*source >= 'A' && *source <= 'F')
vb@0
  1251
				value += (*source - 'A' + 10) << (3 - j++) * 4;
vb@0
  1252
			else if (*source >= '0' && *source <= '9')
vb@0
  1253
				value += (*source - '0') << (3 - j++) * 4;
vb@0
  1254
			
vb@0
  1255
			source++;
vb@0
  1256
		}
vb@0
  1257
vb@0
  1258
		_status = safeword(session, value, lang, &word, &_wsize);
vb@0
  1259
        if (_status == PEP_OUT_OF_MEMORY) {
vb@0
  1260
            free(buffer);
vb@0
  1261
            return PEP_OUT_OF_MEMORY;
vb@0
  1262
        }
vb@0
  1263
		if (word == NULL) {
vb@0
  1264
            free(buffer);
vb@0
  1265
			return PEP_SAFEWORD_NOT_FOUND;
vb@0
  1266
        }
vb@0
  1267
vb@0
  1268
		if (dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1) {
vb@0
  1269
			strncpy(dest, word, _wsize);
vb@0
  1270
            free(word);
vb@0
  1271
			dest += _wsize;
vb@0
  1272
		}
vb@0
  1273
		else {
vb@0
  1274
            free(word);
vb@0
  1275
			break; // buffer full
vb@0
  1276
        }
vb@0
  1277
vb@0
  1278
		if (source < fingerprint + fsize
vb@0
  1279
                && dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1)
vb@0
  1280
			*dest++ = ' ';
vb@0
  1281
vb@0
  1282
		++n_words;
vb@0
  1283
		if (max_words && n_words >= max_words)
vb@0
  1284
			break;
vb@0
  1285
	}
vb@0
  1286
vb@0
  1287
	*words = buffer;
vb@0
  1288
	*wsize = dest - buffer;
vb@0
  1289
	return PEP_STATUS_OK;
vb@0
  1290
}
vb@0
  1291
vb@0
  1292
pEp_identity *new_identity(
vb@0
  1293
        const char *address, const char *fpr, const char *user_id,
vb@0
  1294
        const char *username
vb@0
  1295
    )
vb@0
  1296
{
vb@0
  1297
    pEp_identity *result = calloc(1, sizeof(pEp_identity));
vb@0
  1298
    assert(result);
vb@0
  1299
    if (result) {
vb@0
  1300
        if (address) {
vb@0
  1301
            result->address = strdup(address);
vb@0
  1302
            assert(result->address);
vb@0
  1303
            if (result->address == NULL) {
vb@0
  1304
                free(result);
vb@0
  1305
                return NULL;
vb@0
  1306
            }
vb@0
  1307
            result->address_size = strlen(address);
vb@0
  1308
        }
vb@0
  1309
        if (fpr) {
vb@0
  1310
            result->fpr = strdup(fpr);
vb@0
  1311
            assert(result->fpr);
vb@0
  1312
            if (result->fpr == NULL) {
vb@0
  1313
                free_identity(result);
vb@0
  1314
                return NULL;
vb@0
  1315
            }
vb@0
  1316
            result->fpr_size = strlen(fpr);
vb@0
  1317
        }
vb@0
  1318
        if (user_id) {
vb@0
  1319
            result->user_id = strdup(user_id);
vb@0
  1320
            assert(result->user_id);
vb@0
  1321
            if (result->user_id == NULL) {
vb@0
  1322
                free_identity(result);
vb@0
  1323
                return NULL;
vb@0
  1324
            }
vb@0
  1325
            result->user_id_size = strlen(user_id);
vb@0
  1326
        }
vb@0
  1327
        if (username) {
vb@0
  1328
            result->username = strdup(username);
vb@0
  1329
            assert(result->username);
vb@0
  1330
            if (result->username == NULL) {
vb@0
  1331
                free_identity(result);
vb@0
  1332
                return NULL;
vb@0
  1333
            }
vb@0
  1334
            result->username_size = strlen(username);
vb@0
  1335
        }
vb@0
  1336
        result->struct_size = sizeof(pEp_identity);
vb@0
  1337
    }
vb@0
  1338
    return result;
vb@0
  1339
}
vb@0
  1340
vb@0
  1341
void free_identity(pEp_identity *identity)
vb@0
  1342
{
vb@0
  1343
    if (identity) {
vb@0
  1344
        free(identity->address);
vb@0
  1345
        free(identity->fpr);
vb@0
  1346
        free(identity->user_id);
vb@0
  1347
        free(identity->username);
vb@0
  1348
        free(identity);
vb@0
  1349
    }
vb@0
  1350
}
vb@0
  1351
vb@0
  1352
DYNAMIC_API PEP_STATUS get_identity(
vb@0
  1353
        PEP_SESSION session, const char *address,
vb@0
  1354
        pEp_identity **identity
vb@0
  1355
    )
vb@0
  1356
{
vb@0
  1357
	pEpSession *_session = (pEpSession *) session;
vb@0
  1358
	PEP_STATUS status = PEP_STATUS_OK;
vb@0
  1359
	static pEp_identity *_identity;
vb@0
  1360
	int result;
vb@0
  1361
	const char *_lang;
vb@0
  1362
vb@0
  1363
	assert(session);
vb@0
  1364
	assert(address);
vb@8
  1365
    assert(address[0]);
vb@0
  1366
vb@0
  1367
    sqlite3_reset(_session->get_identity);
vb@0
  1368
    sqlite3_bind_text(_session->get_identity, 1, address, -1, SQLITE_STATIC);
vb@0
  1369
vb@0
  1370
    result = sqlite3_step(_session->get_identity);
vb@0
  1371
	switch (result) {
vb@0
  1372
	case SQLITE_ROW:
vb@0
  1373
        _identity = new_identity(
vb@0
  1374
                address,
vb@0
  1375
                (const char *) sqlite3_column_text(_session->get_identity, 0),
vb@0
  1376
                (const char *) sqlite3_column_text(_session->get_identity, 1),
vb@0
  1377
                (const char *) sqlite3_column_text(_session->get_identity, 2)
vb@0
  1378
                );
vb@0
  1379
        assert(_identity);
vb@0
  1380
        if (_identity == NULL)
vb@0
  1381
            return PEP_OUT_OF_MEMORY;
vb@0
  1382
vb@0
  1383
        _identity->comm_type = (PEP_comm_type) sqlite3_column_int(_session->get_identity, 3);
vb@0
  1384
        _lang = (const char *) sqlite3_column_text(_session->get_identity, 4);
vb@0
  1385
        if (_lang && _lang[0]) {
vb@0
  1386
			assert(_lang[0] >= 'a' && _lang[0] <= 'z');
vb@0
  1387
			assert(_lang[1] >= 'a' && _lang[1] <= 'z');
vb@0
  1388
			assert(_lang[2] == 0);
vb@0
  1389
			_identity->lang[0] = _lang[0];
vb@0
  1390
			_identity->lang[1] = _lang[1];
vb@0
  1391
            _identity->lang[2] = 0;
vb@0
  1392
		}
vb@0
  1393
		*identity = _identity;
vb@0
  1394
		break;
vb@0
  1395
	default:
vb@0
  1396
        status = PEP_CANNOT_FIND_IDENTITY;
vb@0
  1397
		*identity = NULL;
vb@0
  1398
	}
vb@0
  1399
vb@0
  1400
    sqlite3_reset(_session->get_identity);
vb@0
  1401
	return status;
vb@0
  1402
}
vb@0
  1403
vb@0
  1404
DYNAMIC_API PEP_STATUS set_identity(
vb@0
  1405
        PEP_SESSION session, const pEp_identity *identity
vb@0
  1406
    )
vb@0
  1407
{
vb@0
  1408
	pEpSession *_session = (pEpSession *) session;
vb@0
  1409
	int result;
vb@0
  1410
vb@0
  1411
	assert(session);
vb@0
  1412
	assert(identity);
vb@0
  1413
	assert(identity->address);
vb@0
  1414
	assert(identity->fpr);
vb@0
  1415
	assert(identity->user_id);
vb@0
  1416
	assert(identity->username);
vb@0
  1417
vb@0
  1418
	sqlite3_exec(_session->db, "BEGIN ;", NULL, NULL, NULL);
vb@0
  1419
vb@0
  1420
	sqlite3_reset(_session->set_person);
vb@0
  1421
    sqlite3_bind_text(_session->set_person, 1, identity->user_id, -1,
vb@0
  1422
            SQLITE_STATIC);
vb@0
  1423
    sqlite3_bind_text(_session->set_person, 2, identity->username, -1,
vb@0
  1424
            SQLITE_STATIC);
vb@0
  1425
	if (identity->lang[0])
vb@0
  1426
        sqlite3_bind_text(_session->set_person, 3, identity->lang, 1,
vb@0
  1427
                SQLITE_STATIC);
vb@0
  1428
	else
vb@0
  1429
		sqlite3_bind_null(_session->set_person, 3);
vb@0
  1430
	result = sqlite3_step(_session->set_person);
vb@0
  1431
	sqlite3_reset(_session->set_person);
vb@0
  1432
	if (result != SQLITE_DONE) {
vb@0
  1433
		sqlite3_exec(_session->db, "ROLLBACK ;", NULL, NULL, NULL);
vb@0
  1434
		return PEP_CANNOT_SET_PERSON;
vb@0
  1435
	}
vb@0
  1436
vb@0
  1437
	sqlite3_reset(_session->set_pgp_keypair);
vb@0
  1438
    sqlite3_bind_text(_session->set_pgp_keypair, 1, identity->fpr, -1,
vb@0
  1439
            SQLITE_STATIC);
vb@0
  1440
	result = sqlite3_step(_session->set_pgp_keypair);
vb@0
  1441
	sqlite3_reset(_session->set_pgp_keypair);
vb@0
  1442
	if (result != SQLITE_DONE) {
vb@0
  1443
		sqlite3_exec(_session->db, "ROLLBACK ;", NULL, NULL, NULL);
vb@0
  1444
		return PEP_CANNOT_SET_PGP_KEYPAIR;
vb@0
  1445
	}
vb@0
  1446
vb@0
  1447
	sqlite3_reset(_session->set_identity);
vb@0
  1448
    sqlite3_bind_text(_session->set_identity, 1, identity->address, -1,
vb@0
  1449
            SQLITE_STATIC);
vb@0
  1450
    sqlite3_bind_text(_session->set_identity, 2, identity->fpr, -1,
vb@0
  1451
            SQLITE_STATIC);
vb@0
  1452
    sqlite3_bind_text(_session->set_identity, 3, identity->user_id, -1,
vb@0
  1453
            SQLITE_STATIC);
vb@0
  1454
	result = sqlite3_step(_session->set_identity);
vb@0
  1455
	sqlite3_reset(_session->set_identity);
vb@0
  1456
	if (result != SQLITE_DONE) {
vb@0
  1457
		sqlite3_exec(_session->db, "ROLLBACK ;", NULL, NULL, NULL);
vb@0
  1458
		return PEP_CANNOT_SET_IDENTITY;
vb@0
  1459
	}
vb@0
  1460
vb@0
  1461
	sqlite3_reset(_session->set_trust);
vb@0
  1462
    sqlite3_bind_text(_session->set_trust, 1, identity->user_id, -1,
vb@0
  1463
            SQLITE_STATIC);
vb@0
  1464
    sqlite3_bind_text(_session->set_trust, 2, identity->fpr, -1,
vb@0
  1465
            SQLITE_STATIC);
vb@0
  1466
	sqlite3_bind_int(_session->set_trust, 3, identity->comm_type);
vb@0
  1467
	result = sqlite3_step(_session->set_trust);
vb@0
  1468
	sqlite3_reset(_session->set_trust);
vb@0
  1469
	if (result != SQLITE_DONE) {
vb@0
  1470
		sqlite3_exec(_session->db, "ROLLBACK ;", NULL, NULL, NULL);
vb@0
  1471
		return PEP_CANNOT_SET_IDENTITY;
vb@0
  1472
	}
vb@0
  1473
vb@0
  1474
    result = sqlite3_exec(_session->db, "COMMIT ;", NULL, NULL, NULL);
vb@0
  1475
	if (result == SQLITE_OK)
vb@0
  1476
		return PEP_STATUS_OK;
vb@0
  1477
	else
vb@0
  1478
		return PEP_COMMIT_FAILED;
vb@0
  1479
}
vb@0
  1480
vb@0
  1481
DYNAMIC_API PEP_STATUS generate_keypair(
vb@0
  1482
        PEP_SESSION session, pEp_identity *identity
vb@0
  1483
    )
vb@0
  1484
{
vb@0
  1485
	pEpSession *_session = (pEpSession *) session;
vb@0
  1486
	gpgme_error_t gpgme_error;
vb@0
  1487
    char *parms;
vb@0
  1488
    const char *template =
vb@0
  1489
        "<GnupgKeyParms format=\"internal\">\n"
vb@0
  1490
        "Key-Type: RSA\n"
vb@0
  1491
        "Key-Length: 4096\n"
vb@0
  1492
        "Name-Real: %s\n"
vb@0
  1493
        "Name-Email: %s\n"
vb@0
  1494
        /* "Passphrase: %s\n" */
vb@0
  1495
        "Expire-Date: 1y\n"
vb@0
  1496
        "</GnupgKeyParms>\n";
vb@0
  1497
    int result;
vb@0
  1498
    gpgme_genkey_result_t gpgme_genkey_result;
vb@0
  1499
vb@0
  1500
    assert(session);
vb@0
  1501
    assert(identity);
vb@0
  1502
    assert(identity->address);
vb@0
  1503
    assert(identity->fpr == NULL);
vb@0
  1504
    assert(identity->username);
vb@0
  1505
    
vb@0
  1506
    parms = calloc(1, PARMS_MAX);
vb@0
  1507
    assert(parms);
vb@0
  1508
    if (parms == NULL)
vb@0
  1509
        return PEP_OUT_OF_MEMORY;
vb@0
  1510
vb@0
  1511
    result = snprintf(parms, PARMS_MAX, template, identity->username,
vb@0
  1512
            identity->address); // , _session->passphrase);
vb@0
  1513
    assert(result < PARMS_MAX);
vb@0
  1514
    if (result >= PARMS_MAX) {
vb@0
  1515
        free(parms);
vb@0
  1516
        return PEP_BUFFER_TOO_SMALL;
vb@0
  1517
    }
vb@0
  1518
vb@0
  1519
    gpgme_error = _session->gpgme_op_genkey(_session->ctx, parms, NULL, NULL);
vb@0
  1520
    free(parms);
vb@0
  1521
vb@0
  1522
    switch (gpgme_error) {
vb@0
  1523
    case GPG_ERR_NO_ERROR:
vb@0
  1524
        break;
vb@0
  1525
    case GPG_ERR_INV_VALUE:
vb@0
  1526
        return PEP_ILLEGAL_VALUE;
vb@0
  1527
    case GPG_ERR_GENERAL:
vb@0
  1528
        return PEP_CANNOT_CREATE_KEY;
vb@0
  1529
    default:
vb@0
  1530
        assert(0);
vb@0
  1531
        return PEP_UNKNOWN_ERROR;
vb@0
  1532
    }
vb@0
  1533
vb@0
  1534
    gpgme_genkey_result = _session->gpgme_op_genkey_result(_session->ctx);
vb@0
  1535
    assert(gpgme_genkey_result);
vb@0
  1536
    assert(gpgme_genkey_result->fpr);
vb@0
  1537
vb@0
  1538
    identity->fpr = strdup(gpgme_genkey_result->fpr);
vb@0
  1539
vb@0
  1540
    return PEP_STATUS_OK;
vb@0
  1541
}
vb@0
  1542
vb@0
  1543
PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
vb@0
  1544
{
vb@0
  1545
	pEpSession *_session = (pEpSession *) session;
vb@0
  1546
	gpgme_error_t gpgme_error;
vb@0
  1547
    gpgme_key_t key;
vb@0
  1548
vb@0
  1549
    assert(session);
vb@0
  1550
    assert(fpr);
vb@0
  1551
vb@0
  1552
    gpgme_error = _session->gpgme_get_key(_session->ctx, fpr, &key, 0);
vb@0
  1553
    assert(gpgme_error != GPG_ERR_ENOMEM);
vb@0
  1554
    switch (gpgme_error) {
vb@0
  1555
    case GPG_ERR_NO_ERROR:
vb@0
  1556
        break;
vb@0
  1557
    case GPG_ERR_EOF:
vb@0
  1558
        return PEP_KEY_NOT_FOUND;
vb@0
  1559
    case GPG_ERR_INV_VALUE:
vb@0
  1560
        return PEP_ILLEGAL_VALUE;
vb@0
  1561
    case GPG_ERR_AMBIGUOUS_NAME:
vb@0
  1562
        return PEP_KEY_HAS_AMBIG_NAME;
vb@0
  1563
    case GPG_ERR_ENOMEM:
vb@0
  1564
        return PEP_OUT_OF_MEMORY;
vb@0
  1565
    default:
vb@0
  1566
        assert(0);
vb@0
  1567
        return PEP_UNKNOWN_ERROR;
vb@0
  1568
    }
vb@0
  1569
vb@0
  1570
    gpgme_error = _session->gpgme_op_delete(_session->ctx, key, 1);
vb@0
  1571
    _session->gpgme_key_unref(key);
vb@0
  1572
    switch (gpgme_error) {
vb@0
  1573
    case GPG_ERR_NO_ERROR:
vb@0
  1574
        break;
vb@0
  1575
    case GPG_ERR_INV_VALUE:
vb@0
  1576
        assert(0);
vb@0
  1577
        return PEP_UNKNOWN_ERROR;
vb@0
  1578
    case GPG_ERR_NO_PUBKEY:
vb@0
  1579
        assert(0);
vb@0
  1580
        return PEP_KEY_NOT_FOUND;
vb@0
  1581
    case GPG_ERR_AMBIGUOUS_NAME:
vb@0
  1582
        assert(0);
vb@0
  1583
        return PEP_KEY_HAS_AMBIG_NAME;
vb@0
  1584
    default:
vb@0
  1585
        assert(0);
vb@0
  1586
        return PEP_UNKNOWN_ERROR;
vb@0
  1587
    }
vb@0
  1588
vb@0
  1589
    return PEP_STATUS_OK;
vb@0
  1590
}
vb@0
  1591
vb@0
  1592
PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
vb@0
  1593
{
vb@0
  1594
	pEpSession *_session = (pEpSession *) session;
vb@0
  1595
	gpgme_error_t gpgme_error;
vb@0
  1596
    gpgme_data_t dh;
vb@0
  1597
vb@0
  1598
    assert(session);
vb@0
  1599
    assert(key_data);
vb@0
  1600
vb@0
  1601
    gpgme_error = _session->gpgme_data_new_from_mem(&dh, key_data, size, 0);
vb@0
  1602
    assert(gpgme_error != GPG_ERR_ENOMEM);
vb@0
  1603
    switch (gpgme_error) {
vb@0
  1604
    case GPG_ERR_NO_ERROR:
vb@0
  1605
        break;
vb@0
  1606
    case GPG_ERR_ENOMEM:
vb@0
  1607
        return PEP_OUT_OF_MEMORY;
vb@0
  1608
    case GPG_ERR_INV_VALUE:
vb@0
  1609
        assert(0);
vb@0
  1610
        return PEP_UNKNOWN_ERROR;
vb@0
  1611
    default:
vb@0
  1612
        assert(0);
vb@0
  1613
        return PEP_UNKNOWN_ERROR;
vb@0
  1614
    }
vb@0
  1615
vb@0
  1616
    gpgme_error = _session->gpgme_op_import(_session->ctx, dh);
vb@0
  1617
    switch (gpgme_error) {
vb@0
  1618
    case GPG_ERR_NO_ERROR:
vb@0
  1619
        break;
vb@0
  1620
    case GPG_ERR_INV_VALUE:
vb@0
  1621
        assert(0);
vb@0
  1622
        _session->gpgme_data_release(dh);
vb@0
  1623
        return PEP_UNKNOWN_ERROR;
vb@0
  1624
    case GPG_ERR_NO_DATA:
vb@0
  1625
        _session->gpgme_data_release(dh);
vb@0
  1626
        return PEP_ILLEGAL_VALUE;
vb@0
  1627
    default:
vb@0
  1628
        assert(0);
vb@0
  1629
        _session->gpgme_data_release(dh);
vb@0
  1630
        return PEP_UNKNOWN_ERROR;
vb@0
  1631
    }
vb@0
  1632
vb@0
  1633
    _session->gpgme_data_release(dh);
vb@0
  1634
    return PEP_STATUS_OK;
vb@0
  1635
}
vb@0
  1636
vb@0
  1637
PEP_STATUS export_key(
vb@0
  1638
        PEP_SESSION session, const char *fpr, char **key_data, size_t *size
vb@0
  1639
    )
vb@0
  1640
{
vb@0
  1641
	pEpSession *_session = (pEpSession *) session;
vb@0
  1642
	gpgme_error_t gpgme_error;
vb@0
  1643
    gpgme_data_t dh;
vb@0
  1644
    size_t _size;
vb@0
  1645
    char *buffer;
vb@0
  1646
    int reading;
vb@0
  1647
vb@0
  1648
    assert(session);
vb@0
  1649
    assert(fpr);
vb@0
  1650
    assert(key_data);
vb@0
  1651
    assert(size);
vb@0
  1652
vb@0
  1653
    gpgme_error = _session->gpgme_data_new(&dh);
vb@0
  1654
    assert(gpgme_error != GPG_ERR_ENOMEM);
vb@0
  1655
    switch (gpgme_error) {
vb@0
  1656
    case GPG_ERR_NO_ERROR:
vb@0
  1657
        break;
vb@0
  1658
    case GPG_ERR_ENOMEM:
vb@0
  1659
        return PEP_OUT_OF_MEMORY;
vb@0
  1660
    case GPG_ERR_INV_VALUE:
vb@0
  1661
        assert(0);
vb@0
  1662
        return PEP_UNKNOWN_ERROR;
vb@0
  1663
    default:
vb@0
  1664
        assert(0);
vb@0
  1665
        return PEP_UNKNOWN_ERROR;
vb@0
  1666
    }
vb@0
  1667
vb@0
  1668
    gpgme_error = _session->gpgme_op_export(_session->ctx, fpr,
vb@0
  1669
            GPGME_EXPORT_MODE_MINIMAL, dh);
vb@0
  1670
    switch (gpgme_error) {
vb@0
  1671
    case GPG_ERR_NO_ERROR:
vb@0
  1672
        break;
vb@0
  1673
    case GPG_ERR_EOF:
vb@0
  1674
        _session->gpgme_data_release(dh);
vb@0
  1675
        return PEP_KEY_NOT_FOUND;
vb@0
  1676
    case GPG_ERR_INV_VALUE:
vb@0
  1677
        assert(0);
vb@0
  1678
        _session->gpgme_data_release(dh);
vb@0
  1679
        return PEP_UNKNOWN_ERROR;
vb@0
  1680
    default:
vb@0
  1681
        assert(0);
vb@0
  1682
        _session->gpgme_data_release(dh);
vb@0
  1683
        return PEP_UNKNOWN_ERROR;
vb@0
  1684
    };
vb@0
  1685
vb@0
  1686
    _size = _session->gpgme_data_seek(dh, 0, SEEK_END);
vb@0
  1687
    assert(_size != -1);
vb@0
  1688
    _session->gpgme_data_seek(dh, 0, SEEK_SET);
vb@0
  1689
vb@0
  1690
    buffer = malloc(_size + 1);
vb@0
  1691
    assert(buffer);
vb@0
  1692
    if (buffer == NULL) {
vb@0
  1693
        _session->gpgme_data_release(dh);
vb@0
  1694
        return PEP_OUT_OF_MEMORY;
vb@0
  1695
    }
vb@0
  1696
vb@0
  1697
    reading = _session->gpgme_data_read(dh, buffer, _size);
vb@0
  1698
    assert(_size == reading);
vb@0
  1699
vb@0
  1700
    // safeguard for the naive user
vb@0
  1701
    buffer[_size] = 0;
vb@0
  1702
vb@0
  1703
    *key_data = buffer;
vb@0
  1704
    *size = _size;
vb@0
  1705
vb@0
  1706
    _session->gpgme_data_release(dh);
vb@0
  1707
    return PEP_STATUS_OK;
vb@0
  1708
}
vb@0
  1709
vb@0
  1710
static void _switch_mode(pEpSession *_session, gpgme_keylist_mode_t remove_mode,
vb@0
  1711
        gpgme_keylist_mode_t add_mode)
vb@0
  1712
{
vb@0
  1713
	gpgme_error_t gpgme_error;
vb@0
  1714
    gpgme_keylist_mode_t mode;
vb@0
  1715
vb@0
  1716
    mode = _session->gpgme_get_keylist_mode(_session->ctx);
vb@0
  1717
vb@0
  1718
    mode &= ~remove_mode;
vb@0
  1719
    mode |= add_mode;
vb@0
  1720
vb@0
  1721
    gpgme_error = _session->gpgme_set_keylist_mode(_session->ctx, mode);
vb@0
  1722
    assert(gpgme_error == GPG_ERR_NO_ERROR);
vb@0
  1723
}
vb@0
  1724
vb@0
  1725
PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
vb@0
  1726
{
vb@0
  1727
	pEpSession *_session = (pEpSession *) session;
vb@0
  1728
	gpgme_error_t gpgme_error;
vb@0
  1729
    gpgme_key_t key;
vb@0
  1730
vb@0
  1731
    assert(session);
vb@0
  1732
    assert(pattern);
vb@0
  1733
vb@0
  1734
    _switch_mode(_session, GPGME_KEYLIST_MODE_LOCAL, GPGME_KEYLIST_MODE_EXTERN);
vb@0
  1735
vb@0
  1736
    gpgme_error = _session->gpgme_op_keylist_start(_session->ctx, pattern, 0);
vb@0
  1737
    switch (gpgme_error) {
vb@0
  1738
    case GPG_ERR_NO_ERROR:
vb@0
  1739
        break;
vb@0
  1740
    case GPG_ERR_INV_VALUE:
vb@0
  1741
        assert(0);
vb@0
  1742
        _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
vb@0
  1743
                GPGME_KEYLIST_MODE_LOCAL);
vb@0
  1744
        return PEP_UNKNOWN_ERROR;
vb@0
  1745
    default:
vb@0
  1746
        _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
vb@0
  1747
                GPGME_KEYLIST_MODE_LOCAL);
vb@0
  1748
        return PEP_GET_KEY_FAILED;
vb@0
  1749
    };
vb@0
  1750
vb@0
  1751
    do {
vb@0
  1752
        gpgme_error = _session->gpgme_op_keylist_next(_session->ctx, &key);
vb@0
  1753
        assert(gpgme_error != GPG_ERR_INV_VALUE);
vb@0
  1754
        switch (gpgme_error) {
vb@0
  1755
        case GPG_ERR_EOF:
vb@0
  1756
            break;
vb@0
  1757
        case GPG_ERR_NO_ERROR:
vb@0
  1758
            {
vb@0
  1759
                gpgme_error_t gpgme_error;
vb@0
  1760
                gpgme_key_t keys[2];
vb@0
  1761
vb@0
  1762
                keys[0] = key;
vb@0
  1763
                keys[1] = NULL;
vb@0
  1764
vb@0
  1765
                gpgme_error = _session->gpgme_op_import_keys(_session->ctx, keys);
vb@0
  1766
                _session->gpgme_key_unref(key);
vb@0
  1767
                assert(gpgme_error != GPG_ERR_INV_VALUE);
vb@0
  1768
                assert(gpgme_error != GPG_ERR_CONFLICT);
vb@0
  1769
            }
vb@0
  1770
            break;
vb@0
  1771
        case GPG_ERR_ENOMEM:
vb@0
  1772
            _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
vb@0
  1773
                    GPGME_KEYLIST_MODE_LOCAL);
vb@0
  1774
            _session->gpgme_op_keylist_end(_session->ctx);
vb@0
  1775
            return PEP_OUT_OF_MEMORY;
vb@0
  1776
        default:
vb@0
  1777
            // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
vb@0
  1778
            // reading first key
vb@0
  1779
#ifndef NDEBUG
vb@0
  1780
            fprintf(stderr, "warning: unknown result 0x%x of"
vb@0
  1781
                    " gpgme_op_keylist_next()\n", gpgme_error);
vb@0
  1782
#endif
vb@0
  1783
            gpgme_error = GPG_ERR_EOF;
vb@0
  1784
            break;
vb@0
  1785
        };
vb@0
  1786
    } while (gpgme_error != GPG_ERR_EOF);
vb@0
  1787
vb@0
  1788
    _session->gpgme_op_keylist_end(_session->ctx);
vb@0
  1789
    _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
vb@0
  1790
            GPGME_KEYLIST_MODE_LOCAL);
vb@0
  1791
    return PEP_STATUS_OK;
vb@0
  1792
}
vb@0
  1793
vb@0
  1794
DYNAMIC_API PEP_STATUS find_keys(
vb@0
  1795
        PEP_SESSION session, const char *pattern, stringlist_t **keylist
vb@0
  1796
    )
vb@0
  1797
{
vb@0
  1798
	pEpSession *_session = (pEpSession *) session;
vb@0
  1799
	gpgme_error_t gpgme_error;
vb@0
  1800
    gpgme_key_t key;
vb@0
  1801
    stringlist_t *_keylist;
vb@0
  1802
    char *fpr;
vb@0
  1803
vb@0
  1804
    assert(session);
vb@0
  1805
    assert(pattern);
vb@0
  1806
    assert(keylist);
vb@0
  1807
vb@0
  1808
    *keylist = NULL;
vb@0
  1809
vb@0
  1810
    gpgme_error = _session->gpgme_op_keylist_start(_session->ctx, pattern, 0);
vb@0
  1811
    switch (gpgme_error) {
vb@0
  1812
    case GPG_ERR_NO_ERROR:
vb@0
  1813
        break;
vb@0
  1814
    case GPG_ERR_INV_VALUE:
vb@0
  1815
        assert(0);
vb@0
  1816
        return PEP_UNKNOWN_ERROR;
vb@0
  1817
    default:
vb@0
  1818
        return PEP_GET_KEY_FAILED;
vb@0
  1819
    };
vb@0
  1820
vb@0
  1821
    _keylist = new_stringlist(NULL);
vb@0
  1822
    stringlist_t *_k = _keylist;
vb@0
  1823
vb@0
  1824
    do {
vb@0
  1825
        gpgme_error = _session->gpgme_op_keylist_next(_session->ctx, &key);
vb@0
  1826
        assert(gpgme_error != GPG_ERR_INV_VALUE);
vb@0
  1827
        switch (gpgme_error) {
vb@0
  1828
        case GPG_ERR_EOF:
vb@0
  1829
            break;
vb@0
  1830
        case GPG_ERR_NO_ERROR:
vb@0
  1831
            assert(key);
vb@0
  1832
            assert(key->subkeys);
vb@0
  1833
            fpr = key->subkeys->fpr;
vb@0
  1834
            assert(fpr);
vb@0
  1835
            _k = stringlist_add(_k, fpr);
vb@0
  1836
            assert(_k);
vb@0
  1837
            if (_k != NULL)
vb@0
  1838
                break;
vb@0
  1839
        case GPG_ERR_ENOMEM:
vb@0
  1840
            free_stringlist(_keylist);
vb@0
  1841
            _session->gpgme_op_keylist_end(_session->ctx);
vb@0
  1842
            return PEP_OUT_OF_MEMORY;
vb@0
  1843
        default:
vb@0
  1844
            // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
vb@0
  1845
            // reading first key
vb@0
  1846
#ifndef NDEBUG
vb@0
  1847
            fprintf(stderr, "warning: unknown result 0x%x of"
vb@0
  1848
                    " gpgme_op_keylist_next()\n", gpgme_error);
vb@0
  1849
#endif
vb@0
  1850
            gpgme_error = GPG_ERR_EOF;
vb@0
  1851
            break;
vb@0
  1852
        };
vb@0
  1853
    } while (gpgme_error != GPG_ERR_EOF);
vb@0
  1854
vb@0
  1855
    _session->gpgme_op_keylist_end(_session->ctx);
vb@0
  1856
    *keylist = _keylist;
vb@0
  1857
    return PEP_STATUS_OK;
vb@0
  1858
}
vb@0
  1859
vb@0
  1860
PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
vb@0
  1861
{
vb@0
  1862
	pEpSession *_session = (pEpSession *) session;
vb@0
  1863
	gpgme_error_t gpgme_error;
vb@0
  1864
vb@8
  1865
    assert(session);
vb@8
  1866
    assert(pattern);
vb@8
  1867
vb@0
  1868
    gpgme_error = _session->gpgme_op_export(_session->ctx, pattern,
vb@0
  1869
            GPGME_EXPORT_MODE_EXTERN, NULL);
vb@0
  1870
    assert(gpgme_error != GPG_ERR_INV_VALUE);
vb@0
  1871
    if (gpgme_error == GPG_ERR_NO_ERROR)
vb@0
  1872
        return PEP_STATUS_OK;
vb@0
  1873
    else
vb@0
  1874
        return PEP_CANNOT_SEND_KEY;
vb@0
  1875
}
vb@0
  1876
vb@0
  1877
void pEp_free(void *p)
vb@0
  1878
{
vb@0
  1879
    free(p);
vb@0
  1880
}
vb@0
  1881
vb@8
  1882
DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
vb@8
  1883
{
vb@8
  1884
    pEpSession *_session = (pEpSession *) session;
vb@8
  1885
    PEP_STATUS status = PEP_STATUS_OK;
vb@8
  1886
    int result;
vb@8
  1887
vb@8
  1888
    assert(session);
vb@8
  1889
    assert(identity);
vb@8
  1890
    assert(identity->user_id);
vb@8
  1891
    assert(identity->user_id[0]);
vb@8
  1892
    assert(identity->fpr);
vb@8
  1893
    assert(identity->fpr[0]);
vb@8
  1894
vb@8
  1895
    identity->comm_type = PEP_ct_unknown;
vb@8
  1896
vb@8
  1897
    sqlite3_reset(_session->get_trust);
vb@8
  1898
    sqlite3_bind_text(_session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
vb@8
  1899
    sqlite3_bind_text(_session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
vb@8
  1900
vb@8
  1901
    result = sqlite3_step(_session->get_trust);
vb@8
  1902
    switch (result) {
vb@8
  1903
    case SQLITE_ROW: {
vb@8
  1904
        const char * user_id = (const char *) sqlite3_column_text(_session->get_trust, 1);
vb@8
  1905
        int comm_type = (PEP_comm_type) sqlite3_column_int(_session->get_trust, 2);
vb@8
  1906
vb@8
  1907
        if (strcmp(user_id, identity->user_id) != 0) {
vb@8
  1908
            free(identity->user_id);
vb@8
  1909
            identity->user_id = strdup(user_id);
vb@8
  1910
            assert(identity->user_id);
vb@8
  1911
            if (identity->user_id == NULL)
vb@8
  1912
                return PEP_OUT_OF_MEMORY;
vb@8
  1913
        }
vb@8
  1914
        identity->comm_type = comm_type;
vb@8
  1915
        break;
vb@8
  1916
    }
vb@8
  1917
 
vb@8
  1918
    default:
vb@8
  1919
        status = PEP_CANNOT_FIND_IDENTITY;
vb@8
  1920
    }
vb@8
  1921
vb@8
  1922
    sqlite3_reset(_session->get_trust);
vb@8
  1923
    return status;
vb@8
  1924
}