src/keymanagement.c
author Edouard Tisserant <edouard@pep-project.org>
Fri, 28 Apr 2017 12:02:57 +0200
changeset 1738 a7c4c6241b93
parent 1610 1f07d18d8bcc
child 1749 32084f52dada
child 1752 6991834e731a
child 1753 01faac16cec6
permissions -rw-r--r--
update_identity() now takes PEP_ct_key_expired as a special case, and replaces it with actual key rating if not expired enymore. Otherwise, partner's rating with expired key was never comming back to normal, even if key was renewed.
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
edouard@1195
    15
#include "sync_fsm.h"
krista@1253
    16
#include "blacklist.h"
edouard@1195
    17
Edouard@439
    18
#ifndef EMPTYSTR
roker@500
    19
#define EMPTYSTR(STR) ((STR) == NULL || (STR)[0] == '\0')
vb@8
    20
#endif
vb@8
    21
vb@214
    22
#define KEY_EXPIRE_DELTA (60 * 60 * 24 * 365)
vb@214
    23
Edouard@774
    24
PEP_STATUS elect_pubkey(
Edouard@755
    25
        PEP_SESSION session, pEp_identity * identity
Edouard@755
    26
    )
Edouard@755
    27
{
Edouard@755
    28
    PEP_STATUS status;
roker@1559
    29
    stringlist_t *keylist = NULL;
krista@1342
    30
    char *_fpr = "";
Edouard@755
    31
    identity->comm_type = PEP_ct_unknown;
Edouard@755
    32
Edouard@755
    33
    status = find_keys(session, identity->address, &keylist);
Edouard@755
    34
    assert(status != PEP_OUT_OF_MEMORY);
Edouard@755
    35
    if (status == PEP_OUT_OF_MEMORY)
Edouard@755
    36
        return PEP_OUT_OF_MEMORY;
Edouard@755
    37
Edouard@755
    38
    stringlist_t *_keylist;
Edouard@755
    39
    for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
Edouard@755
    40
        PEP_comm_type _comm_type_key;
Edouard@755
    41
Edouard@755
    42
        status = get_key_rating(session, _keylist->value, &_comm_type_key);
Edouard@755
    43
        assert(status != PEP_OUT_OF_MEMORY);
Edouard@755
    44
        if (status == PEP_OUT_OF_MEMORY) {
Edouard@755
    45
            free_stringlist(keylist);
Edouard@755
    46
            return PEP_OUT_OF_MEMORY;
Edouard@755
    47
        }
Edouard@755
    48
Edouard@755
    49
        if (_comm_type_key != PEP_ct_compromized &&
Edouard@755
    50
            _comm_type_key != PEP_ct_unknown)
Edouard@755
    51
        {
Edouard@755
    52
            if (identity->comm_type == PEP_ct_unknown ||
Edouard@755
    53
                _comm_type_key > identity->comm_type)
Edouard@755
    54
            {
krista@1275
    55
                bool blacklisted;
krista@1275
    56
                status = blacklist_is_listed(session, _keylist->value, &blacklisted);
krista@1275
    57
                if (status == PEP_STATUS_OK && !blacklisted) {
krista@1275
    58
                    identity->comm_type = _comm_type_key;
krista@1275
    59
                    _fpr = _keylist->value;
krista@1275
    60
                }
Edouard@755
    61
            }
Edouard@755
    62
        }
Edouard@755
    63
    }
Edouard@755
    64
krista@1342
    65
    
krista@1342
    66
//    if (_fpr) {
krista@1342
    67
    free(identity->fpr);
Edouard@755
    68
krista@1342
    69
    identity->fpr = strdup(_fpr);
krista@1342
    70
    if (identity->fpr == NULL) {
krista@1342
    71
        free_stringlist(keylist);
krista@1342
    72
        return PEP_OUT_OF_MEMORY;
Edouard@755
    73
    }
krista@1342
    74
//    }
Edouard@755
    75
    free_stringlist(keylist);
Edouard@755
    76
    return PEP_STATUS_OK;
Edouard@755
    77
}
Edouard@755
    78
edouard@1406
    79
PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
edouard@1385
    80
edouard@1385
    81
DYNAMIC_API PEP_STATUS update_identity(
edouard@1385
    82
        PEP_SESSION session, pEp_identity * identity
vb@0
    83
    )
