src/pEp_internal.h
author Krista Bennett <krista@pep-project.org>
Tue, 19 Sep 2017 15:59:42 +0200
branchENGINE-214
changeset 2078 12571364b016
parent 2048 4612060c1d49
child 2120 b99308bd100a
permissions -rw-r--r--
ENGINE-214: actually works, but will need to be changed due to need to encapsulate message version in protected part of message. Infrastructure to do that comes in with this commit, but we need to refactor _decrypt_message in order to do everything cleanly. Branching for ENGINE-262 and will return to this branch once done with refactor.
vb@1517
     1
// This file is under GNU General Public License 3.0
vb@1517
     2
// see LICENSE.txt
vb@1517
     3
vb@928
     4
#define PEP_ENGINE_VERSION "0.8.0"
vb@908
     5
vb@908
     6
// maximum attachment size to import as key 1MB, maximum of 20 attachments
vb@908
     7
vb@908
     8
#define MAX_KEY_SIZE (1024 * 1024)
vb@908
     9
#define MAX_KEYS_TO_IMPORT  20
vb@24
    10
vb@233
    11
// this is 20 trustwords with 79 chars max
vb@251
    12
#define MAX_TRUSTWORDS_SPACE (20 * 80)
vb@24
    13
vb@24
    14
// XML parameters string
vb@24
    15
#define PARMS_MAX 32768
vb@24
    16
vb@24
    17
// maximum busy wait time in ms
vb@24
    18
#define BUSY_WAIT_TIME 5000
vb@24
    19
vb@24
    20
// maximum line length for reading gpg.conf
vb@24
    21
#define MAX_LINELENGTH 1024
vb@24
    22
vb@24
    23
// default keyserver
vb@450
    24
#ifndef DEFAULT_KEYSERVER
vb@24
    25
#define DEFAULT_KEYSERVER "hkp://keys.gnupg.net"
vb@450
    26
#endif
vb@450
    27
vb@450
    28
// crashdump constants
vb@450
    29
#ifndef CRASHDUMP_DEFAULT_LINES
vb@450
    30
#define CRASHDUMP_DEFAULT_LINES 100
vb@450
    31
#endif
vb@450
    32
#define CRASHDUMP_MAX_LINES 32767
vb@24
    33
krista@2045
    34
// p≡p full string, NUL-terminated
krista@2045
    35
#ifndef PEP_SUBJ_STRING
krista@2045
    36
#define PEP_SUBJ_STRING {0x70,0xE2,0x89,0xA1,0x70,0x00}
krista@2045
    37
#define PEP_SUBJ_BYTELEN 5
krista@2045
    38
#endif
krista@2045
    39
krista@2078
    40
#ifndef PEP_SUBJ_KEY
krista@2078
    41
#define PEP_SUBJ_KEY "Subject: "
krista@2078
    42
#define PEP_SUBJ_KEY_LC "subject: "
krista@2078
    43
#define PEP_SUBJ_KEY_LEN 9
krista@2078
    44
#endif
krista@2078
    45
krista@2078
    46
#ifndef PEP_MSG_VERSION_KEY
krista@2078
    47
#define PEP_MSG_VERSION_KEY "pEp-Message-Version: "
krista@2078
    48
#define PEP_MSG_VERSION_KEY_LC "pep-message-version: "
krista@2078
    49
#define PEP_MSG_VERSION_KEY_LEN 21
krista@2078
    50
#endif
krista@2078
    51
krista@2078
    52
vb@130
    53
#include "platform.h"
vb@130
    54
vb@24
    55
#ifdef WIN32
vb@24
    56
#define LOCAL_DB windoze_local_db()
vb@24
    57
#define SYSTEM_DB windoze_system_db()
vb@24
    58
#define LIBGPGME "libgpgme-11.dll"
vb@24
    59
#else // UNIX
vb@24
    60
#define _POSIX_C_SOURCE 200809L
vb@24
    61
#include <dlfcn.h>
vb@24
    62
#define LOCAL_DB unix_local_db()
vb@24
    63
#ifndef SYSTEM_DB
vb@24
    64
#define SYSTEM_DB "/usr/share/pEp/system.db"
vb@24
    65
