improv: network authentication
This commit is contained in:
parent
2924fea3ac
commit
f48bcde63b
3 changed files with 31 additions and 55 deletions
|
|
@ -20,7 +20,6 @@ use cosmic_settings_network_manager_subscription::{
|
||||||
self as network_manager, NetworkManagerState,
|
self as network_manager, NetworkManagerState,
|
||||||
available_wifi::{AccessPoint, NetworkType},
|
available_wifi::{AccessPoint, NetworkType},
|
||||||
current_networks::ActiveConnectionInfo,
|
current_networks::ActiveConnectionInfo,
|
||||||
hw_address::HwAddress,
|
|
||||||
nm_secret_agent,
|
nm_secret_agent,
|
||||||
};
|
};
|
||||||
use cosmic_settings_page::{self as page, Section, section};
|
use cosmic_settings_page::{self as page, Section, section};
|
||||||
|
|
@ -103,7 +102,6 @@ enum WiFiDialog {
|
||||||
Forget(network_manager::SSID),
|
Forget(network_manager::SSID),
|
||||||
Password {
|
Password {
|
||||||
ssid: network_manager::SSID,
|
ssid: network_manager::SSID,
|
||||||
hw_address: HwAddress,
|
|
||||||
identity: Option<String>,
|
identity: Option<String>,
|
||||||
password: SecureString,
|
password: SecureString,
|
||||||
password_hidden: bool,
|
password_hidden: bool,
|
||||||
|
|
@ -353,12 +351,7 @@ impl Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
match req {
|
match req {
|
||||||
network_manager::Request::Authenticate {
|
network_manager::Request::Authenticate { ssid, identity, .. } => {
|
||||||
ssid,
|
|
||||||
identity,
|
|
||||||
hw_address,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
if success {
|
if success {
|
||||||
self.connecting.remove(ssid.as_str());
|
self.connecting.remove(ssid.as_str());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -366,7 +359,6 @@ impl Page {
|
||||||
self.dialog = Some(WiFiDialog::Password {
|
self.dialog = Some(WiFiDialog::Password {
|
||||||
ssid: ssid.into(),
|
ssid: ssid.into(),
|
||||||
identity,
|
identity,
|
||||||
hw_address,
|
|
||||||
password: SecureString::from(""),
|
password: SecureString::from(""),
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
|
|
@ -377,9 +369,9 @@ impl Page {
|
||||||
|
|
||||||
network_manager::Request::SelectAccessPoint(
|
network_manager::Request::SelectAccessPoint(
|
||||||
ssid,
|
ssid,
|
||||||
hw_address,
|
|
||||||
network_type,
|
network_type,
|
||||||
_tx,
|
_tx,
|
||||||
|
interface,
|
||||||
) => {
|
) => {
|
||||||
if success || matches!(network_type, NetworkType::Open) {
|
if success || matches!(network_type, NetworkType::Open) {
|
||||||
self.connecting.remove(ssid.as_ref());
|
self.connecting.remove(ssid.as_ref());
|
||||||
|
|
@ -388,7 +380,6 @@ impl Page {
|
||||||
ssid,
|
ssid,
|
||||||
identity: matches!(network_type, NetworkType::EAP)
|
identity: matches!(network_type, NetworkType::EAP)
|
||||||
.then(String::new),
|
.then(String::new),
|
||||||
hw_address,
|
|
||||||
password: SecureString::from(""),
|
password: SecureString::from(""),
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
|
|
@ -499,9 +490,9 @@ impl Page {
|
||||||
.sender
|
.sender
|
||||||
.unbounded_send(network_manager::Request::SelectAccessPoint(
|
.unbounded_send(network_manager::Request::SelectAccessPoint(
|
||||||
ssid,
|
ssid,
|
||||||
ap.hw_address,
|
|
||||||
ap.network_type,
|
ap.network_type,
|
||||||
self.secret_tx.clone(),
|
self.secret_tx.clone(),
|
||||||
|
self.active_device.as_ref().map(|d| d.interface.clone()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -528,7 +519,6 @@ impl Page {
|
||||||
self.dialog = Some(WiFiDialog::Password {
|
self.dialog = Some(WiFiDialog::Password {
|
||||||
ssid,
|
ssid,
|
||||||
identity: matches!(ap.network_type, NetworkType::EAP).then(String::new),
|
identity: matches!(ap.network_type, NetworkType::EAP).then(String::new),
|
||||||
hw_address: ap.hw_address,
|
|
||||||
password: SecureString::from(""),
|
password: SecureString::from(""),
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
|
|
@ -553,7 +543,6 @@ impl Page {
|
||||||
ssid,
|
ssid,
|
||||||
identity,
|
identity,
|
||||||
password,
|
password,
|
||||||
hw_address,
|
|
||||||
tx,
|
tx,
|
||||||
..
|
..
|
||||||
} = dialog
|
} = dialog
|
||||||
|
|
@ -562,6 +551,7 @@ impl Page {
|
||||||
self.connecting.insert(ssid.clone());
|
self.connecting.insert(ssid.clone());
|
||||||
let nm_sender = nm.sender.clone();
|
let nm_sender = nm.sender.clone();
|
||||||
let secret_tx = self.secret_tx.clone();
|
let secret_tx = self.secret_tx.clone();
|
||||||
|
let interface = self.active_device.as_ref().map(|d| d.interface.clone());
|
||||||
return Task::future(async move {
|
return Task::future(async move {
|
||||||
let mut guard = tx.lock().await;
|
let mut guard = tx.lock().await;
|
||||||
if let Some(tx) = guard.take() {
|
if let Some(tx) = guard.take() {
|
||||||
|
|
@ -570,9 +560,9 @@ impl Page {
|
||||||
_ = nm_sender.unbounded_send(network_manager::Request::Authenticate {
|
_ = nm_sender.unbounded_send(network_manager::Request::Authenticate {
|
||||||
ssid: ssid.to_string(),
|
ssid: ssid.to_string(),
|
||||||
identity,
|
identity,
|
||||||
hw_address,
|
|
||||||
password,
|
password,
|
||||||
secret_tx,
|
secret_tx,
|
||||||
|
interface,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -718,7 +708,6 @@ impl Page {
|
||||||
ssid,
|
ssid,
|
||||||
password: previous,
|
password: previous,
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
hw_address: ap.hw_address,
|
|
||||||
identity: matches!(ap.network_type, NetworkType::EAP).then(String::new),
|
identity: matches!(ap.network_type, NetworkType::EAP).then(String::new),
|
||||||
tx,
|
tx,
|
||||||
});
|
});
|
||||||
|
|
@ -736,7 +725,6 @@ impl Page {
|
||||||
ssid,
|
ssid,
|
||||||
password,
|
password,
|
||||||
identity,
|
identity,
|
||||||
hw_address,
|
|
||||||
..
|
..
|
||||||
}) = self.dialog.take()
|
}) = self.dialog.take()
|
||||||
{
|
{
|
||||||
|
|
@ -746,7 +734,6 @@ impl Page {
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
ssid,
|
ssid,
|
||||||
identity,
|
identity,
|
||||||
hw_address,
|
|
||||||
});
|
});
|
||||||
return task::message(Message::FocusSecureInput);
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ use futures::{
|
||||||
FutureExt, SinkExt, StreamExt,
|
FutureExt, SinkExt, StreamExt,
|
||||||
channel::mpsc::{UnboundedReceiver, UnboundedSender, unbounded},
|
channel::mpsc::{UnboundedReceiver, UnboundedSender, unbounded},
|
||||||
};
|
};
|
||||||
use hw_address::HwAddress;
|
|
||||||
use iced_futures::{Subscription, stream};
|
use iced_futures::{Subscription, stream};
|
||||||
use secure_string::SecureString;
|
use secure_string::SecureString;
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
|
@ -45,8 +44,6 @@ pub type UUID = Arc<str>;
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("access point not found")]
|
|
||||||
AccessPointNotFound,
|
|
||||||
#[error("failed to list bluetooth devices with rfkill")]
|
#[error("failed to list bluetooth devices with rfkill")]
|
||||||
BluetoothRfkillList(std::io::Error),
|
BluetoothRfkillList(std::io::Error),
|
||||||
#[error("failed to activate connection")]
|
#[error("failed to activate connection")]
|
||||||
|
|
@ -299,8 +296,8 @@ async fn start_listening(
|
||||||
ssid,
|
ssid,
|
||||||
identity,
|
identity,
|
||||||
password,
|
password,
|
||||||
hw_address,
|
|
||||||
secret_tx,
|
secret_tx,
|
||||||
|
interface,
|
||||||
}) => {
|
}) => {
|
||||||
let nm_state = NetworkManagerState::new(&conn).await.unwrap_or_default();
|
let nm_state = NetworkManagerState::new(&conn).await.unwrap_or_default();
|
||||||
|
|
||||||
|
|
@ -310,13 +307,13 @@ async fn start_listening(
|
||||||
&ssid,
|
&ssid,
|
||||||
identity.as_deref(),
|
identity.as_deref(),
|
||||||
Some(password.unsecure()),
|
Some(password.unsecure()),
|
||||||
hw_address,
|
|
||||||
secret_tx.clone(),
|
secret_tx.clone(),
|
||||||
if identity.is_some() {
|
if identity.is_some() {
|
||||||
NetworkType::EAP
|
NetworkType::EAP
|
||||||
} else {
|
} else {
|
||||||
NetworkType::PSK
|
NetworkType::PSK
|
||||||
},
|
},
|
||||||
|
interface.clone(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.is_ok();
|
.is_ok();
|
||||||
|
|
@ -327,8 +324,8 @@ async fn start_listening(
|
||||||
ssid: ssid.clone(),
|
ssid: ssid.clone(),
|
||||||
identity: identity.clone(),
|
identity: identity.clone(),
|
||||||
password: password.clone(),
|
password: password.clone(),
|
||||||
hw_address,
|
|
||||||
secret_tx: secret_tx.clone(),
|
secret_tx: secret_tx.clone(),
|
||||||
|
interface,
|
||||||
},
|
},
|
||||||
success,
|
success,
|
||||||
state: NetworkManagerState::new(&conn).await.unwrap_or_default(),
|
state: NetworkManagerState::new(&conn).await.unwrap_or_default(),
|
||||||
|
|
@ -336,17 +333,10 @@ async fn start_listening(
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Request::SelectAccessPoint(ssid, hw_address, network_type, secret_tx)) => {
|
Some(Request::SelectAccessPoint(ssid, network_type, secret_tx, interface)) => {
|
||||||
if matches!(network_type, NetworkType::Open) {
|
if matches!(network_type, NetworkType::Open) {
|
||||||
attempt_wifi_connection(
|
attempt_wifi_connection(&conn, ssid, network_type, output, None, interface)
|
||||||
&conn,
|
.await;
|
||||||
ssid,
|
|
||||||
hw_address,
|
|
||||||
network_type,
|
|
||||||
output,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
} else {
|
} else {
|
||||||
// For secured networks, check if we have saved credentials
|
// For secured networks, check if we have saved credentials
|
||||||
let has_saved = has_saved_wifi_credentials(&conn, &ssid).await;
|
let has_saved = has_saved_wifi_credentials(&conn, &ssid).await;
|
||||||
|
|
@ -359,10 +349,10 @@ async fn start_listening(
|
||||||
attempt_wifi_connection(
|
attempt_wifi_connection(
|
||||||
&conn,
|
&conn,
|
||||||
ssid,
|
ssid,
|
||||||
hw_address,
|
|
||||||
network_type,
|
network_type,
|
||||||
output,
|
output,
|
||||||
secret_tx,
|
secret_tx,
|
||||||
|
interface,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
@ -640,10 +630,10 @@ async fn has_saved_wifi_credentials(conn: &zbus::Connection, ssid: &str) -> bool
|
||||||
async fn attempt_wifi_connection(
|
async fn attempt_wifi_connection(
|
||||||
conn: &zbus::Connection,
|
conn: &zbus::Connection,
|
||||||
ssid: SSID,
|
ssid: SSID,
|
||||||
hw_address: HwAddress,
|
|
||||||
network_type: NetworkType,
|
network_type: NetworkType,
|
||||||
output: &mut futures::channel::mpsc::Sender<Event>,
|
output: &mut futures::channel::mpsc::Sender<Event>,
|
||||||
secret_tx: Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
secret_tx: Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
||||||
|
interface: Option<String>,
|
||||||
) {
|
) {
|
||||||
let state = NetworkManagerState::new(conn).await.unwrap_or_default();
|
let state = NetworkManagerState::new(conn).await.unwrap_or_default();
|
||||||
let success = if let Err(err) = state
|
let success = if let Err(err) = state
|
||||||
|
|
@ -652,9 +642,9 @@ async fn attempt_wifi_connection(
|
||||||
ssid.as_ref(),
|
ssid.as_ref(),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
hw_address,
|
|
||||||
secret_tx,
|
secret_tx,
|
||||||
network_type,
|
network_type,
|
||||||
|
interface.clone(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|
@ -666,7 +656,7 @@ async fn attempt_wifi_connection(
|
||||||
|
|
||||||
_ = request_response(
|
_ = request_response(
|
||||||
conn,
|
conn,
|
||||||
Request::SelectAccessPoint(ssid, hw_address, network_type, None),
|
Request::SelectAccessPoint(ssid, network_type, None, interface),
|
||||||
success,
|
success,
|
||||||
)
|
)
|
||||||
.then(|event| output.send(event))
|
.then(|event| output.send(event))
|
||||||
|
|
@ -688,8 +678,8 @@ pub enum Request {
|
||||||
ssid: String,
|
ssid: String,
|
||||||
identity: Option<String>,
|
identity: Option<String>,
|
||||||
password: SecureString,
|
password: SecureString,
|
||||||
hw_address: HwAddress,
|
|
||||||
secret_tx: Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
secret_tx: Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
||||||
|
interface: Option<String>,
|
||||||
},
|
},
|
||||||
/// Get WiFi credentials for a known access point.
|
/// Get WiFi credentials for a known access point.
|
||||||
GetWiFiCredentials(
|
GetWiFiCredentials(
|
||||||
|
|
@ -705,9 +695,9 @@ pub enum Request {
|
||||||
/// Connect to a known access point.
|
/// Connect to a known access point.
|
||||||
SelectAccessPoint(
|
SelectAccessPoint(
|
||||||
SSID,
|
SSID,
|
||||||
HwAddress,
|
|
||||||
NetworkType,
|
NetworkType,
|
||||||
Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
||||||
|
Option<String>,
|
||||||
),
|
),
|
||||||
/// Toggle airplaine mode.
|
/// Toggle airplaine mode.
|
||||||
SetAirplaneMode(bool),
|
SetAirplaneMode(bool),
|
||||||
|
|
@ -907,9 +897,9 @@ impl NetworkManagerState {
|
||||||
ssid: &str,
|
ssid: &str,
|
||||||
identity: Option<&str>,
|
identity: Option<&str>,
|
||||||
password: Option<&str>,
|
password: Option<&str>,
|
||||||
hw_address: HwAddress,
|
|
||||||
mut secret_tx: Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
mut secret_tx: Option<tokio::sync::mpsc::Sender<nm_secret_agent::Request>>,
|
||||||
network_type: NetworkType,
|
network_type: NetworkType,
|
||||||
|
interface: Option<String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
secret_tx = secret_tx.filter(|tx| !tx.is_closed());
|
secret_tx = secret_tx.filter(|tx| !tx.is_closed());
|
||||||
let nm = NetworkManager::new(conn).await?;
|
let nm = NetworkManager::new(conn).await?;
|
||||||
|
|
@ -925,14 +915,6 @@ impl NetworkManagerState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(ap) = self
|
|
||||||
.wireless_access_points
|
|
||||||
.iter()
|
|
||||||
.find(|ap| ap.ssid.as_ref() == ssid && ap.hw_address == hw_address)
|
|
||||||
else {
|
|
||||||
return Err(Error::AccessPointNotFound);
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut conn_settings: HashMap<&str, HashMap<&str, zvariant::Value>> = HashMap::from([
|
let mut conn_settings: HashMap<&str, HashMap<&str, zvariant::Value>> = HashMap::from([
|
||||||
(
|
(
|
||||||
"802-11-wireless",
|
"802-11-wireless",
|
||||||
|
|
@ -984,7 +966,8 @@ impl NetworkManagerState {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
device.device_type().await.unwrap_or(DeviceType::Other),
|
device.device_type().await.unwrap_or(DeviceType::Other),
|
||||||
DeviceType::Wifi
|
DeviceType::Wifi
|
||||||
) {
|
) || (interface.is_some() && interface != device.interface().await.ok())
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1010,7 +993,7 @@ impl NetworkManagerState {
|
||||||
|
|
||||||
let known_conn = if let Some(known_conn) = known_conn {
|
let known_conn = if let Some(known_conn) = known_conn {
|
||||||
if secret_tx.is_none() || identity.is_some() {
|
if secret_tx.is_none() || identity.is_some() {
|
||||||
known_conn.update(conn_settings).await?;
|
known_conn.update(conn_settings).await.unwrap();
|
||||||
}
|
}
|
||||||
known_conn
|
known_conn
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,16 @@ async fn secret_agent_stream_impl(
|
||||||
msg_tx: futures::channel::mpsc::Sender<Event>,
|
msg_tx: futures::channel::mpsc::Sender<Event>,
|
||||||
mut rx: tokio::sync::mpsc::Receiver<Request>,
|
mut rx: tokio::sync::mpsc::Receiver<Request>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
// fail early if we can't connect, closing the channel
|
||||||
|
{
|
||||||
|
let ss = secret_service::SecretService::connect(secret_service::EncryptionType::Dh)
|
||||||
|
.await
|
||||||
|
.map_err(|e| Arc::new(e))?;
|
||||||
|
let collection = ss.get_default_collection().await.map_err(|e| Arc::new(e))?;
|
||||||
|
if collection.is_locked().await.map_err(|e| Arc::new(e))? {
|
||||||
|
_ = collection.unlock().await.map_err(|e| Arc::new(e))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
// register the secret agent with NetworkManager
|
// register the secret agent with NetworkManager
|
||||||
let proxy =
|
let proxy =
|
||||||
nm_secret_agent_manager::AgentManagerProxy::builder(&zbus::Connection::system().await?)
|
nm_secret_agent_manager::AgentManagerProxy::builder(&zbus::Connection::system().await?)
|
||||||
|
|
@ -162,10 +172,6 @@ async fn secret_agent_stream_impl(
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
proxy.register_with_capabilities(identifier, 1).await?;
|
proxy.register_with_capabilities(identifier, 1).await?;
|
||||||
// fail early if we can't connect, closing the channel
|
|
||||||
let _ = secret_service::SecretService::connect(secret_service::EncryptionType::Dh)
|
|
||||||
.await
|
|
||||||
.map_err(|e| Arc::new(e))?;
|
|
||||||
|
|
||||||
while let Some(request) = rx.recv().await {
|
while let Some(request) = rx.recv().await {
|
||||||
match request {
|
match request {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue