diff options
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/encrypted.rs | 216 | ||||
-rw-r--r-- | src/client/mod.rs | 17 | ||||
-rw-r--r-- | src/client/unencrypted.rs | 76 |
3 files changed, 61 insertions, 248 deletions
diff --git a/src/client/encrypted.rs b/src/client/encrypted.rs index a4bf0d1..76f600c 100644 --- a/src/client/encrypted.rs +++ b/src/client/encrypted.rs @@ -1,35 +1,26 @@ -use std::str; - use quick_xml::{ - de::Deserializer, - events::{BytesDecl, BytesStart, Event}, - name::QName, - se::Serializer, + events::{BytesDecl, Event}, Reader, Writer, }; -use rsasl::prelude::{Mechname, SASLClient}; -use serde::{Deserialize, Serialize}; -use tokio::io::{AsyncWriteExt, BufReader, ReadHalf, WriteHalf}; +use tokio::io::{BufReader, ReadHalf, WriteHalf}; use tokio::net::TcpStream; use tokio_native_tls::TlsStream; -use crate::stanza::{ - sasl::{Auth, Challenge, Mechanisms}, - stream::{StreamFeature, StreamFeatures}, -}; +use crate::element::Element; +use crate::stanza::stream::{Stream, StreamFeature}; use crate::Jabber; use crate::Result; pub struct JabberClient<'j> { reader: Reader<BufReader<ReadHalf<TlsStream<TcpStream>>>>, - writer: WriteHalf<TlsStream<TcpStream>>, + writer: Writer<WriteHalf<TlsStream<TcpStream>>>, jabber: &'j mut Jabber<'j>, } impl<'j> JabberClient<'j> { pub fn new( reader: Reader<BufReader<ReadHalf<TlsStream<TcpStream>>>>, - writer: WriteHalf<TlsStream<TcpStream>>, + writer: Writer<WriteHalf<TlsStream<TcpStream>>>, jabber: &'j mut Jabber<'j>, ) -> Self { Self { @@ -40,90 +31,29 @@ impl<'j> JabberClient<'j> { } pub async fn start_stream(&mut self) -> Result<()> { + // client to server let declaration = BytesDecl::new("1.0", None, None); - let mut stream_element = BytesStart::new("stream:stream"); - stream_element.push_attribute(("from".as_bytes(), self.jabber.jid.to_string().as_bytes())); - stream_element.push_attribute(("to".as_bytes(), self.jabber.server.as_bytes())); - stream_element.push_attribute(("version", "1.0")); - stream_element.push_attribute(("xml:lang", "en")); - stream_element.push_attribute(("xmlns", "jabber:client")); - stream_element.push_attribute(("xmlns:stream", "http://etherx.jabber.org/streams")); - let mut writer = Writer::new(&mut self.writer); - writer.write_event_async(Event::Decl(declaration)).await; - writer.write_event_async(Event::Start(stream_element)).await; + let server = &self.jabber.server.to_owned().try_into()?; + let stream_element = + Stream::new_client(&self.jabber.jid, server, None, Some("en".to_string())); + self.writer + .write_event_async(Event::Decl(declaration)) + .await; + let stream_element: Element<'_> = stream_element.into(); + stream_element.write_start(&mut self.writer).await?; + // server to client let mut buf = Vec::new(); - loop { - match self.reader.read_event_into_async(&mut buf).await.unwrap() { - Event::Start(e) => { - println!("{:?}", e); - break; - } - e => println!("decl: {:?}", e), - }; - } + self.reader.read_event_into_async(&mut buf).await?; + let _stream_response = Element::read_start(&mut self.reader).await?; Ok(()) } - pub async fn get_node<'a>(&mut self) -> Result<String> { - let mut buf = Vec::new(); - let mut txt = Vec::new(); - let mut qname_set = false; - let mut qname: Option<Vec<u8>> = None; - loop { - match self.reader.read_event_into_async(&mut buf).await? { - Event::Start(e) => { - if !qname_set { - qname = Some(e.name().into_inner().to_owned()); - qname_set = true; - } - txt.push(b'<'); - txt = txt - .into_iter() - .chain(buf.to_owned()) - .chain(vec![b'>']) - .collect(); - } - Event::End(e) => { - let mut end = false; - if e.name() == QName(qname.as_deref().unwrap()) { - end = true; - } - txt.push(b'<'); - txt = txt - .into_iter() - .chain(buf.to_owned()) - .chain(vec![b'>']) - .collect(); - if end { - break; - } - } - Event::Text(_e) => { - txt = txt.into_iter().chain(buf.to_owned()).collect(); - } - _ => { - txt.push(b'<'); - txt = txt - .into_iter() - .chain(buf.to_owned()) - .chain(vec![b'>']) - .collect(); - } - } - buf.clear(); + pub async fn get_features(&mut self) -> Result<Option<Vec<StreamFeature>>> { + if let Some(features) = Element::read(&mut self.reader).await? { + Ok(Some(features.try_into()?)) + } else { + Ok(None) } - println!("{:?}", txt); - let decoded = str::from_utf8(&txt)?.to_owned(); - println!("{:?}", decoded); - Ok(decoded) - } - - pub async fn get_features(&mut self) -> Result<Vec<StreamFeature>> { - let node = self.get_node().await?; - let mut deserializer = Deserializer::from_str(&node); - let features = StreamFeatures::deserialize(&mut deserializer).unwrap(); - println!("{:?}", features); - Ok(features.features) } pub async fn negotiate(&mut self) -> Result<()> { @@ -131,98 +61,14 @@ impl<'j> JabberClient<'j> { println!("loop"); let features = &self.get_features().await?; println!("{:?}", features); - match &features[0] { - StreamFeature::Sasl(sasl) => { - println!("{:?}", sasl); - self.sasl(&sasl).await?; - } - StreamFeature::Bind => todo!(), - x => println!("{:?}", x), - } + // match &features[0] { + // StreamFeature::Sasl(sasl) => { + // println!("{:?}", sasl); + // todo!() + // } + // StreamFeature::Bind => todo!(), + // x => println!("{:?}", x), + // } } } - - pub async fn sasl(&mut self, mechanisms: &Mechanisms) -> Result<()> { - println!("{:?}", mechanisms); - let sasl = SASLClient::new(self.jabber.auth.clone()); - let mut offered_mechs: Vec<&Mechname> = Vec::new(); - for mechanism in &mechanisms.mechanisms { - offered_mechs.push(Mechname::parse(&mechanism.mechanism.as_bytes())?) - } - println!("{:?}", offered_mechs); - let mut session = sasl.start_suggested(&offered_mechs)?; - let selected_mechanism = session.get_mechname().as_str().to_owned(); - println!("selected mech: {:?}", selected_mechanism); - let mut data: Option<Vec<u8>> = None; - if !session.are_we_first() { - // if not first mention the mechanism then get challenge data - // mention mechanism - let auth = Auth { - ns: "urn:ietf:params:xml:ns:xmpp-sasl".to_owned(), - mechanism: selected_mechanism.clone(), - sasl_data: Some("=".to_owned()), - }; - let mut buffer = String::new(); - let ser = Serializer::new(&mut buffer); - auth.serialize(ser).unwrap(); - self.writer.write_all(buffer.as_bytes()); - // get challenge data - let node = self.get_node().await?; - let mut deserializer = Deserializer::from_str(&node); - let challenge = Challenge::deserialize(&mut deserializer).unwrap(); - println!("challenge: {:?}", challenge); - data = Some(challenge.sasl_data.as_bytes().to_owned()); - println!("we didn't go first"); - } else { - // if first, mention mechanism and send data - let mut sasl_data = Vec::new(); - session.step64(None, &mut sasl_data).unwrap(); - let auth = Auth { - ns: "urn:ietf:params:xml:ns:xmpp-sasl".to_owned(), - mechanism: selected_mechanism.clone(), - sasl_data: Some(str::from_utf8(&sasl_data).unwrap().to_owned()), - }; - let mut buffer = String::new(); - let ser = Serializer::new(&mut buffer); - auth.serialize(ser).unwrap(); - println!("node: {:?}", buffer); - self.writer.write_all(buffer.as_bytes()).await; - println!("we went first"); - // get challenge data - // TODO: check if needed - // let node = self.get_node().await?; - // println!("node: {:?}", node); - // let mut deserializer = Deserializer::from_str(&node); - // let challenge = Challenge::deserialize(&mut deserializer).unwrap(); - // println!("challenge: {:?}", challenge); - // data = Some(challenge.sasl_data.as_bytes().to_owned()); - } - - // stepping the authentication exchange to completion - let mut sasl_data = Vec::new(); - while { - // decide if need to send more data over - let state = session - .step64(data.as_deref(), &mut sasl_data) - .expect("step errored!"); - state.is_running() - } { - // While we aren't finished, receive more data from the other party - let auth = Auth { - ns: "urn:ietf:params:xml:ns:xmpp-sasl".to_owned(), - mechanism: selected_mechanism.clone(), - sasl_data: Some(str::from_utf8(&sasl_data).unwrap().to_owned()), - }; - let mut buffer = String::new(); - let ser = Serializer::new(&mut buffer); - auth.serialize(ser).unwrap(); - self.writer.write_all(buffer.as_bytes()); - let node = self.get_node().await?; - let mut deserializer = Deserializer::from_str(&node); - let challenge = Challenge::deserialize(&mut deserializer).unwrap(); - data = Some(challenge.sasl_data.as_bytes().to_owned()); - } - self.start_stream().await?; - Ok(()) - } } diff --git a/src/client/mod.rs b/src/client/mod.rs index fe3dd34..d545923 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -15,17 +15,16 @@ pub enum JabberClientType<'j> { impl<'j> JabberClientType<'j> { pub async fn ensure_tls(self) -> Result<encrypted::JabberClient<'j>> { match self { - Self::Encrypted(mut c) => { - c.start_stream(); - Ok(c) - } + Self::Encrypted(c) => Ok(c), Self::Unencrypted(mut c) => { - c.start_stream().await?; - let features = c.get_features().await?; - if features.contains(&StreamFeature::StartTls) { - Ok(c.starttls().await?) + if let Some(features) = c.get_features().await? { + if features.contains(&StreamFeature::StartTls) { + Ok(c.starttls().await?) + } else { + Err(JabberError::StartTlsUnavailable) + } } else { - Err(JabberError::StartTlsUnavailable) + Err(JabberError::NoFeatures) } } } diff --git a/src/client/unencrypted.rs b/src/client/unencrypted.rs index d4225d3..ce534c7 100644 --- a/src/client/unencrypted.rs +++ b/src/client/unencrypted.rs @@ -1,19 +1,19 @@ use std::str; use quick_xml::{ - de::Deserializer, events::{BytesDecl, BytesStart, Event}, name::QName, Reader, Writer, }; -use serde::Deserialize; use tokio::io::{BufReader, ReadHalf, WriteHalf}; use tokio::net::TcpStream; use tokio_native_tls::native_tls::TlsConnector; +use crate::element::Element; +use crate::stanza::stream::StreamFeature; +use crate::Jabber; use crate::Result; -use crate::{error::JabberError, stanza::stream::StreamFeature}; -use crate::{stanza::stream::StreamFeatures, Jabber}; +use crate::{error::JabberError, stanza::stream::Stream}; pub struct JabberClient<'j> { reader: Reader<BufReader<ReadHalf<TcpStream>>>, @@ -35,63 +35,30 @@ impl<'j> JabberClient<'j> { } pub async fn start_stream(&mut self) -> Result<()> { + // client to server let declaration = BytesDecl::new("1.0", None, None); - let mut stream_element = BytesStart::new("stream:stream"); - stream_element.push_attribute(("from".as_bytes(), self.jabber.jid.to_string().as_bytes())); - stream_element.push_attribute(("to".as_bytes(), self.jabber.server.as_bytes())); - stream_element.push_attribute(("version", "1.0")); - stream_element.push_attribute(("xml:lang", "en")); - stream_element.push_attribute(("xmlns", "jabber:client")); - stream_element.push_attribute(("xmlns:stream", "http://etherx.jabber.org/streams")); + let server = &self.jabber.server.to_owned().try_into()?; + let stream_element = + Stream::new_client(&self.jabber.jid, server, None, Some("en".to_string())); self.writer .write_event_async(Event::Decl(declaration)) - .await; - self.writer - .write_event_async(Event::Start(stream_element)) - .await - .unwrap(); + .await?; + let stream_element: Element<'_> = stream_element.into(); + stream_element.write_start(&mut self.writer).await?; + // server to client let mut buf = Vec::new(); - loop { - match self.reader.read_event_into_async(&mut buf).await.unwrap() { - Event::Start(e) => { - println!("{:?}", e); - break; - } - Event::Decl(e) => println!("decl: {:?}", e), - _ => return Err(JabberError::BadStream), - } - } + self.reader.read_event_into_async(&mut buf).await?; + let _stream_response = Element::read_start(&mut self.reader).await?; Ok(()) } - pub async fn get_features(&mut self) -> Result<Vec<StreamFeature>> { - let mut buf = Vec::new(); - let mut txt = Vec::new(); - let mut loop_end = false; - while !loop_end { - match self.reader.read_event_into_async(&mut buf).await.unwrap() { - Event::End(e) => { - if e.name() == QName(b"stream:features") { - loop_end = true; - } - } - _ => (), - } - txt.push(b'<'); - txt = txt - .into_iter() - .chain(buf.to_owned()) - .chain(vec![b'>']) - .collect(); - buf.clear(); + pub async fn get_features(&mut self) -> Result<Option<Vec<StreamFeature>>> { + if let Some(features) = Element::read(&mut self.reader).await? { + println!("{:?}", features); + Ok(Some(features.try_into()?)) + } else { + Ok(None) } - println!("{:?}", txt); - let decoded = str::from_utf8(&txt).unwrap(); - println!("decoded: {:?}", decoded); - let mut deserializer = Deserializer::from_str(decoded); - let features = StreamFeatures::deserialize(&mut deserializer).unwrap(); - println!("{:?}", features); - Ok(features.features) } pub async fn starttls(mut self) -> Result<super::encrypted::JabberClient<'j>> { @@ -115,8 +82,9 @@ impl<'j> JabberClient<'j> { .connect(&self.jabber.server, stream) .await { - let (read, writer) = tokio::io::split(tlsstream); + let (read, write) = tokio::io::split(tlsstream); let reader = Reader::from_reader(BufReader::new(read)); + let writer = Writer::new(write); let mut client = super::encrypted::JabberClient::new(reader, writer, self.jabber); client.start_stream().await?; |