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