vb@0
    84
{
roker@1559
    85
    pEp_identity *stored_identity = NULL;
roker@1559
    86
    pEp_identity *temp_id = NULL;
vb@0
    87
    PEP_STATUS status;
vb@0
    88
vb@0
    89
    assert(session);
vb@0
    90
    assert(identity);
Edouard@439
    91
    assert(!EMPTYSTR(identity->address));
vb@0
    92
Edouard@439
    93
    if (!(session && identity && !EMPTYSTR(identity->address)))
vb@191
    94
        return PEP_ILLEGAL_VALUE;
vb@191
    95
vb@1078
    96
    if (identity->me || (identity->user_id && strcmp(identity->user_id, PEP_OWN_USERID) == 0)) {
edouard@1385
    97
        identity->me = true;
edouard@1406
    98
        return _myself(session, identity, false, true);
vb@1078
    99
    }
vb@1078
   100
Edouard@559
   101
    int _no_user_id = EMPTYSTR(identity->user_id);
edouard@1164
   102
    int _did_elect_new_key = 0;
Edouard@559
   103
Edouard@559
   104
    if (_no_user_id)
Edouard@559
   105
    {
vb@1015
   106
        status = get_identity(session, identity->address, PEP_OWN_USERID,
vb@1015
   107
                &stored_identity);
vb@1015
   108
        if (status == PEP_STATUS_OK) {
vb@1015
   109
            free_identity(stored_identity);
edouard@1406
   110
            return _myself(session, identity, false, true);
vb@1015
   111
        }
vb@1015
   112
Edouard@559
   113
        free(identity->user_id);
Edouard@559
   114
vb@591
   115
        identity->user_id = calloc(1, strlen(identity->address) + 6);
Edouard@562
   116
        if (!identity->user_id)
Edouard@562
   117
        {
Edouard@562
   118
            return PEP_OUT_OF_MEMORY;
Edouard@562
   119
        }
vb@983
   120
        snprintf(identity->user_id, strlen(identity->address) + 6,
Edouard@562
   121
                 "TOFU_%s", identity->address);
Edouard@559
   122
    }
vb@934
   123
 
Edouard@559
   124
    status = get_identity(session,
Edouard@559
   125
                          identity->address,
Edouard@559
   126
                          identity->user_id,
Edouard@559
   127
                          &stored_identity);
Edouard@559
   128
    
vb@0
   129
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   130
    if (status == PEP_OUT_OF_MEMORY)
Edouard@829
   131
        goto exit_free;
vb@0
   132
krista@1224
   133
    temp_id = identity_dup(identity);
krista@1220
   134
    
edouard@1501
   135
    /* We don't take given fpr. 
edouard@1501
   136
       In case there's no acceptable stored fpr, it will be elected. */
edouard@1501
   137
    free(temp_id->fpr);
edouard@1501
   138
    temp_id->fpr = NULL;
edouard@1501
   139
    temp_id->comm_type = PEP_ct_unknown;
edouard@1501
   140
            
edouard@1501
   141
    if (stored_identity) {
krista@1188
   142
        
edouard@1501
   143
        bool dont_use_stored_fpr = true;
krista@1220
   144
krista@1220
   145
        /* if we have a stored_identity fpr */
edouard@1501
   146
        if (!EMPTYSTR(stored_identity->fpr)) {
edouard@1501
   147
            status = blacklist_is_listed(session, stored_identity->fpr, &dont_use_stored_fpr);
krista@1220
   148
            if (status != PEP_STATUS_OK)
edouard@1501
   149
                dont_use_stored_fpr = true; 
krista@1220
   150
        }
krista@1188
   151
            
krista@1220
   152
edouard@1501
   153
        if (!dont_use_stored_fpr) {
edouard@1522
   154
            /* Check stored comm_type */
edouard@1522
   155
            PEP_comm_type _comm_type_key;
edouard@1522
   156
            status = get_key_rating(session, stored_identity->fpr, &_comm_type_key);
edouard@1522
   157
            assert(status != PEP_OUT_OF_MEMORY);
edouard@1522
   158
            if (status == PEP_OUT_OF_MEMORY) {
krista@1188
   159
                goto exit_free;
krista@1220
   160
            }
edouard@1522
   161
            if (status == PEP_KEY_NOT_FOUND){
edouard@1522
   162
                /* stored key was deleted from keyring. any other candidate ?*/
edouard@1522
   163
                status = elect_pubkey(session, temp_id);
edouard@1522
   164
                if (status != PEP_STATUS_OK) {
edouard@1522
   165
                    goto exit_free;
edouard@1522
   166
                } else {
edouard@1522
   167
                    _did_elect_new_key = 1;
edouard@1522
   168
                }
edouard@1522
   169
            } else {
edouard@1522
   170
                temp_id->fpr = strdup(stored_identity->fpr);
edouard@1522
   171
                assert(temp_id->fpr);
edouard@1522
   172
                if (temp_id->fpr == NULL) {
edouard@1522
   173
                    status = PEP_OUT_OF_MEMORY;
edouard@1522
   174
                    goto exit_free;
edouard@1522
   175
                }
edouard@1501
   176
edouard@1522
   177
                if (_comm_type_key < PEP_ct_unconfirmed_encryption) {
edouard@1522
   178
                    /* if key not good anymore, 
edouard@1522
   179
                       downgrade eventually trusted comm_type */
edouard@1501
   180
                    temp_id->comm_type = _comm_type_key;
edouard@1522
   181
                } else {
edouard@1738
   182
                    /* otherwise take stored comm_type as-is except if 
edouard@1738
   183
                       is unknown or is expired (but key not expired anymore) */
edouard@1522
   184
                    temp_id->comm_type = stored_identity->comm_type;
edouard@1738
   185
                    if (temp_id->comm_type == PEP_ct_unknown ||
edouard@1738
   186
                        temp_id->comm_type == PEP_ct_key_expired) {
edouard@1522
   187
                        temp_id->comm_type = _comm_type_key;
edouard@1522
   188
                    }
edouard@1501
   189
                }
edouard@1501
   190
            }
krista@1220
   191
        }
edouard@1501
   192
        else {
edouard@1501
   193
            status = elect_pubkey(session, temp_id);
edouard@1522
   194
            if (status != PEP_STATUS_OK){
edouard@1501
   195
                goto exit_free;
edouard@1522
   196
            } else {
krista@1188
   197
                _did_elect_new_key = 1;
krista@1188
   198
            }
krista@1188
   199
        }
krista@1188
   200
        
krista@1220
   201
        /* ok, from here on out, use temp_id */
krista@1220
   202
        
krista@1220
   203
        
krista@1220
   204
        /* At this point, we either have a non-blacklisted fpr we can work */
roker@1559
   205
        /* with, or we've got nada.                                        */
edouard@1501
   206
edouard@1501
   207
        if (EMPTYSTR(temp_id->fpr)) {
edouard@1501
   208
            /* nada : set comm_type accordingly */
krista@1243
   209
            temp_id->comm_type = PEP_ct_key_not_found;
krista@1243
   210
        }
krista@1243
   211
        
krista@1220
   212
        if (EMPTYSTR(temp_id->username)) {
krista@1220
   213
            free(temp_id->username);
krista@1220
   214
            temp_id->username = strdup(stored_identity->username);
krista@1220
   215
            assert(temp_id->username);
krista@1220
   216
            if (temp_id->username == NULL){
Edouard@829
   217
                status = PEP_OUT_OF_MEMORY;
Edouard@829
   218
                goto exit_free;
Edouard@829
   219
            }
vb@22
   220
        }
vb@22
   221
krista@1220
   222
        if (temp_id->lang[0] == 0) {
krista@1220
   223
            temp_id->lang[0] = stored_identity->lang[0];
krista@1220
   224
            temp_id->lang[1] = stored_identity->lang[1];
krista@1220
   225
            temp_id->lang[2] = 0;
vb@21
   226
        }
vb@932
   227
krista@1220
   228
        temp_id->flags = stored_identity->flags;
vb@21
   229
    }
vb@21
   230
    else /* stored_identity == NULL */ {
krista@1220
   231
        temp_id->flags = 0;
vb@934
   232
edouard@1501
   233
        /* We elect a pubkey */
edouard@1501
   234
        status = elect_pubkey(session, temp_id);
edouard@1501
   235
        if (status != PEP_STATUS_OK)
edouard@1501
   236
            goto exit_free;
edouard@1501
   237
        
edouard@1501
   238
        /* Work with the elected key */
krista@1220
   239
        if (!EMPTYSTR(temp_id->fpr)) {
krista@1196
   240
            
edouard@1502
   241
            PEP_comm_type _comm_type_key = temp_id->comm_type;
edouard@1502
   242
            
edouard@1502
   243
            _did_elect_new_key = 1;
vb@21
   244
edouard@1502
   245
            // We don't want to lose a previous trust entry!!!
edouard@1502
   246
            status = get_trust(session, temp_id);
edouard@1501
   247
edouard@1502
   248
            bool has_trust_status = (status == PEP_STATUS_OK);
vb@21
   249
edouard@1502
   250
            if (!has_trust_status)
edouard@1502
   251
                temp_id->comm_type = _comm_type_key;
vb@21
   252
        }
vb@21
   253
    }
vb@21
   254
edouard@1501
   255
    if (temp_id->fpr == NULL) {
krista@1220
   256
        temp_id->fpr = strdup("");
edouard@1501
   257
        if (temp_id->fpr == NULL) {
edouard@1501
   258
            status = PEP_OUT_OF_MEMORY;
edouard@1501
   259
            goto exit_free;
edouard@1501
   260
        }
edouard@1501
   261
    }
krista@1193
   262
    
krista@1193
   263
    
vb@21
   264
    status = PEP_STATUS_OK;
vb@21
   265
krista@1220
   266
    if (temp_id->comm_type != PEP_ct_unknown && !EMPTYSTR(temp_id->user_id)) {
vb@22
   267
krista@1220
   268
        if (EMPTYSTR(temp_id->username)) { // mitigate
krista@1220
   269
            free(temp_id->username);
krista@1220
   270
            temp_id->username = strdup("anonymous");
krista@1220
   271
            assert(temp_id->username);
krista@1220
   272
            if (temp_id->username == NULL){
Edouard@829
   273
                status = PEP_OUT_OF_MEMORY;
Edouard@829
   274
                goto exit_free;
Edouard@829
   275
            }
vb@0
   276
        }
vb@8
   277
Edouard@755
   278
        // Identity doesn't get stored if call was just about checking existing
Edouard@755
   279
        // user by address (i.e. no user id given but already stored)
krista@1223
   280
        if (!(_no_user_id && stored_identity) || _did_elect_new_key)
Edouard@559
   281
        {
krista@1220
   282
            status = set_identity(session, temp_id);
Edouard@559
   283
            assert(status == PEP_STATUS_OK);
Edouard@559
   284
            if (status != PEP_STATUS_OK) {
Edouard@829
   285
                goto exit_free;
Edouard@559
   286
            }
Edouard@499
   287
        }
vb@8
   288
    }
vb@8
   289
krista@1220
   290
    if (temp_id->comm_type != PEP_ct_compromized &&
krista@1220
   291
            temp_id->comm_type < PEP_ct_strong_but_unconfirmed)
vb@297
   292
        if (session->examine_identity)
krista@1220
   293
            session->examine_identity(temp_id, session->examine_management);
krista@1220
   294
    
krista@1220
   295
    /* ok, we got to the end. So we can assign the output identity */
krista@1220
   296
    free(identity->address);
krista@1220
   297
    identity->address = strdup(temp_id->address);
krista@1220
   298
    free(identity->fpr);
krista@1220
   299
    identity->fpr = strdup(temp_id->fpr);
krista@1220
   300
    free(identity->user_id);
krista@1220
   301
    identity->user_id = strdup(temp_id->user_id);
krista@1220
   302
    free(identity->username);
krista@1492
   303
    identity->username = strdup(temp_id->username ? temp_id->username : "anonymous");
krista@1220
   304
    identity->comm_type = temp_id->comm_type;
krista@1220
   305
    identity->lang[0] = temp_id->lang[0];
krista@1220
   306
    identity->lang[1] = temp_id->lang[1];
krista@1220
   307
    identity->lang[2] = 0;
krista@1220
   308
    identity->me = temp_id->me;
krista@1220
   309
    identity->flags = temp_id->flags;
vb@297
   310
Edouard@829
   311
exit_free :
roker@1559
   312
    free_identity(stored_identity);
roker@1559
   313
    free_identity(temp_id);
krista@1220
   314
    
vb@8
   315
    return status;
vb@0
   316
}
vb@0
   317
