From 7061341a41d510644bf2789c359a6dd45955edf4 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 11 Sep 2019 16:45:12 +0200 Subject: cli: add "nmcli d wifi show" A quick overview of the currently connected Wi-Fi network, including credentials. Comes handy if someone wants to connect more devices to their Hotspot or the same network as they are connected to. --- clients/cli/devices.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 218 insertions(+), 5 deletions(-) (limited to 'clients/cli') diff --git a/clients/cli/devices.c b/clients/cli/devices.c index 4321713a0e..24689f63da 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -696,6 +696,7 @@ usage (void) " [bssid ] [name ] [private yes|no] [hidden yes|no]\n\n" " wifi hotspot [ifname ] [con-name ] [ssid ] [band a|bg] [channel ] [password ]\n\n" " wifi rescan [ifname ] [[ssid ] ...]\n\n" + " wifi show-password [ifname ]\n\n" " lldp [list [ifname ]]\n\n" )); } @@ -1829,6 +1830,9 @@ connected_state_cb (AddAndActivateInfo *info) g_print (_("Device '%s' successfully activated with '%s'.\n"), nm_device_get_iface (info->device), nm_active_connection_get_uuid (info->active)); + + if (info->hotspot) + g_print (_("Hint: \"nmcli dev wifi show-password\" shows the Wi-Fi name and password.\n")); } else if ( state <= NM_DEVICE_STATE_DISCONNECTED || state >= NM_DEVICE_STATE_DEACTIVATING) { reason = nm_device_get_state_reason (info->device); @@ -4026,12 +4030,221 @@ finish: return nmc->return_value; } +static void +string_append_mecard (GString *string, const char *tag, const char *text) +{ + const char *p; + bool is_hex = TRUE; + int start; + + if (!text) + return; + + g_string_append (string, tag); + start = string->len; + + for (p = text; *p; p++) { + if (!g_ascii_isxdigit (*p)) + is_hex = FALSE; + if (strchr ("\\\":;,", *p)) + g_string_append_c (string, '\\'); + g_string_append_c (string, *p); + } + + if (is_hex) { + g_string_insert_c (string, start, '\"'); + g_string_append_c (string, '\"'); + } + g_string_append_c (string, ';'); +} + +static void +print_wifi_connection (const NmcConfig *nmc_config, NMConnection *connection) +{ + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wsec; + const char *key_mgmt = NULL; + const char *psk = NULL; + const char *type = NULL; + GBytes *ssid_bytes; + char *ssid; + GString *string; + + s_wireless = nm_connection_get_setting_wireless (connection); + g_return_if_fail (s_wireless); + + ssid_bytes = nm_setting_wireless_get_ssid (s_wireless); + g_return_if_fail (ssid_bytes); + ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid_bytes, NULL), + g_bytes_get_size (ssid_bytes)); + g_return_if_fail (ssid); + g_print ("SSID: %s\n", ssid); + + string = g_string_sized_new (64); + g_string_append (string, "WIFI:"); + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) { + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + psk = nm_setting_wireless_security_get_psk (s_wsec); + } + + if (key_mgmt == NULL) { + type = "nopass"; + g_print ("%s: %s\n", _("Security"), _("None")); + } else if ( strcmp (key_mgmt, "none") == 0 + || strcmp (key_mgmt, "ieee8021x") == 0) { + type = "WEP"; + g_print ("%s: WEP\n", _("Security")); + } else if ( strcmp (key_mgmt, "wpa-none") == 0 + || strcmp (key_mgmt, "wpa-psk") == 0 + || strcmp (key_mgmt, "sae") == 0) { + type = "WPA"; + g_print ("%s: WPA\n", _("Security")); + } + + if (psk) + g_print ("%s: %s\n", _("Password"), psk); + + string_append_mecard(string, "T:", type); + string_append_mecard(string, "S:", ssid); + string_append_mecard(string, "P:", psk); + + if (nm_setting_wireless_get_hidden (s_wireless)) + g_string_append (string, "H:true;"); + + g_string_append_c (string, ';'); + if (nmc_config->use_colors) + nmc_print_qrcode (string->str); + g_string_free (string, TRUE); + + g_print ("\n"); +} + +static gboolean +wifi_show_device (const NmcConfig *nmc_config, NMDevice *device, GError **error) +{ + NMActiveConnection *active_conn; + gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *secrets = NULL; + + if (!NM_IS_DEVICE_WIFI (device)) { + g_set_error (error, NMCLI_ERROR, 0, + _("Error: Device '%s' is not a Wi-Fi device."), + nm_device_get_iface (device)); + return FALSE; + } + + connection = nm_device_get_applied_connection (device, 0, NULL, NULL, error); + if (!connection) + return FALSE; + + active_conn = nm_device_get_active_connection (device); + if (!active_conn) { + g_set_error (error, NMCLI_ERROR, 0, + _("no active connection on device '%s'"), + nm_device_get_iface (device)); + return FALSE; + } + + secrets = nm_remote_connection_get_secrets (nm_active_connection_get_connection (active_conn), + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL, + NULL); + if (secrets && !nm_connection_update_secrets (connection, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + secrets, + error)) { + return FALSE; + } + + print_wifi_connection (nmc_config, connection); + + return TRUE; +} + +static NMCResultCode +do_device_wifi_show_password (NmCli *nmc, int argc, char **argv) +{ + const char *ifname = NULL; + gs_free NMDevice **devices = NULL; + gs_free_error GError *error = NULL; + gboolean found = FALSE; + int i; + + devices = nmc_get_devices_sorted (nmc->client); + + next_arg (nmc, &argc, &argv, NULL); + while (argc > 0) { + if (argc == 1 && nmc->complete) + nmc_complete_strings (*argv, "ifname"); + + if (strcmp (*argv, "ifname") == 0) { + if (ifname) { + g_string_printf (nmc->return_text, + _("Error: '%s' cannot repeat."), + *(argv-1)); + return NMC_RESULT_ERROR_USER_INPUT; + } + argc--; + argv++; + if (!argc) { + g_string_printf (nmc->return_text, + _("Error: %s argument is missing."), + *(argv-1)); + return NMC_RESULT_ERROR_USER_INPUT; + } + ifname = *argv; + if (argc == 1 && nmc->complete) + complete_device (devices, ifname, TRUE); + } else if (!nmc->complete) { + g_string_printf (nmc->return_text, + _("Error: invalid extra argument '%s'."), + *argv); + return NMC_RESULT_ERROR_USER_INPUT; + } + + next_arg (nmc, &argc, &argv, NULL); + } + + if (nmc->complete) + return nmc->return_value; + + for (i = 0; devices[i]; i++) { + if (ifname && g_strcmp0 (nm_device_get_iface (devices[i]), ifname) != 0) + continue; + + if (wifi_show_device (&nmc->nmc_config, devices[i], &error)) { + found = TRUE; + } else { + if (ifname) { + g_string_printf (nmc->return_text, + _("%s"), error->message); + return NMC_RESULT_ERROR_UNKNOWN; + } + g_clear_error (&error); + } + + if (ifname) + break; + } + + if (!found) { + g_string_printf (nmc->return_text, + _("Error: No Wi-Fi device found.")); + return NMC_RESULT_ERROR_UNKNOWN; + } + + return nmc->return_value; +} + static NMCCommand device_wifi_cmds[] = { - { "list", do_device_wifi_list, NULL, TRUE, TRUE }, - { "connect", do_device_wifi_connect, NULL, TRUE, TRUE }, - { "hotspot", do_device_wifi_hotspot, NULL, TRUE, TRUE }, - { "rescan", do_device_wifi_rescan, NULL, TRUE, TRUE }, - { NULL, do_device_wifi_list, NULL, TRUE, TRUE }, + { "list", do_device_wifi_list, NULL, TRUE, TRUE }, + { "connect", do_device_wifi_connect, NULL, TRUE, TRUE }, + { "hotspot", do_device_wifi_hotspot, NULL, TRUE, TRUE }, + { "rescan", do_device_wifi_rescan, NULL, TRUE, TRUE }, + { "show-password", do_device_wifi_show_password, NULL, TRUE, TRUE }, + { NULL, do_device_wifi_list, NULL, TRUE, TRUE }, }; static NMCResultCode -- cgit v1.2.1