ENGINE-352: put in the mechanism to attach an is_pep mechanism for the user; tacking pEp messages is complicated, however, as it seems we've also always fouled up when we checked on that (we don't check what key it's encrypted with before we declare whatever key gets retrieved by update_identity is the same, and then set the comm_type on that, which could be the wrong key.) So that's the next fix. ENGINE-352
authorKrista Bennett <krista@pep-project.org>
Fri, 02 Feb 2018 11:03:20 +0100
branchENGINE-352
changeset 24683a10b4f8ba41
parent 2466 339399330a9b
child 2469 419243d81d6f
ENGINE-352: put in the mechanism to attach an is_pep mechanism for the user; tacking pEp messages is complicated, however, as it seems we've also always fouled up when we checked on that (we don't check what key it's encrypted with before we declare whatever key gets retrieved by update_identity is the same, and then set the comm_type on that, which could be the wrong key.) So that's the next fix.
src/pEpEngine.c
src/pEpEngine.h
src/pEp_internal.h
test/pEpEngineTest.cc
     1.1 --- a/src/pEpEngine.c	Mon Jan 29 16:52:54 2018 +0100
     1.2 +++ b/src/pEpEngine.c	Fri Feb 02 11:03:20 2018 +0100
     1.3 @@ -104,14 +104,26 @@
     1.4      "      where id = ?1), upper(replace(?4,' ','')))),"
     1.5      "    (select device_group from person where id = ?1)) ;";
     1.6  
     1.7 +static const char *sql_set_as_pep_user =
     1.8 +    "update person set is_pep_user = 1 "
     1.9 +    "   where id = ?1 ; ";
    1.10 +
    1.11 +static const char *sql_is_pep_user =
    1.12 +    "select is_pep_user from person "
    1.13 +    "   where id = ?1 ; ";
    1.14 +
    1.15 +static const char* sql_exists_person = 
    1.16 +    "select count(*) from person "
    1.17 +    "   where id = ?1 ;";
    1.18 +
    1.19  static const char *sql_set_device_group = 
    1.20      "update person set device_group = ?1 "
    1.21 -    "where id = ?2;";
    1.22 +    "   where id = ?2;";
    1.23  
    1.24  // This will cascade to identity and trust
    1.25  static const char* sql_replace_userid =
    1.26      "update person set id = ?1 " 
    1.27 -    "where id = ?2;";
    1.28 +    "   where id = ?2;";
    1.29  
    1.30  static const char *sql_replace_main_user_fpr =  
    1.31      "update person "
    1.32 @@ -468,7 +480,7 @@
    1.33      sqlite3_busy_timeout(_session->system_db, 1000);
    1.34  
    1.35  // increment this when patching DDL
    1.36 -#define _DDL_USER_VERSION "6"
    1.37 +#define _DDL_USER_VERSION "7"
    1.38  
    1.39      if (in_first) {
    1.40  
    1.41 @@ -515,7 +527,8 @@
    1.42                  "       on delete set null,\n"
    1.43                  "   lang text,\n"
    1.44                  "   comment text,\n"
    1.45 -                "   device_group text\n"
    1.46 +                "   device_group text,\n"
    1.47 +                "   is_pep_user integer default 0\n"
    1.48                  ");\n"
    1.49                  "create table if not exists identity (\n"
    1.50                  "   address text,\n"
    1.51 @@ -600,8 +613,11 @@
    1.52          // is really necessary...
    1.53          if (version == 1) {
    1.54              bool version_changed = true;
    1.55 -            
    1.56 -            if (table_contains_column(_session, "identity", "is_own") > 0) {
    1.57 +
    1.58 +            if (table_contains_column(_session, "person", "is_pep_user") > 0) {
    1.59 +                version = 7;
    1.60 +            }            
    1.61 +            else if (table_contains_column(_session, "identity", "is_own") > 0) {
    1.62                  version = 6;
    1.63              }
    1.64              else if (table_contains_column(_session, "sequences", "own") > 0) {
    1.65 @@ -777,7 +793,34 @@
    1.66                  );
    1.67                  assert(int_result == SQLITE_OK);    
    1.68              }
    1.69 -        }
    1.70 +            if (version < 7) {
    1.71 +                int_result = sqlite3_exec(
    1.72 +                    _session->db,
    1.73 +                    "alter table person\n"
    1.74 +                    "   add column is_pep_user integer default 0;\n",
    1.75 +                    NULL,
    1.76 +                    NULL,
    1.77 +                    NULL
    1.78 +                );
    1.79 +                assert(int_result == SQLITE_OK);
    1.80 +                int_result = sqlite3_exec(
    1.81 +                    _session->db,
    1.82 +                    "update person\n"
    1.83 +                    "   set is_pep_user = 1\n"
    1.84 +                    "   where id = "
    1.85 +                    "       (select distinct id from person "
    1.86 +                    "               join trust on id = user_id "
    1.87 +                    "               where (case when (comm_type = 127) then (id) "
    1.88 +                    "                           when (comm_type = 255) then (id) "
    1.89 +                    "                           else 0"
    1.90 +                    "                      end) = id );\n",
    1.91 +                    NULL,
    1.92 +                    NULL,
    1.93 +                    NULL
    1.94 +                );
    1.95 +                assert(int_result == SQLITE_OK);    
    1.96 +            }
    1.97 +        }        
    1.98          else { 
    1.99              // Version from DB was 0, it means this is initial setup.
   1.100              // DB has just been created, and all tables are empty.
   1.101 @@ -870,6 +913,18 @@
   1.102              (int)strlen(sql_set_person), &_session->set_person, NULL);
   1.103      assert(int_result == SQLITE_OK);
   1.104  
   1.105 +    int_result = sqlite3_prepare_v2(_session->db, sql_set_as_pep_user,
   1.106 +            (int)strlen(sql_set_as_pep_user), &_session->set_as_pep_user, NULL);
   1.107 +    assert(int_result == SQLITE_OK);
   1.108 +    
   1.109 +    int_result = sqlite3_prepare_v2(_session->db, sql_is_pep_user,
   1.110 +            (int)strlen(sql_is_pep_user), &_session->is_pep_user, NULL);
   1.111 +    assert(int_result == SQLITE_OK);
   1.112 +
   1.113 +    int_result = sqlite3_prepare_v2(_session->db, sql_exists_person,
   1.114 +            (int)strlen(sql_exists_person), &_session->exists_person, NULL);
   1.115 +    assert(int_result == SQLITE_OK);
   1.116 +
   1.117      int_result = sqlite3_prepare_v2(_session->db, sql_set_device_group,
   1.118              (int)strlen(sql_set_device_group), &_session->set_device_group, NULL);
   1.119      assert(int_result == SQLITE_OK);
   1.120 @@ -1096,6 +1151,12 @@
   1.121                  sqlite3_finalize(session->remove_fpr_as_default);            
   1.122              if (session->set_person)
   1.123                  sqlite3_finalize(session->set_person);
   1.124 +            if (session->set_as_pep_user)
   1.125 +                sqlite3_finalize(session->set_as_pep_user);
   1.126 +            if (session->is_pep_user)
   1.127 +                sqlite3_finalize(session->is_pep_user);
   1.128 +            if (session->exists_person)
   1.129 +                sqlite3_finalize(session->exists_person);                        
   1.130              if (session->set_device_group)
   1.131                  sqlite3_finalize(session->set_device_group);
   1.132              if (session->get_device_group)
   1.133 @@ -1824,6 +1885,18 @@
   1.134          assert(identity->lang[2] == 0);
   1.135      }
   1.136  
   1.137 +    if (has_fpr) {
   1.138 +        sqlite3_reset(session->set_pgp_keypair);
   1.139 +        sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
   1.140 +                SQLITE_STATIC);
   1.141 +        result = sqlite3_step(session->set_pgp_keypair);
   1.142 +        sqlite3_reset(session->set_pgp_keypair);
   1.143 +        if (result != SQLITE_DONE) {
   1.144 +            sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   1.145 +            return PEP_CANNOT_SET_PGP_KEYPAIR;
   1.146 +        }
   1.147 +    }
   1.148 +
   1.149      sqlite3_reset(session->set_person);
   1.150      sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
   1.151              SQLITE_STATIC);
   1.152 @@ -1843,18 +1916,6 @@
   1.153          return PEP_CANNOT_SET_PERSON;
   1.154      }
   1.155  
   1.156 -    if (has_fpr) {
   1.157 -        sqlite3_reset(session->set_pgp_keypair);
   1.158 -        sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
   1.159 -                SQLITE_STATIC);
   1.160 -        result = sqlite3_step(session->set_pgp_keypair);
   1.161 -        sqlite3_reset(session->set_pgp_keypair);
   1.162 -        if (result != SQLITE_DONE) {
   1.163 -            sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   1.164 -            return PEP_CANNOT_SET_PGP_KEYPAIR;
   1.165 -        }
   1.166 -    }
   1.167 -
   1.168      sqlite3_reset(session->set_identity);
   1.169      sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
   1.170              SQLITE_STATIC);
   1.171 @@ -1893,6 +1954,146 @@
   1.172          return PEP_COMMIT_FAILED;
   1.173  }
   1.174  
   1.175 +// This ONLY sets the user flag, and creates a shell identity if necessary.
   1.176 +PEP_STATUS set_as_pep_user(PEP_SESSION session, pEp_identity* user) {
   1.177 +
   1.178 +    assert(session);
   1.179 +    assert(user);
   1.180 +    assert(user->address);
   1.181 +    assert(!EMPTYSTR(user->user_id));
   1.182 +    
   1.183 +    char* user_id = user->user_id;
   1.184 +    
   1.185 +    if (!session || !user || user->address || EMPTYSTR(user_id))
   1.186 +        return PEP_ILLEGAL_VALUE;
   1.187 +            
   1.188 +    PEP_STATUS status = PEP_STATUS_OK;
   1.189 +    
   1.190 +    char* alias_default = NULL;
   1.191 +    
   1.192 +    bool person_exists = false;
   1.193 +    
   1.194 +    status = exists_person(session, user_id, &alias_default, &person_exists);
   1.195 +    
   1.196 +    if (status != PEP_STATUS_OK)
   1.197 +        return status;
   1.198 +        
   1.199 +    if (!person_exists) {
   1.200 +        if (!user->address)
   1.201 +            return PEP_ILLEGAL_VALUE;
   1.202 +            
   1.203 +        // create shell identity
   1.204 +        pEp_identity* tmp_id = new_identity(user->address, NULL, user->user_id, user->username);
   1.205 +        status = set_identity(session, tmp_id); // this creates the person
   1.206 +        free_identity(tmp_id);
   1.207 +        if (status != PEP_STATUS_OK)
   1.208 +            return status;
   1.209 +        alias_default = strdup(user->user_id);
   1.210 +    }
   1.211 +        
   1.212 +    // Ok, let's set it.
   1.213 +    sqlite3_reset(session->set_as_pep_user);
   1.214 +    sqlite3_bind_text(session->set_as_pep_user, 1, alias_default, -1,
   1.215 +            SQLITE_STATIC);
   1.216 +    int result = sqlite3_step(session->set_as_pep_user);
   1.217 +    sqlite3_reset(session->set_as_pep_user);
   1.218 +    
   1.219 +    if (result != SQLITE_DONE)
   1.220 +        return PEP_CANNOT_SET_PERSON;
   1.221 +        
   1.222 +    return PEP_STATUS_OK;    
   1.223 +}
   1.224 +
   1.225 +PEP_STATUS exists_person(PEP_SESSION session, const char* user_id,
   1.226 +                         char** default_id, bool* exists) {
   1.227 +    assert(session);
   1.228 +    assert(exists);
   1.229 +    assert(!EMPTYSTR(user_id));
   1.230 +        
   1.231 +    if (!session || !exists || EMPTYSTR(user_id))
   1.232 +        return PEP_ILLEGAL_VALUE;
   1.233 +    
   1.234 +    *exists = false;
   1.235 +    
   1.236 +    char* alias_default = NULL;
   1.237 +    
   1.238 +    PEP_STATUS status = get_userid_alias_default(session, user_id, &alias_default);
   1.239 +    
   1.240 +    if (status == PEP_CANNOT_FIND_ALIAS || EMPTYSTR(alias_default)) {
   1.241 +        free(alias_default);
   1.242 +        alias_default = NULL;
   1.243 +        sqlite3_reset(session->exists_person);
   1.244 +        sqlite3_bind_text(session->exists_person, 1, user_id, -1,
   1.245 +                SQLITE_STATIC);
   1.246 +        int result = sqlite3_step(session->exists_person);
   1.247 +        switch (result) {
   1.248 +            case SQLITE_ROW: {
   1.249 +                // yeah yeah, I know, we could be lazy here, but it looks bad.
   1.250 +                *exists = (sqlite3_column_int(session->exists_person, 0) != 0);
   1.251 +                break;
   1.252 +            }
   1.253 +            default:
   1.254 +                return PEP_UNKNOWN_ERROR;
   1.255 +        }
   1.256 +        if (*exists)
   1.257 +            alias_default = strdup(user_id);
   1.258 +    }
   1.259 +    else
   1.260 +        *exists = true; // thank you, delete on cascade!
   1.261 +
   1.262 +    if (!default_id)
   1.263 +        free(alias_default);
   1.264 +    else    
   1.265 +        *default_id = alias_default;
   1.266 +    
   1.267 +    return PEP_STATUS_OK;
   1.268 +}
   1.269 +
   1.270 +PEP_STATUS is_pep_user(PEP_SESSION session, pEp_identity *identity, bool* is_pep)
   1.271 +{
   1.272 +    assert(session);
   1.273 +    assert(is_pep);
   1.274 +    assert(identity);
   1.275 +    assert(!EMPTYSTR(identity->user_id));
   1.276 +
   1.277 +    if (!session || !is_pep || !identity || EMPTYSTR(identity->user_id))
   1.278 +        return PEP_ILLEGAL_VALUE;
   1.279 +    
   1.280 +    *is_pep = false;
   1.281 +    
   1.282 +    const char* user_id = identity->user_id;
   1.283 +    
   1.284 +    if (!session || EMPTYSTR(user_id))
   1.285 +        return PEP_ILLEGAL_VALUE;
   1.286 +        
   1.287 +    char* alias_default = NULL;
   1.288 +    
   1.289 +    PEP_STATUS status = get_userid_alias_default(session, user_id, &alias_default);
   1.290 +    
   1.291 +    if (status == PEP_CANNOT_FIND_ALIAS || EMPTYSTR(alias_default)) {
   1.292 +        free(alias_default);
   1.293 +        alias_default = strdup(user_id);
   1.294 +    }
   1.295 +    
   1.296 +    sqlite3_reset(session->is_pep_user);
   1.297 +    sqlite3_bind_text(session->is_pep_user, 1, user_id, -1,
   1.298 +            SQLITE_STATIC);
   1.299 +    int result = sqlite3_step(session->is_pep_user);
   1.300 +    switch (result) {
   1.301 +        case SQLITE_ROW: {
   1.302 +            // yeah yeah, I know, we could be lazy here, but it looks bad.
   1.303 +            *is_pep = (sqlite3_column_int(session->is_pep_user, 0) != 0);
   1.304 +            break;
   1.305 +        }
   1.306 +        default:
   1.307 +            free(alias_default);
   1.308 +            return PEP_CANNOT_FIND_PERSON;
   1.309 +    }
   1.310 +
   1.311 +    return PEP_STATUS_OK;
   1.312 +}
   1.313 +
   1.314 +
   1.315  PEP_STATUS remove_fpr_as_default(PEP_SESSION session, 
   1.316                                   const char* fpr) 
   1.317  {
     2.1 --- a/src/pEpEngine.h	Mon Jan 29 16:52:54 2018 +0100
     2.2 +++ b/src/pEpEngine.h	Fri Feb 02 11:03:20 2018 +0100
     2.3 @@ -1231,6 +1231,21 @@
     2.4  
     2.5  PEP_STATUS import_trusted_own_keys(PEP_SESSION session);
     2.6  
     2.7 +// This ONLY sets the *user* flag, and creates a shell identity if necessary.
     2.8 +PEP_STATUS set_as_pep_user(PEP_SESSION session, pEp_identity* user);
     2.9 +
    2.10 +// returns true (by reference) if a person with this user_id exists; if default_id != NULL,
    2.11 +// function will also return by reference a copy of the default id which
    2.12 +// is this user_id is aliased to (which will usually, but not always, 
    2.13 +// string equivalent to the user_id)
    2.14 +PEP_STATUS exists_person(PEP_SESSION session, const char* user_id,
    2.15 +                         char** default_id, bool* exists);
    2.16 +
    2.17 +// returns true if the USER corresponding to this identity has been listed in
    2.18 +// the *person* table as a pEp user. This *does not check comm_type*                         
    2.19 +PEP_STATUS is_pep_user(PEP_SESSION session, pEp_identity *identity, bool* is_pep);
    2.20 +
    2.21 +
    2.22  #ifdef __cplusplus
    2.23  }
    2.24  #endif
     3.1 --- a/src/pEp_internal.h	Mon Jan 29 16:52:54 2018 +0100
     3.2 +++ b/src/pEp_internal.h	Fri Feb 02 11:03:20 2018 +0100
     3.3 @@ -131,6 +131,9 @@
     3.4      sqlite3_stmt *refresh_userid_default_key;
     3.5      sqlite3_stmt *remove_fpr_as_default;
     3.6      sqlite3_stmt *set_person;
     3.7 +    sqlite3_stmt *set_as_pep_user;
     3.8 +    sqlite3_stmt *is_pep_user;
     3.9 +    sqlite3_stmt *exists_person;
    3.10      sqlite3_stmt *set_device_group;
    3.11      sqlite3_stmt *get_device_group;
    3.12      sqlite3_stmt *set_pgp_keypair;
     4.1 --- a/test/pEpEngineTest.cc	Mon Jan 29 16:52:54 2018 +0100
     4.2 +++ b/test/pEpEngineTest.cc	Fri Feb 02 11:03:20 2018 +0100
     4.3 @@ -32,7 +32,7 @@
     4.4          return sstr.str();
     4.5  }
     4.6  
     4.7 -// no C++11, yet? So do our own implementation:
     4.8 +// no C++11, yet? So do our own implementation:1G
     4.9  namespace{
    4.10      std::string to_string(unsigned long u)
    4.11      {
    4.12 @@ -270,6 +270,7 @@
    4.13  
    4.14      cout << "\nsetting identity...\n";
    4.15      PEP_STATUS pep_set_result = set_identity(session, identity);
    4.16 +    cout << pep_set_result << endl;
    4.17      assert(pep_set_result == PEP_STATUS_OK);
    4.18      free_identity(identity);
    4.19      get_identity(session, "leon.schumacher@digitalekho.com", "23", &identity);