Skip to content

Commit

Permalink
wireless: set security from key_mgmt or guess
Browse files Browse the repository at this point in the history
  • Loading branch information
cfconrad committed Sep 26, 2024
1 parent 8dced4b commit 510a286
Show file tree
Hide file tree
Showing 15 changed files with 701 additions and 30 deletions.
270 changes: 245 additions & 25 deletions rust/migrate-wicked/src/wireless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub struct Wireless {

#[serde_as]
#[skip_serializing_none]
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Serialize, Deserialize, Default)]
pub struct Network {
pub essid: String,
#[serde(rename = "scan-ssid")]
Expand Down Expand Up @@ -95,7 +95,7 @@ pub struct Wep {
}

#[serde_as]
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Serialize, Deserialize, Default)]
pub struct WpaEap {
pub method: WickedEapMethods,
pub identity: Option<String>,
Expand Down Expand Up @@ -211,11 +211,20 @@ impl From<&EapAuthProto> for model::WPAProtocolVersion {
}

#[derive(
Debug, PartialEq, SerializeDisplay, DeserializeFromStr, EnumString, Display, Clone, Copy,
Debug,
PartialEq,
SerializeDisplay,
DeserializeFromStr,
EnumString,
Display,
Clone,
Copy,
Default,
)]
#[strum(serialize_all = "snake_case")]
pub enum WickedEapMethods {
Wpa,
#[default]
None,
Md5,
Tls,
Expand Down Expand Up @@ -416,27 +425,93 @@ where
Ok(Some(Networks::deserialize(deserializer)?.network))
}

fn wireless_security_protocol(
wicked_value: &[String],
fn all(array: &[String], needle: &[&str]) -> bool {
if array.is_empty() {
return false;
}

array.iter().all(|x| needle.iter().any(|&y| x == y))
}

fn any(array: &[String], needle: &[&str]) -> bool {
if array.is_empty() {
return false;
}

array.iter().any(|x| needle.iter().any(|&y| x == y))
}

fn guess_wireless_security_protocol(
network: &Network,
) -> Result<model::SecurityProtocol, anyhow::Error> {
if wicked_value.contains(&"wpa-psk".to_string())
|| wicked_value.contains(&"wpa-psk-sha256".to_string())
{
let mgmt = &network.key_management;

let v = if any(mgmt, &["wpa-eap", "wpa-eap-sha256"]) {
Ok(model::SecurityProtocol::WPA2Enterprise)
} else if any(mgmt, &["wpa-eap-suite-b-192", "wpa-eap-suite-b"]) {
Ok(model::SecurityProtocol::WPA3Only)
} else if any(mgmt, &["wpa-psk", "wpa-psk-sha256"]) {
Ok(model::SecurityProtocol::WPA2)
} else if wicked_value.contains(&"sae".to_string()) {
} else if any(mgmt, &["sae", "ft-sae"]) {
Ok(model::SecurityProtocol::WPA3Personal)
} else if wicked_value.contains(&"wpa-eap".to_string())
|| wicked_value.contains(&"wpa-eap-sha256".to_string())
{
Ok(model::SecurityProtocol::WPA2Enterprise)
} else if wicked_value.contains(&"owe".to_string()) {
} else if any(mgmt, &["owe"]) {
Ok(model::SecurityProtocol::OWE)
} else if wicked_value.contains(&"wpa-eap-suite-b-192".to_string()) {
} else if any(mgmt, &["none"]) {
Ok(model::SecurityProtocol::WEP)
} else if network.wpa_eap.is_some() {
Ok(model::SecurityProtocol::WPA2Enterprise)
} else if network.wpa_psk.is_some() {
Ok(model::SecurityProtocol::WPA2)
} else {
Ok(model::SecurityProtocol::WEP)
};
log::warn!(
"Unsupported key-management protocol(s) '{}' guess '{}'",
mgmt.join(","),
match v {
Ok(s) => s.to_string(),
_ => "-".to_string(),
}
);
v
}

fn wireless_security_protocol(network: &Network) -> Result<model::SecurityProtocol, anyhow::Error> {
let mgmt = &network.key_management;

if all(mgmt, &["sae", "ft-sae"]) {
Ok(model::SecurityProtocol::WPA3Personal)
} else if all(mgmt, &["wpa-psk", "wpa-psk-sha256", "sae", "ft-sae"]) {
Ok(model::SecurityProtocol::WPA2)
} else if all(mgmt, &["wpa-eap-suite-b-192", "wpa-eap-suite-b"]) {
Ok(model::SecurityProtocol::WPA3Only)
} else if wicked_value.contains(&"none".to_string()) {
} else if all(
mgmt,
&[
"wpa-eap",
"wpa-eap-sha256",
"wpa-eap-suite-b-192",
"wpa-eap-suite-b",
],
) {
Ok(model::SecurityProtocol::WPA2Enterprise)
} else if all(mgmt, &["owe"]) {
Ok(model::SecurityProtocol::OWE)
} else if all(mgmt, &["none"]) {
Ok(model::SecurityProtocol::WEP)
} else if mgmt.is_empty() {
if network.wpa_eap.is_some() {
Ok(model::SecurityProtocol::WPA2Enterprise)
} else if network.wpa_psk.is_some() {
Ok(model::SecurityProtocol::WPA2)
} else {
Ok(model::SecurityProtocol::WEP)
}
} else {
Err(anyhow!("Unrecognized key-management protocol"))
Err(anyhow!(
"Unrecognized key-management protocol(s): {}",
mgmt.join(",")
))
}
}

Expand All @@ -451,14 +526,16 @@ impl TryFrom<&Network> for model::ConnectionConfig {
..Default::default()
};

if network.key_management.len() > 1 && settings.continue_migration {
log::warn!("Migration of multiple key-management algorithms isn't supported")
} else if network.key_management.len() > 1 {
return Err(anyhow!(
"Migration of multiple key-management algorithms isn't supported"
));
}
config.security = wireless_security_protocol(&network.key_management)?;
config.security = match wireless_security_protocol(network) {
Ok(sec) => Ok(sec),
Err(e) => {
if settings.continue_migration {
guess_wireless_security_protocol(network)
} else {
Err(e)
}
}
}?;

if let Some(wpa_psk) = &network.wpa_psk {
config.password = Some(wpa_psk.passphrase.clone());
Expand Down Expand Up @@ -639,4 +716,147 @@ mod tests {
);
assert_eq!(wireless.band, Some("bg".try_into().unwrap()));
}

#[test]
fn wireless_security_protocol_strict() {
setup_default_migration_settings();

let mut net = Network {
..Default::default()
};

net.key_management = vec![];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WEP
);

net.key_management = vec![];
net.wpa_eap = Some(WpaEap {
..Default::default()
});

assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2Enterprise
);

net.wpa_eap = None;
net.wpa_psk = Some(WpaPsk {
..Default::default()
});
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2
);

