Error management for authentication

This commit is contained in:
Alexis Mousset
2015-07-14 11:18:49 +02:00
parent 75de338409
commit e6b46faa06
5 changed files with 26 additions and 14 deletions

View File

@@ -16,6 +16,7 @@ use crypto::md5::Md5;
use crypto::mac::Mac;
use NUL;
use error::Error;
/// Returns a PLAIN mecanism response
pub fn plain(username: &str, password: &str) -> String {
@@ -23,14 +24,16 @@ pub fn plain(username: &str, password: &str) -> String {
}
/// Returns a CRAM-MD5 mecanism response
pub fn cram_md5(username: &str, password: &str, encoded_challenge: &str) -> String {
// TODO manage errors
let challenge = encoded_challenge.from_base64().unwrap();
pub fn cram_md5(username: &str, password: &str, encoded_challenge: &str) -> Result<String, Error> {
let challenge = match encoded_challenge.from_base64() {
Ok(challenge) => challenge,
Err(error) => return Err(Error::ChallengeParsingError(error)),
};
let mut hmac = Hmac::new(Md5::new(), password.as_bytes());
hmac.input(&challenge);
format!("{} {}", username, hmac.result().code().to_hex()).as_bytes().to_base64(base64::STANDARD)
Ok(format!("{} {}", username, hmac.result().code().to_hex()).as_bytes().to_base64(base64::STANDARD))
}
#[cfg(test)]
@@ -45,7 +48,7 @@ mod test {
#[test]
fn test_cram_md5() {
assert_eq!(cram_md5("alice", "wonderland",
"PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg=="),
"PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==").unwrap(),
"YWxpY2UgNjRiMmE0M2MxZjZlZDY4MDZhOTgwOTE0ZTIzZTc1ZjA=");
}
}

View File

@@ -16,7 +16,7 @@ use std::io::{BufRead, Read, Write};
use bufstream::BufStream;
use response::ResponseParser;
use error::SmtpResult;
use error::{Error, SmtpResult};
use client::net::{Connector, SmtpStream};
use client::authentication::{plain, cram_md5};
use {CRLF, MESSAGE_ENDING};
@@ -175,8 +175,14 @@ impl<S: Connector + Write + Read = SmtpStream> Client<S> {
/// Sends an AUTH command with CRAM-MD5 mecanism
pub fn auth_cram_md5(&mut self, username: &str, password: &str) -> SmtpResult {
let encoded_challenge = try!(self.command("AUTH CRAM-MD5")).first_word().expect("No challenge");
self.command(&format!("AUTH CRAM-MD5 {}", cram_md5(username, password, &encoded_challenge)))
let encoded_challenge = match try!(self.command("AUTH CRAM-MD5")).first_word() {
Some(challenge) => challenge,
None => return Err(Error::ResponseParsingError("Could not read CRAM challenge")),
};
let cram_response = try!(cram_md5(username, password, &encoded_challenge));
self.command(&format!("AUTH CRAM-MD5 {}", cram_response))
}
/// Sends the message content