src/keymanagement.c
author Krista Bennett <krista@pep-project.org>
Mon, 05 Mar 2018 18:02:34 +0100
changeset 2552 09d77d1177ce
parent 2549 5fc5d6be0b36
child 2574 f2e0646c4b0d
permissions -rw-r--r--
Fixed call to _myself in trust_personal_key (should now be set_own_key), and also made sure that when an own identity comes in but the key is public only, that it gets verified but never set as the default when being trusted.
vb@1517
     1
// This file is under GNU General Public License 3.0
vb@1517
     2
// see LICENSE.txt
vb@1517
     3
vb@130
     4
#include "platform.h"
vb@0
     5
vb@0
     6
#include <string.h>
vb@0
     7
#include <stdio.h>
vb@0
     8
#include <stdlib.h>
vb@0
     9
#include <assert.h>
Edouard@512
    10
#include <ctype.h>
vb@0
    11
vb@217
    12
#include "pEp_internal.h"
vb@0
    13
#include "keymanagement.h"
vb@0
    14
krista@2461
    15
#include "sync_fsm.h"
krista@1253
    16
#include "blacklist.h"
edouard@1195
    17
krista@2461
    18
#define KEY_EXPIRE_DELTA (60 * 60 * 24 * 365)
vb@8
    19
krista@2461
    20
static bool key_matches_address(PEP_SESSION session, const char* address,
krista@2461
    21
                                const char* fpr) {
krista@2461
    22
    if (!session || !address || !fpr)
krista@2461
    23
        return false;
krista@2461
    24
    
krista@2461
    25
    bool retval = false;
krista@2461
    26
    stringlist_t *keylist = NULL;
krista@2461
    27
    PEP_STATUS status = find_keys(session, address, &keylist);
krista@2461
    28
    if (status == PEP_STATUS_OK && keylist) {
krista@2461
    29
        stringlist_t* curr = keylist;
krista@2461
    30
        while (curr) {
krista@2461
    31
            if (curr->value) {
krista@2461
    32
                if (strcasecmp(curr->value, fpr)) {
krista@2461
    33
                    retval = true;
krista@2461
    34
                    break;
krista@2461
    35
                }
krista@2461
    36
            }
krista@2461
    37
            curr = curr->next;
krista@2461
    38
        }
krista@2461
    39
    }
krista@2461
    40
    
krista@2461
    41
    free_stringlist(keylist);
krista@2461
    42
    return retval;                             
krista@2461
    43
}
vb@214
    44
Edouard@774
    45
PEP_STATUS elect_pubkey(
krista@2548
    46
        PEP_SESSION session, pEp_identity * identity, bool check_blacklist
Edouard@755
    47
    )
Edouard@755
    48
{
Edouard@755
    49
    PEP_STATUS status;
roker@1559
    50
    stringlist_t *keylist = NULL;
krista@1342
    51
    char *_fpr = "";
Edouard@755
    52
    identity->comm_type = PEP_ct_unknown;
Edouard@755
    53
Edouard@755
    54
    status = find_keys(session, identity->address, &keylist);
Edouard@755
    55
    assert(status != PEP_OUT_OF_MEMORY);
Edouard@755
    56
    if (status == PEP_OUT_OF_MEMORY)
Edouard@755
    57
        return PEP_OUT_OF_MEMORY;
krista@2461
    58
    
krista@2461
    59
    if (!keylist || !keylist->value)
krista@2461
    60
        identity->comm_type = PEP_ct_key_not_found;    
krista@2461
    61
    else {
krista@2461
    62
        stringlist_t *_keylist;
krista@2461
    63
        for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
krista@2461
    64
            PEP_comm_type _comm_type_key;
Edouard@755
    65
krista@2461
    66
            status = get_key_rating(session, _keylist->value, &_comm_type_key);
krista@2461
    67
            assert(status != PEP_OUT_OF_MEMORY);
krista@2461
    68
            if (status == PEP_OUT_OF_MEMORY) {
krista@2461
    69
                free_stringlist(keylist);
krista@2461
    70
                return PEP_OUT_OF_MEMORY;
krista@2461
    71
            }
Edouard@755
    72
krista@2461
    73
            if (_comm_type_key != PEP_ct_compromized &&
krista@2461
    74
                _comm_type_key != PEP_ct_unknown)
Edouard@755
    75
            {
krista@2461
    76
                if (identity->comm_type == PEP_ct_unknown ||
krista@2461
    77
                    _comm_type_key > identity->comm_type)
krista@2461
    78
                {
krista@2548
    79
                    bool blacklisted = false;
krista@2548
    80
                    bool mistrusted = false;
krista@2471
    81
                    status = is_mistrusted_key(session, _keylist->value, &mistrusted);
krista@2548
    82
                    if (status == PEP_STATUS_OK && check_blacklist)
krista@2471
    83
                        status = blacklist_is_listed(session, _keylist->value, &blacklisted);
krista@2471
    84
                    if (status == PEP_STATUS_OK && !mistrusted && !blacklisted) {
krista@2461
    85
                        identity->comm_type = _comm_type_key;
krista@2461
    86
                        _fpr = _keylist->value;
krista@2461
    87
                    }
krista@1275
    88
                }
Edouard@755
    89
            }
Edouard@755
    90
        }
Edouard@755
    91
    }
krista@1342
    92
    free(identity->fpr);
Edouard@755
    93
krista@2471
    94
    if (!_fpr || _fpr[0] == '\0')
krista@2471
    95
        identity->fpr = NULL;
krista@2471
    96
    else {    
krista@2471
    97
        identity->fpr = strdup(_fpr);
krista@2471
    98
        if (identity->fpr == NULL) {
krista@2471
    99
            free_stringlist(keylist);
krista@2471
   100
            return PEP_OUT_OF_MEMORY;
krista@2471
   101
        }
Edouard@755
   102
    }
krista@2461
   103
    
Edouard@755
   104
    free_stringlist(keylist);
Edouard@755
   105
    return PEP_STATUS_OK;
Edouard@755
   106
}
Edouard@755
   107
krista@2461
   108
static PEP_STATUS validate_fpr(PEP_SESSION session, 
krista@2548
   109
                               pEp_identity* ident,
krista@2548
   110
                               bool check_blacklist) {
krista@2461
   111
    
krista@2461
   112
    PEP_STATUS status = PEP_STATUS_OK;
krista@2461
   113
    
krista@2461
   114
    if (!session || !ident || !ident->fpr || !ident->fpr[0])
krista@2461
   115
        return PEP_ILLEGAL_VALUE;    
krista@2461
   116
        
krista@2461
   117
    char* fpr = ident->fpr;
krista@2461
   118
    
krista@2461
   119
    bool has_private = false;
krista@2461
   120
    
krista@2461
   121
    if (ident->me) {
krista@2461
   122
        status = contains_priv_key(session, fpr, &has_private);
krista@2461
   123
        if (status != PEP_STATUS_OK || !has_private)
krista@2461
   124
            return PEP_KEY_UNSUITABLE;
krista@2461
   125
    }
krista@2461
   126
    
krista@2461
   127
    status = get_trust(session, ident);
krista@2461
   128
    if (status != PEP_STATUS_OK)
krista@2461
   129
        ident->comm_type = PEP_ct_unknown;
krista@2461
   130
            
krista@2461
   131
    PEP_comm_type ct = ident->comm_type;
krista@2461
   132
krista@2461
   133
    if (ct == PEP_ct_unknown) {
krista@2461
   134
        // If status is bad, it's ok, we get the rating
krista@2461
   135
        // we should use then (PEP_ct_unknown)
krista@2461
   136
        get_key_rating(session, fpr, &ct);
krista@2461
   137
        ident->comm_type = ct;
krista@2461
   138
    }
krista@2461
   139
    
krista@2543
   140
    bool pep_user = false;
krista@2543
   141
    
krista@2543
   142
    is_pep_user(session, ident, &pep_user);
krista@2543
   143
krista@2543
   144
    if (pep_user) {
krista@2543
   145
        switch (ct) {
krista@2543
   146
            case PEP_ct_OpenPGP:
krista@2543
   147
            case PEP_ct_OpenPGP_unconfirmed:
krista@2543
   148
                ct += 0x47; // difference between PEP and OpenPGP values;
krista@2543
   149
                ident->comm_type = ct;
krista@2543
   150
                break;
krista@2543
   151
            default:
krista@2543
   152
                break;
krista@2543
   153
        }
krista@2543
   154
    }
krista@2543
   155
    
krista@2461
   156
    bool revoked, expired;
krista@2461
   157
    bool blacklisted = false;
krista@2461
   158
    
krista@2461
   159
    status = key_revoked(session, fpr, &revoked);    
krista@2461
   160
        
krista@2461
   161
    if (status != PEP_STATUS_OK) {
krista@2501
   162
        return status;
krista@2461
   163
    }
krista@2461
   164
    
krista@2461
   165
    if (!revoked) {
krista@2461
   166
        time_t exp_time = (ident->me ? 
krista@2461
   167
                           time(NULL) + (7*24*3600) : time(NULL));
krista@2461
   168
                           
krista@2461
   169
        status = key_expired(session, fpr, 
krista@2461
   170
                             exp_time,
krista@2461
   171
                             &expired);
krista@2461
   172
                             
krista@2461
   173
        assert(status == PEP_STATUS_OK);
krista@2461
   174
        if (status != PEP_STATUS_OK)
krista@2501
   175
            return status;
krista@2461
   176
krista@2549
   177
        if (check_blacklist && IS_PGP_CT(ct) &&
krista@2461
   178
            !ident->me) {
krista@2461
   179
            status = blacklist_is_listed(session, 
krista@2461
   180
                                         fpr, 
krista@2461
   181
                                         &blacklisted);
krista@2461
   182
                                         
krista@2461
   183
            if (status != PEP_STATUS_OK)
krista@2501
   184
                return status;
krista@2461
   185
        }
krista@2461
   186
    }
krista@2461
   187
            
krista@2461
   188
    if (ident->me && (ct >= PEP_ct_strong_but_unconfirmed) && !revoked && expired) {
krista@2461
   189
        // extend key
krista@2461
   190
        timestamp *ts = new_timestamp(time(NULL) + KEY_EXPIRE_DELTA);
krista@2461
   191
        status = renew_key(session, fpr, ts);
krista@2461
   192
        free_timestamp(ts);
krista@2461
   193
krista@2461
   194
        if (status == PEP_STATUS_OK) {
krista@2461
   195
            // if key is valid (second check because pEp key might be extended above)
krista@2461
   196
            //      Return fpr        
krista@2461
   197
            status = key_expired(session, fpr, time(NULL), &expired);            
krista@2461
   198
            if (status != PEP_STATUS_OK) {
krista@2461
   199
                 ident->comm_type = PEP_ct_key_expired;
krista@2501
   200
                 return status;
krista@2461
   201
             }
krista@2461
   202
            // communicate key(?)
krista@2461
   203
        }        
krista@2461
   204
    }
krista@2461
   205
     
krista@2461
   206
    if (revoked) 
krista@2461
   207
        ct = PEP_ct_key_revoked;
krista@2461
   208
    else if (expired)
krista@2461
   209
        ct = PEP_ct_key_expired;        
krista@2461
   210
    else if (blacklisted) { // never true for .me
krista@2461
   211
        ident->comm_type = ct = PEP_ct_key_not_found;
krista@2461
   212
        free(ident->fpr);
krista@2461
   213
            ident->fpr = strdup("");
krista@2461
   214
        status = PEP_KEY_BLACKLISTED;
krista@2461
   215
    }
krista@2461
   216
    
krista@2461
   217
    switch (ct) {
krista@2461
   218
        case PEP_ct_key_expired:
krista@2461
   219
        case PEP_ct_key_revoked:
krista@2461
   220
        case PEP_ct_key_b0rken:
krista@2461
   221
            // delete key from being default key for all users/identities
krista@2461
   222
            status = remove_fpr_as_default(session, fpr);
krista@2461
   223
            status = update_trust_for_fpr(session, 
krista@2461
   224
                                          fpr, 
krista@2461
   225
                                          ct);
krista@2467
   226
        case PEP_ct_mistrusted:                                  
krista@2461
   227
            free(ident->fpr);
krista@2461
   228
            ident->fpr = NULL;
krista@2461
   229
            ident->comm_type = ct;            
krista@2461
   230
            status = PEP_KEY_UNSUITABLE;
krista@2461
   231
        default:
krista@2461
   232
            break;
krista@2461
   233
    }            
krista@2461
   234
krista@2461
   235
    return status;
krista@2461
   236
}
krista@2461
   237
krista@2461
   238
