Commit 4b799db1 authored by Jiří Klimeš's avatar Jiří Klimeš

cli: add support for secret agent to 'nmcli dev connect' too

And move secrets getting code to common.c (without changes).
parent a1f16d25
......@@ -900,6 +900,93 @@ nmc_find_connection (const GPtrArray *connections,
return found;
}
static gboolean
get_secrets_from_user (const char *request_id,
const char *title,
const char *msg,
gboolean ask,
GHashTable *pwds_hash,
GPtrArray *secrets)
{
int i;
for (i = 0; i < secrets->len; i++) {
NMSecretAgentSimpleSecret *secret = secrets->pdata[i];
char *pwd = NULL;
/* First try to find the password in provided passwords file,
* then ask user. */
if (pwds_hash && (pwd = g_hash_table_lookup (pwds_hash, secret->prop_name))) {
pwd = g_strdup (pwd);
} else {
g_print ("%s\n", msg);
if (ask) {
if (secret->value) {
/* Prefill the password if we have it. */
rl_startup_hook = nmc_rl_set_deftext;
nmc_rl_pre_input_deftext = g_strdup (secret->value);
}
pwd = nmc_readline ("%s (%s): ", secret->name, secret->prop_name);
if (!pwd)
pwd = g_strdup ("");
} else {
g_printerr (_("Warning: password for '%s' not given in 'passwd-file' "
"and nmcli cannot ask without '--ask' option.\n"),
secret->prop_name);
}
}
/* No password provided, cancel the secrets. */
if (!pwd)
return FALSE;
g_free (secret->value);
secret->value = pwd;
}
return TRUE;
}
/**
* nmc_secrets_requested:
* @agent: the #NMSecretAgentSimple
* @request_id: request ID, to eventually pass to
* nm_secret_agent_simple_response()
* @title: a title for the password request
* @msg: a prompt message for the password request
* @secrets: (element-type #NMSecretAgentSimpleSecret): array of secrets
* being requested.
* @user_data: user data passed to the function
*
* This function is used as a callback for "request-secrets" signal of
* NMSecretAgentSimpleSecret.
*/
void
nmc_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 ();
success = get_secrets_from_user (request_id, title, msg, nmc->in_editor || nmc->ask,
nmc->pwds_hash, secrets);
if (success)
nm_secret_agent_simple_response (agent, request_id, secrets);
else {
/* Unregister our secret agent on failure, so that another agent
* may be tried */
if (nmc->secret_agent) {
nm_secret_agent_unregister (nmc->secret_agent, NULL, NULL);
g_clear_object (&nmc->secret_agent);
}
}
}
/**
* nmc_cleanup_readline:
*
......@@ -1042,3 +1129,18 @@ nmc_rl_gen_func_basic (const char *text, int state, const char **words)
return NULL;
}
/* for pre-filling a string to readline prompt */
char *nmc_rl_pre_input_deftext;
int
nmc_rl_set_deftext (void)
{
if (nmc_rl_pre_input_deftext && rl_startup_hook) {
rl_insert_text (nmc_rl_pre_input_deftext);
g_free (nmc_rl_pre_input_deftext);
nmc_rl_pre_input_deftext = NULL;
rl_startup_hook = NULL;
}
return 0;
}
......@@ -16,13 +16,14 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2012 - 2014 Red Hat, Inc.
* Copyright 2012 - 2014 Red Hat, Inc.
*/
#ifndef NMC_COMMON_H
#define NMC_COMMON_H
#include "nmcli.h"
#include "nm-secret-agent-simple.h"
gboolean print_ip4_config (NMIPConfig *cfg4, NmCli *nmc, const char *group_prefix, const char *one_field);
gboolean print_ip6_config (NMIPConfig *cfg6, NmCli *nmc, const char *group_prefix, const char *one_field);
......@@ -48,10 +49,21 @@ NMConnection *nmc_find_connection (const GPtrArray *connections,
const char *filter_val,
int *start);
void nmc_secrets_requested (NMSecretAgentSimple *agent,
const char *request_id,
const char *title,
const char *msg,
GPtrArray *secrets,
gpointer user_data);
void nmc_cleanup_readline (void);
char *nmc_readline (const char *prompt_fmt, ...) G_GNUC_PRINTF (1, 2);
char *nmc_rl_gen_func_basic (const char *text, int state, const char **words);
gboolean nmc_get_in_readline (void);
void nmc_set_in_readline (gboolean in_readline);
/* for pre-filling a string to readline prompt */
extern char *nmc_rl_pre_input_deftext;
int nmc_rl_set_deftext (void);
#endif /* NMC_COMMON_H */
......@@ -510,20 +510,6 @@ 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)
{
......@@ -2044,77 +2030,7 @@ failure:
return NULL;
}
static gboolean
get_secrets_from_user (const char *request_id,
const char *title,
const char *msg,
gboolean ask,
GHashTable *pwds_hash,
GPtrArray *secrets)
{
int i;
for (i = 0; i < secrets->len; i++) {
NMSecretAgentSimpleSecret *secret = secrets->pdata[i];
char *pwd = NULL;
/* First try to find the password in provided passwords file,
* then ask user. */
if (pwds_hash && (pwd = g_hash_table_lookup (pwds_hash, secret->prop_name))) {
pwd = g_strdup (pwd);
} else {
g_print ("%s\n", msg);
if (ask) {
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);
if (!pwd)
pwd = g_strdup ("");
} else {
g_printerr (_("Warning: password for '%s' not given in 'passwd-file' "
"and nmcli cannot ask without '--ask' option.\n"),
secret->prop_name);
}
}
/* No password provided, cancel the secrets. */
if (!pwd)
return FALSE;
g_free (secret->value);
secret->value = pwd;
}
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 ();
success = get_secrets_from_user (request_id, title, msg, nmc->in_editor || nmc->ask,
nmc->pwds_hash, secrets);
if (success)
nm_secret_agent_simple_response (agent, request_id, secrets);
else {
/* Unregister our secret agent on failure, so that another agent
* may be tried */
if (nmc->secret_agent) {
nm_secret_agent_unregister (nmc->secret_agent, NULL, NULL);
g_clear_object (&nmc->secret_agent);
}
}
}
static gboolean
nmc_activate_connection (NmCli *nmc,
......@@ -2174,7 +2090,7 @@ nmc_activate_connection (NmCli *nmc,
/* 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);
g_signal_connect (nmc->secret_agent, "request-secrets", G_CALLBACK (nmc_secrets_requested), nmc);
if (connection) {
const gchar *path = nm_object_get_path (NM_OBJECT (connection));
......@@ -7062,8 +6978,8 @@ property_edit_submenu (NmCli *nmc,
break;
case NMC_EDITOR_SUB_CMD_CHANGE:
rl_startup_hook = set_deftext;
pre_input_deftext = nmc_setting_get_property_out2in (curr_setting, prop_name, NULL);
rl_startup_hook = nmc_rl_set_deftext;
nmc_rl_pre_input_deftext = nmc_setting_get_property_out2in (curr_setting, prop_name, NULL);
prop_val_user = nmc_readline (_("Edit '%s' value: "), prop_name);
nmc_property_get_gvalue (curr_setting, prop_name, &prop_g_value);
......
......@@ -28,6 +28,7 @@
#include <glib.h>
#include <glib/gi18n.h>
#include "nm-secret-agent-simple.h"
#include "polkit-agent.h"
#include "utils.h"
#include "common.h"
......@@ -1517,6 +1518,14 @@ connect_device_cb (GObject *client, GAsyncResult *result, gpointer user_data)
g_object_unref (active);
quit ();
} else {
if (nmc->secret_agent) {
NMRemoteConnection *connection = nm_active_connection_get_connection (active);
const char *path = nm_connection_get_path (NM_CONNECTION (connection));
nm_secret_agent_simple_set_connection_path (nmc->secret_agent, path);
nm_secret_agent_simple_enable (nmc->secret_agent);
}
g_object_ref (device);
g_signal_connect (device, "notify::state", G_CALLBACK (device_state_cb), active);
g_signal_connect (active, "notify::state", G_CALLBACK (active_state_cb), device);
......@@ -1589,6 +1598,11 @@ do_device_connect (NmCli *nmc, int argc, char **argv)
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
/* 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 (nmc_secrets_requested), nmc);
info = g_malloc0 (sizeof (AddAndActivateInfo));
info->nmc = nmc;
info->device = device;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment