summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi
diff options
context:
space:
mode:
authorAzul <azul@riseup.net>2020-12-09 20:26:52 +0100
committerAzul <azul@riseup.net>2020-12-10 13:57:19 +0100
commit227db80b9d40526387f1e4a64f90464618fb885b (patch)
treebcf1ab1ed4d61fffea8d382872262650c5f49d86 /openpgp-ffi
parent80b59ecf7b33dcd2392eee8b4e2def4101410749 (diff)
buffered-reader: Require Cookies to be Send and Sync.
- This way the entire `BufferedReader<C>` will be `Send` and `Sync`. - Modify all other crates accordingly. - See #615.
Diffstat (limited to 'openpgp-ffi')
-rw-r--r--openpgp-ffi/include/sequoia/io.h8
-rw-r--r--openpgp-ffi/include/sequoia/openpgp.h18
-rw-r--r--openpgp-ffi/src/io.rs25
-rw-r--r--openpgp-ffi/src/parse/stream.rs49
4 files changed, 82 insertions, 18 deletions
diff --git a/openpgp-ffi/include/sequoia/io.h b/openpgp-ffi/include/sequoia/io.h
index e574aefb..35c397dc 100644
--- a/openpgp-ffi/include/sequoia/io.h
+++ b/openpgp-ffi/include/sequoia/io.h
@@ -36,7 +36,13 @@ typedef ssize_t (*pgp_reader_cb_t) (void *cookie, const void *buf, size_t len);
/*/
/// Creates an reader from a callback and cookie.
///
-/// This reader calls the given callback to write data.
+/// This reader calls the given callback to read data.
+///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callback and cookie support that as well.
/*/
pgp_reader_t pgp_reader_from_callback (pgp_reader_cb_t, void *);
diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h
index cb6bc31d..82506efd 100644
--- a/openpgp-ffi/include/sequoia/openpgp.h
+++ b/openpgp-ffi/include/sequoia/openpgp.h
@@ -1999,6 +1999,12 @@ bool pgp_verification_result_bad_signature (pgp_verification_result_t,
/// first parameter to each of them.
///
/// Note: all of the parameters are required; none may be NULL.
+///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callbacks and cookie support that as well.
/*/
pgp_reader_t pgp_decryptor_new (pgp_error_t *errp,
pgp_policy_t policy,
@@ -2014,6 +2020,12 @@ pgp_reader_t pgp_decryptor_new (pgp_error_t *errp,
///
/// No attempt is made to decrypt any encryption packets. These are
/// treated as opaque containers.
+///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callbacks and cookie support that as well.
/*/
pgp_reader_t pgp_verifier_new (pgp_error_t *errp,
pgp_policy_t policy,
@@ -2025,6 +2037,12 @@ pgp_reader_t pgp_verifier_new (pgp_error_t *errp,
/*/
/// Verifies a detached OpenPGP signature.
+///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callbacks and cookie support that as well.
/*/
pgp_detached_verifier_t pgp_detached_verifier_new (pgp_error_t *errp,
pgp_policy_t policy,
diff --git a/openpgp-ffi/src/io.rs b/openpgp-ffi/src/io.rs
index 484615cf..3c5668d6 100644
--- a/openpgp-ffi/src/io.rs
+++ b/openpgp-ffi/src/io.rs
@@ -26,7 +26,7 @@ pub struct Reader(ReaderKind);
/// In some cases, we want to call functions on concrete types. To
/// avoid nasty hacks, we have specialized variants for that.
pub(crate) enum ReaderKind {
- Generic(Box<dyn io::Read>),
+ Generic(Box<dyn io::Read + Send + Sync>),
Armored(openpgp::armor::Reader<'static>),
}
@@ -80,26 +80,39 @@ type ReaderCallbackFn = extern fn(*mut c_void, *const c_void, size_t) -> ssize_t
/// Creates an reader from a callback and cookie.
///
/// This reader calls the given callback to write data.
+///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callback and cookie support that as well.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_reader_from_callback(cb: ReaderCallbackFn,
cookie: *mut c_void)
-> *mut Reader {
- let r: Box<dyn io::Read> = Box::new(ReaderCallback {
- cb, cookie,
- });
+ let r: Box<dyn io::Read + Send + Sync> =
+ Box::new(ReaderCallback(Mutex::new(ReaderClosure {
+ cb, cookie,
+ })));
ReaderKind::Generic(r).move_into_raw()
}
/// A generic callback-based reader implementation.
-struct ReaderCallback {
+struct ReaderCallback(Mutex<ReaderClosure>);
+
+struct ReaderClosure {
cb: ReaderCallbackFn,
cookie: *mut c_void,
}
+unsafe impl Send for ReaderClosure {}
+
impl Read for ReaderCallback {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ let closure = self.0.get_mut().expect("Mutex not to be poisoned");
let r =
- (self.cb)(self.cookie, buf.as_mut_ptr() as *mut c_void, buf.len());
+ (closure.cb)(closure.cookie,
+ buf.as_mut_ptr() as *mut c_void, buf.len());
if r < 0 {
use std::io as stdio;
Err(stdio::Error::new(stdio::ErrorKind::Other,
diff --git a/openpgp-ffi/src/parse/stream.rs b/openpgp-ffi/src/parse/stream.rs
index 747452a0..16fb1829 100644
--- a/openpgp-ffi/src/parse/stream.rs
+++ b/openpgp-ffi/src/parse/stream.rs
@@ -11,6 +11,7 @@
//! [`sequoia-openpgp::parse::stream`]: ../../../../sequoia_openpgp/parse/stream/index.html
use std::ptr;
+use std::sync::Mutex;
use libc::{c_int, c_void, time_t};
use sequoia_openpgp as openpgp;
@@ -430,13 +431,16 @@ type CheckCallback = extern fn(*mut HelperCookie,
-> Status;
// This fetches keys and computes the validity of the verification.
-struct VHelper {
+struct VHelper(Mutex<VHelperClosure>);
+struct VHelperClosure {
inspect_cb: Option<InspectCallback>,
get_certs_cb: GetPublicKeysCallback,
check_signatures_cb: CheckCallback,
cookie: *mut HelperCookie,
}
+unsafe impl Send for VHelperClosure {}
+
impl VHelper {
fn new(inspect_cb: Option<InspectCallback>,
get_certs: GetPublicKeysCallback,
@@ -444,19 +448,20 @@ impl VHelper {
cookie: *mut HelperCookie)
-> Self
{
- VHelper {
+ VHelper(Mutex::new(VHelperClosure {
inspect_cb,
get_certs_cb: get_certs,
check_signatures_cb: check_signatures,
- cookie,
- }
+ cookie: cookie,
+ }))
}
}
impl VerificationHelper for VHelper {
fn inspect(&mut self, pp: &PacketParser) -> openpgp::Result<()> {
- if let Some(cb) = self.inspect_cb {
- match cb(self.cookie, pp) {
+ let closure = self.0.get_mut().expect("Mutex not to be poisoned");
+ if let Some(cb) = closure.inspect_cb {
+ match cb(closure.cookie, pp) {
Status::Success => Ok(()),
// XXX: Convert the status to an error better.
status => Err(anyhow::anyhow!(
@@ -481,8 +486,9 @@ impl VerificationHelper for VHelper {
let mut free : FreeCallback = |_| {};
- let result = (self.get_certs_cb)(
- self.cookie,
+ let closure = self.0.get_mut().expect("Mutex not to be poisoned");
+ let result = (closure.get_certs_cb)(
+ closure.cookie,
ids.as_ptr(), ids.len(),
&mut cert_refs_raw, &mut cert_refs_raw_len as *mut usize,
&mut free);
@@ -515,8 +521,9 @@ impl VerificationHelper for VHelper {
fn check(&mut self, structure: stream::MessageStructure)
-> Result<(), anyhow::Error>
{
- let result = (self.check_signatures_cb)(self.cookie,
- structure.move_into_raw());
+ let closure = self.0.get_mut().expect("Mutex not to be poisoned");
+ let result = (closure.check_signatures_cb)(closure.cookie,
+ structure.move_into_raw());
if result != Status::Success {
// XXX: We need to convert the status to an error. A
// status contains less information, but we should do the
@@ -535,6 +542,12 @@ impl VerificationHelper for VHelper {
/// No attempt is made to decrypt any encryption packets. These are
/// treated as opaque containers.
///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callbacks and cookie support that as well.
+///
/// # Examples
///
/// ```c
@@ -663,6 +676,12 @@ pub struct DetachedVerifier(openpgp::parse::stream::DetachedVerifier<'static, VH
/// Verifies a detached OpenPGP signature.
///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callbacks and cookie support that as well.
+///
/// # Examples
///
/// ```c
@@ -871,8 +890,10 @@ impl DecryptionHelper for DHelper {
(*closure)(algo.into(), sk.ref_raw())
}
+ let closure =
+ self.vhelper.0.get_mut().expect("Mutex not to be poisoned");
let result = (self.decrypt_cb)(
- self.vhelper.cookie,
+ closure.cookie,
pkesks.as_ptr(), pkesks.len(), skesks.as_ptr(), skesks.len(),
sym_algo.map(|s| u8::from(s)).unwrap_or(0),
trampoline::<D>,
@@ -904,6 +925,12 @@ impl DecryptionHelper for DHelper {
///
/// Note: all of the parameters are required; none may be NULL.
///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callbacks and cookie support that as well.
+///
/// # Examples
///
/// ```c