summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/Cargo.toml14
-rw-r--r--ipc/examples/gpg-agent-decrypt.rs16
-rw-r--r--ipc/examples/gpg-agent-sign.rs2
-rw-r--r--ipc/src/assuan/mod.rs17
-rw-r--r--ipc/src/gnupg.rs26
-rw-r--r--ipc/src/lib.rs120
-rw-r--r--ipc/tests/gpg-agent.rs47
7 files changed, 170 insertions, 72 deletions
diff --git a/ipc/Cargo.toml b/ipc/Cargo.toml
index 745e4d9d..d74bfd6e 100644
--- a/ipc/Cargo.toml
+++ b/ipc/Cargo.toml
@@ -1,13 +1,13 @@
[package]
name = "sequoia-ipc"
description = "Interprocess communication infrastructure for Sequoia"
-version = "0.15.0"
+version = "0.17.0"
authors = [
"Justus Winter <justus@sequoia-pgp.org>",
"Kai Michaelis <kai@sequoia-pgp.org>",
"Neal H. Walfield <neal@sequoia-pgp.org>",
]
-documentation = "https://docs.sequoia-pgp.org/0.15.0/sequoia_ipc"
+documentation = "https://docs.sequoia-pgp.org/0.17.0/sequoia_ipc"
build = "build.rs"
homepage = "https://sequoia-pgp.org/"
repository = "https://gitlab.com/sequoia-pgp/sequoia"
@@ -20,8 +20,8 @@ gitlab = { repository = "sequoia-pgp/sequoia" }
maintenance = { status = "actively-developed" }
[dependencies]
-sequoia-openpgp = { path = "../openpgp", version = "0.15" }
-sequoia-core = { path = "../core", version = "0.15" }
+sequoia-openpgp = { path = "../openpgp", version = "0.17" }
+sequoia-core = { path = "../core", version = "0.17" }
anyhow = "1"
capnp-rpc = "0.10"
@@ -36,6 +36,12 @@ thiserror = "1"
tokio = "0.1"
tokio-core = "0.1"
tokio-io = "0.1.4"
+parity-tokio-ipc = "0.4"
+socket2 = "= 0.3.11"
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", default-features = false, features = ["winsock2"] }
+ctor = "0.1"
[build-dependencies]
lalrpop = "0.17"
diff --git a/ipc/examples/gpg-agent-decrypt.rs b/ipc/examples/gpg-agent-decrypt.rs
index bd524e80..76be71db 100644
--- a/ipc/examples/gpg-agent-decrypt.rs
+++ b/ipc/examples/gpg-agent-decrypt.rs
@@ -15,7 +15,7 @@ use crate::openpgp::parse::{
Parse,
stream::{
DecryptionHelper,
- Decryptor,
+ DecryptorBuilder,
VerificationHelper,
GoodChecksum,
VerificationError,
@@ -56,9 +56,8 @@ fn main() {
}).collect();
// Now, create a decryptor with a helper using the given Certs.
- let mut decryptor =
- Decryptor::from_reader(p, io::stdin(), Helper::new(&ctx, p, certs), None)
- .unwrap();
+ let mut decryptor = DecryptorBuilder::from_reader(io::stdin()).unwrap()
+ .with_policy(p, None, Helper::new(&ctx, p, certs)).unwrap();
// Finally, stream the decrypted data to stdout.
io::copy(&mut decryptor, &mut io::stdout())
@@ -101,14 +100,15 @@ impl<'a> DecryptionHelper for Helper<'a> {
sym_algo: Option<SymmetricAlgorithm>,
mut decrypt: D)
-> openpgp::Result<Option<openpgp::Fingerprint>>
- where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()>
+ where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
{
// Try each PKESK until we succeed.
for pkesk in pkesks {
if let Some(key) = self.keys.get(pkesk.recipient()) {
let mut pair = KeyPair::new(self.ctx, key)?;
- if let Ok(_) = pkesk.decrypt(&mut pair, sym_algo)
- .and_then(|(algo, session_key)| decrypt(algo, &session_key))
+ if pkesk.decrypt(&mut pair, sym_algo)
+ .map(|(algo, session_key)| decrypt(algo, &session_key))
+ .unwrap_or(false)
{
break;
}
@@ -121,7 +121,7 @@ impl<'a> DecryptionHelper for Helper<'a> {
}
impl<'a> VerificationHelper for Helper<'a> {
- fn get_public_keys(&mut self, _ids: &[openpgp::KeyHandle])
+ fn get_certs(&mut self, _ids: &[openpgp::KeyHandle])
-> openpgp::Result<Vec<openpgp::Cert>> {
Ok(Vec::new()) // Feed the Certs to the verifier here.
}
diff --git a/ipc/examples/gpg-agent-sign.rs b/ipc/examples/gpg-agent-sign.rs
index 5bad17cd..2991089a 100644
--- a/ipc/examples/gpg-agent-sign.rs
+++ b/ipc/examples/gpg-agent-sign.rs
@@ -51,7 +51,7 @@ fn main() {
// Compose a writer stack corresponding to the output format and
// packet structure we want. First, we want the output to be
// ASCII armored.
- let sink = armor::Writer::new(io::stdout(), armor::Kind::Message, &[])
+ let sink = armor::Writer::new(io::stdout(), armor::Kind::Message)
.expect("Failed to create an armored writer.");
// Stream an OpenPGP message.
diff --git a/ipc/src/assuan/mod.rs b/ipc/src/assuan/mod.rs
index 4234b00e..4b9842c5 100644
--- a/ipc/src/assuan/mod.rs
+++ b/ipc/src/assuan/mod.rs
@@ -10,7 +10,7 @@ use std::path::Path;
use lalrpop_util::ParseError;
use futures::{future, Async, Future, Stream};
-use tokio::net::UnixStream;
+use parity_tokio_ipc::IpcConnection;
use tokio_io::io;
use tokio_io::AsyncRead;
@@ -26,7 +26,7 @@ const MAX_LINE_LENGTH: usize = 1000;
// Load the generated code.
lalrpop_util::lalrpop_mod!(
- #[allow(missing_docs)] grammar, "/assuan/grammar.rs");
+ #[allow(missing_docs, unused_parens)] grammar, "/assuan/grammar.rs");
/// A connection to an Assuan server.
///
@@ -54,15 +54,15 @@ lalrpop_util::lalrpop_mod!(
/// [`Connection::data()`]: #method.data
/// [`Connection::cancel()`]: #method.cancel
pub struct Client {
- r: BufReader<io::ReadHalf<UnixStream>>, // xxx: abstract over
+ r: BufReader<io::ReadHalf<IpcConnection>>, // xxx: abstract over
buffer: Vec<u8>,
done: bool,
w: WriteState,
}
enum WriteState {
- Ready(io::WriteHalf<UnixStream>),
- Sending(future::FromErr<io::WriteAll<io::WriteHalf<tokio::net::UnixStream>, Vec<u8>>, anyhow::Error>),
+ Ready(io::WriteHalf<IpcConnection>),
+ Sending(future::FromErr<io::WriteAll<io::WriteHalf<IpcConnection>, Vec<u8>>, anyhow::Error>),
Transitioning,
Dead,
}
@@ -73,7 +73,10 @@ impl Client {
-> impl Future<Item = Client, Error = anyhow::Error>
where P: AsRef<Path>
{
- UnixStream::connect(path).from_err()
+ // XXX: Implement Windows support using TCP + nonce approach used upstream
+ // https://gnupg.org/documentation/manuals/assuan.pdf#Socket%20wrappers
+ future::result(IpcConnection::connect(path, &Default::default()))
+ .map_err(Into::into)
.and_then(ConnectionFuture::new)
}
@@ -185,7 +188,7 @@ impl Client {
struct ConnectionFuture(Option<Client>);
impl ConnectionFuture {
- fn new(c: UnixStream) -> Self {
+ fn new(c: IpcConnection) -> Self {
let (r, w) = c.split();
let buffer = Vec::with_capacity(MAX_LINE_LENGTH);
Self(Some(Client {
diff --git a/ipc/src/gnupg.rs b/ipc/src/gnupg.rs
index 4ab52d65..4b565553 100644
--- a/ipc/src/gnupg.rs
+++ b/ipc/src/gnupg.rs
@@ -3,6 +3,7 @@
#![warn(missing_docs)]
use std::collections::BTreeMap;
+use std::convert::TryFrom;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::process::Command;
@@ -285,7 +286,7 @@ impl Agent {
pub fn sign<'a, R>(&'a mut self,
key: &'a Key<key::PublicParts, R>,
algo: HashAlgorithm, digest: &'a [u8])
- -> impl Future<Item = crypto::mpis::Signature,
+ -> impl Future<Item = crypto::mpi::Signature,
Error = anyhow::Error> + 'a
where R: key::KeyRole
{
@@ -296,7 +297,7 @@ impl Agent {
/// by the agent.
pub fn decrypt<'a, R>(&'a mut self,
key: &'a Key<key::PublicParts, R>,
- ciphertext: &'a crypto::mpis::Ciphertext)
+ ciphertext: &'a crypto::mpi::Ciphertext)
-> impl Future<Item = crypto::SessionKey,
Error = anyhow::Error> + 'a
where R: key::KeyRole
@@ -307,14 +308,15 @@ impl Agent {
/// Computes options that we want to communicate.
fn options() -> Vec<String> {
use std::env::var;
- use std::ffi::CStr;
let mut r = Vec::new();
if let Ok(tty) = var("GPG_TTY") {
r.push(format!("OPTION ttyname={}", tty));
} else {
+ #[cfg(unix)]
unsafe {
+ use std::ffi::CStr;
let tty = libc::ttyname(0);
if ! tty.is_null() {
if let Ok(tty) = CStr::from_ptr(tty).to_str() {
@@ -404,7 +406,7 @@ fn protocol_error<T>(response: &assuan::Response) -> Result<T> {
impl<'a, 'b, 'c, R> Future for SigningRequest<'a, 'b, 'c, R>
where R: key::KeyRole
{
- type Item = crypto::mpis::Signature;
+ type Item = crypto::mpi::Signature;
type Error = anyhow::Error;
fn poll(&mut self) -> std::result::Result<Async<Self::Item>, Self::Error> {
@@ -518,7 +520,7 @@ struct DecryptionRequest<'a, 'b, 'c, R>
{
c: &'a mut assuan::Client,
key: &'b Key<key::PublicParts, R>,
- ciphertext: &'c crypto::mpis::Ciphertext,
+ ciphertext: &'c crypto::mpi::Ciphertext,
options: Vec<String>,
state: DecryptionRequestState,
}
@@ -528,7 +530,7 @@ impl<'a, 'b, 'c, R> DecryptionRequest<'a, 'b, 'c, R>
{
fn new(c: &'a mut assuan::Client,
key: &'b Key<key::PublicParts, R>,
- ciphertext: &'c crypto::mpis::Ciphertext)
+ ciphertext: &'c crypto::mpi::Ciphertext)
-> Self {
Self {
c,
@@ -629,7 +631,7 @@ impl<'a, 'b, 'c, R> Future for DecryptionRequest<'a, 'b, 'c, R>
},
Async::Ready(None) => {
let mut buf = Vec::new();
- Sexp::from_ciphertext(&self.ciphertext)?
+ Sexp::try_from(self.ciphertext)?
.serialize(&mut buf)?;
self.c.data(&buf)?;
self.state = Inquire(Vec::new(), true);
@@ -699,7 +701,7 @@ impl<'a> KeyPair<'a> {
where R: key::KeyRole
{
Ok(KeyPair {
- public: key.mark_role_unspecified_ref(),
+ public: key.role_as_unspecified(),
agent_socket: ctx.socket("agent")?.into(),
})
}
@@ -711,10 +713,10 @@ impl<'a> crypto::Signer for KeyPair<'a> {
}
fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
- -> openpgp::Result<openpgp::crypto::mpis::Signature>
+ -> openpgp::Result<openpgp::crypto::mpi::Signature>
{
use crate::openpgp::types::PublicKeyAlgorithm::*;
- use crate::openpgp::crypto::mpis::PublicKey;
+ use crate::openpgp::crypto::mpi::PublicKey;
#[allow(deprecated)]
match (self.public.pk_algo(), self.public.mpis())
@@ -741,11 +743,11 @@ impl<'a> crypto::Decryptor for KeyPair<'a> {
self.public
}
- fn decrypt(&mut self, ciphertext: &crypto::mpis::Ciphertext,
+ fn decrypt(&mut self, ciphertext: &crypto::mpi::Ciphertext,
_plaintext_len: Option<usize>)
-> openpgp::Result<crypto::SessionKey>
{
- use crate::openpgp::crypto::mpis::{PublicKey, Ciphertext};
+ use crate::openpgp::crypto::mpi::{PublicKey, Ciphertext};
match (self.public.mpis(), ciphertext) {
(PublicKey::RSA { .. }, Ciphertext::RSA { .. })
diff --git a/ipc/src/lib.rs b/ipc/src/lib.rs
index 623aa66d..7e6a62ab 100644
--- a/ipc/src/lib.rs
+++ b/ipc/src/lib.rs
@@ -41,7 +41,7 @@ use std::io::{self, Read, Write};
use std::net::{Ipv4Addr, SocketAddr, TcpStream, TcpListener};
use std::path::PathBuf;
-use anyhow::Result;
+use anyhow::{anyhow, Result};
use fs2::FileExt;
use futures::{Future, Stream};
@@ -52,11 +52,12 @@ use tokio_io::AsyncRead;
use capnp_rpc::{RpcSystem, twoparty};
use capnp_rpc::rpc_twoparty_capnp::Side;
-/* Unix-specific options. */
-use std::os::unix::io::{IntoRawFd, FromRawFd};
-use std::os::unix::fs::OpenOptionsExt;
-
-/* XXX: Implement Windows support. */
+#[cfg(unix)]
+use std::os::unix::{io::{IntoRawFd, FromRawFd}, fs::OpenOptionsExt};
+#[cfg(windows)]
+use std::os::windows::io::{AsRawSocket, IntoRawSocket, FromRawSocket};
+#[cfg(windows)]
+use winapi::um::winsock2;
use std::process::{Command, Stdio};
use std::thread;
@@ -68,6 +69,21 @@ use sequoia_core as core;
pub mod assuan;
pub mod gnupg;
+macro_rules! platform {
+ { unix => { $($unix:tt)* }, windows => { $($windows:tt)* } } => {
+ if cfg!(unix) {
+ #[cfg(unix)] { $($unix)* }
+ #[cfg(not(unix))] { unreachable!() }
+ } else if cfg!(windows) {
+ #[cfg(windows)] { $($windows)* }
+ #[cfg(not(windows))] { unreachable!() }
+ } else {
+ #[cfg(not(any(unix, windows)))] compile_error!("Unsupported platform");
+ unreachable!()
+ }
+ }
+}
+
/// Servers need to implement this trait.
pub trait Handler {
/// Called on every connection.
@@ -139,12 +155,14 @@ impl Descriptor {
};
fs::create_dir_all(self.ctx.home())?;
- let mut file = fs::OpenOptions::new()
+ let mut file = fs::OpenOptions::new();
+ file
.read(true)
.write(true)
- .create(true)
- .mode(0o600)
- .open(&self.rendezvous)?;
+ .create(true);
+ #[cfg(unix)]
+ file.mode(0o600);
+ let mut file = file.open(&self.rendezvous)?;
file.lock_exclusive()?;
let mut c = vec![];
@@ -205,17 +223,44 @@ impl Descriptor {
}
fn fork(&self, listener: TcpListener) -> Result<()> {
- Command::new(&self.executable)
+ let mut cmd = Command::new(&self.executable);
+ cmd
.arg("--home")
.arg(self.ctx.home())
.arg("--lib")
.arg(self.ctx.lib())
.arg("--ephemeral")
.arg(self.ctx.ephemeral().to_string())
- .stdin(unsafe { Stdio::from_raw_fd(listener.into_raw_fd()) })
.stdout(Stdio::null())
- .stderr(Stdio::null())
- .spawn()?;
+ .stderr(Stdio::null());
+
+ platform! {
+ unix => {
+ // Pass the listening TCP socket as child stdin.
+ cmd.stdin(unsafe { Stdio::from_raw_fd(listener.into_raw_fd()) });
+ },
+ windows => {
+ // Sockets for `TcpListener` are not inheritable by default, so
+ // let's make them so, since we'll pass them to a child process.
+ unsafe {
+ match winapi::um::handleapi::SetHandleInformation(
+ listener.as_raw_socket() as _,
+ winapi::um::winbase::HANDLE_FLAG_INHERIT,
+ winapi::um::winbase::HANDLE_FLAG_INHERIT,
+ ) {
+ 0 => Err(std::io::Error::last_os_error()),
+ _ => Ok(())
+ }?
+ };
+ // We can't pass the socket to stdin directly on Windows, since
+ // non-overlapped (blocking) I/O handles can be redirected there.
+ // We use Tokio (async I/O), so we just pass it via env var rather
+ // than establishing a separate channel to pass the socket through.
+ cmd.env("SOCKET", format!("{}", listener.into_raw_socket()));
+ }
+ }
+
+ cmd.spawn()?;
Ok(())
}
@@ -253,7 +298,7 @@ impl Server {
if args.len() != 7 || args[1] != "--home"
|| args[3] != "--lib" || args[5] != "--ephemeral" {
- return Err(anyhow::anyhow!(
+ return Err(anyhow!(
"Usage: {} --home <HOMEDIR> --lib <LIBDIR> \
--ephemeral true|false", args[0]));
}
@@ -266,7 +311,7 @@ impl Server {
cfg.set_ephemeral();
}
} else {
- return Err(anyhow::anyhow!(
+ return Err(anyhow!(
"Expected 'true' or 'false' for --ephemeral, got: {}",
args[6]));
}
@@ -276,8 +321,11 @@ impl Server {
/// Turns this process into a server.
///
- /// External servers must call this early on. Expects 'stdin' to
- /// be a listening TCP socket.
+ /// External servers must call this early on.
+ ///
+ /// On Linux expects 'stdin' to be a listening TCP socket.
+ /// On Windows this expects `SOCKET` env var to be set to a listening socket
+ /// of the Windows Sockets API `SOCKET` value.
///
/// # Example
///
@@ -299,7 +347,14 @@ impl Server {
/// }
/// ```
pub fn serve(&mut self) -> Result<()> {
- self.serve_listener(unsafe { TcpListener::from_raw_fd(0) })
+ let listener = platform! {
+ unix => { unsafe { TcpListener::from_raw_fd(0) } },
+ windows => {
+ let socket = std::env::var("SOCKET")?.parse()?;
+ unsafe { TcpListener::from_raw_socket(socket) }
+ }
+ };
+ self.serve_listener(listener)
}
fn serve_listener(&mut self, l: TcpListener) -> Result<()> {
@@ -427,3 +482,30 @@ pub enum Error {
#[error("Connection closed unexpectedly.")]
ConnectionClosed(Vec<u8>),
}
+
+// Global initialization and cleanup of the Windows Sockets API (WSA) module.
+// NOTE: This has to be top-level in order for `ctor::{ctor, dtor}` to work.
+#[cfg(windows)]
+use std::sync::atomic::{AtomicBool, Ordering};
+#[cfg(windows)]
+static WSA_INITED: AtomicBool = AtomicBool::new(false);
+
+#[cfg(windows)]
+#[ctor::ctor]
+fn wsa_startup() {
+ unsafe {
+ let ret = winsock2::WSAStartup(
+ 0x202, // version 2.2
+ &mut std::mem::zeroed(),
+ );
+ WSA_INITED.store(ret != 0, Ordering::SeqCst);
+ }
+}
+
+#[cfg(windows)]
+#[ctor::dtor]
+fn wsa_cleanup() {
+ if WSA_INITED.load(Ordering::SeqCst) {
+ let _ = unsafe { winsock2::WSACleanup() };
+ }
+}
diff --git a/ipc/tests/gpg-agent.rs b/ipc/tests/gpg-agent.rs
index 45c532e6..c303cdd4 100644
--- a/ipc/tests/gpg-agent.rs
+++ b/ipc/tests/gpg-agent.rs
@@ -12,7 +12,7 @@ use crate::openpgp::types::{
SymmetricAlgorithm,
};
use crate::openpgp::crypto::SessionKey;
-use crate::openpgp::parse::stream::*;
+use crate::openpgp::parse::{Parse, stream::*};
use crate::openpgp::serialize::{Serialize, stream::*};
use crate::openpgp::cert::prelude::*;
use crate::openpgp::policy::Policy;
@@ -27,7 +27,7 @@ macro_rules! make_context {
Err(e) => {
eprintln!("SKIP: Failed to create GnuPG context: {}\n\
SKIP: Is GnuPG installed?", e);
- return;
+ return Ok(());
},
};
match ctx.start("gpg-agent") {
@@ -35,7 +35,7 @@ macro_rules! make_context {
Err(e) => {
eprintln!("SKIP: Failed to create GnuPG context: {}\n\
SKIP: Is the GnuPG agent installed?", e);
- return;
+ return Ok(());
},
}
ctx
@@ -43,23 +43,25 @@ macro_rules! make_context {
}
#[test]
-fn nop() {
+fn nop() -> openpgp::Result<()> {
let ctx = make_context!();
let mut agent = Agent::connect(&ctx).wait().unwrap();
agent.send("NOP").unwrap();
let response = agent.wait().collect::<Vec<_>>();
assert_eq!(response.len(), 1);
assert!(response[0].is_ok());
+ Ok(())
}
#[test]
-fn help() {
+fn help() -> openpgp::Result<()> {
let ctx = make_context!();
let mut agent = Agent::connect(&ctx).wait().unwrap();
agent.send("HELP").unwrap();
let response = agent.wait().collect::<Vec<_>>();
assert!(response.len() > 3);
assert!(response.iter().last().unwrap().is_ok());
+ Ok(())
}
const MESSAGE: &'static str = "дружба";
@@ -79,7 +81,7 @@ fn gpg_import(ctx: &Context, what: &[u8]) {
}
#[test]
-fn sign() {
+fn sign() -> openpgp::Result<()> {
use self::CipherSuite::*;
use openpgp::policy::StandardPolicy as P;
@@ -131,8 +133,8 @@ fn sign() {
let helper = Helper { cert: &cert };
// Now, create a verifier with a helper using the given Certs.
- let mut verifier =
- Verifier::from_bytes(p, &message, helper, None).unwrap();
+ let mut verifier = VerifierBuilder::from_bytes(&message)?
+ .with_policy(p, None, helper)?;
// Verify the data.
let mut sink = Vec::new();
@@ -145,7 +147,7 @@ fn sign() {
}
impl<'a> VerificationHelper for Helper<'a> {
- fn get_public_keys(&mut self, _ids: &[openpgp::KeyHandle])
+ fn get_certs(&mut self, _ids: &[openpgp::KeyHandle])
-> openpgp::Result<Vec<openpgp::Cert>> {
// Return public keys for signature verification here.
Ok(vec![self.cert.clone()])
@@ -184,10 +186,11 @@ fn sign() {
}
}
}
+ Ok(())
}
#[test]
-fn decrypt() {
+fn decrypt() -> openpgp::Result<()> {
use self::CipherSuite::*;
use openpgp::policy::StandardPolicy as P;
@@ -207,18 +210,19 @@ fn decrypt() {
let mut message = Vec::new();
{
- let recipient =
+ let recipients =
cert.keys().with_policy(p, None).alive().revoked(false)
.for_transport_encryption()
- .map(|ka| ka.key().into())
- .nth(0).unwrap();
+ .map(|ka| ka.key())
+ .collect::<Vec<_>>();
// Start streaming an OpenPGP message.
let message = Message::new(&mut message);
// We want to encrypt a literal data packet.
let encryptor =
- Encryptor::for_recipient(message, recipient).build().unwrap();
+ Encryptor::for_recipients(message, recipients)
+ .build().unwrap();
// Emit a literal data packet.
let mut literal_writer = LiteralWriter::new(
@@ -237,8 +241,8 @@ fn decrypt() {
let helper = Helper { policy: p, ctx: &ctx, cert: &cert, };
// Now, create a decryptor with a helper using the given Certs.
- let mut decryptor = Decryptor::from_bytes(p, &message, helper, None)
- .unwrap();
+ let mut decryptor = DecryptorBuilder::from_bytes(&message).unwrap()
+ .with_policy(p, None, helper).unwrap();
// Decrypt the data.
let mut sink = Vec::new();
@@ -252,7 +256,7 @@ fn decrypt() {
}
impl<'a> VerificationHelper for Helper<'a> {
- fn get_public_keys(&mut self, _ids: &[openpgp::KeyHandle])
+ fn get_certs(&mut self, _ids: &[openpgp::KeyHandle])
-> openpgp::Result<Vec<openpgp::Cert>> {
// Return public keys for signature verification here.
Ok(Vec::new())
@@ -272,8 +276,7 @@ fn decrypt() {
sym_algo: Option<SymmetricAlgorithm>,
mut decrypt: D)
-> openpgp::Result<Option<openpgp::Fingerprint>>
- where D: FnMut(SymmetricAlgorithm, &SessionKey) ->
- openpgp::Result<()>
+ where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
{
let mut keypair = KeyPair::new(
self.ctx,
@@ -283,11 +286,13 @@ fn decrypt() {
.unwrap();
pkesks[0].decrypt(&mut keypair, sym_algo)
- .and_then(|(algo, session_key)| decrypt(algo, &session_key))
- .map(|_| None)
+ .map(|(algo, session_key)| decrypt(algo, &session_key));
+
// XXX: In production code, return the Fingerprint of the
// recipient's Cert here
+ Ok(None)
}
}
}
+ Ok(())
}