Restructure and add unit tests...maybe it works now?

This commit is contained in:
Barry Pederson
2024-11-02 13:49:07 -07:00
parent ac9743dc8a
commit 46ad77f19e
10 changed files with 119 additions and 187 deletions
Generated
+19 -131
View File
@@ -28,12 +28,6 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.34.0"
@@ -49,15 +43,6 @@ dependencies = [
"vec_map",
]
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"version_check",
]
[[package]]
name = "heck"
version = "0.3.3"
@@ -76,64 +61,17 @@ dependencies = [
"libc",
]
[[package]]
name = "hostname"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
dependencies = [
"libc",
"match_cfg",
"winapi",
]
[[package]]
name = "itoa"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "lazy_static"
version = "1.4.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "match_cfg"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "proc-macro-error"
@@ -161,37 +99,29 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.50"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "saslauthd"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"once_cell",
"structopt",
"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"
@@ -224,28 +154,15 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.107"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syslog"
version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978044cc68150ad5e40083c9f6a725e6fd02d7ba1bcf691ec2ff0d66c0b41acc"
dependencies = [
"error-chain",
"hostname",
"libc",
"log",
"time",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@@ -255,52 +172,23 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "time"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [
"itoa",
"libc",
"num_threads",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-segmentation"
version = "1.10.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-width"
version = "0.1.10"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "vec_map"
@@ -310,9 +198,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "winapi"
+2 -4
View File
@@ -1,11 +1,9 @@
[package]
name = "saslauthd"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
once_cell = "^1.9.0"
structopt = "^0.3.26"
syslog = "^6.0"
structopt = "^0.3.26"
+3 -1
View File
@@ -1,3 +1,5 @@
# Demo password file
some-rad-password
some-rad-password
#commented-out
+67 -8
View File
@@ -2,25 +2,26 @@ use std::fs::File;
use std::io::{BufRead, BufReader};
use crate::options::OPTIONS;
use crate::server::{Handler, Request};
use crate::request::Request;
#[derive(Clone)]
pub struct FileHandler;
impl FileHandler {
pub fn new() -> FileHandler {}
}
pub fn new() -> FileHandler {
FileHandler {}
}
impl Handler for FileHandler {
pub fn check_auth(&request: Request) -> bool {
pub fn check_auth(&self, request: &Request) -> bool {
// Don't allow empty userids or passwords
//
if request.userid.is_empty() || request.userid.contains('/') || request.password.is_empty() {
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);
file_name.push(&request.userid);
if let Ok(file) = File::open(file_name) {
for line in BufReader::new(file).lines().flatten() {
@@ -33,3 +34,61 @@ impl Handler for FileHandler {
false
}
}
#[cfg(test)]
mod tests {
use crate::handler::FileHandler;
use crate::request::Request;
#[test]
fn it_checks_good_password() {
let handler = FileHandler::new();
let request = Request {
userid: "bp".to_string(),
password: "some-rad-password".to_string(),
service: "ignore-this".to_string(),
realm: "also-ignore-this".to_string(),
};
assert_eq!(handler.check_auth(&request), true);
}
#[test]
fn it_fails_bad_password() {
let handler = FileHandler::new();
let request = Request {
userid: "bp".to_string(),
password: "not-correct".to_string(),
service: "ignore-this".to_string(),
realm: "also-ignore-this".to_string(),
};
assert_eq!(handler.check_auth(&request), false);
}
#[test]
fn it_fails_bad_userid() {
let handler = FileHandler::new();
let request = Request {
userid: "bp-xxx".to_string(),
password: "some-rad-password".to_string(),
service: "ignore-this".to_string(),
realm: "also-ignore-this".to_string(),
};
assert_eq!(handler.check_auth(&request), false);
}
#[test]
fn it_ignores_comments() {
let handler = FileHandler::new();
let request = Request {
userid: "bp".to_string(),
password: "commented-out".to_string(),
service: "ignore-this".to_string(),
realm: "also-ignore-this".to_string(),
};
assert_eq!(handler.check_auth(&request), false);
}
}
+7 -6
View File
@@ -1,19 +1,19 @@
use crate::handler::FileHandler;
use crate::options::OPTIONS;
use crate::server::Server;
use std::fs::{metadata, set_permissions};
use std::io::Error;
use std::os::unix::fs::PermissionsExt;
use std::os::unix::net::UnixListener;
use std::thread;
use crate::options::OPTIONS;
use crate::server::{CheckFn, Handler, Server};
pub struct Listener {
listener: UnixListener,
handler: Box<dyn Handler>,
handler: FileHandler,
}
impl Listener {
pub fn new(handler: Box<dyn Handler>) -> Result<Listener, Error> {
pub fn new(handler: FileHandler) -> Result<Listener, Error> {
if OPTIONS.socket_name.exists() {
std::fs::remove_file(&OPTIONS.socket_name)?;
}
@@ -33,7 +33,8 @@ impl Listener {
match stream {
Ok(stream) => {
/* connection succeeded */
thread::spawn(|| Server::new(stream, &self.handler).unwrap().handle_client());
let handler = self.handler.clone();
thread::spawn(|| Server::new(stream, handler).unwrap().handle_client());
}
Err(_err) => {
/* connection failed */
+3 -2
View File
@@ -1,12 +1,13 @@
mod handler;
mod listener;
mod options;
mod request;
mod server;
use crate::listener::Listener;
use crate::handler::FileHandler;
use crate::listener::Listener;
fn main() -> std::io::Result<()> {
let mut listener = Listener::new(Box::new(FileHandler::new()))?;
let mut listener = Listener::new(FileHandler::new())?;
listener.run()
}
+2 -2
View File
@@ -1,6 +1,6 @@
use std::path::PathBuf;
use once_cell::sync::Lazy;
use std::sync::LazyLock;
use structopt::StructOpt;
#[derive(StructOpt, Clone, Debug)]
@@ -24,4 +24,4 @@ pub struct Opt {
pub password_dir: PathBuf,
}
pub static OPTIONS: Lazy<Opt> = Lazy::new(Opt::from_args);
pub static OPTIONS: LazyLock<Opt> = LazyLock::new(Opt::from_args);
+6
View File
@@ -0,0 +1,6 @@
pub struct Request {
pub userid: String,
pub password: String,
pub service: String,
pub realm: String,
}
+10 -30
View File
@@ -1,3 +1,5 @@
use crate::handler::FileHandler;
use crate::request::Request;
use std::io::{Error, ErrorKind, Read, Write};
use std::os::unix::net::UnixStream;
@@ -6,30 +8,12 @@ const RESPONSE_OK: [u8; 4] = [0x0, 0x2, b'O', b'K'];
pub struct Server {
stream: UnixStream,
handler: &Box<dyn Handler>,
handler: FileHandler,
}
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, handler: &Box<dyn Handler>) -> Result<Server, Error> {
Ok(
Server {
stream,
handler,
}
)
pub fn new(stream: UnixStream, handler: FileHandler) -> Result<Server, Error> {
Ok(Server { stream, handler })
}
/// The saslauthd protocol transmits strings as
@@ -52,6 +36,7 @@ impl Server {
}
}
/*
fn write_string(&mut self, s: &str) -> Result<(), Error> {
let length = s.len();
@@ -66,19 +51,14 @@ impl Server {
Ok(())
}
*/
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()?;
if userid.is_empty() || password.is_empty() {
self.stream.write_all(&RESPONSE_NO)?;
return Ok(());
}
let request = Request {
userid,
password,
@@ -86,9 +66,9 @@ impl Server {
realm,
};
if self.check_auth(&request) {
if self.handler.check_auth(&request) {
self.stream.write_all(&RESPONSE_OK)?
}else {
} else {
self.stream.write_all(&RESPONSE_NO)?
}
-3
View File
@@ -1,3 +0,0 @@
users:
bp:
- some-rad-password