1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use aes_ctr::cipher::stream::InvalidKeyNonceLength;
use block_padding::{PadError, UnpadError};
use hmac::crypto_mac::MacError;
use std::error::Error;
use std::fmt;

/// A specialized `Result` type for decrypting Ansible vaults results
pub type Result<T> = std::result::Result<T, VaultError>;

/// The error type for decrypting Ansible vaults.
#[derive(Debug)]
pub struct VaultError {
    pub kind: ErrorKind,
    pub message: String,
}

#[derive(Debug, PartialEq)]
pub enum ErrorKind {
    Error,
    IoError,
    NotAVault,
    InvalidFormat,
    IncorrectSecret,
}

fn kind_message(kind: &ErrorKind) -> &str {
    match kind {
        ErrorKind::Error => "Error !",
        ErrorKind::IoError => "Io error",
        ErrorKind::NotAVault => "Input is not a vault",
        ErrorKind::InvalidFormat => "Invalid data format : vault is incorrect",
        ErrorKind::IncorrectSecret => "Invalid secret",
    }
}

impl VaultError {
    pub fn new(kind: ErrorKind, message: &str) -> Self {
        VaultError {
            kind,
            message: message.to_string(),
        }
    }

    pub fn from_kind(kind: ErrorKind) -> Self {
        let msg = kind_message(&kind).to_string();

        VaultError { kind, message: msg }
    }

    pub fn from_string(message: &str) -> Self {
        VaultError {
            kind: ErrorKind::Error,
            message: message.to_string(),
        }
    }
}

impl fmt::Display for VaultError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl Error for VaultError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl From<&str> for VaultError {
    fn from(s: &str) -> Self {
        VaultError::from_string(s)
    }
}

impl std::cmp::PartialEq for VaultError {
    fn eq(&self, other: &VaultError) -> bool {
        self.kind.eq(&other.kind)
    }
}

impl From<std::io::Error> for VaultError {
    fn from(error: std::io::Error) -> Self {
        VaultError::new(ErrorKind::IoError, &error.to_string())
    }
}

impl From<std::string::FromUtf8Error> for VaultError {
    fn from(error: std::string::FromUtf8Error) -> Self {
        VaultError::new(ErrorKind::InvalidFormat, &error.to_string())
    }
}

impl From<hex::FromHexError> for VaultError {
    fn from(error: hex::FromHexError) -> Self {
        VaultError::new(ErrorKind::InvalidFormat, &error.to_string())
    }
}

impl From<hmac::crypto_mac::InvalidKeyLength> for VaultError {
    fn from(error: hmac::crypto_mac::InvalidKeyLength) -> Self {
        VaultError::new(ErrorKind::InvalidFormat, &error.to_string())
    }
}

impl From<MacError> for VaultError {
    fn from(error: MacError) -> Self {
        VaultError::new(ErrorKind::IncorrectSecret, &error.to_string())
    }
}

impl From<PadError> for VaultError {
    fn from(_error: PadError) -> Self {
        VaultError::new(ErrorKind::InvalidFormat, "Padding error")
    }
}

impl From<UnpadError> for VaultError {
    fn from(_error: UnpadError) -> Self {
        VaultError::new(ErrorKind::InvalidFormat, "Padding error")
    }
}

impl From<InvalidKeyNonceLength> for VaultError {
    fn from(error: InvalidKeyNonceLength) -> Self {
        VaultError::new(ErrorKind::InvalidFormat, &error.to_string())
    }
}