#endif
vb@24
    66
#ifndef LIBGPGME
vb@24
    67
#define LIBGPGME "libgpgme-pthread.so"
vb@24
    68
#endif
vb@24
    69
#endif
vb@24
    70
vb@24
    71
#include <locale.h>
vb@24
    72
#include <stdlib.h>
vb@24
    73
#include <string.h>
vb@24
    74
#include <assert.h>
vb@24
    75
#include <stdio.h>
edouard@1521
    76
#include <ctype.h>
vb@24
    77
damiano@1997
    78
#ifdef SQLITE3_FROM_OS
damiano@1997
    79
#include <sqlite3.h>
damiano@1997
    80
#else
vb@24
    81
#include "sqlite3.h"
damiano@1997
    82
#endif
vb@24
    83
vb@24
    84
#define _EXPORT_PEP_ENGINE_DLL
vb@24
    85
#include "pEpEngine.h"
Edouard@168
    86
Edouard@168
    87
// If not specified, build for GPG
Edouard@168
    88
#ifndef USE_NETPGP
Edouard@168
    89
#ifndef USE_GPG
Edouard@168
    90
#define USE_GPG
Edouard@168
    91
#endif
Edouard@168
    92
#endif
Edouard@168
    93
Edouard@168
    94
#ifdef USE_GPG
vb@24
    95
#include "pgp_gpg_internal.h"
vb@229
    96
#elif defined(USE_NETPGP)
Edouard@168
    97
#include "pgp_netpgp_internal.h"
vb@24
    98
#endif
vb@24
    99
vb@292
   100
#include "keymanagement.h"
vb@28
   101
#include "cryptotech.h"
vb@28
   102
#include "transport.h"
vb@604
   103
#include "sync.h"
vb@28
   104
vb@125
   105
#define NOT_IMPLEMENTED assert(0); return PEP_UNKNOWN_ERROR;
vb@24
   106
edouard@1603
   107
struct _pEpSession;
edouard@1603
   108
typedef struct _pEpSession pEpSession;
edouard@1603
   109