Edouard@774
   318
PEP_STATUS elect_ownkey(
krista@1194
   319
        PEP_SESSION session, pEp_identity * identity
Edouard@774
   320
    )
Edouard@774
   321
{
Edouard@774
   322
    PEP_STATUS status;
Edouard@774
   323
    stringlist_t *keylist = NULL;
Edouard@774
   324
Edouard@774
   325
    free(identity->fpr);
Edouard@774
   326
    identity->fpr = NULL;
Edouard@774
   327
krista@1357
   328
    status = find_private_keys(session, identity->address, &keylist);
Edouard@774
   329
    assert(status != PEP_OUT_OF_MEMORY);
Edouard@774
   330
    if (status == PEP_OUT_OF_MEMORY)
Edouard@774
   331
        return PEP_OUT_OF_MEMORY;
Edouard@774
   332
    
Edouard@774
   333
    if (keylist != NULL && keylist->value != NULL)
Edouard@774
   334
    {
Edouard@774
   335
        char *_fpr = NULL;
Edouard@774
   336
        identity->comm_type = PEP_ct_unknown;
Edouard@774
   337
Edouard@774
   338
        stringlist_t *_keylist;
Edouard@774
   339
        for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
Edouard@774
   340
            bool is_own = false;
Edouard@774
   341
            
Edouard@774
   342
            if (session->use_only_own_private_keys)
Edouard@774
   343
            {
Edouard@774
   344
                status = own_key_is_listed(session, _keylist->value, &is_own);
Edouard@774
   345
                assert(status == PEP_STATUS_OK);
Edouard@774
   346
                if (status != PEP_STATUS_OK) {
Edouard@774
   347
                    free_stringlist(keylist);
Edouard@774
   348
                    return status;
Edouard@774
   349
                }
Edouard@774
   350
            }
Edouard@774
   351
Edouard@774
   352
            // TODO : also accept synchronized device group keys ?
Edouard@774
   353
            
Edouard@774
   354
            if (!session->use_only_own_private_keys || is_own)
Edouard@774
   355
            {
Edouard@774
   356
                PEP_comm_type _comm_type_key;
Edouard@774
   357
                
Edouard@774
   358
                status = get_key_rating(session, _keylist->value, &_comm_type_key);
Edouard@774
   359
                assert(status != PEP_OUT_OF_MEMORY);
Edouard@774
   360
                if (status == PEP_OUT_OF_MEMORY) {
Edouard@774
   361
                    free_stringlist(keylist);
Edouard@774
   362
                    return PEP_OUT_OF_MEMORY;
Edouard@774
   363
                }
Edouard@774
   364
                
Edouard@774
   365
                if (_comm_type_key != PEP_ct_compromized &&
Edouard@774
   366
                    _comm_type_key != PEP_ct_unknown)
Edouard@774
   367
                {
Edouard@774
   368
                    if (identity->comm_type == PEP_ct_unknown ||
Edouard@774
   369
                        _comm_type_key > identity->comm_type)
Edouard@774
   370
                    {
Edouard@774
   371
                        identity->comm_type = _comm_type_key;
Edouard@774
   372
                        _fpr = _keylist->value;
Edouard@774
   373
                    }
Edouard@774
   374
                }
Edouard@774
   375
            }
Edouard@774
   376
        }
Edouard@774
   377
        
Edouard@774
   378
        if (_fpr)
Edouard@774
   379
        {
Edouard@774
   380
            identity->fpr = strdup(_fpr);
Edouard@774
   381
            assert(identity->fpr);
Edouard@774
   382
            if (identity->fpr == NULL)
Edouard@774
   383
            {
Edouard@774
   384
                free_stringlist(keylist);
Edouard@774
   385
                return PEP_OUT_OF_MEMORY;
Edouard@774
   386
            }
Edouard@774
   387
        }
Edouard@774
   388
        free_stringlist(keylist);
Edouard@774
   389
    }
