mirror of
https://github.com/chatmail/core.git
synced 2026-05-01 20:36:31 +03:00
integrate encryption when sending
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -99,7 +99,7 @@ dependencies = [
|
|||||||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures_codec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures_codec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"imap-proto 0.9.1 (git+https://github.com/djc/tokio-imap)",
|
"imap-proto 0.9.1 (git+https://github.com/djc/tokio-imap)",
|
||||||
"nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1116,7 +1116,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures_codec"
|
name = "futures_codec"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3483,7 +3483,7 @@ dependencies = [
|
|||||||
"checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6"
|
"checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6"
|
||||||
"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76"
|
"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76"
|
||||||
"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d"
|
"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d"
|
||||||
"checksum futures_codec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b4043054a6220de5dc5c814eb82ab6fd7cd2b6574a844406f651ec688cfa6fcc"
|
"checksum futures_codec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "793d2283ff61ffff52d51cc631be0c8e75370d96056a38e09f124a67263913da"
|
||||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||||
|
|||||||
114
src/e2ee.rs
114
src/e2ee.rs
@@ -10,7 +10,6 @@ use crate::context::Context;
|
|||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::key::*;
|
use crate::key::*;
|
||||||
use crate::keyring::*;
|
use crate::keyring::*;
|
||||||
use crate::mimefactory::MimeFactory;
|
|
||||||
use crate::peerstate::*;
|
use crate::peerstate::*;
|
||||||
use crate::pgp;
|
use crate::pgp;
|
||||||
use crate::securejoin::handle_degrade_event;
|
use crate::securejoin::handle_degrade_event;
|
||||||
@@ -89,19 +88,17 @@ impl EncryptHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to encrypt the passed in `mail`.
|
/// Tries to encrypt the passed in `mail`.
|
||||||
pub fn try_encrypt(
|
pub fn encrypt(
|
||||||
&mut self,
|
&mut self,
|
||||||
factory: &mut MimeFactory,
|
context: &Context,
|
||||||
e2ee_guaranteed: bool,
|
e2ee_guaranteed: bool,
|
||||||
min_verified: PeerstateVerifiedStatus,
|
min_verified: PeerstateVerifiedStatus,
|
||||||
do_gossip: bool,
|
do_gossip: bool,
|
||||||
mut mail: lettre_email::Email,
|
mut mail_to_encrypt: lettre_email::PartBuilder,
|
||||||
imffields_unprotected: Vec<lettre_email::Header>,
|
|
||||||
peerstates: &[(Option<Peerstate>, &str)],
|
peerstates: &[(Option<Peerstate>, &str)],
|
||||||
) -> Result<(lettre_email::Email, bool)> {
|
) -> Result<String> {
|
||||||
let context = &factory.context;
|
|
||||||
let mut keyring = Keyring::default();
|
let mut keyring = Keyring::default();
|
||||||
let mut gossip_headers: Vec<String> = Vec::with_capacity(factory.recipients_addr.len());
|
let mut gossip_headers: Vec<String> = Vec::with_capacity(peerstates.len());
|
||||||
|
|
||||||
for (peerstate, addr) in peerstates
|
for (peerstate, addr) in peerstates
|
||||||
.iter()
|
.iter()
|
||||||
@@ -129,109 +126,16 @@ impl EncryptHelper {
|
|||||||
key
|
key
|
||||||
};
|
};
|
||||||
|
|
||||||
// encrypt message
|
// Add gossip headers
|
||||||
use lettre_email::{EmailBuilder, MimeMessage, PartBuilder};
|
|
||||||
|
|
||||||
// let mut part_to_encrypt: lettre::SendableEmail = mail.into().to_string()?.into_bytes();
|
|
||||||
|
|
||||||
let mut mail_to_encrypt = EmailBuilder::new();
|
|
||||||
|
|
||||||
for header in &gossip_headers {
|
for header in &gossip_headers {
|
||||||
mail_to_encrypt = mail_to_encrypt.header(("Autocrypt-Gossip", header));
|
mail_to_encrypt = mail_to_encrypt.header(("Autocrypt-Gossip", header));
|
||||||
}
|
}
|
||||||
|
|
||||||
// memoryhole headers: move some headers into encrypted part
|
let raw_message = mail_to_encrypt.build().as_string().into_bytes();
|
||||||
|
|
||||||
// while !cur.is_null() {
|
let ctext = pgp::pk_encrypt(&raw_message, &keyring, sign_key.as_ref())?;
|
||||||
// let field = (*cur).data as *mut mailimf_field;
|
|
||||||
// let mut move_to_encrypted = false;
|
|
||||||
|
|
||||||
// if !field.is_null() {
|
Ok(ctext)
|
||||||
// if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
|
|
||||||
// move_to_encrypted = true;
|
|
||||||
// } else if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
|
||||||
// let opt_field = (*field).fld_data.fld_optional_field;
|
|
||||||
// if !opt_field.is_null() && !(*opt_field).fld_name.is_null() {
|
|
||||||
// let fld_name = to_string_lossy((*opt_field).fld_name);
|
|
||||||
// if fld_name.starts_with("Secure-Join")
|
|
||||||
// || (fld_name.starts_with("Chat-") && fld_name != "Chat-Version")
|
|
||||||
// {
|
|
||||||
// move_to_encrypted = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if move_to_encrypted {
|
|
||||||
// mailimf_fields_add(imffields_encrypted, field);
|
|
||||||
// cur = clist_delete((*imffields_unprotected).fld_list, cur);
|
|
||||||
// } else {
|
|
||||||
// cur = (*cur).next;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let subject = mailimf_subject_new("...".strdup());
|
|
||||||
// mailimf_fields_add(imffields_unprotected, mailimf_field_new_subject(subject));
|
|
||||||
|
|
||||||
// wrapmime::append_ct_param(
|
|
||||||
// (*part_to_encrypt).mm_content_type,
|
|
||||||
// "protected-headers",
|
|
||||||
// "v1",
|
|
||||||
// )?;
|
|
||||||
// let plain = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
|
||||||
// let mut col = 0;
|
|
||||||
// mailmime_write_mem(plain, &mut col, message_to_encrypt);
|
|
||||||
// mailmime_free(message_to_encrypt);
|
|
||||||
|
|
||||||
// ensure!(
|
|
||||||
// !(*plain).str_0.is_null() && (*plain).len > 0,
|
|
||||||
// "could not write/allocate"
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let ctext = pgp::pk_encrypt(
|
|
||||||
// std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len),
|
|
||||||
// &keyring,
|
|
||||||
// sign_key.as_ref(),
|
|
||||||
// );
|
|
||||||
// mmap_string_free(plain);
|
|
||||||
|
|
||||||
// let ctext_v = ctext?;
|
|
||||||
|
|
||||||
// // create MIME-structure that will contain the encrypted text
|
|
||||||
// let mut encrypted_part = new_data_part(
|
|
||||||
// ptr::null_mut(),
|
|
||||||
// 0 as libc::size_t,
|
|
||||||
// "multipart/encrypted",
|
|
||||||
// MAILMIME_MECHANISM_BASE64,
|
|
||||||
// )?;
|
|
||||||
// let content = (*encrypted_part).mm_content_type;
|
|
||||||
// wrapmime::append_ct_param(content, "protocol", "application/pgp-encrypted")?;
|
|
||||||
|
|
||||||
// let version_mime = new_data_part(
|
|
||||||
// VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void,
|
|
||||||
// strlen(VERSION_CONTENT.as_mut_ptr()),
|
|
||||||
// "application/pgp-encrypted",
|
|
||||||
// MAILMIME_MECHANISM_7BIT,
|
|
||||||
// )?;
|
|
||||||
// mailmime_smart_add_part(encrypted_part, version_mime);
|
|
||||||
|
|
||||||
// // we assume that ctext_v is not dropped until the end
|
|
||||||
// // of this if-scope
|
|
||||||
// let ctext_part = new_data_part(
|
|
||||||
// ctext_v.as_ptr() as *mut libc::c_void,
|
|
||||||
// ctext_v.len(),
|
|
||||||
// "application/octet-stream",
|
|
||||||
// MAILMIME_MECHANISM_7BIT,
|
|
||||||
// )?;
|
|
||||||
|
|
||||||
// mailmime_smart_add_part(encrypted_part, ctext_part);
|
|
||||||
// (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part;
|
|
||||||
// (*encrypted_part).mm_parent = in_out_message;
|
|
||||||
|
|
||||||
// let gossiped = !&gossip_headers.is_empty();
|
|
||||||
// factory.finalize_mime_message(true, gossiped)?;
|
|
||||||
|
|
||||||
Ok((mail_to_encrypt.build()?, true))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -300,13 +300,9 @@ impl<'a> MimeFactory<'a> {
|
|||||||
"Invalid use of mimefactory-object."
|
"Invalid use of mimefactory-object."
|
||||||
);
|
);
|
||||||
|
|
||||||
let context = &self.context;
|
|
||||||
let peerstates = self.peerstates_for_recipients()?;
|
|
||||||
let e2ee_guranteed = self.is_e2ee_guranteed()?;
|
let e2ee_guranteed = self.is_e2ee_guranteed()?;
|
||||||
|
|
||||||
let mut encrypt_helper = EncryptHelper::new(&context)?;
|
let mut encrypt_helper = EncryptHelper::new(self.context)?;
|
||||||
let should_encrypt =
|
|
||||||
encrypt_helper.should_encrypt(self.context, e2ee_guranteed, &peerstates)?;
|
|
||||||
|
|
||||||
// Headers that are encrypted
|
// Headers that are encrypted
|
||||||
// - Chat-*, except Chat-Version
|
// - Chat-*, except Chat-Version
|
||||||
@@ -400,23 +396,62 @@ impl<'a> MimeFactory<'a> {
|
|||||||
unprotected_headers.push(Header::new("Autocrypt".into(), aheader));
|
unprotected_headers.push(Header::new("Autocrypt".into(), aheader));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected_headers.push(Header::new("Subject".into(), subject));
|
||||||
|
|
||||||
|
let peerstates = self.peerstates_for_recipients()?;
|
||||||
|
let should_encrypt =
|
||||||
|
encrypt_helper.should_encrypt(self.context, e2ee_guranteed, &peerstates)?;
|
||||||
|
|
||||||
let mut outer_message = if should_encrypt && force_plaintext == 0 {
|
let mut outer_message = if should_encrypt && force_plaintext == 0 {
|
||||||
for header in protected_headers.into_iter() {
|
for header in protected_headers.into_iter() {
|
||||||
message = message.header(header);
|
message = message.header(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut outer_message = PartBuilder::new();
|
// Manual Content-Type only works with https://github.com/niax/rust-email/pull/51
|
||||||
|
// At the moment the boundary will not be inserted.
|
||||||
|
let mut outer_message = PartBuilder::new().header((
|
||||||
|
"Content-Type".to_string(),
|
||||||
|
"multipart/encrypted; protocol=\"application/pgp-encrypted\"".to_string(),
|
||||||
|
));
|
||||||
|
|
||||||
for header in unprotected_headers.into_iter() {
|
for header in unprotected_headers.into_iter() {
|
||||||
outer_message = outer_message.header(header);
|
outer_message = outer_message.header(header);
|
||||||
}
|
}
|
||||||
// if let Some(encrypted) = encrypt_helper.try_encrypt(
|
|
||||||
// self,
|
let encrypted = encrypt_helper.encrypt(
|
||||||
// e2ee_guaranteed,
|
self.context,
|
||||||
// min_verified,
|
e2ee_guranteed,
|
||||||
// do_gossip,
|
min_verified,
|
||||||
// message,
|
do_gossip,
|
||||||
// imffields_unprotected,
|
message,
|
||||||
// )? {
|
&peerstates,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
outer_message = outer_message
|
||||||
|
.child(
|
||||||
|
// Autocrypt part 1
|
||||||
|
PartBuilder::new()
|
||||||
|
.content_type(&"application/pgp-encrypted".parse::<mime::Mime>().unwrap())
|
||||||
|
.header(("Content-Description", "PGP/MIME version identification"))
|
||||||
|
.body("Version: 1")
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
// Autocrypt part 2
|
||||||
|
PartBuilder::new()
|
||||||
|
.content_type(
|
||||||
|
&"application/octet-stream; name=\"encrypted.asc\""
|
||||||
|
.parse::<mime::Mime>()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.header(("Content-Description", "OpenPGP encrypted message"))
|
||||||
|
.header(("Content-Disposition", "inline; filename=\"encrypted.asc\""))
|
||||||
|
.body(encrypted)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.header(("Subject".to_string(), "...".to_string()));
|
||||||
|
|
||||||
|
self.finalize_mime_message(true, do_gossip && !peerstates.is_empty())?;
|
||||||
|
|
||||||
outer_message
|
outer_message
|
||||||
} else {
|
} else {
|
||||||
@@ -434,8 +469,7 @@ impl<'a> MimeFactory<'a> {
|
|||||||
|
|
||||||
outer_message = outer_message
|
outer_message = outer_message
|
||||||
.header(Header::new_with_value("To".into(), to).unwrap())
|
.header(Header::new_with_value("To".into(), to).unwrap())
|
||||||
.header(Header::new_with_value("From".into(), vec![from]).unwrap())
|
.header(Header::new_with_value("From".into(), vec![from]).unwrap());
|
||||||
.header(Header::new("Subject".into(), subject));
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// self.envelope = Some(Envelope::new(Some(from), to).expect("setting from"));
|
// self.envelope = Some(Envelope::new(Some(from), to).expect("setting from"));
|
||||||
|
|||||||
Reference in New Issue
Block a user