use std::io;
use std::mem;
use std::vec;
use std::path::Path;
use lalrpop_util::ParseError;
use crate::{
Error,
Fingerprint,
KeyID,
packet::Tag,
packet::Signature,
Packet,
parse::{
Parse,
PacketParserResult,
PacketParser
},
Result,
tpk::ComponentBinding,
TPK,
};
mod low_level;
use low_level::{
Lexer,
TPKParser as TPKLowLevelParser,
TPKParserError,
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<TPKParserError>,
}
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(TPKParserError::OpenPGP(
Error::MalformedMessage(
format!("Invalid TPK: {:?} 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 = TPKLowLevelParser::new().parse(
Lexer::from_tokens(&self.tokens));
if self.finished {
match r {
Ok(_) => KeyringValidity::Keyring,
Err(err) =>
KeyringValidity::Error(
TPKParserError::Parser(parse_error_downcast(err)).into()),
}
} else {
match r {
Ok(_) => KeyringValidity::KeyringPrefix,
Err(ParseError::UnrecognizedEOF { .. }) =>
KeyringValidity::KeyringPrefix,
Err(err) =>
KeyringValidity::Error(
TPKParserError::Parser(parse_error_downcast(err)).into()),
}
}
}
}
#[derive(Debug)]
pub enum TPKValidity {
TPK,
TPKPrefix,
Error(failure::Error),
}
impl TPKValidity {
pub fn is_tpk(&self) -> bool {
if let TPKValidity::TPK = self {
true
} else {
false
}
}
pub fn is_tpk_prefix(&self) -> bool {
if let TPKValidity::TPKPrefix = self {
true
} else {
false
}
}
pub fn is_err(&self) -> bool {
if let TPKValidity::Error(_) = self {
true
} else {
false
}
}
}
#[derive(Debug)]
pub struct TPKValidator(KeyringValidator);
impl Default for TPKValidator {
fn default() -> Self {
TPKValidator::new()
}
}
impl TPKValidator {
pub fn new() -> Self {
TPKValidator(Default::default())
}
pub fn is_tpk(&self) -> bool {
self.check().is_tpk()
}
pub fn is_tpk_prefix(&self) -> bool {
self.check().is_tpk_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) -> TPKValidity {
if self.0.n_keys > 1 {
return TPKValidity::Error(Error::MalformedMessage(
"More than one key found, this is a keyring".into()).into());
}
match self.0.check() {
KeyringValidity::Keyring => TPKValidity::TPK,
KeyringValidity::KeyringPrefix => TPKValidity::TPKPrefix,
KeyringValidity::Error(e) => TPKValidity::Error(e),
}
}
}
enum PacketSource<'a, I: Iterator<Item=Packet>> {
EOF,
PacketParser(PacketParser<'a>),
Iter(I),
}
pub struct TPKParser<'a, I: Iterator<Item=Packet>> {
source: PacketSource<'a, I>,
packets: Vec<Packet>,
saw_error: bool,
filter: Vec<Box<dyn Fn(&TPK, bool) -> bool + 'a>>,
}
impl<'a, I: Iterator<Item=Packet>> Default for TPKParser<'a, I> {
fn default() -> Self {
TPKParser {
source: PacketSource::EOF,
packets: vec![],
saw_error: false,
filter: vec![],
}
}
}
impl<'a> TPKParser<'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, TPKParser<'a, vec::IntoIter<Packet>>>
for TPKParser<'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>> TPKParser<'a, I> {
pub fn from_iter(iter: I) -> Self {
let mut parser : Self = Default::default();
parser.source = PacketSource::Iter(iter);
parser
}
pub fn unvalidated_tpk_filter<F: 'a>(mut self, filter: F) -> Self
where F: Fn(&TPK, bool) -> bool
{
self.filter.push(Box::new(filter));
self
}
fn parse(&mut self, p: Packet) -> Result<Option<TPK>> {
if self.packets.len() > 0 {
match p.tag() {
Tag::PublicKey | Tag::SecretKey => {
return self.tpk(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 tpk(&mut self, pk: Option<Packet>) -> Result<Option<TPK>> {
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::UnsupportedTPK(
"Packet sequence includes non-TPK packets.".into()).into());
}
let tpko = match TPKLowLevelParser::new()
.parse(Lexer::from_tokens(&tokens))
{
Ok(tpko) => tpko,
Err(e) => return Err(
low_level::parse_error_to_openpgp_error(
low_level::parse_error_downcast(e)).into()),
}.and_then(|tpk| {
for filter in &self.filter {
if !filter(&tpk, true) {
return None;
}
}
Some(tpk)
}).and_then(|mut tpk| {
fn split_sigs<C>(primary: &Fingerprint, primary_keyid: &KeyID,
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 is_selfsig =
sig.issuer_fingerprint()
.map(|fp| fp == *primary)
.unwrap_or(false)
|| sig.issuer()
.map(|keyid| keyid == *primary_keyid)
.unwrap_or(false);
use crate::SignatureType::*;
if typ == KeyRevocation
|| typ == SubkeyRevocation
|| typ == CertificateRevocation
{
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 = tpk.primary().fingerprint();
let primary_keyid = primary_fp.to_keyid();
split_sigs(&primary_fp, &primary_keyid, &mut tpk.primary);
for b in tpk.userids.iter_mut() {
split_sigs(&primary_fp, &primary_keyid, b);
}
for b in tpk.user_attributes.iter_mut() {
split_sigs(&primary_fp, &primary_keyid, b);
}
for b in tpk.subkeys.iter_mut() {
split_sigs(&primary_fp, &primary_keyid, b);
}
let tpk = tpk.canonicalize();
for filter in &self.filter {
if !filter(&tpk, true) {
return None;
}
}
Some(tpk)
});
Ok(tpko)
}
}
impl<'a, I: Iterator<Item=Packet>> Iterator for TPKParser<'a, I> {
type Item = Result<TPK>;
fn next(&mut self) -> Option<Self::Item> {
loop {
match mem::replace(&mut self.source, PacketSource::EOF) {
PacketSource::EOF => {
if TRACE {
eprintln!("TPKParser::next: EOF.");
}
if self.packets.len() == 0 {
return None;
}
match self.tpk(None) {
Ok(Some(tpk)) => return Some(Ok(tpk)),
Ok(None) => return None,
Err(err) => return Some(Err(err)),
}
},
PacketSource::PacketParser(pp) => {
match pp.next() {
Ok((packet, ppr)) => {
if let PacketParserResult::Some(pp) = ppr {
self.source = PacketSource::PacketParser(pp);
}
match self.parse(packet) {
Ok(Some(tpk)) => return Some(Ok(tpk)),
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.tpk(None),
};
match r {
Ok(Some(tpk)) => {
if TRACE {
eprintln!("TPKParser::next => {}",
tpk.primary().fingerprint());
}
return Some(Ok(tpk));
}
Ok(None) => (),
Err(err) => return Some(Err(err)),
}
},
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn tokens() {
use crate::tpk::parser::low_level::lexer::{Token, Lexer};
use crate::tpk::parser::low_level::lexer::Token::*;
use crate::tpk::parser::low_level::TPKParser;
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.into_iter() {
if v.result {
let mut l = TPKValidator::new();
for token in v.s.into_iter() {
l.push_token((*token).clone());
assert_match!(TPKValidity::TPKPrefix = l.check());
}
l.finish();
assert_match!(TPKValidity::TPK = l.check());
}
match TPKParser::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),
}
}
}
}