Edouard@774
   390
    return PEP_STATUS_OK;
Edouard@774
   391
}
Edouard@774
   392
krista@1357
   393
PEP_STATUS _has_usable_priv_key(PEP_SESSION session, char* fpr,
krista@1357
   394
                                bool* is_usable) {
krista@1357
   395
    
krista@1357
   396
    bool dont_use_fpr = true;
krista@1357
   397
    
krista@1357
   398
    PEP_STATUS status = blacklist_is_listed(session, fpr, &dont_use_fpr);
krista@1371
   399
    if (status == PEP_STATUS_OK && !dont_use_fpr) {
krista@1357
   400
        // Make sure there is a *private* key associated with this fpr
krista@1357
   401
        bool has_private = false;
krista@1357
   402
        status = contains_priv_key(session, fpr, &has_private);
krista@1371
   403
krista@1371
   404
        if (status == PEP_STATUS_OK)
krista@1371
   405
            dont_use_fpr = !has_private;
krista@1357
   406
    }
krista@1357
   407
    
krista@1357
   408
    *is_usable = !dont_use_fpr;
krista@1357
   409
    
krista@1357
   410
    return status;
krista@1357
   411
}
krista@1357
   412
edouard@1406
   413
PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags)
vb@0
   414
{
roker@1559
   415
    pEp_identity *stored_identity = NULL;
vb@0
   416
    PEP_STATUS status;
vb@0
   417
vb@0
   418
    assert(session);
vb@0
   419
    assert(identity);
vb@1044
   420
    assert(!EMPTYSTR(identity->address));
vb@1043
   421
Edouard@658
   422
    assert(EMPTYSTR(identity->user_id) ||
Edouard@658
   423
           strcmp(identity->user_id, PEP_OWN_USERID) == 0);
vb@0
   424
vb@1044
   425
    if (!(session && identity && !EMPTYSTR(identity->address) &&
vb@1043
   426
            (EMPTYSTR(identity->user_id) ||
vb@1043
   427
            strcmp(identity->user_id, PEP_OWN_USERID) == 0)))
vb@191
   428
        return PEP_ILLEGAL_VALUE;
vb@191
   429
vb@0
   430
    identity->comm_type = PEP_ct_pEp;
vb@0
   431
    identity->me = true;
edouard@1406
   432
    if(ignore_flags)
edouard@1406
   433
        identity->flags = 0;
Edouard@658
   434
    
vb@1043
   435
    if (EMPTYSTR(identity->user_id))
Edouard@658
   436
    {
Edouard@658
   437
        free(identity->user_id);
Edouard@658
   438
        identity->user_id = strdup(PEP_OWN_USERID);
Edouard@658
   439
        assert(identity->user_id);
Edouard@658
   440
        if (identity->user_id == NULL)
Edouard@658
   441
            return PEP_OUT_OF_MEMORY;
Edouard@658
   442
    }
vb@0
   443
edouard@1488
   444
    if (EMPTYSTR(identity->username))
edouard@1488
   445
    {
edouard@1488
   446
        free(identity->username);
edouard@1488
   447
        identity->username = strdup("anonymous");
edouard@1488
   448
        assert(identity->username);
edouard@1488
   449
        if (identity->username == NULL)
edouard@1488
   450
            return PEP_OUT_OF_MEMORY;
edouard@1488
   451
    }
edouard@1488
   452
vb@215
   453
    DEBUG_LOG("myself", "debug", identity->address);
vb@1044
   454
 
Edouard@560
   455
    status = get_identity(session,
Edouard@560
   456
                          identity->address,
Edouard@560
   457
                          identity->user_id,
Edouard@560
   458
                          &stored_identity);
Edouard@560
   459
    
vb@0
   460
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   461
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   462
        return PEP_OUT_OF_MEMORY;
krista@1357
   463
krista@1357
   464
    bool dont_use_stored_fpr = true;
krista@1357
   465
    bool dont_use_input_fpr = true;
krista@1359
   466
        
Edouard@560
   467
    if (stored_identity)
Edouard@560
   468
    {
Edouard@560
   469
        if (EMPTYSTR(identity->fpr)) {
krista@1352
   470
            
krista@1357
   471
            bool has_private = false;
krista@1352
   472
            
krista@1357
   473
            status = _has_usable_priv_key(session, stored_identity->fpr, &has_private); 
krista@1352
   474
            
krista@1371
   475
            // N.B. has_private is never true if the returned status is not PEP_STATUS_OK
krista@1357
   476
            if (has_private) {
krista@1357
   477
                identity->fpr = strdup(stored_identity->fpr);
krista@1357
   478
                assert(identity->fpr);
krista@1357
   479
                if (identity->fpr == NULL)
krista@1357
   480
                {
krista@1357
   481
                    return PEP_OUT_OF_MEMORY;
krista@1357
   482
                }
krista@1357
   483
                dont_use_stored_fpr = false;
Edouard@560
   484
            }
Edouard@560
   485
        }
krista@1357
   486
        
edouard@1406
   487
        identity->flags = (identity->flags & 255) | stored_identity->flags;
edouard@1367
   488
        free_identity(stored_identity);
Edouard@588
   489
    }
krista@1357
   490
    
krista@1357
   491
    if (dont_use_stored_fpr && !EMPTYSTR(identity->fpr))
Edouard@588
   492
    {
Edouard@588
   493
        // App must have a good reason to give fpr, such as explicit
Edouard@588
   494
        // import of private key, or similar.
Edouard@588
   495
Edouard@658
   496
        // Take given fpr as-is.
vb@934
   497
krista@1357
   498
        // BUT:
krista@1357
   499
        // First check to see if it's blacklisted or private part is missing?
krista@1357
   500
        bool has_private = false;
krista@1357
   501
        
krista@1357
   502
        status = _has_usable_priv_key(session, identity->fpr, &has_private); 
krista@1357
   503
        
krista@1371
   504
        // N.B. has_private is never true if the returned status is not PEP_STATUS_OK
krista@1357
   505
        if (has_private) {
krista@1357
   506
            dont_use_input_fpr = false;
krista@1357
   507
        }
Edouard@560
   508
    }
krista@1357
   509
    
krista@1357
   510
    // Ok, we failed to get keys either way, so let's elect one.
krista@1357
   511
    if (dont_use_input_fpr && dont_use_stored_fpr)
Edouard@560
   512
    {
Edouard@774
   513
        status = elect_ownkey(session, identity);
Edouard@774
   514
        assert(status == PEP_STATUS_OK);
Edouard@774
   515
        if (status != PEP_STATUS_OK) {
Edouard@774
   516
            return status;
Edouard@560
   517
        }
vb@934
   518
krista@1357
   519
        bool has_private = false;
krista@1359
   520
        if (identity->fpr) {
krista@1359
   521
            // ok, we elected something.
krista@1359
   522
            // elect_ownkey only returns private keys, so we don't check again.
krista@1359
   523
            // Check to see if it's blacklisted
krista@1359
   524
            bool listed;
krista@1359
   525
            status = blacklist_is_listed(session, identity->fpr, &listed); 
krista@1371
   526
krista@1371
   527
            if (status == PEP_STATUS_OK)
krista@1371
   528
                has_private = !listed;
krista@1359
   529
        }
krista@1357
   530
        
krista@1357
   531
        if (has_private) {
krista@1357
   532
            dont_use_input_fpr = false;
krista@1357
   533
        }
krista@1357
   534
        else { // OK, we've tried everything. Time to generate new keys.
krista@1359
   535
            free(identity->fpr); // It can stay in this state (unallocated) because we'll generate a new key 
krista@1359
   536
            identity->fpr = NULL;
krista@1357
   537
        }
Edouard@560
   538
    }
Edouard@695
   539
Edouard@695
   540
    bool revoked = false;
Edouard@695
   541
    char *r_fpr = NULL;
Edouard@695
   542
    if (!EMPTYSTR(identity->fpr))
Edouard@695
   543
    {
Edouard@695
   544
        status = key_revoked(session, identity->fpr, &revoked);
Edouard@775
   545
Edouard@775
   546
        // Forces re-election if key is missing and own-key-only not forced
Edouard@775
   547
        if (!session->use_only_own_private_keys && status == PEP_KEY_NOT_FOUND) 
Edouard@775
   548
        {
Edouard@775
   549
            status = elect_ownkey(session, identity);
Edouard@775
   550
            assert(status == PEP_STATUS_OK);
Edouard@775
   551
            if (status != PEP_STATUS_OK) {
Edouard@775
   552
                return status;
Edouard@775
   553
            }
Edouard@775
   554
        } 
Edouard@775
   555
        else if (status != PEP_STATUS_OK) 
Edouard@775
   556
        {
Edouard@695
   557
            return status;
Edouard@695
   558
        }
Edouard@695
   559
    }
edouard@1140
   560
   
edouard@1140
   561
    bool new_key_generated = false;
edouard@1140
   562
Edouard@695
   563
    if (EMPTYSTR(identity->fpr) || revoked)
Edouard@695
   564
    {        
edouard@1385
   565
        if(!do_keygen){
edouard@1385
   566
            return PEP_GET_KEY_FAILED;
edouard@1385
   567
        }
edouard@1385
   568
Edouard@695
   569
        if(revoked)
Edouard@695
   570
        {
Edouard@697
   571
            r_fpr = identity->fpr;
Edouard@697
   572
            identity->fpr = NULL;
Edouard@695
   573
        }
Edouard@560
   574
        
vb@215
   575
        DEBUG_LOG("generating key pair", "debug", identity->address);
vb@0
   576
        status = generate_keypair(session, identity);
vb@0
   577
        assert(status != PEP_OUT_OF_MEMORY);
vb@0
   578
        if (status != PEP_STATUS_OK) {
vb@0
   579
            char buf[11];
vb@0
   580
            snprintf(buf, 11, "%d", status);
vb@215
   581
            DEBUG_LOG("generating key pair failed", "debug", buf);
Edouard@695
   582
            if(revoked && r_fpr)
Edouard@695
   583
                free(r_fpr);
vb@0
   584
            return status;
vb@0
   585
        }
edouard@1140
   586
edouard@1140
   587
        new_key_generated = true;
Edouard@560
   588
        
Edouard@695
   589
        if(revoked)
Edouard@695
   590
        {
Edouard@695
   591
            status = set_revoked(session, r_fpr,
Edouard@695
   592
                                 identity->fpr, time(NULL));
Edouard@695
   593
            free(r_fpr);
Edouard@695
   594
            if (status != PEP_STATUS_OK) {
Edouard@695
   595
                return status;
Edouard@695
   596
            }
Edouard@588
   597
        }
vb@0
   598
    }
Edouard@560
   599
    else
Edouard@560
   600
    {
vb@214
   601
        bool expired;
Edouard@701
   602
        status = key_expired(session, identity->fpr, 
Edouard@701
   603
                             time(NULL) + (7*24*3600), // In a week
Edouard@701
   604
                             &expired);
Edouard@701
   605
vb@214
   606
        assert(status == PEP_STATUS_OK);
Edouard@499
   607
        if (status != PEP_STATUS_OK) {
Edouard@588
   608
            return status;
Edouard@499
   609
        }
vb@214
   610
vb@214
   611
        if (status == PEP_STATUS_OK && expired) {
vb@214
   612
            timestamp *ts = new_timestamp(time(NULL) + KEY_EXPIRE_DELTA);
Edouard@560
   613
            renew_key(session, identity->fpr, ts);
vb@214
   614
            free_timestamp(ts);
vb@214
   615
        }
vb@214
   616
    }
vb@0
   617
krista@1353
   618
    if (!identity->username)
krista@1353
   619
        identity->username = strdup("");
krista@1353
   620
    
vb@0
   621
    status = set_identity(session, identity);
vb@0
   622
    assert(status == PEP_STATUS_OK);
Edouard@499
   623
    if (status != PEP_STATUS_OK) {
Edouard@588
   624
        return status;
Edouard@499
   625
    }
vb@0
   626
edouard@1145
   627
    if(new_key_generated)
edouard@1145
   628
    {
edouard@1145
   629
        // if a state machine for keysync is in place, inject notify
edouard@1195
   630
        status = inject_DeviceState_event(session, KeyGen, NULL, NULL);
edouard@1299
   631
        if (status == PEP_OUT_OF_MEMORY){
edouard@1299
   632
            return PEP_OUT_OF_MEMORY;
edouard@1299
   633
        }
edouard@1145
   634
    }
edouard@1140
   635
vb@0
   636
    return PEP_STATUS_OK;
vb@0
   637
}
vb@0
   638
