src/key_reset.c
author Krista 'DarthMama' Bennett <krista@pep.foundation>
Wed, 10 Apr 2019 19:17:42 +0200
branchENGINE-536
changeset 3495 b4d3e47eab14
parent 3347 1572cabb0cc4
child 3502 703cf9bc3139
permissions -rw-r--r--
ENGINE-536: newly refactored key_reset with new functions in. Passes current tests, but need to check new functions.
krista@2947
     1
// This file is under GNU General Public License 3.0
krista@2947
     2
// see LICENSE.txt
krista@2947
     3
krista@2947
     4
#include "pEp_internal.h"
krista@2947
     5
#include "dynamic_api.h"
krista@2947
     6
#include "message_api.h"
krista@2947
     7
krista@2947
     8
#include <string.h>
krista@2947
     9
#include <stdlib.h>
krista@2947
    10
krista@2947
    11
PEP_STATUS has_key_reset_been_sent(
krista@2947
    12
        PEP_SESSION session, 
krista@2947
    13
        const char* user_id, 
krista@2947
    14
        const char* revoked_fpr,
krista@2947
    15
        bool* contacted)
krista@2947
    16
{
krista@2947
    17
    assert(session);
krista@2947
    18
    assert(contacted);
krista@2947
    19
    assert(user_id);
krista@2947
    20
    assert(revoked_fpr);
krista@2947
    21
    assert(!EMPTYSTR(user_id));
krista@2947
    22
krista@2947
    23
    if (!session || !contacted || EMPTYSTR(revoked_fpr) || EMPTYSTR(user_id))
krista@2947
    24
        return PEP_ILLEGAL_VALUE;
krista@2947
    25
    
krista@2947
    26
    *contacted = false;
krista@2947
    27
                    
krista@2947
    28
    char* alias_default = NULL;
krista@2947
    29
    
krista@2947
    30
    PEP_STATUS status = get_userid_alias_default(session, user_id, &alias_default);
krista@2947
    31
    
krista@2947
    32
    if (status == PEP_CANNOT_FIND_ALIAS || EMPTYSTR(alias_default)) {
krista@2947
    33
        free(alias_default);
krista@2947
    34
        alias_default = strdup(user_id);
krista@2947
    35
    }
krista@2947
    36
    
krista@2947
    37
    sqlite3_reset(session->was_id_for_revoke_contacted);
krista@2947
    38
    sqlite3_bind_text(session->was_id_for_revoke_contacted, 1, revoked_fpr, -1,
krista@2947
    39
            SQLITE_STATIC);
krista@2947
    40
    sqlite3_bind_text(session->was_id_for_revoke_contacted, 2, user_id, -1,
krista@2947
    41
            SQLITE_STATIC);        
krista@2947
    42
    int result = sqlite3_step(session->was_id_for_revoke_contacted);
krista@2947
    43
    switch (result) {
krista@2947
    44
        case SQLITE_ROW: {
krista@2947
    45
            *contacted = (sqlite3_column_int(session->was_id_for_revoke_contacted, 0) != 0);
krista@2947
    46
            break;
krista@2947
    47
        }
krista@2947
    48
        default:
krista@2947
    49
            sqlite3_reset(session->was_id_for_revoke_contacted);
krista@2947
    50
            free(alias_default);
krista@2947
    51
            return PEP_UNKNOWN_DB_ERROR;
krista@2947
    52
    }
krista@2947
    53
krista@2947
    54
    sqlite3_reset(session->was_id_for_revoke_contacted);
krista@2947
    55
    return PEP_STATUS_OK;
krista@2947
    56
}
krista@2947
    57
krista@2947
    58
//static const char *sql_set_revoke_contact_as_notified =
krista@2947
    59
//    "insert or replace into revocation_contact_list(fpr, contact_id) values (?1, ?2) ;";
krista@2947
    60
krista@2947
    61
PEP_STATUS set_reset_contact_notified(
krista@2947
    62
        PEP_SESSION session,
krista@2947
    63
        const char* revoke_fpr,
krista@2947
    64
        const char* contact_id
krista@2947
    65
    )