PEP_STATUS get_user_default_key(PEP_SESSION session, const char* user_id,
krista@2461
   239
                                char** default_key) {
krista@2461
   240
    assert(session);
krista@2461
   241
    assert(user_id);
krista@2461
   242
    
krista@2461
   243
    if (!session || !user_id)
krista@2461
   244
        return PEP_ILLEGAL_VALUE;
krista@2461
   245
krista@2461
   246
    PEP_STATUS status = PEP_STATUS_OK;
krista@2461
   247
            
krista@2461
   248
    // try to get default key for user_data
krista@2461
   249
    sqlite3_reset(session->get_user_default_key);
krista@2461
   250
    sqlite3_bind_text(session->get_user_default_key, 1, user_id, 
krista@2461
   251
                      -1, SQLITE_STATIC);
krista@2461
   252
    
krista@2461
   253
    const int result = sqlite3_step(session->get_user_default_key);
krista@2461
   254
    char* user_fpr = NULL;
krista@2461
   255
    if (result == SQLITE_ROW) {
krista@2461
   256
        const char* u_fpr =
krista@2461
   257
            (char *) sqlite3_column_text(session->get_user_default_key, 0);
krista@2461
   258
        if (u_fpr)
krista@2461
   259
            user_fpr = strdup(u_fpr);
krista@2461
   260
    }
krista@2461
   261
    else
krista@2461
   262
        status = PEP_GET_KEY_FAILED;
krista@2461
   263
        
krista@2461
   264
    sqlite3_reset(session->get_user_default_key);
krista@2461
   265
    
krista@2461
   266
    *default_key = user_fpr;
krista@2461
   267
    return status;     
krista@2461
   268
}
krista@2461
   269
krista@2461
   270
// Only call on retrieval of previously stored identity!
krista@2461
   271
// Also, we presume that if the stored_identity was sent in
krista@2461
   272
// without an fpr, there wasn't one in the trust DB for this
krista@2461
   273
// identity.
krista@2461
   274
PEP_STATUS get_valid_pubkey(PEP_SESSION session,
krista@2461
   275
                         pEp_identity* stored_identity,
krista@2461
   276
                         bool* is_identity_default,
krista@2461
   277
                         bool* is_user_default,
krista@2548
   278
                         bool* is_address_default,
krista@2548
   279
                         bool check_blacklist) {
krista@2461
   280
    
krista@2461
   281
    PEP_STATUS status = PEP_STATUS_OK;
krista@2461
   282
krista@2461
   283
    if (!stored_identity || EMPTYSTR(stored_identity->user_id)
krista@2461
   284
        || !is_identity_default || !is_user_default || !is_address_default)
krista@2461
   285
        return PEP_ILLEGAL_VALUE;
krista@2461
   286
        
krista@2461
   287
    *is_identity_default = *is_user_default = *is_address_default = false;
krista@2461
   288
krista@2461
   289
    PEP_comm_type first_reject_comm_type = PEP_ct_key_not_found;
krista@2461
   290
    PEP_STATUS first_reject_status = PEP_KEY_NOT_FOUND;
krista@2461
   291
    
krista@2461
   292
    char* stored_fpr = stored_identity->fpr;
krista@2461
   293
    // Input: stored identity retrieved from database
krista@2461
   294
    // if stored identity contains a default key
krista@2461
   295
    if (!EMPTYSTR(stored_fpr)) {
krista@2548
   296
        status = validate_fpr(session, stored_identity, check_blacklist);    
krista@2461
   297
        if (status == PEP_STATUS_OK && !EMPTYSTR(stored_identity->fpr)) {
krista@2461
   298
            *is_identity_default = *is_address_default = true;
krista@2461
   299
            return status;
krista@2461
   300
        }
krista@2461
   301
        else if (status != PEP_KEY_NOT_FOUND) {
krista@2461
   302
            first_reject_status = status;
krista@2461
   303
            first_reject_comm_type = stored_identity->comm_type;
krista@2461
   304
        }
krista@2461
   305
    }
krista@2461
   306
    // if no valid default stored identity key found
krista@2461
   307
    free(stored_identity->fpr);
krista@2461
   308
    stored_identity->fpr = NULL;
krista@2461
   309
    
krista@2461
   310
    char* user_fpr = NULL;
krista@2461
   311
    status = get_user_default_key(session, stored_identity->user_id, &user_fpr);
krista@2461
   312
    
krista@2461
   313
    if (!EMPTYSTR(user_fpr)) {             
krista@2461
   314
        // There exists a default key for user, so validate
krista@2461
   315
        stored_identity->fpr = user_fpr;
krista@2548
   316
        status = validate_fpr(session, stored_identity, check_blacklist);
krista@2461
   317
        if (status == PEP_STATUS_OK && stored_identity->fpr) {
krista@2461
   318
            *is_user_default = true;
krista@2461
   319
            *is_address_default = key_matches_address(session, 
krista@2461
   320
                                                      stored_identity->address,
krista@2461
   321
                                                      stored_identity->fpr);
krista@2461
   322
            return status;
krista@2461
   323
        }        
krista@2461
   324
        else if (status != PEP_KEY_NOT_FOUND && first_reject_status != PEP_KEY_NOT_FOUND) {
krista@2461
   325
            first_reject_status = status;
krista@2461
   326
            first_reject_comm_type = stored_identity->comm_type;
krista@2461
   327
        }
krista@2461
   328
    }
krista@2461
   329
    
krista@2548
   330
    status = elect_pubkey(session, stored_identity, check_blacklist);
krista@2461
   331
    if (status == PEP_STATUS_OK) {
krista@2461
   332
        if (!EMPTYSTR(stored_identity->fpr))
krista@2548
   333
            validate_fpr(session, stored_identity, false); // blacklist already filtered of needed
krista@2461
   334
    }    
krista@2461
   335
    else if (status != PEP_KEY_NOT_FOUND && first_reject_status != PEP_KEY_NOT_FOUND) {
krista@2461
   336
        first_reject_status = status;
krista@2461
   337
        first_reject_comm_type = stored_identity->comm_type;
krista@2461
   338
    }
krista@2461
   339
    
krista@2461
   340
    switch (stored_identity->comm_type) {
krista@2461
   341
        case PEP_ct_key_revoked:
krista@2461
   342
        case PEP_ct_key_b0rken:
krista@2461
   343
        case PEP_ct_key_expired:
krista@2461
   344
        case PEP_ct_compromized:
krista@2461
   345
        case PEP_ct_mistrusted:
krista@2461
   346
            // this only happens when it's all there is
krista@2461
   347
            status = first_reject_status;
krista@2461
   348
            free(stored_identity->fpr);
krista@2461
   349
            stored_identity->fpr = NULL;
krista@2461
   350
            stored_identity->comm_type = first_reject_comm_type;
krista@2461
   351
            break;    
krista@2461
   352
        default:
krista@2548
   353
            if (check_blacklist && status == PEP_KEY_BLACKLISTED) {
krista@2548
   354
                free(stored_identity->fpr);
krista@2548
   355
                stored_identity->fpr = NULL;
krista@2548
   356
                stored_identity->comm_type = PEP_ct_key_not_found;
krista@2548
   357
            }
krista@2461
   358
            break;
krista@2461
   359
    }
krista@2461
   360
    return status;
krista@2461
   361
}
krista@2461
   362
krista@2461
   363
static void transfer_ident_lang_and_flags(pEp_identity* new_ident,
krista@2461
   364
                                          pEp_identity* stored_ident) {
krista@2461
   365
    if (new_ident->lang[0] == 0) {
krista@2461
   366
      new_ident->lang[0] = stored_ident->lang[0];
krista@2461
   367
      new_ident->lang[1] = stored_ident->lang[1];
krista@2461
   368
      new_ident->lang[2] = 0;
krista@2461
   369
    }
krista@2461
   370
krista@2461
   371
    new_ident->flags = stored_ident->flags;
krista@2461
   372
    new_ident->me = new_ident->me || stored_ident->me;
krista@2461
   373
}
krista@2461
   374
krista@2519
   375
static void adjust_pep_trust_status(PEP_SESSION session, pEp_identity* identity) {
krista@2519
   376
    assert(session);
krista@2519
   377
    assert(identity);
krista@2519
   378
    
krista@2519
   379
    if (identity->comm_type < PEP_ct_strong_but_unconfirmed ||
krista@2519
   380
        (identity->comm_type | PEP_ct_confirmed) == PEP_ct_pEp)
krista@2519
   381
        return;
krista@2519
   382
    
krista@2519
   383
    bool pep_user;
krista@2519
   384
    
krista@2519
   385
    is_pep_user(session, identity, &pep_user);
krista@2519
   386
    
krista@2519
   387
    if (pep_user) {
krista@2519
   388
        PEP_comm_type confirmation_status = identity->comm_type & PEP_ct_confirmed;
krista@2519
   389
        identity->comm_type = PEP_ct_pEp_unconfirmed | confirmation_status;    
krista@2519
   390
    }
krista@2519
   391
}
krista@2519
   392
krista@2519
   393
krista@2461
   394
static PEP_STATUS prepare_updated_identity(PEP_SESSION session,
krista@2461
   395
                                                 pEp_identity* return_id,
krista@2461
   396
                                                 pEp_identity* stored_ident,
krista@2461
   397
                                                 bool store) {
krista@2461
   398
    
krista@2461
   399
    if (!session || !return_id || !stored_ident)
krista@2461
   400
        return PEP_ILLEGAL_VALUE;
krista@2461
   401
    
krista@2461
   402
    PEP_STATUS status;
krista@2461
   403
    
krista@2461
   404
    bool is_identity_default, is_user_default, is_address_default;
krista@2461
   405
    status = get_valid_pubkey(session, stored_ident,
krista@2461
   406
                                &is_identity_default,
krista@2461
   407
                                &is_user_default,
krista@2548
   408
                                &is_address_default,
krista@2548
   409
                              false);
krista@2461
   410
                                
krista@2461
   411
    if (status == PEP_STATUS_OK && stored_ident->fpr && *(stored_ident->fpr) != '\0') {
krista@2461
   412
    // set identity comm_type from trust db (user_id, FPR)
krista@2461
   413
        status = get_trust(session, stored_ident);
krista@2461
   414
        if (status == PEP_CANNOT_FIND_IDENTITY || stored_ident->comm_type == PEP_ct_unknown) {
krista@2461
   415
            // This is OK - there is no trust DB entry, but we
krista@2461
   416
            // found a key. We won't store this, but we'll
krista@2461
   417
            // use it.
krista@2461
   418
            PEP_comm_type ct = PEP_ct_unknown;
krista@2461
   419
            status = get_key_rating(session, stored_ident->fpr, &ct);
krista@2461
   420
            stored_ident->comm_type = ct;
krista@2461
   421
        }
krista@2461
   422
    }
krista@2471
   423
    else {
krista@2471
   424
        if (stored_ident->comm_type == PEP_ct_unknown)
krista@2471
   425
            stored_ident->comm_type = PEP_ct_key_not_found;
krista@2471
   426
    }
krista@2461
   427
    free(return_id->fpr);
krista@2461
   428
    return_id->fpr = NULL;
krista@2461
   429
    if (status == PEP_STATUS_OK && !EMPTYSTR(stored_ident->fpr))
krista@2461
   430
        return_id->fpr = strdup(stored_ident->fpr);
krista@2461
   431
        
krista@2461
   432
    return_id->comm_type = stored_ident->comm_type;
krista@2520
   433
                    
krista@2461
   434
    // We patch the DB with the input username, but if we didn't have
krista@2461
   435
    // one, we pull it out of storage if available.
krista@2461
   436
    // (also, if the input username is "anonymous" and there exists
krista@2461
   437
    //  a DB username, we replace)
krista@2461
   438
    if (!EMPTYSTR(stored_ident->username)) {
krista@2461
   439
        if (!EMPTYSTR(return_id->username) && 
krista@2493
   440
            (strcasecmp(return_id->username, return_id->address) == 0)) {
krista@2461
   441
            free(return_id->username);
krista@2500
   442
            return_id->username = NULL;
krista@2461
   443
        }
krista@2461
   444
        if (EMPTYSTR(return_id->username)) {
krista@2461
   445
            free(return_id->username);
krista@2461
   446
            return_id->username = strdup(stored_ident->username);
krista@2461
   447
        }
krista@2461
   448
    }
krista@2493
   449
    else {
krista@2493
   450
        if (EMPTYSTR(return_id->username))
krista@2493
   451
            return_id->username = strdup(return_id->address);
krista@2493
   452
    }
krista@2461
   453
    
krista@2461
   454
    return_id->me = stored_ident->me;
krista@2461
   455
    
krista@2461
   456
    // FIXME: Do we ALWAYS do this? We probably should...
krista@2461
   457
    if (EMPTYSTR(return_id->user_id)) {
krista@2461
   458
        free(return_id->user_id);
krista@2461
   459
        return_id->user_id = strdup(stored_ident->user_id);
krista@2520
   460
    } 
krista@2520
   461
    
krista@2520
   462
    adjust_pep_trust_status(session, return_id);
krista@2520
   463
   
krista@2461
   464
    // Call set_identity() to store
krista@2461
   465
    if ((is_identity_default || is_user_default) &&
krista@2461
   466
         is_address_default) {                 
krista@2461
   467
         // if we got an fpr which is default for either user
krista@2461
   468
         // or identity AND is valid for this address, set in DB
krista@2461
   469
         // as default
krista@2461
   470
         status = set_identity(session, return_id);
krista@2461
   471
    }
krista@2461
   472
    else {
krista@2461
   473
        // Store without default fpr/ct, but return the fpr and ct 
krista@2461
   474
        // for current use
krista@2461
   475
        char* save_fpr = return_id->fpr;
krista@2461
   476
        PEP_comm_type save_ct = return_id->comm_type;
krista@2461
   477
        return_id->fpr = NULL;
krista@2461
   478
        return_id->comm_type = PEP_ct_unknown;
krista@2461
   479
        PEP_STATUS save_status = status;
krista@2461
   480
        status = set_identity(session, return_id);
krista@2461
   481
        if (save_status != PEP_STATUS_OK)
krista@2461
   482
            status = save_status;
krista@2461
   483
        return_id->fpr = save_fpr;
krista@2461
   484
        return_id->comm_type = save_ct;
krista@2461
   485
    }
krista@2461
   486
    
krista@2461
   487
    transfer_ident_lang_and_flags(return_id, stored_ident);
krista@2461
   488
    
krista@2477
   489
    if (return_id->comm_type == PEP_ct_unknown)
krista@2477
   490
        return_id->comm_type = PEP_ct_key_not_found;
krista@2477
   491
    
krista@2461
   492
    return status;
krista@2461
   493
}
krista@2461
   494
