WIP: trying to refactor to separate password-checking from network-communication
This commit is contained in:
Generated
+55
-31
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user