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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
use base64::DecodeError as base64Error; use std::error::Error as StdError; use std::fmt; use std::io::Error as ioError; use std::sync::mpsc::RecvError as channelError; #[derive(Debug)] pub enum YubicoError { Network(reqwest::Error), HTTPStatusCode(reqwest::StatusCode), IOError(ioError), ChannelError(channelError), DecodeError(base64Error), #[cfg(feature = "online-tokio")] MultipleErrors(Vec<YubicoError>), BadOTP, ReplayedOTP, BadSignature, MissingParameter, NoSuchClient, OperationNotAllowed, BackendError, NotEnoughAnswers, ReplayedRequest, UnknownStatus, OTPMismatch, NonceMismatch, SignatureMismatch, InvalidKeyLength, } impl fmt::Display for YubicoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { YubicoError::Network(ref err) => write!(f, "Connectivity error: {}", err), YubicoError::HTTPStatusCode(code) => write!(f, "Error found: {}", code), YubicoError::IOError(ref err) => write!(f, "IO error: {}", err), YubicoError::ChannelError(ref err) => write!(f, "Channel error: {}", err), YubicoError::DecodeError(ref err) => write!(f, "Decode error: {}", err), #[cfg(feature = "online-tokio")] YubicoError::MultipleErrors(ref errs) => { write!(f, "Multiple errors. ")?; for err in errs { write!(f, "{} ", err)?; } Ok(()) } YubicoError::BadOTP => write!(f, "The OTP has invalid format."), YubicoError::ReplayedOTP => write!(f, "The OTP has already been seen by the service."), YubicoError::BadSignature => write!(f, "The HMAC signature verification failed."), YubicoError::MissingParameter => write!(f, "The request lacks a parameter."), YubicoError::NoSuchClient => write!(f, "The request id does not exist."), YubicoError::OperationNotAllowed => { write!(f, "The request id is not allowed to verify OTPs.") } YubicoError::BackendError => write!( f, "Unexpected error in our server. Please contact us if you see this error." ), YubicoError::NotEnoughAnswers => write!( f, "Server could not get requested number of syncs during before timeout" ), YubicoError::ReplayedRequest => { write!(f, "Server has seen the OTP/Nonce combination before") } YubicoError::UnknownStatus => { write!(f, "Unknown status sent by the OTP validation server") } YubicoError::OTPMismatch => write!(f, "OTP mismatch, It may be an attack attempt"), YubicoError::NonceMismatch => write!(f, "Nonce mismatch, It may be an attack attempt"), YubicoError::SignatureMismatch => { write!(f, "Signature mismatch, It may be an attack attempt") } YubicoError::InvalidKeyLength => { write!(f, "Invalid key length encountered while building signature") } } } } impl StdError for YubicoError { fn description(&self) -> &str { match *self { YubicoError::Network(ref err) => err.description(), YubicoError::HTTPStatusCode(_) => "200 not received", YubicoError::IOError(ref err) => err.description(), YubicoError::ChannelError(ref err) => err.description(), YubicoError::DecodeError(ref err) => err.description(), #[cfg(feature = "online-tokio")] YubicoError::MultipleErrors(ref _errs) => { "Multiple errors. " } YubicoError::BadOTP => "The OTP has invalid format.", YubicoError::ReplayedOTP => "The OTP has already been seen by the service.", YubicoError::BadSignature => "The HMAC signature verification failed.", YubicoError::MissingParameter => "The request lacks a parameter.", YubicoError::NoSuchClient => "The request id does not exist.", YubicoError::OperationNotAllowed => "The request id is not allowed to verify OTPs.", YubicoError::BackendError => "Unexpected error in our server. Please contact us if you see this error.", YubicoError::NotEnoughAnswers => "Server could not get requested number of syncs during before timeout", YubicoError::ReplayedRequest => "Server has seen the OTP/Nonce combination before", YubicoError::UnknownStatus => "Unknown status sent by the OTP validation server", YubicoError::OTPMismatch => "OTP in the response is the same as the supplied in the request. It may be an attack attempt", YubicoError::NonceMismatch => "Nonce in the response is the same as the supplied in the request. It may be an attack attempt", YubicoError::SignatureMismatch => "Signature in the response is the same as the supplied in the request. It may be an attack attempt", YubicoError::InvalidKeyLength => "Invalid key length", } } fn cause(&self) -> Option<&dyn StdError> { match *self { YubicoError::Network(ref err) => Some(err), YubicoError::HTTPStatusCode(_) => None, YubicoError::IOError(ref err) => Some(err), YubicoError::ChannelError(ref err) => Some(err), YubicoError::DecodeError(ref err) => Some(err), #[cfg(feature = "online-tokio")] YubicoError::MultipleErrors(ref errs) => match errs.first() { Some(err) => Some(err), None => None, }, _ => None, } } } impl From<reqwest::Error> for YubicoError { fn from(err: reqwest::Error) -> YubicoError { YubicoError::Network(err) } } impl From<reqwest::StatusCode> for YubicoError { fn from(err: reqwest::StatusCode) -> YubicoError { YubicoError::HTTPStatusCode(err) } } impl From<ioError> for YubicoError { fn from(err: ioError) -> YubicoError { YubicoError::IOError(err) } } impl From<channelError> for YubicoError { fn from(err: channelError) -> YubicoError { YubicoError::ChannelError(err) } } impl From<base64Error> for YubicoError { fn from(err: base64Error) -> YubicoError { YubicoError::DecodeError(err) } }