// -*- mode: Rust; -*- use crate::Error; use crate::packet::Signature; use crate::packet::UserID; use crate::packet::UserAttribute; use crate::packet::{key, Key}; use crate::packet::Unknown; use crate::Packet; use crate::cert::prelude::*; use crate::cert::parser::low_level::lexer; use crate::cert::parser::low_level::lexer::{Token, Component}; use crate::cert::ComponentBundles; use crate::cert::bundle::{ PrimaryKeyBundle, SubkeyBundle, UserIDBundle, UserAttributeBundle, UnknownBundle, }; use lalrpop_util::ParseError; grammar; // The parser is used in two ways: it can either be used to check // whether a sequence of packets forms a Cert, or to build a Cert from a // sequence of packets. In the former case, we only need the packet // tags; in the latter case, we also need the packets. To handle both // situations, the token includes the tag and an optional packet. // When invoking the parser, it is essential, that either *all* tokens // have no packet, or they all have a packet; mixing the two types of // tokens will result in a crash. pub Cert: Option = { =>? { match p { Some((Packet::PublicKey(_), _)) | Some((Packet::SecretKey(_), _)) => { let (key, sigs) = match p { Some((Packet::PublicKey(key), sigs)) => (key, sigs), Some((Packet::SecretKey(key), sigs)) => (key.into(), sigs), _ => unreachable!(), }; let c = c.unwrap(); let mut cert = Cert { primary: PrimaryKeyBundle { component: key, self_signatures: vec![], certifications: sigs, self_revocations: vec![], other_revocations: vec![], }, subkeys: ComponentBundles::new(), userids: ComponentBundles::new(), user_attributes: ComponentBundles::new(), unknowns: ComponentBundles::new(), bad: vec![], }; for c in c.into_iter() { match c { Component::SubkeyBundle(b) => cert.subkeys.push(b), Component::UserIDBundle(b) => cert.userids.push(b), Component::UserAttributeBundle(b) => cert.user_attributes.push(b), Component::UnknownBundle(b) => cert.unknowns.push(b), } } Ok(Some(cert)) } Some((Packet::Unknown(unknown), _sigs)) => { Err(ParseError::User { error: Error::UnsupportedCert(format!( "Unsupported primary key: Unparsable {} ({:?}).", unknown.tag(), unknown).into()) }) } None => { // Just validating a message... assert!(c.is_none() || c.unwrap().len() == 0); Ok(None) } Some((pkt, _)) => unreachable!("Expected key or unknown packet, got {:?}", pkt), } } }; Primary: Option<(Packet, Vec)> = { => { if let Some(pk) = pk { Some((pk, sigs.unwrap())) } else { // Just validating a message... assert!(sigs.is_none() || sigs.unwrap().len() == 0); None } } } PrimaryKey: Option = { => t.into(), => t.into(), }; OptionalSignatures: Option> = { => Some(vec![]), => { match sig { Token::Signature(Some(Packet::Signature(sig))) => { assert!(sigs.is_some()); let mut sigs = sigs.unwrap(); sigs.push(sig); Some(sigs) } Token::Signature(Some(Packet::Unknown(_sig))) => { // Ignore unsupported / bad signatures. assert!(sigs.is_some()); sigs } // Just validating a message... Token::Signature(None) => return None, tok => unreachable!("Expected signature token, got {:?}", tok), } }, // A trust packet can go wherever a signature can go, but they // are ignored. TRUST, } OptionalComponents: Option> = { => Some(vec![]), => { if let Some(c) = c { let mut cs = cs.unwrap(); cs.push(c); Some(cs) } else { // Just validating a message... None } }, } Component: Option = { => { match key { Some(key) => { let sigs = sigs.unwrap(); Some(Component::SubkeyBundle(SubkeyBundle { component: key, self_signatures: vec![], certifications: sigs, self_revocations: vec![], other_revocations: vec![], })) }, // Just validating a message... None => None, } }, => { match u { Some(u) => { let sigs = sigs.unwrap(); Some(Component::UserIDBundle(UserIDBundle { component: u, self_signatures: vec![], certifications: sigs, self_revocations: vec![], other_revocations: vec![], })) }, // Just validating a message... None => None, } }, => { match u { Some(u) => { let sigs = sigs.unwrap(); Some(Component::UserAttributeBundle(UserAttributeBundle { component: u, self_signatures: vec![], certifications: sigs, self_revocations: vec![], other_revocations: vec![], })) }, // Just validating a message... None => None, } }, => { match u { Some(u) => { let sigs = sigs.unwrap(); Some(Component::UnknownBundle(UnknownBundle { component: u, self_signatures: vec![], certifications: sigs, self_revocations: vec![], other_revocations: vec![], })) }, // Just validating a message... None => None, } }, } Subkey: Option> = { => { match t.into() { Some(Packet::PublicSubkey(key)) => Some(key), // Just validating a message... None => None, Some(pkt) => unreachable!("Expected public subkey packet, got {:?}", pkt), } }, => { match t.into() { Some(Packet::SecretSubkey(key)) => Some(key.parts_into_public()), // Just validating a message... None => None, Some(pkt) => unreachable!("Expected secret subkey packet, got {:?}", pkt), } }, } UserID: Option = { => { match t.into() { Some(Packet::UserID(u)) => Some(u), // Just validating a message... None => None, Some(pkt) => unreachable!("Expected user id packet, got {:?}", pkt), } }, } UserAttribute: Option = { => { match t.into() { Some(Packet::UserAttribute(u)) => Some(u), // Just validating a message... None => None, Some(pkt) => unreachable!("Expected user attribute packet, got {:?}", pkt), } }, } Unknown: Option = { => { match t.into() { Some(Packet::Unknown(u)) => Some(u), // Just validating a message... None => None, Some(pkt) => unreachable!("Expected unknown packet, got {:?}", pkt), } }, } extern { type Location = usize; type Error = Error; enum lexer::Token { PUBLIC_KEY => lexer::Token::PublicKey(_), SECRET_KEY => lexer::Token::SecretKey(_), PUBLIC_SUBKEY => lexer::Token::PublicSubkey(_), SECRET_SUBKEY => lexer::Token::SecretSubkey(_), USERID => lexer::Token::UserID(_), USER_ATTRIBUTE => lexer::Token::UserAttribute(_), SIGNATURE => lexer::Token::Signature(_), TRUST => lexer::Token::Trust(_), UNKNOWN => lexer::Token::Unknown(_, _), } }