edouard@1385
   495
DYNAMIC_API PEP_STATUS update_identity(
edouard@1385
   496
        PEP_SESSION session, pEp_identity * identity
vb@0
   497
    )
vb@0
   498
{
vb@0
   499
    PEP_STATUS status;
vb@0
   500
vb@0
   501
    assert(session);
vb@0
   502
    assert(identity);
Edouard@439
   503
    assert(!EMPTYSTR(identity->address));
vb@0
   504
Edouard@439
   505
    if (!(session && identity && !EMPTYSTR(identity->address)))
krista@2501
   506
        return PEP_ILLEGAL_VALUE;
vb@191
   507
krista@2461
   508
    char* default_own_id = NULL;
krista@2461
   509
    status = get_default_own_userid(session, &default_own_id);    
krista@2461
   510
krista@2461
   511
    // Is this me, temporary or not? If so, BAIL.
krista@2461
   512
    if (identity->me || 
krista@2461
   513
       (default_own_id && identity->user_id && (strcmp(default_own_id, identity->user_id) == 0))) 
krista@2461
   514
    {
krista@2461
   515
        return PEP_ILLEGAL_VALUE;
vb@1078
   516
    }
vb@1078
   517
krista@2461
   518
    // We have, at least, an address.
krista@2461
   519
    // Retrieve stored identity information!    
krista@2461
   520
    pEp_identity* stored_ident = NULL;
Edouard@559
   521
krista@2461
   522
    if (!EMPTYSTR(identity->user_id)) {            
krista@2461
   523
        // (we're gonna update the trust/fpr anyway, so we use the no-fpr-from-trust-db variant)
krista@2461
   524
        //      * do get_identity() to retrieve stored identity information
krista@2461
   525
        status = get_identity_without_trust_check(session, identity->address, identity->user_id, &stored_ident);
krista@2461
   526
krista@2461
   527
        // Before we start - if there was no stored identity, we should check to make sure we don't
krista@2461
   528
        // have a stored identity with a temporary user_id that differs from the input user_id. This
krista@2461
   529
        // happens in multithreaded environments sometimes.
krista@2461
   530
        if (!stored_ident) {
krista@2461
   531
            identity_list* id_list = NULL;
krista@2461
   532
            status = get_identities_by_address(session, identity->address, &id_list);
krista@2461
   533
krista@2461
   534
            if (id_list) {
krista@2461
   535
                identity_list* id_curr = id_list;
krista@2461
   536
                while (id_curr) {
krista@2461
   537
                    pEp_identity* this_id = id_curr->ident;
krista@2461
   538
                    if (this_id) {
krista@2461
   539
                        char* this_uid = this_id->user_id;
krista@2461
   540
                        if (this_uid && (strstr(this_uid, "TOFU_") == this_uid)) {
krista@2461
   541
                            // FIXME: should we also be fixing pEp_own_userId in this
krista@2461
   542
                            // function here?
krista@2461
   543
                            
krista@2461
   544
                            // if usernames match, we replace the userid. Or if the temp username
krista@2461
   545
                            // is anonymous.
krista@2493
   546
                            // FIXME: do we need to create an address match function which
krista@2493
   547
                            // matches the whole dot-and-case rigamarole from 
krista@2461
   548
                            if (EMPTYSTR(this_id->username) ||
krista@2493
   549
                                strcasecmp(this_id->username, this_id->address) == 0 ||
krista@2461
   550
                                (identity->username && 
krista@2461
   551
                                 strcasecmp(identity->username, 
krista@2461
   552
                                            this_id->username) == 0)) {
krista@2461
   553
                                
krista@2461
   554
                                // Ok, we have a temp ID. We have to replace this
krista@2461
   555
                                // with the real ID.
krista@2461
   556
                                status = replace_userid(session, 
krista@2461
   557
                                                        this_uid, 
krista@2461
   558
                                                        identity->user_id);
krista@2461
   559
                                if (status != PEP_STATUS_OK) {
krista@2461
   560
                                    free_identity_list(id_list);
krista@2461
   561
                                    return status;
krista@2461
   562
                                }
krista@2461
   563
                                    
krista@2461
   564
                                free(this_uid);
krista@2461
   565
                                this_uid = NULL;
krista@2461
   566
                                
krista@2461
   567
                                // Reflect the change we just made to the DB
krista@2461
   568
                                this_id->user_id = strdup(identity->user_id);
krista@2461
   569
                                stored_ident = this_id;
krista@2461
   570
                                // FIXME: free list.
krista@2461
   571
                                break;                                
krista@2461
   572
                            }                            
krista@2461
   573
                        } 
krista@2461
   574
                    }
krista@2461
   575
                    id_curr = id_curr->next;
krista@2461
   576
                }
krista@2461
   577
            }
krista@2461
   578
        } 
krista@2461
   579
                
krista@2461
   580
        if (status == PEP_STATUS_OK && stored_ident) { 
krista@2461
   581
            //  * if identity available
krista@2461
   582
            //      * patch it with username
krista@2461
   583
            //          (note: this will happen when 
krista@2461
   584
            //           setting automatically below...)
krista@2461
   585
            //      * elect valid key for identity
krista@2461
   586
            //    * if valid key exists
krista@2461
   587
            //        * set return value's fpr
krista@2461
   588
            status = prepare_updated_identity(session,
krista@2461
   589
                                              identity,
krista@2461
   590
                                              stored_ident, true);
vb@1015
   591
        }
krista@2461
   592
        //  * else (identity unavailable)
krista@2461
   593
        else {
krista@2461
   594
            status = PEP_STATUS_OK;
krista@2493
   595
krista@2493
   596
            // FIXME: We may need to roll this back.
krista@2493
   597
            // FIXME: change docs if we don't
krista@2461
   598
            //  if we only have user_id and address and identity not available
krista@2461
   599
            //      * return error status (identity not found)
krista@2493
   600
            if (EMPTYSTR(identity->username)) {
krista@2493
   601
                free(identity->username);
krista@2493
   602
                identity->username = strdup(identity->address);
krista@2493
   603
            }
krista@2461
   604
            
krista@2461
   605
            // Otherwise, if we had user_id, address, and username:
krista@2461
   606
            //    * create identity with user_id, address, username
krista@2461
   607
            //      (this is the input id without the fpr + comm type!)
krista@2493
   608
krista@2493
   609
            if (status == PEP_STATUS_OK) {
krista@2548
   610
                elect_pubkey(session, identity, false);
krista@2493
   611
            }
krista@2493
   612
                        
krista@2461
   613
            //    * We've already checked and retrieved
krista@2461
   614
            //      any applicable temporary identities above. If we're 
krista@2461
   615
            //      here, none of them fit.
krista@2461
   616
            //    * call set_identity() to store
krista@2519
   617
            if (status == PEP_STATUS_OK) {
krista@2493
   618
                // FIXME: Do we set if we had to copy in the address?
krista@2519
   619
                adjust_pep_trust_status(session, identity);
krista@2461
   620
                status = set_identity(session, identity);
krista@2519
   621
            }
krista@2461
   622
            //  * Return: created identity
krista@2461
   623
        }        
krista@2461
   624
    }
krista@2461
   625
    else if (!EMPTYSTR(identity->username)) {
krista@2461
   626
        /*
krista@2461
   627
         * Temporary identity information with username supplied
krista@2461
   628
            * Input: address, username (no others)
krista@2461
   629
         */
krista@2461
   630
         
krista@2461
   631
        //  * See if there is an own identity that uses this address. If so, we'll
krista@2461
   632
        //    prefer that
krista@2461
   633
        stored_ident = NULL;
krista@2461
   634
        
krista@2461
   635
        if (default_own_id) {
krista@2461
   636
            status = get_identity(session, 
krista@2512
   637
                                  identity->address, 
krista@2461
   638
                                  default_own_id, 
krista@2461
   639
                                  &stored_ident);
krista@2461
   640
        }
krista@2461
   641
        // If there isn't an own identity, search for a non-temp stored ident
krista@2461
   642
        // with this address.                      
krista@2461
   643
        if (status == PEP_CANNOT_FIND_IDENTITY || !stored_ident) { 
krista@2461
   644
 
krista@2461
   645
            identity_list* id_list = NULL;
krista@2461
   646
            status = get_identities_by_address(session, identity->address, &id_list);
vb@1015
   647
krista@2461
   648
            if (id_list) {
krista@2461
   649
                identity_list* id_curr = id_list;
krista@2461
   650
                while (id_curr) {
krista@2461
   651
                    pEp_identity* this_id = id_curr->ident;
krista@2461
   652
                    if (this_id) {
krista@2461
   653
                        char* this_uid = this_id->user_id;
krista@2461
   654
                        if (this_uid && (strstr(this_uid, "TOFU_") != this_uid)) {
krista@2461
   655
                            // if usernames match, we replace the userid.
krista@2461
   656
                            if (identity->username && 
krista@2461
   657
                                strcasecmp(identity->username, 
krista@2461
   658
                                           this_id->username) == 0) {
krista@2461
   659
                                
krista@2461
   660
                                // Ok, we have a real ID. Copy it!
krista@2461
   661
                                identity->user_id = strdup(this_uid);
krista@2461
   662
                                
krista@2461
   663
                                if (!identity->user_id)
krista@2461
   664
                                    status = PEP_OUT_OF_MEMORY;
krista@2461
   665
                                stored_ident = this_id;
krista@2461
   666
                                
krista@2461
   667
                                break;                                
krista@2461
   668
                            }                            
krista@2461
   669
                        } 
edouard@1522
   670
                    }
krista@2461
   671
                    id_curr = id_curr->next;
edouard@1501
   672
                }
edouard@1501
   673
            }
krista@1220
   674
        }
krista@2461
   675
        
krista@2461
   676
        if (stored_ident) {
krista@2461
   677
            status = prepare_updated_identity(session,
krista@2461
   678
                                              identity,
krista@2461
   679
                                              stored_ident, true);
krista@2461
   680
        }
edouard@1501
   681
        else {
krista@2461
   682
            identity->user_id = calloc(1, strlen(identity->address) + 6);
krista@2461
   683
            if (!identity->user_id)
krista@2461
   684
                return PEP_OUT_OF_MEMORY;
edouard@1501
   685
krista@2461
   686
            snprintf(identity->user_id, strlen(identity->address) + 6,
krista@2461
   687
                     "TOFU_%s", identity->address);        
krista@2496
   688
krista@2537
   689
            status = get_identity(session, 
krista@2537
   690
                                  identity->address, 
krista@2537
   691
                                  identity->user_id, 
krista@2537
   692
                                  &stored_ident);
krista@2537
   693
krista@2537
   694
            if (status == PEP_STATUS_OK && stored_ident) {
krista@2537
   695
                status = prepare_updated_identity(session,
krista@2537
   696
                                                  identity,
krista@2537
   697
                                                  stored_ident, true);
krista@2537
   698
            }
krista@2537
   699
            else {
krista@2537
   700
                         
krista@2537
   701
                //    * We've already checked and retrieved
krista@2537
   702
                //      any applicable temporary identities above. If we're 
krista@2537
   703
                //      here, none of them fit.
krista@2537
   704
                
krista@2548
   705
                status = elect_pubkey(session, identity, false);
krista@2537
   706
                             
krista@2537
   707
                //    * call set_identity() to store
krista@2537
   708
                if (identity->fpr)
krista@2537
   709
                    status = get_key_rating(session, identity->fpr, &identity->comm_type);
krista@2496
   710
            
krista@2537
   711
                //    * call set_identity() to store
krista@2537
   712
                adjust_pep_trust_status(session, identity);            
krista@2537
   713
                status = set_identity(session, identity);
krista@2537
   714
            }
Edouard@499
   715
        }
vb@8
   716
    }
krista@2461
   717
    else {
krista@2461
   718
        /*
krista@2493
   719
        * Input: address (no others)
krista@2461
   720
         * Temporary identity information without username suplied
krista@2461
   721
         */
krista@2461
   722
         
krista@2461
   723
        //  * Again, see if there is an own identity that uses this address. If so, we'll
krista@2461
   724
        //    prefer that
krista@2461
   725
        stored_ident = NULL;
krista@2461
   726
         
krista@2461
   727
        if (default_own_id) {
krista@2461
   728
            status = get_identity(session, 
krista@2512
   729
                                  identity->address, 
krista@2461
   730
                                  default_own_id, 
krista@2461
   731
                                  &stored_ident);
krista@2461
   732
        }
krista@2461
   733
        // If there isn't an own identity, search for a non-temp stored ident
krista@2461
   734
        // with this address.                      
krista@2461
   735
        if (status == PEP_CANNOT_FIND_IDENTITY || !stored_ident) { 
krista@2461
   736
 
krista@2461
   737
            identity_list* id_list = NULL;
krista@2506
   738
            //    * Search for identity with this address
krista@2461
   739
            status = get_identities_by_address(session, identity->address, &id_list);
vb@8
   740
krista@2506
   741
            // Results are ordered by timestamp descending, so this covers
krista@2506
   742
            // both the one-result and multi-result cases
krista@2506
   743
            if (id_list) {
krista@2506
   744
                if (stored_ident) // unlikely
krista@2506
   745
                    free_identity(stored_ident);
krista@2461
   746
                stored_ident = id_list->ident;
krista@2461
   747
            }
krista@2461
   748
        }
krista@2461
   749
        if (stored_ident)
krista@2461
   750
            status = prepare_updated_identity(session, identity,
krista@2461
   751
                                              stored_ident, false);
krista@2496
   752
        else  {            
krista@2496
   753
            // too little info. BUT. We see if we can find a key; if so, we create a
krista@2496
   754
            // temp identity, look for a key, and store.
krista@2496
   755
                         
krista@2496
   756
            // create temporary identity, store it, and Return this
krista@2496
   757
            // This means TOFU_ user_id
krista@2496
   758
            identity->user_id = calloc(1, strlen(identity->address) + 6);
krista@2496
   759
            if (!identity->user_id)
krista@2496
   760
                return PEP_OUT_OF_MEMORY;
krista@2496
   761
krista@2496
   762
            snprintf(identity->user_id, strlen(identity->address) + 6,
krista@2496
   763
                     "TOFU_%s", identity->address);        
krista@2496
   764
        
krista@2496
   765
            identity->username = strdup(identity->address);
krista@2496
   766
            if (!identity->address)
krista@2496
   767
                return PEP_OUT_OF_MEMORY;            
krista@2496
   768
            
krista@2496
   769
            free(identity->fpr);
krista@2496
   770
            identity->fpr = NULL;
krista@2496
   771
            identity->comm_type = PEP_ct_unknown;
krista@2496
   772
krista@2548
   773
            status = elect_pubkey(session, identity, false);
krista@2496
   774
                         
krista@2496
   775
            if (identity->fpr)
krista@2496
   776
                status = get_key_rating(session, identity->fpr, &identity->comm_type);
krista@2496
   777
        
krista@2519
   778
            //    * call set_identity() to store
krista@2519
   779
            adjust_pep_trust_status(session, identity);            
krista@2496
   780
            status = set_identity(session, identity);
krista@2496
   781
krista@2496
   782
        }
krista@2496
   783
            
krista@2461
   784
    }
krista@2461
   785
    
krista@2461
   786
    // FIXME: This is legacy. I presume it's a notification for the caller...
krista@2461
   787
    // Revisit once I can talk to Volker
krista@2461
   788
    if (identity->comm_type != PEP_ct_compromized &&
krista@2461
   789
        identity->comm_type < PEP_ct_strong_but_unconfirmed)
vb@297
   790
        if (session->examine_identity)
krista@2461
   791
            session->examine_identity(identity, session->examine_management);
vb@297
   792
krista@2501
   793
    return status;
vb@0
   794
}
vb@0
   795
