2017-02-28 12:05:17 +00:00
|
|
|
#![deny(missing_docs)]
|
|
|
|
|
|
|
|
//! This crate provides a framework for SASL authentication and a few authentication mechanisms.
|
|
|
|
//!
|
|
|
|
//! # Examples
|
|
|
|
//!
|
|
|
|
//! ```rust
|
2017-03-07 16:02:57 +00:00
|
|
|
//! use sasl::{Credentials, Mechanism, Error};
|
2017-02-28 12:05:17 +00:00
|
|
|
//! use sasl::mechanisms::Plain;
|
|
|
|
//!
|
2017-03-07 16:02:57 +00:00
|
|
|
//! let creds = Credentials::default()
|
|
|
|
//! .with_username("user")
|
|
|
|
//! .with_password("pencil");
|
2017-02-28 12:05:17 +00:00
|
|
|
//!
|
|
|
|
//! let mut mechanism = Plain::from_credentials(creds).unwrap();
|
|
|
|
//!
|
|
|
|
//! let initial_data = mechanism.initial().unwrap();
|
|
|
|
//!
|
|
|
|
//! assert_eq!(initial_data, b"\0user\0pencil");
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! You may look at the tests of `mechanisms/scram.rs` for examples of more advanced usage.
|
|
|
|
//!
|
|
|
|
//! # Usage
|
|
|
|
//!
|
|
|
|
//! You can use this in your crate by adding this under `dependencies` in your `Cargo.toml`:
|
|
|
|
//!
|
|
|
|
//! ```toml,ignore
|
|
|
|
//! sasl = "*"
|
|
|
|
//! ```
|
2017-02-27 15:08:09 +00:00
|
|
|
|
|
|
|
extern crate openssl;
|
|
|
|
extern crate base64;
|
|
|
|
|
2017-02-28 12:05:17 +00:00
|
|
|
mod error;
|
|
|
|
|
|
|
|
pub use error::Error;
|
2017-02-27 15:08:09 +00:00
|
|
|
|
|
|
|
/// A struct containing SASL credentials.
|
2017-03-07 14:02:38 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2017-03-07 16:02:57 +00:00
|
|
|
pub struct Credentials {
|
2017-02-28 12:05:17 +00:00
|
|
|
/// The requested username.
|
2017-03-07 14:02:38 +00:00
|
|
|
pub username: Option<String>,
|
2017-02-28 12:05:17 +00:00
|
|
|
/// The secret used to authenticate.
|
2017-03-07 16:02:57 +00:00
|
|
|
pub secret: Secret,
|
2017-03-07 14:02:38 +00:00
|
|
|
/// Channel binding data, for *-PLUS mechanisms.
|
|
|
|
pub channel_binding: ChannelBinding,
|
|
|
|
}
|
|
|
|
|
2017-03-07 16:02:57 +00:00
|
|
|
impl Default for Credentials {
|
|
|
|
fn default() -> Credentials {
|
|
|
|
Credentials {
|
2017-03-07 14:02:38 +00:00
|
|
|
username: None,
|
2017-03-07 16:02:57 +00:00
|
|
|
secret: Secret::None,
|
2017-03-07 14:02:38 +00:00
|
|
|
channel_binding: ChannelBinding::None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-07 16:02:57 +00:00
|
|
|
impl Credentials {
|
|
|
|
/// Creates a new Credentials with the specified username.
|
|
|
|
pub fn with_username<N: Into<String>>(mut self, username: N) -> Credentials {
|
2017-03-07 14:02:38 +00:00
|
|
|
self.username = Some(username.into());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-03-07 16:02:57 +00:00
|
|
|
/// Creates a new Credentials with the specified password.
|
|
|
|
pub fn with_password<P: Into<String>>(mut self, password: P) -> Credentials {
|
|
|
|
self.secret = Secret::Password(password.into());
|
2017-03-07 14:02:38 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-03-07 16:02:57 +00:00
|
|
|
/// Creates a new Credentials with the specified chanel binding.
|
|
|
|
pub fn with_channel_binding(mut self, channel_binding: ChannelBinding) -> Credentials {
|
2017-03-07 14:02:38 +00:00
|
|
|
self.channel_binding = channel_binding;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Channel binding configuration.
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub enum ChannelBinding {
|
|
|
|
/// No channel binding data.
|
|
|
|
None,
|
2017-03-07 16:02:57 +00:00
|
|
|
/// Advertise that the client does not think the server supports channel binding.
|
|
|
|
Unsupported,
|
2017-03-07 14:02:38 +00:00
|
|
|
/// p=tls-unique channel binding data.
|
|
|
|
TlsUnique(Vec<u8>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ChannelBinding {
|
|
|
|
/// Return the gs2 header for this channel binding mechanism.
|
|
|
|
pub fn header(&self) -> &[u8] {
|
|
|
|
match *self {
|
|
|
|
ChannelBinding::None => b"n,,",
|
2017-03-07 16:02:57 +00:00
|
|
|
ChannelBinding::Unsupported => b"y,,",
|
2017-03-07 14:02:38 +00:00
|
|
|
ChannelBinding::TlsUnique(_) => b"p=tls-unique,,",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the channel binding data for this channel binding mechanism.
|
|
|
|
pub fn data(&self) -> &[u8] {
|
|
|
|
match *self {
|
|
|
|
ChannelBinding::None => &[],
|
2017-03-07 16:02:57 +00:00
|
|
|
ChannelBinding::Unsupported => &[],
|
2017-03-07 14:02:38 +00:00
|
|
|
ChannelBinding::TlsUnique(ref data) => data,
|
|
|
|
}
|
|
|
|
}
|
2017-02-27 15:08:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Represents a SASL secret, like a password.
|
2017-03-07 14:02:38 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
2017-03-07 16:02:57 +00:00
|
|
|
pub enum Secret {
|
2017-02-27 15:08:09 +00:00
|
|
|
/// No extra data needed.
|
|
|
|
None,
|
|
|
|
/// Password required.
|
|
|
|
Password(String),
|
|
|
|
}
|
|
|
|
|
2017-02-28 12:05:17 +00:00
|
|
|
/// A trait which defines SASL mechanisms.
|
2017-03-07 16:02:57 +00:00
|
|
|
pub trait Mechanism {
|
2017-02-27 15:08:09 +00:00
|
|
|
/// The name of the mechanism.
|
|
|
|
fn name(&self) -> &str;
|
|
|
|
|
2017-03-07 16:02:57 +00:00
|
|
|
/// Creates this mechanism from `Credentials`.
|
|
|
|
fn from_credentials(credentials: Credentials) -> Result<Self, String> where Self: Sized;
|
2017-02-27 15:08:09 +00:00
|
|
|
|
|
|
|
/// Provides initial payload of the SASL mechanism.
|
|
|
|
fn initial(&mut self) -> Result<Vec<u8>, String> {
|
|
|
|
Ok(Vec::new())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a response to the SASL challenge.
|
|
|
|
fn response(&mut self, _challenge: &[u8]) -> Result<Vec<u8>, String> {
|
|
|
|
Ok(Vec::new())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Verifies the server success response, if there is one.
|
|
|
|
fn success(&mut self, _data: &[u8]) -> Result<(), String> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub mod mechanisms;
|