Refactor user ID resolution.
- Add `UserIDDesignators::resolve` to resolve user ID designators for a given certificate. - Use it from `sq pki certify` and `sq pki authorize`.
This commit is contained in:
parent
1a32d11c8f
commit
2caba0758e
@ -1,12 +1,10 @@
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::packet::UserID;
|
||||
use openpgp::Result;
|
||||
use openpgp::types::KeyFlags;
|
||||
|
||||
use crate::Sq;
|
||||
use crate::cli::pki::authorize;
|
||||
use crate::cli::types::FileStdinOrKeyHandle;
|
||||
use crate::cli::types::userid_designator::UserIDDesignator;
|
||||
use crate::commands::FileOrStdout;
|
||||
use crate::parse_notations;
|
||||
|
||||
@ -35,93 +33,8 @@ pub fn authorize(sq: Sq, mut c: authorize::Command)
|
||||
}
|
||||
|
||||
let vc = cert.with_policy(sq.policy, Some(sq.time))?;
|
||||
|
||||
// Find the matching User ID.
|
||||
let mut userids = Vec::new();
|
||||
|
||||
// Don't stop at the first error.
|
||||
let mut missing = false;
|
||||
let mut bad = None;
|
||||
|
||||
for designator in c.userids.iter() {
|
||||
match designator {
|
||||
UserIDDesignator::UserID(userid) => {
|
||||
let userid = UserID::from(&userid[..]);
|
||||
|
||||
// If --add-userid is specified, we use the user ID as
|
||||
// is. Otherwise, we make sure there is a matching
|
||||
// self-signed user ID.
|
||||
if c.userids.add_userid().unwrap_or(false) {
|
||||
userids.push(userid.clone());
|
||||
} else if let Some(_) = vc.userids()
|
||||
.find(|ua| {
|
||||
ua.userid() == &userid
|
||||
})
|
||||
{
|
||||
userids.push(userid.clone());
|
||||
} else {
|
||||
wprintln!("{:?} is not a self-signed user ID.",
|
||||
String::from_utf8_lossy(userid.value()));
|
||||
missing = true;
|
||||
}
|
||||
}
|
||||
UserIDDesignator::Email(email) => {
|
||||
// Validate the email address.
|
||||
let userid = match UserID::from_address(None, None, email) {
|
||||
Ok(userid) => userid,
|
||||
Err(err) => {
|
||||
wprintln!("{:?} is not a valid email address: {}",
|
||||
email, err);
|
||||
bad = Some(err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Extract a normalized version for comparison
|
||||
// purposes.
|
||||
let email_normalized = match userid.email_normalized() {
|
||||
Ok(Some(email)) => email,
|
||||
Ok(None) => {
|
||||
wprintln!("{:?} is not a valid email address", email);
|
||||
bad = Some(anyhow::anyhow!(format!(
|
||||
"{:?} is not a valid email address", email)));
|
||||
continue;
|
||||
}
|
||||
Err(err) => {
|
||||
wprintln!("{:?} is not a valid email address: {}",
|
||||
email, err);
|
||||
bad = Some(err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Find any the matching self-signed user IDs.
|
||||
let mut found = false;
|
||||
for ua in vc.userids() {
|
||||
if Some(&email_normalized)
|
||||
== ua.email_normalized().unwrap_or(None).as_ref()
|
||||
{
|
||||
userids.push(ua.userid().clone());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ! found {
|
||||
if c.userids.add_userid().unwrap_or(false) {
|
||||
// Add the bare email address.
|
||||
userids.push(userid);
|
||||
} else {
|
||||
eprintln!("The email address {:?} does not match any \
|
||||
user IDs.",
|
||||
email);
|
||||
missing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if missing || userids.is_empty() {
|
||||
let mut userids = c.userids.resolve(&vc)?;
|
||||
if userids.is_empty() {
|
||||
// Use all self-signed User IDs.
|
||||
userids = vc.userids()
|
||||
.map(|ua| ua.userid().clone())
|
||||
@ -135,10 +48,6 @@ pub fn authorize(sq: Sq, mut c: authorize::Command)
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(err) = bad {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
let notations = parse_notations(&c.notation)?;
|
||||
|
||||
crate::common::pki::certify::certify(
|
||||
|
@ -1,12 +1,10 @@
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::packet::UserID;
|
||||
use openpgp::Result;
|
||||
use openpgp::types::KeyFlags;
|
||||
|
||||
use crate::Sq;
|
||||
use crate::cli::pki::certify;
|
||||
use crate::cli::types::FileStdinOrKeyHandle;
|
||||
use crate::cli::types::userid_designator::UserIDDesignator;
|
||||
use crate::commands::FileOrStdout;
|
||||
use crate::parse_notations;
|
||||
|
||||
@ -35,112 +33,7 @@ pub fn certify(sq: Sq, mut c: certify::Command)
|
||||
}
|
||||
|
||||
let vc = cert.with_policy(sq.policy, Some(sq.time))?;
|
||||
|
||||
// Find the matching User ID.
|
||||
let mut userids = Vec::new();
|
||||
|
||||
// Don't stop at the first error.
|
||||
let mut missing = false;
|
||||
let mut bad = None;
|
||||
|
||||
for designator in c.userids.iter() {
|
||||
match designator {
|
||||
UserIDDesignator::UserID(userid) => {
|
||||
let userid = UserID::from(&userid[..]);
|
||||
|
||||
// If --add-userid is specified, we use the user ID as
|
||||
// is. Otherwise, we make sure there is a matching
|
||||
// self-signed user ID.
|
||||
if c.userids.add_userid().unwrap_or(false) {
|
||||
userids.push(userid.clone());
|
||||
} else if let Some(_) = vc.userids()
|
||||
.find(|ua| {
|
||||
ua.userid() == &userid
|
||||
})
|
||||
{
|
||||
userids.push(userid.clone());
|
||||
} else {
|
||||
wprintln!("{:?} is not a self-signed user ID.",
|
||||
String::from_utf8_lossy(userid.value()));
|
||||
missing = true;
|
||||
}
|
||||
}
|
||||
UserIDDesignator::Email(email) => {
|
||||
// Validate the email address.
|
||||
let userid = match UserID::from_address(None, None, email) {
|
||||
Ok(userid) => userid,
|
||||
Err(err) => {
|
||||
wprintln!("{:?} is not a valid email address: {}",
|
||||
email, err);
|
||||
bad = Some(err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Extract a normalized version for comparison
|
||||
// purposes.
|
||||
let email_normalized = match userid.email_normalized() {
|
||||
Ok(Some(email)) => email,
|
||||
Ok(None) => {
|
||||
wprintln!("{:?} is not a valid email address", email);
|
||||
bad = Some(anyhow::anyhow!(format!(
|
||||
"{:?} is not a valid email address", email)));
|
||||
continue;
|
||||
}
|
||||
Err(err) => {
|
||||
wprintln!("{:?} is not a valid email address: {}",
|
||||
email, err);
|
||||
bad = Some(err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Find any the matching self-signed user IDs.
|
||||
let mut found = false;
|
||||
for ua in vc.userids() {
|
||||
if Some(&email_normalized)
|
||||
== ua.email_normalized().unwrap_or(None).as_ref()
|
||||
{
|
||||
userids.push(ua.userid().clone());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ! found {
|
||||
if c.userids.add_userid().unwrap_or(false) {
|
||||
// Add the bare email address.
|
||||
userids.push(userid);
|
||||
} else {
|
||||
eprintln!("The email address {:?} does not match any \
|
||||
user IDs.",
|
||||
email);
|
||||
missing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if missing {
|
||||
wprintln!("{}'s self-signed user IDs:", vc.fingerprint());
|
||||
let mut have_valid = false;
|
||||
for ua in vc.userids() {
|
||||
if let Ok(u) = std::str::from_utf8(ua.userid().value()) {
|
||||
have_valid = true;
|
||||
wprintln!(" - {:?}", u);
|
||||
}
|
||||
}
|
||||
if ! have_valid {
|
||||
wprintln!(" - Certificate has no valid user IDs.");
|
||||
}
|
||||
wprintln!("Pass `--add-userid` to certify a user ID even if it \
|
||||
isn't self signed.");
|
||||
return Err(anyhow::anyhow!("Not a self-signed user ID"));
|
||||
};
|
||||
|
||||
if let Some(err) = bad {
|
||||
return Err(err);
|
||||
}
|
||||
let userids = c.userids.resolve(&vc)?;
|
||||
|
||||
let notations = parse_notations(&c.notation)?;
|
||||
|
||||
|
@ -20,6 +20,8 @@ pub mod password;
|
||||
pub mod pki;
|
||||
pub mod userid;
|
||||
|
||||
pub mod types;
|
||||
|
||||
pub const NULL_POLICY: &NullPolicy = &NullPolicy::new();
|
||||
|
||||
/// Something like a User ID.
|
||||
|
1
src/common/types/mod.rs
Normal file
1
src/common/types/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod userid_designator;
|
120
src/common/types/userid_designator.rs
Normal file
120
src/common/types/userid_designator.rs
Normal file
@ -0,0 +1,120 @@
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::cert::ValidCert;
|
||||
use openpgp::packet::UserID;
|
||||
|
||||
use crate::Result;
|
||||
use crate::cli::types::UserIDDesignators;
|
||||
use crate::cli::types::userid_designator::UserIDDesignator;
|
||||
|
||||
impl<Arguments, Options> UserIDDesignators<Arguments, Options> {
|
||||
/// Resolve the user ID designators.
|
||||
pub fn resolve(&self, vc: &ValidCert) -> Result<Vec<UserID>> {
|
||||
// Find the matching User ID.
|
||||
let mut userids = Vec::new();
|
||||
|
||||
// Don't stop at the first error.
|
||||
let mut missing = false;
|
||||
let mut bad = None;
|
||||
|
||||
for designator in self.iter() {
|
||||
match designator {
|
||||
UserIDDesignator::UserID(userid) => {
|
||||
let userid = UserID::from(&userid[..]);
|
||||
|
||||
// If --add-userid is specified, we use the user ID as
|
||||
// is. Otherwise, we make sure there is a matching
|
||||
// self-signed user ID.
|
||||
if self.add_userid().unwrap_or(false) {
|
||||
userids.push(userid.clone());
|
||||
} else if let Some(_) = vc.userids()
|
||||
.find(|ua| {
|
||||
ua.userid() == &userid
|
||||
})
|
||||
{
|
||||
userids.push(userid.clone());
|
||||
} else {
|
||||
wprintln!("{:?} is not a self-signed user ID.",
|
||||
String::from_utf8_lossy(userid.value()));
|
||||
missing = true;
|
||||
}
|
||||
}
|
||||
UserIDDesignator::Email(email) => {
|
||||
// Validate the email address.
|
||||
let userid = match UserID::from_address(None, None, email) {
|
||||
Ok(userid) => userid,
|
||||
Err(err) => {
|
||||
wprintln!("{:?} is not a valid email address: {}",
|
||||
email, err);
|
||||
bad = Some(err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Extract a normalized version for comparison
|
||||
// purposes.
|
||||
let email_normalized = match userid.email_normalized() {
|
||||
Ok(Some(email)) => email,
|
||||
Ok(None) => {
|
||||
wprintln!("{:?} is not a valid email address", email);
|
||||
bad = Some(anyhow::anyhow!(format!(
|
||||
"{:?} is not a valid email address", email)));
|
||||
continue;
|
||||
}
|
||||
Err(err) => {
|
||||
wprintln!("{:?} is not a valid email address: {}",
|
||||
email, err);
|
||||
bad = Some(err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Find any the matching self-signed user IDs.
|
||||
let mut found = false;
|
||||
for ua in vc.userids() {
|
||||
if Some(&email_normalized)
|
||||
== ua.email_normalized().unwrap_or(None).as_ref()
|
||||
{
|
||||
userids.push(ua.userid().clone());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ! found {
|
||||
if self.add_userid().unwrap_or(false) {
|
||||
// Add the bare email address.
|
||||
userids.push(userid);
|
||||
} else {
|
||||
eprintln!("The email address {:?} does not match any \
|
||||
user IDs.",
|
||||
email);
|
||||
missing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if missing {
|
||||
wprintln!("{}'s self-signed user IDs:", vc.fingerprint());
|
||||
let mut have_valid = false;
|
||||
for ua in vc.userids() {
|
||||
if let Ok(u) = std::str::from_utf8(ua.userid().value()) {
|
||||
have_valid = true;
|
||||
wprintln!(" - {:?}", u);
|
||||
}
|
||||
}
|
||||
if ! have_valid {
|
||||
wprintln!(" - Certificate has no valid user IDs.");
|
||||
}
|
||||
wprintln!("Pass `--add-userid` to certify a user ID even if it \
|
||||
isn't self signed.");
|
||||
return Err(anyhow::anyhow!("Not a self-signed user ID"));
|
||||
};
|
||||
|
||||
if let Some(err) = bad {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
Ok(userids)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user