Make decryption and verification helpers public, add quiet mode.

This commit is contained in:
Justus Winter 2024-01-29 15:05:44 +01:00
parent ab9c3bf875
commit cf39ba74d8
No known key found for this signature in database
GPG Key ID: 686F55B4AB2B3386
3 changed files with 110 additions and 29 deletions

View File

@ -396,7 +396,7 @@ pub fn cert_stub(cert: Cert,
Ok(Cert::from_packets(packets.into_iter())?)
}
struct VHelper<'a, 'store> {
pub struct VHelper<'a, 'store> {
#[allow(dead_code)]
config: &'a Config<'store>,
signatures: usize,
@ -409,6 +409,7 @@ struct VHelper<'a, 'store> {
bad_signatures: usize,
bad_checksums: usize,
broken_signatures: usize,
quiet: bool,
}
impl<'a, 'store> VHelper<'a, 'store> {
@ -427,9 +428,17 @@ impl<'a, 'store> VHelper<'a, 'store> {
bad_signatures: 0,
bad_checksums: 0,
broken_signatures: 0,
quiet: false,
}
}
/// Enables or disables quiet operation.
///
/// In quiet operation, only errors are emitted.
pub fn quiet(&mut self, v: bool) {
self.quiet = v;
}
fn print_status(&self) {
fn p(s: &mut String, what: &str, quantity: usize) {
if quantity > 0 {
@ -456,6 +465,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
}
fn print_sigs(&mut self, results: &[VerificationResult]) {
make_qprintln!(self.quiet);
use crate::commands::pki::output::print_path;
use crate::print_error_chain;
@ -526,7 +536,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
prefix = " ";
// Web of trust.
wprintln!("Authenticating {} ({:?}) using the web of trust:",
qprintln!("Authenticating {} ({:?}) using the web of trust:",
cert_fpr, signer_userid);
if let Ok(Some(cert_store)) = self.config.cert_store() {
@ -536,7 +546,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
let userids = if let Some(userid) = sig.signers_user_id() {
let userid = UserID::from(userid);
wprintln!("{}Signature was made by {}",
qprintln!("{}Signature was made by {}",
prefix,
String::from_utf8_lossy(userid.value()));
vec![ userid ]
@ -545,7 +555,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
};
if userids.is_empty() {
wprintln!("{}{} cannot be authenticated. \
qprintln!("{}{} cannot be authenticated. \
It has no User IDs",
prefix, cert_fpr);
} else if let Ok(n) = sequoia_wot::Network::new(&cert_store) {
@ -565,7 +575,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
let amount = paths.amount();
let authenticated = if amount >= sequoia_wot::FULLY_TRUSTED {
wprintln!("{}Fully authenticated \
qprintln!("{}Fully authenticated \
({} of {}) {}, {}",
prefix,
amount,
@ -574,7 +584,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
userid_str);
true
} else if amount > 0 {
wprintln!("{}Partially authenticated \
qprintln!("{}Partially authenticated \
({} of {}) {}, {:?} ",
prefix,
amount,
@ -583,7 +593,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
userid_str);
false
} else {
wprintln!("{}{}: {:?} is unauthenticated \
qprintln!("{}{}: {:?} is unauthenticated \
and may be an impersonation!",
prefix,
cert_fpr,
@ -593,7 +603,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
for (i, (path, amount)) in paths.iter().enumerate() {
let prefix = if paths.len() > 1 {
wprintln!("{} Path #{} of {}, \
qprintln!("{} Path #{} of {}, \
trust amount {}:",
prefix,
i + 1, paths.len(), amount);
@ -602,7 +612,10 @@ impl<'a, 'store> VHelper<'a, 'store> {
format!("{} ", prefix)
};
print_path(&path.into(), userid, &prefix)
if ! self.quiet {
print_path(&path.into(), userid,
&prefix);
}
}
authenticated
@ -617,10 +630,10 @@ impl<'a, 'store> VHelper<'a, 'store> {
authenticated_userids[0].value()).to_string();
}
} else {
wprintln!("Failed to build web of trust network.");
qprintln!("Failed to build web of trust network.");
}
} else {
wprintln!("Skipping, certificate store has been disabled");
qprintln!("Skipping, certificate store has been disabled");
}
}
@ -630,27 +643,27 @@ impl<'a, 'store> VHelper<'a, 'store> {
let level = sig.level();
match (level == 0, trusted) {
(true, true) => {
wprintln!("{}Good signature from {} ({:?})",
qprintln!("{}Good signature from {} ({:?})",
prefix, label, signer_userid);
}
(false, true) => {
wprintln!("{}Good level {} notarization from {} ({:?})",
qprintln!("{}Good level {} notarization from {} ({:?})",
prefix, level, label, signer_userid);
}
(true, false) => {
wprintln!("{}Unauthenticated checksum from {} ({:?})",
qprintln!("{}Unauthenticated checksum from {} ({:?})",
prefix, label, signer_userid);
wprintln!("{} After checking that {} belongs to {:?}, \
qprintln!("{} After checking that {} belongs to {:?}, \
you can authenticate the binding using \
'sq link add {} {:?}'.",
prefix, issuer_str, signer_userid,
issuer_str, signer_userid);
}
(false, false) => {
wprintln!("{}Unauthenticated level {} notarizing \
qprintln!("{}Unauthenticated level {} notarizing \
checksum from {} ({:?})",
prefix, level, label, signer_userid);
wprintln!("{} After checking that {} belongs to {:?}, \
qprintln!("{} After checking that {} belongs to {:?}, \
you can authenticate the binding using \
'sq link add {} {:?}'.",
prefix, issuer_str, signer_userid,
@ -664,7 +677,7 @@ impl<'a, 'store> VHelper<'a, 'store> {
self.good_checksums += 1;
}
wprintln!("");
qprintln!("");
}
}
}
@ -723,16 +736,17 @@ impl<'a, 'store> VerificationHelper for VHelper<'a, 'store> {
}
fn check(&mut self, structure: MessageStructure) -> Result<()> {
make_qprintln!(self.quiet);
for layer in structure {
match layer {
MessageLayer::Compression { algo } =>
wprintln!("Compressed using {}", algo),
qprintln!("Compressed using {}", algo),
MessageLayer::Encryption { sym_algo, aead_algo } =>
if let Some(aead_algo) = aead_algo {
wprintln!("Encrypted and protected using {}/{}",
qprintln!("Encrypted and protected using {}/{}",
sym_algo, aead_algo);
} else {
wprintln!("Encrypted using {}", sym_algo);
qprintln!("Encrypted using {}", sym_algo);
},
MessageLayer::SignatureGroup { ref results } =>
self.print_sigs(results),
@ -743,7 +757,9 @@ impl<'a, 'store> VerificationHelper for VHelper<'a, 'store> {
&& self.bad_signatures + self.bad_checksums == 0 {
Ok(())
} else {
self.print_status();
if ! self.quiet {
self.print_status();
}
Err(anyhow::anyhow!("Verification failed: could not fully \
authenticate any signatures"))
}

View File

@ -131,7 +131,7 @@ impl PrivateKey for RemotePrivateKey {
}
}
struct Helper<'a, 'certdb> {
pub struct Helper<'a, 'certdb> {
vhelper: VHelper<'a, 'certdb>,
secret_keys: HashMap<KeyID, Box<dyn PrivateKey>>,
key_identities: HashMap<KeyID, Fingerprint>,
@ -141,12 +141,26 @@ struct Helper<'a, 'certdb> {
dumper: Option<PacketDumper>,
}
impl<'a, 'certdb> std::ops::Deref for Helper<'a, 'certdb> {
type Target = VHelper<'a, 'certdb>;
fn deref(&self) -> &Self::Target {
&self.vhelper
}
}
impl<'a, 'certdb> std::ops::DerefMut for Helper<'a, 'certdb> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.vhelper
}
}
impl<'a, 'certdb> Helper<'a, 'certdb> {
fn new(config: &'a Config<'certdb>, private_key_store: Option<&str>,
signatures: usize, certs: Vec<Cert>, secrets: Vec<Cert>,
session_keys: Vec<cli::types::SessionKey>,
dump_session_key: bool, dump: bool)
-> Self
pub fn new(config: &'a Config<'certdb>, private_key_store: Option<&str>,
signatures: usize, certs: Vec<Cert>, secrets: Vec<Cert>,
session_keys: Vec<cli::types::SessionKey>,
dump_session_key: bool, dump: bool)
-> Self
{
let mut keys: HashMap<KeyID, Box<dyn PrivateKey>> = HashMap::new();
let mut identities: HashMap<KeyID, Fingerprint> = HashMap::new();
@ -250,6 +264,8 @@ impl<'a, 'certdb> DecryptionHelper for Helper<'a, 'certdb> {
mut decrypt: D) -> openpgp::Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
{
make_qprintln!(self.quiet);
// Before anything else, try the session keys
for sk in &self.session_keys {
let decrypted = if let Some(sa) = sk.symmetric_algo {
@ -262,7 +278,8 @@ impl<'a, 'certdb> DecryptionHelper for Helper<'a, 'certdb> {
.any(|sa| decrypt(sa, &sk.session_key))
};
if decrypted {
wprintln!("Encrypted with Session Key {}", sk.display_sensitive());
qprintln!("Encrypted with Session Key {}",
sk.display_sensitive());
return Ok(None);
}
}

View File

@ -22,3 +22,51 @@ macro_rules! wprintln {
crate::output::wrapping::wprintln(format_args!($($arg),*))
};
}
/// Like wprintln, but doesn't emit anything in quiet mode.
macro_rules! make_qprintln {
($quiet: expr) => {
macro_rules! qprintln {
{} => {
if ! $quiet {
wprintln!();
}
};
{ $a0: expr } => {
if ! $quiet {
wprintln!($a0);
}
};
{ $a0: expr, $a1: expr } => {
if ! $quiet {
wprintln!($a0, $a1);
}
};
{ $a0: expr, $a1: expr, $a2: expr } => {
if ! $quiet {
wprintln!($a0, $a1, $a2);
}
};
{ $a0: expr, $a1: expr, $a2: expr, $a3: expr } => {
if ! $quiet {
wprintln!($a0, $a1, $a2, $a3);
}
};
{ $a0: expr, $a1: expr, $a2: expr, $a3: expr, $a4: expr } => {
if ! $quiet {
wprintln!($a0, $a1, $a2, $a3, $a4);
}
};
{ $a0: expr, $a1: expr, $a2: expr, $a3: expr, $a4: expr, $a5: expr } => {
if ! $quiet {
wprintln!($a0, $a1, $a2, $a3, $a4, $a5);
}
};
{ $a0: expr, $a1: expr, $a2: expr, $a3: expr, $a4: expr, $a5: expr, $a6: expr } => {
if ! $quiet {
wprintln!($a0, $a1, $a2, $a3, $a4, $a5, $a6);
}
};
}
};
}