@@ -662,94 +662,54 @@ impl NetworkModule { |
| 662 | 662 | |
| 663 | 663 | info!("Connecting to enterprise WiFi: {} ({:?})", form.ssid, form.eap_method); |
| 664 | 664 | |
| 665 | | - let conn = match &self.conn { |
| 666 | | - Some(c) => c, |
| 667 | | - None => anyhow::bail!("No D-Bus connection"), |
| 668 | | - }; |
| 669 | | - |
| 670 | | - let wifi_device = match self.get_wifi_device(conn) { |
| 671 | | - Some(d) => d, |
| 672 | | - None => anyhow::bail!("No WiFi device found"), |
| 673 | | - }; |
| 674 | | - |
| 675 | | - let ap_path = self.state.access_points.iter() |
| 676 | | - .find(|ap| ap.ssid == form.ssid) |
| 677 | | - .map(|ap| ap.path.clone()) |
| 678 | | - .ok_or_else(|| anyhow::anyhow!("Access point not found: {}", form.ssid))?; |
| 679 | | - |
| 680 | | - self.add_and_activate_eap_connection(conn, form, &wifi_device, &ap_path) |
| 681 | | - } |
| 682 | | - |
| 683 | | - /// Add and activate a new EAP/802.1X connection |
| 684 | | - fn add_and_activate_eap_connection( |
| 685 | | - &self, |
| 686 | | - conn: &Connection, |
| 687 | | - form: &EapFormState, |
| 688 | | - device_path: &str, |
| 689 | | - ap_path: &str, |
| 690 | | - ) -> Result<()> { |
| 691 | | - use std::collections::HashMap; |
| 692 | | - use zbus::zvariant::ObjectPath; |
| 693 | | - |
| 694 | | - let mut connection: HashMap<&str, Value> = HashMap::new(); |
| 695 | | - connection.insert("type", Value::Str("802-11-wireless".into())); |
| 696 | | - connection.insert("id", Value::Str(form.ssid.clone().into())); |
| 697 | | - let user = std::env::var("USER").unwrap_or_else(|_| "user".to_string()); |
| 698 | | - let permissions = vec![Value::Str(format!("user:{}:", user).into())]; |
| 699 | | - connection.insert("permissions", Value::Array(permissions.into())); |
| 700 | | - |
| 701 | | - let mut wireless: HashMap<&str, Value> = HashMap::new(); |
| 702 | | - let ssid_bytes: Vec<Value> = form.ssid.bytes().map(Value::U8).collect(); |
| 703 | | - wireless.insert("ssid", Value::Array(ssid_bytes.into())); |
| 704 | | - wireless.insert("mode", Value::Str("infrastructure".into())); |
| 705 | | - wireless.insert("security", Value::Str("802-11-wireless-security".into())); |
| 706 | | - |
| 707 | | - let mut wireless_security: HashMap<&str, Value> = HashMap::new(); |
| 708 | | - wireless_security.insert("key-mgmt", Value::Str("wpa-eap".into())); |
| 709 | | - |
| 710 | | - let mut eap_settings: HashMap<&str, Value> = HashMap::new(); |
| 711 | | - let eap_methods = vec![Value::Str(form.eap_method.as_str().into())]; |
| 712 | | - eap_settings.insert("eap", Value::Array(eap_methods.into())); |
| 713 | | - eap_settings.insert("identity", Value::Str(form.identity.clone().into())); |
| 714 | | - eap_settings.insert("password", Value::Str(form.password.clone().into())); |
| 715 | | - eap_settings.insert("password-flags", Value::U32(0)); |
| 716 | | - |
| 665 | + // Use nmcli for enterprise WiFi - it handles the complex settings correctly |
| 666 | + let mut cmd = std::process::Command::new("nmcli"); |
| 667 | + cmd.args([ |
| 668 | + "connection", "add", |
| 669 | + "type", "wifi", |
| 670 | + "con-name", &form.ssid, |
| 671 | + "ssid", &form.ssid, |
| 672 | + "wifi-sec.key-mgmt", "wpa-eap", |
| 673 | + "802-1x.eap", form.eap_method.as_str(), |
| 674 | + "802-1x.identity", &form.identity, |
| 675 | + "802-1x.password", &form.password, |
| 676 | + "802-1x.phase2-auth", form.phase2_auth.as_str(), |
| 677 | + ]); |
| 678 | + |
| 679 | + // Add optional anonymous identity |
| 717 | 680 | if !form.anonymous_identity.is_empty() { |
| 718 | | - eap_settings.insert("anonymous-identity", Value::Str(form.anonymous_identity.clone().into())); |
| 681 | + cmd.args(["802-1x.anonymous-identity", &form.anonymous_identity]); |
| 719 | 682 | } |
| 720 | 683 | |
| 684 | + // Add optional CA certificate |
| 721 | 685 | if !form.ca_cert_path.is_empty() { |
| 722 | | - let ca_path = if form.ca_cert_path.starts_with("file://") { |
| 723 | | - form.ca_cert_path.clone() |
| 724 | | - } else { |
| 725 | | - format!("file://{}", form.ca_cert_path) |
| 726 | | - }; |
| 727 | | - let ca_bytes: Vec<Value> = ca_path.bytes().map(Value::U8).collect(); |
| 728 | | - eap_settings.insert("ca-cert", Value::Array(ca_bytes.into())); |
| 686 | + cmd.args(["802-1x.ca-cert", &form.ca_cert_path]); |
| 729 | 687 | } |
| 730 | 688 | |
| 731 | | - eap_settings.insert("phase2-auth", Value::Str(form.phase2_auth.as_str().into())); |
| 689 | + let output = cmd.output().context("Failed to run nmcli")?; |
| 732 | 690 | |
| 733 | | - let mut settings: HashMap<&str, HashMap<&str, Value>> = HashMap::new(); |
| 734 | | - settings.insert("connection", connection); |
| 735 | | - settings.insert("802-11-wireless", wireless); |
| 736 | | - settings.insert("802-11-wireless-security", wireless_security); |
| 737 | | - settings.insert("802-1x", eap_settings); |
| 691 | + if !output.status.success() { |
| 692 | + let stderr = String::from_utf8_lossy(&output.stderr); |
| 693 | + warn!("nmcli connection add failed: {}", stderr); |
| 694 | + anyhow::bail!("Failed to create connection: {}", stderr.trim()); |
| 695 | + } |
| 738 | 696 | |
| 739 | | - conn.call_method( |
| 740 | | - Some("org.freedesktop.NetworkManager"), |
| 741 | | - "/org/freedesktop/NetworkManager", |
| 742 | | - Some("org.freedesktop.NetworkManager"), |
| 743 | | - "AddAndActivateConnection", |
| 744 | | - &( |
| 745 | | - settings, |
| 746 | | - ObjectPath::from_str_unchecked(device_path), |
| 747 | | - ObjectPath::from_str_unchecked(ap_path), |
| 748 | | - ), |
| 749 | | - )?; |
| 697 | + info!("Created enterprise WiFi connection profile"); |
| 750 | 698 | |
| 751 | | - info!("AddAndActivateConnection with EAP requested for: {}", form.ssid); |
| 752 | | - Ok(()) |
| 699 | + // Now activate the connection |
| 700 | + let output = std::process::Command::new("nmcli") |
| 701 | + .args(["connection", "up", &form.ssid]) |
| 702 | + .output() |
| 703 | + .context("Failed to run nmcli")?; |
| 704 | + |
| 705 | + if output.status.success() { |
| 706 | + info!("Successfully connected to {}", form.ssid); |
| 707 | + Ok(()) |
| 708 | + } else { |
| 709 | + let stderr = String::from_utf8_lossy(&output.stderr); |
| 710 | + warn!("nmcli connection up failed: {}", stderr); |
| 711 | + anyhow::bail!("Failed to connect: {}", stderr.trim()) |
| 712 | + } |
| 753 | 713 | } |
| 754 | 714 | |
| 755 | 715 | /// Disconnect from current WiFi network |