krista@2947
    66
{
krista@2947
    67
    PEP_STATUS status = PEP_STATUS_OK;
krista@2947
    68
    
krista@2947
    69
    assert(session && !EMPTYSTR(revoke_fpr) && !EMPTYSTR(contact_id));
krista@2947
    70
    
krista@2947
    71
    if (!session || EMPTYSTR(revoke_fpr) || EMPTYSTR(contact_id))
krista@2947
    72
        return PEP_ILLEGAL_VALUE;
krista@2947
    73
    
krista@2947
    74
    sqlite3_reset(session->set_revoke_contact_as_notified);
krista@2947
    75
    sqlite3_bind_text(session->set_revoke_contact_as_notified, 1, revoke_fpr, -1, 
krista@2947
    76
            SQLITE_STATIC);
krista@2947
    77
    sqlite3_bind_text(session->set_revoke_contact_as_notified, 2, contact_id, -1,
krista@2947
    78
            SQLITE_STATIC);
krista@2947
    79
krista@2947
    80
    int result;
krista@2947
    81
    
krista@2947
    82
    result = sqlite3_step(session->set_revoke_contact_as_notified);
krista@2947
    83
    switch (result) {
krista@2947
    84
        case SQLITE_DONE:
krista@2947
    85
            status = PEP_STATUS_OK;
krista@2947
    86
            break;
krista@2947
    87
            
krista@2947
    88
        default:
krista@2947
    89
            status = PEP_UNKNOWN_DB_ERROR;
krista@2947
    90
    }
krista@2947
    91
    
krista@2947
    92
    sqlite3_reset(session->set_revoke_contact_as_notified);
krista@2947
    93
    return status;    
krista@2947
    94
}
krista@2947
    95
krista@2947
    96
krista@2947
    97
PEP_STATUS receive_key_reset(PEP_SESSION session,
krista@2947
    98
                             message* reset_msg) {
krista@2947
    99
krista@2947
   100
    if (!session || !reset_msg)
krista@2947
   101
        return PEP_ILLEGAL_VALUE;
krista@2947
   102
krista@2947
   103
    pEp_identity* sender_id = reset_msg->from;
krista@2947
   104
                
krista@2947
   105
    if (!sender_id)
krista@2947
   106
        return PEP_MALFORMED_KEY_RESET_MSG;
krista@2947
   107
        
krista@2947
   108
    PEP_STATUS status = update_identity(session, sender_id);
krista@2947
   109
    if (!sender_id->user_id)
krista@2947
   110
        return PEP_UNKNOWN_ERROR;
krista@2947
   111
        
krista@2947
   112
    if (is_me(session, sender_id))
krista@2947
   113
        return PEP_ILLEGAL_VALUE;    
krista@2947
   114
        
krista@2947
   115
    if (!reset_msg->longmsg || strncmp(reset_msg->longmsg, "OLD: ", 5) != 0) 
krista@2947
   116
        return PEP_MALFORMED_KEY_RESET_MSG;
krista@2947
   117
krista@2947
   118
    status = PEP_STATUS_OK;
krista@2947
   119
    char* old_fpr = NULL;
krista@2947
   120
    char* new_fpr = NULL;
krista@2947
   121
    
krista@2947
   122
    stringlist_t* keylist = NULL;
krista@2947
   123
    pEp_identity* temp_ident = identity_dup(sender_id);
krista@2947
   124
    if (!temp_ident) {
krista@2947
   125
        status = PEP_OUT_OF_MEMORY;
krista@2956
   126
        goto pEp_free;
krista@2947
   127
    }        
krista@2947
   128
            
krista@2947
   129
    char* rest = NULL;
krista@2947
   130
    char* p = strtok_r(reset_msg->longmsg, "\r\n", &rest);
krista@2947
   131
    if (!EMPTYSTR(p + 5))
krista@2947
   132
        old_fpr = strdup(p + 5);
krista@2947
   133
    else {
krista@2947
   134
        status = PEP_MALFORMED_KEY_RESET_MSG;
krista@2956
   135
        goto pEp_free;
krista@2947
   136
    }
krista@2947
   137
    
krista@2947
   138
    bool own_key = false;
krista@2947
   139
    status = is_own_key(session, old_fpr, &own_key);
krista@2947
   140
    
krista@2947
   141
    if (own_key) {
krista@2947
   142
        // Nope, no one can make us our own default. If we want to do that,
krista@2947
   143
        // that's keysync, NOT key reset.
krista@2947
   144
        status = PEP_ILLEGAL_VALUE;
krista@2956
   145
        goto pEp_free;
krista@2947
   146
    }
krista@2947
   147
            
krista@2947
   148
    p = strtok_r(NULL, "\r\n", &rest); 
krista@2947
   149
    if (strncmp(p, "NEW: ", 5) != 0  || EMPTYSTR(p + 5)) {
krista@2947
   150
        status = PEP_MALFORMED_KEY_RESET_MSG;
krista@2956
   151
        goto pEp_free;
krista@2947
   152
    }
krista@2947
   153
krista@2947
   154
    new_fpr = strdup(p + 5);
krista@2947
   155
        
krista@2947
   156
    // Reset the original key
krista@2947
   157
    status = key_reset(session, old_fpr, temp_ident);
krista@2947
   158
    if (status != PEP_STATUS_OK)
krista@2956
   159
        goto pEp_free;
krista@2947
   160
        
krista@2947
   161
    status = find_keys(session, new_fpr, &keylist);
krista@2947
   162
    if (status != PEP_STATUS_OK)
krista@2956
   163
        goto pEp_free;
krista@2947
   164
        
krista@2947
   165
    if (!keylist) {
krista@2947
   166
        status = PEP_KEY_NOT_FOUND;
krista@2956
   167
        goto pEp_free;
krista@2947
   168
    }
krista@2947
   169
krista@2947
   170
    // alright, we've checked as best we can. Let's set that baby.
krista@2947
   171
    sender_id->fpr = new_fpr;
krista@2947
   172
    
krista@2947
   173
    // This only sets as the default, does NOT TRUST IN ANY WAY
krista@2947
   174
    sender_id->comm_type = sender_id->comm_type & (~PEP_ct_confirmed);
krista@2947
   175
    status = set_identity(session, sender_id);
krista@2947
   176
    
krista@2947
   177
    sender_id->fpr = NULL; // ownership for free
krista@2956
   178
pEp_free:    
krista@2947
   179
    free_stringlist(keylist);    
krista@2947
   180
    free(old_fpr);
krista@2947
   181
    free(new_fpr);
krista@2947
   182
    free_identity(temp_ident);
krista@2947
   183
    return status;
krista@2947
   184
}
krista@2947
   185
