Merged in ENGINE-750 sync
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Wed, 06 May 2020 16:24:32 +0200
branchsync
changeset 4665f067c9e95455
parent 4662 71147c43e31b
parent 4664 58871a444403
child 4666 a26edeb42142
Merged in ENGINE-750
.hgtags
src/pEpEngine.h
     1.1 --- a/.hgtags	Wed May 06 00:31:29 2020 +0200
     1.2 +++ b/.hgtags	Wed May 06 16:24:32 2020 +0200
     1.3 @@ -29,5 +29,4 @@
     1.4  c4eb9bb2008fbe531f892fd56f8edce53048eb62 2.0.0-RC
     1.5  c71ec33fb34612be1d35629de5169f3489975b05 Release_2.0.0
     1.6  b5ce496201c0e534c81d18f8447101e39762ec36 Release_2.0.1
     1.7 -f7633443ef921ed222519347720b0a7276b3ef6a 2.0.1_target
     1.8 -0000000000000000000000000000000000000000 2.0.1_target
     1.9 +f7633443ef921ed222519347720b0a7276b3ef6a 2.1.0_target
     2.1 --- a/src/keymanagement.c	Wed May 06 00:31:29 2020 +0200
     2.2 +++ b/src/keymanagement.c	Wed May 06 16:24:32 2020 +0200
     2.3 @@ -2023,6 +2023,100 @@
     2.4      return status;
     2.5  }
     2.6  
     2.7 +static PEP_STATUS _wipe_default_key_if_invalid(PEP_SESSION session,
     2.8 +                                         pEp_identity* ident) {
     2.9 +    
    2.10 +    PEP_STATUS status = PEP_STATUS_OK;
    2.11 +    
    2.12 +    if (!ident->user_id)
    2.13 +        return PEP_ILLEGAL_VALUE;
    2.14 +        
    2.15 +    if (!ident->fpr)
    2.16 +        return status;
    2.17 +    
    2.18 +    char* cached_fpr = strdup(ident->fpr);
    2.19 +    if (!ident->fpr)
    2.20 +        return PEP_OUT_OF_MEMORY;
    2.21 +        
    2.22 +    PEP_STATUS keystatus = validate_fpr(session, ident, true, false);
    2.23 +    switch (keystatus) {
    2.24 +        case PEP_STATUS_OK:
    2.25 +            // Check for non-renewable expiry and 
    2.26 +            // if so, fallthrough
    2.27 +            if (ident->comm_type != PEP_ct_key_expired_but_confirmed &&
    2.28 +                    ident->comm_type != PEP_ct_key_expired) {
    2.29 +                break;
    2.30 +            }        
    2.31 +        case PEP_KEY_UNSUITABLE:
    2.32 +        case PEP_KEY_BLACKLISTED:
    2.33 +            // Remove key as default for all identities and users 
    2.34 +            status = remove_fpr_as_default(session, cached_fpr);
    2.35 +            break;   
    2.36 +        default:
    2.37 +            break;
    2.38 +    }     
    2.39 +    free(cached_fpr);
    2.40 +    
    2.41 +    if (status == PEP_STATUS_OK)
    2.42 +        status = myself(session, ident);
    2.43 +            
    2.44 +    return status;                                        
    2.45 +}
    2.46 +
    2.47 +PEP_STATUS clean_own_key_defaults(PEP_SESSION session) {
    2.48 +    identity_list* idents = NULL;
    2.49 +    PEP_STATUS status = own_identities_retrieve(session, &idents);
    2.50 +    if (status != PEP_STATUS_OK)
    2.51 +        return status;
    2.52 +        
    2.53 +    if (!idents)
    2.54 +        return PEP_STATUS_OK;
    2.55 +
    2.56 +    if (!idents->ident && !idents->next) {
    2.57 +        free_identity_list(idents);
    2.58 +        return PEP_STATUS_OK;
    2.59 +    } // Kludge: FIX own_identities_retrieve. Should return NULL, not empty list    
    2.60 +        
    2.61 +    identity_list* curr = idents;
    2.62 +    
    2.63 +    for ( ; curr ; curr = curr->next) {
    2.64 +        pEp_identity* ident = curr->ident;
    2.65 +        if (!ident)
    2.66 +            continue;
    2.67 +        
    2.68 +        _wipe_default_key_if_invalid(session, ident);    
    2.69 +    }   
    2.70 +    
    2.71 +    free_identity_list(idents);
    2.72 +    
    2.73 +    // Also remove invalid default user key
    2.74 +    char* own_id = NULL;
    2.75 +
    2.76 +    status = get_default_own_userid(session, &own_id);
    2.77 +
    2.78 +    if (status != PEP_STATUS_OK)
    2.79 +        return status;
    2.80 +
    2.81 +    if (own_id) {
    2.82 +        char* user_default_key = NULL;
    2.83 +        status = get_user_default_key(session, own_id, &user_default_key);
    2.84 +        if (status != PEP_STATUS_OK) {
    2.85 +            free(own_id);
    2.86 +            if (status == PEP_KEY_NOT_FOUND)
    2.87 +                status = PEP_STATUS_OK;
    2.88 +            else
    2.89 +                return status;
    2.90 +        }
    2.91 +        else if (user_default_key) {
    2.92 +            pEp_identity* empty_user = new_identity(NULL, user_default_key, NULL, own_id);
    2.93 +            _wipe_default_key_if_invalid(session, empty_user);       
    2.94 +            free(user_default_key);
    2.95 +        }
    2.96 +        free(own_id);    
    2.97 +    }
    2.98 +    return status;
    2.99 +}
   2.100 +
   2.101  #ifdef USE_GPG
   2.102  PEP_STATUS pgp_find_trusted_private_keys(
   2.103          PEP_SESSION session, stringlist_t **keylist
     3.1 --- a/src/keymanagement.h	Wed May 06 00:31:29 2020 +0200
     3.2 +++ b/src/keymanagement.h	Wed May 06 16:24:32 2020 +0200
     3.3 @@ -408,6 +408,8 @@
     3.4                              bool* is_address_default,
     3.5                              bool check_blacklist);
     3.6  
     3.7 +PEP_STATUS clean_own_key_defaults(PEP_SESSION session);
     3.8 +
     3.9  #ifdef __cplusplus
    3.10  }
    3.11  #endif
     4.1 --- a/src/pEpEngine.c	Wed May 06 00:31:29 2020 +0200
     4.2 +++ b/src/pEpEngine.c	Wed May 06 16:24:32 2020 +0200
     4.3 @@ -85,8 +85,8 @@
     4.4      "   is_own, pEp_version_major, pEp_version_minor"
     4.5      "   from identity"
     4.6      "   join person on id = identity.user_id"
     4.7 -    "   join pgp_keypair on fpr = identity.main_key_id"
     4.8 -    "   join trust on id = trust.user_id"
     4.9 +    "   left join pgp_keypair on fpr = identity.main_key_id"
    4.10 +    "   left join trust on id = trust.user_id"
    4.11      "       and pgp_keypair_fpr = identity.main_key_id"    
    4.12      "   where (case when (address = ?1) then (1)"
    4.13      "               when (lower(address) = lower(?1)) then (1)"
    4.14 @@ -103,8 +103,8 @@
    4.15      "   is_own, pEp_version_major, pEp_version_minor"
    4.16      "   from identity"
    4.17      "   join person on id = identity.user_id"
    4.18 -    "   join pgp_keypair on fpr = identity.main_key_id"
    4.19 -    "   join trust on id = trust.user_id"
    4.20 +    "   left join pgp_keypair on fpr = identity.main_key_id"
    4.21 +    "   left join trust on id = trust.user_id"
    4.22      "       and pgp_keypair_fpr = identity.main_key_id"    
    4.23      "   where identity.main_key_id = ?1" 
    4.24      "   order by is_own desc, "
    4.25 @@ -143,8 +143,8 @@
    4.26      "   is_own, pEp_version_major, pEp_version_minor"
    4.27      "   from identity"
    4.28      "   join person on id = identity.user_id"
    4.29 -    "   join pgp_keypair on fpr = identity.main_key_id"
    4.30 -    "   join trust on id = trust.user_id"
    4.31 +    "   left join pgp_keypair on fpr = identity.main_key_id"
    4.32 +    "   left join trust on id = trust.user_id"
    4.33      "       and pgp_keypair_fpr = identity.main_key_id"    
    4.34      "   where identity.user_id = ?1" 
    4.35      "   order by is_own desc, "
    4.36 @@ -155,10 +155,12 @@
    4.37      "   set main_key_id = ?1 "
    4.38      "   where main_key_id = ?2 ;";
    4.39      
    4.40 -static const char *sql_remove_fpr_as_default =
    4.41 -    "update person set main_key_id = NULL where main_key_id = ?1 ;"
    4.42 +static const char *sql_remove_fpr_as_identity_default =
    4.43      "update identity set main_key_id = NULL where main_key_id = ?1 ;";
    4.44  
    4.45 +static const char *sql_remove_fpr_as_user_default =
    4.46 +    "update person set main_key_id = NULL where main_key_id = ?1 ;";
    4.47 +    
    4.48  // Set person, but if already exist, only update.
    4.49  // if main_key_id already set, don't touch.
    4.50  static const char *sql_set_person = 
    4.51 @@ -431,8 +433,8 @@
    4.52      "   lang, identity.flags | pgp_keypair.flags, pEp_version_major, pEp_version_minor"
    4.53      "   from identity"
    4.54      "   join person on id = identity.user_id"
    4.55 -    "   join pgp_keypair on fpr = identity.main_key_id"
    4.56 -    "   join trust on id = trust.user_id"
    4.57 +    "   left join pgp_keypair on fpr = identity.main_key_id"
    4.58 +    "   left join trust on id = trust.user_id"
    4.59      "       and pgp_keypair_fpr = identity.main_key_id"
    4.60      "   where identity.is_own = 1"
    4.61      "       and (identity.flags & ?1) = 0;";
    4.62 @@ -454,7 +456,7 @@
    4.63      "select id from person"
    4.64      "   join identity on id = identity.user_id"
    4.65      "   where identity.is_own = 1";
    4.66 -
    4.67 +    
    4.68  // Sequence
    4.69  static const char *sql_sequence_value1 = 
    4.70      "insert or replace into sequences (name, value) "
    4.71 @@ -1797,9 +1799,14 @@
    4.72              &_session->replace_identities_fpr, NULL);
    4.73      assert(int_result == SQLITE_OK);
    4.74      
    4.75 -    int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_default,
    4.76 -            (int)strlen(sql_remove_fpr_as_default), 
    4.77 -            &_session->remove_fpr_as_default, NULL);
    4.78 +    int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_identity_default,
    4.79 +            (int)strlen(sql_remove_fpr_as_identity_default), 
    4.80 +            &_session->remove_fpr_as_identity_default, NULL);
    4.81 +    assert(int_result == SQLITE_OK);
    4.82 +
    4.83 +    int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_user_default,
    4.84 +            (int)strlen(sql_remove_fpr_as_user_default), 
    4.85 +            &_session->remove_fpr_as_user_default, NULL);
    4.86      assert(int_result == SQLITE_OK);
    4.87  
    4.88      int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
    4.89 @@ -2080,6 +2087,11 @@
    4.90          status = pgp_import_ultimately_trusted_keypairs(_session);        
    4.91  #endif // USE_GPG
    4.92      }
    4.93 +    
    4.94 +    // clean up invalid keys 
    4.95 +    status = clean_own_key_defaults(_session);
    4.96 +    if (status != PEP_STATUS_OK)
    4.97 +        goto pEp_error;
    4.98  
    4.99      *session = _session;
   4.100      
   4.101 @@ -2145,8 +2157,10 @@
   4.102                  sqlite3_finalize(session->add_userid_alias);
   4.103              if (session->replace_identities_fpr)
   4.104                  sqlite3_finalize(session->replace_identities_fpr);        
   4.105 -            if (session->remove_fpr_as_default)
   4.106 -                sqlite3_finalize(session->remove_fpr_as_default);            
   4.107 +            if (session->remove_fpr_as_identity_default)
   4.108 +                sqlite3_finalize(session->remove_fpr_as_identity_default);            
   4.109 +            if (session->remove_fpr_as_user_default)
   4.110 +                sqlite3_finalize(session->remove_fpr_as_user_default);            
   4.111              if (session->set_person)
   4.112                  sqlite3_finalize(session->set_person);
   4.113              if (session->delete_person)
   4.114 @@ -3814,16 +3828,26 @@
   4.115      if (!session || !fpr)
   4.116          return PEP_ILLEGAL_VALUE;
   4.117              
   4.118 -    sqlite3_reset(session->remove_fpr_as_default);
   4.119 -    sqlite3_bind_text(session->remove_fpr_as_default, 1, fpr, -1,
   4.120 +    sqlite3_reset(session->remove_fpr_as_identity_default);
   4.121 +    sqlite3_bind_text(session->remove_fpr_as_identity_default, 1, fpr, -1,
   4.122                        SQLITE_STATIC);
   4.123  
   4.124 -    int result = sqlite3_step(session->remove_fpr_as_default);
   4.125 -    sqlite3_reset(session->remove_fpr_as_default);
   4.126 +    int result = sqlite3_step(session->remove_fpr_as_identity_default);
   4.127 +    sqlite3_reset(session->remove_fpr_as_identity_default);
   4.128      
   4.129      if (result != SQLITE_DONE)
   4.130 -        return PEP_CANNOT_SET_IDENTITY; // misleading - could also be person
   4.131 -
   4.132 +        return PEP_CANNOT_SET_IDENTITY; 
   4.133 +
   4.134 +    sqlite3_reset(session->remove_fpr_as_user_default);
   4.135 +    sqlite3_bind_text(session->remove_fpr_as_user_default, 1, fpr, -1,
   4.136 +                      SQLITE_STATIC);
   4.137 +
   4.138 +    result = sqlite3_step(session->remove_fpr_as_user_default);
   4.139 +    sqlite3_reset(session->remove_fpr_as_user_default);
   4.140 +    
   4.141 +    if (result != SQLITE_DONE)
   4.142 +        return PEP_CANNOT_SET_PERSON; 
   4.143 +        
   4.144      return PEP_STATUS_OK;
   4.145  }
   4.146  
     6.1 --- a/src/pEp_internal.h	Wed May 06 00:31:29 2020 +0200
     6.2 +++ b/src/pEp_internal.h	Wed May 06 16:24:32 2020 +0200
     6.3 @@ -179,7 +179,8 @@
     6.4      sqlite3_stmt *get_main_user_fpr;
     6.5      sqlite3_stmt *refresh_userid_default_key;
     6.6      sqlite3_stmt *delete_key;
     6.7 -    sqlite3_stmt *remove_fpr_as_default;
     6.8 +    sqlite3_stmt *remove_fpr_as_identity_default;
     6.9 +    sqlite3_stmt *remove_fpr_as_user_default;
    6.10      sqlite3_stmt *set_person;
    6.11      sqlite3_stmt *update_person;
    6.12      sqlite3_stmt *delete_person;
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/src/CleanInvalidOwnKeysTest.cc	Wed May 06 16:24:32 2020 +0200
     7.3 @@ -0,0 +1,125 @@
     7.4 +#include <stdlib.h>
     7.5 +#include <string>
     7.6 +#include <cstring>
     7.7 +
     7.8 +#include "pEpEngine.h"
     7.9 +#include "test_util.h"
    7.10 +#include "TestConstants.h"
    7.11 +#include "Engine.h"
    7.12 +
    7.13 +#include <gtest/gtest.h>
    7.14 +
    7.15 +
    7.16 +namespace {
    7.17 +
    7.18 +	//The fixture for CleanInvalidOwnKeysTest
    7.19 +    class CleanInvalidOwnKeysTest : public ::testing::Test {
    7.20 +        public:
    7.21 +            Engine* engine;
    7.22 +            PEP_SESSION session;
    7.23 +
    7.24 +        protected:
    7.25 +            // You can remove any or all of the following functions if its body
    7.26 +            // is empty.
    7.27 +            CleanInvalidOwnKeysTest() {
    7.28 +                // You can do set-up work for each test here.
    7.29 +                test_suite_name = ::testing::UnitTest::GetInstance()->current_test_info()->GTEST_SUITE_SYM();
    7.30 +                test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
    7.31 +                test_path = get_main_test_home_dir() + "/" + test_suite_name + "/" + test_name;
    7.32 +            }
    7.33 +
    7.34 +            ~CleanInvalidOwnKeysTest() override {
    7.35 +                // You can do clean-up work that doesn't throw exceptions here.
    7.36 +            }
    7.37 +
    7.38 +            // If the constructor and destructor are not enough for setting up
    7.39 +            // and cleaning up each test, you can define the following methods:
    7.40 +
    7.41 +            void SetUp() override {
    7.42 +                // Code here will be called immediately after the constructor (right
    7.43 +                // before each test).
    7.44 +
    7.45 +                // Leave this empty if there are no files to copy to the home directory path
    7.46 +                std::vector<std::pair<std::string, std::string>> init_files = std::vector<std::pair<std::string, std::string>>();
    7.47 +                string keyfile = string("test_files/ENGINE-750_") + test_name + "_keys.db";
    7.48 +                string mgmtfile = string("test_files/ENGINE-750_") + test_name + "_mgmt.db";
    7.49 +                init_files.push_back(std::pair<std::string, std::string>(keyfile, std::string("keys.db")));                
    7.50 +                init_files.push_back(std::pair<std::string, std::string>(mgmtfile, std::string("management.db")));
    7.51 +                
    7.52 +                // Get a new test Engine.
    7.53 +                engine = new Engine(test_path);
    7.54 +                ASSERT_NE(engine, nullptr);
    7.55 +
    7.56 +                // Ok, let's initialize test directories etc.
    7.57 +                engine->prep(NULL, NULL, init_files);
    7.58 +
    7.59 +                // Ok, try to start this bugger.
    7.60 +                engine->start();
    7.61 +                ASSERT_NE(engine->session, nullptr);
    7.62 +                session = engine->session;
    7.63 +
    7.64 +                // Engine is up. Keep on truckin'
    7.65 +            }
    7.66 +
    7.67 +            void TearDown() override {
    7.68 +                // Code here will be called immediately after each test (right
    7.69 +                // before the destructor).
    7.70 +                engine->shut_down();
    7.71 +                delete engine;
    7.72 +                engine = NULL;
    7.73 +                session = NULL;
    7.74 +            }
    7.75 +
    7.76 +        private:
    7.77 +            const char* test_suite_name;
    7.78 +            const char* test_name;
    7.79 +            string test_path;
    7.80 +            // Objects declared here can be used by all tests in the CleanInvalidOwnKeysTest suite.
    7.81 +
    7.82 +    };
    7.83 +
    7.84 +}  // namespace
    7.85 +
    7.86 +
    7.87 +TEST_F(CleanInvalidOwnKeysTest, check_clean_invalid_own_keys_no_alts_revoked) {
    7.88 +    // This is just a dummy test case. The convention is check_whatever_you_are_checking
    7.89 +    // so for multiple test cases in a suite, be more explicit ;)   
    7.90 +    pEp_identity* alice = NULL;
    7.91 +    PEP_STATUS status = get_identity(session, "pep.test.alice@pep-project.org", "ALICE", &alice);
    7.92 +    ASSERT_EQ(status, PEP_STATUS_OK);
    7.93 +    ASSERT_EQ(alice->fpr, nullptr);
    7.94 +    char* fpr = NULL;
    7.95 +    status = get_user_default_key(session, "ALICE", &fpr);
    7.96 +    ASSERT_EQ(fpr, nullptr);
    7.97 +    ASSERT_EQ(status, PEP_STATUS_OK);    
    7.98 +}
    7.99 +
   7.100 +TEST_F(CleanInvalidOwnKeysTest, check_clean_invalid_own_keys_no_alts_mistrusted) {
   7.101 +    // This is just a dummy test case. The convention is check_whatever_you_are_checking
   7.102 +    // so for multiple test cases in a suite, be more explicit ;)   
   7.103 +    pEp_identity* alice = NULL;
   7.104 +    PEP_STATUS status = get_identity(session, "pep.test.alice@pep-project.org", "ALICE", &alice);
   7.105 +    ASSERT_EQ(status, PEP_STATUS_OK);
   7.106 +    ASSERT_EQ(alice->fpr, nullptr);
   7.107 +    char* fpr = NULL;
   7.108 +    status = get_user_default_key(session, "ALICE", &fpr);
   7.109 +    ASSERT_EQ(fpr, nullptr);
   7.110 +    ASSERT_EQ(status, PEP_STATUS_OK);    
   7.111 +}
   7.112 +
   7.113 +TEST_F(CleanInvalidOwnKeysTest, check_clean_invalid_own_keys_no_alts_expired) {
   7.114 +    // This is just a dummy test case. The convention is check_whatever_you_are_checking
   7.115 +    // so for multiple test cases in a suite, be more explicit ;)   
   7.116 +    pEp_identity* bob = NULL;
   7.117 +    PEP_STATUS status = get_identity(session, "expired_bob_0@darthmama.org", "BOB", &bob);
   7.118 +    ASSERT_EQ(status, PEP_STATUS_OK);
   7.119 +    ASSERT_NE(bob->fpr, nullptr);
   7.120 +    char* fpr = NULL;
   7.121 +    status = get_user_default_key(session, "BOB", &fpr);
   7.122 +    ASSERT_NE(fpr, nullptr);
   7.123 +    ASSERT_EQ(status, PEP_STATUS_OK);    
   7.124 +    bool expired = true;
   7.125 +    status = key_expired(session, bob->fpr, time(NULL), &expired);
   7.126 +    ASSERT_FALSE(expired);
   7.127 +    ASSERT_STREQ(bob->fpr, fpr);
   7.128 +}
     8.1 Binary file test/test_files/ENGINE-750_check_clean_invalid_own_keys_no_alts_expired_keys.db has changed
     9.1 Binary file test/test_files/ENGINE-750_check_clean_invalid_own_keys_no_alts_expired_mgmt.db has changed
    10.1 Binary file test/test_files/ENGINE-750_check_clean_invalid_own_keys_no_alts_mistrusted_keys.db has changed
    11.1 Binary file test/test_files/ENGINE-750_check_clean_invalid_own_keys_no_alts_mistrusted_mgmt.db has changed
    12.1 Binary file test/test_files/ENGINE-750_check_clean_invalid_own_keys_no_alts_revoked_keys.db has changed
    13.1 Binary file test/test_files/ENGINE-750_check_clean_invalid_own_keys_no_alts_revoked_mgmt.db has changed