mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-09-03 17:45:44 +00:00
fix: detect credential mode in TOML config loader (#2301)
TomlConfigLoader::new_from_str() always calls NetworkIdentity::new() with unwrap_or_default() on network_secret, converting None to ''. This creates a non-zero SHA256 digest, causing credential nodes loaded from TOML to be misidentified as regular nodes (with network_secret), which breaks Noise handshake authentication. Fix: check if secure_mode is enabled AND network_secret is absent/empty, and call NetworkIdentity::new_credential() in that case. The same detection already exists in: - core.rs (CLI path, via --credential flag) - launcher.rs (GUI/web path, via gen_config) This makes TOML config loading consistent with the other two entry points.
This commit is contained in:
@@ -597,16 +597,33 @@ impl TomlConfigLoader {
|
|||||||
Self::normalize_config_source(&mut config);
|
Self::normalize_config_source(&mut config);
|
||||||
|
|
||||||
config.flags_struct = Some(Self::gen_flags(config.flags.clone().unwrap_or_default()));
|
config.flags_struct = Some(Self::gen_flags(config.flags.clone().unwrap_or_default()));
|
||||||
|
let has_network_identity = config.network_identity.is_some();
|
||||||
|
|
||||||
let config = TomlConfigLoader {
|
let config = TomlConfigLoader {
|
||||||
config: Arc::new(Mutex::new(config)),
|
config: Arc::new(Mutex::new(config)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let old_ns = config.get_network_identity();
|
let old_ns = config.get_network_identity();
|
||||||
|
|
||||||
|
// Detect credential mode: secure_mode enabled + no network_secret in TOML
|
||||||
|
let is_credential = has_network_identity
|
||||||
|
&& config
|
||||||
|
.get_secure_mode()
|
||||||
|
.map(|sm| sm.enabled)
|
||||||
|
.unwrap_or(false)
|
||||||
|
&& old_ns
|
||||||
|
.network_secret
|
||||||
|
.as_deref()
|
||||||
|
.is_none_or(|s| s.is_empty());
|
||||||
|
|
||||||
|
if is_credential {
|
||||||
|
config.set_network_identity(NetworkIdentity::new_credential(old_ns.network_name));
|
||||||
|
} else {
|
||||||
config.set_network_identity(NetworkIdentity::new(
|
config.set_network_identity(NetworkIdentity::new(
|
||||||
old_ns.network_name,
|
old_ns.network_name,
|
||||||
old_ns.network_secret.unwrap_or_default(),
|
old_ns.network_secret.unwrap_or_default(),
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
@@ -1359,6 +1376,45 @@ stun_servers = [
|
|||||||
assert_eq!(loaded.get_network_config_source(), ConfigSource::Webhook);
|
assert_eq!(loaded.get_network_config_source(), ConfigSource::Webhook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toml_credential_mode_omits_network_secret() {
|
||||||
|
for network_secret in ["", r#"network_secret = """#] {
|
||||||
|
let config = TomlConfigLoader::new_from_str(&format!(
|
||||||
|
r#"
|
||||||
|
[network_identity]
|
||||||
|
network_name = "credential-network"
|
||||||
|
{network_secret}
|
||||||
|
|
||||||
|
[secure_mode]
|
||||||
|
enabled = true
|
||||||
|
"#
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let identity = config.get_network_identity();
|
||||||
|
assert_eq!(identity.network_name, "credential-network");
|
||||||
|
assert_eq!(identity.network_secret, None);
|
||||||
|
assert_eq!(identity.network_secret_digest, None);
|
||||||
|
assert!(!config.dump().contains("network_secret"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toml_secure_mode_without_network_identity_uses_default_secret() {
|
||||||
|
let config = TomlConfigLoader::new_from_str(
|
||||||
|
r#"
|
||||||
|
[secure_mode]
|
||||||
|
enabled = true
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let identity = config.get_network_identity();
|
||||||
|
assert_eq!(identity.network_name, "default");
|
||||||
|
assert_eq!(identity.network_secret.as_deref(), Some(""));
|
||||||
|
assert!(identity.network_secret_digest.is_some());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_mapped_listener_urls_allows_ws_without_port() {
|
fn test_parse_mapped_listener_urls_allows_ws_without_port() {
|
||||||
let parsed = parse_mapped_listener_urls(&[
|
let parsed = parse_mapped_listener_urls(&[
|
||||||
|
|||||||
+38
-6
@@ -891,17 +891,20 @@ impl NetworkOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let old_ns = cfg.get_network_identity();
|
let old_ns = cfg.get_network_identity();
|
||||||
let network_name = self.network_name.clone().unwrap_or(old_ns.network_name);
|
let network_name = self
|
||||||
|
.network_name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| old_ns.network_name.clone());
|
||||||
|
|
||||||
if self.credential.is_some() {
|
if self.credential.is_some() {
|
||||||
// Credential mode: no network_secret, authenticate via credential keypair
|
// Credential mode: no network_secret, authenticate via credential keypair
|
||||||
cfg.set_network_identity(NetworkIdentity::new_credential(network_name));
|
cfg.set_network_identity(NetworkIdentity::new_credential(network_name));
|
||||||
} else {
|
} else if let Some(network_secret) = &self.network_secret {
|
||||||
let network_secret = self
|
cfg.set_network_identity(NetworkIdentity::new(network_name, network_secret.clone()));
|
||||||
.network_secret
|
} else if let Some(network_secret) = old_ns.network_secret {
|
||||||
.clone()
|
|
||||||
.unwrap_or(old_ns.network_secret.unwrap_or_default());
|
|
||||||
cfg.set_network_identity(NetworkIdentity::new(network_name, network_secret));
|
cfg.set_network_identity(NetworkIdentity::new(network_name, network_secret));
|
||||||
|
} else {
|
||||||
|
cfg.set_network_identity(NetworkIdentity::new_credential(network_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dhcp) = self.dhcp {
|
if let Some(dhcp) = self.dhcp {
|
||||||
@@ -1739,4 +1742,33 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_network_options_merge_preserves_credential_identity() {
|
||||||
|
let cfg = TomlConfigLoader::new_from_str(
|
||||||
|
r#"
|
||||||
|
[network_identity]
|
||||||
|
network_name = "credential-network"
|
||||||
|
network_secret = ""
|
||||||
|
|
||||||
|
[secure_mode]
|
||||||
|
enabled = true
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(cfg.get_network_identity().network_secret, None);
|
||||||
|
|
||||||
|
NetworkOptions {
|
||||||
|
hostname: Some("override-host".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.merge_into(&cfg)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let identity = cfg.get_network_identity();
|
||||||
|
assert_eq!(identity.network_name, "credential-network");
|
||||||
|
assert_eq!(identity.network_secret, None);
|
||||||
|
assert_eq!(identity.network_secret_digest, None);
|
||||||
|
assert_eq!(cfg.get_hostname(), "override-host");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user