krista@2947
   186
PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
krista@2947
   187
                                               message** dst, 
krista@2947
   188
                                               pEp_identity* recip,
krista@2947
   189
                                               const char* old_fpr,
krista@2947
   190
                                               const char* new_fpr) {
krista@2947
   191
                                                   
krista@2947
   192
    if (!dst || !recip->user_id || !recip->address)
krista@2947
   193
        return PEP_ILLEGAL_VALUE;
krista@2947
   194
krista@2947
   195
    if (!old_fpr || !new_fpr)
krista@2947
   196
        return PEP_ILLEGAL_VALUE;
krista@2947
   197
        
krista@2947
   198
    *dst = NULL;
krista@2947
   199
    // Get own identity user has corresponded with
krista@2947
   200
    pEp_identity* own_identity = NULL;
krista@2947
   201
    
krista@2947
   202
    PEP_STATUS status = get_own_ident_for_contact_id(session,
krista@2947
   203
                                                     recip,
krista@2947
   204
                                                     &own_identity);                                                       
krista@2947
   205
    if (status != PEP_STATUS_OK)
krista@2947
   206
        return status;
krista@2947
   207
        
krista@2947
   208
    message* reset_message = new_message(PEP_dir_outgoing);
krista@2947
   209
    reset_message->from = own_identity;
krista@2947
   210
    reset_message->to = new_identity_list(identity_dup(recip)); // ?
krista@2947
   211
    
krista@2947
   212
    const char* oldtag = "OLD: ";
krista@2947
   213
    const char* newtag = "\nNEW: ";
krista@2947
   214
    const size_t taglens = 11;
krista@2947
   215
    size_t full_len = taglens + strlen(old_fpr) + strlen(new_fpr) + 2; // \n and \0
krista@2947
   216
    char* longmsg = calloc(full_len, 1);
krista@2947
   217
    strlcpy(longmsg, oldtag, full_len);
krista@2947
   218
    strlcat(longmsg, old_fpr, full_len);
krista@2947
   219
    strlcat(longmsg, newtag, full_len);
krista@2947
   220
    strlcat(longmsg, new_fpr, full_len);
krista@2947
   221
    strlcat(longmsg, "\n", full_len);
krista@2947
   222
    reset_message->longmsg = longmsg; 
krista@2947
   223
    reset_message->shortmsg = strdup("Key reset");    
krista@2947
   224
    
krista@2947
   225
    message* output_msg = NULL;
krista@2947
   226
    
krista@2947
   227
    status = encrypt_message(session, reset_message, NULL,
krista@2947
   228
                             &output_msg, PEP_enc_PGP_MIME,
krista@2947
   229
                             PEP_encrypt_flag_key_reset_only);
krista@2947
   230
krista@2947
   231
    if (status == PEP_STATUS_OK)
krista@2947
   232
        *dst = output_msg;
krista@2947
   233
        
krista@2947
   234
    free_message(reset_message);
krista@2947
   235
    return status;
krista@2947
   236
}
krista@2947
   237