Edouard@774
   796
PEP_STATUS elect_ownkey(
krista@1194
   797
        PEP_SESSION session, pEp_identity * identity
Edouard@774
   798
    )
Edouard@774
   799
{
Edouard@774
   800
    PEP_STATUS status;
Edouard@774
   801
    stringlist_t *keylist = NULL;
Edouard@774
   802
Edouard@774
   803
    free(identity->fpr);
Edouard@774
   804
    identity->fpr = NULL;
Edouard@774
   805
krista@1357
   806
    status = find_private_keys(session, identity->address, &keylist);
Edouard@774
   807
    assert(status != PEP_OUT_OF_MEMORY);
Edouard@774
   808
    if (status == PEP_OUT_OF_MEMORY)
Edouard@774
   809
        return PEP_OUT_OF_MEMORY;
Edouard@774
   810
    
Edouard@774
   811
    if (keylist != NULL && keylist->value != NULL)
Edouard@774
   812
    {
Edouard@774
   813
        char *_fpr = NULL;
Edouard@774
   814
        identity->comm_type = PEP_ct_unknown;
Edouard@774
   815
Edouard@774
   816
        stringlist_t *_keylist;
Edouard@774
   817
        for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
Edouard@774
   818
            bool is_own = false;
Edouard@774
   819
            
edouard@1752
   820
            status = own_key_is_listed(session, _keylist->value, &is_own);
edouard@1752
   821
            assert(status == PEP_STATUS_OK);
edouard@1752
   822
            if (status != PEP_STATUS_OK) {
edouard@1752
   823
                free_stringlist(keylist);
edouard@1752
   824
                return status;
Edouard@774
   825
            }
Edouard@774
   826
            
edouard@1752
   827
            if (is_own)
Edouard@774
   828
            {
Edouard@774
   829
                PEP_comm_type _comm_type_key;
Edouard@774
   830
                
Edouard@774
   831
                status = get_key_rating(session, _keylist->value, &_comm_type_key);
Edouard@774
   832
                assert(status != PEP_OUT_OF_MEMORY);
Edouard@774
   833
                if (status == PEP_OUT_OF_MEMORY) {
Edouard@774
   834
                    free_stringlist(keylist);
Edouard@774
   835
                    return PEP_OUT_OF_MEMORY;
Edouard@774
   836
                }
Edouard@774
   837
                
Edouard@774
   838
                if (_comm_type_key != PEP_ct_compromized &&
Edouard@774
   839
                    _comm_type_key != PEP_ct_unknown)
Edouard@774
   840
                {
Edouard@774
   841
                    if (identity->comm_type == PEP_ct_unknown ||
Edouard@774
   842
                        _comm_type_key > identity->comm_type)
Edouard@774
   843
                    {
Edouard@774
   844
                        identity->comm_type = _comm_type_key;
Edouard@774
   845
                        _fpr = _keylist->value;
Edouard@774
   846
                    }
Edouard@774
   847
                }
Edouard@774
   848
            }
Edouard@774
   849
        }
Edouard@774
   850
        
Edouard@774
   851
        if (_fpr)
Edouard@774
   852
        {
Edouard@774
   853
            identity->fpr = strdup(_fpr);
Edouard@774
   854
            assert(identity->fpr);
Edouard@774
   855
            if (identity->fpr == NULL)
Edouard@774
   856
            {
Edouard@774
   857
                free_stringlist(keylist);
Edouard@774
   858
                return PEP_OUT_OF_MEMORY;
Edouard@774
   859
            }
Edouard@774
   860
        }
Edouard@774
   861
        free_stringlist(keylist);
Edouard@774
   862
    }
Edouard@774
   863
    return PEP_STATUS_OK;
Edouard@774
   864
}
Edouard@774
   865
krista@1357
   866
PEP_STATUS _has_usable_priv_key(PEP_SESSION session, char* fpr,
krista@1357
   867
                                bool* is_usable) {
krista@1357
   868
    
krista@2549
   869
    bool has_private = false;
krista@2549
   870
    PEP_STATUS status = contains_priv_key(session, fpr, &has_private);
krista@1357
   871
    
krista@2549
   872
    *is_usable = has_private;
krista@1357
   873
    
krista@2501
   874
    return status;
krista@1357
   875
}
krista@1357
   876
edouard@1406
   877
PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags)
vb@0
   878
{
krista@2461
   879
vb@0
   880
    PEP_STATUS status;
vb@0
   881
vb@0
   882
    assert(session);
vb@0
   883
    assert(identity);
vb@1044
   884
    assert(!EMPTYSTR(identity->address));
krista@2461
   885
    assert(!EMPTYSTR(identity->user_id));
vb@1043
   886
krista@2461
   887
    if (!session || !identity || EMPTYSTR(identity->address) ||
krista@2461
   888
        EMPTYSTR(identity->user_id))
krista@2501
   889
        return PEP_ILLEGAL_VALUE;
vb@191
   890
krista@2461
   891
    pEp_identity *stored_identity = NULL;
krista@2461
   892
    char* revoked_fpr = NULL; 
vb@2535
   893
    bool valid_key_found = false;
krista@2461
   894
        
krista@2461
   895
    char* default_own_id = NULL;
krista@2461
   896
    status = get_default_own_userid(session, &default_own_id);
krista@2461
   897
krista@2461
   898
    // Deal with non-default user_ids.
krista@2461
   899
    if (default_own_id && strcmp(default_own_id, identity->user_id) != 0) {
krista@2461
   900
        
krista@2461
   901
        status = set_userid_alias(session, default_own_id, identity->user_id);
krista@2461
   902
        // Do we want this to be fatal? For now, we'll do it...
krista@2461
   903
        if (status != PEP_STATUS_OK)
krista@2461
   904
            goto pep_free;
krista@2461
   905
            
krista@2461
   906
        free(identity->user_id);
krista@2461
   907
        identity->user_id = strdup(default_own_id);
krista@2461
   908
        if (identity->user_id == NULL) {
krista@2461
   909
            status = PEP_OUT_OF_MEMORY;
krista@2461
   910
            goto pep_free;
krista@2461
   911
        }
krista@2461
   912
    }
krista@2461
   913
krista@2461
   914
    // NOTE: IF WE DON'T YET HAVE AN OWN_ID, WE IGNORE REFERENCES TO THIS ADDRESS IN THE
krista@2461
   915
    // DB (WHICH MAY HAVE BEEN SET BEFORE MYSELF WAS CALLED BY RECEIVING AN EMAIL FROM
krista@2461
   916
    // THIS ADDRESS), AS IT IS NOT AN OWN_IDENTITY AND HAS NO INFORMATION WE NEED OR WHAT TO
krista@2461
   917
    // SET FOR MYSELF
krista@2461
   918
    
krista@2461
   919
    // Ok, so now, set up the own_identity:
vb@0
   920
    identity->comm_type = PEP_ct_pEp;
krista@2461
   921
    identity->me = true;
edouard@1406
   922
    if(ignore_flags)
edouard@1406
   923
        identity->flags = 0;
Edouard@658
   924
    
krista@2461
   925
    // Let's see if we have an identity record in the DB for 
krista@2461
   926
    // this user_id + address
krista@2501
   927
//    DEBUG_LOG("myself", "debug", identity->address);
vb@1044
   928
 
Edouard@560
   929
    status = get_identity(session,
Edouard@560
   930
                          identity->address,
Edouard@560
   931
                          identity->user_id,
Edouard@560
   932
                          &stored_identity);
krista@2461
   933
vb@0
   934
    assert(status != PEP_OUT_OF_MEMORY);
vb@2535
   935
    if (status == PEP_OUT_OF_MEMORY) {
vb@2535
   936
        status = PEP_OUT_OF_MEMORY;
vb@2535
   937
        goto pep_free;
vb@2535
   938
    }
krista@1357
   939
krista@2493
   940
    // Set usernames - priority is input username > stored name > address
krista@2461
   941
    // If there's an input username, we always patch the username with that
krista@2461
   942
    // input.
krista@2461
   943
    if (EMPTYSTR(identity->username)) {
krista@2494
   944
        bool stored_uname = (stored_identity && !EMPTYSTR(stored_identity->username));
krista@2493
   945
        char* uname = (stored_uname ? stored_identity->username : identity->address);
krista@2461
   946
        free(identity->username);
krista@2461
   947
        identity->username = strdup(uname);
vb@2535
   948
        if (identity->username == NULL) {
vb@2535
   949
            status = PEP_OUT_OF_MEMORY;
vb@2535
   950
            goto pep_free;
vb@2535
   951
        }
krista@2461
   952
    }
krista@2461
   953
vb@2535
   954
    // ignore input fpr
vb@2535
   955
vb@2535
   956
    if (identity->fpr) {
vb@2535
   957
        free(identity->fpr);
vb@2535
   958
        identity->fpr = NULL;
vb@2535
   959
    }
vb@2535
   960
vb@2535
   961
    // check stored identity
vb@2535
   962
    if (stored_identity && !EMPTYSTR(stored_identity->fpr)) {
krista@2461
   963
        // Fall back / retrieve
krista@2548
   964
        status = validate_fpr(session, stored_identity, false);
vb@2535
   965
        if (status == PEP_OUT_OF_MEMORY)
vb@2535
   966
            goto pep_free;
vb@2535
   967
        if (status == PEP_STATUS_OK) {
vb@2535
   968
            if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
vb@2535
   969
                identity->fpr = strdup(stored_identity->fpr);
vb@2535
   970
                assert(identity->fpr);
vb@2535
   971
                if (!identity->fpr) {
vb@2535
   972
                    status = PEP_OUT_OF_MEMORY;
vb@2535
   973
                    goto pep_free;
vb@2535
   974
                }
vb@2535
   975
                valid_key_found = true;            
vb@2535
   976
            }
vb@2535
   977
            else {
vb@2535
   978
                bool revoked = false;
krista@2461
   979
                status = key_revoked(session, stored_identity->fpr, &revoked);
vb@2535
   980
                if (status)
vb@2535
   981
                    goto pep_free;
vb@2535
   982
                if (revoked) {
krista@2461
   983
                    revoked_fpr = strdup(stored_identity->fpr);
vb@2535
   984
                    assert(revoked_fpr);
vb@2535
   985
                    if (!revoked_fpr) {
vb@2535
   986
                        status = PEP_OUT_OF_MEMORY;
vb@2535
   987
                        goto pep_free;
vb@2535
   988
                    }
vb@2535
   989
                }
vb@2535
   990
            }
krista@1357
   991
        }
Edouard@560
   992
    }