edouard@1385
   639
DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
edouard@1385
   640
{
edouard@1406
   641
    return _myself(session, identity, true, false);
edouard@1385
   642
}
edouard@1385
   643
vb@296
   644
DYNAMIC_API PEP_STATUS register_examine_function(
vb@292
   645
        PEP_SESSION session, 
vb@292
   646
        examine_identity_t examine_identity,
vb@292
   647
        void *management
vb@292
   648
    )
vb@292
   649
{
vb@292
   650
    assert(session);
vb@292
   651
    if (!session)
vb@292
   652
        return PEP_ILLEGAL_VALUE;
vb@292
   653
vb@292
   654
    session->examine_management = management;
vb@292
   655
    session->examine_identity = examine_identity;
vb@292
   656
vb@292
   657
    return PEP_STATUS_OK;
vb@292
   658
}
vb@292
   659
vb@0
   660
DYNAMIC_API PEP_STATUS do_keymanagement(
vb@0
   661
        retrieve_next_identity_t retrieve_next_identity,
vb@0
   662
        void *management
vb@0
   663
    )
vb@0
   664
{
vb@0
   665
    PEP_SESSION session;
vb@0
   666
    pEp_identity *identity;
Edouard@499
   667
    PEP_STATUS status;
vb@0
   668
Edouard@499
   669
    assert(retrieve_next_identity);
Edouard@499
   670
    assert(management);
Edouard@499
   671
Edouard@499
   672
    if (!retrieve_next_identity || !management)
Edouard@499
   673
        return PEP_ILLEGAL_VALUE;
Edouard@499
   674
Edouard@499
   675
    status = init(&session);
vb@0
   676
    assert(status == PEP_STATUS_OK);
vb@0
   677
    if (status != PEP_STATUS_OK)
vb@0
   678
        return status;
vb@0
   679
vb@0
   680
    log_event(session, "keymanagement thread started", "pEp engine", NULL, NULL);
vb@0
   681
Edouard@499
   682
    while ((identity = retrieve_next_identity(management))) 
Edouard@499
   683
    {
vb@0
   684
        assert(identity->address);
Edouard@499
   685
        if(identity->address)
Edouard@499
   686
        {
Edouard@499
   687
            DEBUG_LOG("do_keymanagement", "retrieve_next_identity", identity->address);
Edouard@499
   688
Edouard@499
   689
            if (identity->me) {
Edouard@499
   690
                status = myself(session, identity);
Edouard@499
   691
            } else {
Edouard@499
   692
                status = recv_key(session, identity->address);
Edouard@499
   693
            }
Edouard@499
   694
vb@0
   695
            assert(status != PEP_OUT_OF_MEMORY);
Edouard@499
   696
            if(status == PEP_OUT_OF_MEMORY)
Edouard@499
   697
                return PEP_OUT_OF_MEMORY;
vb@0
   698
        }
vb@0
   699
        free_identity(identity);
vb@0
   700
    }
vb@0
   701
vb@0
   702
    log_event(session, "keymanagement thread shutdown", "pEp engine", NULL, NULL);
vb@0
   703
vb@0
   704
    release(session);
vb@0
   705
    return PEP_STATUS_OK;
vb@0
   706
}
vb@0
   707
