avoid cdata_to_free trick and some more cleanups

This commit is contained in:
holger krekel
2019-09-23 14:02:54 +02:00
parent 5cbcb76039
commit 095cb759ed
2 changed files with 40 additions and 37 deletions

View File

@@ -85,6 +85,25 @@ impl<'a> MimeFactory<'a> {
context, context,
} }
} }
pub fn finalize_mime_message(
&mut self,
message: *mut mailmime,
encrypted: bool,
gossiped: bool,
) -> Result<(), Error> {
unsafe {
assert!(self.out.is_null()); // guard against double-calls
self.out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
let mut col: libc::c_int = 0;
if 0 != mailmime_write_mem(self.out, &mut col, message) {
bail!("could not write memory-mime-message")
}
}
self.out_encrypted = encrypted;
self.out_gossiped = encrypted && gossiped;
Ok(())
}
} }
impl<'a> Drop for MimeFactory<'a> { impl<'a> Drop for MimeFactory<'a> {
@@ -242,7 +261,7 @@ pub fn dc_mimefactory_load_mdn<'a>(
pub unsafe fn dc_mimefactory_render( pub unsafe fn dc_mimefactory_render(
context: &Context, context: &Context,
factory: &mut MimeFactory, mut factory: &mut MimeFactory,
) -> Result<(), Error> { ) -> Result<(), Error> {
if factory.loaded == Loaded::Nothing || !factory.out.is_null() { if factory.loaded == Loaded::Nothing || !factory.out.is_null() {
bail!("Invalid use of mimefactory-object."); bail!("Invalid use of mimefactory-object.");
@@ -729,28 +748,20 @@ pub unsafe fn dc_mimefactory_render(
let aheader = encrypt_helper.get_aheader().to_string(); let aheader = encrypt_helper.get_aheader().to_string();
new_custom_field(imffields_unprotected, "Autocrypt", &aheader); new_custom_field(imffields_unprotected, "Autocrypt", &aheader);
} }
let mut finalized = false;
if force_plaintext == 0 { if force_plaintext == 0 {
let was_encrypted = encrypt_helper.try_encrypt( finalized = encrypt_helper.try_encrypt(
factory.context, &mut factory,
&factory.recipients_addr,
e2ee_guaranteed, e2ee_guaranteed,
min_verified, min_verified,
do_gossip, do_gossip,
message, message,
imffields_unprotected, imffields_unprotected,
)?; )?;
if was_encrypted {
info!(context, "message was encrypted");
factory.out_encrypted = true;
if do_gossip {
factory.out_gossiped = true;
} }
if !finalized {
factory.finalize_mime_message(message, false, false)?;
} }
}
factory.out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
let mut col: libc::c_int = 0;
mailmime_write_mem(factory.out, &mut col, message);
encrypt_helper.thanks();
cleanup(message); cleanup(message);
Ok(()) Ok(())
} }

View File

@@ -23,6 +23,7 @@ use mmime::{mailmime_substitute, MAILIMF_NO_ERROR, MAIL_NO_ERROR};
use crate::aheader::*; use crate::aheader::*;
use crate::config::Config; use crate::config::Config;
use crate::context::Context; use crate::context::Context;
use crate::dc_mimefactory::*;
use crate::dc_mimeparser::*; use crate::dc_mimeparser::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::error::*; use crate::error::*;
@@ -36,21 +37,12 @@ use crate::wrapmime::*;
#[derive(Debug)] #[derive(Debug)]
pub struct EncryptHelper { pub struct EncryptHelper {
cdata_to_free: Option<Box<dyn Any>>,
pub prefer_encrypt: EncryptPreference, pub prefer_encrypt: EncryptPreference,
pub addr: String, pub addr: String,
pub public_key: Key, pub public_key: Key,
} }
impl EncryptHelper { impl EncryptHelper {
/// Frees data referenced by "mailmime" but not freed by mailmime_free(). After calling this function,
/// in_out_message cannot be used any longer!
pub unsafe fn thanks(&mut self) {
if let Some(data) = self.cdata_to_free.take() {
free(Box::into_raw(data) as *mut _)
}
}
pub fn new(context: &Context) -> Result<EncryptHelper> { pub fn new(context: &Context) -> Result<EncryptHelper> {
let e2ee = context.sql.get_config_int(&context, "e2ee_enabled"); let e2ee = context.sql.get_config_int(&context, "e2ee_enabled");
let prefer_encrypt = if 0 != e2ee.unwrap_or_default() { let prefer_encrypt = if 0 != e2ee.unwrap_or_default() {
@@ -72,7 +64,6 @@ impl EncryptHelper {
} }
}; };
Ok(EncryptHelper { Ok(EncryptHelper {
cdata_to_free: None,
prefer_encrypt: prefer_encrypt, prefer_encrypt: prefer_encrypt,
addr: addr, addr: addr,
public_key: public_key, public_key: public_key,
@@ -87,8 +78,7 @@ impl EncryptHelper {
pub fn try_encrypt( pub fn try_encrypt(
&mut self, &mut self,
context: &Context, factory: &mut MimeFactory,
recipients_addr: &Vec<String>,
e2ee_guaranteed: bool, e2ee_guaranteed: bool,
min_verified: libc::c_int, min_verified: libc::c_int,
do_gossip: bool, do_gossip: bool,
@@ -104,11 +94,12 @@ impl EncryptHelper {
return Ok(false); return Ok(false);
} }
let context = &factory.context;
let mut keyring = Keyring::default(); let mut keyring = Keyring::default();
let mut gossip_headers: Vec<String> = Vec::with_capacity(recipients_addr.len()); let mut gossip_headers: Vec<String> = Vec::with_capacity(factory.recipients_addr.len());
// determine if we can and should encrypt // determine if we can and should encrypt
for recipient_addr in recipients_addr.iter() { for recipient_addr in factory.recipients_addr.iter() {
if *recipient_addr == self.addr { if *recipient_addr == self.addr {
continue; continue;
} }
@@ -175,7 +166,7 @@ impl EncryptHelper {
part_to_encrypt, part_to_encrypt,
); );
for header in gossip_headers { for header in &gossip_headers {
wrapmime::new_custom_field(imffields_encrypted, "Autocrypt-Gossip", &header) wrapmime::new_custom_field(imffields_encrypted, "Autocrypt-Gossip", &header)
} }
@@ -244,9 +235,11 @@ impl EncryptHelper {
mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
let mut col: libc::c_int = 0i32; let mut col: libc::c_int = 0i32;
mailmime_write_mem(plain, &mut col, message_to_encrypt); mailmime_write_mem(plain, &mut col, message_to_encrypt);
mailmime_free(message_to_encrypt);
if (*plain).str_0.is_null() || (*plain).len <= 0 { if (*plain).str_0.is_null() || (*plain).len <= 0 {
bail!("could not write/allocate"); bail!("could not write/allocate");
} }
let ctext = dc_pgp_pk_encrypt( let ctext = dc_pgp_pk_encrypt(
std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len), std::slice::from_raw_parts((*plain).str_0 as *const u8, (*plain).len),
&keyring, &keyring,
@@ -274,20 +267,19 @@ impl EncryptHelper {
); );
mailmime_smart_add_part(encrypted_part, version_mime); mailmime_smart_add_part(encrypted_part, version_mime);
let ctext_bytes = ctext_v.len(); // we assume that ctext_v is not dropped until the end
let ctext = ctext_v.strdup(); // of this if-scope
self.cdata_to_free = Some(Box::new(ctext));
let ctext_part: *mut mailmime = new_data_part( let ctext_part: *mut mailmime = new_data_part(
ctext as *mut libc::c_void, ctext_v.as_ptr() as *mut libc::c_void,
ctext_bytes, ctext_v.len(),
"application/octet-stream", "application/octet-stream",
MAILMIME_MECHANISM_7BIT as i32, MAILMIME_MECHANISM_7BIT as i32,
); );
mailmime_smart_add_part(encrypted_part, ctext_part); mailmime_smart_add_part(encrypted_part, ctext_part);
(*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part;
(*encrypted_part).mm_parent = in_out_message; (*encrypted_part).mm_parent = in_out_message;
mailmime_free(message_to_encrypt); let gossiped = !&gossip_headers.is_empty();
factory.finalize_mime_message(in_out_message, true, gossiped)?;
Ok(true) Ok(true)
} else { } else {
bail!("encryption failed") bail!("encryption failed")