diff --git a/g3proxy/CHANGELOG b/g3proxy/CHANGELOG index 810baa6d..2aafd636 100644 --- a/g3proxy/CHANGELOG +++ b/g3proxy/CHANGELOG @@ -9,6 +9,7 @@ v1.7.20: - sni_proxy - tcp_stream - tls_stream + - Feature: allow to set token to null value to disable password auth for user v1.7.19: - Feature: support PROXY Protocol in PlainTcpPort and PlainTlsPort server diff --git a/g3proxy/doc/configuration/user_group/user.rst b/g3proxy/doc/configuration/user_group/user.rst index 86b08c44..c83296e1 100644 --- a/g3proxy/doc/configuration/user_group/user.rst +++ b/g3proxy/doc/configuration/user_group/user.rst @@ -21,6 +21,14 @@ token Set the token used to authenticate the user. The token can be in the following types: +* null + + The null value means password token auth is disabled. + + .. note:: This is different from not setting token value, which means forbid the user. + + .. versionadded:: 1.7.20 + * str The value should be a string in unix format, see crypt(5). diff --git a/g3proxy/src/config/auth/mod.rs b/g3proxy/src/config/auth/mod.rs index 320837d1..2dd146c1 100644 --- a/g3proxy/src/config/auth/mod.rs +++ b/g3proxy/src/config/auth/mod.rs @@ -22,7 +22,7 @@ use yaml_rust::{yaml, Yaml}; use g3_yaml::{HybridParser, YamlDocPosition}; mod token; -pub(crate) use token::UserAuthentication; +pub(crate) use token::PasswordToken; mod site; pub(crate) use site::UserSiteConfig; diff --git a/g3proxy/src/config/auth/token/json.rs b/g3proxy/src/config/auth/token/json.rs index fbd9c408..d01e43ce 100644 --- a/g3proxy/src/config/auth/token/json.rs +++ b/g3proxy/src/config/auth/token/json.rs @@ -20,7 +20,7 @@ use serde_json::{Map, Value}; use g3_types::auth::FastHashedPassPhrase; use g3_xcrypt::XCryptHash; -use super::{UserAuthentication, CONFIG_KEY_TYPE}; +use super::{PasswordToken, CONFIG_KEY_TYPE}; const CONFIG_KEY_SALT: &str = "salt"; @@ -81,21 +81,22 @@ fn as_xcrypt_hash(v: &Value) -> anyhow::Result { } } -impl UserAuthentication { +impl PasswordToken { pub(crate) fn parse_json(v: &Value) -> anyhow::Result { match v { - Value::String(_) => Ok(UserAuthentication::XCrypt(as_xcrypt_hash(v)?)), + Value::String(_) => Ok(PasswordToken::XCrypt(as_xcrypt_hash(v)?)), Value::Object(map) => { if let Ok(map_type) = g3_json::get_required_str(map, CONFIG_KEY_TYPE) { match g3_json::key::normalize(map_type).as_str() { - "fast_hash" => Ok(UserAuthentication::FastHash(as_fast_hash(map)?)), - "xcrypt_hash" => Ok(UserAuthentication::XCrypt(as_xcrypt_hash(v)?)), + "fast_hash" => Ok(PasswordToken::FastHash(as_fast_hash(map)?)), + "xcrypt_hash" => Ok(PasswordToken::XCrypt(as_xcrypt_hash(v)?)), _ => Err(anyhow!("unsupported user authentication type")), } } else { - Ok(UserAuthentication::FastHash(as_fast_hash(map)?)) + Ok(PasswordToken::FastHash(as_fast_hash(map)?)) } } + Value::Null => Ok(PasswordToken::SkipVerify), _ => Err(anyhow!("invalid value type")), } } diff --git a/g3proxy/src/config/auth/token/mod.rs b/g3proxy/src/config/auth/token/mod.rs index f46c3d47..98689d15 100644 --- a/g3proxy/src/config/auth/token/mod.rs +++ b/g3proxy/src/config/auth/token/mod.rs @@ -23,7 +23,7 @@ mod yaml; const CONFIG_KEY_TYPE: &str = "type"; #[derive(Clone)] -pub(crate) enum UserAuthentication { +pub(crate) enum PasswordToken { Forbidden, SkipVerify, FastHash(FastHashedPassPhrase), diff --git a/g3proxy/src/config/auth/token/yaml.rs b/g3proxy/src/config/auth/token/yaml.rs index 91fdebd0..1a945db0 100644 --- a/g3proxy/src/config/auth/token/yaml.rs +++ b/g3proxy/src/config/auth/token/yaml.rs @@ -20,7 +20,7 @@ use yaml_rust::{yaml, Yaml}; use g3_types::auth::FastHashedPassPhrase; use g3_xcrypt::XCryptHash; -use super::{UserAuthentication, CONFIG_KEY_TYPE}; +use super::{PasswordToken, CONFIG_KEY_TYPE}; const CONFIG_KEY_SALT: &str = "salt"; @@ -79,21 +79,22 @@ fn as_xcrypt_hash(v: &Yaml) -> anyhow::Result { } } -impl UserAuthentication { +impl PasswordToken { pub(crate) fn parse_yaml(v: &Yaml) -> anyhow::Result { match v { - Yaml::String(_) => Ok(UserAuthentication::XCrypt(as_xcrypt_hash(v)?)), + Yaml::String(_) => Ok(PasswordToken::XCrypt(as_xcrypt_hash(v)?)), Yaml::Hash(map) => { if let Ok(map_type) = g3_yaml::hash_get_required_str(map, CONFIG_KEY_TYPE) { match g3_yaml::key::normalize(map_type).as_str() { - "fast_hash" => Ok(UserAuthentication::FastHash(as_fast_hash(map)?)), - "xcrypt_hash" => Ok(UserAuthentication::XCrypt(as_xcrypt_hash(v)?)), + "fast_hash" => Ok(PasswordToken::FastHash(as_fast_hash(map)?)), + "xcrypt_hash" => Ok(PasswordToken::XCrypt(as_xcrypt_hash(v)?)), _ => Err(anyhow!("unsupported user authentication type")), } } else { - Ok(UserAuthentication::FastHash(as_fast_hash(map)?)) + Ok(PasswordToken::FastHash(as_fast_hash(map)?)) } } + Yaml::Null => Ok(PasswordToken::SkipVerify), _ => Err(anyhow!("invalid value type")), } } diff --git a/g3proxy/src/config/auth/user/json.rs b/g3proxy/src/config/auth/user/json.rs index 3942a606..000021d9 100644 --- a/g3proxy/src/config/auth/user/json.rs +++ b/g3proxy/src/config/auth/user/json.rs @@ -17,7 +17,7 @@ use anyhow::{anyhow, Context}; use serde_json::{Map, Value}; -use super::{UserAuthentication, UserConfig, UserSiteConfig}; +use super::{PasswordToken, UserConfig, UserSiteConfig}; impl UserConfig { pub(crate) fn parse_json(map: &Map) -> anyhow::Result { @@ -37,8 +37,8 @@ impl UserConfig { Ok(()) } "token" => { - self.token = UserAuthentication::parse_json(v) - .context(format!("invalid value for key {k}"))?; + self.password_token = + PasswordToken::parse_json(v).context(format!("invalid value for key {k}"))?; Ok(()) } "expire" => { diff --git a/g3proxy/src/config/auth/user/mod.rs b/g3proxy/src/config/auth/user/mod.rs index f22eca3a..e33cca76 100644 --- a/g3proxy/src/config/auth/user/mod.rs +++ b/g3proxy/src/config/auth/user/mod.rs @@ -33,7 +33,7 @@ use g3_types::net::{ }; use g3_types::resolve::{ResolveRedirectionBuilder, ResolveStrategy}; -use super::{UserAuditConfig, UserAuthentication, UserSiteConfig}; +use super::{PasswordToken, UserAuditConfig, UserSiteConfig}; mod json; mod yaml; @@ -41,7 +41,7 @@ mod yaml; #[derive(Clone)] pub(crate) struct UserConfig { name: String, - token: UserAuthentication, + password_token: PasswordToken, expire_datetime: Option>, pub(crate) audit: UserAuditConfig, pub(crate) block_and_delay: Option, @@ -75,7 +75,7 @@ impl Default for UserConfig { fn default() -> Self { UserConfig { name: String::new(), - token: UserAuthentication::Forbidden, + password_token: PasswordToken::Forbidden, expire_datetime: None, audit: UserAuditConfig::default(), block_and_delay: None, @@ -121,16 +121,16 @@ impl UserConfig { } pub(crate) fn check_password(&self, password: &str) -> bool { - match &self.token { - UserAuthentication::Forbidden => false, - UserAuthentication::SkipVerify => true, - UserAuthentication::FastHash(fast_hash) => fast_hash.verify(password), - UserAuthentication::XCrypt(xcrypt_hash) => xcrypt_hash.verify(password.as_bytes()), + match &self.password_token { + PasswordToken::Forbidden => false, + PasswordToken::SkipVerify => true, + PasswordToken::FastHash(fast_hash) => fast_hash.verify(password), + PasswordToken::XCrypt(xcrypt_hash) => xcrypt_hash.verify(password.as_bytes()), } } pub(super) fn set_no_password(&mut self) { - self.token = UserAuthentication::SkipVerify; + self.password_token = PasswordToken::SkipVerify; } fn add_site_group(&mut self, sg: UserSiteConfig) -> anyhow::Result<()> { diff --git a/g3proxy/src/config/auth/user/yaml.rs b/g3proxy/src/config/auth/user/yaml.rs index bfa59da2..f5a4ea35 100644 --- a/g3proxy/src/config/auth/user/yaml.rs +++ b/g3proxy/src/config/auth/user/yaml.rs @@ -17,7 +17,7 @@ use anyhow::{anyhow, Context}; use yaml_rust::{yaml, Yaml}; -use super::{UserAuthentication, UserConfig, UserSiteConfig}; +use super::{PasswordToken, UserConfig, UserSiteConfig}; impl UserConfig { pub(crate) fn parse_yaml(map: &yaml::Hash) -> anyhow::Result { @@ -35,8 +35,8 @@ impl UserConfig { Ok(()) } "token" => { - self.token = UserAuthentication::parse_yaml(v) - .context(format!("invalid value for key {k}"))?; + self.password_token = + PasswordToken::parse_yaml(v).context(format!("invalid value for key {k}"))?; Ok(()) } "expire" => {