forked from lavina/lavina
79 lines
2.2 KiB
Rust
79 lines
2.2 KiB
Rust
|
use std::borrow::Borrow;
|
||
|
|
||
|
use quick_xml::{
|
||
|
events::{BytesStart, Event},
|
||
|
NsReader, Writer,
|
||
|
};
|
||
|
use tokio::io::{AsyncBufRead, AsyncWrite};
|
||
|
|
||
|
use super::skip_text;
|
||
|
use crate::prelude::*;
|
||
|
|
||
|
pub enum Mechanism {
|
||
|
Plain,
|
||
|
}
|
||
|
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),
|
||
|
_ => Err(fail(format!("unknown auth mechanism: {input:?}").as_str())),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct Auth {
|
||
|
pub mechanism: Mechanism,
|
||
|
pub body: Vec<u8>,
|
||
|
}
|
||
|
impl Auth {
|
||
|
pub async fn parse(
|
||
|
reader: &mut NsReader<impl AsyncBufRead + Unpin>,
|
||
|
buf: &mut Vec<u8>,
|
||
|
) -> Result<Auth> {
|
||
|
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 {
|
||
|
return Err(fail("expected mechanism attribute in <auth>"));
|
||
|
}
|
||
|
} else {
|
||
|
return Err(fail("expected start of <auth>"));
|
||
|
};
|
||
|
let body = if let Event::Text(text) = reader.read_event_into_async(buf).await? {
|
||
|
text.into_inner().into_owned()
|
||
|
} else {
|
||
|
return Err(fail("expected text body in <auth>"));
|
||
|
};
|
||
|
if let Event::End(_) = reader.read_event_into_async(buf).await? {
|
||
|
//TODO
|
||
|
} else {
|
||
|
return Err(fail("expected end of <auth>"));
|
||
|
};
|
||
|
|
||
|
Ok(Auth { mechanism, body })
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct Success;
|
||
|
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(())
|
||
|
}
|
||
|
}
|