struct _pEpSession {
vb@24
   110
    const char *version;
Edouard@168
   111
#ifdef USE_GPG
vb@24
   112
    gpgme_ctx_t ctx;
vb@229
   113
#elif defined(USE_NETPGP)
Edouard@252
   114
    pEpNetPGPSession ctx;
vb@24
   115
#endif
vb@24
   116
vb@62
   117
    PEP_cryptotech_t *cryptotech;
vb@62
   118
    PEP_transport_t *transports;
vb@28
   119
vb@24
   120
    sqlite3 *db;
vb@24
   121
    sqlite3 *system_db;
vb@24
   122
vb@24
   123
    sqlite3_stmt *log;
vb@233
   124
    sqlite3_stmt *trustword;
vb@24
   125
    sqlite3_stmt *get_identity;
krista@1799
   126
    sqlite3_stmt *replace_identities_fpr;
vb@24
   127
    sqlite3_stmt *set_person;
edouard@1234
   128
    sqlite3_stmt *set_device_group;
edouard@1235
   129
    sqlite3_stmt *get_device_group;
vb@24
   130
    sqlite3_stmt *set_pgp_keypair;
vb@24
   131
    sqlite3_stmt *set_identity;
vb@932
   132
    sqlite3_stmt *set_identity_flags;
edouard@1394
   133
    sqlite3_stmt *unset_identity_flags;
vb@24
   134
    sqlite3_stmt *set_trust;
krista@1799
   135
    sqlite3_stmt *update_trust_for_fpr;
vb@24
   136
    sqlite3_stmt *get_trust;
vb@251
   137
    sqlite3_stmt *least_trust;
vb@357
   138
    sqlite3_stmt *mark_compromized;
Edouard@409
   139
    sqlite3_stmt *reset_trust;
vb@450
   140
    sqlite3_stmt *crashdump;
vb@458
   141
    sqlite3_stmt *languagelist;
vb@458
   142
    sqlite3_stmt *i18n_token;
fdik@494
   143
fdik@494
   144
    // blacklist
fdik@494
   145
    sqlite3_stmt *blacklist_add;
fdik@494
   146
    sqlite3_stmt *blacklist_delete;
fdik@494
   147
    sqlite3_stmt *blacklist_is_listed;
fdik@494
   148
    sqlite3_stmt *blacklist_retrieve;
Edouard@584
   149
    
Edouard@584
   150
    // Own keys
Edouard@584
   151
    sqlite3_stmt *own_key_is_listed;
vb@955
   152
    sqlite3_stmt *own_identities_retrieve;
edouard@1394
   153
    sqlite3_stmt *own_keys_retrieve;
edouard@1394
   154
    sqlite3_stmt *set_own_key;
vb@292
   155
vb@632
   156
    // sequence value
vb@633
   157
    sqlite3_stmt *sequence_value1;
vb@633
   158
    sqlite3_stmt *sequence_value2;
vb@1085
   159
    sqlite3_stmt *sequence_value3;
vb@632
   160
edouard@1236
   161
    // revoked keys
Edouard@693
   162
    sqlite3_stmt *set_revoked;
Edouard@693
   163
    sqlite3_stmt *get_revoked;
Edouard@693
   164
Edouard@693
   165
    // callbacks
vb@292
   166
    examine_identity_t examine_identity;
vb@292
   167
    void *examine_management;
edouard@1462
   168
    void *sync_management;
vb@599
   169
    void *sync_obj;
vb@604
   170
    messageToSend_t messageToSend;
edouard@1459
   171
    notifyHandshake_t notifyHandshake;
vb@1043
   172
    inject_sync_msg_t inject_sync_msg;
vb@1043
   173
    retrieve_next_sync_msg_t retrieve_next_sync_msg;
vb@464
   174
edouard@1236
   175
    // key sync
edouard@1603
   176
    pEpSession* sync_session;
vb@690
   177
    DeviceState_state sync_state;
edouard@1460
   178
    void* sync_state_payload;
edouard@1236
   179
    char sync_uuid[37];
edouard@1316
   180
    time_t LastCannotDecrypt;
edouard@1316
   181
    time_t LastUpdateRequest;
vb@690
   182
vb@464
   183
    // runtime config
vb@464
   184
vb@464
   185
    bool passive_mode;
vb@464
   186
    bool unencrypted_subject;
vb@1110
   187
    bool keep_sync_msg;
vb@1819
   188
    bool service_log;
Edouard@720
   189
    
roker@1722
   190
#ifdef DEBUG_ERRORSTACK
roker@1722
   191
    stringlist_t* errorstack;
roker@1722
   192
#endif
edouard@1603
   193
};
vb@48
   194
roker@1722
   195
vb@62
   196
PEP_STATUS init_transport_system(PEP_SESSION session, bool in_first);
vb@62
   197
void release_transport_system(PEP_SESSION session, bool out_last);
vb@48
   198
krista@1639
   199
/* NOT to be exposed to the outside!!! */
krista@1639
   200
PEP_STATUS encrypt_only(
krista@1639
   201
        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
krista@1639
   202
        size_t psize, char **ctext, size_t *csize
krista@1639
   203
);
krista@1639
   204
krista@2047
   205
#if defined(NDEBUG) || defined(NOLOG)
vb@216
   206
#define DEBUG_LOG(TITLE, ENTITY, DESC)
vb@216
   207
#else
huss@1571
   208
#ifdef ANDROID
huss@1571
   209
#include <android/log.h>
vb@1819
   210
#define  LOG_MORE(...)  __android_log_print(ANDROID_LOG_DEBUG, "pEpEngine", " %s :: %s :: %s :: %s ", __VA_ARGS__);
edouard@1630
   211
#else
edouard@1630
   212
#include <stdio.h>
vb@1819
   213
#define  LOG_MORE(...)  fprintf(stderr, "pEpEngine DEBUG_LOG('%s','%s','%s','%s')\n", __VA_ARGS__);
huss@1571
   214
#endif
edouard@1630
   215
#define DEBUG_LOG(TITLE, ENTITY, DESC) {\
vb@1819
   216
    log_event(session, (TITLE), (ENTITY), (DESC), "debug " __FILE__ ":" S_LINE);\
