diff --git a/lettre/Cargo.toml b/lettre/Cargo.toml index 0d3f1b7..503a261 100644 --- a/lettre/Cargo.toml +++ b/lettre/Cargo.toml @@ -24,10 +24,7 @@ nom = { version = "^3.2", optional = true } bufstream = { version = "^0.1", optional = true } native-tls = { version = "^0.1", optional = true } base64 = { version = "^0.9", optional = true } -hex = { version = "^0.3", optional = true } hostname = { version = "^0.1", optional = true } -md-5 = { version = "^0.7", optional = true } -hmac = { version = "^0.6", optional = true } serde = { version = "^1.0", optional = true } serde_json = { version = "^1.0", optional = true } serde_derive = { version = "^1.0", optional = true } @@ -41,7 +38,6 @@ default = ["file-transport", "smtp-transport", "sendmail-transport"] unstable = [] serde-impls = ["serde", "serde_derive"] file-transport = ["serde-impls", "serde_json"] -crammd5-auth = ["md-5", "hmac", "hex"] smtp-transport = ["bufstream", "native-tls", "base64", "nom", "hostname"] sendmail-transport = [] diff --git a/lettre/src/lib.rs b/lettre/src/lib.rs index b120073..07a22cb 100644 --- a/lettre/src/lib.rs +++ b/lettre/src/lib.rs @@ -10,16 +10,10 @@ extern crate base64; #[cfg(feature = "smtp-transport")] extern crate bufstream; -#[cfg(feature = "crammd5-auth")] -extern crate hex; -#[cfg(feature = "crammd5-auth")] -extern crate hmac; #[cfg(feature = "smtp-transport")] extern crate hostname; #[macro_use] extern crate log; -#[cfg(feature = "crammd5-auth")] -extern crate md5; #[cfg(feature = "smtp-transport")] extern crate native_tls; #[cfg(feature = "smtp-transport")] diff --git a/lettre/src/smtp/authentication.rs b/lettre/src/smtp/authentication.rs index 1a359b7..589f909 100644 --- a/lettre/src/smtp/authentication.rs +++ b/lettre/src/smtp/authentication.rs @@ -1,31 +1,14 @@ -//! Provides authentication mechanisms +//! Provides limited SASL authentication mechanisms -#[cfg(feature = "crammd5-auth")] -use md5::Md5; -#[cfg(feature = "crammd5-auth")] -use hmac::{Hmac, Mac}; -#[cfg(feature = "crammd5-auth")] -use hex; use smtp::NUL; use smtp::error::Error; use std::fmt::{self, Display, Formatter}; /// Accepted authentication mechanisms on an encrypted connection /// Trying LOGIN last as it is deprecated. -#[cfg(feature = "crammd5-auth")] -pub const DEFAULT_ENCRYPTED_MECHANISMS: &[Mechanism] = - &[Mechanism::Plain, Mechanism::CramMd5, Mechanism::Login]; -/// Accepted authentication mechanisms on an encrypted connection -/// Trying LOGIN last as it is deprecated. -#[cfg(not(feature = "crammd5-auth"))] pub const DEFAULT_ENCRYPTED_MECHANISMS: &[Mechanism] = &[Mechanism::Plain, Mechanism::Login]; /// Accepted authentication mechanisms on an unencrypted connection -#[cfg(feature = "crammd5-auth")] -pub const DEFAULT_UNENCRYPTED_MECHANISMS: &[Mechanism] = &[Mechanism::CramMd5]; -/// Accepted authentication mechanisms on an unencrypted connection -/// When CRAMMD5 support is not enabled, no mechanisms are allowed. -#[cfg(not(feature = "crammd5-auth"))] pub const DEFAULT_UNENCRYPTED_MECHANISMS: &[Mechanism] = &[]; /// Convertable to user credentials @@ -51,14 +34,14 @@ impl, T: Into> IntoCredentials for (S, T) { #[derive(PartialEq, Eq, Clone, Hash, Debug)] #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))] pub struct Credentials { - username: String, - password: String, + authentication_identity: String, + secret: String, } impl Credentials { /// Create a `Credentials` struct from username and password pub fn new(username: String, password: String) -> Credentials { - Credentials { username, password } + Credentials { authentication_identity: username, secret: password } } } @@ -73,10 +56,6 @@ pub enum Mechanism { /// Obsolete but needed for some providers (like office365) /// https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt Login, - /// CRAM-MD5 authentication mechanism - /// RFC 2195: https://tools.ietf.org/html/rfc2195 - #[cfg(feature = "crammd5-auth")] - CramMd5, } impl Display for Mechanism { @@ -87,8 +66,6 @@ impl Display for Mechanism { match *self { Mechanism::Plain => "PLAIN", Mechanism::Login => "LOGIN", - #[cfg(feature = "crammd5-auth")] - Mechanism::CramMd5 => "CRAM-MD5", } ) } @@ -101,8 +78,6 @@ impl Mechanism { match *self { Mechanism::Plain => true, Mechanism::Login => false, - #[cfg(feature = "crammd5-auth")] - Mechanism::CramMd5 => false, } } @@ -118,7 +93,7 @@ impl Mechanism { Some(_) => Err(Error::Client("This mechanism does not expect a challenge")), None => Ok(format!( "{}{}{}{}", - NUL, credentials.username, NUL, credentials.password + NUL, credentials.authentication_identity, NUL, credentials.secret )), }, Mechanism::Login => { @@ -128,32 +103,15 @@ impl Mechanism { }; if vec!["User Name", "Username:", "Username"].contains(&decoded_challenge) { - return Ok(credentials.username.to_string()); + return Ok(credentials.authentication_identity.to_string()); } if vec!["Password", "Password:"].contains(&decoded_challenge) { - return Ok(credentials.password.to_string()); + return Ok(credentials.secret.to_string()); } Err(Error::Client("Unrecognized challenge")) } - #[cfg(feature = "crammd5-auth")] - Mechanism::CramMd5 => { - let decoded_challenge = match challenge { - Some(challenge) => challenge, - None => return Err(Error::Client("This mechanism does expect a challenge")), - }; - - let mut hmac: Hmac = Hmac::new_varkey(credentials.password.as_bytes()) - .expect("md5 should support variable key size"); - hmac.input(decoded_challenge.as_bytes()); - - Ok(format!( - "{} {}", - credentials.username, - hex::encode(hmac.result().code()) - )) - } } } } @@ -191,23 +149,4 @@ mod test { ); assert!(mechanism.response(&credentials, None).is_err()); } - - #[test] - #[cfg(feature = "crammd5-auth")] - fn test_cram_md5() { - let mechanism = Mechanism::CramMd5; - - let credentials = Credentials::new("alice".to_string(), "wonderland".to_string()); - - assert_eq!( - mechanism - .response( - &credentials, - Some("PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==") - ) - .unwrap(), - "alice a540ebe4ef2304070bbc3c456c1f64c0" - ); - assert!(mechanism.response(&credentials, None).is_err()); - } } diff --git a/lettre/src/smtp/commands.rs b/lettre/src/smtp/commands.rs index 9052a14..9f3762a 100644 --- a/lettre/src/smtp/commands.rs +++ b/lettre/src/smtp/commands.rs @@ -313,8 +313,6 @@ impl AuthCommand { mod test { use super::*; use smtp::extension::MailBodyParameter; - #[cfg(feature = "crammd5-auth")] - use smtp::response::{Category, Code, Detail, Severity}; #[test] fn test_display() { @@ -391,18 +389,6 @@ mod test { ), "AUTH PLAIN AHVzZXIAcGFzc3dvcmQ=\r\n" ); - #[cfg(feature = "crammd5-auth")] - assert_eq!( - format!( - "{}", - AuthCommand::new( - Mechanism::CramMd5, - credentials.clone(), - Some("test".to_string()), - ).unwrap() - ), - "dXNlciAzMTYxY2NmZDdmMjNlMzJiYmMzZTQ4NjdmYzk0YjE4Nw==\r\n" - ); assert_eq!( format!( "{}", @@ -410,24 +396,5 @@ mod test { ), "AUTH LOGIN\r\n" ); - #[cfg(feature = "crammd5-auth")] - assert_eq!( - format!( - "{}", - AuthCommand::new_from_response( - Mechanism::CramMd5, - credentials.clone(), - &Response::new( - Code::new( - Severity::PositiveIntermediate, - Category::Unspecified3, - Detail::Four, - ), - vec!["dGVzdAo=".to_string()], - ), - ).unwrap() - ), - "dXNlciA1NTIzNThiMzExOWFjOWNkYzM2YWRiN2MxNWRmMWJkNw==\r\n" - ); } } diff --git a/lettre/src/smtp/extension.rs b/lettre/src/smtp/extension.rs index 1ddab70..b4fba39 100644 --- a/lettre/src/smtp/extension.rs +++ b/lettre/src/smtp/extension.rs @@ -145,10 +145,6 @@ impl ServerInfo { "LOGIN" => { features.insert(Extension::Authentication(Mechanism::Login)); } - #[cfg(feature = "crammd5-auth")] - "CRAM-MD5" => { - features.insert(Extension::Authentication(Mechanism::CramMd5)); - } _ => (), } }, @@ -357,8 +353,6 @@ mod test { assert!(server_info.supports_feature(Extension::EightBitMime)); assert!(!server_info.supports_feature(Extension::StartTls)); - #[cfg(feature = "crammd5-auth")] - assert!(!server_info.supports_auth_mechanism(Mechanism::CramMd5)); let response2 = Response::new( Code::new( @@ -377,8 +371,6 @@ mod test { let mut features2 = HashSet::new(); assert!(features2.insert(Extension::EightBitMime)); assert!(features2.insert(Extension::Authentication(Mechanism::Plain),)); - #[cfg(feature = "crammd5-auth")] - assert!(features2.insert(Extension::Authentication(Mechanism::CramMd5),)); let server_info2 = ServerInfo { name: "me".to_string(), @@ -389,8 +381,6 @@ mod test { assert!(server_info2.supports_feature(Extension::EightBitMime)); assert!(server_info2.supports_auth_mechanism(Mechanism::Plain)); - #[cfg(feature = "crammd5-auth")] - assert!(server_info2.supports_auth_mechanism(Mechanism::CramMd5)); assert!(!server_info2.supports_feature(Extension::StartTls)); } } diff --git a/lettre/src/smtp/mod.rs b/lettre/src/smtp/mod.rs index b99172b..4d6d84f 100644 --- a/lettre/src/smtp/mod.rs +++ b/lettre/src/smtp/mod.rs @@ -8,8 +8,7 @@ //! It implements the following extensions: //! //! * 8BITMIME ([RFC 6152](https://tools.ietf.org/html/rfc6152)) -//! * AUTH ([RFC 4954](http://tools.ietf.org/html/rfc4954)) with PLAIN, LOGIN and -//! CRAM-MD5 mechanisms +//! * AUTH ([RFC 4954](http://tools.ietf.org/html/rfc4954)) with PLAIN, LOGIN mechanisms //! * STARTTLS ([RFC 2487](http://tools.ietf.org/html/rfc2487)) //! * SMTPUTF8 ([RFC 6531](http://tools.ietf.org/html/rfc6531)) //!