use std::io;
use std::mem;
use std::vec;
use std::path::Path;
use lalrpop_util::ParseError;
use crate::{
Error,
KeyHandle,
packet::Tag,
packet::Signature,
Packet,
parse::{
Parse,
PacketParserResult,
PacketParser
},
Result,
cert::ComponentBinding,
Cert,
};
mod low_level;
use low_level::{
Lexer,
CertParser as CertLowLevelParser,
CertParserError,
Token,
parse_error_downcast,
};
use super::TRACE;
#[derive(Debug)]
pub enum KeyringValidity {
Keyring,
KeyringPrefix,
Error(failure::Error),
}
impl KeyringValidity {
pub fn is_keyring(&self) -> bool {
if let KeyringValidity::Keyring = self {
true
} else {
false
}
}
pub fn is_keyring_prefix(&self) -> bool {
if let KeyringValidity::KeyringPrefix = self {
true
} else {
false
}
}
pub fn is_err(&self) -> bool {
if let KeyringValidity::Error(_) = self {
true
} else {
false
}
}
}
#[derive(Debug)]
pub struct KeyringValidator {
tokens: Vec<Token>,
n_keys: usize,
n_packets: usize,
finished: bool,
error: Option<CertParserError>,
}
impl Default for KeyringValidator {
fn default() -> Self {
KeyringValidator::new()
}
}
impl KeyringValidator {
pub fn new() -> Self {
KeyringValidator {
tokens: vec![],
n_keys: 0,
n_packets: 0,
finished: false,
error: None,
}
}
pub fn is_keyring(&self) -> bool {
self.check().is_keyring()
}
pub fn is_keyring_prefix(&self) -> bool {
self.check().is_keyring_prefix()
}
pub fn is_err(&self) -> bool {
self.check().is_err()
}
pub fn push_token(&mut self, token: Token) {
assert!(!self.finished);
if self.error.is_some() {
return;
}
match token {
Token::PublicKey(_) | Token::SecretKey(_) => {
self.tokens.clear();
self.n_keys += 1;
},
_ => (),
}
self.n_packets += 1;
if destructures_to!(Token::Signature(None) = &token)
&& destructures_to!(Some(Token::Signature(None)) = self.tokens.last())
{
} else {
self.tokens.push(token);
}
}
pub fn push(&mut self, tag: Tag) {
let token = match tag {
Tag::PublicKey => Token::PublicKey(None),
Tag::SecretKey => Token::SecretKey(None),
Tag::PublicSubkey => Token::PublicSubkey(None),
Tag::SecretSubkey => Token::SecretSubkey(None),
Tag::UserID => Token::UserID(None),
Tag::UserAttribute => Token::UserAttribute(None),
Tag::Signature => Token::Signature(None),
Tag::Trust => Token::Trust(None),
_ => {
self.error = Some(CertParserError::OpenPGP(
Error::MalformedMessage(
format!("Invalid Cert: {:?} packet (at {}) not expected",
tag, self.n_packets).into())));
self.tokens.clear();
return;
}
};
self.push_token(token)
}
pub fn finish(&mut self) {
assert!(!self.finished);
self.finished = true;
}
pub fn check(&self) -> KeyringValidity {
if let Some(ref err) = self.error {
return KeyringValidity::Error((*err).clone().into());
}
let r = CertLowLevelParser::new().parse(
Lexer::from_tokens(&self.tokens));
if self.finished {
match r {
Ok(_) => KeyringValidity::Keyring,
Err(err) =>
KeyringValidity::Error(
CertParserError::Parser(parse_error_downcast(err)).into()),
}
} else {
match r {
Ok(_) => KeyringValidity::KeyringPrefix,
Err(ParseError::UnrecognizedEOF { .. }) =>
KeyringValidity::KeyringPrefix,
Err(err) =>
KeyringValidity::Error(
CertParserError::Parser(parse_error_downcast(err)).into()),
}
}
}
}
#[derive(Debug)]
pub enum CertValidity {
Cert,
CertPrefix,
Error(failure::Error),
}
impl CertValidity {
pub fn is_cert(&self) -> bool {
if let CertValidity::Cert = self {
true
} else {
false
}
}
pub fn is_cert_prefix(&self) -> bool {
if let CertValidity::CertPrefix = self {
true
} else {
false
}
}
pub fn is_err(&self) -> bool {
if let CertValidity::Error(_) = self {
true
} else {
false
}
}
}
#[derive(Debug)]
pub struct CertValidator(KeyringValidator);
impl Default for CertValidator {
fn default() -> Self {
CertValidator::new()
}
}
impl CertValidator {
pub fn new() -> Self {
CertValidator(Default::default())
}
pub fn is_cert(&self) -> bool {
self.check().is_cert()
}
pub fn is_cert_prefix(&self) -> bool {
self.check().is_cert_prefix()
}
pub fn is_err(&self) -> bool {
self.check().is_err()
}
pub fn push_token(&mut self, token: Token) {
self.0.push_token(token)
}
pub fn push(&mut self, tag: Tag) {
self.0.push(tag)
}
pub fn finish(&mut self) {
self.0.finish()
}
pub fn check(&self) -> CertValidity {
if self.0.n_keys > 1 {
return CertValidity::Error(Error::MalformedMessage(
"More than one key found, this is a keyring".into()).into());
}
match self.0.check() {
KeyringValidity::Keyring => CertValidity::Cert,
KeyringValidity::KeyringPrefix => CertValidity::CertPrefix,
KeyringValidity::Error(e) => CertValidity::Error(e),
}
}
}
enum PacketSource<'a, I: Iterator<Item=Packet>> {
EOF,
PacketParser(PacketParser<'a>),
Iter(I),
}
pub struct CertParser<'a, I: Iterator<Item=Packet>> {
source: PacketSource<'a, I>,
packets: Vec<Packet>,
saw_error: bool,
filter: Vec<Box<dyn Fn(&Cert, bool) -> bool + 'a>>,
}
impl<'a, I: Iterator<Item=Packet>> Default for CertParser<'a, I> {
fn default() -> Self {
CertParser {
source: PacketSource::EOF,
packets: vec![],
saw_error: false,
filter: vec![],
}
}
}
impl<'a> CertParser<'a, vec::IntoIter<Packet>> {
pub fn from_packet_parser(ppr: PacketParserResult<'a>) -> Self {
let mut parser : Self = Default::default();
if let PacketParserResult::Some(pp) = ppr {
parser.source = PacketSource::PacketParser(pp);
}
parser
}
}
impl<'a> Parse<'a, CertParser<'a, vec::IntoIter<Packet>>>
for CertParser<'a, vec::IntoIter<Packet>>
{
fn from_reader<R: 'a + io::Read>(reader: R) -> Result<Self> {
Ok(Self::from_packet_parser(PacketParser::from_reader(reader)?))
}
fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
Ok(Self::from_packet_parser(PacketParser::from_file(path)?))
}
fn from_bytes<D: AsRef<[u8]> + ?Sized>(data: &'a D) -> Result<Self> {
Ok(Self::from_packet_parser(PacketParser::from_bytes(data)?))
}
}
impl<'a, I: Iterator<Item=Packet>> CertParser<'a, I> {
pub fn from_iter(iter: I) -> Self {
let mut parser : Self = Default::default();
parser.source = PacketSource::Iter(iter);
parser
}
pub fn unvalidated_cert_filter<F: 'a>(mut self, filter: F) -> Self
where F: Fn(&Cert, bool) -> bool
{
self.filter.push(Box::new(filter));
self
}
fn parse(&mut self, p: Packet) -> Result<Option<Cert>> {
if let Packet::Marker(_) = p {
return Ok(None);
}
if self.packets.len() > 0 {
match p.tag() {
Tag::PublicKey | Tag::SecretKey => {
return self.cert(Some(p));
},
_ => {},
}
}
self.packets.push(p);
Ok(None)
}
fn reset(&mut self) -> Self {
let mut orig = mem::replace(self, Default::default());
self.source = mem::replace(&mut orig.source, PacketSource::EOF);
orig
}
fn cert(&mut self, pk: Option<Packet>) -> Result<Option<Cert>> {
let orig = self.reset();
if let Some(pk) = pk {
self.packets.push(pk);
}
let packets = orig.packets.len();
let tokens = orig.packets
.into_iter()
.filter_map(|p| p.into())
.collect::<Vec<Token>>();
if tokens.len() != packets {
return Err(Error::UnsupportedCert(
"Packet sequence includes non-Cert packets.".into()).into());
}
let certo = match CertLowLevelParser::new()
.parse(Lexer::from_tokens(&tokens))
{
Ok(certo) => certo,
Err(e) => return Err(
low_level::parse_error_to_openpgp_error(
low_level::parse_error_downcast(e)).into()),
}.and_then(|cert| {
for filter in &self.filter {
if !filter(&cert, true) {
return None;
}
}
Some(cert)
}).and_then(|mut cert| {
fn split_sigs<C>(primary: &KeyHandle, primary_keyid: &KeyHandle,
b: &mut ComponentBinding<C>)
{
let mut self_signatures = vec![];
let mut certifications = vec![];
let mut self_revs = vec![];
let mut other_revs = vec![];
for sig in mem::replace(&mut b.certifications, vec![]) {
match sig {
Signature::V4(sig) => {
let typ = sig.typ();
let issuers =
sig.get_issuers();
let is_selfsig =
issuers.contains(primary)
|| issuers.contains(primary_keyid);
use crate::SignatureType::*;
if typ == KeyRevocation
|| typ == SubkeyRevocation
|| typ == CertificationRevocation
{
if is_selfsig {
self_revs.push(sig.into());
} else {
other_revs.push(sig.into());
}
} else {
if is_selfsig {
self_signatures.push(sig.into());
} else {
certifications.push(sig.into());
}
}
},
}
}
b.self_signatures = self_signatures;
b.certifications = certifications;
b.self_revocations = self_revs;
b.other_revocations = other_revs;
}
let primary_fp: KeyHandle = cert.primary().fingerprint().into();
let primary_keyid = KeyHandle::KeyID(primary_fp.clone().into());
split_sigs(&primary_fp, &primary_keyid, &mut cert.primary);
for b in cert.userids.iter_mut() {
split_sigs(&primary_fp, &primary_keyid, b);
}
for b in cert.user_attributes.iter_mut() {
split_sigs(&primary_fp, &primary_keyid, b);
}
for b in cert.subkeys.iter_mut() {
split_sigs(&primary_fp, &primary_keyid, b);
}
let cert = cert.canonicalize();
for filter in &self.filter {
if !filter(&cert, true) {
return None;
}
}
Some(cert)
});
Ok(certo)
}
}
impl<'a, I: Iterator<Item=Packet>> Iterator for CertParser<'a, I> {
type Item = Result<Cert>;
fn next(&mut self) -> Option<Self::Item> {
loop {
match mem::replace(&mut self.source, PacketSource::EOF) {
PacketSource::EOF => {
if TRACE {
eprintln!("CertParser::next: EOF.");
}
if self.packets.len() == 0 {
return None;
}
match self.cert(None) {
Ok(Some(cert)) => return Some(Ok(cert)),
Ok(None) => return None,
Err(err) => return Some(Err(err)),
}
},
PacketSource::PacketParser(mut pp) => {
if let Packet::Unknown(_) = pp.packet {
if let Err(e) = pp.buffer_unread_content() {
return Some(Err(e));
}
}
match pp.next() {
Ok((packet, ppr)) => {
if let PacketParserResult::Some(pp) = ppr {
self.source = PacketSource::PacketParser(pp);
}
match self.parse(packet) {
Ok(Some(cert)) => return Some(Ok(cert)),
Ok(None) => (),
Err(err) => return Some(Err(err)),
}
},
Err(err) => {
self.saw_error = true;
return Some(Err(err));
}
}
},
PacketSource::Iter(mut iter) => {
let r = match iter.next() {
Some(packet) => {
self.source = PacketSource::Iter(iter);
self.parse(packet)
}
None if self.packets.len() == 0 => Ok(None),
None => self.cert(None),
};
match r {
Ok(Some(cert)) => {
if TRACE {
eprintln!("CertParser::next => {}",
cert.primary().fingerprint());
}
return Some(Ok(cert));
}
Ok(None) => (),
Err(err) => return Some(Err(err)),
}
},
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn tokens() {
use crate::cert::parser::low_level::lexer::{Token, Lexer};
use crate::cert::parser::low_level::lexer::Token::*;
use crate::cert::parser::low_level::CertParser;
struct TestVector<'a> {
s: &'a [Token],
result: bool,
}
let test_vectors = [
TestVector {
s: &[ PublicKey(None) ],
result: true,
},
TestVector {
s: &[ SecretKey(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
UserID(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
UserID(None), Signature(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
UserAttribute(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
UserAttribute(None), Signature(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
PublicSubkey(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
PublicSubkey(None), Signature(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
SecretSubkey(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
SecretSubkey(None), Signature(None) ],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
SecretSubkey(None), Signature(None),
SecretSubkey(None), Signature(None),
SecretSubkey(None), Signature(None),
SecretSubkey(None), Signature(None),
SecretSubkey(None), Signature(None),
UserID(None), Signature(None),
Signature(None), Signature(None),
SecretSubkey(None), Signature(None),
UserAttribute(None), Signature(None),
Signature(None), Signature(None),
SecretSubkey(None), Signature(None),
UserID(None),
UserAttribute(None), Signature(None),
Signature(None), Signature(None),
],
result: true,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
PublicKey(None), Signature(None), Signature(None),
],
result: false,
},
TestVector {
s: &[ PublicKey(None), Signature(None), Signature(None),
SecretKey(None), Signature(None), Signature(None),
],
result: false,
},
TestVector {
s: &[ SecretKey(None), Signature(None), Signature(None),
SecretKey(None), Signature(None), Signature(None),
],
result: false,
},
TestVector {
s: &[ SecretKey(None), Signature(None), Signature(None),
PublicKey(None), Signature(None), Signature(None),
],
result: false,
},
TestVector {
s: &[ SecretSubkey(None), Signature(None), Signature(None),
PublicSubkey(None), Signature(None), Signature(None),
],
result: false,
},
];
for v in &test_vectors {
if v.result {
let mut l = CertValidator::new();
for token in v.s.into_iter() {
l.push_token((*token).clone());
assert_match!(CertValidity::CertPrefix = l.check());
}
l.finish();
assert_match!(CertValidity::Cert = l.check());
}
match CertParser::new().parse(Lexer::from_tokens(v.s)) {
Ok(r) => assert!(v.result, "Parsing: {:?} => {:?}", v.s, r),
Err(e) => assert!(! v.result, "Parsing: {:?} => {:?}", v.s, e),
}
}
}
#[test]
fn marker_packet_ignored() {
use crate::serialize::Serialize;
let mut testy_with_marker = Vec::new();
Packet::Marker(Default::default())
.serialize(&mut testy_with_marker).unwrap();
testy_with_marker.extend_from_slice(crate::tests::key("testy.pgp"));
CertParser::from_packet_parser(
PacketParser::from_bytes(&testy_with_marker).unwrap())
.nth(0).unwrap().unwrap();
}
}