Test authentication functions
This commit is contained in:
51
src/client/authentication.rs
Normal file
51
src/client/authentication.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2014 Alexis Mousset. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Provides authentications functions
|
||||
|
||||
use serialize::base64::{self, ToBase64, FromBase64};
|
||||
use serialize::hex::ToHex;
|
||||
use crypto::hmac::Hmac;
|
||||
use crypto::md5::Md5;
|
||||
use crypto::mac::Mac;
|
||||
|
||||
use tools::NUL;
|
||||
|
||||
/// Returns a PLAIN mecanism response
|
||||
pub fn plain(username: &str, password: &str) -> String {
|
||||
format!("{}{}{}{}", NUL, username, NUL, password).as_bytes().to_base64(base64::STANDARD)
|
||||
}
|
||||
|
||||
/// 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();
|
||||
|
||||
let mut hmac = Hmac::new(Md5::new(), password.as_bytes());
|
||||
hmac.input(challenge.as_slice());
|
||||
|
||||
format!("{} {}", username, hmac.result().code().to_hex()).as_bytes().to_base64(base64::STANDARD)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{plain, cram_md5};
|
||||
|
||||
#[test]
|
||||
fn test_plain() {
|
||||
assert_eq!(plain("username", "password").as_slice(), "AHVzZXJuYW1lAHBhc3N3b3Jk");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cram_md5() {
|
||||
assert_eq!(cram_md5("alice", "wonderland",
|
||||
"PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==").as_slice(),
|
||||
"YWxpY2UgNjRiMmE0M2MxZjZlZDY4MDZhOTgwOTE0ZTIzZTc1ZjA=");
|
||||
}
|
||||
}
|
||||
@@ -15,19 +15,15 @@ use std::net::TcpStream;
|
||||
use std::net::{SocketAddr, ToSocketAddrs};
|
||||
use std::io::{BufRead, BufStream, Read, Write};
|
||||
|
||||
use serialize::base64::{self, ToBase64, FromBase64};
|
||||
use serialize::hex::ToHex;
|
||||
use crypto::hmac::Hmac;
|
||||
use crypto::md5::Md5;
|
||||
use crypto::mac::Mac;
|
||||
|
||||
use tools::{NUL, CRLF, MESSAGE_ENDING};
|
||||
use tools::{CRLF, MESSAGE_ENDING};
|
||||
use tools::{escape_dot, escape_crlf};
|
||||
use response::{Response, Severity, Category};
|
||||
use error::SmtpResult;
|
||||
use client::connecter::Connecter;
|
||||
use client::authentication::{plain, cram_md5};
|
||||
|
||||
pub mod connecter;
|
||||
mod authentication;
|
||||
|
||||
/// Structure that implements the SMTP client
|
||||
pub struct Client<S = TcpStream> {
|
||||
@@ -172,22 +168,13 @@ impl<S: Connecter + Write + Read = TcpStream> Client<S> {
|
||||
|
||||
/// Sends an AUTH command with PLAIN mecanism
|
||||
pub fn auth_plain(&mut self, username: &str, password: &str) -> SmtpResult {
|
||||
let auth_string = format!("{}{}{}{}", NUL, username, NUL, password);
|
||||
self.command(format!("AUTH PLAIN {}", auth_string.as_bytes().to_base64(base64::STANDARD)).as_slice())
|
||||
self.command(format!("AUTH PLAIN {}", plain(username, password)).as_slice())
|
||||
}
|
||||
|
||||
/// Sends an AUTH command with CRAM-MD5 mecanism
|
||||
pub fn auth_cram_md5(&mut self, username: &str, password: &str) -> SmtpResult {
|
||||
let encoded_challenge = try_smtp!(self.command("AUTH CRAM-MD5"), self).first_word().expect("No challenge");
|
||||
// TODO manage errors
|
||||
let challenge = encoded_challenge.from_base64().unwrap();
|
||||
|
||||
let mut hmac = Hmac::new(Md5::new(), password.as_bytes());
|
||||
hmac.input(challenge.as_slice());
|
||||
|
||||
let auth_string = format!("{} {}", username, hmac.result().code().to_hex());
|
||||
|
||||
self.command(format!("AUTH CRAM-MD5 {}", auth_string.as_bytes().to_base64(base64::STANDARD)).as_slice())
|
||||
self.command(format!("AUTH CRAM-MD5 {}", cram_md5(username, password, encoded_challenge.as_slice())).as_slice())
|
||||
}
|
||||
|
||||
/// Sends the message content and close
|
||||
|
||||
Reference in New Issue
Block a user