krista@2947
   238
PEP_STATUS send_key_reset_to_recents(PEP_SESSION session,
krista@2947
   239
                                     const char* old_fpr, 
krista@2947
   240
                                     const char* new_fpr) {
krista@2947
   241
    assert(old_fpr);
krista@2947
   242
    assert(new_fpr);
krista@2947
   243
    assert(session);
krista@2956
   244
    assert(session->messageToSend);
krista@2947
   245
    
krista@2947
   246
    if (!session || !old_fpr || !new_fpr)
krista@2947
   247
        return PEP_ILLEGAL_VALUE;
krista@2947
   248
krista@2956
   249
    messageToSend_t send_cb = session->messageToSend;
krista@2947
   250
    if (!send_cb)
krista@2947
   251
        return PEP_SYNC_NO_MESSAGE_SEND_CALLBACK;
krista@2947
   252
        
krista@2947
   253
    identity_list* recent_contacts = NULL;
krista@2947
   254
    message* reset_msg = NULL;
krista@2947
   255
krista@2947
   256
    PEP_STATUS status = get_last_contacted(session, &recent_contacts);
krista@2947
   257
    
krista@2947
   258
    if (status != PEP_STATUS_OK)
krista@2956
   259
        goto pEp_free;
krista@2947
   260
                    
krista@2947
   261
    identity_list* curr_id_ptr = recent_contacts;
krista@2947
   262
krista@2947
   263
    for (curr_id_ptr = recent_contacts; curr_id_ptr; curr_id_ptr = curr_id_ptr->next) {
krista@2947
   264
        pEp_identity* curr_id = curr_id_ptr->ident;
krista@2947
   265
        
krista@2947
   266
        if (!curr_id)
krista@2947
   267
            break;
krista@2947
   268
    
krista@2947
   269
        const char* user_id = curr_id->user_id;
krista@2947
   270
        
krista@2947
   271
        // Should be impossible, but?
krista@2947
   272
        if (!user_id)
krista@2947
   273
            continue;
krista@2947
   274
        
krista@2947
   275
        // Check if it's us - if so, pointless...
krista@2947
   276
        if (is_me(session, curr_id))
krista@2947
   277
            continue;
krista@2947
   278
            
krista@2947
   279
        // Check if they've already been told - this shouldn't be the case, but...
krista@2947
   280
        bool contacted = false;
krista@2947
   281
        status = has_key_reset_been_sent(session, user_id, old_fpr, &contacted);
krista@2947
   282
        if (status != PEP_STATUS_OK)
krista@2956
   283
            goto pEp_free;
krista@2947
   284
    
krista@2947
   285
        if (contacted)
krista@2947
   286
            continue;
krista@2947
   287
            
krista@2947
   288
        // if not, make em a message    
krista@2947
   289
        reset_msg = NULL;
krista@2947
   290
        
krista@2947
   291
        status = create_standalone_key_reset_message(session,
krista@2947
   292
                                                     &reset_msg,
krista@2947
   293
                                                     curr_id,
krista@2947
   294
                                                     old_fpr,
krista@2947
   295
                                                     new_fpr);
krista@2947
   296
krista@2947
   297
        if (status == PEP_CANNOT_FIND_IDENTITY) { // this is ok, just means we never mailed them 
krista@2947
   298
            status = PEP_STATUS_OK;
krista@2947
   299
            continue; 
krista@2947
   300
        }
krista@2947
   301
            
krista@2947
   302
        if (status != PEP_STATUS_OK) {
krista@2947
   303
            free(reset_msg);
krista@2956
   304
            goto pEp_free;
krista@2947
   305
        }
krista@2947
   306
        
krista@2947
   307
        // insert into queue
krista@2956
   308
        status = send_cb(reset_msg);
krista@2947
   309
krista@2947
   310
        if (status != PEP_STATUS_OK) {
krista@2947
   311
            free(reset_msg);
krista@2956
   312
            goto pEp_free;            
krista@2947
   313
        }
krista@2947
   314
            
krista@2947
   315
        // Put into notified DB
krista@2947
   316
        status = set_reset_contact_notified(session, old_fpr, user_id);
krista@2947
   317
        if (status != PEP_STATUS_OK)
krista@2956
   318
            goto pEp_free;            
krista@2947
   319
    }
krista@2947
   320
    
krista@2956
   321
pEp_free:
krista@2947
   322
    free_identity_list(recent_contacts);
krista@2947
   323
    return status;
krista@2947
   324
}
krista@2947
   325
