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..112a732 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,6 +2,7 @@ use hmac::{Hmac, Mac}; use once_cell::sync::OnceCell; use regex::Regex; use sha2::Sha256; +use std::collections::HashSet; use std::env; #[derive(Debug)] @@ -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 */ @@ -112,6 +115,20 @@ impl Config { 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 { port, @@ -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..b4d4172 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"; @@ -76,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); @@ -409,11 +406,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); + } } } }