ENGINE-112: #comment Fixed empty fpr problems in stored identities which occurred due to blacklisting. When adding other keys, we now check to see if there is a matching identity entry which lacks an fpr and, if so, we update it instead of adding a new one. Also fixed elect_pubkey NOT to return blacklisted pubkeys. ENGINE-112
authorKrista Grothoff <krista@pep-project.org>
Thu, 13 Oct 2016 16:22:09 +0200
branchENGINE-112
changeset 127539dfd55d21ee
parent 1274 e35e9eada9ca
child 1276 a926b9e401ee
child 1277 e60902b9f1a7
ENGINE-112: #comment Fixed empty fpr problems in stored identities which occurred due to blacklisting. When adding other keys, we now check to see if there is a matching identity entry which lacks an fpr and, if so, we update it instead of adding a new one. Also fixed elect_pubkey NOT to return blacklisted pubkeys.
src/keymanagement.c
src/pEpEngine.c
src/pEp_internal.h
test/blacklist_test.cc
     1.1 --- a/src/keymanagement.c	Wed Oct 12 23:08:45 2016 +0200
     1.2 +++ b/src/keymanagement.c	Thu Oct 13 16:22:09 2016 +0200
     1.3 @@ -49,8 +49,12 @@
     1.4              if (identity->comm_type == PEP_ct_unknown ||
     1.5                  _comm_type_key > identity->comm_type)
     1.6              {
     1.7 -                identity->comm_type = _comm_type_key;
     1.8 -                _fpr = _keylist->value;
     1.9 +                bool blacklisted;
    1.10 +                status = blacklist_is_listed(session, _keylist->value, &blacklisted);
    1.11 +                if (status == PEP_STATUS_OK && !blacklisted) {
    1.12 +                    identity->comm_type = _comm_type_key;
    1.13 +                    _fpr = _keylist->value;
    1.14 +                }
    1.15              }
    1.16          }
    1.17      }
     2.1 --- a/src/pEpEngine.c	Wed Oct 12 23:08:45 2016 +0200
     2.2 +++ b/src/pEpEngine.c	Thu Oct 13 16:22:09 2016 +0200
     2.3 @@ -32,6 +32,8 @@
     2.4      static const char *sql_get_device_group;
     2.5      static const char *sql_set_pgp_keypair;
     2.6      static const char *sql_set_identity;
     2.7 +    static const char *sql_exists_empty_fpr_entry;
     2.8 +    static const char *sql_update_fprless_identity;
     2.9      static const char *sql_set_identity_flags;
    2.10      static const char *sql_set_trust;
    2.11      static const char *sql_get_trust;
    2.12 @@ -46,7 +48,7 @@
    2.13      static const char *sql_blacklist_delete;
    2.14      static const char *sql_blacklist_is_listed;
    2.15      static const char *sql_blacklist_retrieve;
    2.16 -
    2.17 +    
    2.18      // Own keys
    2.19      static const char *sql_own_key_is_listed;
    2.20      static const char *sql_own_identities_retrieve;
    2.21 @@ -334,6 +336,13 @@
    2.22          sql_set_identity = "insert or replace into identity (address, main_key_id, "
    2.23                             "user_id, flags) values (?1, upper(replace(?2,' ','')),"
    2.24                             "?3, ?4 & 255) ;";
    2.25 +        
    2.26 +        sql_exists_empty_fpr_entry = "select count(*) from identity where address = ?1 and user_id = ?2 "
    2.27 +                                        "and (main_key_id is null or main_key_id = '');";
    2.28 +                
    2.29 +        sql_update_fprless_identity = "update identity set main_key_id = upper(replace(?2,' ','')), "
    2.30 +                                         "flags = ?4 & 255 where address = ?1 and user_id = ?3 and "
    2.31 +                                         "(main_key_id is null or main_key_id = '');";
    2.32  
    2.33          sql_set_identity_flags = "update identity set flags = ?1 & 255 "
    2.34                                   "where address = ?2 and user_id = ?3 ;";
    2.35 @@ -367,7 +376,7 @@
    2.36          sql_blacklist_is_listed = "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
    2.37  
    2.38          sql_blacklist_retrieve = "select * from blacklist_keys ;";
    2.39 -        
    2.40 +                
    2.41          // Own keys
    2.42          
    2.43          sql_own_key_is_listed =
    2.44 @@ -439,6 +448,16 @@
    2.45              (int)strlen(sql_set_identity), &_session->set_identity, NULL);
    2.46      assert(int_result == SQLITE_OK);
    2.47  
    2.48 +    int_result = sqlite3_prepare_v2(_session->db, sql_exists_empty_fpr_entry,
    2.49 +                                    (int)strlen(sql_exists_empty_fpr_entry), &_session->exists_empty_fpr_entry,
    2.50 +                                    NULL);
    2.51 +    assert(int_result == SQLITE_OK);
    2.52 +    
    2.53 +    int_result = sqlite3_prepare_v2(_session->db, sql_update_fprless_identity,
    2.54 +                                    (int)strlen(sql_update_fprless_identity), &_session->update_fprless_identity,
    2.55 +                                    NULL);
    2.56 +    assert(int_result == SQLITE_OK);
    2.57 +    
    2.58      int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags,
    2.59              (int)strlen(sql_set_identity_flags), &_session->set_identity_flags,
    2.60              NULL);
    2.61 @@ -493,7 +512,7 @@
    2.62              (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve,
    2.63              NULL);
    2.64      assert(int_result == SQLITE_OK);
    2.65 -
    2.66 +    
    2.67      // Own keys
    2.68      
    2.69      int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
    2.70 @@ -995,6 +1014,47 @@
    2.71      return status;
    2.72  }
    2.73  
    2.74 +
    2.75 +static PEP_STATUS exists_empty_fpr_entry (
    2.76 +    PEP_SESSION session,
    2.77 +    const char* address,
    2.78 +    const char* user_id,
    2.79 +    bool *exists_empty_fpr
    2.80 +)
    2.81 +{
    2.82 +    PEP_STATUS status = PEP_STATUS_OK;
    2.83 +    int count;
    2.84 +    
    2.85 +    assert(session && address && user_id && exists_empty_fpr);
    2.86 +    
    2.87 +    if (!(session && address && user_id && exists_empty_fpr))
    2.88 +        return PEP_ILLEGAL_VALUE;
    2.89 +    
    2.90 +    *exists_empty_fpr = false;
    2.91 +    
    2.92 +    sqlite3_reset(session->exists_empty_fpr_entry);
    2.93 +    sqlite3_bind_text(session->exists_empty_fpr_entry, 1, address, -1, SQLITE_STATIC);
    2.94 +    sqlite3_bind_text(session->exists_empty_fpr_entry, 2, user_id, -1, SQLITE_STATIC);
    2.95 +    
    2.96 +    int result;
    2.97 +    
    2.98 +    result = sqlite3_step(session->exists_empty_fpr_entry);
    2.99 +    switch (result) {
   2.100 +        case SQLITE_ROW:
   2.101 +            count = sqlite3_column_int(session->exists_empty_fpr_entry, 0);
   2.102 +            *exists_empty_fpr = count > 0;
   2.103 +            status = PEP_STATUS_OK;
   2.104 +            break;
   2.105 +            
   2.106 +        default:
   2.107 +            status = PEP_UNKNOWN_ERROR;
   2.108 +    }
   2.109 +    
   2.110 +    sqlite3_reset(session->exists_empty_fpr_entry);
   2.111 +    return status;
   2.112 +}
   2.113 +
   2.114 +
   2.115  DYNAMIC_API PEP_STATUS set_identity(
   2.116          PEP_SESSION session, const pEp_identity *identity
   2.117      )
   2.118 @@ -1012,8 +1072,11 @@
   2.119          return PEP_ILLEGAL_VALUE;
   2.120  
   2.121      bool listed;
   2.122 +    bool exists_empty_fpr;
   2.123      
   2.124      if (identity->fpr && identity->fpr[0] != '\0') {
   2.125 +        
   2.126 +        // blacklist check
   2.127          PEP_STATUS status = blacklist_is_listed(session, identity->fpr, &listed);
   2.128          assert(status == PEP_STATUS_OK);
   2.129          if (status != PEP_STATUS_OK)
   2.130 @@ -1021,6 +1084,13 @@
   2.131  
   2.132          if (listed)
   2.133              return PEP_KEY_BLACKLISTED;
   2.134 +        
   2.135 +        // empty fpr already in DB
   2.136 +        status = exists_empty_fpr_entry(session, identity->address,
   2.137 +                                           identity->user_id, &exists_empty_fpr);
   2.138 +        if (status != PEP_STATUS_OK)
   2.139 +            return status;
   2.140 +        
   2.141      }
   2.142  
   2.143      sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
   2.144 @@ -1060,16 +1130,19 @@
   2.145          return PEP_CANNOT_SET_PGP_KEYPAIR;
   2.146      }
   2.147  
   2.148 -    sqlite3_reset(session->set_identity);
   2.149 -    sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
   2.150 +    sqlite3_stmt *update_or_set_identity = 
   2.151 +        (exists_empty_fpr ? session->update_fprless_identity : session->set_identity);
   2.152 +    
   2.153 +    sqlite3_reset(update_or_set_identity);
   2.154 +    sqlite3_bind_text(update_or_set_identity, 1, identity->address, -1,
   2.155              SQLITE_STATIC);
   2.156 -    sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
   2.157 +    sqlite3_bind_text(update_or_set_identity, 2, identity->fpr, -1,
   2.158              SQLITE_STATIC);
   2.159 -    sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
   2.160 +    sqlite3_bind_text(update_or_set_identity, 3, identity->user_id, -1,
   2.161              SQLITE_STATIC);
   2.162 -    sqlite3_bind_int(session->set_identity, 4, identity->flags);
   2.163 -    result = sqlite3_step(session->set_identity);
   2.164 -    sqlite3_reset(session->set_identity);
   2.165 +    sqlite3_bind_int(update_or_set_identity, 4, identity->flags);
   2.166 +    result = sqlite3_step(update_or_set_identity);
   2.167 +    sqlite3_reset(update_or_set_identity);
   2.168      if (result != SQLITE_DONE) {
   2.169          sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   2.170          return PEP_CANNOT_SET_IDENTITY;
     3.1 --- a/src/pEp_internal.h	Wed Oct 12 23:08:45 2016 +0200
     3.2 +++ b/src/pEp_internal.h	Thu Oct 13 16:22:09 2016 +0200
     3.3 @@ -99,6 +99,8 @@
     3.4      sqlite3_stmt *get_device_group;
     3.5      sqlite3_stmt *set_pgp_keypair;
     3.6      sqlite3_stmt *set_identity;
     3.7 +    sqlite3_stmt *exists_empty_fpr_entry;
     3.8 +    sqlite3_stmt *update_fprless_identity;
     3.9      sqlite3_stmt *set_identity_flags;
    3.10      sqlite3_stmt *set_trust;
    3.11      sqlite3_stmt *get_trust;
     4.1 --- a/test/blacklist_test.cc	Wed Oct 12 23:08:45 2016 +0200
     4.2 +++ b/test/blacklist_test.cc	Thu Oct 13 16:22:09 2016 +0200
     4.3 @@ -1,8 +1,11 @@
     4.4  #include <iostream>
     4.5 +#include <iostream>
     4.6 +#include <fstream>
     4.7  #include <string>
     4.8  #include <cstring> // for strcmp()
     4.9  #include <assert.h>
    4.10  #include "blacklist.h"
    4.11 +#include "keymanagement.h"
    4.12  
    4.13  using namespace std;
    4.14  
    4.15 @@ -56,6 +59,61 @@
    4.16      assert(!listed);
    4.17      cout << "23 is not listed any more.\n";
    4.18  
    4.19 +    cout << "blacklist only key for identity / unblacklist key / add key" << endl;
    4.20 +    
    4.21 +    // 2797 65A2 FEB5 B7C7 31B8  61D9 3E4C EFD9 F7AF 4684 - this is the blacklisted key in blacklisted_pub.asc
    4.22 +
    4.23 +    /* read the key into memory */
    4.24 +    ifstream infile("blacklisted_pub.asc");
    4.25 +    string keytext;
    4.26 +    while (!infile.eof()) {
    4.27 +        static string line;
    4.28 +        getline(infile, line);
    4.29 +        keytext += line + "\n";
    4.30 +    }
    4.31 +    infile.close(); 
    4.32 +    
    4.33 +    /* FIXME: put in automated test stuff (N.B. only gdb mem examination to this point to get
    4.34 +     *        fix in */
    4.35 +    /* import it into pep */
    4.36 +    PEP_STATUS status7 = import_key(session, keytext.c_str(), keytext.length(), NULL);
    4.37 +    
    4.38 +    const char* bl_fpr_1 = "279765A2FEB5B7C731B861D93E4CEFD9F7AF4684";
    4.39 +    const char* bl_fpr_2 = "634FAC4417E9B2A5DC2BD4AAC4AEEBBE7E62701B";
    4.40 +    bool is_blacklisted = false;
    4.41 +    
    4.42 +    pEp_identity* blacklisted_identity = new_identity("blacklistedkeys@kgrothoff.org",
    4.43 +                                                      bl_fpr_1,
    4.44 +                                                      NULL,
    4.45 +                                                      "Blacklist Keypair");
    4.46 +    PEP_STATUS status8 = update_identity(session, blacklisted_identity);
    4.47 +
    4.48 +    PEP_STATUS status9 = blacklist_add(session, bl_fpr_1);
    4.49 +    PEP_STATUS status10 = blacklist_is_listed(session, bl_fpr_1, &is_blacklisted);
    4.50 +    PEP_STATUS status11 = update_identity(session, blacklisted_identity);
    4.51 +
    4.52 +    /* read the key into memory */
    4.53 +    ifstream infile2("blacklisted_pub2.asc");
    4.54 +    string keytext2;
    4.55 +    while (!infile2.eof()) {
    4.56 +        static string line2;
    4.57 +        getline(infile2, line2);
    4.58 +        keytext2 += line2 + "\n";
    4.59 +    }
    4.60 +    infile2.close(); 
    4.61 +    
    4.62 +    PEP_STATUS status14 = import_key(session, keytext.c_str(), keytext.length(), NULL);
    4.63 +    
    4.64 +    pEp_identity* blacklisted_identity2 = new_identity("blacklistedkeys@kgrothoff.org",
    4.65 +                                                       bl_fpr_2,
    4.66 +                                                        NULL,
    4.67 +                                                       "Blacklist Keypair");
    4.68 +    PEP_STATUS status15 = update_identity(session, blacklisted_identity2);
    4.69 +    PEP_STATUS status12 = blacklist_delete(session, bl_fpr_1);
    4.70 +    PEP_STATUS status13 = update_identity(session, blacklisted_identity);
    4.71 +    
    4.72 +    /* FIXME: remove both keys again from everywhere and clean up identities */
    4.73 +    
    4.74      cout << "calling release()\n";
    4.75      release(session);
    4.76      return 0;