krista@1357
   993
    
krista@2461
   994
    // Nothing left to do but generate a key
krista@2461
   995
    if (!valid_key_found) {
krista@2461
   996
        if (!do_keygen)
krista@2461
   997
            status = PEP_GET_KEY_FAILED;
krista@2461
   998
        else {
krista@2501
   999
// /            DEBUG_LOG("Generating key pair", "debug", identity->address);
vb@934
  1000
krista@2461
  1001
            free(identity->fpr);
krista@2461
  1002
            identity->fpr = NULL;
krista@2461
  1003
            status = generate_keypair(session, identity);
krista@2461
  1004
            assert(status != PEP_OUT_OF_MEMORY);
krista@1371
  1005
krista@2461
  1006
            if (status != PEP_STATUS_OK) {
krista@2461
  1007
                char buf[11];
krista@2461
  1008
                snprintf(buf, 11, "%d", status); // uh, this is kludgey. FIXME
krista@2501
  1009
//                DEBUG_LOG("Generating key pair failed", "debug", buf);
krista@2461
  1010
            }        
krista@2461
  1011
            else {
krista@2461
  1012
                valid_key_found = true;
krista@2461
  1013
                if (revoked_fpr) {
krista@2461
  1014
                    status = set_revoked(session, revoked_fpr,
krista@2461
  1015
                                         stored_identity->fpr, time(NULL));
krista@2461
  1016
                }
krista@2461
  1017
            }
krista@1357
  1018
        }
Edouard@560
  1019
    }
Edouard@695
  1020
krista@2461
  1021
    if (valid_key_found) {
krista@2461
  1022
        identity->comm_type = PEP_ct_pEp;
krista@2461
  1023
        status = PEP_STATUS_OK;
krista@2461
  1024
    }
krista@2461
  1025
    else {
krista@2461
  1026
        free(identity->fpr);
krista@2461
  1027
        identity->fpr = NULL;
krista@2461
  1028
        identity->comm_type = PEP_ct_unknown;
krista@2461
  1029
    }
krista@2461
  1030
    
krista@2461
  1031
    status = set_identity(session, identity);
krista@2504
  1032
    if (status == PEP_STATUS_OK)
krista@2504
  1033
        status = set_as_pep_user(session, identity);
Edouard@775
  1034
krista@2461
  1035
pep_free:    
krista@2461
  1036
    free(default_own_id);
krista@2461
  1037
    free(revoked_fpr);                     
krista@2461
  1038
    free_identity(stored_identity);
krista@2501
  1039
    return status;
krista@2461
  1040
}
krista@2461
  1041
vb@2535
  1042
// DYNAMIC_API PEP_STATUS initialise_own_identities(PEP_SESSION session,
vb@2535
  1043
//                                                  identity_list* my_idents) {
vb@2535
  1044
//     PEP_STATUS status = PEP_STATUS_OK;
vb@2535
  1045
//     if (!session)
vb@2535
  1046
//         return PEP_ILLEGAL_VALUE;
vb@2535
  1047
//         
vb@2535
  1048
//     if (!my_idents)
vb@2535
  1049
//         return PEP_STATUS_OK;
vb@2535
  1050
//             
vb@2535
  1051
//     identity_list* ident_curr = my_idents;
vb@2535
  1052
//     while (ident_curr) {
vb@2535
  1053
//         pEp_identity* ident = ident_curr->ident;
vb@2535
  1054
//         if (!ident || !ident->address) {
vb@2535
  1055
//             status = PEP_ILLEGAL_VALUE;
vb@2535
  1056
//             goto pep_error;
vb@2535
  1057
//         }
vb@2535
  1058
// 
vb@2535
  1059
//         status = _myself(session, ident, false, false);
vb@2535
  1060
//         
vb@2535
  1061
//         ident_curr = ident_curr->next;
vb@2535
  1062
//     }
vb@2535
  1063
//     
vb@2535
  1064
// pep_error:
vb@2535
  1065
//     return status;
vb@2535
  1066
// }
vb@0
  1067
edouard@1385
  1068
DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
edouard@1385
  1069
{
krista@2501
  1070
    return _myself(session, identity, true, false);
edouard@1385
  1071
}
edouard@1385
  1072
vb@296
  1073
DYNAMIC_API PEP_STATUS register_examine_function(
vb@292
  1074
        PEP_SESSION session, 
vb@292
  1075
        examine_identity_t examine_identity,
vb@292
  1076
        void *management
vb@292
  1077
    )
vb@292
  1078
{
vb@292
  1079
    assert(session);
vb@292
  1080
    if (!session)
vb@292
  1081
        return PEP_ILLEGAL_VALUE;
vb@292
  1082
vb@292
  1083
    session->examine_management = management;
vb@292
  1084
    session->examine_identity = examine_identity;
vb@292
  1085
vb@292
  1086
    return PEP_STATUS_OK;
vb@292
  1087
}
vb@292
  1088
vb@0
  1089
DYNAMIC_API PEP_STATUS do_keymanagement(
vb@0
  1090
        retrieve_next_identity_t retrieve_next_identity,
vb@0
  1091
        void *management
vb@0
  1092
    )
vb@0
  1093
{
vb@0
  1094
    PEP_SESSION session;
vb@0
  1095
    pEp_identity *identity;
Edouard@499
  1096
    PEP_STATUS status;
vb@0
  1097
Edouard@499
  1098
    assert(retrieve_next_identity);
Edouard@499
  1099
    assert(management);
Edouard@499
  1100
Edouard@499
  1101
    if (!retrieve_next_identity || !management)
Edouard@499
  1102
        return PEP_ILLEGAL_VALUE;
Edouard@499
  1103
Edouard@499
  1104
    status = init(&session);
vb@0
  1105
    assert(status == PEP_STATUS_OK);
vb@0
  1106
    if (status != PEP_STATUS_OK)
vb@0
  1107
        return status;
vb@0
  1108
vb@0
  1109
    log_event(session, "keymanagement thread started", "pEp engine", NULL, NULL);
vb@0
  1110
Edouard@499
  1111
    while ((identity = retrieve_next_identity(management))) 
Edouard@499
  1112
    {
vb@0
  1113
        assert(identity->address);
Edouard@499
  1114
        if(identity->address)
Edouard@499
  1115
        {
Edouard@499
  1116
            DEBUG_LOG("do_keymanagement", "retrieve_next_identity", identity->address);
Edouard@499
  1117
krista@2461
  1118
            if (identity->me) {
Edouard@499
  1119
                status = myself(session, identity);
Edouard@499
  1120
            } else {
Edouard@499
  1121
                status = recv_key(session, identity->address);
Edouard@499
  1122
            }
Edouard@499
  1123
vb@0
  1124
            assert(status != PEP_OUT_OF_MEMORY);
Edouard@499
  1125
            if(status == PEP_OUT_OF_MEMORY)
Edouard@499
  1126
                return PEP_OUT_OF_MEMORY;
vb@0
  1127
        }
vb@0
  1128
        free_identity(identity);
vb@0
  1129
    }
vb@0
  1130
vb@0
  1131
    log_event(session, "keymanagement thread shutdown", "pEp engine", NULL, NULL);
vb@0
  1132
vb@0
  1133
    release(session);
vb@0
  1134
    return PEP_STATUS_OK;
vb@0
  1135
}
vb@0
  1136
krista@1213
  1137
DYNAMIC_API PEP_STATUS key_mistrusted(
vb@357
  1138
        PEP_SESSION session,
vb@357
  1139
        pEp_identity *ident
vb@357
  1140
    )
vb@215
  1141
{
vb@218
  1142
    PEP_STATUS status = PEP_STATUS_OK;
vb@218
  1143
vb@215
  1144
    assert(session);
vb@357
  1145
    assert(ident);
Edouard@439
  1146
    assert(!EMPTYSTR(ident->fpr));
vb@215
  1147
vb@357
  1148
    if (!(session && ident && ident->fpr))
vb@215
  1149
        return PEP_ILLEGAL_VALUE;
vb@215
  1150
krista@2461
  1151
    if (ident->me)
Edouard@697
  1152
    {
vb@357
  1153
        revoke_key(session, ident->fpr, NULL);
Edouard@697
  1154
        myself(session, ident);
Edouard@697
  1155
    }
Edouard@697
  1156
    else
Edouard@697
  1157
    {
krista@2129
  1158
        // for undo
krista@2129
  1159
        if (session->cached_mistrusted)
krista@2129
  1160
            free(session->cached_mistrusted);
krista@2129
  1161
        session->cached_mistrusted = identity_dup(ident);
krista@2461
  1162
        
krista@2461
  1163
        // set mistrust for this user_id/keypair (even if there's not an
krista@2461
  1164
        // identity set yet, this is important, as we need to record the mistrust
krista@2461
  1165
        // action)
krista@2478
  1166
        
krista@2483
  1167
        // double-check to be sure key is even in the DB
krista@2483
  1168
        if (ident->fpr)
krista@2483
  1169
            status = set_pgp_keypair(session, ident->fpr);
krista@2483
  1170
krista@2478
  1171
        // We set this temporarily but will grab it back from the cache afterwards
krista@2478
  1172
        ident->comm_type = PEP_ct_mistrusted;
krista@2478
  1173
        status = set_trust(session, ident);
krista@2478
  1174
        ident->comm_type = session->cached_mistrusted->comm_type;
krista@2478
  1175
        
krista@2461
  1176
        if (status == PEP_STATUS_OK)
krista@2461
  1177
            // cascade that mistrust for anyone using this key
krista@2461
  1178
            status = mark_as_compromized(session, ident->fpr);
krista@2461
  1179
        if (status == PEP_STATUS_OK)
krista@2461
  1180
            status = remove_fpr_as_default(session, ident->fpr);
krista@2471
  1181
        if (status == PEP_STATUS_OK)
krista@2471
  1182
            status = add_mistrusted_key(session, ident->fpr);
Edouard@697
  1183
    }
vb@218
  1184
vb@218
  1185
    return status;
vb@215
  1186
}
vb@215
  1187
krista@2129
  1188