krista@1213
   708
DYNAMIC_API PEP_STATUS key_mistrusted(
vb@357
   709
        PEP_SESSION session,
vb@357
   710
        pEp_identity *ident
vb@357
   711
    )
vb@215
   712
{
vb@218
   713
    PEP_STATUS status = PEP_STATUS_OK;
vb@218
   714
vb@215
   715
    assert(session);
vb@357
   716
    assert(ident);
Edouard@439
   717
    assert(!EMPTYSTR(ident->fpr));
vb@215
   718
vb@357
   719
    if (!(session && ident && ident->fpr))
vb@215
   720
        return PEP_ILLEGAL_VALUE;
vb@215
   721
vb@357
   722
    if (ident->me)
Edouard@697
   723
    {
vb@357
   724
        revoke_key(session, ident->fpr, NULL);
Edouard@697
   725
        myself(session, ident);
Edouard@697
   726
    }
Edouard@697
   727
    else
Edouard@697
   728
    {
Edouard@697
   729
        status = mark_as_compromized(session, ident->fpr);
Edouard@697
   730
    }
vb@218
   731
vb@218
   732
    return status;
vb@215
   733
}
vb@215
   734
Edouard@410
   735
DYNAMIC_API PEP_STATUS key_reset_trust(
Edouard@410
   736
        PEP_SESSION session,
Edouard@410
   737
        pEp_identity *ident
Edouard@410
   738
    )
Edouard@410
   739
{
Edouard@410
   740
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@410
   741
Edouard@410
   742
    assert(session);
Edouard@410
   743
    assert(ident);
vb@420
   744
    assert(!ident->me);
Edouard@439
   745
    assert(!EMPTYSTR(ident->fpr));
Edouard@439
   746
    assert(!EMPTYSTR(ident->address));
Edouard@439
   747
    assert(!EMPTYSTR(ident->user_id));
Edouard@410
   748
vb@420
   749
    if (!(session && ident && !ident->me && ident->fpr && ident->address &&
vb@420
   750
            ident->user_id))
Edouard@410
   751
        return PEP_ILLEGAL_VALUE;
Edouard@410
   752
vb@420
   753
    status = update_identity(session, ident);
vb@420
   754
    if (status != PEP_STATUS_OK)
vb@420
   755
        return status;
Edouard@410
   756
Edouard@442
   757
    if (ident->comm_type == PEP_ct_mistrusted)
vb@421
   758
        ident->comm_type = PEP_ct_unknown;
vb@421
   759
    else
vb@421
   760
        ident->comm_type &= ~PEP_ct_confirmed;
vb@421
   761
vb@420
   762
    status = set_identity(session, ident);
vb@421
   763
    if (status != PEP_STATUS_OK)
vb@421
   764
        return status;
vb@421
   765
vb@422
   766
    if (ident->comm_type == PEP_ct_unknown)
vb@422
   767
        status = update_identity(session, ident);
Edouard@410
   768
    return status;
Edouard@410
   769
}
Edouard@410
   770
vb@354
   771
DYNAMIC_API PEP_STATUS trust_personal_key(
vb@354
   772
        PEP_SESSION session,
vb@354
   773
        pEp_identity *ident
vb@354
   774
    )
vb@354
   775
{
vb@354
   776
    PEP_STATUS status = PEP_STATUS_OK;
vb@354
   777
vb@354
   778
    assert(session);
vb@354
   779
    assert(ident);
Edouard@439
   780
    assert(!EMPTYSTR(ident->address));
Edouard@439
   781
    assert(!EMPTYSTR(ident->user_id));
Edouard@439
   782
    assert(!EMPTYSTR(ident->fpr));
krista@1610
   783
//    assert(!ident->me);
vb@354
   784
Edouard@439
   785
    if (!ident || EMPTYSTR(ident->address) || EMPTYSTR(ident->user_id) ||
krista@1610
   786
            EMPTYSTR(ident->fpr)) // || ident->me)
vb@354
   787
        return PEP_ILLEGAL_VALUE;
vb@354
   788
vb@354
   789
    status = update_identity(session, ident);
vb@354
   790
    if (status != PEP_STATUS_OK)
vb@354
   791
        return status;
vb@354
   792
vb@356
   793
    if (ident->comm_type > PEP_ct_strong_but_unconfirmed) {
vb@356
   794
        ident->comm_type |= PEP_ct_confirmed;
Edouard@488
   795
        status = set_identity(session, ident);
vb@356
   796
    }
vb@356
   797
    else {
vb@356
   798
        // MISSING: S/MIME has to be handled depending on trusted CAs
vb@370
   799
        status = PEP_CANNOT_SET_TRUST;
vb@356
   800
    }
vb@354
   801
vb@354
   802
    return status;
vb@354
   803
}
vb@354
   804
