From de7f85bdec86c8cd8e08a57f4217bc0ccaf96f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Mon, 6 Oct 2014 15:25:53 +0200 Subject: [PATCH] cli: use secret agent for getting passwords from user --ask option has to be used, so that nmcli can be interactive. --- clients/cli/Makefile.am | 7 +++- clients/cli/connections.c | 84 +++++++++++++++++++++++++++++++++------ clients/cli/nmcli.c | 7 ++++ clients/cli/nmcli.h | 1 + 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/clients/cli/Makefile.am b/clients/cli/Makefile.am index 94a249749e..4f4fcf4c6d 100644 --- a/clients/cli/Makefile.am +++ b/clients/cli/Makefile.am @@ -9,6 +9,7 @@ AM_CPPFLAGS = \ -I${top_builddir}/libnm-core \ -I${top_srcdir}/libnm \ -I${top_builddir}/libnm \ + -I${top_srcdir}/clients/common \ $(GLIB_CFLAGS) \ -DG_LOG_DOMAIN=\""nmcli"\" \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ @@ -28,7 +29,11 @@ nmcli_SOURCES = \ nmcli.c \ nmcli.h \ utils.c \ - utils.h + utils.h \ + \ + $(srcdir)/../common/nm-secret-agent-simple.c \ + $(srcdir)/../common/nm-secret-agent-simple.h \ + $(NULL) nmcli_LDADD = \ $(GLIB_LIBS) \ diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 4d48e2fb60..1e95b023ff 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -35,6 +35,7 @@ #include "common.h" #include "settings.h" #include "connections.h" +#include "nm-secret-agent-simple.h" /* define some prompts for connection editor */ #define EDITOR_PROMPT_SETTING _("Setting name? ") @@ -507,6 +508,20 @@ quit (void) g_main_loop_quit (loop); /* quit main loop */ } +/* for pre-filling a string to readline prompt */ +static char *pre_input_deftext; +static int +set_deftext (void) +{ + if (pre_input_deftext && rl_startup_hook) { + rl_insert_text (pre_input_deftext); + g_free (pre_input_deftext); + pre_input_deftext = NULL; + rl_startup_hook = NULL; + } + return 0; +} + static const char * construct_header_name (const char *base, const char *spec) { @@ -1926,6 +1941,57 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat g_free (info); } +static gboolean +get_secrets_from_user (const char *request_id, + const char *title, + const char *msg, + GPtrArray *secrets) +{ + int i; + char *pwd; + + g_print ("%s\n", msg); + for (i = 0; i < secrets->len; i++) { + NMSecretAgentSimpleSecret *secret = secrets->pdata[i]; + if (secret->value) { + /* Prefill the password if we have it. */ + rl_startup_hook = set_deftext; + pre_input_deftext = g_strdup (secret->value); + } + pwd = nmc_readline ("%s (%s): ", secret->name, secret->prop_name); + g_free (secret->value); + secret->value = pwd ? pwd : g_strdup (""); + } + return TRUE; +} + +static void +secrets_requested (NMSecretAgentSimple *agent, + const char *request_id, + const char *title, + const char *msg, + GPtrArray *secrets, + gpointer user_data) +{ + NmCli *nmc = (NmCli *) user_data; + gboolean success = FALSE; + + if (nmc->print_output == NMC_PRINT_PRETTY) + nmc_terminal_erase_line (); + + if (nmc->ask) { + success = get_secrets_from_user (request_id, title, msg, secrets); + } else { + g_print ("%s\n", msg); + g_print ("%s\n", _("Warning: nmcli does not ask for password without '--ask' argument.")); + } + + if (success) + nm_secret_agent_simple_response (agent, request_id, secrets); + else + nm_secret_agent_simple_response (agent, request_id, NULL); +} + static gboolean nmc_activate_connection (NmCli *nmc, NMConnection *connection, @@ -1967,6 +2033,11 @@ nmc_activate_connection (NmCli *nmc, return FALSE; } + /* Create secret agent */ + nmc->secret_agent = nm_secret_agent_simple_new ("nmcli-connect"); + if (nmc->secret_agent) + g_signal_connect (nmc->secret_agent, "request-secrets", G_CALLBACK (secrets_requested), nmc); + info = g_malloc0 (sizeof (ActivateConnectionInfo)); info->nmc = nmc; info->device = device; @@ -5426,19 +5497,6 @@ uuid_display_hook (char **array, int len, int max_len) rl_forced_update_display (); } -static char *pre_input_deftext; -static int -set_deftext (void) -{ - if (pre_input_deftext && rl_startup_hook) { - rl_insert_text (pre_input_deftext); - g_free (pre_input_deftext); - pre_input_deftext = NULL; - rl_startup_hook = NULL; - } - return 0; -} - static char * gen_nmcli_cmds_menu (const char *text, int state) { diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index b1a810ce7a..74029438f1 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -499,6 +499,7 @@ nmc_init (NmCli *nmc) nmc->timeout = -1; nmc->connections = NULL; + nmc->secret_agent = NULL; nmc->should_wait = FALSE; nmc->nowait_flag = TRUE; @@ -525,6 +526,12 @@ nmc_cleanup (NmCli *nmc) g_string_free (nmc->return_text, TRUE); + if (nmc->secret_agent) { + /* Destroy secret agent if we have one. */ + nm_secret_agent_unregister (nmc->secret_agent, NULL, NULL); + g_object_unref (nmc->secret_agent); + } + g_free (nmc->required_fields); nmc_empty_output_fields (nmc); g_ptr_array_unref (nmc->output_data); diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h index 0a87bd9147..6fe39392ff 100644 --- a/clients/cli/nmcli.h +++ b/clients/cli/nmcli.h @@ -111,6 +111,7 @@ typedef struct _NmCli { int timeout; /* Operation timeout */ const GPtrArray *connections; /* List of connections */ + NMSecretAgent *secret_agent; /* Secret agent */ gboolean should_wait; /* Indication that nmcli should not end yet */ gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */