diff --git a/src/message.h b/src/message.h index f733dba2..53ec6dad 100644 --- a/src/message.h +++ b/src/message.h @@ -28,17 +28,6 @@ typedef enum _PEP_msg_direction { PEP_dir_outgoing } PEP_msg_direction; -typedef enum _PEP_enc_format { - PEP_enc_none = 0, // message is not encrypted - PEP_enc_pieces = 1, // inline PGP + PGP extensions, was removed - PEP_enc_inline = 1, // still there - PEP_enc_S_MIME, // RFC5751 - PEP_enc_PGP_MIME, // RFC3156 - PEP_enc_PEP, // pEp encryption format - PEP_enc_PGP_MIME_Outlook1, // Message B0rken by Outlook type 1 - PEP_enc_inline_EA -} PEP_enc_format; - struct _message_ref_list; typedef struct _message { diff --git a/src/message_api.c b/src/message_api.c index 35789ebc..012f1c5f 100644 --- a/src/message_api.c +++ b/src/message_api.c @@ -3,6 +3,7 @@ #include "pEp_internal.h" #include "message_api.h" +#include "pEpEngine.h" #include "platform.h" #include "mime.h" @@ -1743,6 +1744,28 @@ static void _cleanup_src(message* src, bool remove_attached_key) { } } +static PEP_STATUS id_list_set_enc_format(PEP_SESSION session, identity_list* id_list, PEP_enc_format enc_format) { + PEP_STATUS status = PEP_STATUS_OK; + identity_list* id_list_curr = id_list; + for ( ; id_list_curr && id_list_curr->ident && status == PEP_STATUS_OK; id_list_curr = id_list_curr->next) { + status = set_ident_enc_format(session, id_list_curr->ident, enc_format); + } + return status; +} + +// N.B. +// depends on update_identity and friends having already been called on list +static void update_encryption_format(identity_list* id_list, PEP_enc_format* enc_format) { + identity_list* id_list_curr; + for (id_list_curr = id_list; id_list_curr && id_list_curr->ident; id_list_curr = id_list_curr->next) { + PEP_enc_format format = id_list_curr->ident->enc_format; + if (format != PEP_enc_none) { + *enc_format = format; + break; + } + } +} + DYNAMIC_API PEP_STATUS encrypt_message( PEP_SESSION session, message *src, @@ -2003,6 +2026,21 @@ DYNAMIC_API PEP_STATUS encrypt_message( if (max_version_major == 1) force_v_1 = true; + + if (enc_format == PEP_enc_none) { + update_encryption_format(src->to, &enc_format); + if (enc_format == PEP_enc_none && src->cc) + update_encryption_format(src->cc, &enc_format); + if (enc_format == PEP_enc_none && src->bcc) + update_encryption_format(src->bcc, &enc_format); + } + else { + status = id_list_set_enc_format(session, src->to, enc_format); + status = ((status != PEP_STATUS_OK || !(src->cc)) ? status : id_list_set_enc_format(session, src->cc, enc_format)); + status = ((status != PEP_STATUS_OK || !(src->bcc)) ? status : id_list_set_enc_format(session, src->bcc, enc_format)); + if (status != PEP_STATUS_OK) + goto pEp_error; + } if (enc_format == PEP_enc_none || !dest_keys_found || stringlist_length(keys) == 0 || @@ -5372,4 +5410,3 @@ PEP_STATUS try_encrypt_message( return status; } - diff --git a/src/pEpEngine.c b/src/pEpEngine.c index 4c6ccf45..cd496e52 100644 --- a/src/pEpEngine.c +++ b/src/pEpEngine.c @@ -312,6 +312,16 @@ static const char *sql_unset_identity_flags = " end) = 1" " and user_id = ?3 ;"; +static const char *sql_set_ident_enc_format = + "update identity " + " set enc_format = ?1 " + " where (case when (address = ?2) then (1)" + " when (lower(address) = lower(?2)) then (1)" + " when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1) " + " else 0 " + " end) = 1 " + " and user_id = ?3 ;"; + static const char *sql_set_pEp_version = "update identity " " set pEp_version_major = ?1, " @@ -1058,7 +1068,7 @@ DYNAMIC_API PEP_STATUS init( sqlite3_busy_timeout(_session->system_db, 1000); // increment this when patching DDL -#define _DDL_USER_VERSION "13" +#define _DDL_USER_VERSION "14" if (in_first) { @@ -1120,7 +1130,8 @@ DYNAMIC_API PEP_STATUS init( " flags integer default 0,\n" " is_own integer default 0,\n" " pEp_version_major integer default 0,\n" - " pEp_version_minor integer default 0,\n" + " pEp_version_minor integer default 0,\n" + " enc_format integer default 0,\n" " timestamp integer default (datetime('now')),\n" " primary key (address, user_id)\n" ");\n" @@ -1232,7 +1243,10 @@ DYNAMIC_API PEP_STATUS init( // Sometimes the user_version wasn't set correctly. if (version == 1) { bool version_changed = true; - if (table_contains_column(_session, "revocation_contact_list", "own_address")) { + if (table_contains_column(_session, "identity", "enc_format")) { + version = 14; + } + else if (table_contains_column(_session, "revocation_contact_list", "own_address")) { version = 13; } else if (table_contains_column(_session, "identity", "pEp_version_major")) { @@ -1692,7 +1706,19 @@ DYNAMIC_API PEP_STATUS init( assert(status == PEP_STATUS_OK); if (status != PEP_STATUS_OK) return status; - } + } + if (version < 14) { + int_result = sqlite3_exec( + _session->db, + "alter table identity\n" + " add column enc_format integer default 0;\n", + NULL, + NULL, + NULL + ); + assert(int_result == SQLITE_OK); + } + } else { // Version from DB was 0, it means this is initial setup. @@ -1906,6 +1932,11 @@ DYNAMIC_API PEP_STATUS init( NULL); assert(int_result == SQLITE_OK); + int_result = sqlite3_prepare_v2(_session->db, sql_set_ident_enc_format, + (int)strlen(sql_set_ident_enc_format), &_session->set_ident_enc_format, + NULL); + assert(int_result == SQLITE_OK); + int_result = sqlite3_prepare_v2(_session->db, sql_set_pEp_version, (int)strlen(sql_set_pEp_version), &_session->set_pEp_version, NULL); @@ -2180,6 +2211,8 @@ DYNAMIC_API void release(PEP_SESSION session) sqlite3_finalize(session->set_identity_flags); if (session->unset_identity_flags) sqlite3_finalize(session->unset_identity_flags); + if (session->set_ident_enc_format) + sqlite3_finalize(session->set_ident_enc_format); if (session->set_pEp_version) sqlite3_finalize(session->set_pEp_version); if (session->exists_trust_entry) @@ -3978,6 +4011,38 @@ DYNAMIC_API PEP_STATUS unset_identity_flags( return PEP_STATUS_OK; } +PEP_STATUS set_ident_enc_format( + PEP_SESSION session, + pEp_identity *identity, + PEP_enc_format format + ) +{ + int result; + + assert(session); + assert(identity); + assert(identity->address); + assert(identity->user_id); + + if (!(session && identity && identity->address && identity->user_id)) + return PEP_ILLEGAL_VALUE; + + sqlite3_reset(session->set_ident_enc_format); + sqlite3_bind_int(session->set_ident_enc_format, 1, format); + sqlite3_bind_text(session->set_ident_enc_format, 2, identity->address, -1, + SQLITE_STATIC); + sqlite3_bind_text(session->set_ident_enc_format, 3, identity->user_id, -1, + SQLITE_STATIC); + + result = sqlite3_step(session->set_ident_enc_format); + + sqlite3_reset(session->set_ident_enc_format); + if (result != SQLITE_DONE) + return PEP_CANNOT_SET_IDENTITY; + + return PEP_STATUS_OK; +} + PEP_STATUS get_trust_by_userid(PEP_SESSION session, const char* user_id, labeled_int_list_t** trust_list) { diff --git a/src/pEpEngine.h b/src/pEpEngine.h index c6b80936..2b100be8 100644 --- a/src/pEpEngine.h +++ b/src/pEpEngine.h @@ -153,6 +153,17 @@ typedef enum { PEP_VERSION_MISMATCH = -7, } PEP_STATUS; +typedef enum _PEP_enc_format { + PEP_enc_none = 0, // message is not encrypted + PEP_enc_pieces = 1, // inline PGP + PGP extensions, was removed + PEP_enc_inline = 1, // still there + PEP_enc_S_MIME, // RFC5751 + PEP_enc_PGP_MIME, // RFC3156 + PEP_enc_PEP, // pEp encryption format + PEP_enc_PGP_MIME_Outlook1, // Message B0rken by Outlook type 1 + PEP_enc_inline_EA +} PEP_enc_format; + // messageToSend() - a message needs to be delivered by application // @@ -624,8 +635,9 @@ typedef struct _pEp_identity { char lang[3]; // language of conversation // ISO 639-1 ALPHA-2, last byte is 0 bool me; // if this is the local user herself/himself - unsigned int major_ver; // highest version of pEp message received, if any - unsigned int minor_ver; // highest version of pEp message received, if any + unsigned int major_ver; // highest version of pEp message received, if any + unsigned int minor_ver; // highest version of pEp message received, if any + PEP_enc_format enc_format; // Last specified format we encrypted to for this identity identity_flags_t flags; // identity_flag1 | identity_flag2 | ... } pEp_identity; @@ -1521,7 +1533,11 @@ PEP_STATUS exists_person(PEP_SESSION session, pEp_identity* identity, bool* exis PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr); PEP_STATUS set_pEp_version(PEP_SESSION session, pEp_identity* ident, unsigned int new_ver_major, unsigned int new_ver_minor); - + +PEP_STATUS set_ident_enc_format(PEP_SESSION session, + pEp_identity *identity, + PEP_enc_format format); + PEP_STATUS clear_trust_info(PEP_SESSION session, const char* user_id, const char* fpr); @@ -1571,6 +1587,7 @@ PEP_STATUS set_all_userids_to_own(PEP_SESSION session, PEP_STATUS has_partner_contacted_address(PEP_SESSION session, const char* partner_id, const char* own_address, bool* was_contacted); + #ifdef __cplusplus } #endif diff --git a/src/pEp_internal.h b/src/pEp_internal.h index 69fe197f..a0ef5648 100644 --- a/src/pEp_internal.h +++ b/src/pEp_internal.h @@ -188,6 +188,7 @@ struct _pEpSession { sqlite3_stmt *exists_identity_entry; sqlite3_stmt *set_identity_flags; sqlite3_stmt *unset_identity_flags; + sqlite3_stmt *set_ident_enc_format; sqlite3_stmt *set_pEp_version; sqlite3_stmt *clear_trust_info; sqlite3_stmt *set_trust;