Edouard@584
   805
DYNAMIC_API PEP_STATUS own_key_is_listed(
vb@955
   806
        PEP_SESSION session,
vb@955
   807
        const char *fpr,
vb@955
   808
        bool *listed
vb@955
   809
    )
Edouard@584
   810
{
Edouard@584
   811
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@584
   812
    int count;
Edouard@584
   813
    
Edouard@584
   814
    assert(session && fpr && fpr[0] && listed);
Edouard@584
   815
    
Edouard@584
   816
    if (!(session && fpr && fpr[0] && listed))
Edouard@584
   817
        return PEP_ILLEGAL_VALUE;
Edouard@584
   818
    
Edouard@584
   819
    *listed = false;
Edouard@584
   820
    
Edouard@584
   821
    sqlite3_reset(session->own_key_is_listed);
Edouard@584
   822
    sqlite3_bind_text(session->own_key_is_listed, 1, fpr, -1, SQLITE_STATIC);
Edouard@584
   823
    
Edouard@584
   824
    int result;
Edouard@584
   825
    
Edouard@584
   826
    result = sqlite3_step(session->own_key_is_listed);
Edouard@584
   827
    switch (result) {
Edouard@584
   828
        case SQLITE_ROW:
Edouard@584
   829
            count = sqlite3_column_int(session->own_key_is_listed, 0);
Edouard@584
   830
            *listed = count > 0;
Edouard@584
   831
            status = PEP_STATUS_OK;
Edouard@584
   832
            break;
Edouard@584
   833
            
Edouard@584
   834
        default:
Edouard@584
   835
            status = PEP_UNKNOWN_ERROR;
Edouard@584
   836
    }
Edouard@584
   837
    
Edouard@584
   838
    sqlite3_reset(session->own_key_is_listed);
Edouard@584
   839
    return status;
Edouard@584
   840
}
Edouard@584
   841
edouard@1412
   842
PEP_STATUS _own_identities_retrieve(
vb@955
   843
        PEP_SESSION session,
edouard@1412
   844
        identity_list **own_identities,
edouard@1412
   845
        identity_flags_t excluded_flags
vb@955
   846
      )
Edouard@584
   847
{
Edouard@584
   848
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@584
   849
    
vb@955
   850
    assert(session && own_identities);
vb@955
   851
    if (!(session && own_identities))
Edouard@584
   852
        return PEP_ILLEGAL_VALUE;
Edouard@584
   853
    
vb@955
   854
    *own_identities = NULL;
vb@955
   855
    identity_list *_own_identities = new_identity_list(NULL);
vb@955
   856
    if (_own_identities == NULL)
Edouard@584
   857
        goto enomem;
Edouard@584
   858
    
vb@955
   859
    sqlite3_reset(session->own_identities_retrieve);
Edouard@584
   860
    
Edouard@584
   861
    int result;
vb@955
   862
    // address, fpr, username, user_id, comm_type, lang, flags
vb@955
   863
    const char *address = NULL;
Edouard@584
   864
    const char *fpr = NULL;
vb@955
   865
    const char *username = NULL;
vb@955
   866
    const char *user_id = NULL;
vb@955
   867
    PEP_comm_type comm_type = PEP_ct_unknown;
vb@955
   868
    const char *lang = NULL;
vb@955
   869
    unsigned int flags = 0;
Edouard@584
   870
    
vb@955
   871
    identity_list *_bl = _own_identities;
Edouard@584
   872
    do {
edouard@1412
   873
        sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
vb@955
   874
        result = sqlite3_step(session->own_identities_retrieve);
Edouard@584
   875
        switch (result) {
Edouard@584
   876
            case SQLITE_ROW:
vb@955
   877
                address = (const char *)
vb@955
   878
                    sqlite3_column_text(session->own_identities_retrieve, 0);
vb@955
   879
                fpr = (const char *)
vb@955
   880
                    sqlite3_column_text(session->own_identities_retrieve, 1);
vb@1071
   881
                user_id = PEP_OWN_USERID;
vb@1071
   882
                username = (const char *)
vb@1069
   883
                    sqlite3_column_text(session->own_identities_retrieve, 2);
vb@1071
   884
                comm_type = PEP_ct_pEp;
vb@1071
   885
                lang = (const char *)
vb@955
   886
                    sqlite3_column_text(session->own_identities_retrieve, 3);
vb@1071
   887
                flags = (unsigned int)
edouard@1444
   888
                    sqlite3_column_int(session->own_identities_retrieve, 4);
vb@955
   889
vb@1078
   890
                pEp_identity *ident = new_identity(address, fpr, user_id, username);
vb@1079
   891
                if (!ident)
Edouard@584
   892
                    goto enomem;
vb@955
   893
                ident->comm_type = comm_type;
vb@955
   894
                if (lang && lang[0]) {
vb@955
   895
                    ident->lang[0] = lang[0];
vb@955
   896
                    ident->lang[1] = lang[1];
vb@1078
   897
                    ident->lang[2] = 0;
vb@955
   898
                }
vb@1068
   899
                ident->me = true;
vb@955
   900
                ident->flags = flags;
vb@955
   901
vb@955
   902
                _bl = identity_list_add(_bl, ident);
vb@1080
   903
                if (_bl == NULL) {
vb@1080
   904
                    free_identity(ident);
vb@983
   905
                    goto enomem;
vb@1080
   906
                }
Edouard@584
   907
                
Edouard@584
   908
                break;
Edouard@584
   909
                
Edouard@584
   910
            case SQLITE_DONE:
Edouard@584
   911
                break;
Edouard@584
   912
                
Edouard@584
   913
            default:
Edouard@584
   914
                status = PEP_UNKNOWN_ERROR;
Edouard@584
   915
                result = SQLITE_DONE;
Edouard@584
   916
        }
Edouard@584
   917
    } while (result != SQLITE_DONE);
Edouard@584
   918
    
vb@955
   919
    sqlite3_reset(session->own_identities_retrieve);
Edouard@584
   920
    if (status == PEP_STATUS_OK)
vb@955
   921
        *own_identities = _own_identities;
Edouard@584
   922
    else
vb@955
   923
        free_identity_list(_own_identities);
Edouard@584
   924
    
Edouard@584
   925
    goto the_end;
Edouard@584
   926
    
Edouard@584
   927
enomem:
vb@955
   928
    free_identity_list(_own_identities);
Edouard@584
   929
    status = PEP_OUT_OF_MEMORY;
Edouard@584
   930
    
Edouard@584
   931
the_end:
Edouard@584
   932
    return status;
Edouard@584
   933
}
vb@955
   934
