ENGINE-332: rewrite complete, but needs checking and testing. ENGINE-332
authorKrista Bennett <krista@pep-project.org>
Mon, 22 Jan 2018 11:11:38 +0100
branchENGINE-332
changeset 24335ecf504e88eb
parent 2432 946a64545ddf
child 2435 66750e44dc49
ENGINE-332: rewrite complete, but needs checking and testing.
src/keymanagement.c
src/pEpEngine.c
src/pEpEngine.h
src/pEp_internal.h
     1.1 --- a/src/keymanagement.c	Fri Jan 19 17:36:12 2018 +0100
     1.2 +++ b/src/keymanagement.c	Mon Jan 22 11:11:38 2018 +0100
     1.3 @@ -21,6 +21,13 @@
     1.4  
     1.5  #define KEY_EXPIRE_DELTA (60 * 60 * 24 * 365)
     1.6  
     1.7 +#ifndef _MIN
     1.8 +#define _MIN(A, B) ((B) > (A) ? (A) : (B))
     1.9 +#endif
    1.10 +#ifndef _MAX
    1.11 +#define _MAX(A, B) ((B) > (A) ? (B) : (A))
    1.12 +#endif
    1.13 +
    1.14  
    1.15  static bool key_matches_address(PEP_SESSION session, const char* address,
    1.16                                  const char* fpr) {
    1.17 @@ -1149,39 +1156,101 @@
    1.18              EMPTYSTR(ident->fpr))
    1.19          return PEP_ILLEGAL_VALUE;
    1.20  
    1.21 +    bool ident_has_trusted_default = false;
    1.22 +    char* ident_default_fpr = NULL;
    1.23 +
    1.24 +    // Before we do anything, be sure the input fpr is even eligible to be trusted
    1.25 +    PEP_comm_type input_default_ct = PEP_ct_unknown;
    1.26 +    status = get_key_rating(session, ident->fpr, &input_default_ct);
    1.27 +    if (input_default_ct < PEP_ct_strong_but_unconfirmed)
    1.28 +        return PEP_KEY_UNSUITABLE;
    1.29 +
    1.30 +    // Save the input fpr
    1.31 +    char* cached_fpr = strdup(ident->fpr);
    1.32 +    ident->fpr = NULL;
    1.33 +
    1.34      bool me = is_me(session, ident);
    1.35  
    1.36      if (me)
    1.37 -        status = myself(session, ident);
    1.38 -    else {
    1.39 -        char* saved_fpr = ident->fpr;
    1.40 -        ident->fpr = NULL;
    1.41 +        return myself(session, ident); // FIXME: Not the right thing if we 
    1.42 +                                       // don't always replace user default!!!
    1.43 +
    1.44 +    // First, set up a temp trusted identity for the input fpr without a comm type;
    1.45 +    pEp_identity* tmp_id = new_identity(ident->address, cached_fpr, ident->user_id, NULL);
    1.46 +    status = validate_fpr(session, tmp_id);
    1.47          
    1.48 +    if (status == PEP_STATUS_OK) {
    1.49 +        // Validate fpr gets trust DB or, when that fails, key comm type. we checked
    1.50 +        // above that the key was ok. (not revoked or expired), but we want the max.
    1.51 +        tmp_id->comm_type = _MAX(tmp_id->comm_type, input_default_ct) | PEP_ct_confirmed;
    1.52 +                                       
    1.53 +        // Get the default identity without setting the fpr
    1.54          status = update_identity(session, ident);
    1.55 -        
    1.56 -        if (EMPTYSTR(ident->fpr) || strcmp(ident->fpr, saved_fpr) != 0) {
    1.57 -            ident->fpr = saved_fpr;
    1.58 -            ident->comm_type = PEP_ct_unknown;
    1.59 -            status = set_identity(session, ident);
    1.60 -            if (status == PEP_STATUS_OK)
    1.61 -                status = update_identity(session, ident);
    1.62 +        ident_default_fpr = strdup(ident->fpr);
    1.63 +
    1.64 +        if (status == PEP_STATUS_OK) {
    1.65 +            bool trusted_default = false;
    1.66 +
    1.67 +            // If there's no default, or the default is different from the input...
    1.68 +            if (EMPTYSTR(ident_default_fpr) || strcmp(cached_fpr, ident_default_fpr) != 0) {
    1.69 +                
    1.70 +                // If the default fpr (if there is one) is trusted and key is strong enough,
    1.71 +                // don't replace, we just set the trusted bit on this key for this user_id...
    1.72 +                // (If there's no default fpr, this won't be true anyway.)
    1.73 +                if (ident->comm_type >= PEP_ct_strong_but_unconfirmed && 
    1.74 +                    (ident->comm_type & PEP_ct_confirmed)) {                        
    1.75 +
    1.76 +                    trusted_default = true;
    1.77 +                                    
    1.78 +                    status = set_trust(session, tmp_id->user_id, cached_fpr, tmp_id->comm_type);
    1.79 +                    input_default_ct = tmp_id->comm_type;                    
    1.80 +                }
    1.81 +                else {
    1.82 +                    free(ident->fpr);
    1.83 +                    ident->fpr = strdup(cached_fpr);
    1.84 +                    ident->comm_type = tmp_id->comm_type;
    1.85 +                    status = set_identity(session, ident); // replace identity default            
    1.86 +                }
    1.87 +            }
    1.88 +            else { // we're setting this on the default fpr
    1.89 +                ident->comm_type = tmp_id->comm_type;
    1.90 +                status = set_identity(session, ident);
    1.91 +                trusted_default = true;
    1.92 +            }
    1.93 +            if (status == PEP_STATUS_OK) {
    1.94 +                // Ok, there wasn't a trusted default, so we replaced. Thus, we also
    1.95 +                // make sure there's a trusted default on the user_id. If there
    1.96 +                // is not, we make this the default.
    1.97 +
    1.98 +                char* user_default = NULL;
    1.99 +            
   1.100 +                status = get_main_user_fpr(session, ident->user_id, &user_default);
   1.101 +            
   1.102 +                if (status == PEP_STATUS_OK && user_default) {
   1.103 +                    pEp_identity* tmp_user_ident = new_identity(ident->address, 
   1.104 +                                                                user_default, 
   1.105 +                                                                ident->user_id, 
   1.106 +                                                                NULL);
   1.107 +                    if (!tmp_user_ident)
   1.108 +                        status = PEP_OUT_OF_MEMORY;
   1.109 +                    else {
   1.110 +                        status = validate_fpr(session, tmp_user_ident);
   1.111 +                        
   1.112 +                        if (status != PEP_STATUS_OK ||
   1.113 +                            tmp_user_ident->comm_type < PEP_ct_strong_but_unconfirmed ||
   1.114 +                            !(tmp_user_ident->comm_type & PEP_ct_confirmed)) 
   1.115 +                        {
   1.116 +                            char* trusted_fpr = (trusted_default ? ident_default_fpr : cached_fpr);
   1.117 +                            status = replace_main_user_fpr(session, ident->user_id, trusted_fpr);
   1.118 +                        } 
   1.119 +                    }
   1.120 +                }
   1.121 +            }
   1.122          }
   1.123 -        // either saved_fpr got copied in update_identity and we're done
   1.124 -        // with it, or it's not referenced anymore because we didn't call
   1.125 -        // it.
   1.126 -        free(saved_fpr);            
   1.127 -    } 
   1.128 -    if (status != PEP_STATUS_OK)
   1.129 -        return status;
   1.130 -
   1.131 -    if (ident->comm_type > PEP_ct_strong_but_unconfirmed) {
   1.132 -        ident->comm_type |= PEP_ct_confirmed;
   1.133 -        status = set_identity(session, ident);
   1.134 -    }
   1.135 -    else {
   1.136 -        // MISSING: S/MIME has to be handled depending on trusted CAs
   1.137 -        status = PEP_CANNOT_SET_TRUST;
   1.138 -    }
   1.139 +        free(ident_default_fpr);
   1.140 +        free(cached_fpr); // we took ownership upon successful update_identity call above
   1.141 +        free_identity(tmp_id);
   1.142 +    }    
   1.143  
   1.144      return status;
   1.145  }
     2.1 --- a/src/pEpEngine.c	Fri Jan 19 17:36:12 2018 +0100
     2.2 +++ b/src/pEpEngine.c	Mon Jan 22 11:11:38 2018 +0100
     2.3 @@ -113,6 +113,15 @@
     2.4      "update person set id = ?1 " 
     2.5      "where id = ?2;";
     2.6  
     2.7 +static const char *sql_replace_main_user_fpr =  
     2.8 +    "update person"
     2.9 +    "   set main_key_id = ?1 "
    2.10 +    "   where id = ?2 ;";
    2.11 +
    2.12 +static const char *sql_get_main_user_fpr =  
    2.13 +    "select main_key_id from person"
    2.14 +    "   where id = ?1 ;";
    2.15 +
    2.16  static const char *sql_get_device_group = 
    2.17      "select device_group from person "
    2.18      "where id = ?1;";
    2.19 @@ -823,6 +832,14 @@
    2.20              (int)strlen(sql_replace_userid), &_session->replace_userid, NULL);
    2.21      assert(int_result == SQLITE_OK);
    2.22  
    2.23 +    int_result = sqlite3_prepare_v2(_session->db, sql_replace_main_user_fpr,
    2.24 +            (int)strlen(sql_replace_main_user_fpr), &_session->replace_main_user_fpr, NULL);
    2.25 +    assert(int_result == SQLITE_OK);
    2.26 +
    2.27 +    int_result = sqlite3_prepare_v2(_session->db, sql_get_main_user_fpr,
    2.28 +            (int)strlen(sql_get_main_user_fpr), &_session->get_main_user_fpr, NULL);
    2.29 +    assert(int_result == SQLITE_OK);
    2.30 +
    2.31      int_result = sqlite3_prepare_v2(_session->db, sql_replace_identities_fpr,
    2.32              (int)strlen(sql_replace_identities_fpr), 
    2.33              &_session->replace_identities_fpr, NULL);
    2.34 @@ -1117,6 +1134,10 @@
    2.35                  sqlite3_finalize(session->i18n_token);
    2.36              if (session->replace_userid)
    2.37                  sqlite3_finalize(session->replace_userid);
    2.38 +            if (session->replace_main_user_fpr)
    2.39 +                sqlite3_finalize(session->replace_main_user_fpr);                
    2.40 +            if (session->get_main_user_fpr)
    2.41 +                sqlite3_finalize(session->get_main_user_fpr);                    
    2.42              if (session->blacklist_add)
    2.43                  sqlite3_finalize(session->blacklist_add);
    2.44              if (session->blacklist_delete)
    2.45 @@ -1791,7 +1812,7 @@
    2.46      bool has_fpr = (identity->fpr && identity->fpr[0] != '\0');
    2.47      
    2.48      if (has_fpr) {    
    2.49 -        // blacklist check
    2.50 +        // blacklist check - FIXME: ENGINE-294 will remove
    2.51          status = blacklist_is_listed(session, identity->fpr, &listed);
    2.52          assert(status == PEP_STATUS_OK);
    2.53          if (status != PEP_STATUS_OK)
    2.54 @@ -2123,6 +2144,69 @@
    2.55      return PEP_STATUS_OK;
    2.56  }
    2.57  
    2.58 +PEP_STATUS replace_main_user_fpr(PEP_SESSION session, const char* user_id,
    2.59 +                                 const char* new_fpr) {
    2.60 +    assert(session);
    2.61 +    assert(user_id);
    2.62 +    assert(new_fpr);
    2.63 +    
    2.64 +    if (!session || !user_id || !new_fpr)
    2.65 +        return PEP_ILLEGAL_VALUE;
    2.66 +
    2.67 +    int result;
    2.68 +
    2.69 +    sqlite3_reset(session->replace_main_user_fpr);
    2.70 +    sqlite3_bind_text(session->replace_main_user_fpr, 1, new_fpr, -1,
    2.71 +            SQLITE_STATIC);
    2.72 +    sqlite3_bind_text(session->replace_main_user_fpr, 2, user_id, -1,
    2.73 +            SQLITE_STATIC);
    2.74 +    result = sqlite3_step(session->replace_main_user_fpr);
    2.75 +    sqlite3_reset(session->replace_main_user_fpr);
    2.76 +    if (result != SQLITE_DONE)
    2.77 +        return PEP_CANNOT_SET_PERSON;
    2.78 +
    2.79 +    return PEP_STATUS_OK;
    2.80 +}
    2.81 +
    2.82 +PEP_STATUS get_main_user_fpr(PEP_SESSION session, 
    2.83 +                                         const char* user_id,
    2.84 +                                         char** main_fpr)
    2.85 +{
    2.86 +    PEP_STATUS status = PEP_STATUS_OK;
    2.87 +    int result;
    2.88 +    
    2.89 +    assert(session);
    2.90 +    assert(user_id);
    2.91 +    assert(main_fpr);
    2.92 +    
    2.93 +    if (!(session && user_id && user_id[0] && main_fpr))
    2.94 +        return PEP_ILLEGAL_VALUE;
    2.95 +        
    2.96 +    *main_fpr = NULL;
    2.97 +    
    2.98 +    sqlite3_reset(session->get_main_user_fpr);
    2.99 +    sqlite3_bind_text(session->get_main_user_fpr, 1, user_id, -1,
   2.100 +                      SQLITE_STATIC);
   2.101 +    result = sqlite3_step(session->get_main_user_fpr);
   2.102 +    switch (result) {
   2.103 +    case SQLITE_ROW: {
   2.104 +        const char* _fpr = 
   2.105 +            (const char *) sqlite3_column_text(session->get_main_user_fpr, 0);
   2.106 +        if (_fpr)
   2.107 +            *main_fpr = strdup(_fpr);
   2.108 +        if (!(*main_fpr))
   2.109 +            status = PEP_OUT_OF_MEMORY;
   2.110 +        break;
   2.111 +    }
   2.112 +    default:
   2.113 +        status = PEP_CANNOT_FIND_PERSON;
   2.114 +    }
   2.115 +
   2.116 +    sqlite3_reset(session->get_main_user_fpr);
   2.117 +    return status;
   2.118 +}
   2.119 +
   2.120 +
   2.121  DYNAMIC_API PEP_STATUS mark_as_compromized(
   2.122          PEP_SESSION session,
   2.123          const char *fpr
   2.124 @@ -2153,6 +2237,36 @@
   2.125      free(p);
   2.126  }
   2.127  
   2.128 +PEP_STATUS set_trust(PEP_SESSION session, 
   2.129 +                     const char* user_id,
   2.130 +                     const char* fpr, 
   2.131 +                     PEP_comm_type comm_type) 
   2.132 +{
   2.133 +    assert(session);
   2.134 +    assert(user_id);
   2.135 +    assert(fpr);
   2.136 +    
   2.137 +    if (!session || !user_id || user_id[0] == '\0' || !fpr || fpr[0] == '\0')
   2.138 +        return PEP_ILLEGAL_VALUE;
   2.139 +        
   2.140 +    int result;
   2.141 +                
   2.142 +    sqlite3_reset(session->set_trust);
   2.143 +    sqlite3_bind_text(session->set_trust, 1, user_id, -1,
   2.144 +            SQLITE_STATIC);
   2.145 +    sqlite3_bind_text(session->set_trust, 2, fpr, -1,
   2.146 +            SQLITE_STATIC);
   2.147 +    sqlite3_bind_int(session->set_trust, 3, comm_type);
   2.148 +    result = sqlite3_step(session->set_trust);
   2.149 +    assert(result == SQLITE_DONE);
   2.150 +    sqlite3_reset(session->set_trust);
   2.151 +    if (result != SQLITE_DONE)
   2.152 +        return PEP_CANNOT_SET_TRUST;
   2.153 +
   2.154 +    return PEP_STATUS_OK;
   2.155 +}
   2.156 +
   2.157 +
   2.158  DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
   2.159  {
   2.160      PEP_STATUS status = PEP_STATUS_OK;
     3.1 --- a/src/pEpEngine.h	Fri Jan 19 17:36:12 2018 +0100
     3.2 +++ b/src/pEpEngine.h	Mon Jan 22 11:11:38 2018 +0100
     3.3 @@ -58,6 +58,7 @@
     3.4      PEP_CANNOT_SET_IDENTITY                         = 0x0383,
     3.5      PEP_CANNOT_SET_TRUST                            = 0x0384,
     3.6      PEP_KEY_BLACKLISTED                             = 0x0385,
     3.7 +    PEP_CANNOT_FIND_PERSON                          = 0x0386,
     3.8      
     3.9      PEP_CANNOT_FIND_ALIAS                           = 0x0391,
    3.10      PEP_CANNOT_SET_ALIAS                            = 0x0392,
    3.11 @@ -668,6 +669,7 @@
    3.12          const char* default_id,
    3.13          const char* alias_id);
    3.14  
    3.15 +
    3.16  // set_device_group() - update own person's device group
    3.17  //
    3.18  //    parameters:
    3.19 @@ -1217,6 +1219,13 @@
    3.20  PEP_STATUS remove_fpr_as_default(PEP_SESSION session, 
    3.21                                      const char* fpr);
    3.22                                
    3.23 +                                    
    3.24 +PEP_STATUS get_main_user_fpr(PEP_SESSION session, 
    3.25 +                             const char* user_id,
    3.26 +                             char** main_fpr);
    3.27 +
    3.28 +PEP_STATUS replace_main_user_fpr(PEP_SESSION session, const char* user_id,
    3.29 +                              const char* new_fpr);
    3.30      
    3.31  #ifdef __cplusplus
    3.32  }
     4.1 --- a/src/pEp_internal.h	Fri Jan 19 17:36:12 2018 +0100
     4.2 +++ b/src/pEp_internal.h	Mon Jan 22 11:11:38 2018 +0100
     4.3 @@ -126,6 +126,8 @@
     4.4      sqlite3_stmt *get_identity_without_trust_check;
     4.5      sqlite3_stmt *get_identities_by_address;
     4.6      sqlite3_stmt *replace_identities_fpr;
     4.7 +    sqlite3_stmt *replace_main_user_fpr;
     4.8 +    sqlite3_stmt *get_main_user_fpr;
     4.9      sqlite3_stmt *remove_fpr_as_default;
    4.10      sqlite3_stmt *set_person;
    4.11      sqlite3_stmt *set_device_group;