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