Skip to content

Commit

Permalink
rage: Detect PowerShell corruption during decryption
Browse files Browse the repository at this point in the history
This matches the detection done by `age`.

Closes #287.
  • Loading branch information
str4d committed Mar 20, 2022
1 parent 804b783 commit 01c0519
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
3 changes: 3 additions & 0 deletions rage/i18n/en-US/rage.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ err-enc-plugin-name-flag = {-flag-plugin-name} can't be used with {-flag-encrypt
## Decryption errors

err-detected-powershell-corruption = It looks like this file was corrupted by PowerShell redirection.
rec-detected-powershell-corruption = Consider using -o or -a to encrypt files in PowerShell.
rec-dec-excessive-work = To decrypt, retry with {-flag-max-work-factor} {$wf}
err-dec-armor-flag = {-flag-armor} can't be used with {-flag-decrypt}.
Expand Down
12 changes: 12 additions & 0 deletions rage/src/bin/rage/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ impl fmt::Display for EncryptError {
}
}

#[derive(Debug)]
pub(crate) struct DetectedPowerShellCorruptionError;

impl fmt::Display for DetectedPowerShellCorruptionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
wlnfl!(f, "err-detected-powershell-corruption")?;
wfl!(f, "rec-detected-powershell-corruption")
}
}

impl std::error::Error for DetectedPowerShellCorruptionError {}

pub(crate) enum DecryptError {
Age(age::DecryptError),
ArmorFlag,
Expand Down
21 changes: 21 additions & 0 deletions rage/src/bin/rage/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,27 @@ fn decrypt(opts: AgeOptions) -> Result<(), error::DecryptError> {

let (input, output) = set_up_io(opts.input, opts.output, file_io::OutputFormat::Unknown)?;

// CRLF_MANGLED_INTRO and UTF16_MANGLED_INTRO are the intro lines of the age format after
// mangling by various versions of PowerShell redirection, truncated to the length of the
// correct intro line. See https://github.com/FiloSottile/age/issues/290 for more info.
const CRLF_MANGLED_INTRO: &[u8] = b"age-encryption.org/v1\r";
const UTF16_MANGLED_INTRO: &[u8] =
b"\xff\xfea\x00g\x00e\x00-\x00e\x00n\x00c\x00r\x00y\x00p\x00";
let err_powershell_corruption = Box::new(|| {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
error::DetectedPowerShellCorruptionError,
))
});

let input = ReadChecker::new(
input,
[
(CRLF_MANGLED_INTRO, err_powershell_corruption.clone()),
(UTF16_MANGLED_INTRO, err_powershell_corruption),
],
);

match age::Decryptor::new(ArmoredReader::new(input))? {
age::Decryptor::Passphrase(decryptor) => {
// The `rpassword` crate opens `/dev/tty` directly on Unix, so we don't have
Expand Down

0 comments on commit 01c0519

Please sign in to comment.