diff --git a/src/keymanagement.c b/src/keymanagement.c index 6cc12b5d..922091b2 100644 --- a/src/keymanagement.c +++ b/src/keymanagement.c @@ -436,6 +436,9 @@ static PEP_STATUS prepare_updated_identity(PEP_SESSION session, transfer_ident_lang_and_flags(return_id, stored_ident); + if (return_id->comm_type == PEP_ct_unknown) + return_id->comm_type = PEP_ct_key_not_found; + return status; } @@ -1219,6 +1222,10 @@ DYNAMIC_API PEP_STATUS trust_personal_key( if (input_default_ct < PEP_ct_strong_but_unconfirmed) return PEP_KEY_UNSUITABLE; + status = set_pgp_keypair(session, ident->fpr); + if (status != PEP_STATUS_OK) + return status; + // Save the input fpr char* cached_fpr = strdup(ident->fpr); ident->fpr = NULL; diff --git a/src/message_api.c b/src/message_api.c index c6c529c3..a93bbd4a 100644 --- a/src/message_api.c +++ b/src/message_api.c @@ -1532,7 +1532,7 @@ DYNAMIC_API PEP_STATUS encrypt_message( else _status = myself(session, _il->ident); if (_status != PEP_STATUS_OK) { - status = _status; + status = PEP_UNENCRYPTED; GOTO(pep_error); } @@ -1564,7 +1564,7 @@ DYNAMIC_API PEP_STATUS encrypt_message( else _status = myself(session, _il->ident); if (_status != PEP_STATUS_OK) { - status = _status; + status = PEP_UNENCRYPTED; GOTO(pep_error); } @@ -1596,7 +1596,7 @@ DYNAMIC_API PEP_STATUS encrypt_message( _status = myself(session, _il->ident); if (_status != PEP_STATUS_OK) { - status = _status; + status = PEP_UNENCRYPTED; GOTO(pep_error); } @@ -1609,7 +1609,6 @@ DYNAMIC_API PEP_STATUS encrypt_message( } else { dest_keys_found = false; - status = PEP_KEY_NOT_FOUND; } } } diff --git a/src/message_api.h b/src/message_api.h index 843c4373..f710e42f 100644 --- a/src/message_api.h +++ b/src/message_api.h @@ -56,11 +56,8 @@ typedef unsigned int PEP_encrypt_flags_t; // // return value: // PEP_STATUS_OK on success -// PEP_KEY_NOT_FOUND at least one of the receipient keys -// could not be found // PEP_KEY_HAS_AMBIG_NAME at least one of the receipient keys has // an ambiguous name -// PEP_GET_KEY_FAILED cannot retrieve key // PEP_UNENCRYPTED on demand or no recipients with usable // key, is left unencrypted, and key is // attached to it diff --git a/src/pEpEngine.c b/src/pEpEngine.c index eabcb57e..aff6f794 100644 --- a/src/pEpEngine.c +++ b/src/pEpEngine.c @@ -98,12 +98,23 @@ static const char *sql_remove_fpr_as_default = // Set person, but if already exist, only update. // if main_key_id already set, don't touch. static const char *sql_set_person = - "insert or replace into person (id, username, lang, main_key_id, device_group)" - " values (?1, ?2, ?3," - " (select coalesce((select main_key_id from person " - " where id = ?1), upper(replace(?4,' ',''))))," - " (select device_group from person where id = ?1)) ;"; - + "insert or ignore into person (id, username, lang, main_key_id, device_group)" + " values (?1, ?2, ?3," + " (select coalesce( " + " (select main_key_id from person where id = ?1), " + " upper(replace(?4,' ',''))))," + " (select device_group from person where id = ?1)) ;" + "update person " + " set username = ?2, " + " lang = ?3, " + " main_key_id = " + " (select coalesce( " + " (select main_key_id from person where id = ?1), " + " upper(replace(?4,' ',''))))," + " device_group = " + " (select device_group from person where id = ?1)" + " where id = ?1 ;"; + static const char *sql_set_as_pep_user = "update person set is_pep_user = 1 " " where id = ?1 ; "; @@ -151,17 +162,26 @@ static const char *sql_get_device_group = "where id = ?1;"; static const char *sql_set_pgp_keypair = - "insert or replace into pgp_keypair (fpr) " + "insert or ignore into pgp_keypair (fpr) " "values (upper(replace(?1,' ',''))) ;"; static const char *sql_set_identity = - "insert or replace into identity (" - " address, main_key_id, " - " user_id, flags, is_own" - ") values (" - " ?1," - " upper(replace(?2,' ',''))," - " ?3," + "insert or ignore into identity (" + " address, main_key_id, " + " user_id, flags, is_own" + " ) values (" + " ?1," + " upper(replace(?2,' ',''))," + " ?3," + " ?4," + " ?5" + " );" + "update identity " + " set main_key_id = upper(replace(?2,' ','')), " + " flags = ?4, " + " is_own = ?5 " + " where address = ?1 and user_id = ?3 ;"; + // " (select" // " coalesce(" // " (select flags from identity" @@ -170,9 +190,8 @@ static const char *sql_set_identity = // " 0)" // " ) | (?4 & 255)" /* set_identity ignores previous flags, and doesn't filter machine flags */ - " ?4," - " ?5" - ");"; + + static const char *sql_set_identity_flags = "update identity set flags = " @@ -187,9 +206,11 @@ static const char *sql_unset_identity_flags = "where address = ?2 and user_id = ?3 ;"; static const char *sql_set_trust = - "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) " - "values (?1, upper(replace(?2,' ','')), ?3) ;"; - + "insert or ignore into trust (user_id, pgp_keypair_fpr, comm_type) " + "values (?1, upper(replace(?2,' ','')), ?3) ;" + "update trust set comm_type = ?3 " + " where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));"; + static const char *sql_update_trust_for_fpr = "update trust " "set comm_type = ?1 " @@ -222,7 +243,7 @@ static const char *sql_i18n_token = // blacklist static const char *sql_blacklist_add = - "insert or replace into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;" + "insert or ignore into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;" "delete from identity where main_key_id = upper(replace(?1,' ','')) ;" "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;"; @@ -308,7 +329,7 @@ static const char *sql_get_userid_alias_default = // Revocation tracking static const char *sql_add_mistrusted_key = - "insert or replace into mistrusted_keys (fpr) " + "insert or ignore into mistrusted_keys (fpr) " " values (upper(replace(?1,' ',''))) ;"; static const char *sql_delete_mistrusted_key = @@ -318,7 +339,7 @@ static const char *sql_is_mistrusted_key = "select count(*) from mistrusted_keys where fpr = upper(replace(?1,' ','')) ;"; static const char *sql_add_userid_alias = - "insert or replace into alternate_user_id (default_id, alternate_id) " + "insert or ignore into alternate_user_id (default_id, alternate_id) " "values (?1, ?2) ;"; static int user_version(void *_version, int count, char **text, char **name) @@ -384,6 +405,10 @@ static int table_contains_column(PEP_SESSION session, const char* table_name, return retval; } +void errorLogCallback(void *pArg, int iErrCode, const char *zMsg){ + fprintf(stderr, "(%d) %s\n", iErrCode, zMsg); +} + DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) { PEP_STATUS status = PEP_STATUS_OK; @@ -441,6 +466,8 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) status = PEP_INIT_CANNOT_OPEN_DB; goto pep_error; } + + sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, NULL); int_result = sqlite3_open_v2( LOCAL_DB, @@ -584,8 +611,8 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) ");\n" // user id aliases "create table if not exists alternate_user_id (\n" - " default_id text references person (id)\n" - " on delete cascade on update cascade,\n" + " default_id text references person (id),\n" +// " on delete cascade on update cascade,\n" " alternate_id text primary key\n" ");\n" // mistrusted keys @@ -623,6 +650,17 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) NULL, NULL); assert(int_result == SQLITE_OK); + + int_result = sqlite3_exec( + _session->db, + "pragma foreign_keys=ON;\n", + NULL, + NULL, + NULL + ); + + assert(int_result == SQLITE_OK); + // Sometimes the user_version wasn't set correctly. Check to see if this // is really necessary... @@ -797,8 +835,8 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) "\n" "PRAGMA foreign_keys=on;\n" "create table if not exists alternate_user_id (\n" - " default_id text references person (id)\n" - " on delete cascade on update cascade,\n" + " default_id text references person (id),\n" +// " on delete cascade on update cascade,\n" " alternate_id text primary key\n" ");\n" , @@ -1888,6 +1926,25 @@ PEP_STATUS get_identities_by_address( return PEP_STATUS_OK; } +// FIXME: We can rollback in set_identity on the return status, +// so we should probably do that. +PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr) { + if (!session || EMPTYSTR(fpr)) + return PEP_ILLEGAL_VALUE; + + int result; + + sqlite3_reset(session->set_pgp_keypair); + sqlite3_bind_text(session->set_pgp_keypair, 1, fpr, -1, + SQLITE_STATIC); + result = sqlite3_step(session->set_pgp_keypair); + sqlite3_reset(session->set_pgp_keypair); + if (result != SQLITE_DONE) { + return PEP_CANNOT_SET_PGP_KEYPAIR; + } + + return PEP_STATUS_OK; +} DYNAMIC_API PEP_STATUS set_identity( PEP_SESSION session, const pEp_identity *identity @@ -2768,6 +2825,10 @@ DYNAMIC_API PEP_STATUS generate_keypair( if (status != PEP_STATUS_OK) return status; + if (identity->fpr) + status = set_pgp_keypair(session, identity->fpr); + + // add to known keypair DB, as this might not end up being a default return status; } diff --git a/src/pEpEngine.h b/src/pEpEngine.h index f28dc637..fd520eec 100644 --- a/src/pEpEngine.h +++ b/src/pEpEngine.h @@ -1245,6 +1245,7 @@ PEP_STATUS exists_person(PEP_SESSION session, const char* user_id, // the *person* table as a pEp user. This *does not check comm_type* PEP_STATUS is_pep_user(PEP_SESSION session, pEp_identity *identity, bool* is_pep); +PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr); #ifdef __cplusplus } diff --git a/test/Makefile b/test/Makefile index 9de971ad..c325e091 100644 --- a/test/Makefile +++ b/test/Makefile @@ -55,7 +55,7 @@ TEST_CMD_PFX=$(LIBPATH)=$(EXTRA_LIB_PATHS) HOME=$(TEST_HOME) GNUPGHOME=$(TEST_GN UNIT_TESTS_SOURCE=$(wildcard *_test.cc) UNIT_TESTS=$(subst .cc,,$(UNIT_TESTS_SOURCE)) -UNIT_TESTS_RUN=$(subst .cc,_run,$(UNIT_TESTS_SOURCE)) +UNIT_TESTS_RUN=$(subst .cc,_gdb,$(UNIT_TESTS_SOURCE)) CFLAGS:=$(filter-out -DNDEBUG,$(CFLAGS)) ifneq ($(MAKECMDGOALS),clean) diff --git a/test/external_revoke_test.cc b/test/external_revoke_test.cc index 040e15ec..a32d89cd 100644 --- a/test/external_revoke_test.cc +++ b/test/external_revoke_test.cc @@ -148,7 +148,7 @@ int main() { // (note - as of 23.5.17, revoke_key() doesn't touch the trust db, just the keyring, so we can do this) cout << "Revoking key." << endl; - status = get_identity(session, uniqname, r1_userid, &recip1); + status = update_identity(session, recip1); status = revoke_key(session, recip1->fpr, "encrypt_for_identity_test"); cout << "Status of revocation call for " << recip1->fpr << " is "<< tl_status_string(status) << endl; @@ -177,12 +177,13 @@ int main() { cout << "2b. Encrypt message for recip whose key has been externally revoked in the keyring, not the app." << endl; cout << "---------------------------------------------------------" << endl << endl; + status = encrypt_message(session, outgoing_msg, NULL, &encrypted_outgoing_msg, PEP_enc_PGP_MIME, 0); cout << "Encryption returns with status " << tl_status_string(status) << endl; - assert (status == PEP_KEY_UNSUITABLE); + assert (status == PEP_UNENCRYPTED); assert (encrypted_outgoing_msg == NULL); status = update_identity(session, recip1); - assert (recip1->comm_type = PEP_ct_key_revoked); + assert(recip1->comm_type = PEP_ct_key_not_found); cout << endl << "---------------------------------------------------------" << endl; cout << "2c. Check trust of recip, whose only key has been revoked, once an encryption attempt has been made." << endl; @@ -194,7 +195,7 @@ int main() { recip1->fpr = NULL; cout << "Recip's trust DB comm_type = " << hex << tl_ct_string(recip1->comm_type) << endl; - assert(recip1->comm_type == PEP_ct_key_revoked); + assert(recip1->comm_type == PEP_ct_unknown || recip1->comm_type == PEP_ct_key_revoked); free_message(decrypted_msg); free_message(outgoing_msg); diff --git a/test/new_update_id_and_myself_test.cc b/test/new_update_id_and_myself_test.cc index f1d78cd0..99f67dfb 100644 --- a/test/new_update_id_and_myself_test.cc +++ b/test/new_update_id_and_myself_test.cc @@ -17,6 +17,8 @@ using namespace std; int main() { cout << "\n*** test update_identity and myself ***\n\n"; + test_init(); + PEP_SESSION session; cout << "calling init()\n"; @@ -225,7 +227,8 @@ int main() { const char* new_username = "Test Patchy"; - alex = new_identity(alex_address, NULL, alex_userid, new_username); + alex = new_identity(alex_address, NULL, alex_userid, new_username); + cout << "Timing is everything" << endl; status = update_identity(session, alex); assert(status == PEP_STATUS_OK); assert(alex->fpr); diff --git a/test/test_util.cc b/test/test_util.cc index d1d2a248..ec3af1d1 100644 --- a/test/test_util.cc +++ b/test/test_util.cc @@ -6,6 +6,13 @@ #include #include + +void test_init() { + unlink ("../test_home/.pEp_management.db"); + unlink ("../test_home/.pEp_management.db-shm"); + unlink ("../test_home/.pEp_management.db-wal"); +} + std::string slurp(const std::string& filename) { std::ifstream input(filename.c_str()); diff --git a/test/test_util.h b/test/test_util.h index ad8cf2e0..fc2ac309 100644 --- a/test/test_util.h +++ b/test/test_util.h @@ -2,6 +2,8 @@ #include "pEpEngine.h" #include "message_api.h" +void test_init(); + // reads a whole file and returns it as std::string // throws std::runtime_error() if the file cannot be read. Empty file is not an error. std::string slurp(const std::string& filename);