ENGINE-398: Well, it compiles... ENGINE-398
authorKrista Bennett <krista@pep-project.org>
Tue, 14 Aug 2018 07:38:03 +0200
branchENGINE-398
changeset 281748e3e80b5d26
parent 2804 f58a31635b13
child 2818 a3737c5de1c0
ENGINE-398: Well, it compiles...
src/message_api.c
src/pEpEngine.c
src/pEpEngine.h
     1.1 --- a/src/message_api.c	Tue Aug 07 10:24:10 2018 +0200
     1.2 +++ b/src/message_api.c	Tue Aug 14 07:38:03 2018 +0200
     1.3 @@ -1508,6 +1508,66 @@
     1.4      free(revoked_fpr);
     1.5  }
     1.6  
     1.7 +PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
     1.8 +                                               message** dst, 
     1.9 +                                               pEp_identity* recip,
    1.10 +                                               const char* revoke_fpr,
    1.11 +                                               const char* new_fpr) {
    1.12 +                                                   
    1.13 +    if (!dst || !recip->user_id || !recip->address)
    1.14 +        return PEP_ILLEGAL_VALUE;
    1.15 +
    1.16 +    if (!revoke_fpr || !new_fpr)
    1.17 +        return PEP_ILLEGAL_VALUE;
    1.18 +        
    1.19 +    *dst = NULL;
    1.20 +    // Get own identity user has corresponded with
    1.21 +    pEp_identity* own_identity = NULL;
    1.22 +    
    1.23 +    PEP_STATUS status = get_own_ident_for_contact_id(session,
    1.24 +                                                     recip,
    1.25 +                                                     &own_identity);                                                       
    1.26 +    if (status != PEP_STATUS_OK)
    1.27 +        return status;
    1.28 +        
    1.29 +    message* reset_message = new_message(PEP_dir_outgoing);
    1.30 +    reset_message->from = own_identity;
    1.31 +    reset_message->to = new_identity_list(identity_dup(recip)); // ?
    1.32 +    
    1.33 +    const char* oldtag = "OLD: ";
    1.34 +    const char* newtag = "\nNEW: ";
    1.35 +    const size_t taglens = 11;
    1.36 +    size_t full_len = taglens + strlen(revoke_fpr) + strlen(new_fpr) + 2; // \n and \0
    1.37 +    char* longmsg = calloc(full_len, 1);
    1.38 +     
    1.39 +    strlcpy(longmsg, oldtag, full_len);
    1.40 +    strlcat(longmsg, revoke_fpr, full_len);
    1.41 +    strlcat(longmsg, newtag, full_len);
    1.42 +    strlcat(longmsg, new_fpr, full_len);
    1.43 +    strlcat(longmsg, "\n", full_len);
    1.44 +    
    1.45 +    status = _attach_key(session, revoke_fpr, reset_message);
    1.46 +    if (status != PEP_STATUS_OK)
    1.47 +        goto pep_free;
    1.48 +    status = _attach_key(session, new_fpr, reset_message);
    1.49 +    if (status != PEP_STATUS_OK)
    1.50 +        goto pep_free;
    1.51 +    
    1.52 +    message* output_msg = NULL;
    1.53 +    
    1.54 +    status = encrypt_message(session, reset_message, NULL,
    1.55 +                             &output_msg, PEP_enc_PGP_MIME,
    1.56 +                             PEP_encrypt_flag_key_reset_only);
    1.57 +
    1.58 +    if (status == PEP_STATUS_OK)
    1.59 +        *dst = output_msg;
    1.60 +        
    1.61 +pep_free:
    1.62 +    free_message(reset_message);
    1.63 +    return status;
    1.64 +}
    1.65 +
    1.66 +
    1.67  PEP_STATUS send_key_reset_to_recents(PEP_SESSION session,
    1.68                                       const char* revoke_fpr, 
    1.69                                       const char* new_fpr) {
    1.70 @@ -1515,8 +1575,8 @@
    1.71      assert(new_fpr);
    1.72      assert(session);
    1.73      assert(session->sync_session);
    1.74 -    assert(session->sync_session->inject_sync_message);
    1.75 -    assert(session->sync_session->management);
    1.76 +    assert(session->sync_session->inject_sync_msg);
    1.77 +    assert(session->sync_session->sync_management);
    1.78      
    1.79      if (!session || !revoke_fpr || !new_fpr)
    1.80          return PEP_ILLEGAL_VALUE;
    1.81 @@ -1559,7 +1619,8 @@
    1.82          // if not, make em a message    
    1.83          reset_msg = NULL;
    1.84          
    1.85 -        status = create_standalone_key_reset_message(&reset_msg,
    1.86 +        status = create_standalone_key_reset_message(session,
    1.87 +                                                     &reset_msg,
    1.88                                                       curr_id,
    1.89                                                       revoke_fpr,
    1.90                                                       new_fpr);
    1.91 @@ -1589,62 +1650,6 @@
    1.92      return status;
    1.93  }
    1.94  
    1.95 -PEP_STATUS create_standalone_key_reset_message(message** dst, 
    1.96 -                                               pEp_identity* recip,
    1.97 -                                               const char* revoke_fpr,
    1.98 -                                               const char* new_fpr) {
    1.99 -                                                   
   1.100 -    if (!dst || !recip->user_id || !recip->address)
   1.101 -        return PEP_ILLEGAL_VALUE;
   1.102 -
   1.103 -    if (!revoke_fpr || !new_fpr)
   1.104 -        return PEP_ILLEGAL_VALUE;
   1.105 -        
   1.106 -    *dst = NULL;
   1.107 -    // Get own identity user has corresponded with
   1.108 -    pEp_identity* own_identity = NULL;
   1.109 -    PEP_STATUS status = get_own_address_for_contact_id(PEP_SESSION session,
   1.110 -                                                       recip,
   1.111 -                                                       &own_identity);                                                       
   1.112 -    if (status != PEP_STATUS_OK)
   1.113 -        return status;
   1.114 -        
   1.115 -    message* reset_message = new_message(PEP_dir_outgoing);
   1.116 -    reset_message->from = own_identity;
   1.117 -    reset_message->to = new_identity_list(identity_dup(recip)); // ?
   1.118 -    
   1.119 -    const char* oldtag = "OLD: ";
   1.120 -    const char* newtag = "\nNEW: ";
   1.121 -    const size_t taglens = 11;
   1.122 -    size_t full_len = taglens + strlen(revoke_fpr) + strlen(new_fpr) + 2; // \n and \0
   1.123 -    char* longmsg = calloc(full_len, 1);
   1.124 -     
   1.125 -    strlcpy(longmsg, oldtag, full_len);
   1.126 -    strlcat(longmsg, revoke_fpr, full_len);
   1.127 -    strlcat(longmsg, newtag, full_len);
   1.128 -    strlcat(longmsg, new_fpr);
   1.129 -    strlcat(longmsg, "\n");
   1.130 -    
   1.131 -    status = _attach_key(session, revoke_fpr, reset_message);
   1.132 -    if (status != PEP_STATUS_OK)
   1.133 -        goto pep_free;
   1.134 -    status = _attach_key(session, new_fpr, reset_message);
   1.135 -    if (status != PEP_STATUS_OK)
   1.136 -        goto pep_free;
   1.137 -    
   1.138 -    message* output_msg = NULL;
   1.139 -    
   1.140 -    status = encrypt_message(session, reset_message, NULL,
   1.141 -                             output_msg, PEP_enc_PGP_MIME,
   1.142 -                             PEP_encrypt_flag_key_reset_only);
   1.143 -
   1.144 -    if (status == PEP_STATUS_OK)
   1.145 -        *dst = output_msg;
   1.146 -        
   1.147 -pep_free:
   1.148 -    free_message(reset_message);
   1.149 -    return status;
   1.150 -}
   1.151  
   1.152  PEP_cryptotech determine_encryption_format(message *msg)
   1.153  {
   1.154 @@ -1954,8 +1959,8 @@
   1.155      else {
   1.156          // FIXME - we need to deal with transport types (via flag)
   1.157          if ((!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
   1.158 -            message_wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default);
   1.159 -            _src = wrap_message_as_attachment(NULL, src, message_wrap_type, false);
   1.160 +            message_wrap_type wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default);
   1.161 +            _src = wrap_message_as_attachment(NULL, src, wrap_type, false);
   1.162              if (!_src)
   1.163                  goto pep_error;
   1.164          }
   1.165 @@ -3171,23 +3176,73 @@
   1.166  PEP_STATUS check_for_own_revoked_key(
   1.167          PEP_SESSION session, 
   1.168          stringlist_t* keylist,
   1.169 -        char** bad_fpr,
   1.170 -        char** replacement_fpr
   1.171 +        stringpair_list_t** revoked_fpr_pairs
   1.172      ) 
   1.173  {
   1.174 -    if (!session || !bad_fpr || !replacement_fpr)
   1.175 +    if (!session || !revoked_fpr_pairs)
   1.176          return PEP_ILLEGAL_VALUE;
   1.177 +        
   1.178 +    *revoked_fpr_pairs = NULL;
   1.179 +
   1.180 +    PEP_STATUS status = PEP_STATUS_OK;
   1.181 +    stringpair_list_t* _the_list = new_stringpair_list(NULL);
   1.182 +        
   1.183      stringlist_t* _k = keylist;
   1.184 -    while (_k) {
   1.185 +    for ( ; _k; _k = _k->next) {
   1.186 +
   1.187 +        if (EMPTYSTR(_k->value))
   1.188 +            continue; // Maybe the right thing to do is choke. 
   1.189 +                      // But we can have NULL-valued empty list heads.
   1.190 +
   1.191 +        const char* recip_fpr = _k->value;
   1.192 +        char* replace_fpr = NULL;
   1.193 +        uint64_t revoke_date = 0; 
   1.194 +        status = get_replacement_fpr(session, 
   1.195 +                                     recip_fpr, 
   1.196 +                                     &replace_fpr, 
   1.197 +                                     &revoke_date);
   1.198 +
   1.199 +        bool own_key = false;
   1.200          
   1.201 +        switch (status) {
   1.202 +            case PEP_CANNOT_FIND_IDENTITY:
   1.203 +                continue;
   1.204 +            case PEP_STATUS_OK:
   1.205 +        
   1.206 +                status = is_own_key(session, recip_fpr, &own_key);
   1.207 +                
   1.208 +                if (status != PEP_STATUS_OK) {
   1.209 +                    free(replace_fpr);
   1.210 +                    return status;
   1.211 +                }
   1.212 +                
   1.213 +                if (own_key)
   1.214 +                    stringpair_list_add(_the_list, new_stringpair(recip_fpr, replace_fpr));
   1.215 +
   1.216 +                free(replace_fpr);
   1.217 +                replace_fpr = NULL;
   1.218 +                
   1.219 +            default:    
   1.220 +                goto pep_free;    
   1.221 +        }
   1.222      }
   1.223 +    
   1.224 +    if (_the_list && _the_list->value) {
   1.225 +        *revoked_fpr_pairs = _the_list;
   1.226 +        _the_list = NULL;
   1.227 +    }
   1.228 +            
   1.229 +pep_free:
   1.230 +    free_stringpair_list(_the_list);
   1.231 +    return status;
   1.232 +
   1.233  }
   1.234  
   1.235  PEP_STATUS receive_key_reset(PEP_SESSION session,
   1.236                               message* reset_msg,
   1.237                               const char* signing_fpr) {
   1.238  
   1.239 -    if (!session || !reset_msg || !revoke_fpr || !new_fpr)
   1.240 +    if (!session || !reset_msg)
   1.241          return PEP_ILLEGAL_VALUE;
   1.242          
   1.243      if (EMPTYSTR(signing_fpr))
   1.244 @@ -3196,24 +3251,31 @@
   1.245      if (!reset_msg->from || !reset_msg->from->user_id)
   1.246          return PEP_MALFORMED_KEY_RESET_MSG;
   1.247          
   1.248 -    if (is_me(reset_msg->from)) // hrm...
   1.249 +    if (is_me(session, reset_msg->from)) // hrm...
   1.250          return PEP_ILLEGAL_VALUE;
   1.251          
   1.252      if (!reset_msg->longmsg || strncmp(reset_msg->longmsg, "OLD: ", 5) != 0) 
   1.253          return PEP_MALFORMED_KEY_RESET_MSG;
   1.254  
   1.255      PEP_STATUS status = PEP_STATUS_OK;
   1.256 -    const char* revoke_fpr = NULL;
   1.257 -    const char* new_fpr = NULL;
   1.258 +    char* revoke_fpr = NULL;
   1.259 +    char* new_fpr = NULL;
   1.260      
   1.261      stringlist_t* keylist = NULL;
   1.262 -
   1.263 +    pEp_identity* temp_ident = NULL;
   1.264 +    
   1.265      // Make sure the signing fpr belongs to the "from" user, since that is 
   1.266      // who we are to change defaults for.
   1.267      
   1.268      // 1. See if this fpr is even associated with this user_id
   1.269 -    const char* sender_id = reset_msg->from->user_id;
   1.270 -    status = exists_trust_entry(session, sender_id, *signing_fpr, user_has_fpr);
   1.271 +    pEp_identity* sender_id = reset_msg->from;
   1.272 +    bool user_has_fpr = false;
   1.273 +    
   1.274 +    temp_ident = identity_dup(sender_id);
   1.275 +    free(temp_ident->fpr);
   1.276 +    temp_ident->fpr = strdup(signing_fpr);
   1.277 +    
   1.278 +    status = exists_trust_entry(session, temp_ident, &user_has_fpr);
   1.279      if (status != PEP_STATUS_OK)
   1.280          goto pep_free;
   1.281          
   1.282 @@ -3250,8 +3312,13 @@
   1.283      // tricks us into using one here.
   1.284      identity_list* private_il = NULL;
   1.285      
   1.286 -    bool imported_keys = import_attached_keys(session, reset_message, &private_il);
   1.287 -
   1.288 +    bool imported_keys = import_attached_keys(session, reset_msg, &private_il);
   1.289 +
   1.290 +    if (!imported_keys) {
   1.291 +        status = PEP_KEY_NOT_RESET; // ??
   1.292 +        goto pep_free;
   1.293 +    }
   1.294 +        
   1.295      if (private_il) {
   1.296          // This is clearly not a real key reset message. We NEVER distribute
   1.297          // private keys this way, so indicate foul play and abort.
   1.298 @@ -3263,7 +3330,7 @@
   1.299      // We know that the signer has the sender's user_id, and that the revoked fpr
   1.300      // is theirs. We now need to make sure that we've imported the key we need.
   1.301      
   1.302 -    status = find_keys(session, *new_fpr, &keylist);
   1.303 +    status = find_keys(session, new_fpr, &keylist);
   1.304      if (status != PEP_STATUS_OK)
   1.305          goto pep_free;
   1.306          
   1.307 @@ -3273,9 +3340,8 @@
   1.308      }
   1.309  
   1.310      // alright, we've checked as best we can. Let's set that baby.
   1.311 -    sender_id->from->fpr = new_fpr;
   1.312 +    sender_id->fpr = new_fpr;
   1.313      
   1.314 -    reset_msg->flags |= PEP_decrypt_flag_consume;
   1.315      sender_id->comm_type = sender_id->comm_type & (~PEP_ct_confirmed);
   1.316      status = set_identity(session, sender_id);
   1.317      
   1.318 @@ -3286,6 +3352,7 @@
   1.319      free(keylist);    
   1.320      free(revoke_fpr);
   1.321      free(new_fpr);
   1.322 +    free(temp_ident);
   1.323      return status;
   1.324  }
   1.325  
   1.326 @@ -3316,6 +3383,7 @@
   1.327      PEP_STATUS _decrypt_in_pieces_status = PEP_CANNOT_DECRYPT_UNKNOWN;
   1.328      message* msg = NULL;
   1.329      message* calculated_src = src;
   1.330 +    message* reset_msg = NULL;
   1.331      
   1.332      char *ctext;
   1.333      size_t csize;
   1.334 @@ -3555,26 +3623,25 @@
   1.335      
   1.336                                      if (wrap_info) {
   1.337                                          bool is_inner = (strcmp(wrap_info, "INNER") == 0);
   1.338 -                                        bool is_key_reset = (strcmp(wrap_info, "KEY_RESET") == 0)
   1.339 -
   1.340 -                                        if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED && is_key_reset) {
   1.341 -                                            
   1.342 +                                        bool is_key_reset = (strcmp(wrap_info, "KEY_RESET") == 0);
   1.343 +
   1.344 +                                        if (is_key_reset) {
   1.345 +                                            if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED) {
   1.346 +                                                if (!_keylist || !_keylist->value) {
   1.347 +                                                    status = PEP_UNKNOWN_ERROR;
   1.348 +                                                    goto pep_error;
   1.349 +                                                }    
   1.350 +                                                status = receive_key_reset(session,
   1.351 +                                                                           inner_message,
   1.352 +                                                                           _keylist->value);
   1.353 +                                                if (status != PEP_STATUS_OK) {
   1.354 +                                                    free_message(inner_message);
   1.355 +                                                    goto pep_error;
   1.356 +                                                }
   1.357 +                                                *flags |= PEP_decrypt_flag_consume;
   1.358 +                                            }
   1.359                                          }
   1.360 -
   1.361 -                                        if (is_key_reset) {
   1.362 -                                            const char* revoke_fpr = NULL;
   1.363 -                                            const char* new_fpr = NULL; 
   1.364 -                                            status = receive_key_reset(session,
   1.365 -                                                                       inner_message,
   1.366 -                                                                       &revoke_fpr,
   1.367 -                                                                       &new_fpr);
   1.368 -                                            if (status != PEP_STATUS_OK) {
   1.369 -                                                free_message(inner_message);
   1.370 -                                                goto pep_error;
   1.371 -                                            }
   1.372 -                                            
   1.373 -                                        }
   1.374 -                                        if (is_inner || is_key_reset) {
   1.375 +                                        else if (is_inner) {
   1.376  
   1.377                                              // check for private key in decrypted message attachment while importing
   1.378                                              // N.B. Apparently, we always import private keys into the keyring; however,
   1.379 @@ -3600,13 +3667,6 @@
   1.380                                              reconcile_src_and_inner_messages(src, inner_message);
   1.381                                              
   1.382  
   1.383 -                                            if (is_key_reset) {
   1.384 -                                                // FIXME: WE HAVE TO DO WAY MORE THAN THIS.
   1.385 -                                                // Key reset message needs to contain both old and new key fprs.
   1.386 -                                                // We need to check this here.
   1.387 -                                                inner_message->flags |= PEP_decrypt_flag_consume;
   1.388 -                                            }
   1.389 -    
   1.390                                              // FIXME: free msg, but check references
   1.391                                              //src = msg = inner_message;
   1.392                                              calculated_src = msg = inner_message;
   1.393 @@ -3710,13 +3770,64 @@
   1.394          }
   1.395      } // End prepare output message for return
   1.396  
   1.397 -    // 3. Check to see if the sender used a bad key
   1.398 -    char* bad_fpr = NULL;
   1.399 -    status = check_for_own_revoked_key(session, _keylist, &bad_fpr);
   1.400 +    // 3. Check to see if the sender used any of our revoked keys
   1.401 +    stringpair_list_t* revoke_replace_pairs = NULL;
   1.402 +    status = check_for_own_revoked_key(session, _keylist, &revoke_replace_pairs);
   1.403 +
   1.404 +    assert(status != PEP_STATUS_OK); // FIXME: FOR DEBUGGING ONLY DO NOT LEAVE IN    
   1.405 +    if (status != PEP_STATUS_OK) {
   1.406 +        // This should really never choke unless the DB is broken.
   1.407 +    }
   1.408      
   1.409 +    stringpair_list_t* curr_pair_node;
   1.410 +    stringpair_t* curr_pair;
   1.411 +    
   1.412 +    for (curr_pair_node = revoke_replace_pairs; curr_pair_node; curr_pair_node = curr_pair_node->next) {
   1.413 +        curr_pair = curr_pair_node->value;
   1.414 +        
   1.415 +        if (!curr_pair)
   1.416 +            continue; // Again, shouldn't occur
   1.417 +            
   1.418 +        if (curr_pair->key && curr_pair->value) {
   1.419 +            status = create_standalone_key_reset_message(session,
   1.420 +                                                         &reset_msg,
   1.421 +                                                         msg->from,
   1.422 +                                                         curr_pair->key,
   1.423 +                                                         curr_pair->value);
   1.424 +
   1.425 +            if (status != PEP_STATUS_OK)
   1.426 +                goto pep_error;
   1.427 +                
   1.428 +            if (!reset_msg) {
   1.429 +                status = PEP_OUT_OF_MEMORY;
   1.430 +                goto pep_error;
   1.431 +            }
   1.432 +            // insert into queue
   1.433 +            int result = session->sync_session->inject_sync_msg(reset_msg, 
   1.434 +                                                                session->sync_session->sync_management);
   1.435 +
   1.436 +            if (result == 0) {    
   1.437 +                // Put into notified DB
   1.438 +                status = set_reset_contact_notified(session, curr_pair->key, msg->from->user_id);
   1.439 +                if (status != PEP_STATUS_OK) // It's ok to barf because it's a DB problem??
   1.440 +                    goto pep_error;
   1.441 +            }
   1.442 +            else {
   1.443 +                // According to Volker, this would only be a fatal error, so...
   1.444 +                status = PEP_SYNC_INJECT_FAILED; // FIXME: see what can happen here
   1.445 +                goto pep_error;
   1.446 +            }
   1.447 +        
   1.448 +            free_message(reset_msg);
   1.449 +            reset_msg = NULL;
   1.450 +        }
   1.451 +    }
   1.452 +    
   1.453 +    // 4. Set up return values
   1.454      *dst = msg;
   1.455      *keylist = _keylist;
   1.456  
   1.457 +    // 5. Reencrypt if necessary
   1.458      if (reencrypt) {
   1.459          if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED) {
   1.460              message* reencrypt_msg = NULL;
   1.461 @@ -3767,6 +3878,7 @@
   1.462      free(ptext);
   1.463      free(signer_fpr);
   1.464      free_message(msg);
   1.465 +    free_message(reset_msg);
   1.466      free_stringlist(_keylist);
   1.467  
   1.468      return status;
     2.1 --- a/src/pEpEngine.c	Tue Aug 07 10:24:10 2018 +0200
     2.2 +++ b/src/pEpEngine.c	Tue Aug 14 07:38:03 2018 +0200
     2.3 @@ -1237,15 +1237,6 @@
     2.4              &_session->get_last_contacted, NULL);
     2.5      assert(int_result == SQLITE_OK);
     2.6  
     2.7 -static const char *sql_was_id_for_revoke_contacted = 
     2.8 -    "select count(*) from revocation_contact_list where fpr = ?1 and contact_id = ?2 ;";
     2.9 -
    2.10 -// We only need user_id and address, since in the main usage, we'll call update_identity
    2.11 -// on this anyway when sending out messages.
    2.12 -static const char *sql_get_last_contacted =
    2.13 -    "select userid, address from identity where datetime('now') < datetime(timestamp, '+14 days') ; ";
    2.14 -
    2.15 -
    2.16      int_result = sqlite3_prepare_v2(_session->db, 
    2.17              sql_get_own_address_binding_from_contact,
    2.18              (int)strlen(sql_get_own_address_binding_from_contact), 
    2.19 @@ -2272,9 +2263,10 @@
    2.20      sqlite3_bind_text(session->exists_identity_entry, 1, identity->address, -1,
    2.21                        SQLITE_STATIC);
    2.22      sqlite3_bind_text(session->exists_identity_entry, 2, identity->user_id, -1,
    2.23 +                      SQLITE_STATIC);
    2.24                    
    2.25      int result = sqlite3_step(session->exists_identity_entry);
    2.26 -    SQLITE_STATIC);
    2.27 +
    2.28      switch (result) {
    2.29          case SQLITE_ROW: {
    2.30              // yeah yeah, I know, we could be lazy here, but it looks bad.
    2.31 @@ -2754,8 +2746,9 @@
    2.32  }
    2.33  
    2.34  PEP_STATUS get_own_ident_for_contact_id(PEP_SESSION session,
    2.35 -                                          const pEp_identity* contact
    2.36 +                                          const pEp_identity* contact,
    2.37                                            pEp_identity** own_ident) {
    2.38 +                                              
    2.39      if (!contact || !contact->user_id || !own_ident)
    2.40          return PEP_ILLEGAL_VALUE;
    2.41          
    2.42 @@ -2769,13 +2762,16 @@
    2.43      sqlite3_reset(session->get_own_address_binding_from_contact);
    2.44      sqlite3_bind_text(session->get_own_address_binding_from_contact, 1, own_user_id, -1,
    2.45              SQLITE_STATIC);
    2.46 -    sqlite3_bind_text(session->get_own_address_binding_from_contact, 2, contact_ident->user_id, -1,
    2.47 +    sqlite3_bind_text(session->get_own_address_binding_from_contact, 2, contact->user_id, -1,
    2.48              SQLITE_STATIC);
    2.49  
    2.50 -    result = sqlite3_step(session->get_own_address_binding_from_contact);
    2.51 +    int result = sqlite3_step(session->get_own_address_binding_from_contact);
    2.52 +    
    2.53 +    const char* own_address = NULL;
    2.54 +    
    2.55      switch (result) {
    2.56          case SQLITE_ROW:
    2.57 -            const char* const own_address = (const char *)
    2.58 +            own_address = (const char *)
    2.59                  sqlite3_column_text(session->get_own_address_binding_from_contact, 0);
    2.60              if (own_address) {
    2.61                  status = get_identity(session, own_address, own_user_id, own_ident);
    2.62 @@ -3954,6 +3950,35 @@
    2.63      return status;
    2.64  }
    2.65  
    2.66 +PEP_STATUS is_own_key(PEP_SESSION session, const char* fpr, bool* own_key) {
    2.67 +    
    2.68 +    assert(session);
    2.69 +    assert(!EMPTYSTR(fpr));
    2.70 +
    2.71 +    if (!session || EMPTYSTR(fpr))
    2.72 +        return PEP_ILLEGAL_VALUE;
    2.73 +    
    2.74 +    *own_key = false;
    2.75 +    sqlite3_reset(session->own_key_is_listed);
    2.76 +    
    2.77 +    sqlite3_bind_text(session->own_key_is_listed, 1, fpr, -1,
    2.78 +            SQLITE_STATIC);
    2.79 +    int result = sqlite3_step(session->own_key_is_listed);
    2.80 +    switch (result) {
    2.81 +        case SQLITE_ROW: {
    2.82 +            *own_key = (sqlite3_column_int(session->own_key_is_listed, 0) != 0);
    2.83 +            break;
    2.84 +        }
    2.85 +        default:
    2.86 +            sqlite3_reset(session->own_key_is_listed);
    2.87 +            return PEP_UNKNOWN_DB_ERROR;
    2.88 +    }
    2.89 +
    2.90 +    sqlite3_reset(session->own_key_is_listed);
    2.91 +    return PEP_STATUS_OK;
    2.92 +
    2.93 +}
    2.94 +
    2.95  DYNAMIC_API PEP_STATUS set_revoked(
    2.96         PEP_SESSION session,
    2.97         const char *revoked_fpr,
    2.98 @@ -4055,15 +4080,9 @@
    2.99  {
   2.100      PEP_STATUS status = PEP_STATUS_OK;
   2.101  
   2.102 -    assert(session &&
   2.103 -           revoked_fpr &&
   2.104 -           fpr && fpr[0]
   2.105 -          );
   2.106 +    assert(session && revoked_fpr && !EMPTYSTR(fpr) && revocation_date);
   2.107      
   2.108 -    if (!(session &&
   2.109 -           revoked_fpr &&
   2.110 -           fpr && fpr[0]
   2.111 -          ))
   2.112 +    if (!session || !revoked_fpr || EMPTYSTR(fpr) || !revocation_date)
   2.113          return PEP_ILLEGAL_VALUE;
   2.114  
   2.115      *revoked_fpr = NULL;
   2.116 @@ -4104,11 +4123,9 @@
   2.117      pEp_identity* ident;
   2.118  
   2.119      assert(session);
   2.120 -    assert(address);
   2.121 -    assert(address[0]);
   2.122      assert(id_list);
   2.123  
   2.124 -    if (!(session && address && address[0] && id_list))
   2.125 +    if (!(session && id_list))
   2.126          return PEP_ILLEGAL_VALUE;
   2.127  
   2.128      *id_list = NULL;
   2.129 @@ -4122,7 +4139,8 @@
   2.130                  (const char *) sqlite3_column_text(session->get_last_contacted, 1),
   2.131                  NULL,
   2.132                  (const char *) sqlite3_column_text(session->get_last_contacted, 0),
   2.133 -                );
   2.134 +                NULL);
   2.135 +                
   2.136          assert(ident);
   2.137          if (ident == NULL) {
   2.138              sqlite3_reset(session->get_last_contacted);
   2.139 @@ -4154,10 +4172,11 @@
   2.140  {
   2.141      assert(session);
   2.142      assert(contacted);
   2.143 -    assert(identity);
   2.144 +    assert(user_id);
   2.145 +    assert(revoked_fpr);
   2.146      assert(!EMPTYSTR(user_id));
   2.147  
   2.148 -    if (!session || !contacted || !identity || EMPTYSTR(user_id))
   2.149 +    if (!session || !contacted || EMPTYSTR(revoked_fpr) || EMPTYSTR(user_id))
   2.150          return PEP_ILLEGAL_VALUE;
   2.151      
   2.152      *contacted = false;
   2.153 @@ -4203,9 +4222,9 @@
   2.154  {
   2.155      PEP_STATUS status = PEP_STATUS_OK;
   2.156      
   2.157 -    assert(session && !EMPTY_STR(revoke_fpr) && !EMPTY_STR(contact_id));
   2.158 +    assert(session && !EMPTYSTR(revoke_fpr) && !EMPTYSTR(contact_id));
   2.159      
   2.160 -    if (!session || EMPTY_STR(revoke_fpr) || EMPTY_STR(contact_id))
   2.161 +    if (!session || EMPTYSTR(revoke_fpr) || EMPTYSTR(contact_id))
   2.162          return PEP_ILLEGAL_VALUE;
   2.163      
   2.164      sqlite3_reset(session->set_revoke_contact_as_notified);
     3.1 --- a/src/pEpEngine.h	Tue Aug 07 10:24:10 2018 +0200
     3.2 +++ b/src/pEpEngine.h	Tue Aug 14 07:38:03 2018 +0200
     3.3 @@ -54,6 +54,7 @@
     3.4      PEP_KEY_UNSUITABLE                              = 0x0206,
     3.5      PEP_KEY_RESET_SUCCESSFUL                        = 0x0210,
     3.6      PEP_MALFORMED_KEY_RESET_MSG                     = 0x0211,
     3.7 +    PEP_KEY_NOT_RESET                               = 0x0212,
     3.8      
     3.9      PEP_CANNOT_FIND_IDENTITY                        = 0x0301,
    3.10      PEP_CANNOT_SET_PERSON                           = 0x0381,
    3.11 @@ -1268,6 +1269,13 @@
    3.12  PEP_STATUS replace_main_user_fpr(PEP_SESSION session, const char* user_id,
    3.13                                const char* new_fpr);
    3.14      
    3.15 +DYNAMIC_API PEP_STATUS get_replacement_fpr(
    3.16 +        PEP_SESSION session,
    3.17 +        const char *fpr,
    3.18 +        char **revoked_fpr,
    3.19 +        uint64_t *revocation_date
    3.20 +    );
    3.21 +    
    3.22  PEP_STATUS refresh_userid_default_key(PEP_SESSION session, const char* user_id);
    3.23  
    3.24  // This ONLY sets the *user* flag, and creates a shell identity if necessary.
    3.25 @@ -1279,6 +1287,33 @@
    3.26  
    3.27  PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr);
    3.28  
    3.29 +PEP_STATUS get_last_contacted(
    3.30 +        PEP_SESSION session,
    3.31 +        identity_list** id_list
    3.32 +    );
    3.33 +
    3.34 +
    3.35 +PEP_STATUS has_key_reset_been_sent(
    3.36 +        PEP_SESSION session, 
    3.37 +        const char* user_id, 
    3.38 +        const char* revoked_fpr,
    3.39 +        bool* contacted);
    3.40 +
    3.41 +PEP_STATUS set_reset_contact_notified(
    3.42 +        PEP_SESSION session,
    3.43 +        const char* revoke_fpr,
    3.44 +        const char* contact_id
    3.45 +    );
    3.46 +
    3.47 +PEP_STATUS get_own_ident_for_contact_id(PEP_SESSION session,
    3.48 +                                          const pEp_identity* contact,
    3.49 +                                          pEp_identity** own_ident);
    3.50 +
    3.51 +PEP_STATUS exists_trust_entry(PEP_SESSION session, pEp_identity* identity,
    3.52 +                              bool* exists);
    3.53 +
    3.54 +PEP_STATUS is_own_key(PEP_SESSION session, const char* fpr, bool* own_key);
    3.55 +
    3.56  #ifdef __cplusplus
    3.57  }
    3.58  #endif