From 488985f8f2e119c553f2d03d8bd87d49f45d8227 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Fri, 3 Apr 2020 21:50:10 +0200 Subject: openpgp: Rename ComponentBundleIter to ComponentAmalgamationIter. - Rename `ComponentBundleIter` to `ComponentAmalgamationIter` and `ValidComponentBundleIter` to `ValidComponentAmalgamationIter`. - Move module from cert::bundle to cert::amalgamation. - Fixes 8ebaf6e4ada1cea0b9e6f6dfee61c22cfdc9748c. --- openpgp-ffi/src/cert.rs | 4 +- openpgp/src/cert/amalgamation.rs | 10 +- openpgp/src/cert/amalgamation/iter.rs | 217 ++++++++++++++++++++++++++++++++++ openpgp/src/cert/bundle.rs | 6 - openpgp/src/cert/bundle/iter.rs | 217 ---------------------------------- openpgp/src/cert/mod.rs | 20 ++-- openpgp/src/cert/prelude.rs | 4 +- 7 files changed, 240 insertions(+), 238 deletions(-) create mode 100644 openpgp/src/cert/amalgamation/iter.rs delete mode 100644 openpgp/src/cert/bundle/iter.rs diff --git a/openpgp-ffi/src/cert.rs b/openpgp-ffi/src/cert.rs index 2d57677f..9516ad75 100644 --- a/openpgp-ffi/src/cert.rs +++ b/openpgp-ffi/src/cert.rs @@ -378,7 +378,7 @@ fn pgp_cert_primary_user_id(cert: *const Cert, policy: *const Policy, /// Wraps a UserIDIter for export via the FFI. pub struct UserIDIterWrapper<'a> { pub(crate) // For serialize.rs. - iter: Option>, + iter: Option>, // Whether next has been called. next_called: bool, } @@ -450,7 +450,7 @@ pub extern "C" fn pgp_cert_user_id_iter_next<'a>( /// Wraps a ValidKeyAmalgamationIter for export via the FFI. pub struct ValidUserIDIterWrapper<'a> { pub(crate) // For serialize.rs. - iter: Option>, + iter: Option>, // Whether next has been called. next_called: bool, } diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs index 0ba7a808..8f5c46e9 100644 --- a/openpgp/src/cert/amalgamation.rs +++ b/openpgp/src/cert/amalgamation.rs @@ -35,11 +35,19 @@ use crate::{ }, }; + +mod iter; +pub use iter::{ + ComponentAmalgamationIter, + ValidComponentAmalgamationIter, +}; + mod keyiter; pub use keyiter::{ KeyAmalgamationIter, ValidKeyAmalgamationIter, }; + mod key; pub use key::{ ErasedKeyAmalgamation, @@ -584,7 +592,7 @@ impl<'a, C> ValidComponentAmalgamation<'a, C> /// Returns the amalgamated primary component at time `time` /// /// If `time` is None, then the current time is used. - /// `ValidComponentBundleIter` for the definition of a valid component. + /// `ValidComponentAmalgamationIter` for the definition of a valid component. /// /// The primary component is determined by taking the components that /// are alive at time `t`, and sorting them as follows: diff --git a/openpgp/src/cert/amalgamation/iter.rs b/openpgp/src/cert/amalgamation/iter.rs new file mode 100644 index 00000000..34eca638 --- /dev/null +++ b/openpgp/src/cert/amalgamation/iter.rs @@ -0,0 +1,217 @@ +use std::slice; +use std::fmt; +use std::time::SystemTime; + +use crate::{ + types::RevocationStatus, + cert::prelude::*, + policy::Policy, +}; + +/// An iterator over all component bundles of a given type in a certificate. +/// +/// `ComponentAmalgamationIter` follows the builder pattern. There is no need to +/// explicitly finalize it, however: it already implements the +/// `Iterator` trait. +/// +/// By default, `ComponentAmalgamationIter` returns each component in turn. +pub struct ComponentAmalgamationIter<'a, C> { + cert: &'a Cert, + iter: slice::Iter<'a, ComponentBundle>, +} + +impl<'a, C> fmt::Debug for ComponentAmalgamationIter<'a, C> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ComponentAmalgamationIter") + .finish() + } +} + +impl<'a, C> Iterator for ComponentAmalgamationIter<'a, C> +{ + type Item = ComponentAmalgamation<'a, C>; + + fn next(&mut self) -> Option { + self.iter.next().map(|c| ComponentAmalgamation::new(self.cert, c)) + } +} + +impl<'a, C> ComponentAmalgamationIter<'a, C> { + /// Returns a new `ComponentAmalgamationIter` instance. + pub(crate) fn new(cert: &'a Cert, + iter: std::slice::Iter<'a, ComponentBundle>) -> Self + where Self: 'a + { + ComponentAmalgamationIter { + cert, iter, + } + } + + /// Changes the iterator to only return components that are valid + /// for the given policy at the specified time. + /// + /// If `time` is None, then the current time is used. + /// + /// See `ValidComponentAmalgamationIter` for the definition of a valid component. + pub fn with_policy(self, policy: &'a dyn Policy, time: T) + -> ValidComponentAmalgamationIter<'a, C> + where T: Into> + { + ValidComponentAmalgamationIter { + cert: self.cert, + iter: self.iter, + time: time.into().unwrap_or_else(SystemTime::now), + policy, + revoked: None, + } + } +} + +/// An iterator over all valid `Component`s of a given type in a +/// certificate. +/// +/// A component is valid at time `t` if it was not created after `t` +/// and it has a live self-signature at time `t`. +/// +/// `ValidComponentAmalgamationIter` follows the builder pattern. There is no +/// need to explicitly finalize it, however: it already implements the +/// `Iterator` trait. +pub struct ValidComponentAmalgamationIter<'a, C> { + // This is an option to make it easier to create an empty ValidComponentAmalgamationIter. + cert: &'a Cert, + iter: slice::Iter<'a, ComponentBundle>, + + policy: &'a dyn Policy, + // The time. + time: SystemTime, + + // If not None, filters by whether the component is revoked or not + // at time `t`. + revoked: Option, +} + +impl<'a, C> fmt::Debug for ValidComponentAmalgamationIter<'a, C> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ValidComponentAmalgamationIter") + .field("time", &self.time) + .field("revoked", &self.revoked) + .finish() + } +} + +impl<'a, C> Iterator for ValidComponentAmalgamationIter<'a, C> + where C: std::fmt::Debug +{ + type Item = ValidComponentAmalgamation<'a, C>; + + fn next(&mut self) -> Option { + tracer!(false, "ValidComponentAmalgamationIter::next", 0); + t!("ValidComponentAmalgamationIter: {:?}", self); + + loop { + let ca = ComponentAmalgamation::new(self.cert, self.iter.next()?); + t!("Considering component: {:?}", ca.component()); + + let vca = match ca.with_policy(self.policy, self.time) { + Ok(vca) => vca, + Err(e) => { + t!("Rejected: {}", e); + continue; + }, + }; + + if let Some(want_revoked) = self.revoked { + if let RevocationStatus::Revoked(_) = vca.revoked() { + // The component is definitely revoked. + if ! want_revoked { + t!("Component revoked... skipping."); + continue; + } + } else { + // The component is probably not revoked. + if want_revoked { + t!("Component not revoked... skipping."); + continue; + } + } + } + + return Some(vca); + } + } +} + +impl<'a, C> ExactSizeIterator for ComponentAmalgamationIter<'a, C> +{ + fn len(&self) -> usize { + self.iter.len() + } +} + +impl<'a, C> ValidComponentAmalgamationIter<'a, C> { + /// Filters by whether a component is definitely revoked. + /// + /// A value of None disables this filter. + /// + /// Note: If you call this function multiple times on the same + /// iterator, only the last value is used. + /// + /// Note: This only checks if the component is not revoked; it does not + /// check whether the certificate not revoked. + /// + /// This filter checks whether a component's revocation status is + /// `RevocationStatus::Revoked` or not. The latter (i.e., + /// `revoked(false)`) is equivalent to: + /// + /// ```rust + /// extern crate sequoia_openpgp as openpgp; + /// # use openpgp::Result; + /// use openpgp::cert::prelude::*; + /// use openpgp::types::RevocationStatus; + /// use sequoia_openpgp::policy::StandardPolicy; + /// + /// # fn main() { f().unwrap(); } + /// # fn f() -> Result<()> { + /// let p = &StandardPolicy::new(); + /// + /// # let (cert, _) = + /// # CertBuilder::general_purpose(None, Some("alice@example.org")) + /// # .generate()?; + /// # let timestamp = None; + /// let non_revoked_uas = cert + /// .user_attributes() + /// .with_policy(p, timestamp) + /// .filter(|ca| { + /// match ca.revoked() { + /// RevocationStatus::Revoked(_) => + /// // It's definitely revoked, skip it. + /// false, + /// RevocationStatus::CouldBe(_) => + /// // There is a designated revoker that we + /// // should check, but don't (or can't). To + /// // avoid a denial of service arising from fake + /// // revocations, we assume that the component has not + /// // been revoked and return it. + /// true, + /// RevocationStatus::NotAsFarAsWeKnow => + /// // We have no evidence to suggest that the component + /// // is revoked. + /// true, + /// } + /// }) + /// .collect::>(); + /// # Ok(()) + /// # } + /// ``` + /// + /// As the example shows, this filter is significantly less + /// flexible than using `ValidComponentAmalgamation::revoked`. + /// However, this filter implements a typical policy, and does not + /// preclude using `filter` to realize alternative policies. + pub fn revoked(mut self, revoked: T) -> Self + where T: Into> + { + self.revoked = revoked.into(); + self + } +} diff --git a/openpgp/src/cert/bundle.rs b/openpgp/src/cert/bundle.rs index 85a36b0e..4bbe9e4f 100644 --- a/openpgp/src/cert/bundle.rs +++ b/openpgp/src/cert/bundle.rs @@ -25,12 +25,6 @@ use super::{ canonical_signature_order, }; -mod iter; -pub use iter::{ - ComponentBundleIter, - ValidComponentBundleIter, -}; - /// A Cert component binding. /// /// A Cert component is a primary key, a subkey, a user id, or a user diff --git a/openpgp/src/cert/bundle/iter.rs b/openpgp/src/cert/bundle/iter.rs deleted file mode 100644 index c40c2de9..00000000 --- a/openpgp/src/cert/bundle/iter.rs +++ /dev/null @@ -1,217 +0,0 @@ -use std::slice; -use std::fmt; -use std::time::SystemTime; - -use crate::{ - types::RevocationStatus, - cert::prelude::*, - policy::Policy, -}; - -/// An iterator over all component bundles of a given type in a certificate. -/// -/// `ComponentBundleIter` follows the builder pattern. There is no need to -/// explicitly finalize it, however: it already implements the -/// `Iterator` trait. -/// -/// By default, `ComponentBundleIter` returns each component in turn. -pub struct ComponentBundleIter<'a, C> { - cert: &'a Cert, - iter: slice::Iter<'a, ComponentBundle>, -} - -impl<'a, C> fmt::Debug for ComponentBundleIter<'a, C> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("ComponentBundleIter") - .finish() - } -} - -impl<'a, C> Iterator for ComponentBundleIter<'a, C> -{ - type Item = ComponentAmalgamation<'a, C>; - - fn next(&mut self) -> Option { - self.iter.next().map(|c| ComponentAmalgamation::new(self.cert, c)) - } -} - -impl<'a, C> ComponentBundleIter<'a, C> { - /// Returns a new `ComponentBundleIter` instance. - pub(crate) fn new(cert: &'a Cert, - iter: std::slice::Iter<'a, ComponentBundle>) -> Self - where Self: 'a - { - ComponentBundleIter { - cert, iter, - } - } - - /// Changes the iterator to only return components that are valid - /// for the given policy at the specified time. - /// - /// If `time` is None, then the current time is used. - /// - /// See `ValidComponentBundleIter` for the definition of a valid component. - pub fn with_policy(self, policy: &'a dyn Policy, time: T) - -> ValidComponentBundleIter<'a, C> - where T: Into> - { - ValidComponentBundleIter { - cert: self.cert, - iter: self.iter, - time: time.into().unwrap_or_else(SystemTime::now), - policy, - revoked: None, - } - } -} - -/// An iterator over all valid `Component`s of a given type in a -/// certificate. -/// -/// A component is valid at time `t` if it was not created after `t` -/// and it has a live self-signature at time `t`. -/// -/// `ValidComponentBundleIter` follows the builder pattern. There is no -/// need to explicitly finalize it, however: it already implements the -/// `Iterator` trait. -pub struct ValidComponentBundleIter<'a, C> { - // This is an option to make it easier to create an empty ValidComponentBundleIter. - cert: &'a Cert, - iter: slice::Iter<'a, ComponentBundle>, - - policy: &'a dyn Policy, - // The time. - time: SystemTime, - - // If not None, filters by whether the component is revoked or not - // at time `t`. - revoked: Option, -} - -impl<'a, C> fmt::Debug for ValidComponentBundleIter<'a, C> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("ValidComponentBundleIter") - .field("time", &self.time) - .field("revoked", &self.revoked) - .finish() - } -} - -impl<'a, C> Iterator for ValidComponentBundleIter<'a, C> - where C: std::fmt::Debug -{ - type Item = ValidComponentAmalgamation<'a, C>; - - fn next(&mut self) -> Option { - tracer!(false, "ValidComponentBundleIter::next", 0); - t!("ValidComponentBundleIter: {:?}", self); - - loop { - let ca = ComponentAmalgamation::new(self.cert, self.iter.next()?); - t!("Considering component: {:?}", ca.component()); - - let vca = match ca.with_policy(self.policy, self.time) { - Ok(vca) => vca, - Err(e) => { - t!("Rejected: {}", e); - continue; - }, - }; - - if let Some(want_revoked) = self.revoked { - if let RevocationStatus::Revoked(_) = vca.revoked() { - // The component is definitely revoked. - if ! want_revoked { - t!("Component revoked... skipping."); - continue; - } - } else { - // The component is probably not revoked. - if want_revoked { - t!("Component not revoked... skipping."); - continue; - } - } - } - - return Some(vca); - } - } -} - -impl<'a, C> ExactSizeIterator for ComponentBundleIter<'a, C> -{ - fn len(&self) -> usize { - self.iter.len() - } -} - -impl<'a, C> ValidComponentBundleIter<'a, C> { - /// Filters by whether a component is definitely revoked. - /// - /// A value of None disables this filter. - /// - /// Note: If you call this function multiple times on the same - /// iterator, only the last value is used. - /// - /// Note: This only checks if the component is not revoked; it does not - /// check whether the certificate not revoked. - /// - /// This filter checks whether a component's revocation status is - /// `RevocationStatus::Revoked` or not. The latter (i.e., - /// `revoked(false)`) is equivalent to: - /// - /// ```rust - /// extern crate sequoia_openpgp as openpgp; - /// # use openpgp::Result; - /// use openpgp::cert::prelude::*; - /// use openpgp::types::RevocationStatus; - /// use sequoia_openpgp::policy::StandardPolicy; - /// - /// # fn main() { f().unwrap(); } - /// # fn f() -> Result<()> { - /// let p = &StandardPolicy::new(); - /// - /// # let (cert, _) = - /// # CertBuilder::general_purpose(None, Some("alice@example.org")) - /// # .generate()?; - /// # let timestamp = None; - /// let non_revoked_uas = cert - /// .user_attributes() - /// .with_policy(p, timestamp) - /// .filter(|ca| { - /// match ca.revoked() { - /// RevocationStatus::Revoked(_) => - /// // It's definitely revoked, skip it. - /// false, - /// RevocationStatus::CouldBe(_) => - /// // There is a designated revoker that we - /// // should check, but don't (or can't). To - /// // avoid a denial of service arising from fake - /// // revocations, we assume that the component has not - /// // been revoked and return it. - /// true, - /// RevocationStatus::NotAsFarAsWeKnow => - /// // We have no evidence to suggest that the component - /// // is revoked. - /// true, - /// } - /// }) - /// .collect::>(); - /// # Ok(()) - /// # } - /// ``` - /// - /// As the example shows, this filter is significantly less - /// flexible than using `ValidComponentAmalgamation::revoked`. - /// However, this filter implements a typical policy, and does not - /// preclude using `filter` to realize alternative policies. - pub fn revoked(mut self, revoked: T) -> Self - where T: Into> - { - self.revoked = revoked.into(); - self - } -} diff --git a/openpgp/src/cert/mod.rs b/openpgp/src/cert/mod.rs index 751b4143..3e239e80 100644 --- a/openpgp/src/cert/mod.rs +++ b/openpgp/src/cert/mod.rs @@ -640,8 +640,8 @@ impl Cert { } /// Returns an iterator over the Cert's userids. - pub fn userids(&self) -> ComponentBundleIter { - ComponentBundleIter::new(self, self.userids.iter()) + pub fn userids(&self) -> ComponentAmalgamationIter { + ComponentAmalgamationIter::new(self, self.userids.iter()) } /// Returns the amalgamated primary user attribute at `t`, if any. @@ -655,20 +655,20 @@ impl Cert { } /// Returns an iterator over the Cert's `UserAttributeBundle`s. - pub fn user_attributes(&self) -> ComponentBundleIter { - ComponentBundleIter::new(self, self.user_attributes.iter()) + pub fn user_attributes(&self) -> ComponentAmalgamationIter { + ComponentAmalgamationIter::new(self, self.user_attributes.iter()) } /// Returns an iterator over the Cert's subkeys. - pub(crate) fn subkeys(&self) -> ComponentBundleIter ComponentAmalgamationIter> { - ComponentBundleIter::new(self, self.subkeys.iter()) + ComponentAmalgamationIter::new(self, self.subkeys.iter()) } /// Returns an iterator over the Cert's unknown components. - pub fn unknowns(&self) -> ComponentBundleIter { - ComponentBundleIter::new(self, self.unknowns.iter()) + pub fn unknowns(&self) -> ComponentAmalgamationIter { + ComponentAmalgamationIter::new(self, self.unknowns.iter()) } /// Returns a slice containing all bad signatures. @@ -1481,7 +1481,7 @@ impl<'a> ValidCert<'a> { } /// Returns an iterator over the Cert's userids. - pub fn userids(&self) -> ValidComponentBundleIter { + pub fn userids(&self) -> ValidComponentAmalgamationIter { self.cert.userids().with_policy(self.policy, self.time) } @@ -1493,7 +1493,7 @@ impl<'a> ValidCert<'a> { } /// Returns an iterator over the Cert's `UserAttributeBundle`s. - pub fn user_attributes(&self) -> ValidComponentBundleIter { + pub fn user_attributes(&self) -> ValidComponentAmalgamationIter { self.cert.user_attributes().with_policy(self.policy, self.time) } } diff --git a/openpgp/src/cert/prelude.rs b/openpgp/src/cert/prelude.rs index fdb71436..15e06129 100644 --- a/openpgp/src/cert/prelude.rs +++ b/openpgp/src/cert/prelude.rs @@ -29,6 +29,7 @@ pub use crate::cert::{ UserIDRevocationBuilder, ValidCert, amalgamation::ComponentAmalgamation, + amalgamation::ComponentAmalgamationIter, amalgamation::ErasedKeyAmalgamation, amalgamation::KeyAmalgamation, amalgamation::KeyAmalgamationIter, @@ -37,6 +38,7 @@ pub use crate::cert::{ amalgamation::SubordinateKeyAmalgamation, amalgamation::ValidAmalgamation as _, amalgamation::ValidComponentAmalgamation, + amalgamation::ValidComponentAmalgamationIter, amalgamation::ValidErasedKeyAmalgamation, amalgamation::ValidKeyAmalgamation, amalgamation::ValidKeyAmalgamationIter, @@ -44,12 +46,10 @@ pub use crate::cert::{ amalgamation::ValidSubordinateKeyAmalgamation, amalgamation::ValidateAmalgamation as _, bundle::ComponentBundle, - bundle::ComponentBundleIter, bundle::KeyBundle, bundle::PrimaryKeyBundle, bundle::SubkeyBundle, bundle::UnknownBundle, bundle::UserAttributeBundle, bundle::UserIDBundle, - bundle::ValidComponentBundleIter, }; -- cgit v1.2.3