From e71fad85460b4a3de0c6e247eb0222ba769bc28f Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Mon, 19 Feb 2024 19:11:13 +0100 Subject: [PATCH] Check login before logging it --- Cargo.lock | 26 ++++++++++++++++++++++++++ Cargo.toml | 5 +++-- src/controllers/admin_api.rs | 5 +++++ src/controllers/admin_controller.rs | 12 +++++++++++- src/controllers/login_controller.rs | 11 +++++++++++ src/data/user.rs | 2 +- src/utils/string_utils.rs | 15 ++++++++++++++- 7 files changed, 71 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ce6998..12c6dc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,6 +428,12 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "ascii_utils" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" + [[package]] name = "askama" version = "0.12.1" @@ -604,6 +610,7 @@ dependencies = [ "lazy_static", "light-openid", "log", + "mailchecker", "mime_guess", "qrcode-generator", "rand", @@ -1173,6 +1180,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "fast_chemail" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4" +dependencies = [ + "ascii_utils", +] + [[package]] name = "fastrand" version = "2.0.1" @@ -1781,6 +1797,16 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "mailchecker" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a1951055840e30b5c9c60fcadca14b0b9962797a6228d4e5a73e438a3185ed" +dependencies = [ + "fast_chemail", + "once_cell", +] + [[package]] name = "memchr" version = "2.7.1" diff --git a/Cargo.toml b/Cargo.toml index 3c7aae2..ae26b5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ futures-util = "0.3.30" urlencoding = "2.1.3" rand = "0.8.5" base64 = "0.21.7" -jwt-simple = { version = "0.12.8", default-features=false, features=["pure-rust"] } +jwt-simple = { version = "0.12.8", default-features = false, features = ["pure-rust"] } digest = "0.10.7" sha2 = "0.10.8" lazy-regex = "3.1.0" @@ -35,7 +35,8 @@ base32 = "0.4.0" qrcode-generator = "4.1.9" webauthn-rs = { version = "0.4.8", features = ["danger-allow-state-serialisation"] } url = "2.5.0" -light-openid = { version = "1.0.1", features=["crypto-wrapper"] } +light-openid = { version = "1.0.1", features = ["crypto-wrapper"] } bincode = "2.0.0-rc.3" chrono = "0.4.34" lazy_static = "1.4.0" +mailchecker = "6.0.1" \ No newline at end of file diff --git a/src/controllers/admin_api.rs b/src/controllers/admin_api.rs index a32ebca..eeb78b6 100644 --- a/src/controllers/admin_api.rs +++ b/src/controllers/admin_api.rs @@ -6,6 +6,7 @@ use crate::actors::users_actor::{DeleteUserRequest, FindUserByUsername, UsersAct use crate::data::action_logger::{Action, ActionLogger}; use crate::data::current_user::CurrentUser; use crate::data::user::UserID; +use crate::utils::string_utils; #[derive(serde::Deserialize)] pub struct FindUserNameReq { @@ -21,6 +22,10 @@ pub async fn find_username( req: web::Form, users: web::Data>, ) -> impl Responder { + if !string_utils::is_acceptable_login(&req.username) { + return HttpResponse::BadRequest().json("Invalid login!"); + } + let res = users .send(FindUserByUsername(req.0.username)) .await diff --git a/src/controllers/admin_controller.rs b/src/controllers/admin_controller.rs index bd20792..e1f5770 100644 --- a/src/controllers/admin_controller.rs +++ b/src/controllers/admin_controller.rs @@ -15,6 +15,7 @@ use crate::data::client::{Client, ClientID, ClientManager}; use crate::data::current_user::CurrentUser; use crate::data::provider::{Provider, ProviderID, ProvidersManager}; use crate::data::user::{GeneralSettings, GrantedClients, User, UserID}; +use crate::utils::string_utils; use crate::utils::string_utils::rand_str; #[derive(Template)] @@ -105,7 +106,16 @@ pub async fn users_route( let mut danger = None; let mut success = None; - if let Some(update) = update_query { + // Check update query for invalid input + if update_query + .as_ref() + .map(|l| string_utils::is_acceptable_login(&l.username)) + == Some(false) + { + danger = Some("Invalid login provided, the modifications could not be saved!".to_string()); + } + // Perform request (if any) + else if let Some(update) = update_query { let edited_user: Option = users .send(users_actor::GetUserRequest(update.uid.clone())) .await diff --git a/src/controllers/login_controller.rs b/src/controllers/login_controller.rs index 93398af..f76d1b7 100644 --- a/src/controllers/login_controller.rs +++ b/src/controllers/login_controller.rs @@ -18,6 +18,7 @@ use crate::data::provider::{Provider, ProvidersManager}; use crate::data::session_identity::{SessionIdentity, SessionStatus}; use crate::data::user::User; use crate::data::webauthn_manager::WebAuthManagerReq; +use crate::utils::string_utils; pub struct BaseLoginPage<'a> { pub danger: Option, @@ -132,6 +133,16 @@ pub async fn login_route( query.redirect.get_encoded() )); } + // Check if given login is not acceptable + else if req + .as_ref() + .map(|r| string_utils::is_acceptable_login(&r.login)) + == Some(false) + { + danger = Some( + "Given login could not be processed, because it has an invalid format!".to_string(), + ); + } // Try to authenticate user else if let Some(req) = &req { login = req.login.clone(); diff --git a/src/data/user.rs b/src/data/user.rs index 74d4d25..f693756 100644 --- a/src/data/user.rs +++ b/src/data/user.rs @@ -311,7 +311,7 @@ impl Eq for User {} impl Default for User { fn default() -> Self { Self { - uid: UserID("".to_string()), + uid: UserID(uuid::Uuid::new_v4().to_string()), first_name: "".to_string(), last_name: "".to_string(), username: "".to_string(), diff --git a/src/utils/string_utils.rs b/src/utils/string_utils.rs index c508dfd..ada87d3 100644 --- a/src/utils/string_utils.rs +++ b/src/utils/string_utils.rs @@ -36,9 +36,14 @@ pub fn apply_env_vars(val: &str) -> String { val } +/// Check out whether a given login is acceptable or not +pub fn is_acceptable_login(login: &str) -> bool { + mailchecker::is_valid(login) || lazy_regex::regex!("^[a-zA-Z0-9-+]+$").is_match(login) +} + #[cfg(test)] mod test { - use crate::utils::string_utils::apply_env_vars; + use crate::utils::string_utils::{apply_env_vars, is_acceptable_login}; use std::env; const VAR_ONE: &str = "VAR_ONE"; @@ -56,4 +61,12 @@ mod test { let src = format!("This is ${{{}}}", VAR_INVALID); assert_eq!(src, apply_env_vars(&src)); } + + #[test] + fn test_is_acceptable_login() { + assert!(is_acceptable_login("admin")); + assert!(is_acceptable_login("someone@somewhere.fr")); + assert!(!is_acceptable_login("someone@somewhere.#fr")); + assert!(!is_acceptable_login("bad bad")); + } }