ENGINE-398: intermittent non-compiling commit ENGINE-398
authorKrista Bennett <krista@pep-project.org>
Tue, 07 Aug 2018 10:24:10 +0200
branchENGINE-398
changeset 2804f58a31635b13
parent 2800 2c40068e30a0
child 2817 48e3e80b5d26
ENGINE-398: intermittent non-compiling commit
src/message_api.c
src/pEpEngine.h
     1.1 --- a/src/message_api.c	Fri Aug 03 12:20:08 2018 +0200
     1.2 +++ b/src/message_api.c	Tue Aug 07 10:24:10 2018 +0200
     1.3 @@ -1597,6 +1597,9 @@
     1.4      if (!dst || !recip->user_id || !recip->address)
     1.5          return PEP_ILLEGAL_VALUE;
     1.6  
     1.7 +    if (!revoke_fpr || !new_fpr)
     1.8 +        return PEP_ILLEGAL_VALUE;
     1.9 +        
    1.10      *dst = NULL;
    1.11      // Get own identity user has corresponded with
    1.12      pEp_identity* own_identity = NULL;
    1.13 @@ -1610,6 +1613,18 @@
    1.14      reset_message->from = own_identity;
    1.15      reset_message->to = new_identity_list(identity_dup(recip)); // ?
    1.16      
    1.17 +    const char* oldtag = "OLD: ";
    1.18 +    const char* newtag = "\nNEW: ";
    1.19 +    const size_t taglens = 11;
    1.20 +    size_t full_len = taglens + strlen(revoke_fpr) + strlen(new_fpr) + 2; // \n and \0
    1.21 +    char* longmsg = calloc(full_len, 1);
    1.22 +     
    1.23 +    strlcpy(longmsg, oldtag, full_len);
    1.24 +    strlcat(longmsg, revoke_fpr, full_len);
    1.25 +    strlcat(longmsg, newtag, full_len);
    1.26 +    strlcat(longmsg, new_fpr);
    1.27 +    strlcat(longmsg, "\n");
    1.28 +    
    1.29      status = _attach_key(session, revoke_fpr, reset_message);
    1.30      if (status != PEP_STATUS_OK)
    1.31          goto pep_free;
    1.32 @@ -3168,6 +3183,111 @@
    1.33      }
    1.34  }
    1.35  
    1.36 +PEP_STATUS receive_key_reset(PEP_SESSION session,
    1.37 +                             message* reset_msg,
    1.38 +                             const char* signing_fpr) {
    1.39 +
    1.40 +    if (!session || !reset_msg || !revoke_fpr || !new_fpr)
    1.41 +        return PEP_ILLEGAL_VALUE;
    1.42 +        
    1.43 +    if (EMPTYSTR(signing_fpr))
    1.44 +        return PEP_ILLEGAL_VALUE; // need better error - this is an attack 
    1.45 +        
    1.46 +    if (!reset_msg->from || !reset_msg->from->user_id)
    1.47 +        return PEP_MALFORMED_KEY_RESET_MSG;
    1.48 +        
    1.49 +    if (is_me(reset_msg->from)) // hrm...
    1.50 +        return PEP_ILLEGAL_VALUE;
    1.51 +        
    1.52 +    if (!reset_msg->longmsg || strncmp(reset_msg->longmsg, "OLD: ", 5) != 0) 
    1.53 +        return PEP_MALFORMED_KEY_RESET_MSG;
    1.54 +
    1.55 +    PEP_STATUS status = PEP_STATUS_OK;
    1.56 +    const char* revoke_fpr = NULL;
    1.57 +    const char* new_fpr = NULL;
    1.58 +    
    1.59 +    stringlist_t* keylist = NULL;
    1.60 +
    1.61 +    // Make sure the signing fpr belongs to the "from" user, since that is 
    1.62 +    // who we are to change defaults for.
    1.63 +    
    1.64 +    // 1. See if this fpr is even associated with this user_id
    1.65 +    const char* sender_id = reset_msg->from->user_id;
    1.66 +    status = exists_trust_entry(session, sender_id, *signing_fpr, user_has_fpr);
    1.67 +    if (status != PEP_STATUS_OK)
    1.68 +        goto pep_free;
    1.69 +        
    1.70 +    if (!user_has_fpr) {   
    1.71 +        status = PEP_KEY_NOT_FOUND;
    1.72 +        goto pep_free;
    1.73 +    }
    1.74 +    
    1.75 +    char* rest = NULL;
    1.76 +    char* p = strtok_r(reset_msg->longmsg, "\n", &rest);
    1.77 +    if (!EMPTYSTR(p + 5))
    1.78 +        revoke_fpr = strdup(p + 5);
    1.79 +    else {
    1.80 +        status = PEP_MALFORMED_KEY_RESET_MSG;
    1.81 +        goto pep_free;
    1.82 +    }
    1.83 +
    1.84 +    // Before we go further, let's be sure this was signed be the revoked fpr.
    1.85 +    if (strcasecmp(revoke_fpr, signing_fpr) != 0) {
    1.86 +        status = PEP_ILLEGAL_VALUE;
    1.87 +        goto pep_free;
    1.88 +    }
    1.89 +        
    1.90 +    // Ok, we can go on. This was a first check, in any event.    
    1.91 +    p = strtok_r(NULL, "\n", &rest); 
    1.92 +    if (strncmp(p, "NEW: ", 5) != 0  || EMPTYSTR(p + 5)) {
    1.93 +        status = PEP_MALFORMED_KEY_RESET_MSG;
    1.94 +        goto pep_free;
    1.95 +    }
    1.96 +
    1.97 +    new_fpr = strdup(p + 5);
    1.98 +        
    1.99 +    // We do NOT want to import private keys - we're trying to make sure nobody
   1.100 +    // tricks us into using one here.
   1.101 +    identity_list* private_il = NULL;
   1.102 +    
   1.103 +    bool imported_keys = import_attached_keys(session, reset_message, &private_il);
   1.104 +
   1.105 +    if (private_il) {
   1.106 +        // This is clearly not a real key reset message. We NEVER distribute
   1.107 +        // private keys this way, so indicate foul play and abort.
   1.108 +        free(private_il);
   1.109 +        status = PEP_MALFORMED_KEY_RESET_MSG;
   1.110 +        goto pep_free;
   1.111 +    }
   1.112 +        
   1.113 +    // We know that the signer has the sender's user_id, and that the revoked fpr
   1.114 +    // is theirs. We now need to make sure that we've imported the key we need.
   1.115 +    
   1.116 +    status = find_keys(session, *new_fpr, &keylist);
   1.117 +    if (status != PEP_STATUS_OK)
   1.118 +        goto pep_free;
   1.119 +        
   1.120 +    if (!keylist) {
   1.121 +        status = PEP_KEY_NOT_FOUND;
   1.122 +        goto pep_free;
   1.123 +    }
   1.124 +
   1.125 +    // alright, we've checked as best we can. Let's set that baby.
   1.126 +    sender_id->from->fpr = new_fpr;
   1.127 +    
   1.128 +    reset_msg->flags |= PEP_decrypt_flag_consume;
   1.129 +    sender_id->comm_type = sender_id->comm_type & (~PEP_ct_confirmed);
   1.130 +    status = set_identity(session, sender_id);
   1.131 +    
   1.132 +    if (status == PEP_STATUS_OK)
   1.133 +        status = PEP_KEY_RESET_SUCCESSFUL;
   1.134 +    
   1.135 +pep_free:    
   1.136 +    free(keylist);    
   1.137 +    free(revoke_fpr);
   1.138 +    free(new_fpr);
   1.139 +    return status;
   1.140 +}
   1.141  
   1.142  DYNAMIC_API PEP_STATUS _decrypt_message(
   1.143          PEP_SESSION session,
   1.144 @@ -3426,13 +3546,35 @@
   1.145                                      inner_message->enc_format = src->enc_format;
   1.146                                      // FIXME
   1.147                                      status = unencapsulate_hidden_fields(inner_message, NULL, &wrap_info);
   1.148 +                                    
   1.149 +                                    // ?
   1.150 +                                    if (status != PEP_STATUS_OK) {
   1.151 +                                        free_message(inner_message);
   1.152 +                                        goto pep_error;
   1.153 +                                    }
   1.154 +    
   1.155                                      if (wrap_info) {
   1.156 -                                        // useless check, but just in case we screw up?
   1.157 -                                        if (strcmp(wrap_info, "INNER") == 0) {
   1.158 +                                        bool is_inner = (strcmp(wrap_info, "INNER") == 0);
   1.159 +                                        bool is_key_reset = (strcmp(wrap_info, "KEY_RESET") == 0)
   1.160 +
   1.161 +                                        if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED && is_key_reset) {
   1.162 +                                            
   1.163 +                                        }
   1.164 +
   1.165 +                                        if (is_key_reset) {
   1.166 +                                            const char* revoke_fpr = NULL;
   1.167 +                                            const char* new_fpr = NULL; 
   1.168 +                                            status = receive_key_reset(session,
   1.169 +                                                                       inner_message,
   1.170 +                                                                       &revoke_fpr,
   1.171 +                                                                       &new_fpr);
   1.172                                              if (status != PEP_STATUS_OK) {
   1.173                                                  free_message(inner_message);
   1.174                                                  goto pep_error;
   1.175                                              }
   1.176 +                                            
   1.177 +                                        }
   1.178 +                                        if (is_inner || is_key_reset) {
   1.179  
   1.180                                              // check for private key in decrypted message attachment while importing
   1.181                                              // N.B. Apparently, we always import private keys into the keyring; however,
   1.182 @@ -3457,10 +3599,19 @@
   1.183                                              // needed...
   1.184                                              reconcile_src_and_inner_messages(src, inner_message);
   1.185                                              
   1.186 +
   1.187 +                                            if (is_key_reset) {
   1.188 +                                                // FIXME: WE HAVE TO DO WAY MORE THAN THIS.
   1.189 +                                                // Key reset message needs to contain both old and new key fprs.
   1.190 +                                                // We need to check this here.
   1.191 +                                                inner_message->flags |= PEP_decrypt_flag_consume;
   1.192 +                                            }
   1.193 +    
   1.194                                              // FIXME: free msg, but check references
   1.195                                              //src = msg = inner_message;
   1.196                                              calculated_src = msg = inner_message;
   1.197                                              
   1.198 +                                            // FIXME: should this be msg???
   1.199                                              if (src->from) {
   1.200                                                  if (!is_me(session, src->from))
   1.201                                                      update_identity(session, (src->from));
     2.1 --- a/src/pEpEngine.h	Fri Aug 03 12:20:08 2018 +0200
     2.2 +++ b/src/pEpEngine.h	Tue Aug 07 10:24:10 2018 +0200
     2.3 @@ -52,6 +52,8 @@
     2.4      PEP_CANNOT_EXPORT_KEY                           = 0x0204,
     2.5      PEP_CANNOT_EDIT_KEY                             = 0x0205,
     2.6      PEP_KEY_UNSUITABLE                              = 0x0206,
     2.7 +    PEP_KEY_RESET_SUCCESSFUL                        = 0x0210,
     2.8 +    PEP_MALFORMED_KEY_RESET_MSG                     = 0x0211,
     2.9      
    2.10      PEP_CANNOT_FIND_IDENTITY                        = 0x0301,
    2.11      PEP_CANNOT_SET_PERSON                           = 0x0381,