Add a separate client binary, with some common code to the server.

The cargo workspace thing was a PITA to figure out, but it seems to be working.  Could maybe be simplified?
This commit is contained in:
Barry Pederson
2024-11-02 15:58:35 -07:00
parent 46ad77f19e
commit 076e48f457
16 changed files with 380 additions and 255 deletions
+6
View File
@@ -0,0 +1,6 @@
[package]
name = "common"
version = "0.2.0"
edition = "2021"
[dependencies]
+71
View File
@@ -0,0 +1,71 @@
use std::io::{Error, ErrorKind, Read, Write};
pub const RESPONSE_NO: [u8; 4] = [0x0, 0x2, b'N', b'O'];
pub const RESPONSE_OK: [u8; 4] = [0x0, 0x2, b'O', b'K'];
pub struct Request {
pub userid: String,
pub password: String,
pub service: String,
pub realm: String,
}
/// The saslauthd protocol transmits strings as
/// 16-bit unsigned network-byte-order lengths followed
/// by the string itself.
///
pub fn read_string(stream: &mut impl Read) -> Result<String, Error> {
let mut length_buffer = [0u8, 0u8];
stream.read_exact(&mut length_buffer)?;
let length = u16::from_be_bytes(length_buffer);
let mut string_buffer = vec![0u8; length as usize];
stream.read_exact(&mut string_buffer)?;
match String::from_utf8(string_buffer) {
Ok(str) => Ok(str),
Err(_err) => Err(Error::new(ErrorKind::Other, "Invalid UTF-8 sent")),
}
}
fn write_string(stream: &mut impl Write, s: &str) -> Result<(), Error> {
let length = s.len();
if length > 0xffff {
return Err(Error::new(ErrorKind::Other, "String too long to write"));
}
let length_buffer = [(length >> 8) as u8, (length & 0xff) as u8];
stream.write_all(&length_buffer)?;
stream.write_all(s.as_bytes())?;
Ok(())
}
impl Request {
pub fn from_stream(stream: &mut impl Read) -> Result<Self, Error> {
let userid = read_string(stream)?;
let password = read_string(stream)?;
let service = read_string(stream)?;
let realm = read_string(stream)?;
Ok(Request {
userid,
password,
service,
realm,
})
}
pub fn write_to_stream(&self, stream: &mut impl Write) -> Result<(), Error> {
write_string(stream, &self.userid)?;
write_string(stream, &self.password)?;
write_string(stream, &self.service)?;
write_string(stream, &self.realm)?;
Ok(())
}
}