/* * meli * * Copyright 2019 Manos Pitsidianakis * * This file is part of meli. * * meli is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * meli is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with meli. If not, see . */ use melib::email::{ attachment_types::{ContentDisposition, ContentType, MultipartType}, pgp as melib_pgp, Attachment, AttachmentBuilder, }; use melib::error::*; use melib::gpgme::*; use melib::parser::BytesExt; use std::future::Future; use std::pin::Pin; pub async fn decrypt(raw: Vec) -> Result<(melib_pgp::DecryptionMetadata, Vec)> { let mut ctx = Context::new()?; let cipher = ctx.new_data_mem(&raw)?; ctx.decrypt(cipher)?.await } pub async fn verify(a: Attachment) -> Result<()> { let (data, sig) = melib_pgp::verify_signature(&a).chain_err_summary(|| "Could not verify signature.")?; let mut ctx = Context::new()?; let sig = ctx.new_data_mem(&sig.body().trim())?; let data = ctx.new_data_mem(&data)?; ctx.verify(sig, data)?.await } pub fn sign_filter( sign_keys: Vec, ) -> Result< impl FnOnce(AttachmentBuilder) -> Pin> + Send>> + Send, > { Ok( move |a: AttachmentBuilder| -> Pin>+Send>> { Box::pin(async move { let a: Attachment = a.into(); let mut ctx = Context::new()?; let data = ctx.new_data_mem(&melib_pgp::convert_attachment_to_rfc_spec( a.into_raw().as_bytes(), ))?; let sig_attachment = Attachment::new( ContentType::PGPSignature, Default::default(), ctx.sign(sign_keys, data)?.await?, ); let a: AttachmentBuilder = a.into(); let parts = vec![a, sig_attachment.into()]; let boundary = ContentType::make_boundary(&parts); Ok(Attachment::new( ContentType::Multipart { boundary: boundary.into_bytes(), kind: MultipartType::Signed, parts: parts.into_iter().map(|a| a.into()).collect::>(), }, Default::default(), Vec::new(), ) .into()) }) }, ) } pub fn encrypt_filter( sign_keys: Option>, encrypt_keys: Vec, ) -> Result< impl FnOnce(AttachmentBuilder) -> Pin> + Send>> + Send, > { Ok( move |a: AttachmentBuilder| -> Pin>+Send>> { Box::pin(async move { let a: Attachment = a.into(); debug!("main attachment is {:?}", &a); let mut ctx = Context::new()?; let data = ctx.new_data_mem( a.into_raw().as_bytes() )?; let sig_attachment = { let mut a = Attachment::new( ContentType::OctetStream { name: None }, Default::default(), ctx.encrypt(sign_keys, encrypt_keys, data)?.await?, ); a.content_disposition = ContentDisposition::from(r#"attachment; filename="msg.asc""#.as_bytes()); a }; let mut a: AttachmentBuilder = AttachmentBuilder::new("Version: 1".as_bytes()); a.set_content_type_from_bytes("application/pgp-encrypted".as_bytes()); a.set_content_disposition(ContentDisposition::from("attachment".as_bytes())); let parts = vec![a, sig_attachment.into()]; let boundary = ContentType::make_boundary(&parts); Ok(Attachment::new( ContentType::Multipart { boundary: boundary.into_bytes(), kind: MultipartType::Encrypted, parts: parts.into_iter().map(|a| a.into()).collect::>(), }, Default::default(), Vec::new(), ) .into()) }) }, ) }