diff --git a/src/client.rs b/src/client.rs index c84d568..f8cd6fa 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,6 +5,8 @@ use ns; use plugin::{Plugin, PluginProxyBinding}; use event::AbstractEvent; use connection::{Connection, C2S}; +use sasl::SaslMechanism; +use sasl::mechanisms::Plain as SaslPlain; use base64; @@ -148,11 +150,9 @@ impl Client { self.transport.write_element(&elem)?; } else { - let mut auth = Vec::new(); - auth.push(0); - auth.extend(self.jid.node.as_ref().expect("JID has no node").bytes()); - auth.push(0); - auth.extend(password.bytes()); + let name = self.jid.node.clone().expect("JID has no node"); + let mut plain = SaslPlain::new(name, password.to_owned()); + let auth = plain.initial(); let elem = Element::builder("auth") .text(base64::encode(&auth)) .ns(ns::SASL) diff --git a/src/lib.rs b/src/lib.rs index 2d941ff..f35f0cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,5 +12,6 @@ pub mod plugin; pub mod event; pub mod plugins; pub mod connection; +pub mod sasl; mod locked_io; diff --git a/src/sasl.rs b/src/sasl.rs new file mode 100644 index 0000000..aa04b49 --- /dev/null +++ b/src/sasl.rs @@ -0,0 +1,60 @@ +//! Provides the `SaslMechanism` trait and some implementations. + +pub trait SaslMechanism { + /// The name of the mechanism. + fn name() -> &'static str; + + /// Provides initial payload of the SASL mechanism. + fn initial(&mut self) -> Vec { + Vec::new() + } + + /// Creates a response to the SASL challenge. + fn respond(&mut self, _challenge: &[u8]) -> Vec { + Vec::new() + } +} + +/// A few SASL mechanisms. +pub mod mechanisms { + use super::SaslMechanism; + + pub struct Anonymous; + + impl Anonymous { + pub fn new() -> Anonymous { + Anonymous + } + } + + impl SaslMechanism for Anonymous { + fn name() -> &'static str { "ANONYMOUS" } + } + + pub struct Plain { + name: String, + password: String, + } + + impl Plain { + pub fn new, P: Into>(name: N, password: P) -> Plain { + Plain { + name: name.into(), + password: password.into(), + } + } + } + + impl SaslMechanism for Plain { + fn name() -> &'static str { "PLAIN" } + + fn initial(&mut self) -> Vec { + let mut auth = Vec::new(); + auth.push(0); + auth.extend(self.name.bytes()); + auth.push(0); + auth.extend(self.password.bytes()); + auth + } + } +}