krista@3495
   326
DYNAMIC_API PEP_STATUS key_reset_identity(
krista@3495
   327
        PEP_SESSION session,
krista@3495
   328
        const char* fpr,
krista@3495
   329
        pEp_identity* ident
krista@3495
   330
    )
krista@3495
   331
{
krista@3495
   332
    if (!session || !ident || EMPTYSTR(ident->user_id) || EMPTYSTR(ident->address))
krista@3495
   333
        return PEP_ILLEGAL_VALUE;
krista@3495
   334
    
krista@3495
   335
    return key_reset(session, fpr, ident);    
krista@3495
   336
}
krista@3495
   337
krista@3495
   338
DYNAMIC_API PEP_STATUS key_reset_user(
krista@3495
   339
        PEP_SESSION session,
krista@3495
   340
        const char* fpr,
krista@3495
   341
        const char* user_id
krista@3495
   342
    )
krista@3495
   343
{
krista@3495
   344
    if (!session)
krista@3495
   345
        return PEP_ILLEGAL_VALUE;
krista@3495
   346
krista@3495
   347
    pEp_identity* input_ident = NULL;
krista@3495
   348
    
krista@3495
   349
    if (!EMPTYSTR(user_id)) {
krista@3495
   350
        input_ident = new_identity(NULL, NULL, NULL, user_id);
krista@3495
   351
krista@3495
   352
        if (!input_ident)
krista@3495
   353
            return PEP_OUT_OF_MEMORY;
krista@3495
   354
    }
krista@3495
   355
        
krista@3495
   356
    PEP_STATUS status = key_reset(session, fpr, input_ident);
krista@3495
   357
krista@3495
   358
    free_identity(input_ident);
krista@3495
   359
    return status;            
krista@3495
   360
}
krista@3495
   361
krista@3495
   362
// Notes to integrate into header:
krista@3495
   363
// IF there is an ident, it must have a user_id.
krista@3495
   364
PEP_STATUS key_reset(
krista@2947
   365
        PEP_SESSION session,
krista@2947
   366
        const char* key_id,
krista@2947
   367
        pEp_identity* ident
krista@2947
   368
    )
