diff --git a/Cargo.lock b/Cargo.lock index ec3b181..76e6b64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2316,6 +2316,28 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.64", +] + [[package]] name = "subtle" version = "2.5.0" @@ -2734,6 +2756,8 @@ dependencies = [ "slog-async", "slog-redis", "slog-term", + "strum", + "strum_macros", "thiserror", "tokio", "unftp-auth-jsonfile", diff --git a/Cargo.toml b/Cargo.toml index e77ada5..4863827 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,8 @@ unftp-auth-jsonfile = { version = "0.3.4", optional = true } unftp-sbe-rooter = "0.2.1" unftp-sbe-restrict = "0.1.2" url = "2.5.0" +strum = { version = "0.26.2", features = ["derive"] } +strum_macros = "0.26.2" [target.'cfg(unix)'.dependencies] unftp-auth-pam = { version = "0.2.5", optional = true } diff --git a/src/args.rs b/src/args.rs index 981dc2c..4a14bdf 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,6 +1,7 @@ use crate::app; use clap::{Arg, ArgEnum, Command}; use std::str::FromStr; +use strum_macros::{Display, EnumString}; pub const AUTH_JSON_PATH: &str = "auth-json-path"; pub const AUTH_PAM_SERVICE: &str = "auth-pam-service"; @@ -45,13 +46,13 @@ pub const USR_JSON_PATH: &str = "usr-json-path"; pub const USR_HTTP_URL: &str = "usr-http-url"; pub const VERBOSITY: &str = "verbosity"; -#[derive(ArgEnum, Clone, Debug)] -#[allow(non_camel_case_types)] +#[derive(Debug, EnumString, Display, PartialEq)] +#[strum(serialize_all = "lowercase")] pub enum AuthType { - anonymous, - pam, - rest, - json, + Anonymous, + Pam, + Rest, + Json, } #[derive(ArgEnum, Clone, Debug)] diff --git a/src/main.rs b/src/main.rs index f412ccc..3e6a5d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ use crate::infra::userdetail_http::HTTPUserDetailProvider; use crate::{ app::libunftp_version, args::FtpsClientAuthType, auth::DefaultUserProvider, notify::FTPListener, }; +use args::AuthType; use auth::LookupAuthenticator; use clap::ArgMatches; use domain::events::{EventDispatcher, FTPEvent, FTPEventPayload}; @@ -93,13 +94,49 @@ fn load_user_file( fn make_auth( m: &clap::ArgMatches, ) -> Result + Send + Sync + 'static>, String> { - let mut auth: LookupAuthenticator = match m.value_of(args::AUTH_TYPE) { - None | Some("anonymous") => make_anon_auth(), - Some("pam") => make_pam_auth(m), - Some("rest") => make_rest_auth(m), - Some("json") => make_json_auth(m), - unknown_type => Err(format!("unknown auth type: {}", unknown_type.unwrap())), + let default_auth_type = AuthType::Anonymous.to_string(); + let input_auth_type = m.value_of(args::AUTH_TYPE).unwrap_or(&default_auth_type); + let auth_type_variant = match input_auth_type.parse::() { + Ok(auth_type_variant) => auth_type_variant, + Err(strum::ParseError::VariantNotFound) => { + return Err(format!("unknown auth type: {}", input_auth_type)) + } + }; + + let mut auth: LookupAuthenticator = match auth_type_variant { + AuthType::Anonymous => make_anon_auth(), + AuthType::Pam => make_pam_auth(m), + AuthType::Rest => make_rest_auth(m), + AuthType::Json => make_json_auth(m), }?; + + if auth_type_variant != AuthType::Pam && m.is_present(args::AUTH_PAM_SERVICE) { + return Err(format!( + "parameter {} set while auth_type is set to {}", + args::AUTH_PAM_SERVICE, + auth_type_variant + )); + } else if auth_type_variant != AuthType::Json && m.is_present(args::AUTH_JSON_PATH) { + return Err(format!( + "parameter {} set while auth_type is set to {}", + args::AUTH_JSON_PATH, + auth_type_variant + )); + } else if auth_type_variant != AuthType::Rest + && [ + args::AUTH_REST_URL, + args::AUTH_REST_REGEX, + args::AUTH_REST_SELECTOR, + ] + .iter() + .any(|&arg| m.is_present(arg)) + { + return Err(format!( + "REST auth parameter(s) set while auth_type is set to {}", + auth_type_variant + )); + } + auth.set_usr_detail( match ( m.value_of(args::USR_JSON_PATH),