lib.rs

  1#![deny(missing_docs)]
  2
  3//! This crate provides a framework for SASL authentication and a few authentication mechanisms.
  4//!
  5//! # Examples
  6//!
  7//! ```rust
  8//! use sasl::{SaslCredentials, SaslMechanism, Error};
  9//! use sasl::mechanisms::Plain;
 10//!
 11//! let creds = SaslCredentials::default()
 12//!                             .with_username("user")
 13//!                             .with_password("pencil");
 14//!
 15//! let mut mechanism = Plain::from_credentials(creds).unwrap();
 16//!
 17//! let initial_data = mechanism.initial().unwrap();
 18//!
 19//! assert_eq!(initial_data, b"\0user\0pencil");
 20//! ```
 21//!
 22//! You may look at the tests of `mechanisms/scram.rs` for examples of more advanced usage.
 23//!
 24//! # Usage
 25//!
 26//! You can use this in your crate by adding this under `dependencies` in your `Cargo.toml`:
 27//!
 28//! ```toml,ignore
 29//! sasl = "*"
 30//! ```
 31
 32extern crate base64;
 33extern crate openssl;
 34
 35mod error;
 36
 37pub use error::Error;
 38
 39/// A struct containing SASL credentials.
 40#[derive(Clone, Debug)]
 41pub struct SaslCredentials {
 42    /// The requested username.
 43    pub username: Option<String>,
 44    /// The secret used to authenticate.
 45    pub secret: SaslSecret,
 46    /// Channel binding data, for *-PLUS mechanisms.
 47    pub channel_binding: ChannelBinding,
 48}
 49
 50impl Default for SaslCredentials {
 51    fn default() -> SaslCredentials {
 52        SaslCredentials {
 53            username: None,
 54            secret: SaslSecret::None,
 55            channel_binding: ChannelBinding::None,
 56        }
 57    }
 58}
 59
 60impl SaslCredentials {
 61    /// Creates a new SaslCredentials with the specified username.
 62    pub fn with_username<N: Into<String>>(mut self, username: N) -> SaslCredentials {
 63        self.username = Some(username.into());
 64        self
 65    }
 66
 67    /// Creates a new SaslCredentials with the specified password.
 68    pub fn with_password<P: Into<String>>(mut self, password: P) -> SaslCredentials {
 69        self.secret = SaslSecret::Password(password.into());
 70        self
 71    }
 72
 73    /// Creates a new SaslCredentials with the specified chanel binding.
 74    pub fn with_channel_binding(mut self, channel_binding: ChannelBinding) -> SaslCredentials {
 75        self.channel_binding = channel_binding;
 76        self
 77    }
 78}
 79
 80/// Channel binding configuration.
 81#[derive(Clone, Debug, PartialEq, Eq)]
 82pub enum ChannelBinding {
 83    /// No channel binding data.
 84    None,
 85    /// p=tls-unique channel binding data.
 86    TlsUnique(Vec<u8>),
 87}
 88
 89impl ChannelBinding {
 90    /// Return the gs2 header for this channel binding mechanism.
 91    pub fn header(&self) -> &[u8] {
 92        match *self {
 93            ChannelBinding::None => b"n,,",
 94            ChannelBinding::TlsUnique(_) => b"p=tls-unique,,",
 95        }
 96    }
 97
 98    /// Return the channel binding data for this channel binding mechanism.
 99    pub fn data(&self) -> &[u8] {
100        match *self {
101            ChannelBinding::None => &[],
102            ChannelBinding::TlsUnique(ref data) => data,
103        }
104    }
105}
106
107/// Represents a SASL secret, like a password.
108#[derive(Clone, Debug, PartialEq, Eq)]
109pub enum SaslSecret {
110    /// No extra data needed.
111    None,
112    /// Password required.
113    Password(String),
114}
115
116/// A trait which defines SASL mechanisms.
117pub trait SaslMechanism {
118    /// The name of the mechanism.
119    fn name(&self) -> &str;
120
121    /// Creates this mechanism from `SaslCredentials`.
122    fn from_credentials(credentials: SaslCredentials) -> Result<Self, String>
123    where
124        Self: Sized;
125
126    /// Provides initial payload of the SASL mechanism.
127    fn initial(&mut self) -> Result<Vec<u8>, String> {
128        Ok(Vec::new())
129    }
130
131    /// Creates a response to the SASL challenge.
132    fn response(&mut self, _challenge: &[u8]) -> Result<Vec<u8>, String> {
133        Ok(Vec::new())
134    }
135
136    /// Verifies the server success response, if there is one.
137    fn success(&mut self, _data: &[u8]) -> Result<(), String> {
138        Ok(())
139    }
140}
141
142pub mod mechanisms;