krista@2947
   369
{
krista@3495
   370
    if (!session || (ident && EMPTYSTR(ident->user_id)))
krista@2947
   371
        return PEP_ILLEGAL_VALUE;
krista@2947
   372
        
krista@2947
   373
    PEP_STATUS status = PEP_STATUS_OK;
krista@2947
   374
        
krista@2947
   375
    char* fpr_copy = NULL;
krista@2947
   376
    char* own_id = NULL;
krista@3495
   377
    char* user_id = NULL;
krista@2947
   378
    char* new_key = NULL;
krista@3495
   379
    pEp_identity* tmp_ident = NULL;
krista@2947
   380
    identity_list* key_idents = NULL;
krista@2947
   381
    stringlist_t* keys = NULL;
krista@2947
   382
    
krista@2947
   383
    if (!EMPTYSTR(key_id)) {
krista@2947
   384
        fpr_copy = strdup(key_id);
krista@2947
   385
        if (!fpr_copy)
krista@2947
   386
            return PEP_OUT_OF_MEMORY;
krista@2947
   387
    }
krista@3495
   388
krista@3495
   389
    // This is true when we don't have a user_id and address and the fpr isn't specified
krista@3495
   390
    bool reset_all_for_user = !fpr_copy && (!ident || EMPTYSTR(ident->address));
krista@3495
   391
krista@3495
   392
    // FIXME: does this need to be done everywhere?> I think not.
krista@3495
   393
    if (ident) {
krista@3495
   394
        user_id = strdup(ident->user_id);
krista@3495
   395
        if (!user_id) {
krista@3495
   396
            status = PEP_OUT_OF_MEMORY;
krista@2956
   397
            goto pEp_free;
krista@3495
   398
        }
krista@3495
   399
    }
krista@3495
   400
    else {
krista@3495
   401
        status = get_default_own_userid(session, &user_id);
krista@3495
   402
        if (status != PEP_STATUS_OK || !user_id)
krista@3495
   403
            goto pEp_free;                    
krista@3495
   404
    }
krista@3495
   405
    
krista@3495
   406
    // FIXME: Make sure this can't result in a double-free in recursive calls
krista@3495
   407
    tmp_ident = (ident ? identity_dup(ident) : new_identity(NULL, NULL, user_id, NULL));
krista@3495
   408
    
krista@3495
   409
    if (reset_all_for_user) {
krista@3495
   410
        status = get_all_keys_for_user(session, user_id, &keys);
krista@3495
   411
        // TODO: free
krista@3495
   412
        if (status == PEP_STATUS_OK) {
krista@3495
   413
            stringlist_t* curr_key;
krista@2947
   414
            
krista@3495
   415
            for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
krista@3495
   416
                // FIXME: Is the ident really necessary?
krista@3495
   417
                status = key_reset(session, curr_key->value, tmp_ident);
krista@2947
   418
                if (status != PEP_STATUS_OK)
krista@3495
   419
                    break;
krista@2947
   420
            }
krista@2947
   421
        }
krista@3495
   422
        goto pEp_free;
krista@3495
   423
    }                   
