2023-03-05 21:04:28 +00:00
|
|
|
use std::borrow::Borrow;
|
|
|
|
|
2023-10-13 14:54:08 +00:00
|
|
|
use anyhow::{anyhow, Result};
|
|
|
|
use quick_xml::events::{BytesStart, Event};
|
|
|
|
use quick_xml::{NsReader, Writer};
|
2023-03-05 21:04:28 +00:00
|
|
|
use tokio::io::{AsyncBufRead, AsyncWrite};
|
|
|
|
|
|
|
|
use super::skip_text;
|
|
|
|
|
|
|
|
pub enum Mechanism {
|
|
|
|
Plain,
|
|
|
|
}
|
2023-10-08 13:53:39 +00:00
|
|
|
|
2023-03-05 21:04:28 +00:00
|
|
|
impl Mechanism {
|
|
|
|
pub fn to_str(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
Mechanism::Plain => "PLAIN",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_str(input: &[u8]) -> Result<Mechanism> {
|
|
|
|
match input {
|
|
|
|
b"PLAIN" => Ok(Mechanism::Plain),
|
2023-09-30 15:43:46 +00:00
|
|
|
_ => Err(anyhow!("unknown auth mechanism: {input:?}")),
|
2023-03-05 21:04:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Auth {
|
|
|
|
pub mechanism: Mechanism,
|
|
|
|
pub body: Vec<u8>,
|
|
|
|
}
|
2023-10-08 13:53:39 +00:00
|
|
|
|
2023-03-05 21:04:28 +00:00
|
|
|
impl Auth {
|
2023-10-13 14:54:08 +00:00
|
|
|
pub async fn parse(reader: &mut NsReader<impl AsyncBufRead + Unpin>, buf: &mut Vec<u8>) -> Result<Auth> {
|
2023-03-05 21:04:28 +00:00
|
|
|
let event = skip_text!(reader, buf);
|
|
|
|
let mechanism = if let Event::Start(bytes) = event {
|
|
|
|
let mut mechanism = None;
|
|
|
|
for attr in bytes.attributes() {
|
|
|
|
let attr = attr?;
|
|
|
|
if attr.key.0 == b"mechanism" {
|
|
|
|
mechanism = Some(attr.value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(mechanism) = mechanism {
|
|
|
|
Mechanism::from_str(mechanism.borrow())?
|
|
|
|
} else {
|
2023-09-30 15:43:46 +00:00
|
|
|
return Err(anyhow!("expected mechanism attribute in <auth>"));
|
2023-03-05 21:04:28 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-09-30 15:43:46 +00:00
|
|
|
return Err(anyhow!("expected start of <auth>"));
|
2023-03-05 21:04:28 +00:00
|
|
|
};
|
|
|
|
let body = if let Event::Text(text) = reader.read_event_into_async(buf).await? {
|
|
|
|
text.into_inner().into_owned()
|
|
|
|
} else {
|
2023-09-30 15:43:46 +00:00
|
|
|
return Err(anyhow!("expected text body in <auth>"));
|
2023-03-05 21:04:28 +00:00
|
|
|
};
|
|
|
|
if let Event::End(_) = reader.read_event_into_async(buf).await? {
|
|
|
|
//TODO
|
|
|
|
} else {
|
2023-09-30 15:43:46 +00:00
|
|
|
return Err(anyhow!("expected end of <auth>"));
|
2023-03-05 21:04:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Auth { mechanism, body })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Success;
|
2023-10-08 13:53:39 +00:00
|
|
|
|
2023-03-05 21:04:28 +00:00
|
|
|
impl Success {
|
|
|
|
pub async fn write_xml(&self, writer: &mut Writer<impl AsyncWrite + Unpin>) -> Result<()> {
|
|
|
|
let event = BytesStart::new(r#"success xmlns="urn:ietf:params:xml:ns:xmpp-sasl""#);
|
|
|
|
writer.write_event_async(Event::Empty(event)).await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|