Merged in fixes for ENGINE-352, ENGINE-345, a bunch of trust/mistrust issues, and general mayhem.

doc_update_sequoia
Krista Bennett 5 years ago
commit fe33d8c45a

@ -77,8 +77,11 @@ PEP_STATUS elect_pubkey(
_comm_type_key > identity->comm_type)
{
bool blacklisted;
status = blacklist_is_listed(session, _keylist->value, &blacklisted);
if (status == PEP_STATUS_OK && !blacklisted) {
bool mistrusted;
status = is_mistrusted_key(session, _keylist->value, &mistrusted);
if (status == PEP_STATUS_OK)
status = blacklist_is_listed(session, _keylist->value, &blacklisted);
if (status == PEP_STATUS_OK && !mistrusted && !blacklisted) {
identity->comm_type = _comm_type_key;
_fpr = _keylist->value;
}
@ -88,10 +91,14 @@ PEP_STATUS elect_pubkey(
}
free(identity->fpr);
identity->fpr = strdup(_fpr);
if (identity->fpr == NULL) {
free_stringlist(keylist);
return PEP_OUT_OF_MEMORY;
if (!_fpr || _fpr[0] == '\0')
identity->fpr = NULL;
else {
identity->fpr = strdup(_fpr);
if (identity->fpr == NULL) {
free_stringlist(keylist);
return PEP_OUT_OF_MEMORY;
}
}
free_stringlist(keylist);
@ -199,6 +206,7 @@ static PEP_STATUS validate_fpr(PEP_SESSION session,
status = update_trust_for_fpr(session,
fpr,
ct);
case PEP_ct_mistrusted:
free(ident->fpr);
ident->fpr = NULL;
ident->comm_type = ct;
@ -369,14 +377,15 @@ static PEP_STATUS prepare_updated_identity(PEP_SESSION session,
stored_ident->comm_type = ct;
}
}
else {
if (stored_ident->comm_type == PEP_ct_unknown)
stored_ident->comm_type = PEP_ct_key_not_found;
}
free(return_id->fpr);
return_id->fpr = NULL;
if (status == PEP_STATUS_OK && !EMPTYSTR(stored_ident->fpr))
return_id->fpr = strdup(stored_ident->fpr);
// This is outside the if block ON PURPOSE - we return an empty FPR +
// the reason why a key wasn't used in the comm_type string if we can't
// find or use one.
return_id->comm_type = stored_ident->comm_type;
// We patch the DB with the input username, but if we didn't have
@ -1064,6 +1073,8 @@ DYNAMIC_API PEP_STATUS key_mistrusted(
status = mark_as_compromized(session, ident->fpr);
if (status == PEP_STATUS_OK)
status = remove_fpr_as_default(session, ident->fpr);
if (status == PEP_STATUS_OK)
status = add_mistrusted_key(session, ident->fpr);
}
return status;
@ -1082,12 +1093,15 @@ DYNAMIC_API PEP_STATUS undo_last_mistrust(PEP_SESSION session) {
if (!cached_ident)
status = PEP_CANNOT_FIND_IDENTITY;
else {
status = set_identity(session, cached_ident);
free_identity(session->cached_mistrusted);
status = delete_mistrusted_key(session, cached_ident->fpr);
if (status == PEP_STATUS_OK) {
status = set_identity(session, cached_ident);
free_identity(session->cached_mistrusted);
}
}
session->cached_mistrusted = NULL;
return status;
}
@ -1128,7 +1142,19 @@ DYNAMIC_API PEP_STATUS key_reset_trust(
if (status != PEP_STATUS_OK)
goto pep_free;
bool mistrusted_key = false;
status = is_mistrusted_key(session, ident->fpr, &mistrusted_key);
if (status != PEP_STATUS_OK)
goto pep_free;
if (mistrusted_key)
status = delete_mistrusted_key(session, ident->fpr);
if (status != PEP_STATUS_OK)
goto pep_free;
input_copy->comm_type = new_trust;
tmp_ident = new_identity(ident->address, NULL, ident->user_id, NULL);
@ -1568,3 +1594,80 @@ PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr,
return session->cryptotech[PEP_crypt_OpenPGP].contains_priv_key(session, fpr, has_private);
}
PEP_STATUS add_mistrusted_key(PEP_SESSION session, const char* fpr)
{
int result;
assert(!EMPTYSTR(fpr));
if (!(session) || EMPTYSTR(fpr))
return PEP_ILLEGAL_VALUE;
sqlite3_reset(session->add_mistrusted_key);
sqlite3_bind_text(session->add_mistrusted_key, 1, fpr, -1,
SQLITE_STATIC);
result = sqlite3_step(session->add_mistrusted_key);
sqlite3_reset(session->add_mistrusted_key);
if (result != SQLITE_DONE)
return PEP_CANNOT_SET_PGP_KEYPAIR; // FIXME: Better status?
return PEP_STATUS_OK;
}
PEP_STATUS delete_mistrusted_key(PEP_SESSION session, const char* fpr)
{
int result;
assert(!EMPTYSTR(fpr));
if (!(session) || EMPTYSTR(fpr))
return PEP_ILLEGAL_VALUE;
sqlite3_reset(session->delete_mistrusted_key);
sqlite3_bind_text(session->delete_mistrusted_key, 1, fpr, -1,
SQLITE_STATIC);
result = sqlite3_step(session->delete_mistrusted_key);
sqlite3_reset(session->delete_mistrusted_key);
if (result != SQLITE_DONE)
return PEP_UNKNOWN_ERROR; // FIXME: Better status?
return PEP_STATUS_OK;
}
PEP_STATUS is_mistrusted_key(PEP_SESSION session, const char* fpr,
bool* mistrusted)
{
PEP_STATUS status = PEP_STATUS_OK;
assert(session);
assert(!EMPTYSTR(fpr));
if (!(session && fpr))
return PEP_ILLEGAL_VALUE;
*mistrusted = false;
sqlite3_reset(session->is_mistrusted_key);
sqlite3_bind_text(session->is_mistrusted_key, 1, fpr, -1, SQLITE_STATIC);
int result;
result = sqlite3_step(session->is_mistrusted_key);
switch (result) {
case SQLITE_ROW:
*mistrusted = sqlite3_column_int(session->is_mistrusted_key, 0);
status = PEP_STATUS_OK;
break;
default:
status = PEP_UNKNOWN_ERROR;
}
sqlite3_reset(session->is_mistrusted_key);
return status;
}

@ -344,6 +344,11 @@ DYNAMIC_API PEP_STATUS set_own_key(
PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
PEP_STATUS add_mistrusted_key(PEP_SESSION session, const char* fpr);
PEP_STATUS delete_mistrusted_key(PEP_SESSION session, const char* fpr);
PEP_STATUS is_mistrusted_key(PEP_SESSION session, const char* fpr, bool* mistrusted);
#ifdef __cplusplus
}
#endif

@ -20,6 +20,12 @@
#define _MAX(A, B) ((B) > (A) ? (B) : (A))
#endif
// These are globals used in generating message IDs and should only be
// computed once, as they're either really constants or OS-dependent
int _pEp_rand_max_bits;
double _pEp_log2_36;
static bool is_a_pEpmessage(const message *msg)
{
for (stringpair_list_t *i = msg->opt_fields; i && i->value ; i=i->next) {
@ -1495,6 +1501,8 @@ DYNAMIC_API PEP_STATUS encrypt_message(
}
bool dest_keys_found = true;
bool has_pep_user = false;
PEP_comm_type max_comm_type = PEP_ct_pEp;
identity_list * _il;
@ -1518,6 +1526,8 @@ DYNAMIC_API PEP_STATUS encrypt_message(
_il->ident->comm_type = PEP_ct_key_not_found;
_status = PEP_STATUS_OK;
}
if (!has_pep_user)
is_pep_user(session, _il->ident, &has_pep_user);
}
else
_status = myself(session, _il->ident);
@ -1548,6 +1558,8 @@ DYNAMIC_API PEP_STATUS encrypt_message(
_il->ident->comm_type = PEP_ct_key_not_found;
_status = PEP_STATUS_OK;
}
if (!has_pep_user)
is_pep_user(session, _il->ident, &has_pep_user);
}
else
_status = myself(session, _il->ident);
@ -1577,6 +1589,8 @@ DYNAMIC_API PEP_STATUS encrypt_message(
_il->ident->comm_type = PEP_ct_key_not_found;
_status = PEP_STATUS_OK;
}
if (!has_pep_user)
is_pep_user(session, _il->ident, &has_pep_user);
}
else
_status = myself(session, _il->ident);
@ -1606,7 +1620,7 @@ DYNAMIC_API PEP_STATUS encrypt_message(
PEP_rating_undefined) < PEP_rating_reliable)
{
free_stringlist(keys);
if (!session->passive_mode &&
if ((has_pep_user || !session->passive_mode) &&
!(flags & PEP_encrypt_flag_force_no_attached_key)) {
attach_own_key(session, src);
decorate_message(src, PEP_rating_undefined, NULL, true);
@ -1823,31 +1837,31 @@ pep_error:
return ADD_TO_LOG(status);
}
static PEP_STATUS _update_identity_for_incoming_message(
PEP_SESSION session,
const message *src
)
{
PEP_STATUS status;
if (src->from && src->from->address) {
if (!is_me(session, src->from))
status = update_identity(session, src->from);
else
status = myself(session, src->from);
if (status == PEP_STATUS_OK
&& is_a_pEpmessage(src)
&& src->from->comm_type >= PEP_ct_OpenPGP_unconfirmed
&& src->from->comm_type != PEP_ct_pEp_unconfirmed
&& src->from->comm_type != PEP_ct_pEp)
{
src->from->comm_type |= PEP_ct_pEp_unconfirmed;
status = set_identity(session, src->from);
}
return status;
}
return PEP_ILLEGAL_VALUE;
}
// static PEP_STATUS _update_identity_for_incoming_message(
// PEP_SESSION session,
// const message *src
// )
// {
// PEP_STATUS status;
//
// if (src->from && src->from->address) {
// if (!is_me(session, src->from))
// status = update_identity(session, src->from);
// else
// status = myself(session, src->from);
// if (status == PEP_STATUS_OK
// && is_a_pEpmessage(src)
// && src->from->comm_type >= PEP_ct_OpenPGP_unconfirmed
// && src->from->comm_type != PEP_ct_pEp_unconfirmed
// && src->from->comm_type != PEP_ct_pEp)
// {
// src->from->comm_type |= PEP_ct_pEp_unconfirmed;
// status = set_identity(session, src->from);
// }
// return status;
// }
// return PEP_ILLEGAL_VALUE;
// }
static PEP_STATUS _get_detached_signature(message* msg,
@ -2037,7 +2051,7 @@ static PEP_STATUS amend_rating_according_to_sender_and_recipients(
}
else {
pEp_identity *_sender = new_identity(sender->address, fpr,
sender->user_id, sender->username);
sender->user_id, sender->username);
if (_sender == NULL)
return PEP_OUT_OF_MEMORY;
@ -2426,6 +2440,58 @@ static PEP_STATUS import_priv_keys_from_decrypted_msg(PEP_SESSION session,
return status;
}
static PEP_STATUS update_sender_to_pep_trust(
PEP_SESSION session,
pEp_identity* sender,
stringlist_t* keylist)
{
assert(session);
assert(sender);
assert(keylist && !EMPTYSTR(keylist->value));
if (!session || !sender || !keylist || EMPTYSTR(keylist->value))
return PEP_ILLEGAL_VALUE;
free(sender->fpr);
sender->fpr = NULL;
PEP_STATUS status =
is_me(session, sender) ? myself(session, sender) : update_identity(session, sender);
if (EMPTYSTR(sender->fpr) || strcmp(sender->fpr, keylist->value) != 0) {
free(sender->fpr);
sender->fpr = strdup(keylist->value);
if (!sender->fpr)
return PEP_OUT_OF_MEMORY;
status = get_trust(session, sender);
if (status == PEP_CANNOT_FIND_IDENTITY || sender->comm_type == PEP_ct_unknown) {
PEP_comm_type ct = PEP_ct_unknown;
status = get_key_rating(session, sender->fpr, &ct);
if (status != PEP_STATUS_OK)
return status;
sender->comm_type = ct;
}
}
// Could be done elegantly, but we do this explicitly here for readability.
// This file's code is difficult enough to parse. But change at will.
switch (sender->comm_type) {
case PEP_ct_OpenPGP_unconfirmed:
status = set_trust(session, sender->user_id, sender->fpr, PEP_ct_pEp_unconfirmed);
break;
case PEP_ct_OpenPGP:
status = set_trust(session, sender->user_id, sender->fpr, PEP_ct_pEp);
break;
default:
break;
}
return status;
}
DYNAMIC_API PEP_STATUS _decrypt_message(
PEP_SESSION session,
message *src,
@ -2456,36 +2522,58 @@ DYNAMIC_API PEP_STATUS _decrypt_message(
char *ptext = NULL;
size_t psize;
stringlist_t *_keylist = NULL;
char* signer_fpr = NULL;
bool is_pep_msg = is_a_pEpmessage(src);
*dst = NULL;
*keylist = NULL;
*rating = PEP_rating_undefined;
*flags = 0;
/*** End init ***/
/*** Begin Import any attached public keys and update identities accordingly ***/
// Ok, before we do anything, if it's a pEp message, regardless of whether it's
// encrypted or not, we set the sender as a pEp user. This has NOTHING to do
// with the key.
if (src->from && !(is_me(session, src->from))) {
if (is_pep_msg) {
pEp_identity* tmp_from = src->from;
// Ensure there's a user id
if (EMPTYSTR(tmp_from->user_id) && tmp_from->address) {
status = update_identity(session, tmp_from);
if (status == PEP_CANNOT_FIND_IDENTITY) {
tmp_from->user_id = calloc(1, strlen(tmp_from->address) + 6);
if (!tmp_from->user_id)
return PEP_OUT_OF_MEMORY;
snprintf(tmp_from->user_id, strlen(tmp_from->address) + 6,
"TOFU_%s", tmp_from->address);
status = PEP_STATUS_OK;
}
}
if (status == PEP_STATUS_OK) {
// Now set user as PEP (may also create an identity if none existed yet)
status = set_as_pep_user(session, tmp_from);
}
}
}
// We really need key used in signing to do anything further on the pEp comm_type.
// So we can't adjust the rating of the sender just yet.
/*** Begin Import any attached public keys and update identities accordingly ***/
// Private key in unencrypted mail are ignored -> NULL
bool imported_keys = import_attached_keys(session, src, NULL);
// Update src->from in case we just imported a key
// we would need to check signature
status = _update_identity_for_incoming_message(session, src);
if (status == PEP_ILLEGAL_VALUE && src->from && is_me(session, src->from)) {
// the above function should fail if it's us.
// We don't need to update, as any revocations or expirations
// of our own key imported above, which are all that we
// would care about for anything imported,
// SHOULD get caught when they matter later.
// (Private keys imported above are not stored in the trust DB)
status = PEP_STATUS_OK;
}
// FIXME: is this really necessary here?
if (!is_me(session, src->from))
status = update_identity(session, src->from);
else
status = myself(session, src->from);
if (status != PEP_STATUS_OK)
return ADD_TO_LOG(status);
/*** End Import any attached public keys and update identities accordingly ***/
/*** Begin get detached signatures that are attached to the encrypted message ***/
@ -2519,7 +2607,7 @@ DYNAMIC_API PEP_STATUS _decrypt_message(
status = get_crypto_text(src, &ctext, &csize);
if (status != PEP_STATUS_OK)
return status;
/** Ok, we should be ready to decrypt. Try decrypt and verify first! **/
status = cryptotech[crypto].decrypt_and_verify(session, ctext,
csize, dsig_text, dsig_size,
@ -2677,12 +2765,17 @@ DYNAMIC_API PEP_STATUS _decrypt_message(
}
*rating = decrypt_rating(decrypt_status);
// Ok, so if it was signed and it's all verified, we can update
// eligible signer comm_types to PEP_ct_pEp_*
if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED && is_pep_msg)
status = update_sender_to_pep_trust(session, src->from, _keylist);
/* Ok, now we have a keylist used for decryption/verification.
now we need to update the message rating with the
sender and recipients in mind */
status = amend_rating_according_to_sender_and_recipients(session,
rating, src->from, _keylist);
rating, src->from, _keylist);
if (status != PEP_STATUS_OK)
GOTO(pep_error);
@ -2741,6 +2834,7 @@ enomem:
pep_error:
free(ptext);
free(signer_fpr);
free_message(msg);
free_stringlist(_keylist);

@ -104,14 +104,26 @@ static const char *sql_set_person =
" where id = ?1), upper(replace(?4,' ','')))),"
" (select device_group from person where id = ?1)) ;";
static const char *sql_set_as_pep_user =
"update person set is_pep_user = 1 "
" where id = ?1 ; ";
static const char *sql_is_pep_user =
"select is_pep_user from person "
" where id = ?1 ; ";
static const char* sql_exists_person =
"select count(*) from person "
" where id = ?1 ;";
static const char *sql_set_device_group =
"update person set device_group = ?1 "
"where id = ?2;";
" where id = ?2;";
// This will cascade to identity and trust
static const char* sql_replace_userid =
"update person set id = ?1 "
"where id = ?2;";
" where id = ?2;";
static const char *sql_replace_main_user_fpr =
"update person "
@ -294,6 +306,17 @@ static const char *sql_get_userid_alias_default =
"select default_id from alternate_user_id "
" where alternate_id = ?1 ; ";
// Revocation tracking
static const char *sql_add_mistrusted_key =
"insert or replace into mistrusted_keys (fpr) "
" values (upper(replace(?1,' ',''))) ;";
static const char *sql_delete_mistrusted_key =
"delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
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) "
"values (?1, ?2) ;";
@ -468,7 +491,7 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
sqlite3_busy_timeout(_session->system_db, 1000);
// increment this when patching DDL
#define _DDL_USER_VERSION "6"
#define _DDL_USER_VERSION "7"
if (in_first) {
@ -515,7 +538,8 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
" on delete set null,\n"
" lang text,\n"
" comment text,\n"
" device_group text\n"
" device_group text,\n"
" is_pep_user integer default 0\n"
");\n"
"create table if not exists identity (\n"
" address text,\n"
@ -564,6 +588,10 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
" on delete cascade on update cascade,\n"
" alternate_id text primary key\n"
");\n"
// mistrusted keys
"create table if not exists mistrusted_keys (\n"
" fpr text primary key\n"
");\n"
,
NULL,
NULL,
@ -600,8 +628,11 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
// is really necessary...
if (version == 1) {
bool version_changed = true;
if (table_contains_column(_session, "identity", "is_own") > 0) {
if (table_contains_column(_session, "person", "is_pep_user") > 0) {
version = 7;
}
else if (table_contains_column(_session, "identity", "is_own") > 0) {
version = 6;
}
else if (table_contains_column(_session, "sequences", "own") > 0) {
@ -777,7 +808,45 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
);
assert(int_result == SQLITE_OK);
}
}
if (version < 7) {
int_result = sqlite3_exec(
_session->db,
"alter table person\n"
" add column is_pep_user integer default 0;\n",
NULL,
NULL,
NULL
);
assert(int_result == SQLITE_OK);
int_result = sqlite3_exec(
_session->db,
"update person\n"
" set is_pep_user = 1\n"
" where id = "
" (select distinct id from person "
" join trust on id = user_id "
" where (case when (comm_type = 127) then (id) "
" when (comm_type = 255) then (id) "
" else 0"
" end) = id );\n",
NULL,
NULL,
NULL
);
assert(int_result == SQLITE_OK);
int_result = sqlite3_exec(
_session->db,
"create table if not exists mistrusted_keys (\n"
" fpr text primary key\n"
");\n",
NULL,
NULL,
NULL
);
assert(int_result == SQLITE_OK);
}
}
else {
// Version from DB was 0, it means this is initial setup.
// DB has just been created, and all tables are empty.
@ -870,6 +939,18 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
(int)strlen(sql_set_person), &_session->set_person, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_set_as_pep_user,
(int)strlen(sql_set_as_pep_user), &_session->set_as_pep_user, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_is_pep_user,
(int)strlen(sql_is_pep_user), &_session->is_pep_user, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_exists_person,
(int)strlen(sql_exists_person), &_session->exists_person, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_set_device_group,
(int)strlen(sql_set_device_group), &_session->set_device_group, NULL);
assert(int_result == SQLITE_OK);
@ -1000,6 +1081,18 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
(int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_add_mistrusted_key,
(int)strlen(sql_add_mistrusted_key), &_session->add_mistrusted_key, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_delete_mistrusted_key,
(int)strlen(sql_delete_mistrusted_key), &_session->delete_mistrusted_key, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_is_mistrusted_key,
(int)strlen(sql_is_mistrusted_key), &_session->is_mistrusted_key, NULL);
assert(int_result == SQLITE_OK);
status = init_cryptotech(_session, in_first);
if (status != PEP_STATUS_OK)
goto pep_error;
@ -1096,6 +1189,12 @@ DYNAMIC_API void release(PEP_SESSION session)
sqlite3_finalize(session->remove_fpr_as_default);
if (session->set_person)
sqlite3_finalize(session->set_person);
if (session->set_as_pep_user)
sqlite3_finalize(session->set_as_pep_user);
if (session->is_pep_user)
sqlite3_finalize(session->is_pep_user);
if (session->exists_person)
sqlite3_finalize(session->exists_person);
if (session->set_device_group)
sqlite3_finalize(session->set_device_group);
if (session->get_device_group)
@ -1159,6 +1258,13 @@ DYNAMIC_API void release(PEP_SESSION session)
if (session->get_revoked)
sqlite3_finalize(session->get_revoked);
if (session->add_mistrusted_key)
sqlite3_finalize(session->add_mistrusted_key);
if (session->delete_mistrusted_key)
sqlite3_finalize(session->delete_mistrusted_key);
if (session->is_mistrusted_key)
sqlite3_finalize(session->is_mistrusted_key);
if (session->db)
sqlite3_close_v2(session->db);
if (session->system_db)
@ -1824,6 +1930,18 @@ DYNAMIC_API PEP_STATUS set_identity(
assert(identity->lang[2] == 0);
}
if (has_fpr) {
sqlite3_reset(session->set_pgp_keypair);
sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
SQLITE_STATIC);
result = sqlite3_step(session->set_pgp_keypair);
sqlite3_reset(session->set_pgp_keypair);
if (result != SQLITE_DONE) {
sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
return PEP_CANNOT_SET_PGP_KEYPAIR;
}
}
sqlite3_reset(session->set_person);
sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
SQLITE_STATIC);
@ -1843,18 +1961,6 @@ DYNAMIC_API PEP_STATUS set_identity(
return PEP_CANNOT_SET_PERSON;
}
if (has_fpr) {
sqlite3_reset(session->set_pgp_keypair);
sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
SQLITE_STATIC);
result = sqlite3_step(session->set_pgp_keypair);
sqlite3_reset(session->set_pgp_keypair);
if (result != SQLITE_DONE) {
sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
return PEP_CANNOT_SET_PGP_KEYPAIR;
}
}
sqlite3_reset(session->set_identity);
sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
SQLITE_STATIC);
@ -1893,6 +1999,146 @@ DYNAMIC_API PEP_STATUS set_identity(
return PEP_COMMIT_FAILED;
}
// This ONLY sets the user flag, and creates a shell identity if necessary.
PEP_STATUS set_as_pep_user(PEP_SESSION session, pEp_identity* user) {
assert(session);
assert(user);
assert(user->address);
assert(!EMPTYSTR(user->user_id));
char* user_id = user->user_id;
if (!session || !user || user->address || EMPTYSTR(user_id))
return PEP_ILLEGAL_VALUE;
PEP_STATUS status = PEP_STATUS_OK;
char* alias_default = NULL;
bool person_exists = false;
status = exists_person(session, user_id, &alias_default, &person_exists);
if (status != PEP_STATUS_OK)
return status;
if (!person_exists) {
if (!user->address)
return PEP_ILLEGAL_VALUE;
// create shell identity
pEp_identity* tmp_id = new_identity(user->address, NULL, user->user_id, user->username);
status = set_identity(session, tmp_id); // this creates the person
free_identity(tmp_id);
if (status != PEP_STATUS_OK)
return status;
alias_default = strdup(user->user_id);
}
// Ok, let's set it.
sqlite3_reset(session->set_as_pep_user);
sqlite3_bind_text(session->set_as_pep_user, 1, alias_default, -1,
SQLITE_STATIC);
int result = sqlite3_step(session->set_as_pep_user);
sqlite3_reset(session->set_as_pep_user);
if (result != SQLITE_DONE)
return PEP_CANNOT_SET_PERSON;
return PEP_STATUS_OK;
}
PEP_STATUS exists_person(PEP_SESSION session, const char* user_id,
char** default_id, bool* exists) {
assert(session);
assert(exists);
assert(!EMPTYSTR(user_id));
if (!session || !exists || EMPTYSTR(user_id))
return PEP_ILLEGAL_VALUE;
*exists = false;
char* alias_default = NULL;
PEP_STATUS status = get_userid_alias_default(session, user_id, &alias_default);
if (status == PEP_CANNOT_FIND_ALIAS || EMPTYSTR(alias_default)) {
free(alias_default);
alias_default = NULL;
sqlite3_reset(session->exists_person);
sqlite3_bind_text(session->exists_person, 1, user_id, -1,
SQLITE_STATIC);
int result = sqlite3_step(session->exists_person);
switch (result) {
case SQLITE_ROW: {
// yeah yeah, I know, we could be lazy here, but it looks bad.
*exists = (sqlite3_column_int(session->exists_person, 0) != 0);
break;
}
default:
return PEP_UNKNOWN_ERROR;
}
if (*exists)
alias_default = strdup(user_id);
}
else
*exists = true; // thank you, delete on cascade!
if (!default_id)
free(alias_default);
else
*default_id = alias_default;
return PEP_STATUS_OK;
}
PEP_STATUS is_pep_user(PEP_SESSION session, pEp_identity *identity, bool* is_pep)
{
assert(session);
assert(is_pep);
assert(identity);
assert(!EMPTYSTR(identity->user_id));
if (!session || !is_pep || !identity || EMPTYSTR(identity->user_id))
return PEP_ILLEGAL_VALUE;
*is_pep = false;
const char* user_id = identity->user_id;
if (!session || EMPTYSTR(user_id))
return PEP_ILLEGAL_VALUE;
char* alias_default = NULL;
PEP_STATUS status = get_userid_alias_default(session, user_id, &alias_default);
if (status == PEP_CANNOT_FIND_ALIAS || EMPTYSTR(alias_default)) {
free(alias_default);
alias_default = strdup(user_id);
}
sqlite3_reset(session->is_pep_user);
sqlite3_bind_text(session->is_pep_user, 1, user_id, -1,
SQLITE_STATIC);
int result = sqlite3_step(session->is_pep_user);
switch (result) {
case SQLITE_ROW: {
// yeah yeah, I know, we could be lazy here, but it looks bad.
*is_pep = (sqlite3_column_int(session->is_pep_user, 0) != 0);
break;
}
default:
free(alias_default);
return PEP_CANNOT_FIND_PERSON;
}
return PEP_STATUS_OK;
}
PEP_STATUS remove_fpr_as_default(PEP_SESSION session,
const char* fpr)
{

@ -1231,6 +1231,21 @@ PEP_STATUS refresh_userid_default_key(PEP_SESSION session, const char* user_id);
PEP_STATUS import_trusted_own_keys(PEP_SESSION session);
// This ONLY sets the *user* flag, and creates a shell identity if necessary.
PEP_STATUS set_as_pep_user(PEP_SESSION session, pEp_identity* user);
// returns true (by reference) if a person with this user_id exists; if default_id != NULL,
// function will also return by reference a copy of the default id which
// is this user_id is aliased to (which will usually, but not always,
// string equivalent to the user_id)
PEP_STATUS exists_person(PEP_SESSION session, const char* user_id,
char** default_id, bool* exists);
// returns true if the USER corresponding to this identity has been listed in
// 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);
#ifdef __cplusplus
}
#endif

@ -131,6 +131,9 @@ struct _pEpSession {
sqlite3_stmt *refresh_userid_default_key;
sqlite3_stmt *remove_fpr_as_default;
sqlite3_stmt *set_person;
sqlite3_stmt *set_as_pep_user;
sqlite3_stmt *is_pep_user;
sqlite3_stmt *exists_person;
sqlite3_stmt *set_device_group;
sqlite3_stmt *get_device_group;
sqlite3_stmt *set_pgp_keypair;
@ -173,6 +176,11 @@ struct _pEpSession {
sqlite3_stmt *set_revoked;
sqlite3_stmt *get_revoked;
// mistrusted
sqlite3_stmt* add_mistrusted_key;
sqlite3_stmt* is_mistrusted_key;
sqlite3_stmt* delete_mistrusted_key;
// aliases
sqlite3_stmt *get_userid_alias_default;
sqlite3_stmt *add_userid_alias;
@ -405,8 +413,8 @@ static inline bool is_me(PEP_SESSION session, pEp_identity* test_ident) {
// These are globals used in generating message IDs and should only be
// computed once, as they're either really constants or OS-dependent
int _pEp_rand_max_bits;
double _pEp_log2_36;
extern int _pEp_rand_max_bits;
extern double _pEp_log2_36;
static inline void _init_globals() {
_pEp_rand_max_bits = ceil(log2(RAND_MAX));

@ -58,8 +58,12 @@ int main() {
assert(status == PEP_STATUS_OK);
status = update_identity(session,recip1);
assert(status == PEP_STATUS_OK);
assert(recip1->comm_type == PEP_ct_key_not_found);
recip1->fpr = strdup("BACC7A60A88A39A25D99B4A545D7542F39E5DAB5");
status = get_trust(session, recip1);
assert(recip1->comm_type == PEP_ct_mistrusted);
cout << "Mistrusted mistrust.undo.test@pep-project.org (BACC7A60A88A39A25D99B4A545D7542F39E5DAB5) and comm_type set to PEP_ct_mistrusted)." << endl << endl;
cout << "Mistrusted mistrust.undo.test@pep-project.org (BACC7A60A88A39A25D99B4A545D7542F39E5DAB5) and comm_type IN DB set to PEP_ct_mistrusted)." << endl << endl;
cout << "Undo mistrust (restore identity and trust in DB)" << endl;
// Undo it

@ -38,7 +38,7 @@ int main() {
cout << uniqname << "\n";
const char* own_user_id = "FineOwnIdentitiesOfBuckTFerris";
const char* own_user_id = get_new_uuid();
const char* start_username = "Unser Testkandidat";
pEp_identity * new_me = new_identity(uniqname, NULL, own_user_id, start_username);
@ -481,28 +481,130 @@ int main() {
cout << "****************************************************************************************" << endl;
cout << "* III: 2. key election: get identity for user with only revoked keys " << endl;
cout << "* III: 2. key election: get identity for user with only revoked or mistrusted keys " << endl;
cout << "****************************************************************************************" << endl << endl;
// Create id with no key
cout << "Creating new id with no key for : ";
char *uniqname_10000 = strdup("AAAAtestuser@testdomain.org");
srandom(time(NULL));
for(int i=0; i < 4;i++)
uniqname_10000[i] += random() & 0xf;
cout << uniqname_10000 << "\n";
char* revoke_uuid = get_new_uuid();
pEp_identity * revokemaster_3000 = new_identity(uniqname_10000, NULL, revoke_uuid, start_username);
cout << "Generate three keys for " << uniqname_10000 << " who has user_id " << revoke_uuid << endl;
char* revoke_fpr_arr[3];
status = generate_keypair(session, revokemaster_3000);
assert(status == PEP_STATUS_OK && revokemaster_3000->fpr);
revoke_fpr_arr[0] = strdup(revokemaster_3000->fpr);
free(revokemaster_3000->fpr);
revokemaster_3000->fpr = NULL;
status = generate_keypair(session, revokemaster_3000);
assert(status == PEP_STATUS_OK && revokemaster_3000->fpr);
revoke_fpr_arr[1] = strdup(revokemaster_3000->fpr);
free(revokemaster_3000->fpr);
revokemaster_3000->fpr = NULL;
status = generate_keypair(session, revokemaster_3000);
assert(status == PEP_STATUS_OK && revokemaster_3000->fpr);
revoke_fpr_arr[2] = strdup(revokemaster_3000->fpr);
free(revokemaster_3000->fpr);
revokemaster_3000->fpr = NULL;
cout << "Trust " << revoke_fpr_arr[2] << " (default for identity) and " << revoke_fpr_arr[0] << endl;
status = revoke_key(session, new_fpr, "Because it's more fun to revoke ALL of someone's keys");
free(revokemaster_3000->fpr);
revokemaster_3000->fpr = strdup(revoke_fpr_arr[2]);
status = trust_personal_key(session, revokemaster_3000);
assert(status == PEP_STATUS_OK);
assert(revokemaster_3000->comm_type & PEP_ct_confirmed);
free(revokemaster_3000->fpr);
revokemaster_3000->fpr = strdup(revoke_fpr_arr[0]);
status = trust_personal_key(session, revokemaster_3000);
assert(status == PEP_STATUS_OK);
assert(revokemaster_3000->comm_type & PEP_ct_confirmed);
status = update_identity(session, revokemaster_3000);
assert(status == PEP_STATUS_OK);
assert(revokemaster_3000->fpr);
assert(strcmp(revokemaster_3000->fpr, revoke_fpr_arr[2]) == 0);
assert(revokemaster_3000->comm_type & PEP_ct_confirmed);
cout << "update_identity returns the correct identity default." << endl;
cout << "Ok, now... we revoke the default..." << endl;
cout << "Revoking " << revoke_fpr_arr[2] << endl;
status = revoke_key(session, revoke_fpr_arr[2], "This little pubkey went to market");
assert (status == PEP_STATUS_OK);
bool is_revoked;
status = key_revoked(session, revokemaster_3000->fpr, &is_revoked);
assert(status == PEP_STATUS_OK);
assert(is_revoked);
cout << "Success revoking " << revoke_fpr_arr[2] << "!!! get_trust for this fpr gives us " << revokemaster_3000->comm_type << endl;
cout << "Now see if update_identity gives us " << revoke_fpr_arr[0] << ", the only trusted key left." << endl;
status = update_identity(session, revokemaster_3000);
assert(status == PEP_STATUS_OK);
assert(revokemaster_3000->fpr);
assert(strcmp(revokemaster_3000->fpr, revoke_fpr_arr[0]) == 0);
assert(revokemaster_3000->comm_type & PEP_ct_confirmed);
new_me = new_identity(uniqname, NULL, NULL, NULL);
cout << "Success! So let's mistrust it, because seriously, that key was so uncool." << endl;
status = update_identity(session, new_me);
assert(status != PEP_STATUS_OK);
assert(!new_me->fpr);
assert(new_me->username);
assert(strcmp(new_me->username, start_username) == 0);
assert(new_me->user_id);
assert(strcmp(new_me->user_id, default_own_id) == 0);
assert(new_me->me);
assert(new_me->comm_type == PEP_ct_key_revoked);
status = key_mistrusted(session, revokemaster_3000);
assert(status == PEP_STATUS_OK);
status = get_trust(session, revokemaster_3000);
assert(status == PEP_STATUS_OK);
assert(revokemaster_3000->comm_type == PEP_ct_mistrusted);
cout << "PASS: update_identity() correctly rejected two revoked keys with PEP_KEY_UNSUITABLE and PEP_ct_key_revoked";
cout << endl << endl;
cout << "Success! get_trust for this fpr gives us " << revokemaster_3000->comm_type << endl;
free_identity(new_me);
cout << "The only fpr left is an untrusted one - let's make sure this is what we get from update_identity." << endl;
status = update_identity(session, revokemaster_3000);
assert(status == PEP_STATUS_OK);
assert(revokemaster_3000->fpr);
assert(strcmp(revokemaster_3000->fpr, revoke_fpr_arr[1]) == 0);
assert(!(revokemaster_3000->comm_type & PEP_ct_confirmed));
cout << "Success! We got " << revoke_fpr_arr[1] << "as the fpr with comm_type " << revokemaster_3000->comm_type << endl;
cout << "But, you know... let's revoke that one too and see what update_identity gives us." << endl;
status = revoke_key(session, revoke_fpr_arr[1], "Because it's more fun to revoke ALL of someone's keys");
assert (status == PEP_STATUS_OK);
status = key_revoked(session, revokemaster_3000->fpr, &is_revoked);
assert(status == PEP_STATUS_OK);
assert(is_revoked);
cout << "Success! get_trust for this fpr gives us " << revokemaster_3000->comm_type << endl;
cout << "Call update_identity - we expect nothing, plus an error comm type." << endl;
status = update_identity(session, revokemaster_3000);
assert(status != PEP_STATUS_OK);
assert(!revokemaster_3000->fpr);
assert(revokemaster_3000->username);
assert(strcmp(revokemaster_3000->user_id, revoke_uuid) == 0);
assert(revokemaster_3000->comm_type == PEP_ct_key_not_found);
cout << "Success! No key found. The comm_status error was " << revokemaster_3000->comm_type << "and the return status was " << tl_status_string(status) << endl;
free_identity(revokemaster_3000);
cout << "****************************************************************************************" << endl;
cout << "* III: 100000000. key election: more to come " << endl;

@ -32,7 +32,7 @@ std::string slurp(const std::string& filename)
return sstr.str();
}
// no C++11, yet? So do our own implementation:
// no C++11, yet? So do our own implementation:1G
namespace{
std::string to_string(unsigned long u)
{
@ -270,6 +270,7 @@ int main(int argc, char* argv[])
cout << "\nsetting identity...\n";
PEP_STATUS pep_set_result = set_identity(session, identity);
cout << pep_set_result << endl;
assert(pep_set_result == PEP_STATUS_OK);
free_identity(identity);
get_identity(session, "leon.schumacher@digitalekho.com", "23", &identity);

Loading…
Cancel
Save