vb@1819
   217
    LOG_MORE((TITLE), (ENTITY), (DESC), __FILE__ ":" S_LINE)\
edouard@1630
   218
}
vb@216
   219
#endif
vb@216
   220
edouard@1746
   221
typedef enum _normalize_hex_rest_t {
edouard@1746
   222
    accept_hex,
edouard@1746
   223
    ignore_hex,
edouard@1746
   224
    reject_hex
edouard@1746
   225
} normalize_hex_res_t;
edouard@1746
   226
edouard@1746
   227
static inline normalize_hex_res_t _normalize_hex(char *hex) 
edouard@1746
   228
{
edouard@1746
   229
    if (*hex >= '0' && *hex <= '9')
edouard@1746
   230
        return accept_hex;
edouard@1746
   231
edouard@1746
   232
    if (*hex >= 'A' && *hex <= 'F') {
edouard@1746
   233
        *hex += 'a' - 'A';
edouard@1746
   234
        return accept_hex;
edouard@1746
   235
    }
edouard@1746
   236
edouard@1746
   237
    if (*hex >= 'a' && *hex <= 'f') 
edouard@1746
   238
        return accept_hex;
edouard@1746
   239
edouard@1746
   240
    if (*hex == ' ') 
edouard@1746
   241
        return ignore_hex;
edouard@1746
   242
edouard@1746
   243
    return reject_hex;
edouard@1746
   244
}
edouard@1746
   245
edouard@1521
   246
// Space tolerant and case insensitive fingerprint string compare
edouard@1746
   247
static inline PEP_STATUS _compare_fprs(
edouard@1746
   248
        const char* fpra,
edouard@1746
   249
        size_t fpras,
edouard@1746
   250
        const char* fprb,
edouard@1746
   251
        size_t fprbs,
edouard@1746
   252
        int* comparison)
edouard@1746
   253
{
edouard@1746
   254
edouard@1746
   255
    size_t ai = 0;
edouard@1746
   256
    size_t bi = 0;
edouard@1746
   257
    size_t significant = 0;
edouard@1746
   258
    int _comparison = 0;
edouard@1746
   259
    const int _FULL_FINGERPRINT_LENGTH = 40;
edouard@1746
   260
   
edouard@1746
   261
    // First compare every non-ignored chars until an end is reached
edouard@1746
   262
    while(ai < fpras && bi < fprbs)
edouard@1746
   263
    {
edouard@1746
   264
        char fprac = fpra[ai];
edouard@1746
   265
        char fprbc = fprb[bi];
edouard@1746
   266
        normalize_hex_res_t fprah = _normalize_hex(&fprac);
edouard@1746
   267
        normalize_hex_res_t fprbh = _normalize_hex(&fprbc);
edouard@1746
   268
edouard@1746
   269
        if(fprah == reject_hex || fprbh == reject_hex)
edouard@1746
   270
            return PEP_ILLEGAL_VALUE;
edouard@1746
   271
edouard@1746
   272
        if ( fprah == ignore_hex )
edouard@1746
   273
        {
edouard@1746
   274
            ai++;
edouard@1746
   275
        }
edouard@1746
   276
        else if ( fprbh == ignore_hex )
edouard@1746
   277
        {
edouard@1746
   278
            bi++;
edouard@1746
   279
        }
edouard@1746
   280
        else
edouard@1746
   281
        {
edouard@1746
   282
            if(fprac != fprbc && _comparison == 0 )
edouard@1746
   283
            {
edouard@1746
   284
                _comparison = fprac > fprbc ? 1 : -1;
edouard@1746
   285
            }
edouard@1746
   286
edouard@1746
   287
            significant++;
edouard@1746
   288
            ai++;
edouard@1746
   289
            bi++;
edouard@1746
   290
edouard@1746
   291
        } 
edouard@1746
   292
    }
edouard@1746
   293
edouard@1746
   294
    // Bail out if we didn't got enough significnt chars
edouard@1746
   295
    if (significant != _FULL_FINGERPRINT_LENGTH )
edouard@1746
   296
        return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
edouard@1746
   297
edouard@1746
   298
    // Then purge remaining chars, all must be ignored chars
edouard@1746
   299
    while ( ai < fpras )
edouard@1746
   300
    {
edouard@1746
   301
        char fprac = fpra[ai];
edouard@1746
   302
        normalize_hex_res_t fprah = _normalize_hex(&fprac);
edouard@1746
   303
        if( fprah == reject_hex )
edouard@1746
   304
            return PEP_ILLEGAL_VALUE;
edouard@1746
   305
        if ( fprah != ignore_hex )
edouard@1746
   306
            return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
edouard@1746
   307
        ai++;
edouard@1746
   308
    }
edouard@1746
   309
    while ( bi < fprbs )
edouard@1746
   310
    {
edouard@1746
   311
        char fprbc = fprb[bi];
edouard@1746
   312
        normalize_hex_res_t fprbh = _normalize_hex(&fprbc);
edouard@1746
   313
        if( fprbh == reject_hex )
edouard@1746
   314
            return PEP_ILLEGAL_VALUE;
edouard@1746
   315
        if ( fprbh != ignore_hex )
edouard@1746
   316
            return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
edouard@1746
   317
        bi++;
edouard@1746
   318
    }
edouard@1746
   319
edouard@1746
   320
    *comparison = _comparison;
edouard@1746
   321
    return PEP_STATUS_OK;
edouard@1746
   322
}
edouard@1746
   323