krista@3495
   424
    else {
krista@3495
   425
        // tmp_ident => tmp_ident->user_id (was checked)
krista@3495
   426
        //
krista@3495
   427
        // !(EMPTYSTR(fpr) && (!tmp_ident || EMPTYSTR(tmp_ident->address)))
krista@3495
   428
        // => fpr || (tmp_ident && tmp_ident->address)
krista@3495
   429
        //
krista@3495
   430
        // so: We have an fpr or we have an ident with user_id and address
krista@3495
   431
        //     or both
krista@3495
   432
        if (!fpr_copy) {
krista@3495
   433
            // We are guaranteed to have an ident w/ id + addr here.
krista@3495
   434
            // Get the default key.
krista@3495
   435
            pEp_identity* stored_ident = NULL;
krista@3495
   436
            status = get_identity(session, tmp_ident->address, 
krista@3495
   437
                                  tmp_ident->user_id, &stored_ident);
krista@3495
   438
krista@3495
   439
            // FIXME FIXME FIXME
krista@3495
   440
            if (status == PEP_STATUS_OK) {
krista@3495
   441
                // transfer ownership
krista@3495
   442
                fpr_copy = stored_ident->fpr;
krista@3495
   443
                stored_ident->fpr = NULL;
krista@3495
   444
                free_identity(stored_ident);                
krista@3495
   445
            }
krista@3174
   446
            
krista@3495
   447
            if (!fpr_copy || status == PEP_CANNOT_FIND_IDENTITY) {
krista@3495
   448
                // There's no identity default. Try resetting user default
krista@3495
   449
                status = get_user_default_key(session, tmp_ident->user_id, &fpr_copy);
krista@3495
   450
            }            
krista@2947
   451
            
krista@3495
   452
            if (!fpr_copy || status != PEP_STATUS_OK) // No default to free. We're done here.
krista@3495
   453
                goto pEp_free;            
krista@3495
   454
        }
krista@3495
   455
        
krista@3495
   456
        // Ok - now we have at least an ident with user_id and an fpr.
krista@3495
   457
        // Now it matters if we're talking about ourselves or a partner.
krista@3495
   458
        bool is_own_private = false;
krista@3495
   459
        if (is_me(session, tmp_ident)) {
krista@3495
   460
            bool own_key = false;            
krista@3495
   461
            status = is_own_key(session, fpr_copy, &own_key);
krista@3495
   462
krista@3495
   463
            if (status != PEP_STATUS_OK)
krista@3495
   464
                goto pEp_free;
krista@3495
   465
            if (!own_key) {
krista@3495
   466
                status = PEP_ILLEGAL_VALUE;
krista@3495
   467
                goto pEp_free;
krista@3495
   468
            }
krista@3495
   469
krista@3495
   470
            status = contains_priv_key(session, fpr_copy, &is_own_private);
krista@3495
   471
            if (status != PEP_STATUS_OK)
krista@3495
   472
                goto pEp_free;
krista@3495
   473
        }
krista@3495
   474
        
krista@3495
   475
        // Up to this point, we haven't cared about whether or not we 
krista@3495
   476
        // had a full identity. Now we have to deal with that in the 
krista@3495
   477
        // case of own identities with private keys.
krista@3495
   478
        
krista@3495
   479
        if (is_own_private) {
krista@3495
   480
            
krista@3495
   481
            // If there's no address, we want to reset this key for every identity 
krista@3495
   482
            // it's a part of. Since this means generating new keys, we have to 
krista@3495
   483
            // grab all the identities associated with it.
krista@3495
   484
            if (EMPTYSTR(tmp_ident->address)) {
krista@3495
   485
                status = get_identities_by_main_key_id(session, fpr_copy, &key_idents);
krista@3495
   486
                
krista@3495
   487
                if (status != PEP_CANNOT_FIND_IDENTITY) {
krista@3495
   488
                    if (status == PEP_STATUS_OK) {
krista@3495
   489
                        // now have ident list, or should
krista@3495
   490
                        identity_list* curr_ident;
krista@3495
   491
                        
krista@3495
   492
                        for (curr_ident = key_idents; curr_ident && curr_ident->ident; 
krista@3495
   493
                                                        curr_ident = curr_ident->next) {
krista@3495
   494
                            
krista@3495
   495
                            pEp_identity* this_identity = curr_ident->ident;
krista@3495
   496
                            // Do the full reset on this identity        
krista@3495
   497
                            status = key_reset(session, fpr_copy, this_identity);
krista@3495
   498
                            
krista@3495
   499
                            // Ident list gets freed below, do not free here!
krista@3495
   500
krista@3495
   501
                            if (status != PEP_STATUS_OK)
krista@3495
   502
                                break;
krista@3495
   503
                            
krista@3495
   504
                        }
krista@2947
   505
                    }
krista@3495
   506
                    // Ok, we've either now reset for each own identity with this key, or 
krista@3495
   507
                    // we got an error and want to bail anyway.
krista@3495
   508
                    goto pEp_free;
krista@3495
   509
                }    
krista@2947
   510
            }
krista@3495
   511
            
krista@2947
   512
            // Create revocation
krista@2947
   513
            status = revoke_key(session, fpr_copy, NULL);
krista@2947
   514
            
krista@3495
   515
            // If we have a full identity, we have some cleanup and generation tasks here
krista@3495
   516
            if (!EMPTYSTR(tmp_ident->address)) {
krista@3495
   517
                // generate new key
krista@3495
   518
                if (status == PEP_STATUS_OK) {
krista@3495
   519
                    tmp_ident->fpr = NULL;
krista@3495
   520
                    status = generate_keypair(session, tmp_ident);
krista@3495
   521
                }
krista@3495
   522
                if (status == PEP_STATUS_OK) {
krista@3495
   523
                    new_key = strdup(tmp_ident->fpr);
krista@3495
   524
                    status = set_own_key(session, tmp_ident, new_key);
krista@3495
   525
                }
krista@3495
   526
                // mistrust fpr from trust
krista@3495
   527
                tmp_ident->fpr = fpr_copy;
krista@3495
   528
                
krista@3495
   529
                tmp_ident->comm_type = PEP_ct_mistrusted;
krista@3495
   530
                status = set_trust(session, tmp_ident);
krista@3495
   531
                tmp_ident->fpr = NULL;
krista@3495
   532
                
krista@3495
   533
                // Done with old use of ident.
krista@3495
   534
                if (status == PEP_STATUS_OK) {
krista@3495
   535
                    // Update fpr for outgoing
krista@3495
   536
                    status = myself(session, tmp_ident);
krista@3495
   537
                }
krista@3495
   538
            }    
krista@2947
   539
            
krista@2947
   540
            if (status == PEP_STATUS_OK)
krista@2947
   541
                // cascade that mistrust for anyone using this key
krista@2947
   542
                status = mark_as_compromised(session, fpr_copy);
krista@3495
   543
                
krista@2947
   544
            if (status == PEP_STATUS_OK)
krista@2947
   545
                status = remove_fpr_as_default(session, fpr_copy);
krista@2947
   546
            if (status == PEP_STATUS_OK)
krista@2947
   547
                status = add_mistrusted_key(session, fpr_copy);
krista@3495
   548
krista@3495
   549
            // If there's a new key, do the DB linkage with the revoked one, and 
krista@3495
   550
            // send the key reset mail opportunistically to recently contacted
krista@3495
   551
            // partners
krista@3495
   552
            if (new_key) {
krista@3495
   553
                // add to revocation list 
krista@3495
   554
                if (status == PEP_STATUS_OK) 
krista@3495
   555
                    status = set_revoked(session, fpr_copy, new_key, time(NULL));            
krista@3495
   556
                // for all active communication partners:
krista@3495
   557
                //      active_send revocation
krista@3495
   558
                if (status == PEP_STATUS_OK)
krista@3495
   559
                    status = send_key_reset_to_recents(session, fpr_copy, new_key);        
krista@3495
   560
            }        
krista@3495
   561
        } // end is_own_private
krista@3495
   562
        else {
krista@3495
   563
            // This is a public key (or a private key that isn't ours, which means
krista@3495
   564
            // we want it gone anyway)
krista@3495
   565
            //
krista@3495
   566
            // Delete this key from the keyring.
krista@3495
   567
            status = delete_keypair(session, fpr_copy);
krista@2947
   568
        }
krista@3495
   569
krista@3495
   570
        // REGARDLESS OF WHO OWNS THE KEY, WE NOW NEED TO REMOVE IT AS A DEFAULT.
krista@3495
   571
        PEP_STATUS cached_status = status;
krista@3495
   572
        // remove fpr from all identities
krista@3495
   573
        // remove fpr from all users
krista@3495
   574
        status = remove_fpr_as_default(session, fpr_copy);
krista@3495
   575
        // delete key from DB - this does NOT touch the keyring!
krista@3495
   576
        // Note: for own priv keys, we cannot do this. But we'll never encrypt to/from it.
krista@3495
   577
        if (status == PEP_STATUS_OK && !is_own_private) {
krista@3495
   578
            status = remove_key(session, fpr_copy);
krista@2947
   579
        }
krista@3495
   580
        if (status == PEP_STATUS_OK)
krista@3495
   581
            status = cached_status;
krista@3495
   582
    }           
krista@3495
   583
        
krista@2956
   584
pEp_free:
krista@3495
   585
    if (!ident)
krista@3495
   586
        free_identity(tmp_ident);
krista@2947
   587
    free(fpr_copy);
krista@2947
   588
    free(own_id);
krista@2947
   589
    free_identity_list(key_idents);
krista@2947
   590
    free_stringlist(keys);
krista@2947
   591
    free(new_key);    
krista@2947
   592
    return status;
krista@2947
   593
}