Skip to content

Commit

Permalink
Add additional wireless settings
Browse files Browse the repository at this point in the history
  • Loading branch information
jcronenberg committed Sep 13, 2024
1 parent 9a6d145 commit 25d6e19
Show file tree
Hide file tree
Showing 5 changed files with 435 additions and 13 deletions.
60 changes: 60 additions & 0 deletions rust/agama-lib/share/profile.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,66 @@
"mesh",
"ap"
]
},
"hidden": {
"title": "Indicates that the wifi network is not broadcasting it's SSID",
"type": "boolean"
},
"band": {
"title": "Frequency band of the wifi network",
"type": "string",
"enum": [
"a",
"bg"
]
},
"channel": {
"title": "Wireless channel of the wifi network",
"type": "integer",
"minimum" : 0
},
"bssid": {
"title": "Only allow connection to this mac address",
"type": "string"
},
"group_algorithms": {
"type": "array",
"items": {
"title": "A list of group/broadcast encryption algorithms",
"type": "string",
"enum": [
"wep40",
"wep104",
"tkip",
"ccmp"
]
},
},
"pairwise_algorithms": {
"type": "array",
"items": {
"title": "A list of pairwise encryption algorithms",
"type": "string",
"enum": [
"tkip",
"ccmp"
]
}
},
"wpa_protocol_versions": {
"type": "array",
"items": {
"title": "A list of allowed WPA protocol versions",
"type": "string",
"enum": [
"wpa",
"rsn"
]
}
},
"pmf": {
"title": "Indicates whether Protected Management Frames must be enabled for the connection",
"type": "integer"
}
}
},
Expand Down
33 changes: 31 additions & 2 deletions rust/agama-lib/src/network/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,42 @@ impl MatchSettings {
}
}