DYNAMIC_API PEP_STATUS undo_last_mistrust(PEP_SESSION session) {
krista@2129
  1189
    assert(session);
krista@2129
  1190
    
krista@2129
  1191
    if (!session)
krista@2129
  1192
        return PEP_ILLEGAL_VALUE;
krista@2129
  1193
    
krista@2129
  1194
    PEP_STATUS status = PEP_STATUS_OK;
krista@2129
  1195
        
krista@2129
  1196
    pEp_identity* cached_ident = session->cached_mistrusted;
krista@2129
  1197
    
krista@2129
  1198
    if (!cached_ident)
krista@2129
  1199
        status = PEP_CANNOT_FIND_IDENTITY;
krista@2129
  1200
    else {
krista@2471
  1201
        status = delete_mistrusted_key(session, cached_ident->fpr);
krista@2471
  1202
        if (status == PEP_STATUS_OK) {
krista@2504
  1203
            status = set_identity(session, cached_ident);
krista@2504
  1204
            // THIS SHOULDN'T BE NECESSARY - PREVIOUS VALUE WAS IN THE DB
krista@2504
  1205
            // if (status == PEP_STATUS_OK) {
krista@2504
  1206
            //     if ((cached_ident->comm_type | PEP_ct_confirmed) == PEP_ct_pEp)
krista@2504
  1207
            //         status = set_as_pep_user(session, cached_ident);
krista@2504
  1208
            // }            
krista@2471
  1209
            free_identity(session->cached_mistrusted);
krista@2471
  1210
        }
krista@2129
  1211
    }
krista@2129
  1212
    
krista@2129
  1213
    session->cached_mistrusted = NULL;
krista@2471
  1214
    
krista@2129
  1215
    return status;
krista@2129
  1216
}
krista@2129
  1217
Edouard@410
  1218
DYNAMIC_API PEP_STATUS key_reset_trust(
Edouard@410
  1219
        PEP_SESSION session,
Edouard@410
  1220
        pEp_identity *ident
Edouard@410
  1221
    )
Edouard@410
  1222
{
Edouard@410
  1223
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@410
  1224
Edouard@410
  1225
    assert(session);
Edouard@410
  1226
    assert(ident);
Edouard@439
  1227
    assert(!EMPTYSTR(ident->fpr));
Edouard@439
  1228
    assert(!EMPTYSTR(ident->address));
Edouard@439
  1229
    assert(!EMPTYSTR(ident->user_id));
Edouard@410
  1230
krista@2461
  1231
    if (!(session && ident && ident->fpr && ident->fpr[0] != '\0' && ident->address &&
vb@420
  1232
            ident->user_id))
Edouard@410
  1233
        return PEP_ILLEGAL_VALUE;
Edouard@410
  1234
krista@2461
  1235
    // we do not change the input struct at ALL.
krista@2461
  1236
    pEp_identity* input_copy = identity_dup(ident);
krista@2461
  1237
    
krista@2461
  1238
    pEp_identity* tmp_ident = NULL;
krista@2461
  1239
    
krista@2461
  1240
    status = get_trust(session, input_copy);
krista@2461
  1241
    
vb@420
  1242
    if (status != PEP_STATUS_OK)
krista@2461
  1243
        goto pep_free;
krista@2461
  1244
        
krista@2461
  1245
    PEP_comm_type new_trust = PEP_ct_unknown;
Edouard@410
  1246
krista@2461
  1247
    if (input_copy->comm_type != PEP_ct_mistrusted)
krista@2461
  1248
        new_trust = input_copy->comm_type & ~PEP_ct_confirmed;
vb@421
  1249
krista@2478
  1250
    // We'll return the status from the input_copy cache afterward
krista@2478
  1251
    input_copy->comm_type = new_trust;
krista@2478
  1252
    status = set_trust(session, input_copy);
krista@2461
  1253
    
vb@421
  1254
    if (status != PEP_STATUS_OK)
krista@2461
  1255
        goto pep_free;
vb@421
  1256
krista@2471
  1257
    bool mistrusted_key = false;
krista@2461
  1258
        
krista@2471
  1259
    status = is_mistrusted_key(session, ident->fpr, &mistrusted_key);
krista@2471
  1260
krista@2471
  1261
    if (status != PEP_STATUS_OK)
krista@2471
  1262
        goto pep_free;
krista@2471
  1263
    
krista@2471
  1264
    if (mistrusted_key)
krista@2471
  1265
        status = delete_mistrusted_key(session, ident->fpr);
krista@2471
  1266
krista@2471
  1267
    if (status != PEP_STATUS_OK)
krista@2471
  1268
        goto pep_free;
krista@2461
  1269
        
krista@2461
  1270
    tmp_ident = new_identity(ident->address, NULL, ident->user_id, NULL);
krista@2461
  1271
krista@2461
  1272
    if (!tmp_ident)
krista@2461
  1273
        return PEP_OUT_OF_MEMORY;
krista@2461
  1274
    
krista@2461
  1275
    status = update_identity(session, tmp_ident);
krista@2461
  1276
    
krista@2461
  1277
    if (status != PEP_STATUS_OK)
krista@2461
  1278
        goto pep_free;
krista@2461
  1279
    
krista@2461
  1280
    // remove as default if necessary
krista@2507
  1281
    if (!EMPTYSTR(tmp_ident->fpr) && strcmp(tmp_ident->fpr, ident->fpr) == 0) {
krista@2461
  1282
        free(tmp_ident->fpr);
krista@2461
  1283
        tmp_ident->fpr = NULL;
krista@2461
  1284
        tmp_ident->comm_type = PEP_ct_unknown;
krista@2461
  1285
        status = set_identity(session, tmp_ident);
krista@2461
  1286
        if (status != PEP_STATUS_OK)
krista@2461
  1287
            goto pep_free;
krista@2461
  1288
    }
krista@2461
  1289
    
krista@2461
  1290
    char* user_default = NULL;
krista@2461
  1291
    status = get_main_user_fpr(session, tmp_ident->user_id, &user_default);
krista@2461
  1292
    
krista@2461
  1293
    if (!EMPTYSTR(user_default)) {
krista@2461
  1294
        if (strcmp(user_default, ident->fpr) == 0)
krista@2461
  1295
            status = refresh_userid_default_key(session, ident->user_id);
krista@2461
  1296
        if (status != PEP_STATUS_OK)
krista@2461
  1297
            goto pep_free;    
krista@2461
  1298
    }
krista@2461
  1299
            
krista@2461
  1300
pep_free:
krista@2461
  1301
    free_identity(tmp_ident);
krista@2461
  1302
    free_identity(input_copy);
Edouard@410
  1303
    return status;
Edouard@410
  1304
}
Edouard@410
  1305
vb@354
  1306
DYNAMIC_API PEP_STATUS trust_personal_key(
vb@354
  1307
        PEP_SESSION session,
vb@354
  1308
        pEp_identity *ident
vb@354
  1309
    )
vb@354
  1310
{
vb@354
  1311
    PEP_STATUS status = PEP_STATUS_OK;
vb@354
  1312
vb@354
  1313
    assert(session);
vb@354
  1314
    assert(ident);
Edouard@439
  1315
    assert(!EMPTYSTR(ident->address));
Edouard@439
  1316
    assert(!EMPTYSTR(ident->user_id));
Edouard@439
  1317
    assert(!EMPTYSTR(ident->fpr));
vb@354
  1318
Edouard@439
  1319
    if (!ident || EMPTYSTR(ident->address) || EMPTYSTR(ident->user_id) ||
edouard@1945
  1320
            EMPTYSTR(ident->fpr))
vb@354
  1321
        return PEP_ILLEGAL_VALUE;
vb@354
  1322
krista@2461
  1323
    //bool ident_has_trusted_default = false;
krista@2461
  1324
    char* ident_default_fpr = NULL;
vb@354
  1325
krista@2461
  1326
    // Before we do anything, be sure the input fpr is even eligible to be trusted
krista@2461
  1327
    PEP_comm_type input_default_ct = PEP_ct_unknown;
krista@2461
  1328
    status = get_key_rating(session, ident->fpr, &input_default_ct);
krista@2461
  1329
    if (input_default_ct < PEP_ct_strong_but_unconfirmed)
krista@2461
  1330
        return PEP_KEY_UNSUITABLE;
krista@2461
  1331
krista@2477
  1332
    status = set_pgp_keypair(session, ident->fpr);
krista@2477
  1333
    if (status != PEP_STATUS_OK)
krista@2477
  1334
        return status;
krista@2461
  1335
krista@2461
  1336
    bool me = is_me(session, ident);
krista@2461
  1337
krista@2494
  1338
    pEp_identity* ident_copy = identity_dup(ident);
krista@2494
  1339
    char* cached_fpr = NULL;
krista@2494
  1340
krista@2494
  1341
    // for setting up a temp trusted identity for the input fpr
krista@2494
  1342
    pEp_identity* tmp_id = NULL;
krista@2494
  1343
roker@2497
  1344
    // For later, in case we need to check the user default key
roker@2497
  1345
    pEp_identity* tmp_user_ident = NULL;
roker@2497
  1346
krista@2494
  1347
    if (me) {
krista@2552
  1348
        bool has_private = false;
krista@2552
  1349
        // first of all, does this key even have a private component.
krista@2552
  1350
        status = contains_priv_key(session, ident->fpr, &has_private);
krista@2552
  1351
        if (status != PEP_STATUS_OK && status != PEP_KEY_NOT_FOUND)
krista@2552
  1352
            goto pep_free;
krista@2552
  1353
            
krista@2552
  1354
        if (has_private) {
krista@2552
  1355
            status = set_own_key(session, ident_copy, ident->fpr); 
krista@2552
  1356
            goto pep_free;
krista@2552
  1357
        }
krista@2494
  1358
    }
krista@2494
  1359
    
krista@2552
  1360
    // Either it's not me, or it's me but the key has no private key. 
krista@2552
  1361
    // We're only talking about pub keys here. Moving on.
krista@2552
  1362
    
krista@2522
  1363
    // Save the input fpr, which we already tested as non-NULL
krista@2494
  1364
    cached_fpr = strdup(ident->fpr);
krista@2461
  1365
krista@2552
  1366
    // Set up a temp trusted identity for the input fpr without a comm type;
krista@2494
  1367
    tmp_id = new_identity(ident->address, ident->fpr, ident->user_id, NULL);
krista@2552
  1368
    
krista@2552
  1369
    // ->me isn't set, even if this is an own identity, so this will work.
krista@2548
  1370
    status = validate_fpr(session, tmp_id, false);
krista@2461
  1371
        
krista@2461
  1372
    if (status == PEP_STATUS_OK) {
krista@2461
  1373
        // Validate fpr gets trust DB or, when that fails, key comm type. we checked
krista@2461
  1374
        // above that the key was ok. (not revoked or expired), but we want the max.
krista@2461
  1375
        tmp_id->comm_type = _MAX(tmp_id->comm_type, input_default_ct) | PEP_ct_confirmed;
krista@2552
  1376
krista@2552
  1377
        // Get the default identity without setting the fpr                                       
krista@2552
  1378
        if (me)
krista@2552
  1379
            status = _myself(session, ident_copy, false, true);
krista@2552
  1380
        else    
krista@2552
  1381
            status = update_identity(session, ident_copy);
krista@2552
  1382
            
krista@2522
  1383
        ident_default_fpr = (EMPTYSTR(ident_copy->fpr) ? NULL : strdup(ident_copy->fpr));
krista@2461
  1384
krista@2461
  1385
        if (status == PEP_STATUS_OK) {
krista@2461
  1386
            bool trusted_default = false;
krista@2461
  1387
krista@2461
  1388
            // If there's no default, or the default is different from the input...
krista@2552
  1389
            if (me || EMPTYSTR(ident_default_fpr) || strcmp(cached_fpr, ident_default_fpr) != 0) {
krista@2461
  1390
                
krista@2461
  1391
                // If the default fpr (if there is one) is trusted and key is strong enough,
krista@2461
  1392
                // don't replace, we just set the trusted bit on this key for this user_id...
krista@2461
  1393
                // (If there's no default fpr, this won't be true anyway.)
krista@2552
  1394
                if (me || (ident_copy->comm_type >= PEP_ct_strong_but_unconfirmed && 
krista@2552
  1395
                          (ident_copy->comm_type & PEP_ct_confirmed))) {                        
krista@2461
  1396
krista@2461
  1397
                    trusted_default = true;
krista@2461
  1398
                                    
krista@2478
  1399
                    status = set_trust(session, tmp_id);
krista@2461
  1400
                    input_default_ct = tmp_id->comm_type;                    
krista@2461
  1401
                }
krista@2461
  1402
                else {
krista@2494
  1403
                    free(ident_copy->fpr);
krista@2494
  1404
                    ident_copy->fpr = strdup(cached_fpr);
krista@2494
  1405
                    ident_copy->comm_type = tmp_id->comm_type;
krista@2504
  1406
                    status = set_identity(session, ident_copy); // replace identity default
krista@2504
  1407
                    if (status == PEP_STATUS_OK) {
krista@2504
  1408
                        if ((ident_copy->comm_type | PEP_ct_confirmed) == PEP_ct_pEp)
krista@2504
  1409
                            status = set_as_pep_user(session, ident_copy);
krista@2504
  1410
                    }            
krista@2461
  1411
                }
krista@2461
  1412
            }
krista@2461
  1413
            else { // we're setting this on the default fpr
krista@2461
  1414
                ident->comm_type = tmp_id->comm_type;
krista@2461
  1415
                status = set_identity(session, ident);
krista@2461
  1416
                trusted_default = true;
krista@2461
  1417
            }
krista@2461
  1418
            if (status == PEP_STATUS_OK && !trusted_default) {
krista@2461
  1419
                // Ok, there wasn't a trusted default, so we replaced. Thus, we also
krista@2461
  1420
                // make sure there's a trusted default on the user_id. If there
krista@2461
  1421
                // is not, we make this the default.
krista@2461
  1422
                char* user_default = NULL;
krista@2461
  1423
                status = get_main_user_fpr(session, ident->user_id, &user_default);
krista@2461
  1424
            
krista@2461
  1425
                if (status == PEP_STATUS_OK && user_default) {
krista@2494
  1426
                    tmp_user_ident = new_identity(ident->address, 
krista@2494
  1427
                                                  user_default, 
krista@2494
  1428
                                                  ident->user_id, 
krista@2494
  1429
                                                  NULL);
krista@2461
  1430
                    if (!tmp_user_ident)
krista@2461
  1431
                        status = PEP_OUT_OF_MEMORY;
krista@2461
  1432
                    else {
krista@2548
  1433
                        status = validate_fpr(session, tmp_user_ident, false);
krista@2461
  1434
                        
krista@2461
  1435
                        if (status != PEP_STATUS_OK ||
krista@2461
  1436
                            tmp_user_ident->comm_type < PEP_ct_strong_but_unconfirmed ||
krista@2461
  1437
                            !(tmp_user_ident->comm_type & PEP_ct_confirmed)) 
krista@2461
  1438
                        {
krista@2461
  1439
                            char* trusted_fpr = (trusted_default ? ident_default_fpr : cached_fpr);
krista@2461
  1440
                            status = replace_main_user_fpr(session, ident->user_id, trusted_fpr);
krista@2461
  1441
                        } 
krista@2461
  1442
                    }
krista@2461
  1443
                }
krista@2461
  1444
            }
krista@2461
  1445
        }
krista@2461
  1446
    }    
vb@354
  1447
krista@2494
  1448
pep_free:
krista@2494
  1449
    free(ident_default_fpr);
krista@2494
  1450
    free(cached_fpr);
krista@2494
  1451
    free_identity(tmp_id);
krista@2494
  1452
    free_identity(ident_copy);
krista@2494
  1453
    free_identity(tmp_user_ident);
vb@354
  1454
    return status;
vb@354
  1455
}
vb@354
  1456
