diff --git a/src/key_reset.c b/src/key_reset.c new file mode 100644 index 00000000..6ce9181e --- /dev/null +++ b/src/key_reset.c @@ -0,0 +1,478 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "pEp_internal.h" +#include "dynamic_api.h" +#include "message_api.h" + +#include +#include + +PEP_STATUS has_key_reset_been_sent( + PEP_SESSION session, + const char* user_id, + const char* revoked_fpr, + bool* contacted) +{ + assert(session); + assert(contacted); + assert(user_id); + assert(revoked_fpr); + assert(!EMPTYSTR(user_id)); + + if (!session || !contacted || EMPTYSTR(revoked_fpr) || EMPTYSTR(user_id)) + return PEP_ILLEGAL_VALUE; + + *contacted = 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 = strdup(user_id); + } + + sqlite3_reset(session->was_id_for_revoke_contacted); + sqlite3_bind_text(session->was_id_for_revoke_contacted, 1, revoked_fpr, -1, + SQLITE_STATIC); + sqlite3_bind_text(session->was_id_for_revoke_contacted, 2, user_id, -1, + SQLITE_STATIC); + int result = sqlite3_step(session->was_id_for_revoke_contacted); + switch (result) { + case SQLITE_ROW: { + *contacted = (sqlite3_column_int(session->was_id_for_revoke_contacted, 0) != 0); + break; + } + default: + sqlite3_reset(session->was_id_for_revoke_contacted); + free(alias_default); + return PEP_UNKNOWN_DB_ERROR; + } + + sqlite3_reset(session->was_id_for_revoke_contacted); + return PEP_STATUS_OK; +} + +//static const char *sql_set_revoke_contact_as_notified = +// "insert or replace into revocation_contact_list(fpr, contact_id) values (?1, ?2) ;"; + +PEP_STATUS set_reset_contact_notified( + PEP_SESSION session, + const char* revoke_fpr, + const char* contact_id + ) +{ + PEP_STATUS status = PEP_STATUS_OK; + + assert(session && !EMPTYSTR(revoke_fpr) && !EMPTYSTR(contact_id)); + + if (!session || EMPTYSTR(revoke_fpr) || EMPTYSTR(contact_id)) + return PEP_ILLEGAL_VALUE; + + sqlite3_reset(session->set_revoke_contact_as_notified); + sqlite3_bind_text(session->set_revoke_contact_as_notified, 1, revoke_fpr, -1, + SQLITE_STATIC); + sqlite3_bind_text(session->set_revoke_contact_as_notified, 2, contact_id, -1, + SQLITE_STATIC); + + int result; + + result = sqlite3_step(session->set_revoke_contact_as_notified); + switch (result) { + case SQLITE_DONE: + status = PEP_STATUS_OK; + break; + + default: + status = PEP_UNKNOWN_DB_ERROR; + } + + sqlite3_reset(session->set_revoke_contact_as_notified); + return status; +} + + +PEP_STATUS receive_key_reset(PEP_SESSION session, + message* reset_msg) { + + if (!session || !reset_msg) + return PEP_ILLEGAL_VALUE; + + pEp_identity* sender_id = reset_msg->from; + + if (!sender_id) + return PEP_MALFORMED_KEY_RESET_MSG; + + PEP_STATUS status = update_identity(session, sender_id); + if (!sender_id->user_id) + return PEP_UNKNOWN_ERROR; + + if (is_me(session, sender_id)) + return PEP_ILLEGAL_VALUE; + + if (!reset_msg->longmsg || strncmp(reset_msg->longmsg, "OLD: ", 5) != 0) + return PEP_MALFORMED_KEY_RESET_MSG; + + status = PEP_STATUS_OK; + char* old_fpr = NULL; + char* new_fpr = NULL; + + stringlist_t* keylist = NULL; + pEp_identity* temp_ident = identity_dup(sender_id); + if (!temp_ident) { + status = PEP_OUT_OF_MEMORY; + goto pep_free; + } + + char* rest = NULL; + char* p = strtok_r(reset_msg->longmsg, "\r\n", &rest); + if (!EMPTYSTR(p + 5)) + old_fpr = strdup(p + 5); + else { + status = PEP_MALFORMED_KEY_RESET_MSG; + goto pep_free; + } + + bool own_key = false; + status = is_own_key(session, old_fpr, &own_key); + + if (own_key) { + // Nope, no one can make us our own default. If we want to do that, + // that's keysync, NOT key reset. + status = PEP_ILLEGAL_VALUE; + goto pep_free; + } + + p = strtok_r(NULL, "\r\n", &rest); + if (strncmp(p, "NEW: ", 5) != 0 || EMPTYSTR(p + 5)) { + status = PEP_MALFORMED_KEY_RESET_MSG; + goto pep_free; + } + + new_fpr = strdup(p + 5); + + // Reset the original key + status = key_reset(session, old_fpr, temp_ident); + if (status != PEP_STATUS_OK) + goto pep_free; + + status = find_keys(session, new_fpr, &keylist); + if (status != PEP_STATUS_OK) + goto pep_free; + + if (!keylist) { + status = PEP_KEY_NOT_FOUND; + goto pep_free; + } + + // alright, we've checked as best we can. Let's set that baby. + sender_id->fpr = new_fpr; + + // This only sets as the default, does NOT TRUST IN ANY WAY + sender_id->comm_type = sender_id->comm_type & (~PEP_ct_confirmed); + status = set_identity(session, sender_id); + + sender_id->fpr = NULL; // ownership for free +pep_free: + free_stringlist(keylist); + free(old_fpr); + free(new_fpr); + free_identity(temp_ident); + return status; +} + +PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session, + message** dst, + pEp_identity* recip, + const char* old_fpr, + const char* new_fpr) { + + if (!dst || !recip->user_id || !recip->address) + return PEP_ILLEGAL_VALUE; + + if (!old_fpr || !new_fpr) + return PEP_ILLEGAL_VALUE; + + *dst = NULL; + // Get own identity user has corresponded with + pEp_identity* own_identity = NULL; + + PEP_STATUS status = get_own_ident_for_contact_id(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)); // ? + + const char* oldtag = "OLD: "; + const char* newtag = "\nNEW: "; + const size_t taglens = 11; + size_t full_len = taglens + strlen(old_fpr) + strlen(new_fpr) + 2; // \n and \0 + char* longmsg = calloc(full_len, 1); + strlcpy(longmsg, oldtag, full_len); + strlcat(longmsg, old_fpr, full_len); + strlcat(longmsg, newtag, full_len); + strlcat(longmsg, new_fpr, full_len); + strlcat(longmsg, "\n", full_len); + reset_message->longmsg = longmsg; + reset_message->shortmsg = strdup("Key reset"); + + 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; + + free_message(reset_message); + return status; +} + +PEP_STATUS send_key_reset_to_recents(PEP_SESSION session, + const char* old_fpr, + const char* new_fpr) { + assert(old_fpr); + assert(new_fpr); + assert(session); + assert(session->messageToSend || session->sync_session->messageToSend); + + if (!session || !old_fpr || !new_fpr) + return PEP_ILLEGAL_VALUE; + + messageToSend_t send_cb = send_cb = session->messageToSend; + void* sync_obj = session->sync_obj; + if (!send_cb) { + send_cb = session->sync_session->messageToSend; + sync_obj = session->sync_session->sync_obj; + } + if (!send_cb) + return PEP_SYNC_NO_MESSAGE_SEND_CALLBACK; + + identity_list* recent_contacts = NULL; + message* reset_msg = NULL; + + PEP_STATUS status = get_last_contacted(session, &recent_contacts); + + if (status != PEP_STATUS_OK) + goto pep_free; + + identity_list* curr_id_ptr = recent_contacts; + + for (curr_id_ptr = recent_contacts; curr_id_ptr; curr_id_ptr = curr_id_ptr->next) { + pEp_identity* curr_id = curr_id_ptr->ident; + + if (!curr_id) + break; + + const char* user_id = curr_id->user_id; + + // Should be impossible, but? + if (!user_id) + continue; + + // Check if it's us - if so, pointless... + if (is_me(session, curr_id)) + continue; + + // Check if they've already been told - this shouldn't be the case, but... + bool contacted = false; + status = has_key_reset_been_sent(session, user_id, old_fpr, &contacted); + if (status != PEP_STATUS_OK) + goto pep_free; + + if (contacted) + continue; + + // if not, make em a message + reset_msg = NULL; + + status = create_standalone_key_reset_message(session, + &reset_msg, + curr_id, + old_fpr, + new_fpr); + + if (status == PEP_CANNOT_FIND_IDENTITY) { // this is ok, just means we never mailed them + status = PEP_STATUS_OK; + continue; + } + + if (status != PEP_STATUS_OK) { + free(reset_msg); + goto pep_free; + } + + // insert into queue + status = send_cb(sync_obj, reset_msg); + + if (status != PEP_STATUS_OK) { + free(reset_msg); + goto pep_free; + } + + // Put into notified DB + status = set_reset_contact_notified(session, old_fpr, user_id); + if (status != PEP_STATUS_OK) + goto pep_free; + } + +pep_free: + free_identity_list(recent_contacts); + return status; +} + +DYNAMIC_API PEP_STATUS key_reset( + PEP_SESSION session, + const char* key_id, + pEp_identity* ident + ) +{ + if (!session) + return PEP_ILLEGAL_VALUE; + + PEP_STATUS status = PEP_STATUS_OK; + + char* fpr_copy = NULL; + char* own_id = NULL; + char* new_key = NULL; + identity_list* key_idents = NULL; + stringlist_t* keys = NULL; + + if (!EMPTYSTR(key_id)) { + fpr_copy = strdup(key_id); + if (!fpr_copy) + return PEP_OUT_OF_MEMORY; + } + + if (!ident) { + // Get list of own identities + status = get_default_own_userid(session, &own_id); + if (status != PEP_STATUS_OK) + goto pep_free; + + if (EMPTYSTR(fpr_copy)) { + status = get_all_keys_for_user(session, own_id, &keys); + if (status == PEP_STATUS_OK) { + stringlist_t* curr_key; + for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) { + status = key_reset(session, curr_key->value, NULL); + if (status != PEP_STATUS_OK) + break; + } + } + goto pep_free; + } // otherwise, we have a specific fpr to process + + // fpr_copy exists, so... let's go. + // Process own identities with this fpr + status = get_identities_by_main_key_id(session, fpr_copy, &key_idents); + + if (status == PEP_STATUS_OK) { + // have ident list, or should + identity_list* curr_ident; + for (curr_ident = key_idents; curr_ident && curr_ident->ident; + curr_ident = curr_ident->next) { + pEp_identity* this_identity = curr_ident->ident; + status = key_reset(session, fpr_copy, this_identity); + if (status != PEP_STATUS_OK) + break; + } + } + goto pep_free; + } + else { // an identity was specified. + if (is_me(session, ident)) { + // FIXME: make sure this IS our fpr? + + // If it got sent in with an empty fpr... + if (EMPTYSTR(fpr_copy)) { + // + // if (!EMPTYSTR(ident->fpr)) + // fpr_copy = strdup(ident->fpr); + status = _myself(session, ident, false, true); + if (status == PEP_STATUS_OK && ident->fpr) + fpr_copy = strdup(ident->fpr); + else { + // last resort? + // Get list of own identities + char* own_id = NULL; + status = get_default_own_userid(session, &own_id); + if (status == PEP_STATUS_OK) + status = get_user_default_key(session, own_id, &fpr_copy); + if (status != PEP_STATUS_OK || EMPTYSTR(fpr_copy)) { + free(own_id); + return (status == PEP_STATUS_OK ? PEP_KEY_NOT_FOUND : status); + } + } + } + + free(ident->fpr); + ident->fpr = fpr_copy; + // Create revocation + status = revoke_key(session, fpr_copy, NULL); + // generate new key + if (status == PEP_STATUS_OK) { + ident->fpr = NULL; + status = generate_keypair(session, ident); + } + if (status == PEP_STATUS_OK) { + new_key = strdup(ident->fpr); + status = set_own_key(session, ident, new_key); + } + // mistrust fpr from trust + ident->fpr = fpr_copy; + + ident->comm_type = PEP_ct_mistrusted; + status = set_trust(session, ident); + ident->fpr = NULL; + + // Done with old use of ident. + if (status == PEP_STATUS_OK) { + // Update fpr for outgoing + status = myself(session, ident); + } + + if (status == PEP_STATUS_OK) + // cascade that mistrust for anyone using this key + status = mark_as_compromised(session, fpr_copy); + if (status == PEP_STATUS_OK) + status = remove_fpr_as_default(session, fpr_copy); + if (status == PEP_STATUS_OK) + status = add_mistrusted_key(session, fpr_copy); + // add to revocation list + if (status == PEP_STATUS_OK) + status = set_revoked(session, fpr_copy, new_key, time(NULL)); + // for all active communication partners: + // active_send revocation + if (status == PEP_STATUS_OK) + status = send_key_reset_to_recents(session, fpr_copy, new_key); + + } + else { // not is_me + // remove fpr from all identities + // remove fpr from all users + if (status == PEP_STATUS_OK) + status = remove_fpr_as_default(session, fpr_copy); + // delete key from DB + if (status == PEP_STATUS_OK) {}; +// status = delete_keypair(session, fpr_copy); + // N.B. If this key is being replaced by something else, it + // is done outside of this function. + } + } + +pep_free: + free(fpr_copy); + free(own_id); + free_identity_list(key_idents); + free_stringlist(keys); + free(new_key); + return status; +} diff --git a/src/key_reset.h b/src/key_reset.h new file mode 100644 index 00000000..61261c13 --- /dev/null +++ b/src/key_reset.h @@ -0,0 +1,93 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#pragma once + +#include "key_reset.h" + +#include "pEpEngine.h" +#include "keymanagement.h" +#include "message.h" +#include "message_api.h" +#include "cryptotech.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// FIXME: Proper docs! +// Algorithm: +// +// Key Reset trigger; either manually or in another protocol, parameter key (optional) +// +// if identity given: +// +// key reset for one identity +// +// else +// +// For identity in own identities +// +// key reset for one identitiy +// +// Key Reset for identity: +// +// if own identity: +// +// Create revocation +// +// add to revocation list +// +// mistrust fpr from trust +// +// Remove fpr from ALL identities +// +// Remove fpr from ALL users +// +// generate new key +// +// for all active communication partners: +// +// active_send revocation +// +// else +// +// remove fpr from all identities +// +// remove fpr from all users +// +// delete key from key ring +DYNAMIC_API PEP_STATUS key_reset( + PEP_SESSION session, + const char* fpr, + pEp_identity* ident + ); + +PEP_STATUS has_key_reset_been_sent( + PEP_SESSION session, + const char* user_id, + const char* revoked_fpr, + bool* contacted); + +PEP_STATUS set_reset_contact_notified( + PEP_SESSION session, + const char* revoke_fpr, + const char* contact_id + ); + +PEP_STATUS receive_key_reset(PEP_SESSION session, + message* reset_msg); + +PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session, + message** dst, + pEp_identity* recip, + const char* old_fpr, + const char* new_fpr); + +PEP_STATUS send_key_reset_to_recents(PEP_SESSION session, + const char* old_fpr, + const char* new_fpr); + +#ifdef __cplusplus +} +#endif diff --git a/src/message_api.c b/src/message_api.c index 7f56317b..a1dc61cc 100644 --- a/src/message_api.c +++ b/src/message_api.c @@ -1547,153 +1547,6 @@ void attach_own_key(PEP_SESSION session, message *msg) free(revoked_fpr); } -PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session, - message** dst, - pEp_identity* recip, - const char* old_fpr, - const char* new_fpr) { - - if (!dst || !recip->user_id || !recip->address) - return PEP_ILLEGAL_VALUE; - - if (!old_fpr || !new_fpr) - return PEP_ILLEGAL_VALUE; - - *dst = NULL; - // Get own identity user has corresponded with - pEp_identity* own_identity = NULL; - - PEP_STATUS status = get_own_ident_for_contact_id(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)); // ? - - const char* oldtag = "OLD: "; - const char* newtag = "\nNEW: "; - const size_t taglens = 11; - size_t full_len = taglens + strlen(old_fpr) + strlen(new_fpr) + 2; // \n and \0 - char* longmsg = calloc(full_len, 1); - strlcpy(longmsg, oldtag, full_len); - strlcat(longmsg, old_fpr, full_len); - strlcat(longmsg, newtag, full_len); - strlcat(longmsg, new_fpr, full_len); - strlcat(longmsg, "\n", full_len); - reset_message->longmsg = longmsg; - reset_message->shortmsg = strdup("Key reset"); - - 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; - - free_message(reset_message); - return status; -} - - -PEP_STATUS send_key_reset_to_recents(PEP_SESSION session, - const char* old_fpr, - const char* new_fpr) { - assert(old_fpr); - assert(new_fpr); - assert(session); - assert(session->messageToSend || session->sync_session->messageToSend); - - if (!session || !old_fpr || !new_fpr) - return PEP_ILLEGAL_VALUE; - - messageToSend_t send_cb = send_cb = session->messageToSend; - void* sync_obj = session->sync_obj; - if (!send_cb) { - send_cb = session->sync_session->messageToSend; - sync_obj = session->sync_session->sync_obj; - } - if (!send_cb) - return PEP_SYNC_NO_MESSAGE_SEND_CALLBACK; - - identity_list* recent_contacts = NULL; - message* reset_msg = NULL; - - PEP_STATUS status = get_last_contacted(session, &recent_contacts); - - if (status != PEP_STATUS_OK) - goto pep_free; - - identity_list* curr_id_ptr = recent_contacts; - - for (curr_id_ptr = recent_contacts; curr_id_ptr; curr_id_ptr = curr_id_ptr->next) { - pEp_identity* curr_id = curr_id_ptr->ident; - - if (!curr_id) - break; - - const char* user_id = curr_id->user_id; - - // Should be impossible, but? - if (!user_id) - continue; - - // Check if it's us - if so, pointless... - if (is_me(session, curr_id)) - continue; - - // Check if they've already been told - this shouldn't be the case, but... - bool contacted = false; - status = has_key_reset_been_sent(session, user_id, old_fpr, &contacted); - if (status != PEP_STATUS_OK) - goto pep_free; - - if (contacted) - continue; - - // if not, make em a message - reset_msg = NULL; - - status = create_standalone_key_reset_message(session, - &reset_msg, - curr_id, - old_fpr, - new_fpr); - - if (status == PEP_CANNOT_FIND_IDENTITY) { // this is ok, just means we never mailed them - status = PEP_STATUS_OK; - continue; - } - - if (status != PEP_STATUS_OK) { - free(reset_msg); - goto pep_free; - } - - // insert into queue - status = send_cb(sync_obj, reset_msg); - - if (status != PEP_STATUS_OK) { - free(reset_msg); - goto pep_free; - } - - // Put into notified DB - status = set_reset_contact_notified(session, old_fpr, user_id); - if (status != PEP_STATUS_OK) - goto pep_free; - } - -pep_free: - free_identity_list(recent_contacts); - return status; -} - - PEP_cryptotech determine_encryption_format(message *msg) { assert(msg); @@ -3290,86 +3143,6 @@ pep_free: } -PEP_STATUS receive_key_reset(PEP_SESSION session, - message* reset_msg) { - - if (!session || !reset_msg) - return PEP_ILLEGAL_VALUE; - - pEp_identity* sender_id = reset_msg->from; - - if (!sender_id) - return PEP_MALFORMED_KEY_RESET_MSG; - - PEP_STATUS status = update_identity(session, sender_id); - if (!sender_id->user_id) - return PEP_UNKNOWN_ERROR; - - // FIXME: We'll have to change this for lists!!! - if (is_me(session, sender_id)) // hrm... - return PEP_ILLEGAL_VALUE; - - if (!reset_msg->longmsg || strncmp(reset_msg->longmsg, "OLD: ", 5) != 0) - return PEP_MALFORMED_KEY_RESET_MSG; - - status = PEP_STATUS_OK; - char* old_fpr = NULL; - char* new_fpr = NULL; - - stringlist_t* keylist = NULL; - pEp_identity* temp_ident = identity_dup(sender_id); - if (!temp_ident) { - status = PEP_OUT_OF_MEMORY; - goto pep_free; - } - - char* rest = NULL; - char* p = strtok_r(reset_msg->longmsg, "\r\n", &rest); - if (!EMPTYSTR(p + 5)) - old_fpr = strdup(p + 5); - else { - status = PEP_MALFORMED_KEY_RESET_MSG; - goto pep_free; - } - - p = strtok_r(NULL, "\r\n", &rest); - if (strncmp(p, "NEW: ", 5) != 0 || EMPTYSTR(p + 5)) { - status = PEP_MALFORMED_KEY_RESET_MSG; - goto pep_free; - } - - new_fpr = strdup(p + 5); - - // Reset the original key - status = key_reset(session, old_fpr, temp_ident); - if (status != PEP_STATUS_OK) - goto pep_free; - - status = find_keys(session, new_fpr, &keylist); - if (status != PEP_STATUS_OK) - goto pep_free; - - if (!keylist) { - status = PEP_KEY_NOT_FOUND; - goto pep_free; - } - - // alright, we've checked as best we can. Let's set that baby. - sender_id->fpr = new_fpr; - - // This only sets as the default, does NOT TRUST IN ANY WAY - sender_id->comm_type = sender_id->comm_type & (~PEP_ct_confirmed); - status = set_identity(session, sender_id); - - sender_id->fpr = NULL; // ownership for free -pep_free: - free_stringlist(keylist); - free(old_fpr); - free(new_fpr); - free_identity(temp_ident); - return status; -} - DYNAMIC_API PEP_STATUS _decrypt_message( PEP_SESSION session, message *src, @@ -3957,156 +3730,6 @@ DYNAMIC_API PEP_STATUS own_message_private_key_details( return status; } -DYNAMIC_API PEP_STATUS key_reset( - PEP_SESSION session, - const char* key_id, - pEp_identity* ident - ) -{ - if (!session) - return PEP_ILLEGAL_VALUE; - - PEP_STATUS status = PEP_STATUS_OK; - - char* fpr_copy = NULL; - char* own_id = NULL; - char* new_key = NULL; - identity_list* key_idents = NULL; - stringlist_t* keys = NULL; - - if (!EMPTYSTR(key_id)) { - fpr_copy = strdup(key_id); - if (!fpr_copy) - return PEP_OUT_OF_MEMORY; - } - - if (!ident) { - // Get list of own identities - status = get_default_own_userid(session, &own_id); - if (status != PEP_STATUS_OK) - goto pep_free; - - if (EMPTYSTR(fpr_copy)) { - status = get_all_keys_for_user(session, own_id, &keys); - if (status == PEP_STATUS_OK) { - stringlist_t* curr_key; - for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) { - status = key_reset(session, curr_key->value, NULL); - if (status != PEP_STATUS_OK) - break; - } - } - goto pep_free; - } // otherwise, we have a specific fpr to process - - // fpr_copy exists, so... let's go. - // Process own identities with this fpr - status = get_identities_by_main_key_id(session, fpr_copy, &key_idents); - - if (status == PEP_STATUS_OK) { - // have ident list, or should - identity_list* curr_ident; - for (curr_ident = key_idents; curr_ident && curr_ident->ident; - curr_ident = curr_ident->next) { - pEp_identity* this_identity = curr_ident->ident; - status = key_reset(session, fpr_copy, this_identity); - if (status != PEP_STATUS_OK) - break; - } - } - goto pep_free; - } - else { // an identity was specified. - if (is_me(session, ident)) { - // FIXME: make sure this IS our fpr? - - // If it got sent in with an empty fpr... - if (EMPTYSTR(fpr_copy)) { - // - // if (!EMPTYSTR(ident->fpr)) - // fpr_copy = strdup(ident->fpr); - status = _myself(session, ident, false, true); - if (status == PEP_STATUS_OK && ident->fpr) - fpr_copy = strdup(ident->fpr); - else { - // last resort? - // Get list of own identities - char* own_id = NULL; - status = get_default_own_userid(session, &own_id); - if (status == PEP_STATUS_OK) - status = get_user_default_key(session, own_id, &fpr_copy); - if (status != PEP_STATUS_OK || EMPTYSTR(fpr_copy)) { - free(own_id); - return (status == PEP_STATUS_OK ? PEP_KEY_NOT_FOUND : status); - } - } - } - - free(ident->fpr); - ident->fpr = fpr_copy; - // Create revocation - status = revoke_key(session, fpr_copy, NULL); - // generate new key - if (status == PEP_STATUS_OK) { - ident->fpr = NULL; - status = generate_keypair(session, ident); - } - if (status == PEP_STATUS_OK) { - new_key = strdup(ident->fpr); - status = set_own_key(session, ident, new_key); - } - // mistrust fpr from trust - ident->fpr = fpr_copy; - - ident->comm_type = PEP_ct_mistrusted; - status = set_trust(session, ident); - ident->fpr = NULL; - - // Done with old use of ident. - if (status == PEP_STATUS_OK) { - // Update fpr for outgoing - status = myself(session, ident); - } - - if (status == PEP_STATUS_OK) - // cascade that mistrust for anyone using this key - status = mark_as_compromised(session, fpr_copy); - if (status == PEP_STATUS_OK) - status = remove_fpr_as_default(session, fpr_copy); - if (status == PEP_STATUS_OK) - status = add_mistrusted_key(session, fpr_copy); - // add to revocation list - if (status == PEP_STATUS_OK) - status = set_revoked(session, fpr_copy, new_key, time(NULL)); - // for all active communication partners: - // active_send revocation - if (status == PEP_STATUS_OK) - status = send_key_reset_to_recents(session, fpr_copy, new_key); - - } - else { // not is_me - // remove fpr from all identities - // remove fpr from all users - if (status == PEP_STATUS_OK) - status = remove_fpr_as_default(session, fpr_copy); - // delete key from DB - if (status == PEP_STATUS_OK) {}; -// status = delete_keypair(session, fpr_copy); - // N.B. If this key is being replaced by something else, it - // is done outside of this function. - } - } - -pep_free: - free(fpr_copy); - free(own_id); - free_identity_list(key_idents); - free_stringlist(keys); - free(new_key); - return status; -} - - // Note: if comm_type_determine is false, it generally means that // we were unable to get key information for anyone in the list, // likely because a key is missing. diff --git a/src/pEpEngine.c b/src/pEpEngine.c index cd902cc3..d57f8e2e 100644 --- a/src/pEpEngine.c +++ b/src/pEpEngine.c @@ -4366,92 +4366,6 @@ PEP_STATUS get_last_contacted( } -PEP_STATUS has_key_reset_been_sent( - PEP_SESSION session, - const char* user_id, - const char* revoked_fpr, - bool* contacted) -{ - assert(session); - assert(contacted); - assert(user_id); - assert(revoked_fpr); - assert(!EMPTYSTR(user_id)); - - if (!session || !contacted || EMPTYSTR(revoked_fpr) || EMPTYSTR(user_id)) - return PEP_ILLEGAL_VALUE; - - *contacted = 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 = strdup(user_id); - } - - sqlite3_reset(session->was_id_for_revoke_contacted); - sqlite3_bind_text(session->was_id_for_revoke_contacted, 1, revoked_fpr, -1, - SQLITE_STATIC); - sqlite3_bind_text(session->was_id_for_revoke_contacted, 2, user_id, -1, - SQLITE_STATIC); - int result = sqlite3_step(session->was_id_for_revoke_contacted); - switch (result) { - case SQLITE_ROW: { - *contacted = (sqlite3_column_int(session->was_id_for_revoke_contacted, 0) != 0); - break; - } - default: - sqlite3_reset(session->was_id_for_revoke_contacted); - free(alias_default); - return PEP_UNKNOWN_DB_ERROR; - } - - sqlite3_reset(session->was_id_for_revoke_contacted); - return PEP_STATUS_OK; -} - -//static const char *sql_set_revoke_contact_as_notified = -// "insert or replace into revocation_contact_list(fpr, contact_id) values (?1, ?2) ;"; - -PEP_STATUS set_reset_contact_notified( - PEP_SESSION session, - const char* revoke_fpr, - const char* contact_id - ) -{ - PEP_STATUS status = PEP_STATUS_OK; - - assert(session && !EMPTYSTR(revoke_fpr) && !EMPTYSTR(contact_id)); - - if (!session || EMPTYSTR(revoke_fpr) || EMPTYSTR(contact_id)) - return PEP_ILLEGAL_VALUE; - - sqlite3_reset(session->set_revoke_contact_as_notified); - sqlite3_bind_text(session->set_revoke_contact_as_notified, 1, revoke_fpr, -1, - SQLITE_STATIC); - sqlite3_bind_text(session->set_revoke_contact_as_notified, 2, contact_id, -1, - SQLITE_STATIC); - - int result; - - result = sqlite3_step(session->set_revoke_contact_as_notified); - switch (result) { - case SQLITE_DONE: - status = PEP_STATUS_OK; - break; - - default: - status = PEP_UNKNOWN_DB_ERROR; - } - - sqlite3_reset(session->set_revoke_contact_as_notified); - return status; -} - - PEP_STATUS key_created( PEP_SESSION session, const char *fpr, diff --git a/src/pEpEngine.h b/src/pEpEngine.h index 7e2cc6a5..be7ae49b 100644 --- a/src/pEpEngine.h +++ b/src/pEpEngine.h @@ -1177,54 +1177,6 @@ DYNAMIC_API PEP_STATUS get_revoked( uint64_t *revocation_date ); -// Algorithm: -// -// Key Reset trigger; either manually or in another protocol, parameter key (optional) -// -// if identity given: -// -// key reset for one identity -// -// else -// -// For identity in own identities -// -// key reset for one identitiy -// -// Key Reset for identity: -// -// if own identity: -// -// Create revocation -// -// add to revocation list -// -// mistrust fpr from trust -// -// Remove fpr from ALL identities -// -// Remove fpr from ALL users -// -// generate new key -// -// for all active communication partners: -// -// active_send revocation -// -// else -// -// remove fpr from all identities -// -// remove fpr from all users -// -// delete key from key ring -DYNAMIC_API PEP_STATUS key_reset( - PEP_SESSION session, - const char* fpr, - pEp_identity* ident - ); - - // key_created() - get creation date of a key // // parameters: @@ -1349,19 +1301,6 @@ PEP_STATUS get_last_contacted( identity_list** id_list ); - -PEP_STATUS has_key_reset_been_sent( - PEP_SESSION session, - const char* user_id, - const char* revoked_fpr, - bool* contacted); - -PEP_STATUS set_reset_contact_notified( - PEP_SESSION session, - const char* revoke_fpr, - const char* contact_id - ); - PEP_STATUS get_own_ident_for_contact_id(PEP_SESSION session, const pEp_identity* contact, pEp_identity** own_ident); diff --git a/src/pEp_internal.h b/src/pEp_internal.h index 482628a6..21b4fc67 100644 --- a/src/pEp_internal.h +++ b/src/pEp_internal.h @@ -108,6 +108,8 @@ #include "transport.h" #include "sync.h" +#include "key_reset.h" + #define NOT_IMPLEMENTED assert(0); return PEP_UNKNOWN_ERROR; struct _pEpSession; diff --git a/test/test_files/398_gabrielle_to_alice.eml b/test/test_files/398_gabrielle_to_alice.eml new file mode 100644 index 00000000..bfff73c2 --- /dev/null +++ b/test/test_files/398_gabrielle_to_alice.eml @@ -0,0 +1,87 @@ +Message-ID: +From: Gabi +To: Alice is tired of Bob +Subject: =?utf-8?Q?p=E2=89=A1p?= +X-pEp-Version: 2.0 +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="d39e5287be3847623f45c9767504e45"; + protocol="application/pgp-encrypted" + +--d39e5287be3847623f45c9767504e45 +Content-Type: application/pgp-encrypted + +Version: 1 +--d39e5287be3847623f45c9767504e45 +Content-Type: application/octet-stream +Content-Transfer-Encoding: 7bit +Content-Disposition: inline; filename="msg.asc" + +-----BEGIN PGP MESSAGE----- + +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 +6ihY +=/YtR +-----END PGP MESSAGE----- + +--d39e5287be3847623f45c9767504e45-- + diff --git a/test/test_files/398_reset_from_alice_to_bob.eml b/test/test_files/398_reset_from_alice_to_bob.eml new file mode 100644 index 00000000..90b4eb58 --- /dev/null +++ b/test/test_files/398_reset_from_alice_to_bob.eml @@ -0,0 +1,115 @@ +From: Alice in Wonderland +To: Bob's Burgers +Subject: =?utf-8?Q?p=E2=89=A1p?= +X-pEp-Version: 2.0 +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="41fb875950ea35e61360a605caa7977"; + protocol="application/pgp-encrypted" + +--41fb875950ea35e61360a605caa7977 +Content-Type: application/pgp-encrypted + +Version: 1 +--41fb875950ea35e61360a605caa7977 +Content-Type: application/octet-stream +Content-Transfer-Encoding: 7bit +Content-Disposition: inline; filename="msg.asc" + +-----BEGIN PGP MESSAGE----- + +hQEMA5Jd4qLmEMkZAQf+OnDf3f/QjoHqkMz/WdWwu0Trr4uN1k1QpNXgZEl8VpAk +Jlj1Akv3ksKMgNVRkdPGOSu14PE/xG7YxDDtzu4e0ruw3uFPl462i0WNz7fOmEdZ +YnMpfn4fNMf+H7/sG5BvaUs/Vdto7uhZ1+ebgeIcwVfKwiOs7NEvGghiJUMOteo/ +Jqki9TMytX9sb58tL8x5d/dKbXEewNs1jqt28DKjAP+TCa+F2APN3z86GWBqaRse +JMnw5kOqDXEuyQ2XKA+nlLbThxMZ/5y0+4r4YeKmDqJdcqmSwggLet0LROhZajlV +O+UgkmIEpqKkj5yjG1Aobl8i+RbDSgcN2EcPjG+dHoUBDAOK25E37BudTgEH/1aK +OKh53th8VkK0XSnWqb3Th30X6/4pJNTi+gPM6jHGxRJmlcDgETw3oPii6Q9unWGF +LxFidBJLy91nfO+hxLwb/xVttQ8Gm8JO0ErjTPqdLC13sEN30nD6pBLl19CFPuYX +cq05KtFlSoip9T4Ie9Z9RfI3iX0FKYcOBUImXd41WD9VUMRghPKUyxILspkT5Lzr +hHHsAoDLMjAClwrJi+jFQ0tiBZXxA5E7g2uBvEWkI6zXlahR8LqFtczZRUKtkaUW +4B6SUhe/lhEysZ+OQeyicLN+UypYjHKOWRhZQ/c5ZCQ9WYQ8/fuvAW68vVauCVQz +Yi/Q+zUFYHuI0grCvCvS6wH1lh7lW+O6N6Q6yZEiuWkrKY/vPPsujSLSNV0rnhek +YIy/Dv6smWbmTmT0J4pu4LBOFeSxmoMPRqKvgGuxderlNd846y7y4UIcvHdZ7iit +bWQlTVvZiAUs3fZDRDGIHc55woaTaShHuQKsWq8Bz85gyZQyhf4OmqBKVdiV4Owx +5jdsFey96y+pK6hjMZxzBLDj5uLPtv9qpUAEw+2/GvX44RXf9gD+UEwo4KLx7iA2 +lfktUa/93Ib3oFLFt0daej1bQVS6X+hREwt5djd2ufLitSzYQXGhDEKQ8PXnxT4G +oEaLuGS70CbQGk2WoWc5Lpb99K8Q6jCowh8YtcN+OKmjTvpeJlo0+bcTq1UJcbah +8vAmV9hnyJsOelCwKZnLGgx9q7ti86qtTHxtyRsvw0Pw0IFsUQBW9ZkIybOZrUfz +bPxt+de+jkbAsHK8gRhug2SWmb2XtEfhEoU6EMGZvaRwLF8GNvL1N5EOXFXKJ/dK +YR4mGDLBFjahq42wUlL0TADulj3E2vE89bLaUD23SI3yK2+Bva5JegI0YOg0cgKq +IZEpb29VeAxzae9/Gkmusp06GNsgjBqXgkLeO2rpPhzfrqgeKcD6I4UpTleSAP0U +ApdxisSnZlFjmOyxIqxbNV3JjYtApaeUi+B8nGmHnHE/lE/flSc8SdZne7MTq2iw +1pJMLDZNhWB+S2Ch6bhgYbnmiwBMJq+b/yEWOev8aL+ZGgWTAsWr2Kc//mdH0htH +Rk2Eckz/pyTJ7q0d/Tk9aOXVc5/Q5mWzrttrfoo40oJlR8IN3wcq5eKT+ZU3SygP +KRVt1iLWdj9/9TgeixtMlRUX7kXaBWRV/x0kX1mV9INEulzDvtwqcJiTRSX/pqPY +rTm+9FdpsPv+Rp1ep+iKkoPZRlzJh6z932+gZ6jam1eQz/UdBS4ttKMLvhxdaBgG +Rb29XKjIVRXdItq48n9UaBk91rGUT0Ol3i0NtiBIj5Z87tph+dq4XSLmhr720Imn +QvEl627xGbhb4xOE/MBxh0HYhSi1F2arxsIv+7c0YK5agbCqnl2+b+8L4Hlljlr3 +FUu/GbkzOfkGDBYHYBfY48/VwEbDqoCDTef9uBJ7XQDFvwfhGwvKBOBnv5WW3j8i +pUVKby2x9oWTjH+7Tdn1oL4DiNcnyOGhmDOisWYhIDxFrWH02fHI5Ag9jvbY3mah +nrdWm8PNqnKRaS/fe++LYW3zKyo08+5TDGzQJqrOJ3wPK8UK51pXsMG1N/J3wxXr +saEBTzwhlPdc7bd734Grn0mmc/lBbBKK9VzgjwxS8lGRr0FOIdDTRdMJU42Zq5dC +vJ4fRDDx+0QlAos6+srlgYcmK6KFcp/9OpU+cNztQYolp4HNdZRPaG2TSdnl3SBi +e/DhE5JsVPVvlHXYPwPE1s4voxEQqce8BsbvNPBSCdN+UKd9/NAL3yCxqgQa+MPV +Cx7fJoIVD0Rpu4jBhga6ePxntuA16nNDefHh0BNKoptkbD3Ls0fWBAf0RC/kQbU8 +wEeFwQfjIYES/OHKex51qhdxG+6yF3w5yehzbPoUPUM+Rmriwiq6lDEYDVfnJrK+ +TqTxyHcDhLtgsCEo1DgS1wUMbbY7RbLXqfHUj+0VSpD65mkG6+0gu3gQLYGtTYDu +ssX/vYD63kuj2r2dYbN7muQrfPpOX4SGoh8Ao5e39A/G91+pD5MTrw4JUQ49EV6l +1KeewEivDBJ2inFPzg1ijRuQG5Zj/mDYCu2wkks0V2kqtikSIUAao/DK7UZ7fC1p +1NIYZcRjgL54P3fqize+0FW+a6FheLtBlzrcRXR9JXjpQHh/9zRw4PkGJOJsXv1L +GXcuPOL60wo5YF8SVrsmd6xzcrt1CB8egcQGFzdxOXrMC6sBCJ+xyWySZShotGvG +6/rwv1s7/Hl6ls5Pb1ii4FuxKSdrz70Fz01z066RszL7W0xqtgGcPw49/pBp1gCr +tqj/gD9/xM9j1N8gKtc9ABZVGS+fldUVxQ01S2Cg2riU0JpDAG6hVJyT/qWl6myQ +owLWdJOWcczyEa/aOiH+ls5yO7NT7hwT+EGWDx5B7VKA1JsouTBOK5BZbWLGI23G +SVVqVaRHiAeoqhIxmIHrzZK3hERohOG9T+IyMfOlMiGCfqPUUf/q7+LS3djTjQ2t +dEKfCpEdKmUOMQpb+I/lrbxP3dV+wEhmM7aSrRKke6PjiUXjfZMiGR/02evumhKi +aRqtwXy0s/QagTzo6z5Jp6ZqiALqZ2jopb390X+6Hz1GNvDZ1GSDX4KASlI7dnGA +8JzbKRwA1+H6Z+tgKFzl+96/56gtXTz6E1ynRF6tIp00j8sukBpTdi3lpZPAte/K +E3Ke7Ts0AyMHD5K35QJ0+zcunPrQ1AVfa7lBmUkBBE9Vf6jIgtAou+jWDMXZr5O9 +u+qC4kSNoMglD3P2RO/XiqIdBCpcQigaVd+CTL+3vLUzm7swn36bRX+LYaHLDSUi +AKuhJ0UzRwetuxnUBQP3h7L8BzkfceixpUX97itmm6ZBZP3vl24eWPL8UKQwFboS +UuYzd4LOhv3G4nKSgFQcPj4isQlCJZyKsPZ95UHsA7SEuTgXQM/WXzWz7LtO2zOW +0tTVkBOyVADjqgXpihhA0hXYMJJAqhV99XRhiCc9LNOHqwPb72GZai3qQa8TC4gY +WXAzLM2oLI/DzhQNF1CRrGfj/tKfqrG6b9wH+NuW0fD2TapgsGF8Xgu8fMP0lcMs +6n5yJNm2Ocgu+j5nXMT4ovK10a/+ndI/oAB3a/YE7Z6pgnp7X6/fIkHLlwrAA3/W +jlH76PEFeVSBSWZy/1FwKYRHW33Dgync4SjK0UfTJdzU+N0CYetNYKGLvLV0Ffws +1CEqeXTNT0FUoeTNhdaUsgwJWmdRcIXZq5wduRFTWjJ69sRyHTGrFemg3WzUCpdm +AL/Ozbs2kC11bBjHovc6dne9SAXTQR9nZtf/+Zvu8Yyoswi/yG4WeRCIsEk1XVBj +SzyXRHCVMJC/HMGFTwNc4Iff/rcQnbFiTPvhjTsLC1vLgr5eLitF7QQW6Q9KPugH +VHmpNxlejj5nYIqUBal4w0TE5OvS+P9HPatwJCNcMjOh/NYdAIYv2lYRS+EepeC+ +46EKB4s0o8hur5e1AHfhlsbrVZ6fyPPvNT0QTdAH6hgpHEZ/AUzxoJ6pTaN1smsJ +GIyqCPPy5Pq1VTv1fAx1wVZ7Xh3XZYDwv49qFO4swoYRspAAB47bW1sUGkI/gcSo +gtYWDYceP+GjsPKbLlfSfFUWirw4xMsbRH5BEmh0IGSGdycFv81PC1ii5VpWULFz +8M5qt9omY99EOppe6xVhw8gHRV09pT+ewizvJ4kQNyMs8/YqP3HUrPYSTaRnVZmG +AxJBQubYQyYx8r7sZnZRnorhlhBbl/0hY66eBbdU9kQpXDDE/S+Nt2iJ0I5c3hFt +Cs8sgIB0rsErIxjlefEo0nkfNgriF6ZGIIs2/NPjkxN5YDRLP6Ksbsq8SR+FFWCI +yhpd9478VilUfhd6c1uz8sLm5w7nQMTyBkjSS6rW+4XYa7uPu31EaVfm9bfodO8e +vKSZpvfcGsgZTuDx+CQkEpo/tAUsglnglvienoyoqFt33VZr3DaqQj6HZNsR/cZu +xt/72vHwhaPcFJyOn+qbbJ/P2rgsvbdszQhBJTfn4j63GPdHV7tVAChUFtX3fseR +PgpPcZea6JlaR+0CprUKRCsOQ7WZHNJIHjthavxegXi7qFJjfHN+/zrT1GUdyos/ +NvEmO5ahXrmWVxfUjn5CTsByAkqzxInBsM+WS5iI4fq1oCsTsOyiVlCQi97+dAIi +3OIC+GDEsQbi+id2FJsMfKQuKwjmPCUrF6FYqpEUzwv8DKb+9Nb8OlKdFxayetGC +zkMvbuVsdEt7/Fale9RbiWkRqpSmgDFovFWEjJ73Ri/QZFP8Li3XjjnNt4cndc2Z +BoB+hAzv+FrpTInxGhrrCKGyBrEnKxRiCD9DDR0tKfiIbe3ZAXOo1MeZDDpCgr0Z +rAwb4AOkoAakS65sJ6ADtmTE4Jv4U2ulZABk8QG7yl5vxVSQcyJ+ZeVWXhW9S4rA +Kf+lB8I8T+rE69PKA3Y+ehPpFaRTx3rtktHfKfM3HUXz6OEcSrsqXreKE5am5qBM +QQ//vD9sHmkb9TTyrBYl0an/4DdxGDTxh+8lnhI/4bLrSrMluhkw6mRjow5yjA/+ +zOYAwP15E5Xq+d7OHJomqTSnUtdFVLNs5ljIQQEXIsVDGU/UifQW6MycLREntHCW ++TZNRWk+H8JwVEPOnOEQCNzdCTwRhlhJkykxY8swaQezsdkG3ryNTqfT3ITRPOoA +l/huOyjHnWLo8496QciMLg6oBPieQhk9Ti93Mi2a5o8zDnOFvPc2etFWhYh3FdHQ +bMCESq6IqjVwz4u/terRQ+tZN751pGjhR5eS3/qJL8hvNHuRO2SoD7qI2SFo5d2H +8LtgQBMWWYQkF/WFieaLqvS+h/yrvXntfpv5+5O0Ceqk3rXWlC9Unjmvib4AUqPX +PUgbCJ06seSUS93Oy1VV+WTMxqi+5vvQ2stpudhos2BDQbpCIQL6wjcO/mQ3OAdr +SgRT1DJvq+n9JoRouyJHpnQuFpBZF5fMXy2sAoDsGqksy3sHvSjlKgZzwSetwiRk +Kixdan1Wbz5yp0VIcebyxQORTQqYHSicdTHmSzM8VrmgjeSxl+WWrn/uW36yJFP2 +uCPoNKtF9BfgFu6sWgAOxXd5jTDR8LVFzi5oA9C2RCL5sZo4vZuQtPE1bSJYiKuW +QwnAFaNs9zV79FAmvvxjgoUWyjwB83yVtrrVaAyh/7KGzhF3tlGry/XN+kqWk2lW +bTpcLhSgzABkv0X12caWgV5uIMCDXxJv0h+x+P7C99+t/6xAGf0rR+5xmbN/EZjK +zJgnl/XNS18P7vciphoEcUSdQ7fTQmUyJIqBlSKlBbmtld7bph8nht9kEZdsfN+G +aSmWYw7HRaCXoq+IqVJeFoykvC35dBX/X30BV1d0HrO3kgTS87Fdl/7nF0boO528 +ICgsOg1vvjXDZLqEyHrjxMCHpZiCNBksnQ== +=0apO +-----END PGP MESSAGE----- + +--41fb875950ea35e61360a605caa7977-- + diff --git a/test/test_files/398_reset_from_alice_to_fenris.eml b/test/test_files/398_reset_from_alice_to_fenris.eml new file mode 100644 index 00000000..ab30e30b --- /dev/null +++ b/test/test_files/398_reset_from_alice_to_fenris.eml @@ -0,0 +1,121 @@ +Message-ID: +From: Alice in Wonderland +To: Fenris Leto Hawke +Subject: =?utf-8?Q?p=E2=89=A1p?= +X-pEp-Version: 2.0 +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="7e23a74c7397f0666f31d87d17b86a89"; + protocol="application/pgp-encrypted" + +--7e23a74c7397f0666f31d87d17b86a89 +Content-Type: application/pgp-encrypted + +Version: 1 +--7e23a74c7397f0666f31d87d17b86a89 +Content-Type: application/octet-stream +Content-Transfer-Encoding: 7bit +Content-Disposition: inline; filename="msg.asc" + +-----BEGIN PGP MESSAGE----- + +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 +Gbdayy1g6mwuZA== +=ncTl +-----END PGP MESSAGE----- + +--7e23a74c7397f0666f31d87d17b86a89-- +