edouard@1412
   935
DYNAMIC_API PEP_STATUS own_identities_retrieve(
edouard@1364
   936
        PEP_SESSION session,
edouard@1412
   937
        identity_list **own_identities
edouard@1412
   938
      )
edouard@1412
   939
{
edouard@1412
   940
    return _own_identities_retrieve(session, own_identities, 0);
edouard@1412
   941
}
edouard@1412
   942
edouard@1412
   943
PEP_STATUS _own_keys_retrieve(
edouard@1412
   944
        PEP_SESSION session,
edouard@1412
   945
        stringlist_t **keylist,
edouard@1412
   946
        identity_flags_t excluded_flags
edouard@1364
   947
      )
edouard@1364
   948
{
edouard@1364
   949
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1364
   950
    
edouard@1364
   951
    assert(session && keylist);
edouard@1364
   952
    if (!(session && keylist))
edouard@1364
   953
        return PEP_ILLEGAL_VALUE;
edouard@1364
   954
    
edouard@1364
   955
    *keylist = NULL;
edouard@1364
   956
    stringlist_t *_keylist = NULL;
edouard@1364
   957
    
edouard@1394
   958
    sqlite3_reset(session->own_keys_retrieve);
edouard@1364
   959
    
edouard@1364
   960
    int result;
edouard@1364
   961
    char *fpr = NULL;
edouard@1364
   962
    
edouard@1364
   963
    stringlist_t *_bl = _keylist;
edouard@1364
   964
    do {
edouard@1412
   965
        sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
edouard@1394
   966
        result = sqlite3_step(session->own_keys_retrieve);
edouard@1364
   967
        switch (result) {
edouard@1364
   968
            case SQLITE_ROW:
edouard@1394
   969
                fpr = strdup((const char *) sqlite3_column_text(session->own_keys_retrieve, 0));
edouard@1364
   970
                if(fpr == NULL)
edouard@1364
   971
                    goto enomem;
edouard@1364
   972
edouard@1364
   973
                _bl = stringlist_add(_bl, fpr);
edouard@1364
   974
                if (_bl == NULL) {
edouard@1364
   975
                    free(fpr);
edouard@1364
   976
                    goto enomem;
edouard@1364
   977
                }
edouard@1364
   978
                if (_keylist == NULL)
edouard@1364
   979
                    _keylist = _bl;
edouard@1364
   980
                
edouard@1364
   981
                break;
edouard@1364
   982
                
edouard@1364
   983
            case SQLITE_DONE:
edouard@1364
   984
                break;
edouard@1364
   985
                
edouard@1364
   986
            default:
edouard@1364
   987
                status = PEP_UNKNOWN_ERROR;
edouard@1364
   988
                result = SQLITE_DONE;
edouard@1364
   989
        }
edouard@1364
   990
    } while (result != SQLITE_DONE);
edouard@1364
   991
    
edouard@1394
   992
    sqlite3_reset(session->own_keys_retrieve);
edouard@1364
   993
    if (status == PEP_STATUS_OK)
edouard@1364
   994
        *keylist = _keylist;
edouard@1364
   995
    else
edouard@1364
   996
        free_stringlist(_keylist);
edouard@1364
   997
    
edouard@1364
   998
    goto the_end;
edouard@1364
   999
    
edouard@1364
  1000
enomem:
edouard@1364
  1001
    free_stringlist(_keylist);
edouard@1364
  1002
    status = PEP_OUT_OF_MEMORY;
edouard@1364
  1003
    
edouard@1364
  1004
the_end:
edouard@1364
  1005
    return status;
edouard@1364
  1006
}
edouard@1364
  1007
edouard@1412
  1008
DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **keylist)
edouard@1412
  1009
{
edouard@1412
  1010
    return _own_keys_retrieve(session, keylist, 0);
edouard@1412
  1011
}
edouard@1412
  1012
edouard@1394
  1013
// TODO: Unused for now, but should be used when sync receive old keys (ENGINE-145)
edouard@1394
  1014
DYNAMIC_API PEP_STATUS set_own_key(
edouard@1394
  1015
       PEP_SESSION session,
edouard@1394
  1016
       const char *address,
edouard@1394
  1017
       const char *fpr
edouard@1394
  1018
    )
edouard@1394
  1019
{
edouard@1394
  1020
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1394
  1021
    
edouard@1394
  1022
    assert(session &&
edouard@1394
  1023
           address && address[0] &&
edouard@1394
  1024
           fpr && fpr[0]
edouard@1394
  1025
          );
edouard@1394
  1026
    
edouard@1394
  1027
    if (!(session &&
edouard@1394
  1028
          address && address[0] &&
edouard@1394
  1029
          fpr && fpr[0]
edouard@1394
  1030
         ))
edouard@1394
  1031
        return PEP_ILLEGAL_VALUE;
edouard@1394
  1032
    
edouard@1394
  1033
    sqlite3_reset(session->set_own_key);
edouard@1394
  1034
    sqlite3_bind_text(session->set_own_key, 1, address, -1, SQLITE_STATIC);
edouard@1394
  1035
    sqlite3_bind_text(session->set_own_key, 2, fpr, -1, SQLITE_STATIC);
edouard@1394
  1036
edouard@1394
  1037
    int result;
edouard@1394
  1038
    
edouard@1394
  1039
    result = sqlite3_step(session->set_own_key);
edouard@1394
  1040
    switch (result) {
edouard@1394
  1041
        case SQLITE_DONE:
edouard@1394
  1042
            status = PEP_STATUS_OK;
edouard@1394
  1043
            break;
edouard@1394
  1044
            
edouard@1394
  1045
        default:
edouard@1394
  1046
            status = PEP_UNKNOWN_ERROR;
edouard@1394
  1047
    }
edouard@1394
  1048
    
edouard@1394
  1049
    sqlite3_reset(session->set_own_key);
edouard@1394
  1050
    return status;
edouard@1394
  1051
}
krista@1357
  1052
krista@1357
  1053
PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr,
krista@1357
  1054
                             bool *has_private) {
krista@1357
  1055
krista@1357
  1056
    assert(session);
krista@1357
  1057
    assert(fpr);
krista@1357
  1058
    assert(has_private);
krista@1357
  1059
    
krista@1357
  1060
    if (!(session && fpr && has_private))
krista@1357
  1061
        return PEP_ILLEGAL_VALUE;
krista@1357
  1062
krista@1357
  1063
    return session->cryptotech[PEP_crypt_OpenPGP].contains_priv_key(session, fpr, has_private);
edouard@1385
  1064
}