summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-12-09 12:35:42 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-12-09 12:58:57 +0100
commitf8b6d65101e964803c5261903481b43c07591e6c (patch)
tree9dd2c3ebe1df121afa8b2d9a12db0174940f2d30
parent63ba6252eb546e07b8f35274a9f69d1f9bc99c0e (diff)
net: Allow hkp queries by KeyHandle.
-rw-r--r--ffi/src/net.rs4
-rw-r--r--net/src/lib.rs27
-rw-r--r--net/tests/hkp.rs5
-rw-r--r--sq/src/sq-usage.rs4
-rw-r--r--sq/src/sq.rs37
-rw-r--r--sq/src/sq_cli.rs5
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<Cert> {
- let keyid_want = keyid.clone();
+ /// Retrieves the certificate with the given handle.
+ pub async fn get<H: Into<KeyHandle>>(&mut self, handle: H)
+ -> Result<Cert>
+ {
+ 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] <KEYID>
+//! sq keyserver get [FLAGS] [OPTIONS] <QUERY>
//!
//! FLAGS:
//! -B, --binary Don't ASCII-armor encode the OpenPGP data
@@ -323,7 +323,7 @@
//! -o, --output <FILE> Sets the output file to use
//!
//! ARGS:
-//! <KEYID> ID of the key to retrieve
+//! <QUERY> 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<KeyHandle> = {
+ let q_fp = query.parse::<Fingerprint>();
+ let q_id = query.parse::<KeyID>();
+ 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")