Merged in default (including ENGINE-463) - tests pass

generate_api
Krista Bennett 5 years ago
commit f49d137edb

@ -237,6 +237,16 @@ NETPGP_INC=
#NETPGP_INC=-I$(PREFIX)/include
######### OpenPGP #########
# CppUnit library search flag
CPPUNIT_LIB=
#CPPUNIT_LIB=-L$(HOME)/local/lib
# CppUnit include search flag
CPPUNIT_INC=
#CPPUNIT_INC=-I$(HOME)/local/inc
######### Engine internals #########
# C macros (not environment variables) that can be overridden:
# DEFAULT_KEYSERVER - string with default keyserver

@ -19,7 +19,8 @@ typedef enum _PEP_cryptotech {
typedef PEP_STATUS (*decrypt_and_verify_t)(
PEP_SESSION session, const char *ctext, size_t csize,
const char *dsigtext, size_t dsigsize,
char **ptext, size_t *psize, stringlist_t **keylist
char **ptext, size_t *psize, stringlist_t **keylist,
char **filename_ptr
);
typedef PEP_STATUS (*verify_text_t)(

@ -568,40 +568,53 @@ DYNAMIC_API PEP_STATUS update_identity(
if (id_list) {
identity_list* id_curr = id_list;
bool input_is_TOFU = strstr(identity->user_id, "TOFU_") == identity->user_id;
while (id_curr) {
pEp_identity* this_id = id_curr->ident;
if (this_id) {
char* this_uid = this_id->user_id;
if (this_uid && (strstr(this_uid, "TOFU_") == this_uid)) {
// FIXME: should we also be fixing pEp_own_userId in this
// function here?
// if usernames match, we replace the userid. Or if the temp username
// is anonymous.
// FIXME: do we need to create an address match function which
// matches the whole dot-and-case rigamarole from
if (EMPTYSTR(this_id->username) ||
strcasecmp(this_id->username, this_id->address) == 0 ||
(identity->username &&
strcasecmp(identity->username,
this_id->username) == 0)) {
bool curr_is_TOFU = strstr(this_uid, "TOFU_") == this_uid;
if (this_uid) {
if (curr_is_TOFU && !input_is_TOFU) {
// FIXME: should we also be fixing pEp_own_userId in this
// function here?
// Ok, we have a temp ID. We have to replace this
// with the real ID.
status = replace_userid(session,
this_uid,
identity->user_id);
if (status != PEP_STATUS_OK) {
free_identity_list(id_list);
free(default_own_id);
return status;
}
// if usernames match, we replace the userid. Or if the temp username
// is anonymous.
// FIXME: do we need to create an address match function which
// matches the whole dot-and-case rigamarole from
if (EMPTYSTR(this_id->username) ||
strcasecmp(this_id->username, this_id->address) == 0 ||
(identity->username &&
strcasecmp(identity->username,
this_id->username) == 0)) {
free(this_uid);
this_uid = NULL;
// Reflect the change we just made to the DB
this_id->user_id = strdup(identity->user_id);
// Ok, we have a temp ID. We have to replace this
// with the real ID.
status = replace_userid(session,
this_uid,
identity->user_id);
if (status != PEP_STATUS_OK) {
free_identity_list(id_list);
free(default_own_id);
return status;
}
free(this_uid);
this_uid = NULL;
// Reflect the change we just made to the DB
this_id->user_id = strdup(identity->user_id);
stored_ident = this_id;
// FIXME: free list.
break;
}
}
else if (input_is_TOFU && !curr_is_TOFU) {
// Replace ruthlessly - this is NOT supposed to happen.
// BAD APP BEHAVIOUR.
free(identity->user_id);
identity->user_id = strdup(this_id->user_id);
stored_ident = this_id;
// FIXME: free list.
break;

@ -0,0 +1,121 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "platform.h"
#include "labeled_int_list.h"
labeled_int_list_t *new_labeled_int_list(int value, const char* label)
{
assert(label);
if (!label)
return NULL;
labeled_int_list_t * labeled_int_list = calloc(1, sizeof(labeled_int_list_t));
assert(labeled_int_list);
if (labeled_int_list == NULL)
return NULL;
labeled_int_list->value = value;
labeled_int_list->label = strdup(label);
if (!labeled_int_list->label) {
free(labeled_int_list);
labeled_int_list = NULL;
}
return labeled_int_list;
}
void free_labeled_int_list(labeled_int_list_t *labeled_int_list)
{
labeled_int_list_t *curr = labeled_int_list;
while (curr) {
labeled_int_list_t *next = curr->next;
free(curr->label);
free(curr);
curr = next;
}
}
labeled_int_list_t *labeled_int_list_dup(const labeled_int_list_t *src)
{
assert(src);
if (src == NULL)
return NULL;
labeled_int_list_t *labeled_int_list = NULL;
labeled_int_list = new_labeled_int_list(src->value, src->label);
if (labeled_int_list == NULL)
goto enomem;
labeled_int_list_t* src_curr = src->next;
labeled_int_list_t** dst_curr_ptr = &labeled_int_list->next;
// list
while (src_curr) {
*dst_curr_ptr = new_labeled_int_list(src_curr->value, src_curr->label);
if (*dst_curr_ptr == NULL)
goto enomem;
src_curr = src_curr->next;
dst_curr_ptr = &((*dst_curr_ptr)->next);
}
return labeled_int_list;
enomem:
free_labeled_int_list(labeled_int_list);
return NULL;
}
labeled_int_list_t *labeled_int_list_add(labeled_int_list_t *labeled_int_list, int value, const char* label)
{
if (!label)
return NULL;
if (!labeled_int_list)
return new_labeled_int_list(value, label);
if (!labeled_int_list->label) { // empty list
assert(!labeled_int_list->next);
if (labeled_int_list->next)
return NULL; // invalid list
labeled_int_list->value = value;
labeled_int_list->label = strdup(label);
if (!labeled_int_list->label) {
free(labeled_int_list);
labeled_int_list = NULL;
}
return labeled_int_list;
}
labeled_int_list_t* list_curr = labeled_int_list;
while (list_curr->next)
list_curr = list_curr->next;
list_curr->next = new_labeled_int_list(value, label);
assert(list_curr->next);
if (!list_curr->next)
return NULL;
return list_curr->next;
}
int labeled_int_list_length(const labeled_int_list_t *labeled_int_list)
{
int len = 0;
for (const labeled_int_list_t *_li = labeled_int_list; _li && _li->label; _li = _li->next)
len++;
return len;
}

@ -0,0 +1,31 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#pragma once
#include "dynamic_api.h"
#include "stringpair.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _labeled_int_list_t {
int value;
char* label; // UTF-8 string, null-terminated
struct _labeled_int_list_t *next; // this is a single linked list
} labeled_int_list_t;
labeled_int_list_t *new_labeled_int_list(int value, const char* label);
void free_labeled_int_list(labeled_int_list_t *labeled_int_list);
labeled_int_list_t *labeled_int_list_dup(const labeled_int_list_t *src);
labeled_int_list_t *labeled_int_list_add(labeled_int_list_t *labeled_int_list, int value, const char* label);
int labeled_int_list_length(const labeled_int_list_t *labeled_int_list);
#ifdef __cplusplus
}
#endif

@ -1458,7 +1458,8 @@ bool import_attached_keys(
blob_value, blob_size,
NULL, 0,
&bl_ptext, &bl_psize,
&bl_keylist);
&bl_keylist,
NULL);
free_stringlist(bl_keylist); // we don't care about key encryption as long as we decrypt
if (_status == PEP_DECRYPTED || _status == PEP_DECRYPTED_AND_VERIFIED) {
free_blobval = true;
@ -2711,7 +2712,8 @@ static PEP_STATUS verify_decrypted(PEP_SESSION session,
free_stringlist(*keylist);
*decrypt_status = decrypt_and_verify(session, ctext, csize,
NULL, 0,
&ptext, &psize, keylist);
&ptext, &psize, keylist,
NULL);
}
@ -2761,9 +2763,12 @@ static PEP_STATUS _decrypt_in_pieces(PEP_SESSION session,
free(ptext);
ptext = NULL;
char* pgp_filename = NULL;
status = decrypt_and_verify(session, attctext, attcsize,
NULL, 0,
&ptext, &psize, &_keylist);
&ptext, &psize, &_keylist,
&pgp_filename);
free_stringlist(_keylist);
if (ptext) {
@ -2773,17 +2778,25 @@ static PEP_STATUS _decrypt_in_pieces(PEP_SESSION session,
}
else {
static const char * const mime_type = "application/octet-stream";
char * const filename =
without_double_ending(_s->filename);
if (filename == NULL)
return PEP_OUT_OF_MEMORY;
_m = bloblist_add(_m, ptext, psize, mime_type,
filename);
free(filename);
if (_m == NULL)
return PEP_OUT_OF_MEMORY;
if (pgp_filename) {
_m = bloblist_add(_m, ptext, psize, mime_type,
pgp_filename);
free(pgp_filename);
if (_m == NULL)
return PEP_OUT_OF_MEMORY;
}
else {
char * const filename =
without_double_ending(_s->filename);
if (filename == NULL)
return PEP_OUT_OF_MEMORY;
_m = bloblist_add(_m, ptext, psize, mime_type,
filename);
free(filename);
if (_m == NULL)
return PEP_OUT_OF_MEMORY;
}
ptext = NULL;
if (msg->attachments == NULL)
@ -2812,6 +2825,7 @@ static PEP_STATUS _decrypt_in_pieces(PEP_SESSION session,
return PEP_OUT_OF_MEMORY;
}
}
return status;
}
@ -3273,7 +3287,8 @@ DYNAMIC_API PEP_STATUS _decrypt_message(
/** 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,
&ptext, &psize, &_keylist);
&ptext, &psize, &_keylist,
NULL);
if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
goto pEp_error;

@ -98,19 +98,6 @@ static const char *sql_get_identity =
" order by is_own desc, "
" timestamp desc; ";
static const char *sql_get_identities_by_userid =
"select address, fpr, username, comm_type, lang,"
" identity.flags | pgp_keypair.flags,"
" is_own"
" from identity"
" join person on id = identity.user_id"
" join pgp_keypair on fpr = identity.main_key_id"
" join trust on id = trust.user_id"
" and pgp_keypair_fpr = identity.main_key_id"
" where identity.user_id = ?1"
" order by is_own desc, "
" timestamp desc; ";
static const char *sql_get_identities_by_main_key_id =
"select address, identity.user_id, username, comm_type, lang,"
" identity.flags | pgp_keypair.flags,"
@ -150,6 +137,19 @@ static const char *sql_get_identities_by_address =
" end) = 1 "
" order by is_own desc, "
" timestamp desc; ";
static const char *sql_get_identities_by_userid =
"select address, fpr, username, comm_type, lang,"
" identity.flags | pgp_keypair.flags,"
" is_own"
" from identity"
" join person on id = identity.user_id"
" join pgp_keypair on fpr = identity.main_key_id"
" join trust on id = trust.user_id"
" and pgp_keypair_fpr = identity.main_key_id"
" where identity.user_id = ?1"
" order by is_own desc, "
" timestamp desc; ";
static const char *sql_replace_identities_fpr =
"update identity"
@ -178,7 +178,11 @@ static const char *sql_update_person =
" device_group = "
" (select device_group from person where id = ?1)"
" where id = ?1 ;";
// Will cascade.
static const char *sql_delete_person =
"delete from person where id = ?1 ;";
static const char *sql_set_as_pEp_user =
"update person set is_pEp_user = 1 "
" where id = ?1 ; ";
@ -337,6 +341,9 @@ static const char *sql_get_trust =
"select comm_type from trust where user_id = ?1 "
"and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
static const char *sql_get_trust_by_userid =
"select pgp_keypair_fpr, comm_type from trust where user_id = ?1 ";
static const char *sql_least_trust =
"select min(comm_type) from trust where"
" pgp_keypair_fpr = upper(replace(?1,' ',''))"
@ -1157,7 +1164,7 @@ DYNAMIC_API PEP_STATUS init(
(int)strlen(sql_get_identities_by_address),
&_session->get_identities_by_address, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_get_identities_by_userid,
(int)strlen(sql_get_identities_by_userid),
&_session->get_identities_by_userid, NULL);
@ -1226,6 +1233,10 @@ DYNAMIC_API PEP_STATUS init(
(int)strlen(sql_update_person), &_session->update_person, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_delete_person,
(int)strlen(sql_delete_person), &_session->delete_person, 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);
@ -1337,6 +1348,10 @@ DYNAMIC_API PEP_STATUS init(
(int)strlen(sql_get_trust), &_session->get_trust, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_get_trust_by_userid,
(int)strlen(sql_get_trust_by_userid), &_session->get_trust_by_userid, NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
(int)strlen(sql_least_trust), &_session->least_trust, NULL);
assert(int_result == SQLITE_OK);
@ -1539,6 +1554,8 @@ 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->delete_person)
sqlite3_finalize(session->delete_person);
if (session->set_as_pEp_user)
sqlite3_finalize(session->set_as_pEp_user);
if (session->is_pEp_user)
@ -1585,6 +1602,8 @@ DYNAMIC_API void release(PEP_SESSION session)
sqlite3_finalize(session->update_trust_for_fpr);
if (session->get_trust)
sqlite3_finalize(session->get_trust);
if (session->get_trust_by_userid)
sqlite3_finalize(session->get_trust_by_userid);
if (session->least_trust)
sqlite3_finalize(session->least_trust);
if (session->mark_compromised)
@ -2853,6 +2872,27 @@ PEP_STATUS exists_person(PEP_SESSION session, pEp_identity* identity,
return status;
}
PEP_STATUS delete_person(PEP_SESSION session, const char* user_id) {
assert(session);
assert(!EMPTYSTR(user_id));
if (!session || EMPTYSTR(user_id))
return PEP_ILLEGAL_VALUE;
PEP_STATUS status = PEP_STATUS_OK;
sqlite3_reset(session->delete_person);
sqlite3_bind_text(session->delete_person, 1, user_id, -1,
SQLITE_STATIC);
int result = sqlite3_step(session->delete_person);
if (result != SQLITE_DONE)
status = PEP_UNKNOWN_ERROR;
sqlite3_reset(session->delete_person);
return status;
}
DYNAMIC_API PEP_STATUS is_pEp_user(PEP_SESSION session, pEp_identity *identity, bool* is_pEp)
{
assert(session);
@ -3184,9 +3224,327 @@ DYNAMIC_API PEP_STATUS unset_identity_flags(
return PEP_STATUS_OK;
}
PEP_STATUS get_trust_by_userid(PEP_SESSION session, const char* user_id,
labeled_int_list_t** trust_list)
{
int result;
if (!(session && user_id && user_id[0]))
return PEP_ILLEGAL_VALUE;
*trust_list = NULL;
labeled_int_list_t* t_list = NULL;
sqlite3_reset(session->get_trust_by_userid);
sqlite3_bind_text(session->get_trust_by_userid, 1, user_id, -1, SQLITE_STATIC);
while ((result = sqlite3_step(session->get_trust_by_userid)) == SQLITE_ROW) {
if (!t_list)
t_list = new_labeled_int_list(sqlite3_column_int(session->get_trust_by_userid, 1),
(const char *) sqlite3_column_text(session->get_trust_by_userid, 0));
else
labeled_int_list_add(t_list, sqlite3_column_int(session->get_trust_by_userid, 1),
(const char *) sqlite3_column_text(session->get_trust_by_userid, 0));
}
sqlite3_reset(session->get_trust_by_userid);
*trust_list = t_list;
return PEP_STATUS_OK;
}
PEP_comm_type reconcile_trust(PEP_comm_type t_old, PEP_comm_type t_new) {
switch (t_new) {
case PEP_ct_mistrusted:
case PEP_ct_key_revoked:
case PEP_ct_compromised:
case PEP_ct_key_b0rken:
return t_new;
default:
break;
}
switch (t_old) {
case PEP_ct_mistrusted:
case PEP_ct_key_revoked:
case PEP_ct_compromised:
case PEP_ct_key_b0rken:
return t_old;
default:
break;
}
if (t_old < PEP_ct_strong_but_unconfirmed && t_new >= PEP_ct_strong_but_unconfirmed)
return t_new;
bool confirmed = (t_old & PEP_ct_confirmed) || (t_new & PEP_ct_confirmed);
PEP_comm_type result = _MAX(t_old, t_new);
if (confirmed)
result |= PEP_ct_confirmed;
return result;
}
PEP_STATUS reconcile_pEp_status(PEP_SESSION session, const char* old_uid,
const char* new_uid) {
PEP_STATUS status = PEP_STATUS_OK;
// We'll make this easy - if the old one has a pEp status, we set no matter
// what.
pEp_identity* ident = new_identity(NULL, NULL, old_uid, NULL);
bool is_pEp_peep = false;
status = is_pEp_user(session, ident, &is_pEp_peep);
if (is_pEp_peep) {
free(ident->user_id);
ident->user_id = strdup(new_uid);
if (!ident->user_id) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
}
status = set_as_pEp_user(session, ident);
}
pEp_free:
free_identity(ident);
return status;
}
const char* reconcile_usernames(const char* old_name, const char* new_name,
const char* address) {
if (EMPTYSTR(old_name)) {
if (EMPTYSTR(new_name))
return address;
else
return new_name;
}
if (EMPTYSTR(new_name))
return old_name;
if (strcmp(new_name, address) == 0)
return old_name;
return new_name;
}
PEP_STATUS reconcile_default_keys(PEP_SESSION session, pEp_identity* old_ident,
pEp_identity* new_ident) {
PEP_STATUS status = PEP_STATUS_OK;
const char* old_fpr = old_ident->fpr;
const char* new_fpr = new_ident->fpr;
if (!old_fpr)
return status;
PEP_comm_type old_ct = old_ident->comm_type;
PEP_comm_type new_ct = new_ident->comm_type;
if (!new_fpr) {
new_ident->fpr = strdup(old_fpr);
if (!new_ident->fpr)
status = PEP_OUT_OF_MEMORY;
else
new_ident->comm_type = old_ct;
return status;
}
if (strcmp(old_fpr, new_fpr) == 0) {
new_ident->comm_type = reconcile_trust(old_ct, new_ct);
return status;
}
bool old_confirmed = old_ct & PEP_ct_confirmed;
bool new_confirmed = new_ct & PEP_ct_confirmed;
if (new_confirmed)
return status;
else if (old_confirmed) {
free(new_ident->fpr);
new_ident->fpr = strdup(old_fpr);
if (!new_ident->fpr)
status = PEP_OUT_OF_MEMORY;
else
new_ident->comm_type = old_ct;
return status;
}
if (old_ct > new_ct) {
free(new_ident->fpr);
new_ident->fpr = strdup(old_fpr);
if (!new_ident->fpr)
status = PEP_OUT_OF_MEMORY;
else
new_ident->comm_type = old_ct;
}
return status;
}
void reconcile_language(pEp_identity* old_ident,
pEp_identity* new_ident) {
if (new_ident->lang[0] == 0) {
if (old_ident->lang[0] != 0) {
new_ident->lang[0] = old_ident->lang[0];
new_ident->lang[1] = old_ident->lang[1];
new_ident->lang[2] = old_ident->lang[2];
}
}
}
// ONLY CALL THIS IF BOTH IDs ARE IN THE PERSON DB, FOOL! </Mr_T>
PEP_STATUS merge_records(PEP_SESSION session, const char* old_uid,
const char* new_uid) {
PEP_STATUS status = PEP_STATUS_OK;
status = reconcile_pEp_status(session, old_uid, new_uid);
if (status != PEP_STATUS_OK)
goto pEp_free;
pEp_identity* new_ident = NULL;
identity_list* old_identities = NULL;
labeled_int_list_t* trust_list = NULL;
stringlist_t* touched_keys = new_stringlist(NULL);
char* main_user_fpr = NULL;
bool new_is_pEp = false;
new_ident = new_identity(NULL, NULL, new_uid, NULL);
status = is_pEp_user(session, new_ident, &new_is_pEp);
if (status != PEP_STATUS_OK)
goto pEp_free;
free(new_ident);
new_ident = NULL;
status = get_identities_by_userid(session, old_uid, &old_identities);
if (status == PEP_STATUS_OK && old_identities) {
identity_list* curr_old = old_identities;
for (; curr_old && curr_old->ident; curr_old = curr_old->next) {
pEp_identity* old_ident = curr_old->ident;
const char* address = old_ident->address;
status = get_identity(session, address, new_uid, &new_ident);
if (status == PEP_CANNOT_FIND_IDENTITY) {
// No new identity matching the old one, so we just set one w. new user_id
free(old_ident->user_id);
old_ident->user_id = strdup(new_uid);
if (!old_ident->user_id) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
}
if (new_is_pEp) {
PEP_comm_type confirmed_bit = old_ident->comm_type & PEP_ct_confirmed;
if ((old_ident->comm_type | PEP_ct_confirmed) == PEP_ct_OpenPGP)
old_ident->comm_type = PEP_ct_pEp_unconfirmed | confirmed_bit;
}
status = set_identity(session, old_ident);
if (status != PEP_STATUS_OK)
goto pEp_free;
}
else if (status != PEP_STATUS_OK)
goto pEp_free;
else {
// Ok, so we have two idents which might be in conflict. Have to merge them.
const char* username = reconcile_usernames(old_ident->username,
new_ident->username,
address);
if (!new_ident->username || strcmp(username, new_ident->username) != 0) {
free(new_ident->username);
new_ident->username = strdup(username);
if (!new_ident->username) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
}
}
// Reconcile default keys if they differ, trust if they don't
status = reconcile_default_keys(session, old_ident, new_ident);
if (status != PEP_STATUS_OK)
goto pEp_free;
// reconcile languages
reconcile_language(old_ident, new_ident);
// reconcile flags - FIXME - is this right?
new_ident->flags |= old_ident->flags;
// NOTE: In principle, this is only called from update_identity,
// which would never have me flags set. So I am ignoring them here.
// if this function is ever USED for that, though, you'll have
// to go through making sure that the user ids are appropriately
// aliased, etc. So be careful.
// Set the reconciled record
status = set_identity(session, new_ident);
if (status != PEP_STATUS_OK)
goto pEp_free;
if (new_ident->fpr)
stringlist_add(touched_keys, new_ident->fpr);
free_identity(new_ident);
new_ident = NULL;
}
}
}
// otherwise, no need to reconcile identity records. But maybe trust...
new_ident = new_identity(NULL, NULL, new_uid, NULL);
if (!new_ident) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
}
status = get_trust_by_userid(session, old_uid, &trust_list);
labeled_int_list_t* trust_curr = trust_list;
for (; trust_curr && trust_curr->label; trust_curr = trust_curr->next) {
const char* curr_fpr = trust_curr->label;
new_ident->fpr = strdup(curr_fpr);
status = get_trust(session, new_ident);
switch (status) {
case PEP_STATUS_OK:
new_ident->comm_type = reconcile_trust(trust_curr->value,
new_ident->comm_type);
break;
case PEP_CANNOT_FIND_IDENTITY:
new_ident->comm_type = trust_curr->value;
break;
default:
goto pEp_free;
}
new_ident->comm_type = reconcile_trust(trust_curr->value,
new_ident->comm_type);
if (new_is_pEp) {
PEP_comm_type confirmed_bit = new_ident->comm_type & PEP_ct_confirmed;
if ((new_ident->comm_type | PEP_ct_confirmed) == PEP_ct_OpenPGP)
new_ident->comm_type = PEP_ct_pEp_unconfirmed | confirmed_bit;
}
status = set_trust(session, new_ident);
if (status != PEP_STATUS_OK) {
goto pEp_free;
}
free(new_ident->fpr);
new_ident->fpr = NULL;
new_ident->comm_type = 0;
}
// reconcile the default keys if the new id doesn't have one?
status = get_main_user_fpr(session, new_uid, &main_user_fpr);
if (status == PEP_KEY_NOT_FOUND || (status == PEP_STATUS_OK && !main_user_fpr)) {
status = get_main_user_fpr(session, old_uid, &main_user_fpr);
if (status == PEP_STATUS_OK && main_user_fpr)
status = replace_main_user_fpr(session, new_uid, main_user_fpr);
if (status != PEP_STATUS_OK)
goto pEp_free;
}
// delete the old user
status = delete_person(session, old_uid);
pEp_free:
free_identity(new_ident);
free_identity_list(old_identities);
free_labeled_int_list(trust_list);
free_stringlist(touched_keys);
free(main_user_fpr);
return status;
}
PEP_STATUS replace_userid(PEP_SESSION session, const char* old_uid,
const char* new_uid) {
const char* new_uid) {
assert(session);
assert(old_uid);
assert(new_uid);
@ -3194,6 +3552,15 @@ PEP_STATUS replace_userid(PEP_SESSION session, const char* old_uid,
if (!session || !old_uid || !new_uid)
return PEP_ILLEGAL_VALUE;
pEp_identity* temp_ident = new_identity(NULL, NULL, new_uid, NULL);
bool new_exists = false;
PEP_STATUS status = exists_person(session, temp_ident, &new_exists);
free_identity(temp_ident);
if (status != PEP_STATUS_OK) // DB error
return status;
if (new_exists)
return merge_records(session, old_uid, new_uid);
int result;
@ -3203,6 +3570,12 @@ PEP_STATUS replace_userid(PEP_SESSION session, const char* old_uid,
sqlite3_bind_text(session->replace_userid, 2, old_uid, -1,
SQLITE_STATIC);
result = sqlite3_step(session->replace_userid);
#ifndef NDEBUG
if (result) {
const char *errmsg = sqlite3_errmsg(session->db);
log_event(session, "SQLite3 error", "replace_userid", errmsg, NULL);
}
#endif // !NDEBUG
sqlite3_reset(session->replace_userid);
if (result != SQLITE_DONE)
return PEP_CANNOT_SET_PERSON; // May need clearer retval
@ -3376,8 +3749,8 @@ DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
return PEP_ILLEGAL_VALUE;
identity->comm_type = PEP_ct_unknown;
sqlite3_reset(session->get_trust);
sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
SQLITE_STATIC);
sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
@ -3399,6 +3772,7 @@ DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
return status;
}
DYNAMIC_API PEP_STATUS least_trust(
PEP_SESSION session,
const char *fpr,
@ -3439,7 +3813,8 @@ DYNAMIC_API PEP_STATUS least_trust(
DYNAMIC_API PEP_STATUS decrypt_and_verify(
PEP_SESSION session, const char *ctext, size_t csize,
const char *dsigtext, size_t dsigsize,
char **ptext, size_t *psize, stringlist_t **keylist
char **ptext, size_t *psize, stringlist_t **keylist,
char** filename_ptr
)
{
assert(session);
@ -3453,8 +3828,8 @@ DYNAMIC_API PEP_STATUS decrypt_and_verify(
return PEP_ILLEGAL_VALUE;
PEP_STATUS status = session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(
session, ctext, csize, dsigtext, dsigsize, ptext, psize, keylist);
if (status == PEP_DECRYPT_NO_KEY)
session, ctext, csize, dsigtext, dsigsize, ptext, psize, keylist,
filename_ptr);
signal_Sync_event(session, Sync_PR_keysync, CannotDecrypt);
return status;

@ -13,7 +13,8 @@ extern "C" {
#include "dynamic_api.h"
#include "stringlist.h"
#include "stringpair.h"
#include "stringpair.h"
#include "labeled_int_list.h"
#include "timestamp.h"
#define PEP_VERSION "2.0" // protocol version
@ -282,16 +283,20 @@ DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable);
// decrypt_and_verify() - decrypt and/or verify a message
//
// parameters:
// session (in) session handle
// ctext (in) cipher text to decrypt and/or verify
// csize (in) size of cipher text
// dsigtext (in) if extant, *detached* signature text for this
// message (or NULL if not)
// dsize (in) size of *detached* signature text for this
// message (0, if no detached sig exists)
// ptext (out) pointer to internal buffer with plain text
// psize (out) size of plain text
// keylist (out) list of key ids which where used to encrypt
// session (in) session handle
// ctext (in) cipher text to decrypt and/or verify
// csize (in) size of cipher text
// dsigtext (in) if extant, *detached* signature text for this
// message (or NULL if not)
// dsize (in) size of *detached* signature text for this
// message (0, if no detached sig exists)
// ptext (out) pointer to internal buffer with plain text
// psize (out) size of plain text
// keylist (out) list of key ids which where used to encrypt
// filename_ptr (out) mails produced by certain PGP implementations
// may return a decrypted filename here for attachments.
// Externally, this can generally be NULL, and is an optional
// parameter.
//
// return value:
// PEP_UNENCRYPTED message was unencrypted and not signed
@ -313,7 +318,8 @@ DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable);
DYNAMIC_API PEP_STATUS decrypt_and_verify(
PEP_SESSION session, const char *ctext, size_t csize,
const char *dsigtext, size_t dsigsize,
char **ptext, size_t *psize, stringlist_t **keylist
char **ptext, size_t *psize, stringlist_t **keylist,
char ** filename_ptr
);
@ -1338,6 +1344,9 @@ PEP_STATUS exists_person(PEP_SESSION session, pEp_identity* identity, bool* exis
PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr);
// exposed for testing
PEP_STATUS set_person(PEP_SESSION session, pEp_identity* identity,
bool guard_transaction);
PEP_STATUS bind_own_ident_with_contact_ident(PEP_SESSION session,
pEp_identity* own_ident,
pEp_identity* contact_ident);

@ -146,6 +146,7 @@ struct _pEpSession {
sqlite3_stmt *remove_fpr_as_default;
sqlite3_stmt *set_person;
sqlite3_stmt *update_person;
sqlite3_stmt *delete_person;
sqlite3_stmt *exists_person;
sqlite3_stmt *set_as_pEp_user;
sqlite3_stmt *is_pEp_user;
@ -169,6 +170,7 @@ struct _pEpSession {
sqlite3_stmt *update_trust_to_pEp;
sqlite3_stmt *update_trust_for_fpr;
sqlite3_stmt *get_trust;
sqlite3_stmt *get_trust_by_userid;
sqlite3_stmt *least_trust;
sqlite3_stmt *mark_compromised;
sqlite3_stmt *reset_trust;

@ -575,7 +575,8 @@ void pgp_release(PEP_SESSION session, bool out_last)
PEP_STATUS pgp_decrypt_and_verify(
PEP_SESSION session, const char *ctext, size_t csize,
const char *dsigtext, size_t dsigsize,
char **ptext, size_t *psize, stringlist_t **keylist
char **ptext, size_t *psize, stringlist_t **keylist,
char** filename_ptr
)
{
PEP_STATUS result;
@ -691,6 +692,15 @@ PEP_STATUS pgp_decrypt_and_verify(
*keylist = NULL;
result = PEP_OUT_OF_MEMORY;
}
// Get filename, if desired
if (filename_ptr) {
const char* fname = gpgme_decrypt_result->file_name;
if (fname) {
*filename_ptr = strdup(fname);
if (!(*filename_ptr))
result = PEP_OUT_OF_MEMORY;
}
}
} /* Ok, so now we have any recipients it was encrypted for
in recipient_keylist */
@ -809,7 +819,7 @@ PEP_STATUS pgp_decrypt_and_verify(
}
case GPG_ERR_CERT_REVOKED:
case GPG_ERR_BAD_SIGNATURE:
result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
//result = PEP_DECRYPT_BAD_SIGNATURE;
break;
case GPG_ERR_SIG_EXPIRED:

@ -41,7 +41,8 @@ void pgp_release(PEP_SESSION session, bool out_last);
// psize (out) size of cyphertext in bytes
// keylist (out) list of keys being used; first is the key being
// used for signing
//
// filename (out) PGP filename, when rendered (Optional, only necessary for some PGP implementations (e.g. Symantec),
// *** Mostly internal ***
// return value:
// PEP_DECRYPTED_AND_VERIFIED data could be decryped and verified
// PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH
@ -64,7 +65,8 @@ PEP_STATUS pgp_decrypt_and_verify(
size_t dsigsize,
char **ptext,
size_t *psize,
stringlist_t **keylist
stringlist_t **keylist,
char** filename_ptr
);
@ -115,7 +117,7 @@ PEP_STATUS pgp_encrypt_and_sign(
// PEP_GET_KEY_FAILED access to keyring failed
// PEP_ILLEGAL_VALUE parameters wrong
// PEP_OUT_OF_MEMORY out of memory error
// PEP_UNKOWN_ERROR internal error
// PEP_UNKNOWN_ERROR internal error
PEP_STATUS pgp_encrypt_only(
PEP_SESSION session,

@ -373,7 +373,8 @@ static PEP_STATUS _validation_results(
PEP_STATUS pgp_decrypt_and_verify(
PEP_SESSION session, const char *ctext, size_t csize,
const char *dsigtext, size_t dsigsize,
char **ptext, size_t *psize, stringlist_t **keylist
char **ptext, size_t *psize, stringlist_t **keylist,
char** filename_ptr // will be ignored
)
{
char *_ptext = NULL;

@ -10,7 +10,8 @@ void pgp_release(PEP_SESSION session, bool out_last);
PEP_STATUS pgp_decrypt_and_verify(
PEP_SESSION session, const char *ctext, size_t csize,
const char *dsigtext, size_t dsigsize,
char **ptext, size_t *psize, stringlist_t **keylist
char **ptext, size_t *psize, stringlist_t **keylist,
char** filename_ptr // will be ignored
);
PEP_STATUS pgp_encrypt_and_sign(

@ -113,6 +113,17 @@ DYNAMIC_API stringlist_t *stringlist_add(
return list_curr->next;
}
stringlist_t* stringlist_search(stringlist_t* head, const char* value) {
if (!head || !value || !head->value)
return NULL;
stringlist_t* retval = head;
for (; retval ; retval = retval->next) {
if (strcmp(retval->value, value) == 0)
break;
}
return retval;
}
DYNAMIC_API stringlist_t *stringlist_add_unique(
stringlist_t *stringlist,
const char *value

@ -133,6 +133,7 @@ DYNAMIC_API stringlist_t *stringlist_delete(
DYNAMIC_API void free_stringlist(stringlist_t *stringlist);
stringlist_t* stringlist_search(stringlist_t* head, const char* value);
#ifdef __cplusplus
}

@ -18,14 +18,14 @@ OBJS := $(addsuffix .o,$(basename $(SRCS)))
DEPS := $(OBJS:.o=.d)
INC_DIRS := ./include /usr/local/include
INC_FLAGS := $(addprefix -I,$(INC_DIRS)) $(GPGME_INC)
INC_FLAGS := $(addprefix -I,$(INC_DIRS)) $(GPGME_INC) $(CPPUNIT_INC)
LDFLAGS += -L/usr/local/lib
CFLAGS += -Wno-deprecated
CXXFLAGS += -Wno-deprecated
LDFLAGS+= $(ETPAN_LIB) -L../asn.1 -L../src
LDFLAGS+= $(ETPAN_LIB) $(CPPUNIT_LIB) -L../asn.1 -L../src
LDLIBS+= -letpan -lpEpEngine -lstdc++ -lasn1
ifeq ($(BUILD_FOR),Linux)

@ -1,5 +1,5 @@
import argparse
import gnupg
from pretty_bad_protocol import gnupg
import os
import subprocess
@ -19,10 +19,11 @@ priv_path = os.path.join(args.output_root, "priv")
homedir = os.path.join(os.path.expanduser('~'),"gnupg")
print("GNUPGHOME=" + homedir + "\n")
try:
gpg = gnupg.GPG(gnupghome=homedir)
gpg = gnupg.GPG(binary='/usr/bin/gpg', gnupghome=homedir)
except TypeError:
gpg = gnupg.GPG(homedir=homedir)
gpg = gnupg.GPG(binary='/usr/bin/gpg', homedir=homedir)
name = args.real_name_prefix
email = args.email_address_prefix
@ -61,7 +62,7 @@ for i in range(num_keys):
email = e_split[0] + "_" + i_str + "@" + e_split[1]
print("Generating key data for " + name + " " + email + "\n")
input_data = gpg.gen_key_input(key_type="RSA", key_length=2048, subkey_type="RSA", subkey_length=2048, expire_date=0, name_real=name, name_email=email, password="")
input_data = gpg.gen_key_input(key_type="RSA", key_length=2048, expire_date=0, name_real=name, name_email=email)
if not input_data:
raise Exception('Input data not created in iteration ' + str(i))

@ -0,0 +1,20 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#ifndef ENGINE463_H
#define ENGINE463_H
#include <string>
#include "EngineTestIndividualSuite.h"
using namespace std;
class Engine463Tests : public EngineTestIndividualSuite {
public:
Engine463Tests(string test_suite, string test_home_dir);
private:
void check_engine_463_no_own_key();
void check_engine_463_own_key();
};
#endif

@ -0,0 +1,112 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#ifndef USER_ID_COLLISION_H
#define USER_ID_COLLISION_H
#include <string>
#include "EngineTestIndividualSuite.h"
using namespace std;
class UserIdCollisionTests : public EngineTestIndividualSuite {
public:
UserIdCollisionTests(string test_suite, string test_home_dir);
protected:
void setup();
void tear_down();
// own user
pEp_identity* user_alice;
// real ID, only minimal info w/ username
pEp_identity* real_alex;
// tofu ID, only minimal info w/ username
pEp_identity* tofu_alex;
// real ID, only minimal info w/o username
pEp_identity* real_alex_0;
// tofu ID, only minimal info w/o username
pEp_identity* tofu_alex_0;
// real ID, only minimal info w/o username
pEp_identity* real_alex_1;
// tofu ID, only minimal info w/o username
pEp_identity* tofu_alex_1;
// real ID, various kinds of info
pEp_identity* real_alex_2;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_2;
// real ID, various kinds of info
pEp_identity* real_alex_3;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_3;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_4;
// real ID, various kinds of info
pEp_identity* real_alex_4;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_5;
// real ID, various kinds of info
pEp_identity* real_alex_5;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_6a;
// real ID, various kinds of info
pEp_identity* real_alex_6a;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_6b;
// real ID, various kinds of info
pEp_identity* real_alex_6b;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_6c;
// real ID, various kinds of info
pEp_identity* real_alex_6c;
// tofu ID, various kinds of info
pEp_identity* tofu_alex_6d;
// real ID, various kinds of info
pEp_identity* real_alex_6d;
const char* const alice_keyfile = "test_keys/pub/pep-test-alice-0x6FF00E97_pub.asc";
const char* const alice_keyid = "4ABE3AAF59AC32CFE4F86500A9411D176FF00E97";
const char* const alice_email = "pep.test.alice@pep-project.org";
const char* const alex_keyfile = "test_keys/pub/pep.test.alexander-0x26B54E4E_pub.asc";
const char* const alex_keyid = "3AD9F60FAEB22675DB873A1362D6981326B54E4E";
const char* const alex_email = "pep.test.alexander@peptest.ch";
const char* const alex0_keyfile = "test_keys/pub/pep.test.alexander0-0x3B7302DB_pub.asc";
const char* const alex0_keyid = "F4598A17D4690EB3B5B0F6A344F04E963B7302DB";
const char* const alex0_email = "pep.test.alexander0@darthmama.org";
const char* const alex1_keyfile = "test_keys/pub/pep.test.alexander1-0x541260F6_pub.asc";
const char* const alex1_keyid = "59AF4C51492283522F6904531C09730A541260F6";
const char* const alex1_email = "pep.test.alexander1@darthmama.org";
const char* const alex2_keyfile = "test_keys/pub/pep.test.alexander2-0xA6512F30_pub.asc";
const char* const alex2_keyid = "46A994F19077C05610870273C4B8AB0BA6512F30";
const char* const alex2_email = "pep.test.alexander2@darthmama.org";
const char* const alex3_keyfile = "test_keys/pub/pep.test.alexander3-0x724B3975_pub.asc";
const char* const alex3_keyid = "5F7076BBD92E14EA49F0DF7C2CE49419724B3975";
const char* const alex3_email = "pep.test.alexander3@darthmama.org";
const char* const alex4_keyfile = "test_keys/pub/pep.test.alexander4-0x844B9DCF_pub.asc";
const char* const alex4_keyid = "E95FFF95B8E2FDD4A12C3374395F1485844B9DCF";
const char* const alex4_email = "pep.test.alexander4@darthmama.org";
const char* const alex5_keyfile = "test_keys/pub/pep.test.alexander5-0x0773CD29_pub.asc";
const char* const alex5_keyid = "58BCC2BF2AE1E3C4FBEAB89AD7838ACA0773CD29";
const char* const alex5_email = "pep.test.alexander5@darthmama.org";
const char* const alex6a_keyfile = "test_keys/pub/pep.test.alexander6-0xBDA17020_pub.asc";
const char* const alex6a_keyid = "B4CE2F6947B6947C500F0687AEFDE530BDA17020";
const char* const alex6_email = "pep.test.alexander6@darthmama.org";
const char* const alex6b_keyfile = "test_keys/pub/pep.test.alexander6-0x503B14D8_pub.asc";
const char* const alex6b_keyid = "2E21325D202A44BFD9C607FCF095B202503B14D8";
const char* const alex6c_keyfile = "test_keys/pub/pep.test.alexander6-0xA216E95A_pub.asc";
const char* const alex6c_keyid = "3C1E713D8519D7F907E3142D179EAA24A216E95A";
const char* const alex6d_keyfile = "test_keys/pub/pep.test.alexander6-0x0019697D_pub.asc";
const char* const alex6d_keyid = "74D79B4496E289BD8A71B70BA8E2C4530019697D";
private:
void simple_tofu_collision();
void simple_tofu_collision_different_usernames();
void tofu_collision_two_tofus();
void tofu_collision_two_tofus_diff_usernames();
void real_followed_by_explicit_tofu();
void merge_records_normal();
void merge_records_set();
void merge_records_set_2();
};
#endif

@ -47,6 +47,8 @@ const char* tl_status_string(PEP_STATUS status);
// Grabs a new uuid for your randomish string needs.
char* get_new_uuid();
bool slurp_and_import_key(PEP_SESSION session, const char* key_filename);
bool slurp_message_and_import_key(PEP_SESSION session, const char* message_fname, std::string& message, const char* key_filename);
int util_delete_filepath(const char *filepath,

@ -12,167 +12,175 @@
#include "SuiteMaker.h"
// Begin where we generate stuff
#include "MimeTests.h"
#include "BloblistTests.h"
#include "NewUpdateIdAndMyselfTests.h"
#include "I18nTests.h"
#include "DecorateTests.h"
#include "UserIdCollisionTests.h"
#include "ReencryptPlusExtraKeysTests.h"
#include "BlacklistTests.h"
#include "AppleMailTests.h"
#include "MessageTwoPointOhTests.h"
#include "IdentityListTests.h"
#include "PgpBinaryTests.h"
#include "MessageNullFromTests.h"
#include "LeastCommonDenomColorTests.h"
#include "StringlistTests.h"
#include "PgpListKeysTests.h"
#include "MessageApiTests.h"
#include "EncryptMissingPrivateKeyTests.h"
#include "CaseAndDotAddressTests.h"
#include "UserIDAliasTests.h"
#include "I18nTests.h"
#include "Engine463Tests.h"
#include "DecryptAttachPrivateKeyUntrustedTests.h"
#include "BCCTests.h"
#include "LeastColorGroupTests.h"
#include "BlacklistAcceptNewKeyTests.h"
#include "DecryptAttachPrivateKeyUntrustedTests.h"
#include "BlacklistTests.h"
#include "MessageApiTests.h"
#include "StringlistTests.h"
#include "StringpairListTests.h"
#include "TrustManipulationTests.h"
#include "SyncTests.h"
#include "EncryptAttachPrivateKeyTests.h"
#include "BloblistTests.h"
#include "KeyResetMessageTests.h"
#include "SequenceTests.h"
#include "TrustwordsTests.h"
#include "RevokeRegenAttachTests.h"
#include "EncryptMissingPrivateKeyTests.h"
#include "PepSubjectReceivedTests.h"