// -*- mode: Rust; -*- use Error; use packet::Signature; use packet::UserID; use packet::UserAttribute; use packet::Key; use packet::Unknown; use Packet; use TPK; use tpk::lexer; use tpk::lexer::{Token, Component}; use tpk::{SubkeyBinding, UserIDBinding, UserAttributeBinding, UnknownBinding}; 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 TPK, or to build a TPK 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 TPK: Option = { =>? { match p { Some((Packet::PublicKey(key), sigs)) | Some((Packet::SecretKey(key), sigs)) => { let c = c.unwrap(); let mut tpk = TPK { primary: key, primary_selfsigs: vec![], primary_certifications: sigs, primary_self_revocations: vec![], primary_other_revocations: vec![], subkeys: vec![], userids: vec![], user_attributes: vec![], unknowns: vec![], bad: vec![], }; for c in c.into_iter() { match c { Component::SubkeyBinding(b) => tpk.subkeys.push(b), Component::UserIDBinding(b) => tpk.userids.push(b), Component::UserAttributeBinding(b) => tpk.user_attributes.push(b), Component::UnknownBinding(b) => tpk.unknowns.push(b), } } Ok(Some(tpk)) } Some((Packet::Unknown(unknown), _sigs)) => { Err(ParseError::User { error: Error::UnsupportedTPK(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 whereever 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::SubkeyBinding(SubkeyBinding { subkey: key, selfsigs: 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::UserIDBinding(UserIDBinding { userid: u, selfsigs: 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::UserAttributeBinding(UserAttributeBinding { user_attribute: u, selfsigs: 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::UnknownBinding(UnknownBinding { unknown: u, sigs: sigs, })) }, // 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), // 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(_, _), } }