From f8b6d65101e964803c5261903481b43c07591e6c Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Wed, 9 Dec 2020 12:35:42 +0100 Subject: net: Allow hkp queries by KeyHandle. --- ffi/src/net.rs | 4 ++-- net/src/lib.rs | 27 +++++++++++++++------------ net/tests/hkp.rs | 5 +++-- sq/src/sq-usage.rs | 4 ++-- sq/src/sq.rs | 37 +++++++++++++++++++++++++++---------- sq/src/sq_cli.rs | 5 +++-- 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/ffi/src/net.rs b/ffi/src/net.rs index 3a4abe2f..60154838 100644 --- a/ffi/src/net.rs +++ b/ffi/src/net.rs @@ -121,10 +121,10 @@ fn sq_keyserver_get(ctx: *mut Context, let ctx = ffi_param_ref_mut!(ctx); ffi_make_fry_from_ctx!(ctx); let ks = ffi_param_ref_mut!(ks); - let id = id.ref_raw(); + let id = id.ref_raw().clone(); let mut core = ffi_try_or!(basic_runtime(), None); - core.block_on(ks.get(&id)).move_into_raw(Some(ctx.errp())) + core.block_on(ks.get(id)).move_into_raw(Some(ctx.errp())) } /// Sends the given key to the server. diff --git a/net/src/lib.rs b/net/src/lib.rs index d39c62cc..b1cfe70f 100644 --- a/net/src/lib.rs +++ b/net/src/lib.rs @@ -20,8 +20,8 @@ //! # async fn f() -> Result<()> { //! let ctx = Context::new()?; //! let mut ks = KeyServer::keys_openpgp_org(&ctx)?; -//! let keyid = "31855247603831FD".parse()?; -//! println!("{:?}", ks.get(&keyid).await?); +//! let keyid: KeyID = "31855247603831FD".parse()?; +//! println!("{:?}", ks.get(keyid).await?); //! # Ok(()) //! # } //! ``` @@ -41,7 +41,7 @@ use url::Url; use sequoia_openpgp::Cert; use sequoia_openpgp::parse::Parse; -use sequoia_openpgp::{KeyID, armor, serialize::Serialize}; +use sequoia_openpgp::{KeyHandle, armor, serialize::Serialize}; use sequoia_core::{Context, NetworkPolicy}; pub mod wkd; @@ -130,11 +130,14 @@ impl KeyServer { Ok(KeyServer{client, uri}) } - /// Retrieves the key with the given `keyid`. - pub async fn get(&mut self, keyid: &KeyID) -> Result { - let keyid_want = keyid.clone(); + /// Retrieves the certificate with the given handle. + pub async fn get>(&mut self, handle: H) + -> Result + { + let handle = handle.into(); + let want_handle = handle.clone(); let uri = self.uri.join( - &format!("pks/lookup?op=get&options=mr&search=0x{:X}", keyid))?; + &format!("pks/lookup?op=get&options=mr&search=0x{:X}", handle))?; let res = self.client.do_get(uri).await?; match res.status() { @@ -145,10 +148,10 @@ impl KeyServer { armor::ReaderMode::Tolerant(Some(armor::Kind::PublicKey)), ); let cert = Cert::from_reader(r)?; - if cert.keys().any(|ka| KeyID::from(ka.fingerprint()) == keyid_want) { + if cert.keys().any(|ka| ka.key_handle().aliases(&want_handle)) { Ok(cert) } else { - Err(Error::MismatchedKeyID(keyid_want, cert).into()) + Err(Error::MismatchedKeyHandle(want_handle, cert).into()) } } StatusCode::NOT_FOUND => Err(Error::NotFound.into()), @@ -226,9 +229,9 @@ pub enum Error { /// A requested key was not found. #[error("Key not found")] NotFound, - /// Mismatched key ID - #[error("Mismatched key ID, expected {0}")] - MismatchedKeyID(KeyID, Cert), + /// Mismatched key handle + #[error("Mismatched key handle, expected {0}")] + MismatchedKeyHandle(KeyHandle, Cert), /// A given keyserver URI was malformed. #[error("Malformed URI; expected hkp: or hkps:")] MalformedUri, diff --git a/net/tests/hkp.rs b/net/tests/hkp.rs index 544c4533..8dafe9a6 100644 --- a/net/tests/hkp.rs +++ b/net/tests/hkp.rs @@ -7,6 +7,7 @@ use rand::rngs::OsRng; use std::io::Cursor; use std::net::{SocketAddr, IpAddr, Ipv4Addr}; +use sequoia_openpgp::KeyID; use sequoia_openpgp::armor::Reader; use sequoia_openpgp::Cert; use sequoia_openpgp::parse::Parse; @@ -128,8 +129,8 @@ async fn get() -> anyhow::Result<()> { let addr = start_server(); let mut keyserver = KeyServer::new(&ctx, &format!("hkp://{}", addr))?; - let keyid = ID.parse()?; - let key = keyserver.get(&keyid).await?; + let keyid: KeyID = ID.parse()?; + let key = keyserver.get(keyid).await?; assert_eq!(key.fingerprint(), FP.parse().unwrap()); diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs index 05814ced..1e232f26 100644 --- a/sq/src/sq-usage.rs +++ b/sq/src/sq-usage.rs @@ -312,7 +312,7 @@ //! Retrieves a key //! //! USAGE: -//! sq keyserver get [FLAGS] [OPTIONS] +//! sq keyserver get [FLAGS] [OPTIONS] //! //! FLAGS: //! -B, --binary Don't ASCII-armor encode the OpenPGP data @@ -323,7 +323,7 @@ //! -o, --output Sets the output file to use //! //! ARGS: -//! ID of the key to retrieve +//! Fingerprint or KeyID of the key to retrieve //! ``` //! //! ### Subcommand keyserver send diff --git a/sq/src/sq.rs b/sq/src/sq.rs index 36e57c83..266a8bd8 100644 --- a/sq/src/sq.rs +++ b/sq/src/sq.rs @@ -17,7 +17,12 @@ use sequoia_core; use sequoia_net; use sequoia_store as store; -use crate::openpgp::Result; +use openpgp::{ + Result, + Fingerprint, + KeyID, + KeyHandle, +}; use crate::openpgp::{armor, Cert}; use sequoia_autocrypt as autocrypt; use crate::openpgp::fmt::hex; @@ -425,18 +430,30 @@ fn main() -> Result<()> { match m.subcommand() { ("get", Some(m)) => { - let keyid = m.value_of("keyid").unwrap(); - let id = keyid.parse(); - if id.is_err() { - eprintln!("Malformed key ID: {:?}\n\ - (Note: only long Key IDs are supported.)", - keyid); - exit(1); + let query = m.value_of("query").unwrap(); + + let handle: Option = { + let q_fp = query.parse::(); + let q_id = query.parse::(); + if let Ok(Fingerprint::V4(_)) = q_fp { + q_fp.ok().map(Into::into) + } else if let Ok(KeyID::V4(_)) = q_id { + q_fp.ok().map(Into::into) + } else { + None + } + }; + + if handle.is_none() { + Err(anyhow::anyhow!( + "Malformed key handle: {:?}\n\ + (Note: only Fingerprints long KeyIDs are \ + supported.)", query))?; } - let id = id.unwrap(); + let handle = handle.unwrap(); let mut output = create_or_stdout(m.value_of("output"), force)?; - let cert = rt.block_on(ks.get(&id)) + let cert = rt.block_on(ks.get(handle)) .context("Failed to retrieve key")?; if ! m.is_present("binary") { cert.armored().serialize(&mut output) diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs index 5bb5f80b..c4c8fd73 100644 --- a/sq/src/sq_cli.rs +++ b/sq/src/sq_cli.rs @@ -302,9 +302,10 @@ pub fn build() -> App<'static, 'static> { .long("binary") .short("B") .help("Don't ASCII-armor encode the OpenPGP data")) - .arg(Arg::with_name("keyid").value_name("KEYID") + .arg(Arg::with_name("query").value_name("QUERY") .required(true) - .help("ID of the key to retrieve"))) + .help("Fingerprint or KeyID of the key \ + to retrieve"))) .subcommand(SubCommand::with_name("send") .about("Sends a key") .arg(Arg::with_name("input").value_name("FILE") -- cgit v1.2.3