Edouard@584
  1457
DYNAMIC_API PEP_STATUS own_key_is_listed(
vb@955
  1458
        PEP_SESSION session,
vb@955
  1459
        const char *fpr,
vb@955
  1460
        bool *listed
vb@955
  1461
    )
Edouard@584
  1462
{
Edouard@584
  1463
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@584
  1464
    int count;
Edouard@584
  1465
    
Edouard@584
  1466
    assert(session && fpr && fpr[0] && listed);
Edouard@584
  1467
    
Edouard@584
  1468
    if (!(session && fpr && fpr[0] && listed))
Edouard@584
  1469
        return PEP_ILLEGAL_VALUE;
Edouard@584
  1470
    
Edouard@584
  1471
    *listed = false;
Edouard@584
  1472
    
Edouard@584
  1473
    sqlite3_reset(session->own_key_is_listed);
Edouard@584
  1474
    sqlite3_bind_text(session->own_key_is_listed, 1, fpr, -1, SQLITE_STATIC);
Edouard@584
  1475
    
Edouard@584
  1476
    int result;
Edouard@584
  1477
    
Edouard@584
  1478
    result = sqlite3_step(session->own_key_is_listed);
Edouard@584
  1479
    switch (result) {
Edouard@584
  1480
        case SQLITE_ROW:
Edouard@584
  1481
            count = sqlite3_column_int(session->own_key_is_listed, 0);
Edouard@584
  1482
            *listed = count > 0;
krista@2461
  1483
            status = PEP_STATUS_OK;
Edouard@584
  1484
            break;
Edouard@584
  1485
            
Edouard@584
  1486
        default:
Edouard@584
  1487
            status = PEP_UNKNOWN_ERROR;
Edouard@584
  1488
    }
Edouard@584
  1489
    
Edouard@584
  1490
    sqlite3_reset(session->own_key_is_listed);
Edouard@584
  1491
    return status;
Edouard@584
  1492
}
Edouard@584
  1493
edouard@1412
  1494
PEP_STATUS _own_identities_retrieve(
vb@955
  1495
        PEP_SESSION session,
edouard@1412
  1496
        identity_list **own_identities,
edouard@1412
  1497
        identity_flags_t excluded_flags
vb@955
  1498
      )
Edouard@584
  1499
{
Edouard@584
  1500
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@584
  1501
    
vb@955
  1502
    assert(session && own_identities);
vb@955
  1503
    if (!(session && own_identities))
Edouard@584
  1504
        return PEP_ILLEGAL_VALUE;
Edouard@584
  1505
    
vb@955
  1506
    *own_identities = NULL;
vb@955
  1507
    identity_list *_own_identities = new_identity_list(NULL);
vb@955
  1508
    if (_own_identities == NULL)
Edouard@584
  1509
        goto enomem;
Edouard@584
  1510
    
vb@955
  1511
    sqlite3_reset(session->own_identities_retrieve);
Edouard@584
  1512
    
Edouard@584
  1513
    int result;
vb@955
  1514
    // address, fpr, username, user_id, comm_type, lang, flags
vb@955
  1515
    const char *address = NULL;
Edouard@584
  1516
    const char *fpr = NULL;
vb@955
  1517
    const char *username = NULL;
vb@955
  1518
    const char *user_id = NULL;
vb@955
  1519
    PEP_comm_type comm_type = PEP_ct_unknown;
vb@955
  1520
    const char *lang = NULL;
vb@955
  1521
    unsigned int flags = 0;
Edouard@584
  1522
    
vb@955
  1523
    identity_list *_bl = _own_identities;
Edouard@584
  1524
    do {
edouard@1412
  1525
        sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
vb@955
  1526
        result = sqlite3_step(session->own_identities_retrieve);
Edouard@584
  1527
        switch (result) {
Edouard@584
  1528
            case SQLITE_ROW:
vb@955
  1529
                address = (const char *)
vb@955
  1530
                    sqlite3_column_text(session->own_identities_retrieve, 0);
vb@955
  1531
                fpr = (const char *)
vb@955
  1532
                    sqlite3_column_text(session->own_identities_retrieve, 1);
krista@2461
  1533
                user_id = (const char *)
krista@2461
  1534
                    sqlite3_column_text(session->own_identities_retrieve, 2);
vb@1071
  1535
                username = (const char *)
krista@2461
  1536
                    sqlite3_column_text(session->own_identities_retrieve, 3);
vb@1071
  1537
                comm_type = PEP_ct_pEp;
vb@1071
  1538
                lang = (const char *)
krista@2461
  1539
                    sqlite3_column_text(session->own_identities_retrieve, 4);
vb@1071
  1540
                flags = (unsigned int)
krista@2461
  1541
                    sqlite3_column_int(session->own_identities_retrieve, 5);
vb@955
  1542
vb@1078
  1543
                pEp_identity *ident = new_identity(address, fpr, user_id, username);
vb@1079
  1544
                if (!ident)
Edouard@584
  1545
                    goto enomem;
vb@955
  1546
                ident->comm_type = comm_type;
vb@955
  1547
                if (lang && lang[0]) {
vb@955
  1548
                    ident->lang[0] = lang[0];
vb@955
  1549
                    ident->lang[1] = lang[1];
vb@1078
  1550
                    ident->lang[2] = 0;
vb@955
  1551
                }
krista@2461
  1552
                ident->me = true;
vb@955
  1553
                ident->flags = flags;
vb@955
  1554
vb@955
  1555
                _bl = identity_list_add(_bl, ident);
vb@1080
  1556
                if (_bl == NULL) {
vb@1080
  1557
                    free_identity(ident);
vb@983
  1558
                    goto enomem;
vb@1080
  1559
                }
Edouard@584
  1560
                
Edouard@584
  1561
                break;
Edouard@584
  1562
                
Edouard@584
  1563
            case SQLITE_DONE:
Edouard@584
  1564
                break;
Edouard@584
  1565
                
Edouard@584
  1566
            default:
Edouard@584
  1567
                status = PEP_UNKNOWN_ERROR;
Edouard@584
  1568
                result = SQLITE_DONE;
Edouard@584
  1569
        }
Edouard@584
  1570
    } while (result != SQLITE_DONE);
Edouard@584
  1571
    
vb@955
  1572
    sqlite3_reset(session->own_identities_retrieve);
Edouard@584
  1573
    if (status == PEP_STATUS_OK)
vb@955
  1574
        *own_identities = _own_identities;
Edouard@584
  1575
    else
vb@955
  1576
        free_identity_list(_own_identities);
Edouard@584
  1577
    
Edouard@584
  1578
    goto the_end;
Edouard@584
  1579
    
Edouard@584
  1580
enomem:
vb@955
  1581
    free_identity_list(_own_identities);
Edouard@584
  1582
    status = PEP_OUT_OF_MEMORY;
Edouard@584
  1583
    
Edouard@584
  1584
the_end:
Edouard@584
  1585
    return status;
Edouard@584
  1586
}
vb@955
  1587
edouard@1412
  1588
DYNAMIC_API PEP_STATUS own_identities_retrieve(
edouard@1364
  1589
        PEP_SESSION session,
edouard@1412
  1590
        identity_list **own_identities
edouard@1412
  1591
      )
edouard@1412
  1592
{
edouard@1412
  1593
    return _own_identities_retrieve(session, own_identities, 0);
edouard@1412
  1594
}
edouard@1412
  1595
edouard@1412
  1596
PEP_STATUS _own_keys_retrieve(
edouard@1412
  1597
        PEP_SESSION session,
edouard@1412
  1598
        stringlist_t **keylist,
edouard@1412
  1599
        identity_flags_t excluded_flags
edouard@1364
  1600
      )
edouard@1364
  1601
{
edouard@1364
  1602
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1364
  1603
    
edouard@1364
  1604
    assert(session && keylist);
edouard@1364
  1605
    if (!(session && keylist))
edouard@1364
  1606
        return PEP_ILLEGAL_VALUE;
edouard@1364
  1607
    
edouard@1364
  1608
    *keylist = NULL;
edouard@1364
  1609
    stringlist_t *_keylist = NULL;
edouard@1364
  1610
    
edouard@1394
  1611
    sqlite3_reset(session->own_keys_retrieve);
edouard@1364
  1612
    
edouard@1364
  1613
    int result;
edouard@1364
  1614
    char *fpr = NULL;
edouard@1364
  1615
    
edouard@1364
  1616
    stringlist_t *_bl = _keylist;
edouard@1364
  1617
    do {
edouard@1412
  1618
        sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
edouard@1394
  1619
        result = sqlite3_step(session->own_keys_retrieve);
edouard@1364
  1620
        switch (result) {
edouard@1364
  1621
            case SQLITE_ROW:
edouard@1394
  1622
                fpr = strdup((const char *) sqlite3_column_text(session->own_keys_retrieve, 0));
edouard@1364
  1623
                if(fpr == NULL)
edouard@1364
  1624
                    goto enomem;
edouard@1364
  1625
edouard@1364
  1626
                _bl = stringlist_add(_bl, fpr);
edouard@1364
  1627
                if (_bl == NULL) {
edouard@1364
  1628
                    free(fpr);
edouard@1364
  1629
                    goto enomem;
edouard@1364
  1630
                }
edouard@1364
  1631
                if (_keylist == NULL)
edouard@1364
  1632
                    _keylist = _bl;
edouard@1364
  1633
                
edouard@1364
  1634
                break;
edouard@1364
  1635
                
edouard@1364
  1636
            case SQLITE_DONE:
edouard@1364
  1637
                break;
edouard@1364
  1638
                
edouard@1364
  1639
            default:
edouard@1364
  1640
                status = PEP_UNKNOWN_ERROR;
edouard@1364
  1641
                result = SQLITE_DONE;
edouard@1364
  1642
        }
edouard@1364
  1643
    } while (result != SQLITE_DONE);
edouard@1364
  1644
    
edouard@1394
  1645
    sqlite3_reset(session->own_keys_retrieve);
edouard@1364
  1646
    if (status == PEP_STATUS_OK)
edouard@1364
  1647
        *keylist = _keylist;
edouard@1364
  1648
    else
edouard@1364
  1649
        free_stringlist(_keylist);
edouard@1364
  1650
    
edouard@1364
  1651
    goto the_end;
edouard@1364
  1652
    
edouard@1364
  1653
enomem:
edouard@1364
  1654
    free_stringlist(_keylist);
edouard@1364
  1655
    status = PEP_OUT_OF_MEMORY;
edouard@1364
  1656
    
edouard@1364
  1657
the_end:
edouard@1364
  1658
    return status;
edouard@1364
  1659
}
edouard@1364
  1660
