use std::fmt;
use crate::{
packet::Signature,
Result,
};
pub trait Policy : fmt::Debug {
fn signature(&self, _sig: &Signature) -> Result<()> {
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct StandardPolicy {
}
impl Default for StandardPolicy {
fn default() -> Self {
Self {
}
}
}
impl<'a> From<&'a StandardPolicy> for Option<&'a dyn Policy> {
fn from(p: &'a StandardPolicy) -> Self {
Some(p as &dyn Policy)
}
}
impl StandardPolicy {
pub fn new() -> Self {
Self::default()
}
}
impl Policy for StandardPolicy {
}
#[cfg(test)]
mod test {
use std::io::Read;
use super::*;
use crate::Fingerprint;
use crate::cert::{Cert, CertBuilder};
use crate::parse::Parse;
use crate::policy::StandardPolicy as P;
#[test]
fn binding_signature() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_signing_subkey()
.add_transport_encryption_subkey()
.generate().unwrap();
assert_eq!(cert.keys().with_policy(p, None).count(), 3);
#[derive(Debug)]
struct NoDirectKeySigs;
impl Policy for NoDirectKeySigs {
fn signature(&self, sig: &Signature) -> Result<()> {
use crate::types::SignatureType::*;
match sig.typ() {
DirectKey => Err(format_err!("direct key!")),
_ => Ok(()),
}
}
}
let p = &NoDirectKeySigs {};
assert_eq!(cert.keys().with_policy(p, None).count(), 0);
#[derive(Debug)]
struct NoSubkeySigs;
impl Policy for NoSubkeySigs {
fn signature(&self, sig: &Signature) -> Result<()> {
use crate::types::SignatureType::*;
match sig.typ() {
SubkeyBinding => Err(format_err!("subkey signature!")),
_ => Ok(()),
}
}
}
let p = &NoSubkeySigs {};
assert_eq!(cert.keys().with_policy(p, None).count(), 1);
}
#[test]
fn revocation() -> Result<()> {
use crate::cert::UserIDRevocationBuilder;
use crate::cert::SubkeyRevocationBuilder;
use crate::types::SignatureType;
use crate::types::ReasonForRevocation;
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_userid("Alice")
.add_signing_subkey()
.add_transport_encryption_subkey()
.generate()?;
assert_eq!(cert.keys().with_policy(p, None).count(), 3);
assert_eq!(cert.userids().with_policy(p, None).count(), 1);
#[derive(Debug)]
struct NoPositiveCertifications;
impl Policy for NoPositiveCertifications {
fn signature(&self, sig: &Signature) -> Result<()> {
use crate::types::SignatureType::*;
match sig.typ() {
PositiveCertification =>
Err(format_err!("positive certification!")),
_ => Ok(()),
}
}
}
let p = &NoPositiveCertifications {};
assert_eq!(cert.userids().with_policy(p, None).count(), 0);
let mut keypair = cert.primary_key().key().clone()
.mark_parts_secret()?.into_keypair()?;
let ca = cert.userids().nth(0).unwrap();
let revocation =
UserIDRevocationBuilder::new()
.set_reason_for_revocation(
ReasonForRevocation::KeyRetired,
b"Left example.org.")?
.build(&mut keypair, &cert, ca.userid(), None)?;
assert_eq!(revocation.typ(), SignatureType::CertificationRevocation);
let cert = cert.merge_packets(vec![revocation.clone().into()])?;
assert_eq!(cert.userids().with_policy(p, None).revoked(false).count(), 0);
#[derive(Debug)]
struct NoCertificationRevocation;
impl Policy for NoCertificationRevocation {
fn signature(&self, sig: &Signature) -> Result<()> {
use crate::types::SignatureType::*;
match sig.typ() {
CertificationRevocation =>
Err(format_err!("certification certification!")),
_ => Ok(()),
}
}
}
let p = &NoCertificationRevocation {};
assert_eq!(cert.userids().with_policy(p, None).revoked(false).count(), 1);
let subkey = cert.keys().subkeys().nth(0).unwrap();
let revocation =
SubkeyRevocationBuilder::new()
.set_reason_for_revocation(
ReasonForRevocation::KeyRetired,
b"Smells funny.").unwrap()
.build(&mut keypair, &cert, subkey.key(), None)?;
assert_eq!(revocation.typ(), SignatureType::SubkeyRevocation);
assert_eq!(cert.keys().with_policy(p, None).revoked(false).count(), 3);
let cert = cert.merge_packets(vec![revocation.clone().into()])?;
assert_eq!(cert.keys().with_policy(p, None).revoked(false).count(), 2);
#[derive(Debug)]
struct NoSubkeyRevocation;
impl Policy for NoSubkeyRevocation {
fn signature(&self, sig: &Signature) -> Result<()> {
use crate::types::SignatureType::*;
match sig.typ() {
SubkeyRevocation =>
Err(format_err!("subkey revocation!")),
_ => Ok(()),
}
}
}
let p = &NoSubkeyRevocation {};
assert_eq!(cert.keys().with_policy(p, None).revoked(false).count(), 3);
Ok(())
}
#[test]
fn binary_signature() {
use crate::crypto::SessionKey;
use crate::types::SymmetricAlgorithm;
use crate::packet::{PKESK, SKESK};
use crate::parse::stream::MessageLayer;
use crate::parse::stream::MessageStructure;
use crate::parse::stream::Verifier;
use crate::parse::stream::Decryptor;
use crate::parse::stream::VerificationHelper;
use crate::parse::stream::DecryptionHelper;
#[derive(PartialEq, Debug)]
struct VHelper {
good: usize,
errors: usize,
keys: Vec<Cert>,
}
impl VHelper {
fn new(keys: Vec<Cert>) -> Self {
VHelper {
good: 0,
errors: 0,
keys: keys,
}
}
}
impl VerificationHelper for VHelper {
fn get_public_keys(&mut self, _ids: &[crate::KeyHandle])
-> Result<Vec<Cert>>
{
Ok(self.keys.clone())
}
fn check(&mut self, structure: MessageStructure) -> Result<()>
{
use crate::parse::stream::VerificationResult::*;
for layer in structure.iter() {
match layer {
MessageLayer::SignatureGroup { ref results } =>
for result in results {
eprintln!("result: {:?}", result);
match result {
GoodChecksum { .. } => self.good += 1,
Error { .. } => self.errors += 1,
_ => (),
}
}
MessageLayer::Compression { .. } => (),
_ => unreachable!(),
}
}
Ok(())
}
}
impl DecryptionHelper for VHelper {
fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK], _: D)
-> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> Result<()>
{
unreachable!();
}
}
#[derive(Debug)]
struct NoBinarySigantures;
impl Policy for NoBinarySigantures {
fn signature(&self, sig: &Signature) -> Result<()> {
use crate::types::SignatureType::*;
eprintln!("{:?}", sig.typ());
match sig.typ() {
Binary =>
Err(format_err!("binary!")),
_ => Ok(()),
}
}
}
let no_binary_signatures = &NoBinarySigantures {};
#[derive(Debug)]
struct NoSubkeySigs;
impl Policy for NoSubkeySigs {
fn signature(&self, sig: &Signature) -> Result<()> {
use crate::types::SignatureType::*;
match sig.typ() {
SubkeyBinding => Err(format_err!("subkey signature!")),
_ => Ok(()),
}
}
}
let no_subkey_signatures = &NoSubkeySigs {};
let standard = &P::new();
let keys = [
"neal.pgp",
].iter()
.map(|f| Cert::from_bytes(crate::tests::key(f)).unwrap())
.collect::<Vec<_>>();
let data = "messages/signed-1.gpg";
let reference = crate::tests::manifesto();
let h = VHelper::new(keys.clone());
let mut v =
match Verifier::from_bytes(standard, crate::tests::file(data), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => panic!("{}", e),
};
assert!(v.message_processed());
assert_eq!(v.helper_ref().good, 1);
assert_eq!(v.helper_ref().errors, 0);
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
let h = VHelper::new(keys.clone());
let mut v = match Verifier::from_bytes(no_subkey_signatures,
crate::tests::file(data), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => panic!("{}", e),
};
assert!(v.message_processed());
assert_eq!(v.helper_ref().good, 0);
assert_eq!(v.helper_ref().errors, 1);
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
let h = VHelper::new(keys.clone());
let mut v =
match Verifier::from_bytes(no_binary_signatures,
crate::tests::file(data), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => panic!("{}", e),
};
assert!(v.message_processed());
assert_eq!(v.helper_ref().good, 0);
assert_eq!(v.helper_ref().errors, 1);
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
let h = VHelper::new(keys.clone());
let mut v =
match Decryptor::from_bytes(standard, crate::tests::file(data), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => panic!("{}", e),
};
assert!(v.message_processed());
assert_eq!(v.helper_ref().good, 1);
assert_eq!(v.helper_ref().errors, 0);
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
let h = VHelper::new(keys.clone());
let mut v = match Decryptor::from_bytes(no_subkey_signatures,
crate::tests::file(data), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => panic!("{}", e),
};
assert!(v.message_processed());
assert_eq!(v.helper_ref().good, 0);
assert_eq!(v.helper_ref().errors, 1);
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
let h = VHelper::new(keys.clone());
let mut v =
match Decryptor::from_bytes(no_binary_signatures,
crate::tests::file(data), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => panic!("{}", e),
};
assert!(v.message_processed());
assert_eq!(v.helper_ref().good, 0);
assert_eq!(v.helper_ref().errors, 1);
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
}
}