From 08ace7a490093dc890da97fda57708e132a56b92 Mon Sep 17 00:00:00 2001 From: Krista Bennett Date: Fri, 15 Jun 2018 20:17:49 +0200 Subject: [PATCH] shelving to debug other things --- src/message_api.c | 84 +++++++++++++++++++-- src/message_api.h | 9 ++- src/pEpEngine.c | 184 +++++++++++++++++++++++++++++++++++++++++---- src/pEp_internal.h | 5 ++ 4 files changed, 260 insertions(+), 22 deletions(-) diff --git a/src/message_api.c b/src/message_api.c index 2d6badd4..a244bcd5 100644 --- a/src/message_api.c +++ b/src/message_api.c @@ -857,7 +857,7 @@ enomem: } static message* wrap_message_as_attachment(message* envelope, - message* attachment, bool keep_orig_subject) { + message* attachment, message_wrap_type wrap_type, bool keep_orig_subject) { if (!attachment) return NULL; @@ -868,14 +868,22 @@ static message* wrap_message_as_attachment(message* envelope, replace_opt_field(attachment, "X-pEp-Version", PEP_VERSION); - if (!_envelope) { + if (!_envelope && (wrap_type != PEP_message_transport)) { _envelope = extract_minimal_envelope(attachment, PEP_dir_outgoing); status = generate_message_id(_envelope); if (status != PEP_STATUS_OK) goto enomem; - attachment->longmsg = encapsulate_message_wrap_info("INNER", attachment->longmsg); + const char* inner_type_string = ""; + switch (wrap_type) { + case PEP_message_key_reset: + inner_type_string = "KEY_RESET"; + break; + default: + inner_type_string = "INNER"; + } + attachment->longmsg = encapsulate_message_wrap_info(inner_type_string, attachment->longmsg); _envelope->longmsg = encapsulate_message_wrap_info("OUTER", _envelope->longmsg); } else { @@ -1457,6 +1465,48 @@ void attach_own_key(PEP_SESSION session, message *msg) free(revoked_fpr); } +PEP_STATUS create_standalone_key_reset_message(message** dst, + pEp_identity* recip, + const char* revoke_fpr, + const char* new_fpr) { + + if (!dst || !recip->user_id || !recip->address) + return PEP_ILLEGAL_VALUE; + + *dst = NULL; + // Get own identity user has corresponded with + pEp_identity* own_identity = NULL; + PEP_STATUS status = get_own_address_for_contact_id(PEP_SESSION session, + recip, + &own_identity); + if (status != PEP_STATUS_OK) + return status; + + message* reset_message = new_message(PEP_dir_outgoing); + reset_message->from = own_identity; + reset_message->to = new_identity_list(identity_dup(recip)); // ? + + status = _attach_key(session, revoke_fpr, reset_message); + if (status != PEP_STATUS_OK) + goto pep_free; + status = _attach_key(session, new_fpr, reset_message); + if (status != PEP_STATUS_OK) + goto pep_free; + + message* output_msg = NULL; + + status = encrypt_message(session, reset_message, NULL, + output_msg, PEP_enc_PGP_MIME, + PEP_encrypt_flag_key_reset_only); + + if (status == PEP_STATUS_OK) + *dst = output_msg; + +pep_free: + free_message(reset_message); + return status; +} + PEP_cryptotech determine_encryption_format(message *msg) { assert(msg); @@ -1580,7 +1630,6 @@ DYNAMIC_API PEP_STATUS encrypt_message( identity_list * _il; - if (enc_format != PEP_enc_none && (_il = src->bcc) && _il->ident) { // BCC limited support: @@ -1764,7 +1813,8 @@ DYNAMIC_API PEP_STATUS encrypt_message( else { // FIXME - we need to deal with transport types (via flag) if ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp) { - _src = wrap_message_as_attachment(NULL, src, false); + message_wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default); + _src = wrap_message_as_attachment(NULL, src, message_wrap_type, false); if (!_src) goto pep_error; } @@ -2061,8 +2111,8 @@ DYNAMIC_API PEP_STATUS encrypt_message_for_self( determine_encryption_format(src); if (src->enc_format != PEP_enc_none) return PEP_ILLEGAL_VALUE; - if (target_id && (!target_id->user_id || target_id->user_id[0] == '\0')) { + char* own_id = NULL; status = get_default_own_userid(session, &own_id); if (own_id) { @@ -2105,7 +2155,7 @@ DYNAMIC_API PEP_STATUS encrypt_message_for_self( // if (!(flags & PEP_encrypt_flag_force_no_attached_key)) // _attach_key(session, target_fpr, src); - _src = wrap_message_as_attachment(NULL, src, false); + _src = wrap_message_as_attachment(NULL, src, PEP_message_default, false); if (!_src) goto pep_error; @@ -2977,6 +3027,22 @@ static char* seek_good_trusted_private_fpr(PEP_SESSION session, char* own_id, return NULL; } +PEP_STATUS check_for_own_revoked_key( + PEP_SESSION session, + stringlist_t* keylist, + char** bad_fpr, + char** replacement_fpr + ) +{ + if (!session || !bad_fpr || !replacement_fpr) + return PEP_ILLEGAL_VALUE; + stringlist_t* _k = keylist; + while (_k) { + + } +} + + DYNAMIC_API PEP_STATUS _decrypt_message( PEP_SESSION session, message *src, @@ -3367,6 +3433,10 @@ DYNAMIC_API PEP_STATUS _decrypt_message( } } // End prepare output message for return + // 3. Check to see if the sender used a bad key + char* bad_fpr = NULL; + status = check_for_own_revoked_key(session, _keylist, &bad_fpr); + *dst = msg; *keylist = _keylist; diff --git a/src/message_api.h b/src/message_api.h index 30c3a943..d6c1d80a 100644 --- a/src/message_api.h +++ b/src/message_api.h @@ -37,12 +37,19 @@ typedef enum _PEP_encrypt_flags { // This is used for outer messages (used to wrap the real message) // This is only used internally and (eventually) by transport functions - PEP_encrypt_flag_inner_message = 0x8 + PEP_encrypt_flag_inner_message = 0x8, + + PEP_encrypt_flag_key_reset_only = 0x16, } PEP_encrypt_flags; typedef unsigned int PEP_encrypt_flags_t; +typedef enum _message_wrap_type { + PEP_message_default, // typical inner/outer message 2.0 + PEP_message_transport, // e.g. for onion layers + PEP_message_key_reset // for wrapped key reset information +} message_wrap_type; // encrypt_message() - encrypt message in memory // diff --git a/src/pEpEngine.c b/src/pEpEngine.c index 319693fa..ba2bc88a 100644 --- a/src/pEpEngine.c +++ b/src/pEpEngine.c @@ -408,6 +408,10 @@ static const char *sql_get_revoked = "select revoked_fpr, revocation_date from revoked_keys" " where replacement_fpr = upper(replace(?1,' ','')) ;"; +static const char *sql_get_replacement_fpr = + "select replacement_fpr, revocation_date from revoked_keys" + " where revoked_fpr = upper(replace(?1,' ','')) ;"; + static const char *sql_get_userid_alias_default = "select default_id from alternate_user_id " " where alternate_id = ?1 ; "; @@ -428,8 +432,20 @@ static const char *sql_add_userid_alias = "values (?2, ?1) ;"; static const char *sql_add_into_social_graph = - "insert or replace into social_graph(own_userid, own_address, contact_userid text) " + "insert or replace into social_graph(own_userid, own_address, contact_userid) " "values (?1, ?2, ?3) ;"; + +static const char *sql_get_own_address_binding_from_contact = + "select own_address from social_graph where own_userid = ?1 and contact_userid = ?2 ;"; + +static const char *sql_set_revoke_contact_as_notified = + "insert or replace into revocation_contact_list(fpr, contact_id) values (?1, ?2) ;"; + +static const char *sql_get_contacted_ids_from_revoke_fpr = + "select * from revocation_contact_list where fpr = ?1 ;"; + +static const char *sql_was_id_for_revoke_contacted = + "select count(*) from revocation_contact_list where fpr = ?1 and contact_id = ?2 ;"; static int user_version(void *_version, int count, char **text, char **name) { @@ -726,13 +742,20 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) "create table if not exists social_graph (\n" " own_userid text,\n" " own_address text,\n" - " contact_userid text\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " CONSTRAINT fk_identity\n" + " contact_userid text,\n" + " CONSTRAINT fk_own_identity\n" " FOREIGN KEY(own_address, own_userid)\n" " REFERENCES identity(address, user_id)\n" - " ON DELETE CASCADE ON UPDATE CASCADE\n" + " ON DELETE CASCADE ON UPDATE CASCADE,\n" + ");\n" + // list of user_ids sent revocation + "create table if not exists revocation_contact_list (\n" + " fpr text not null references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " contact_id text not null references person (id)\n" + " on delete cascade on update cascade,\n" + " timestamp integer default (datetime('now')),\n" + " PRIMARY KEY(fpr, contact_id)\n" ");\n" , NULL, @@ -1045,13 +1068,19 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) "create table if not exists social_graph (\n" " own_userid text,\n" " own_address text,\n" - " contact_userid text\n" - " references person (id)\n" - " on delete cascade on update cascade,\n" - " CONSTRAINT fk_identity\n" + " contact_userid text,\n" + " CONSTRAINT fk_own_identity\n" " FOREIGN KEY(own_address, own_userid)\n" " REFERENCES identity(address, user_id)\n" - " ON DELETE CASCADE ON UPDATE CASCADE\n" + " ON DELETE CASCADE ON UPDATE CASCADE,\n" + ");\n" + "create table if not exists revocation_contact_list (\n" + " fpr text not null references pgp_keypair (fpr)\n" + " on delete cascade,\n" + " contact_id text not null references person (id)\n" + " on delete cascade on update cascade,\n" + " timestamp integer default (datetime('now')),\n" + " PRIMARY KEY(fpr, contact_id)\n" ");\n" , NULL, @@ -1173,6 +1202,30 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session) (int)strlen(sql_add_into_social_graph), &_session->add_into_social_graph, NULL); assert(int_result == SQLITE_OK); + int_result = sqlite3_prepare_v2(_session->db, + sql_get_own_address_binding_from_contact, + (int)strlen(sql_get_own_address_binding_from_contact), + &_session->get_own_address_binding_from_contact, NULL); + assert(int_result == SQLITE_OK); + + int_result = sqlite3_prepare_v2(_session->db, + sql_set_revoke_contact_as_notified, + (int)strlen(sql_set_revoke_contact_as_notified), + &_session->set_revoke_contact_as_notified, NULL); + assert(int_result == SQLITE_OK); + + int_result = sqlite3_prepare_v2(_session->db, + sql_get_contacted_ids_from_revoke_fpr, + (int)strlen(sql_get_contacted_ids_from_revoke_fpr), + &_session->get_contacted_ids_from_revoke_fpr, NULL); + assert(int_result == SQLITE_OK); + + int_result = sqlite3_prepare_v2(_session->db, + sql_get_own_address_binding_from_contact, + (int)strlen(sql_get_own_address_binding_from_contact), + &_session->get_own_address_binding_from_contact, 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); @@ -1323,6 +1376,10 @@ 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_get_replacement_fpr, + (int)strlen(sql_get_replacement_fpr), &_session->get_replacement_fpr, 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); @@ -1440,7 +1497,15 @@ DYNAMIC_API void release(PEP_SESSION session) if (session->exists_person) sqlite3_finalize(session->exists_person); if (session->add_into_social_graph) - sqlite3_finalize(session->add_into_social_graph); + sqlite3_finalize(session->add_into_social_graph); + if (session->get_own_address_binding_from_contact) + sqlite3_finalize(session->get_own_address_binding_from_contact); + if (session->set_revoke_contact_as_notified) + sqlite3_finalize(session->set_revoke_contact_as_notified); + if (session->get_contacted_ids_from_revoke_fpr) + sqlite3_finalize(session->get_contacted_ids_from_revoke_fpr); + if (session->was_id_for_revoke_contacted) + sqlite3_finalize(session->was_id_for_revoke_contacted); if (session->set_device_group) sqlite3_finalize(session->set_device_group); if (session->get_device_group) @@ -1513,7 +1578,8 @@ DYNAMIC_API void release(PEP_SESSION session) sqlite3_finalize(session->set_revoked); if (session->get_revoked) sqlite3_finalize(session->get_revoked); - + if (session->get_replacement_fpr) + sqlite3_finalize(session->get_replacement_fpr); if (session->add_mistrusted_key) sqlite3_finalize(session->add_mistrusted_key); if (session->delete_mistrusted_key) @@ -2177,9 +2243,9 @@ PEP_STATUS exists_identity_entry(PEP_SESSION session, pEp_identity* identity, sqlite3_bind_text(session->exists_identity_entry, 1, identity->address, -1, SQLITE_STATIC); sqlite3_bind_text(session->exists_identity_entry, 2, identity->user_id, -1, - SQLITE_STATIC); int result = sqlite3_step(session->exists_identity_entry); + SQLITE_STATIC); switch (result) { case SQLITE_ROW: { // yeah yeah, I know, we could be lazy here, but it looks bad. @@ -2661,6 +2727,45 @@ PEP_STATUS bind_own_ident_with_contact_ident(PEP_SESSION session, return PEP_STATUS_OK; } +PEP_STATUS get_own_ident_for_contact_id(PEP_SESSION session, + const pEp_identity* contact + pEp_identity** own_ident) { + if (!contact || !contact->user_id || !own_ident) + return PEP_ILLEGAL_VALUE; + + char* own_user_id = NULL; + *own_ident = NULL; + PEP_STATUS status = get_default_own_userid(session, &own_user_id); + + if (status != PEP_STATUS_OK) + return status; + + sqlite3_reset(session->get_own_address_binding_from_contact); + sqlite3_bind_text(session->get_own_address_binding_from_contact, 1, own_user_id, -1, + SQLITE_STATIC); + sqlite3_bind_text(session->get_own_address_binding_from_contact, 2, contact_ident->user_id, -1, + SQLITE_STATIC); + + result = sqlite3_step(session->get_own_address_binding_from_contact); + switch (result) { + case SQLITE_ROW: + const char* const own_address = (const char *) + sqlite3_column_text(session->get_own_address_binding_from_contact, 0); + if (own_address) { + status = get_identity(session, own_address, own_user_id, own_ident); + if (status == PEP_STATUS_OK) { + if (!own_ident) + status = PEP_CANNOT_FIND_IDENTITY; + } + } + break; + default: + status = PEP_CANNOT_FIND_IDENTITY; + } + + free(own_user_id); + return status; +} PEP_STATUS remove_fpr_as_default(PEP_SESSION session, const char* fpr) @@ -3915,6 +4020,57 @@ DYNAMIC_API PEP_STATUS get_revoked( return status; } +DYNAMIC_API PEP_STATUS get_replacement_fpr( + PEP_SESSION session, + const char *fpr, + char **revoked_fpr, + uint64_t *revocation_date + ) +{ + PEP_STATUS status = PEP_STATUS_OK; + + assert(session && + revoked_fpr && + fpr && fpr[0] + ); + + if (!(session && + revoked_fpr && + fpr && fpr[0] + )) + return PEP_ILLEGAL_VALUE; + + *revoked_fpr = NULL; + *revocation_date = 0; + + sqlite3_reset(session->get_replacement_fpr); + sqlite3_bind_text(session->get_replacement_fpr, 1, fpr, -1, SQLITE_STATIC); + + int result; + + result = sqlite3_step(session->get_replacement_fpr); + switch (result) { + case SQLITE_ROW: { + *revoked_fpr = strdup((const char *) + sqlite3_column_text(session->get_replacement_fpr, 0)); + if(*revoked_fpr) + *revocation_date = sqlite3_column_int64(session->get_replacement_fpr, + 1); + else + status = PEP_OUT_OF_MEMORY; + + break; + } + default: + status = PEP_CANNOT_FIND_IDENTITY; + } + + sqlite3_reset(session->get_replacement_fpr); + + return status; +} + + PEP_STATUS key_created( PEP_SESSION session, const char *fpr, diff --git a/src/pEp_internal.h b/src/pEp_internal.h index 60ad0f5f..d08498a4 100644 --- a/src/pEp_internal.h +++ b/src/pEp_internal.h @@ -142,6 +142,10 @@ struct _pEpSession { sqlite3_stmt *set_as_pep_user; sqlite3_stmt *is_pep_user; sqlite3_stmt *add_into_social_graph; + sqlite3_stmt *get_own_address_binding_from_contact; + sqlite3_stmt *set_revoke_contact_as_notified; + sqlite3_stmt *get_contacted_ids_from_revoke_fpr; + sqlite3_stmt *was_id_for_revoke_contacted; sqlite3_stmt *set_device_group; sqlite3_stmt *get_device_group; sqlite3_stmt *set_pgp_keypair; @@ -188,6 +192,7 @@ struct _pEpSession { // revoked keys sqlite3_stmt *set_revoked; sqlite3_stmt *get_revoked; + sqlite3_stmt *get_replacement_fpr; // mistrusted sqlite3_stmt* add_mistrusted_key;