edouard@1412
  1661
DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **keylist)
edouard@1412
  1662
{
edouard@1412
  1663
    return _own_keys_retrieve(session, keylist, 0);
edouard@1412
  1664
}
edouard@1412
  1665
edouard@1394
  1666
DYNAMIC_API PEP_STATUS set_own_key(
edouard@1394
  1667
       PEP_SESSION session,
vb@2535
  1668
       pEp_identity *me,
edouard@1394
  1669
       const char *fpr
edouard@1394
  1670
    )
edouard@1394
  1671
{
edouard@1394
  1672
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1394
  1673
    
vb@2535
  1674
    assert(session && me);
vb@2535
  1675
    assert(!EMPTYSTR(fpr));
vb@2535
  1676
    assert(!EMPTYSTR(me->address));
vb@2535
  1677
    assert(!EMPTYSTR(me->user_id));
vb@2535
  1678
    assert(!EMPTYSTR(me->username));
vb@2535
  1679
vb@2535
  1680
    if (!session || !me || EMPTYSTR(fpr) || EMPTYSTR(me->address) ||
vb@2535
  1681
            EMPTYSTR(me->user_id) || EMPTYSTR(me->username))
edouard@1394
  1682
        return PEP_ILLEGAL_VALUE;
vb@2535
  1683
vb@2535
  1684
    status = _myself(session, me, false, true);
vb@2535
  1685
    // we do not need a valid key but dislike other errors
vb@2535
  1686
    if (status != PEP_STATUS_OK && status != PEP_GET_KEY_FAILED && status != PEP_KEY_UNSUITABLE)
krista@2461
  1687
        return status;
vb@2535
  1688
    status = PEP_STATUS_OK;
vb@2535
  1689
 
vb@2535
  1690
    if (me->fpr)
vb@2535
  1691
        free(me->fpr);
vb@2535
  1692
    me->fpr = strdup(fpr);
vb@2535
  1693
    assert(me->fpr);
vb@2535
  1694
    if (!me->fpr)
vb@2535
  1695
        return PEP_OUT_OF_MEMORY;
krista@2461
  1696
krista@2548
  1697
    status = validate_fpr(session, me, false);
vb@2535
  1698
    if (status)
vb@2535
  1699
        return status;
vb@2535
  1700
vb@2535
  1701
    me->comm_type = PEP_ct_pEp;
vb@2535
  1702
    status = set_identity(session, me);
edouard@1394
  1703
    return status;
edouard@1394
  1704
}
krista@1357
  1705
krista@1357
  1706
PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr,
krista@1357
  1707
                             bool *has_private) {
krista@1357
  1708
krista@1357
  1709
    assert(session);
krista@1357
  1710
    assert(fpr);
krista@1357
  1711
    assert(has_private);
krista@1357
  1712
    
krista@1357
  1713
    if (!(session && fpr && has_private))
krista@1357
  1714
        return PEP_ILLEGAL_VALUE;
krista@1357
  1715
krista@1357
  1716
    return session->cryptotech[PEP_crypt_OpenPGP].contains_priv_key(session, fpr, has_private);
edouard@1385
  1717
}
krista@2471
  1718
krista@2471
  1719
PEP_STATUS add_mistrusted_key(PEP_SESSION session, const char* fpr)
krista@2471
  1720
{
krista@2471
  1721
    int result;
krista@2471
  1722
krista@2471
  1723
    assert(!EMPTYSTR(fpr));
krista@2471
  1724
    
krista@2471
  1725
    if (!(session) || EMPTYSTR(fpr))
krista@2471
  1726
        return PEP_ILLEGAL_VALUE;
krista@2471
  1727
krista@2471
  1728
    sqlite3_reset(session->add_mistrusted_key);
krista@2471
  1729
    sqlite3_bind_text(session->add_mistrusted_key, 1, fpr, -1,
krista@2471
  1730
            SQLITE_STATIC);
krista@2471
  1731
krista@2471
  1732
    result = sqlite3_step(session->add_mistrusted_key);
krista@2471
  1733
    sqlite3_reset(session->add_mistrusted_key);
krista@2471
  1734
krista@2471
  1735
    if (result != SQLITE_DONE)
krista@2471
  1736
        return PEP_CANNOT_SET_PGP_KEYPAIR; // FIXME: Better status?
krista@2471
  1737
krista@2471
  1738
    return PEP_STATUS_OK;
krista@2471
  1739
}
krista@2471
  1740
krista@2471
  1741
PEP_STATUS delete_mistrusted_key(PEP_SESSION session, const char* fpr)
krista@2471
  1742
{
krista@2471
  1743
    int result;
krista@2471
  1744
krista@2471
  1745
    assert(!EMPTYSTR(fpr));
krista@2471
  1746
    
krista@2471
  1747
    if (!(session) || EMPTYSTR(fpr))
krista@2471
  1748
        return PEP_ILLEGAL_VALUE;
krista@2471
  1749
krista@2471
  1750
    sqlite3_reset(session->delete_mistrusted_key);
krista@2471
  1751
    sqlite3_bind_text(session->delete_mistrusted_key, 1, fpr, -1,
krista@2471
  1752
            SQLITE_STATIC);
krista@2471
  1753
krista@2471
  1754
    result = sqlite3_step(session->delete_mistrusted_key);
krista@2471
  1755
    sqlite3_reset(session->delete_mistrusted_key);
krista@2471
  1756
krista@2471
  1757
    if (result != SQLITE_DONE)
krista@2471
  1758
        return PEP_UNKNOWN_ERROR; // FIXME: Better status?
krista@2471
  1759
krista@2471
  1760
    return PEP_STATUS_OK;
krista@2471
  1761
}
krista@2471
  1762
krista@2471
  1763
PEP_STATUS is_mistrusted_key(PEP_SESSION session, const char* fpr,
krista@2471
  1764
                             bool* mistrusted)
krista@2471
  1765
{
krista@2471
  1766
    PEP_STATUS status = PEP_STATUS_OK;
krista@2471
  1767
krista@2471
  1768
    assert(session);
krista@2471
  1769
    assert(!EMPTYSTR(fpr));
krista@2471
  1770
krista@2471
  1771
    if (!(session && fpr))
krista@2471
  1772
        return PEP_ILLEGAL_VALUE;
krista@2471
  1773
krista@2471
  1774
    *mistrusted = false;
krista@2471
  1775
krista@2471
  1776
    sqlite3_reset(session->is_mistrusted_key);
krista@2471
  1777
    sqlite3_bind_text(session->is_mistrusted_key, 1, fpr, -1, SQLITE_STATIC);
krista@2471
  1778
krista@2471
  1779
    int result;
krista@2471
  1780
krista@2471
  1781
    result = sqlite3_step(session->is_mistrusted_key);
krista@2471
  1782
    switch (result) {
krista@2471
  1783
    case SQLITE_ROW:
krista@2471
  1784
        *mistrusted = sqlite3_column_int(session->is_mistrusted_key, 0);
krista@2471
  1785
        status = PEP_STATUS_OK;
krista@2471
  1786
        break;
krista@2471
  1787
krista@2471
  1788
    default:
krista@2471
  1789
        status = PEP_UNKNOWN_ERROR;
krista@2471
  1790
    }
krista@2471
  1791
krista@2471
  1792
    sqlite3_reset(session->is_mistrusted_key);
krista@2471
  1793
    return status;
krista@2471
  1794
}
vb@2539
  1795
vb@2539
  1796
#ifdef USE_GPG
vb@2539
  1797
PEP_STATUS pgp_find_trusted_private_keys(
vb@2539
  1798
        PEP_SESSION session, stringlist_t **keylist
vb@2539
  1799
    );
vb@2539
  1800
vb@2539
  1801
enum _pgp_thing {
vb@2539
  1802
    _pgp_none = 0,
vb@2539
  1803
    _pgp_fpr,
vb@2539
  1804
    _pgp_email,
vb@2539
  1805
    _pgp_name
vb@2539
  1806
};
vb@2539
  1807
vb@2539
  1808
static enum _pgp_thing _pgp_thing_next(enum _pgp_thing thing)
vb@2539
  1809
{
vb@2539
  1810
    switch (thing) {
vb@2539
  1811
        case _pgp_fpr:
vb@2539
  1812
            return _pgp_email;
vb@2539
  1813
        case _pgp_email:
vb@2539
  1814
            return _pgp_name;
vb@2539
  1815
        case _pgp_name:
vb@2539
  1816
            return _pgp_fpr;
vb@2539
  1817
        default:
vb@2539
  1818
            return _pgp_fpr;
vb@2539
  1819
    }
vb@2539
  1820
}
vb@2539
  1821
vb@2539
  1822
PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) {
vb@2539
  1823
    assert(session);
vb@2539
  1824
    if (!session)
vb@2539
  1825
        return PEP_ILLEGAL_VALUE;
vb@2539
  1826
vb@2539
  1827
    stringlist_t* priv_keylist = NULL;
vb@2539
  1828
    PEP_STATUS status = PEP_STATUS_OK;
vb@2539
  1829
vb@2539
  1830
    // 1. get keys
vb@2539
  1831
    status = pgp_find_trusted_private_keys(session, &priv_keylist);
vb@2539
  1832
    if (status)
vb@2539
  1833
        return status;
vb@2539
  1834
vb@2539
  1835
    pEp_identity *identity = NULL;
vb@2539
  1836
    stringlist_t *_sl;
vb@2541
  1837
	
vb@2541
  1838
    char *fpr = NULL;
vb@2539
  1839
    enum _pgp_thing thing = _pgp_none;
vb@2539
  1840
    for (_sl = priv_keylist; _sl && _sl->value; _sl = _sl->next) {
vb@2539
  1841
        thing = _pgp_thing_next(thing);
vb@2539
  1842
        switch (thing) {
vb@2539
  1843
            case _pgp_fpr:
vb@2539
  1844
                identity = new_identity(NULL, NULL, PEP_OWN_USERID, NULL);
vb@2539
  1845
                if (!identity)
vb@2539
  1846
                    status = PEP_OUT_OF_MEMORY;
vb@2539
  1847
                identity->me = true;
vb@2539
  1848
                fpr = strdup(_sl->value);
vb@2539
  1849
                assert(fpr);
vb@2539
  1850
                if (!fpr) {
vb@2539
  1851
                    status = PEP_OUT_OF_MEMORY;
vb@2539
  1852
                    free_identity(identity);
vb@2539
  1853
                }
vb@2539
  1854
                break;
vb@2539
  1855
            case _pgp_email:
vb@2539
  1856
                assert(identity);
vb@2539
  1857
                identity->address = strdup(_sl->value);
vb@2539
  1858
                assert(identity->address);
vb@2539
  1859
                if (!identity->address) {
vb@2539
  1860
                    status = PEP_OUT_OF_MEMORY;
vb@2539
  1861
                    free_identity(identity);
vb@2539
  1862
                }
vb@2539
  1863
                break;
vb@2539
  1864
            case _pgp_name:
vb@2539
  1865
                assert(identity);
vb@2539
  1866
                identity->username = strdup(_sl->value);
vb@2539
  1867
                assert(identity->username);
vb@2539
  1868
                if (!identity->username)
vb@2539
  1869
                    status = PEP_OUT_OF_MEMORY;
vb@2539
  1870
                else
vb@2539
  1871
                    status = set_own_key(session, identity, fpr);
vb@2539
  1872
                free_identity(identity);
vb@2539
  1873
                identity = NULL;
vb@2539
  1874
                break;
vb@2539
  1875
            default:
vb@2539
  1876
                assert(0);
vb@2539
  1877
                free_identity(identity);
vb@2539
  1878
                status = PEP_UNKNOWN_ERROR;
vb@2539
  1879
        }
vb@2539
  1880
        if (status)
vb@2539
  1881
            break;
vb@2539
  1882
    }
vb@2539
  1883
    
vb@2539
  1884
    free_stringlist(priv_keylist);
vb@2539
  1885
    return status;
vb@2539
  1886
}
vb@2539
  1887
#endif // USE_GPG