Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion age-core/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const RESPONSE_FAIL: &str = "fail";
const RESPONSE_UNSUPPORTED: &str = "unsupported";

/// An error within the plugin protocol.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
Fail,
Unsupported,
Expand Down
1 change: 1 addition & 0 deletions age-plugin/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ impl<R: io::Read, W: io::Write> Callbacks<Error> for BidirCallbacks<'_, '_, R, W
}

/// The kinds of errors that can occur within the identity plugin state machine.
#[derive(PartialEq, Eq)]
pub enum Error {
/// An error caused by a specific identity.
Identity {
Expand Down
1 change: 1 addition & 0 deletions age-plugin/src/recipient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ impl<R: io::Read, W: io::Write> Callbacks<Error> for BidirCallbacks<'_, '_, R, W
}

/// The kinds of errors that can occur within the recipient plugin state machine.
#[derive(PartialEq, Eq)]
pub enum Error {
/// An error caused by a specific recipient.
Recipient {
Expand Down
17 changes: 5 additions & 12 deletions age/src/cli_common/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::io;
use crate::{DecryptError, wfl};

/// Errors that can occur while reading recipients or identities.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ReadError {
/// An error occured while decrypting passphrase-encrypted identities.
Expand All @@ -23,7 +23,7 @@ pub enum ReadError {
line_number: usize,
},
/// An I/O error occurred while reading.
Io(io::Error),
Io(io::ErrorKind, String),
/// The given recipients file could not be found.
MissingRecipientsFile(String),
/// Standard input was used by multiple files.
Expand All @@ -49,7 +49,7 @@ pub enum ReadError {

impl From<io::Error> for ReadError {
fn from(e: io::Error) -> Self {
ReadError::Io(e)
ReadError::Io(e.kind(), e.to_string())
}
}

Expand Down Expand Up @@ -83,7 +83,7 @@ impl fmt::Display for ReadError {
filename = filename.as_str(),
line_number = line_number,
),
ReadError::Io(e) => write!(f, "{e}"),
ReadError::Io(_, message) => write!(f, "{message}"),
ReadError::MissingRecipientsFile(filename) => wfl!(
f,
"err-read-missing-recipients-file",
Expand All @@ -106,11 +106,4 @@ impl fmt::Display for ReadError {
}
}

impl std::error::Error for ReadError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io(inner) => Some(inner),
_ => None,
}
}
}
impl std::error::Error for ReadError {}
2 changes: 1 addition & 1 deletion age/src/cli_common/identities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub(super) fn parse_identity_files<Ctx, E: From<ReadError> + From<io::Error>>(
#[cfg_attr(not(any(feature = "armor", feature = "ssh")), allow(unused_mut))]
let mut reader =
PeekableReader::new(stdin_guard.open(filename.clone()).map_err(|e| match e {
ReadError::Io(e) if matches!(e.kind(), io::ErrorKind::NotFound) => {
ReadError::Io(io::ErrorKind::NotFound, _) => {
ReadError::IdentityNotFound(filename.clone())
}
_ => e,
Expand Down
2 changes: 1 addition & 1 deletion age/src/cli_common/recipients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub fn read_recipients(

for arg in recipients_file_strings {
let f = stdin_guard.open(arg.clone()).map_err(|e| match e {
ReadError::Io(e) if matches!(e.kind(), io::ErrorKind::NotFound) => {
ReadError::Io(io::ErrorKind::NotFound, _) => {
ReadError::MissingRecipientsFile(arg.clone())
}
_ => e,
Expand Down
87 changes: 15 additions & 72 deletions age/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ use age_core::format::Stanza;
use crate::plugin::CMD_ERROR;

/// Errors returned when converting an identity file to a recipients file.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum IdentityFileConvertError {
/// An I/O error occurred while writing out a recipient corresponding to an identity
/// in this file.
FailedToWriteOutput(io::Error),
FailedToWriteOutput(io::ErrorKind, String),
/// The identity file contains a plugin identity, which can be converted to a
/// recipient for encryption purposes, but not for writing a recipients file.
#[cfg(feature = "plugin")]
Expand All @@ -40,8 +40,8 @@ pub enum IdentityFileConvertError {
impl fmt::Display for IdentityFileConvertError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
IdentityFileConvertError::FailedToWriteOutput(e) => {
wfl!(f, "err-failed-to-write-output", err = e.to_string())
IdentityFileConvertError::FailedToWriteOutput(_, message) => {
wfl!(f, "err-failed-to-write-output", err = message.as_str())
}
#[cfg(feature = "plugin")]
IdentityFileConvertError::IdentityFileContainsPlugin {
Expand Down Expand Up @@ -70,19 +70,12 @@ impl fmt::Display for IdentityFileConvertError {
}
}

impl std::error::Error for IdentityFileConvertError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
IdentityFileConvertError::FailedToWriteOutput(e) => Some(e),
_ => None,
}
}
}
impl std::error::Error for IdentityFileConvertError {}

/// Errors returned by a plugin.
#[cfg(feature = "plugin")]
#[cfg_attr(docsrs, doc(cfg(feature = "plugin")))]
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PluginError {
/// An error caused by a specific identity.
Identity {
Expand Down Expand Up @@ -172,7 +165,7 @@ impl fmt::Display for PluginError {
}

/// The various errors that can be returned during the encryption process.
#[derive(Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum EncryptError {
/// An error occured while decrypting passphrase-encrypted identities.
Expand All @@ -190,7 +183,7 @@ pub enum EncryptError {
/// Labels must be valid age "arbitrary string"s (`1*VCHAR` in ABNF).
InvalidRecipientLabels(HashSet<String>),
/// An I/O error occurred during encryption.
Io(io::Error),
Io(io::ErrorKind, String),
/// The encryptor was not given any recipients.
MissingRecipients,
/// [`scrypt::Recipient`] was mixed with other recipient types.
Expand All @@ -209,27 +202,7 @@ pub enum EncryptError {

impl From<io::Error> for EncryptError {
fn from(e: io::Error) -> Self {
EncryptError::Io(e)
}
}

impl Clone for EncryptError {
fn clone(&self) -> Self {
match self {
Self::EncryptedIdentities(e) => Self::EncryptedIdentities(e.clone()),
Self::IncompatibleRecipients { l_labels, r_labels } => Self::IncompatibleRecipients {
l_labels: l_labels.clone(),
r_labels: r_labels.clone(),
},
Self::InvalidRecipientLabels(labels) => Self::InvalidRecipientLabels(labels.clone()),
Self::Io(e) => Self::Io(io::Error::new(e.kind(), e.to_string())),
Self::MissingRecipients => Self::MissingRecipients,
Self::MixedRecipientAndPassphrase => Self::MixedRecipientAndPassphrase,
#[cfg(feature = "plugin")]
Self::Plugin(e) => Self::Plugin(e.clone()),
#[cfg(feature = "plugin")]
Self::PluginResolve(e) => Self::PluginResolve(e.clone()),
}
EncryptError::Io(e.kind(), e.to_string())
}
}

Expand Down Expand Up @@ -278,7 +251,7 @@ impl fmt::Display for EncryptError {
"err-invalid-recipient-labels",
labels = print_labels(labels),
),
EncryptError::Io(e) => e.fmt(f),
EncryptError::Io(_, message) => write!(f, "{message}"),
EncryptError::MissingRecipients => wfl!(f, "err-missing-recipients"),
EncryptError::MixedRecipientAndPassphrase => {
wfl!(f, "err-mixed-recipient-passphrase")
Expand All @@ -305,14 +278,13 @@ impl std::error::Error for EncryptError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
EncryptError::EncryptedIdentities(inner) => Some(inner),
EncryptError::Io(inner) => Some(inner),
_ => None,
}
}
}

/// The various errors that can be returned during the decryption process.
#[derive(Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum DecryptError {
/// The age file failed to decrypt.
Expand All @@ -329,7 +301,7 @@ pub enum DecryptError {
/// The MAC in the age header was invalid.
InvalidMac,
/// An I/O error occurred during decryption.
Io(io::Error),
Io(io::ErrorKind, String),
/// Failed to decrypt an encrypted key.
KeyDecryptionFailed,
/// None of the provided keys could be used to decrypt the age file.
Expand All @@ -346,28 +318,6 @@ pub enum DecryptError {
UnknownFormat,
}

impl Clone for DecryptError {
fn clone(&self) -> Self {
match self {
Self::DecryptionFailed => Self::DecryptionFailed,
Self::ExcessiveWork { required, target } => Self::ExcessiveWork {
required: *required,
target: *target,
},
Self::InvalidHeader => Self::InvalidHeader,
Self::InvalidMac => Self::InvalidMac,
Self::Io(e) => Self::Io(io::Error::new(e.kind(), e.to_string())),
Self::KeyDecryptionFailed => Self::KeyDecryptionFailed,
Self::NoMatchingKeys => Self::NoMatchingKeys,
#[cfg(feature = "plugin")]
Self::Plugin(e) => Self::Plugin(e.clone()),
#[cfg(feature = "plugin")]
Self::PluginResolve(e) => Self::PluginResolve(e.clone()),
Self::UnknownFormat => Self::UnknownFormat,
}
}
}

impl fmt::Display for DecryptError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Expand All @@ -382,7 +332,7 @@ impl fmt::Display for DecryptError {
}
DecryptError::InvalidHeader => wfl!(f, "err-header-invalid"),
DecryptError::InvalidMac => wfl!(f, "err-header-mac-invalid"),
DecryptError::Io(e) => e.fmt(f),
DecryptError::Io(_, message) => write!(f, "{message}"),
DecryptError::KeyDecryptionFailed => wfl!(f, "err-key-decryption"),
DecryptError::NoMatchingKeys => wfl!(f, "err-no-matching-keys"),
#[cfg(feature = "plugin")]
Expand Down Expand Up @@ -415,7 +365,7 @@ impl From<chacha20poly1305::aead::Error> for DecryptError {

impl From<io::Error> for DecryptError {
fn from(e: io::Error) -> Self {
DecryptError::Io(e)
DecryptError::Io(e.kind(), e.to_string())
}
}

Expand All @@ -433,11 +383,4 @@ impl From<rsa::errors::Error> for DecryptError {
}
}

impl std::error::Error for DecryptError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
DecryptError::Io(inner) => Some(inner),
_ => None,
}
}
}
impl std::error::Error for DecryptError {}
12 changes: 6 additions & 6 deletions age/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,10 @@ impl Header {
// currently-defined header formats are newline-separated, to more
// efficiently read data for the parser to consume.
if input.read_until(b'\n', &mut data)? == 0 {
break Err(DecryptError::Io(io::Error::new(
break Err(DecryptError::Io(
io::ErrorKind::UnexpectedEof,
"Incomplete header",
)));
"Incomplete header".to_owned(),
));
}
}
Err(_) => {
Expand Down Expand Up @@ -206,10 +206,10 @@ impl Header {
// currently-defined header formats are newline-separated, to more
// efficiently read data for the parser to consume.
if input.read_until(b'\n', &mut data).await? == 0 {
break Err(DecryptError::Io(io::Error::new(
break Err(DecryptError::Io(
io::ErrorKind::UnexpectedEof,
"Incomplete header",
)));
"Incomplete header".to_owned(),
));
}
}
Err(_) => {
Expand Down
7 changes: 5 additions & 2 deletions age/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,11 @@ impl<C: Callbacks> IdentityFile<C> {

for identity in &self.identities {
match identity {
IdentityFileEntry::Native(sk) => writeln!(output, "{}", sk.to_public())
.map_err(IdentityFileConvertError::FailedToWriteOutput)?,
IdentityFileEntry::Native(sk) => {
writeln!(output, "{}", sk.to_public()).map_err(|e| {
IdentityFileConvertError::FailedToWriteOutput(e.kind(), e.to_string())
})?
}
#[cfg(feature = "plugin")]
IdentityFileEntry::Plugin(id) => {
return Err(IdentityFileConvertError::IdentityFileContainsPlugin {
Expand Down
2 changes: 1 addition & 1 deletion age/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ impl<C: Callbacks> crate::Identity for IdentityPluginV1<C> {
}

/// Errors returned when resolving a plugin.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ResolveError {
/// A provided plugin name was invalid.
Expand Down
2 changes: 1 addition & 1 deletion age/src/primitives/armor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ impl<W: AsyncWrite> AsyncWrite for ArmoredWriter<W> {
}

/// The various errors that can be returned while parsing the armored format.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ArmoredReadError {
/// An error occurred while parsing Base64.
Expand Down
14 changes: 6 additions & 8 deletions age/tests/testkit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,14 +728,12 @@ fn check_decrypt_error(filename: &str, testfile: TestFile, e: DecryptError) {
assert_eq!(testfile.expect, Expect::HeaderFailure);
}
}
DecryptError::Io(e) => {
let kind = e.kind();
if e.into_inner().map(|inner| inner.is::<ArmoredReadError>()) == Some(true) {
assert_eq!(kind, io::ErrorKind::InvalidData);
assert_eq!(testfile.expect, Expect::ArmorFailure);
} else {
assert_eq!(testfile.expect, Expect::HeaderFailure);
}
DecryptError::Io(io::ErrorKind::InvalidData, _) => {
// Armor errors are always reported with `io::ErrorKind::InvalidData`.
assert_eq!(testfile.expect, Expect::ArmorFailure);
}
DecryptError::Io(_, _) => {
assert_eq!(testfile.expect, Expect::HeaderFailure);
}
DecryptError::ExcessiveWork { .. } | DecryptError::UnknownFormat => {
assert_eq!(testfile.expect, Expect::HeaderFailure)
Expand Down
Loading