net.wpa_psk = None;
net.key_management = vec!["wpa-psk".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2
);
net.key_management = vec!["sae".to_string(), "wpa-psk".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2
);
net.key_management = vec!["sae".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA3Personal
);

net.key_management = vec!["wpa-eap".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2Enterprise
);
net.key_management = vec!["wpa-eap".to_string(), "wpa-eap-suite-b".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2Enterprise
);
net.key_management = vec!["wpa-eap-suite-b".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA3Only
);

net.key_management = vec!["owe".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::OWE
);

net.key_management = vec!["none".to_string()];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WEP
);

net.key_management = vec!["none".to_string(), "wpa-psk".to_string()];
assert!(!wireless_security_protocol(&net).is_ok());
net.key_management = vec!["wpa-eap".to_string(), "wpa-psk".to_string()];
assert!(!wireless_security_protocol(&net).is_ok());
net.key_management = vec!["wpa-eap".to_string(), "sae".to_string()];
assert!(!wireless_security_protocol(&net).is_ok());
net.key_management = vec!["wpa-eap-suite-b".to_string(), "sae".to_string()];
assert!(!wireless_security_protocol(&net).is_ok());
net.key_management = vec!["wpa-eap-suite-b".to_string(), "owe".to_string()];
assert!(!wireless_security_protocol(&net).is_ok());
net.key_management = vec!["wpa-psk".to_string(), "owe".to_string()];
assert!(!wireless_security_protocol(&net).is_ok());
}

#[test]
fn wireless_security_protocol_continue_migration() {
setup_default_migration_settings();

let mut net = Network {
..Default::default()
};

net.key_management = vec![];
assert_eq!(
wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WEP
);

net.key_management = vec![];
net.wpa_eap = Some(WpaEap {
..Default::default()
});

net.key_management = vec!["none".to_string(), "wpa-psk".to_string()];
assert_eq!(
guess_wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2
);
net.key_management = vec!["wpa-eap".to_string(), "wpa-psk".to_string()];
assert_eq!(
guess_wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2Enterprise
);
net.key_management = vec!["wpa-eap".to_string(), "sae".to_string()];
assert_eq!(
guess_wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2Enterprise
);
net.key_management = vec!["wpa-eap-suite-b".to_string(), "sae".to_string()];
assert_eq!(
guess_wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA3Only
);
net.key_management = vec!["wpa-eap-suite-b".to_string(), "owe".to_string()];
assert_eq!(
guess_wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA3Only
);
net.key_management = vec!["wpa-psk".to_string(), "owe".to_string()];
assert_eq!(
guess_wireless_security_protocol(&net).unwrap(),
model::SecurityProtocol::WPA2
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[connection]
id=wlan0-0
uuid=1089cc84-f99f-4bb8-8a0d-fafde6544e85
uuid=2a262d6e-ccba-4afb-a190-ec08d0175c56
type=wifi
interface-name=wlan0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[connection]
id=wlan0-1
uuid=b0c56f00-cf58-4c6c-b6dd-edf97a612063
uuid=e05ab8eb-9905-4746-b81a-54e190b16354
type=wifi
interface-name=wlan0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[connection]
id=wlan1
uuid=3bc52d5e-4095-4e1a-9976-d46f766bb627
uuid=9d48ef42-2c96-4e43-8ab6-6c66385efdb6
type=wifi
interface-name=wlan1

[wifi]
bssid=12:34:56:78:9A:BC
mode=infrastructure
ssid=test
ssid=wep_1

[wifi-security]
auth-alg=shared
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[connection]
id=wlan2-0
uuid=81ea2b2d-e6bb-4897-aded-de95eb298de5
type=wifi
interface-name=wlan2

[wifi]
hidden=true
mode=infrastructure
ssid=open_1

[wifi-security]
key-mgmt=none

[match]

[ipv4]
method=disabled

[ipv6]
addr-gen-mode=default
method=disabled

[proxy]
Loading

0 comments on commit 510a286

Please sign in to comment.