Use error structs for errors instead of plain strings.
This commit is contained in:
parent
09745829f1
commit
7fd6923464
10 changed files with 357 additions and 99 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use crate::common::Identity;
|
||||
use crate::secret;
|
||||
use crate::server::{Mechanism, Response, Validator};
|
||||
use crate::server::{Mechanism, MechanismError, Response, Validator};
|
||||
|
||||
pub struct Plain<V: Validator<secret::Plain>> {
|
||||
validator: V,
|
||||
|
|
@ -19,19 +19,19 @@ impl<V: Validator<secret::Plain>> Mechanism for Plain<V> {
|
|||
"PLAIN"
|
||||
}
|
||||
|
||||
fn respond(&mut self, payload: &[u8]) -> Result<Response, String> {
|
||||
fn respond(&mut self, payload: &[u8]) -> Result<Response, MechanismError> {
|
||||
let mut sp = payload.split(|&b| b == 0);
|
||||
sp.next();
|
||||
let username = sp
|
||||
.next()
|
||||
.ok_or_else(|| "no username specified".to_owned())?;
|
||||
let username =
|
||||
String::from_utf8(username.to_vec()).map_err(|_| "error decoding username")?;
|
||||
.ok_or_else(|| MechanismError::NoUsernameSpecified)?;
|
||||
let username = String::from_utf8(username.to_vec())
|
||||
.map_err(|_| MechanismError::ErrorDecodingUsername)?;
|
||||
let password = sp
|
||||
.next()
|
||||
.ok_or_else(|| "no password specified".to_owned())?;
|
||||
let password =
|
||||
String::from_utf8(password.to_vec()).map_err(|_| "error decoding password")?;
|
||||
.ok_or_else(|| MechanismError::NoPasswordSpecified)?;
|
||||
let password = String::from_utf8(password.to_vec())
|
||||
.map_err(|_| MechanismError::ErrorDecodingPassword)?;
|
||||
let ident = Identity::Username(username);
|
||||
self.validator.validate(&ident, &secret::Plain(password))?;
|
||||
Ok(Response::Success(ident, Vec::new()))
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::common::scram::{generate_nonce, ScramProvider};
|
|||
use crate::common::{parse_frame, xor, ChannelBinding, Identity};
|
||||
use crate::secret;
|
||||
use crate::secret::Pbkdf2Secret;
|
||||
use crate::server::{Mechanism, Provider, Response};
|
||||
use crate::server::{Mechanism, MechanismError, Provider, Response};
|
||||
|
||||
enum ScramState {
|
||||
Init,
|
||||
|
|
@ -61,7 +61,7 @@ where
|
|||
&self.name
|
||||
}
|
||||
|
||||
fn respond(&mut self, payload: &[u8]) -> Result<Response, String> {
|
||||
fn respond(&mut self, payload: &[u8]) -> Result<Response, MechanismError> {
|
||||
let next_state;
|
||||
let ret;
|
||||
match self.state {
|
||||
|
|
@ -82,7 +82,7 @@ where
|
|||
}
|
||||
}
|
||||
if commas < 2 {
|
||||
return Err("failed to decode message".to_owned());
|
||||
return Err(MechanismError::FailedToDecodeMessage);
|
||||
}
|
||||
let gs2_header = payload[..idx].to_vec();
|
||||
let rest = payload[idx..].to_vec();
|
||||
|
|
@ -92,29 +92,29 @@ where
|
|||
// Not supported.
|
||||
if gs2_header[0] != 0x79 {
|
||||
// ord("y")
|
||||
return Err("channel binding not supported".to_owned());
|
||||
return Err(MechanismError::ChannelBindingNotSupported);
|
||||
}
|
||||
}
|
||||
ref other => {
|
||||
// Supported.
|
||||
if gs2_header[0] == 0x79 {
|
||||
// ord("y")
|
||||
return Err("channel binding is supported".to_owned());
|
||||
return Err(MechanismError::ChannelBindingIsSupported);
|
||||
} else if !other.supports("tls-unique") {
|
||||
// TODO: grab the data
|
||||
return Err("channel binding mechanism incorrect".to_owned());
|
||||
return Err(MechanismError::ChannelBindingMechanismIncorrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
let frame =
|
||||
parse_frame(&rest).map_err(|_| "can't decode initial message".to_owned())?;
|
||||
let username = frame.get("n").ok_or_else(|| "no username".to_owned())?;
|
||||
parse_frame(&rest).map_err(|_| MechanismError::CannotDecodeInitialMessage)?;
|
||||
let username = frame.get("n").ok_or_else(|| MechanismError::NoUsername)?;
|
||||
let identity = Identity::Username(username.to_owned());
|
||||
let client_nonce = frame.get("r").ok_or_else(|| "no nonce".to_owned())?;
|
||||
let client_nonce = frame.get("r").ok_or_else(|| MechanismError::NoNonce)?;
|
||||
let mut server_nonce = String::new();
|
||||
server_nonce += client_nonce;
|
||||
server_nonce +=
|
||||
&generate_nonce().map_err(|_| "failed to generate nonce".to_owned())?;
|
||||
&generate_nonce().map_err(|_| MechanismError::FailedToGenerateNonce)?;
|
||||
let pbkdf2 = self.provider.provide(&identity)?;
|
||||
let mut buf = Vec::new();
|
||||
buf.extend(b"r=");
|
||||
|
|
@ -141,7 +141,8 @@ where
|
|||
ref initial_client_message,
|
||||
ref initial_server_message,
|
||||
} => {
|
||||
let frame = parse_frame(payload).map_err(|_| "can't decode response".to_owned())?;
|
||||
let frame =
|
||||
parse_frame(payload).map_err(|_| MechanismError::CannotDecodeResponse)?;
|
||||
let mut cb_data: Vec<u8> = Vec::new();
|
||||
cb_data.extend(gs2_header);
|
||||
cb_data.extend(self.channel_binding.data());
|
||||
|
|
@ -161,11 +162,11 @@ where
|
|||
let stored_key = S::hash(&client_key);
|
||||
let client_signature = S::hmac(&auth_message, &stored_key)?;
|
||||
let client_proof = xor(&client_key, &client_signature);
|
||||
let sent_proof = frame.get("p").ok_or_else(|| "no proof".to_owned())?;
|
||||
let sent_proof = frame.get("p").ok_or_else(|| MechanismError::NoProof)?;
|
||||
let sent_proof =
|
||||
base64::decode(sent_proof).map_err(|_| "can't decode proof".to_owned())?;
|
||||
base64::decode(sent_proof).map_err(|_| MechanismError::CannotDecodeProof)?;
|
||||
if client_proof != sent_proof {
|
||||
return Err("authentication failed".to_owned());
|
||||
return Err(MechanismError::AuthenticationFailed);
|
||||
}
|
||||
let server_signature = S::hmac(&auth_message, &server_key)?;
|
||||
let mut buf = Vec::new();
|
||||
|
|
@ -175,7 +176,7 @@ where
|
|||
next_state = ScramState::Done;
|
||||
}
|
||||
ScramState::Done => {
|
||||
return Err("sasl session is already over".to_owned());
|
||||
return Err(MechanismError::SaslSessionAlreadyOver);
|
||||
}
|
||||
}
|
||||
self.state = next_state;
|
||||
|
|
|
|||
Loading…
Reference in a new issue