/// Wireless configuration
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WirelessSettings {
/// Password of the wifi network
#[serde(skip_serializing_if = "Option::is_none")]
pub password: Option<String>,
/// Security method/key management
pub security: String,
/// SSID of the wifi network
pub ssid: String,
/// Wifi network mode
pub mode: String,
/// Frequency band of the wifi network
#[serde(skip_serializing_if = "Option::is_none")]
pub band: Option<String>,
/// Wireless channel of the wifi network
#[serde(skip_serializing_if = "is_zero", default)]
pub channel: u32,
/// Only allow connection to this mac address
#[serde(skip_serializing_if = "Option::is_none")]
pub bssid: Option<String>,
/// Indicates that the wifi network is not broadcasting it's SSID
#[serde(skip_serializing_if = "std::ops::Not::not", default)]
pub hidden: bool,
/// A list of group/broadcast encryption algorithms
#[serde(skip_serializing_if = "Vec::is_empty")]
pub group_algorithms: Vec<String>,
/// A list of pairwise encryption algorithms
#[serde(skip_serializing_if = "Vec::is_empty")]
pub pairwise_algorithms: Vec<String>,
/// A list of allowed WPA protocol versions
#[serde(skip_serializing_if = "Vec::is_empty")]
pub wpa_protocol_versions: Vec<String>,
/// Indicates whether Protected Management Frames must be enabled for the connection
#[serde(skip_serializing_if = "is_zero", default)]
pub pmf: i32,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -154,8 +183,8 @@ pub struct NetworkConnection {
pub ieee_8021x: Option<IEEE8021XSettings>,
}

fn is_zero(u: &u32) -> bool {
*u == 0
fn is_zero<T: PartialEq + From<u16>>(u: &T) -> bool {
*u == T::from(0)
}

impl NetworkConnection {
Expand Down
10 changes: 10 additions & 0 deletions rust/agama-server/src/network/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ pub enum NetworkStateError {
InvalidEAPMethod(String),
#[error("Invalid phase2 authentication method: '{0}'")]
InvalidPhase2AuthMethod(String),
#[error("Invalid group algorithm: '{0}'")]
InvalidGroupAlgorithm(String),
#[error("Invalid pairwise algorithm: '{0}'")]
InvalidPairwiseAlgorithm(String),
#[error("Invalid WPA protocol version: '{0}'")]
InvalidWPAProtocolVersion(String),
#[error("Invalid wireless band: '{0}'")]
InvalidWirelessBand(String),
#[error("Invalid bssid: '{0}'")]
InvalidBssid(String),
}

impl From<NetworkStateError> for zbus::fdo::Error {
Expand Down
187 changes: 185 additions & 2 deletions rust/agama-server/src/network/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -971,13 +971,19 @@ pub struct WirelessConfig {
pub security: SecurityProtocol,
#[serde(skip_serializing_if = "Option::is_none")]
pub band: Option<WirelessBand>,
#[serde(skip_serializing_if = "Option::is_none")]
pub channel: Option<u32>,
pub channel: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub bssid: Option<macaddr::MacAddr6>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wep_security: Option<WEPSecurity>,
pub hidden: bool,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub group_algorithms: Vec<GroupAlgorithm>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub pairwise_algorithms: Vec<PairwiseAlgorithm>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub wpa_protocol_versions: Vec<WPAProtocolVersion>,
pub pmf: i32,
}

impl TryFrom<ConnectionConfig> for WirelessConfig {
Expand All @@ -998,11 +1004,60 @@ impl TryFrom<WirelessSettings> for WirelessConfig {
let ssid = SSID(settings.ssid.as_bytes().into());
let mode = WirelessMode::try_from(settings.mode.as_str())?;
let security = SecurityProtocol::try_from(settings.security.as_str())?;
let band = if let Some(band) = &settings.band {
Some(
WirelessBand::try_from(band.as_str())
.map_err(|_| NetworkStateError::InvalidWirelessBand(band.to_string()))?,
)
} else {
None
};
let bssid = if let Some(bssid) = &settings.bssid {
Some(
macaddr::MacAddr6::from_str(bssid)
.map_err(|_| NetworkStateError::InvalidBssid(bssid.to_string()))?,
)
} else {
None
};
let group_algorithms = settings
.group_algorithms
.iter()
.map(|x| {
GroupAlgorithm::from_str(x)
.map_err(|_| NetworkStateError::InvalidGroupAlgorithm(x.to_string()))
})
.collect::<Result<Vec<GroupAlgorithm>, NetworkStateError>>()?;
let pairwise_algorithms = settings
.pairwise_algorithms
.iter()
.map(|x| {
PairwiseAlgorithm::from_str(x)
.map_err(|_| NetworkStateError::InvalidGroupAlgorithm(x.to_string()))
})
.collect::<Result<Vec<PairwiseAlgorithm>, NetworkStateError>>()?;
let wpa_protocol_versions = settings
.wpa_protocol_versions
.iter()
.map(|x| {
WPAProtocolVersion::from_str(x)
.map_err(|_| NetworkStateError::InvalidGroupAlgorithm(x.to_string()))
})
.collect::<Result<Vec<WPAProtocolVersion>, NetworkStateError>>()?;

Ok(WirelessConfig {
ssid,
mode,
security,
password: settings.password,
band,
channel: settings.channel,
bssid,
hidden: settings.hidden,
group_algorithms,
pairwise_algorithms,
wpa_protocol_versions,
pmf: settings.pmf,
..Default::default()
})
}
Expand All @@ -1012,11 +1067,37 @@ impl TryFrom<WirelessConfig> for WirelessSettings {
type Error = NetworkStateError;

fn try_from(wireless: WirelessConfig) -> Result<Self, Self::Error> {
let band = wireless.band.map(|x| x.to_string());
let bssid = wireless.bssid.map(|x| x.to_string());
let group_algorithms = wireless
.group_algorithms
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>();
let pairwise_algorithms = wireless
.pairwise_algorithms
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>();
let wpa_protocol_versions = wireless
.wpa_protocol_versions
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>();

Ok(WirelessSettings {
ssid: wireless.ssid.to_string(),
mode: wireless.mode.to_string(),
security: wireless.security.to_string(),
password: wireless.password,
band,
channel: wireless.channel,
bssid,
hidden: wireless.hidden,
group_algorithms,
pairwise_algorithms,
wpa_protocol_versions,
pmf: wireless.pmf,
})
}
}
Expand Down Expand Up @@ -1105,6 +1186,108 @@ impl TryFrom<&str> for SecurityProtocol {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
pub enum GroupAlgorithm {
Wep40,
Wep104,
Tkip,
Ccmp,
}

#[derive(Debug, Error)]
#[error("Invalid group algorithm: {0}")]
pub struct InvalidGroupAlgorithm(String);

impl FromStr for GroupAlgorithm {
type Err = InvalidGroupAlgorithm;

fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"wep40" => Ok(GroupAlgorithm::Wep40),
"wep104" => Ok(GroupAlgorithm::Wep104),
"tkip" => Ok(GroupAlgorithm::Tkip),
"ccmp" => Ok(GroupAlgorithm::Ccmp),
_ => Err(InvalidGroupAlgorithm(value.to_string())),
}
}
}

impl fmt::Display for GroupAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match &self {
GroupAlgorithm::Wep40 => "wep40",
GroupAlgorithm::Wep104 => "wep104",
GroupAlgorithm::Tkip => "tkip",
GroupAlgorithm::Ccmp => "ccmp",
};
write!(f, "{}", name)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
pub enum PairwiseAlgorithm {
Tkip,
Ccmp,
}

#[derive(Debug, Error)]
#[error("Invalid pairwise algorithm: {0}")]
pub struct InvalidPairwiseAlgorithm(String);

impl FromStr for PairwiseAlgorithm {
type Err = InvalidPairwiseAlgorithm;

fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"tkip" => Ok(PairwiseAlgorithm::Tkip),
"ccmp" => Ok(PairwiseAlgorithm::Ccmp),
_ => Err(InvalidPairwiseAlgorithm(value.to_string())),
}
}
}

impl fmt::Display for PairwiseAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match &self {
PairwiseAlgorithm::Tkip => "tkip",
PairwiseAlgorithm::Ccmp => "ccmp",
};
write!(f, "{}", name)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
pub enum WPAProtocolVersion {
Wpa,
Rsn,
}

#[derive(Debug, Error)]
#[error("Invalid WPA protocol version: {0}")]
pub struct InvalidWPAProtocolVersion(String);

impl FromStr for WPAProtocolVersion {
type Err = InvalidWPAProtocolVersion;

fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"wpa" => Ok(WPAProtocolVersion::Wpa),
"rsn" => Ok(WPAProtocolVersion::Rsn),
_ => Err(InvalidWPAProtocolVersion(value.to_string())),
}
}
}

impl fmt::Display for WPAProtocolVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match &self {
WPAProtocolVersion::Wpa => "wpa",
WPAProtocolVersion::Rsn => "rsn",
};
write!(f, "{}", name)
}
}

#[derive(Debug, Default, PartialEq, Clone, Serialize)]
pub struct WEPSecurity {
pub auth_alg: WEPAuthAlg,
Expand Down
Loading

0 comments on commit 25d6e19

Please sign in to comment.