From 3139dcfe3a3bd6e4172fa92f7ca34d94ea8bb813 Mon Sep 17 00:00:00 2001 From: Deathbaron Date: Tue, 6 Jan 2026 19:01:47 +0100 Subject: [PATCH 1/2] adding passwd location, disabled users config options --- README.md | 2 ++ src/config.rs | 19 +++++++++++++++++++ src/main.rs | 15 ++++++++++----- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bc57435..d4b8d90 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,8 @@ Look at the `examples` directory in the repository or the below details section | `RATE_LIMITER_MAX_RETRIES` | Max retries allowed within `RATE_LIMITER_FIND_TIME` | integer | `3` | `5` | `RATE_LIMITER_FIND_TIME` | Time in seconds to keep track of login attempts | integer | `120` | `60` | `RATE_LIMITER_BAN_TIME` | Time in seconds to ban clients after reaching `RATE_LIMITER_MAX_RETRIES` | integer | `300` | `600` +| `PASSWD_FILE` | The passwd file location to read for auth requests | string | `/passwd` | `/mnt/nforwardauth_passwd` +| `DISABLED_USERS` | Deny access for specific users, env variable delimeted by `,` | string | - | `user1,user2` ## Roadmap diff --git a/src/config.rs b/src/config.rs index 1253b0d..30af5f6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use hmac::{Hmac, Mac}; use once_cell::sync::OnceCell; use regex::Regex; @@ -17,6 +18,8 @@ pub struct Config { pub rate_limiter_max_retries: u32, pub rate_limiter_find_time: u32, pub rate_limiter_ban_time: u32, + pub passwd_file: String, + pub disabled_users: HashSet, } /* Config Singleton Instance and Implementation */ @@ -111,6 +114,20 @@ impl Config { Ok(ban_time) => ban_time.parse::().unwrap(), Err(..) => 300, }; + + // passwd_file: The passwd file location to read for auth requests + let passwd_file: String = match env::var("PASSWD_FILE") { + Ok(value) => value, + Err(..) => "/passwd".to_string(), + }; + + // disabled_users: Deny access for specific users, env variable delimeted by `,` + let disabled_users: HashSet = env::var("DISABLED_USERS") + .unwrap_or_default() + .split(',') + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect(); // Create config instance with initialized values let config = Config { @@ -125,6 +142,8 @@ impl Config { rate_limiter_max_retries, rate_limiter_find_time, rate_limiter_ban_time, + passwd_file, + disabled_users, }; // Initialize config in instance diff --git a/src/main.rs b/src/main.rs index 856e67a..58e0fff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,7 +34,6 @@ static FORWARDED_USER: &str = "X-Forwarded-User"; // Static file paths static INDEX_DOCUMENT: &str = "/public/index.html"; static LOGOUT_DOCUMENT: &str = "/public/logout.html"; -static PASSWD_FILE: &str = "/passwd"; // HTTP response body content static NOT_FOUND: &[u8] = b"Not Found"; @@ -409,11 +408,17 @@ async fn api_serve_file(filename: &str, status_code: StatusCode) -> Result Result { - if let Ok(passwd) = fs::read_to_string(PASSWD_FILE).await { + if Config::global().disabled_users.contains(user) { + return Ok(false); + } + if let Ok(passwd) = fs::read_to_string(&Config::global().passwd_file).await { for line in passwd.lines() { - if let Some((stored_user, stored_hash)) = line.split_once(':') { - if stored_user == user && pwhash::unix::verify(password, stored_hash) { - return Ok(true); + if let Some((stored_user, stored_hash_rest)) = line.split_once(':') { + if stored_user == user { + let stored_hash = stored_hash_rest.split(':').next().unwrap(); + if pwhash::unix::verify(password, stored_hash) { + return Ok(true); + } } } } From 41a6f8974a30c71932998233fb65278259d835fc Mon Sep 17 00:00:00 2001 From: Deathbaron Date: Tue, 6 Jan 2026 22:32:10 +0100 Subject: [PATCH 2/2] formatting, clippy --- src/config.rs | 22 +++++++++++----------- src/main.rs | 16 +++++++--------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/config.rs b/src/config.rs index 30af5f6..112a732 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,8 @@ -use std::collections::HashSet; use hmac::{Hmac, Mac}; use once_cell::sync::OnceCell; use regex::Regex; use sha2::Sha256; +use std::collections::HashSet; use std::env; #[derive(Debug)] @@ -19,7 +19,7 @@ pub struct Config { pub rate_limiter_find_time: u32, pub rate_limiter_ban_time: u32, pub passwd_file: String, - pub disabled_users: HashSet, + pub disabled_users: HashSet, } /* Config Singleton Instance and Implementation */ @@ -114,20 +114,20 @@ impl Config { Ok(ban_time) => ban_time.parse::().unwrap(), Err(..) => 300, }; - + // passwd_file: The passwd file location to read for auth requests let passwd_file: String = match env::var("PASSWD_FILE") { Ok(value) => value, Err(..) => "/passwd".to_string(), }; - + // disabled_users: Deny access for specific users, env variable delimeted by `,` - let disabled_users: HashSet = env::var("DISABLED_USERS") - .unwrap_or_default() - .split(',') - .filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - .collect(); + let disabled_users: HashSet = env::var("DISABLED_USERS") + .unwrap_or_default() + .split(',') + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect(); // Create config instance with initialized values let config = Config { @@ -143,7 +143,7 @@ impl Config { rate_limiter_find_time, rate_limiter_ban_time, passwd_file, - disabled_users, + disabled_users, }; // Initialize config in instance diff --git a/src/main.rs b/src/main.rs index 58e0fff..b4d4172 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,10 +75,8 @@ async fn api_forward_auth( .unwrap_or(false); // Get token from request headers and check if cookie exists, otherwise serve login page - let user = validate_cookie(headers); - if user.is_some() { + if let Some(user) = validate_cookie(headers) { // User is authenticated via cookie - let user = user.unwrap(); if is_forwarded { // AUTHORIZED response on forward let mut response = Response::builder().status(StatusCode::OK); @@ -408,17 +406,17 @@ async fn api_serve_file(filename: &str, status_code: StatusCode) -> Result Result { - if Config::global().disabled_users.contains(user) { - return Ok(false); + if Config::global().disabled_users.contains(user) { + return Ok(false); } if let Ok(passwd) = fs::read_to_string(&Config::global().passwd_file).await { for line in passwd.lines() { if let Some((stored_user, stored_hash_rest)) = line.split_once(':') { if stored_user == user { - let stored_hash = stored_hash_rest.split(':').next().unwrap(); - if pwhash::unix::verify(password, stored_hash) { - return Ok(true); - } + let stored_hash = stored_hash_rest.split(':').next().unwrap(); + if pwhash::unix::verify(password, stored_hash) { + return Ok(true); + } } } }