WIP: trying to refactor to separate password-checking from network-communication

This commit is contained in:
Barry Pederson
2024-11-02 11:05:16 -07:00
parent 15daa7d7a1
commit ac9743dc8a
5 changed files with 140 additions and 75 deletions
Generated
+55 -31
View File
@@ -89,9 +89,9 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.1"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "lazy_static"
@@ -101,15 +101,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.119"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
@@ -122,18 +122,18 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "num_threads"
version = "0.1.3"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.9.0"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "proc-macro-error"
@@ -161,18 +161,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.36"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-xid",
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.15"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@@ -186,6 +186,12 @@ dependencies = [
"syslog",
]
[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
[[package]]
name = "strsim"
version = "0.8.0"
@@ -218,13 +224,13 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.86"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"unicode-ident",
]
[[package]]
@@ -251,32 +257,50 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.7"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [
"itoa",
"libc",
"num_threads",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
name = "time-core"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
[[package]]
name = "time-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
dependencies = [
"time-core",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-segmentation"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
[[package]]
name = "unicode-width"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "vec_map"
+35
View File
@@ -0,0 +1,35 @@
use std::fs::File;
use std::io::{BufRead, BufReader};
use crate::options::OPTIONS;
use crate::server::{Handler, Request};
pub struct FileHandler;
impl FileHandler {
pub fn new() -> FileHandler {}
}
impl Handler for FileHandler {
pub fn check_auth(&request: Request) -> bool {
// Don't allow empty userids or passwords
//
if request.userid.is_empty() || request.userid.contains('/') || request.password.is_empty() {
return false;
}
let mut file_name = OPTIONS.password_dir.clone();
file_name.push(request.userid);
if let Ok(file) = File::open(file_name) {
for line in BufReader::new(file).lines().flatten() {
if !line.starts_with('#') && line.trim() == request.password {
return true;
}
}
}
false
}
}
+5 -4
View File
@@ -5,14 +5,15 @@ use std::os::unix::net::UnixListener;
use std::thread;
use crate::options::OPTIONS;
use crate::server::Server;
use crate::server::{CheckFn, Handler, Server};
pub struct Listener {
listener: UnixListener,
handler: Box<dyn Handler>,
}
impl Listener {
pub fn new() -> Result<Listener, Error> {
pub fn new(handler: Box<dyn Handler>) -> Result<Listener, Error> {
if OPTIONS.socket_name.exists() {
std::fs::remove_file(&OPTIONS.socket_name)?;
}
@@ -23,7 +24,7 @@ impl Listener {
perms.set_mode(0o0777);
set_permissions(&OPTIONS.socket_name, perms)?;
Ok(Listener { listener })
Ok(Listener { handler, listener })
}
pub fn run(&mut self) -> Result<(), Error> {
@@ -32,7 +33,7 @@ impl Listener {
match stream {
Ok(stream) => {
/* connection succeeded */
thread::spawn(|| Server::new(stream).unwrap().handle_client());
thread::spawn(|| Server::new(stream, &self.handler).unwrap().handle_client());
}
Err(_err) => {
/* connection failed */
+4 -2
View File
@@ -1,10 +1,12 @@
mod handler;
mod listener;
mod options;
mod server;
use crate::listener::Listener;
use crate::handler::FileHandler;
fn main() -> std::io::Result<()> {
let mut server = Listener::new()?;
server.run()
let mut listener = Listener::new(Box::new(FileHandler::new()))?;
listener.run()
}
+41 -38
View File
@@ -1,20 +1,35 @@
use std::fs::File;
use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write};
use std::net::Shutdown;
use std::io::{Error, ErrorKind, Read, Write};
use std::os::unix::net::UnixStream;
use crate::options::OPTIONS;
const RESPONSE_NO: [u8; 4] = [0x0, 0x2, b'N', b'O'];
const RESPONSE_OK: [u8; 4] = [0x0, 0x2, b'O', b'K'];
pub struct Server {
stream: UnixStream,
handler: &Box<dyn Handler>,
}
pub struct Request {
userid: String,
password: String,
service: String,
realm: String,
}
pub trait Handler {
fn check_auth(&self, request: &Request) -> bool;
}
pub type CheckFn = fn(&Request) -> bool;
impl Server {
pub fn new(stream: UnixStream) -> Result<Server, Error> {
Ok(Server { stream })
pub fn new(stream: UnixStream, handler: &Box<dyn Handler>) -> Result<Server, Error> {
Ok(
Server {
stream,
handler,
}
)
}
/// The saslauthd protocol transmits strings as
@@ -52,41 +67,29 @@ impl Server {
Ok(())
}
fn check_auth(&mut self, userid: &str, password: &str) -> Result<bool, Error> {
// Don't allow empty userids or passwords
//
if userid.is_empty() || password.is_empty() {
return Ok(false);
}
let mut password_file = OPTIONS.password_dir.clone();
password_file.push(&userid);
let file = File::open(password_file)?;
for line in BufReader::new(file).lines().flatten() {
if !line.starts_with('#') && line.trim() == password {
return Ok(true);
}
}
Ok(false)
}
fn communicate(&mut self) -> Result<(), Error> {
let userid = self.read_string()?;
let password = self.read_string()?;
let _service = self.read_string()?;
let _realm = self.read_string()?;
let service = self.read_string()?;
let realm = self.read_string()?;
match self.check_auth(&userid, &password) {
Ok(true) => self.stream.write_all(&RESPONSE_OK)?,
Ok(false) => self.stream.write_all(&RESPONSE_NO)?,
Err(e) => {
self.stream.write_all(&RESPONSE_NO)?;
self.stream.shutdown(Shutdown::Both)?;
return Err(e);
}
if userid.is_empty() || password.is_empty() {
self.stream.write_all(&RESPONSE_NO)?;
return Ok(());
}
let request = Request {
userid,
password,
service,
realm,
};
if self.check_auth(&request) {
self.stream.write_all(&RESPONSE_OK)?
}else {
self.stream.write_all(&RESPONSE_NO)?
}
Ok(())
@@ -94,7 +97,7 @@ impl Server {
pub fn handle_client(&mut self) {
if let Err(error) = self.communicate() {
eprint!("{}", error);
eprint!("{error}");
}
}
}