edouard@1521
   324
static inline int _same_fpr(
edouard@1521
   325
        const char* fpra,
edouard@1521
   326
        size_t fpras,
edouard@1521
   327
        const char* fprb,
edouard@1521
   328
        size_t fprbs
edouard@1521
   329
    )
edouard@1521
   330
{
edouard@1746
   331
    // illegal values are ignored, and considered not same.
edouard@1746
   332
    int comparison = 1;
edouard@1746
   333
edouard@1746
   334
    _compare_fprs(fpra, fpras, fprb, fprbs, &comparison);
edouard@1746
   335
edouard@1746
   336
    return comparison == 0;
edouard@1521
   337
}
roker@1722
   338
edouard@1945
   339
static inline bool _identity_me(
edouard@1945
   340
        pEp_identity * identity
edouard@1945
   341
    )
edouard@1945
   342
{
edouard@1945
   343
    return identity->user_id && strcmp(identity->user_id, PEP_OWN_USERID) == 0;
edouard@1945
   344
}
roker@1722
   345
krista@2045
   346
// size is the length of the bytestr that's coming in. This is really only intended
krista@2045
   347
// for comparing two full strings. If charstr's length is different from bytestr_size,
krista@2045
   348
// we'll return a non-zero value.
krista@2045
   349
static inline int _unsigned_signed_strcmp(const unsigned char* bytestr, const char* charstr, int bytestr_size) {
krista@2045
   350
    int charstr_len = strlen(charstr);
krista@2045
   351
    if (charstr_len != bytestr_size)
krista@2045
   352
        return -1; // we don't actually care except that it's non-zero
krista@2045
   353
    return memcmp(bytestr, charstr, bytestr_size);
krista@2045
   354
}
krista@2045
   355
krista@2045
   356
// This is just a horrible example of C type madness. UTF-8 made me do it.
krista@2045
   357
static inline char* _pep_subj_copy() {
krista@2045
   358
    unsigned char pepstr[] = PEP_SUBJ_STRING;
krista@2045
   359
    void* retval = calloc(1, sizeof(unsigned char)*PEP_SUBJ_BYTELEN + 1);
krista@2045
   360
    memcpy(retval, pepstr, PEP_SUBJ_BYTELEN);
krista@2045
   361
    return (char*)retval;
krista@2045
   362
}
krista@2045
   363
roker@1722
   364
#ifdef DEBUG_ERRORSTACK
roker@1722
   365
    PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status);
roker@1853
   366
    #define ADD_TO_LOG(status)   session_add_error(session, __FILE__, __LINE__, (status))
roker@1853
   367
    #define GOTO(label)          do{ (void)session_add_error(session, __FILE__, __LINE__, status); goto label; }while(0)
roker@1722
   368
#else
roker@1853
   369
    #define ADD_TO_LOG(status)   (status)
roker@1853
   370
    #define GOTO(label)          goto label
roker@1722
   371
#endif