merge: use NM secret agent in nmcli when connecting to networks (bgo #705998)

The secret agent code is shared between nmcli and nmtui.

https://bugzilla.gnome.org/show_bug.cgi?id=705998
https://bugzilla.redhat.com/show_bug.cgi?id=990111
This commit is contained in:
Jiří Klimeš 2014-11-07 11:32:38 +01:00
commit 847e2a405b
13 changed files with 505 additions and 280 deletions

View file

@ -9,6 +9,7 @@ AM_CPPFLAGS = \
-I${top_builddir}/libnm-core \ -I${top_builddir}/libnm-core \
-I${top_srcdir}/libnm \ -I${top_srcdir}/libnm \
-I${top_builddir}/libnm \ -I${top_builddir}/libnm \
-I${top_srcdir}/clients/common \
$(GLIB_CFLAGS) \ $(GLIB_CFLAGS) \
-DG_LOG_DOMAIN=\""nmcli"\" \ -DG_LOG_DOMAIN=\""nmcli"\" \
-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
@ -28,7 +29,11 @@ nmcli_SOURCES = \
nmcli.c \ nmcli.c \
nmcli.h \ nmcli.h \
utils.c \ utils.c \
utils.h utils.h \
\
$(srcdir)/../common/nm-secret-agent-simple.c \
$(srcdir)/../common/nm-secret-agent-simple.h \
$(NULL)
nmcli_LDADD = \ nmcli_LDADD = \
$(GLIB_LIBS) \ $(GLIB_LIBS) \

View file

@ -35,6 +35,7 @@
#include "common.h" #include "common.h"
#include "settings.h" #include "settings.h"
#include "connections.h" #include "connections.h"
#include "nm-secret-agent-simple.h"
/* define some prompts for connection editor */ /* define some prompts for connection editor */
#define EDITOR_PROMPT_SETTING _("Setting name? ") #define EDITOR_PROMPT_SETTING _("Setting name? ")
@ -250,9 +251,9 @@ usage (void)
"COMMAND := { show | up | down | add | modify | edit | delete | reload | load }\n\n" "COMMAND := { show | up | down | add | modify | edit | delete | reload | load }\n\n"
" show [--active] [[--show-secrets] [id | uuid | path | apath] <ID>] ...\n\n" " show [--active] [[--show-secrets] [id | uuid | path | apath] <ID>] ...\n\n"
#if WITH_WIMAX #if WITH_WIMAX
" up [[id | uuid | path] <ID>] [ifname <ifname>] [ap <BSSID>] [nsp <name>]\n\n" " up [[id | uuid | path] <ID>] [ifname <ifname>] [ap <BSSID>] [nsp <name>] [passwd-file <file with passwords>]\n\n"
#else #else
" up [[id | uuid | path] <ID>] [ifname <ifname>] [ap <BSSID>]\n\n" " up [[id | uuid | path] <ID>] [ifname <ifname>] [ap <BSSID>] [passwd-file <file with passwords>]\n\n"
#endif #endif
" down [id | uuid | path | apath] <ID>\n\n" " down [id | uuid | path | apath] <ID>\n\n"
" add COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS IP_OPTIONS\n\n" " add COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS IP_OPTIONS\n\n"
@ -290,19 +291,20 @@ usage_connection_up (void)
{ {
g_printerr (_("Usage: nmcli connection up { ARGUMENTS | help }\n" g_printerr (_("Usage: nmcli connection up { ARGUMENTS | help }\n"
"\n" "\n"
"ARGUMENTS := [id | uuid | path] <ID> [ifname <ifname>] [ap <BSSID>] [nsp <name>]\n" "ARGUMENTS := [id | uuid | path] <ID> [ifname <ifname>] [ap <BSSID>] [nsp <name>] [passwd-file <file with passwords>]\n"
"\n" "\n"
"Activate a connection on a device. The profile to activate is identified by its\n" "Activate a connection on a device. The profile to activate is identified by its\n"
"name, UUID or D-Bus path.\n" "name, UUID or D-Bus path.\n"
"\n" "\n"
"ARGUMENTS := ifname <ifname> [ap <BSSID>] [nsp <name>]\n" "ARGUMENTS := ifname <ifname> [ap <BSSID>] [nsp <name>] [passwd-file <file with passwords>]\n"
"\n" "\n"
"Activate a device with a connection. The connection profile is selected\n" "Activate a device with a connection. The connection profile is selected\n"
"automatically by NetworkManager.\n" "automatically by NetworkManager.\n"
"\n" "\n"
"ifname - specifies the device to active the connection on\n" "ifname - specifies the device to active the connection on\n"
"ap - specifies AP to connect to (only valid for Wi-Fi)\n" "ap - specifies AP to connect to (only valid for Wi-Fi)\n"
"nsp - specifies NSP to connect to (only valid for WiMAX)\n\n")); "nsp - specifies NSP to connect to (only valid for WiMAX)\n"
"passwd-file - file with password(s) required to activate the connection\n\n"));
} }
static void static void
@ -507,6 +509,20 @@ quit (void)
g_main_loop_quit (loop); /* quit main loop */ 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 * static const char *
construct_header_name (const char *base, const char *spec) construct_header_name (const char *base, const char *spec)
{ {
@ -1926,16 +1942,173 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
g_free (info); g_free (info);
} }
/**
* parse_passwords:
* @passwd_file: file with passwords to parse
* @error: location to store error, or %NULL
*
* Parse passwords given in @passwd_file and insert them into a hash table.
* Example of @passwd_file contents:
* wifi.psk:tajne heslo
* 802-1x.password:krakonos
* 802-11-wireless-security:leap-password:my leap password
*
* Returns: hash table with parsed passwords, or %NULL on an error
*/
static GHashTable *
parse_passwords (const char *passwd_file, GError **error)
{
GHashTable *pwds_hash;
char *contents = NULL;
gsize len = 0;
GError *local_err = NULL;
char **lines, **iter;
char *pwd_spec, *pwd, *prop;
const char *setting;
pwds_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
if (!passwd_file)
return pwds_hash;
/* Read the passwords file */
if (!g_file_get_contents (passwd_file, &contents, &len, &local_err)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("failed to read passwd-file '%s': %s"),
passwd_file, local_err->message);
g_error_free (local_err);
g_hash_table_destroy (pwds_hash);
return NULL;
}
lines = nmc_strsplit_set (contents, "\r\n", -1);
for (iter = lines; *iter; iter++) {
pwd = strchr (*iter, ':');
if (!pwd) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("missing colon in 'password' entry '%s'"), *iter);
goto failure;
}
*(pwd++) = '\0';
prop = strchr (*iter, '.');
if (!prop) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("missing dot in 'password' entry '%s'"), *iter);
goto failure;
}
*(prop++) = '\0';
setting = *iter;
while (g_ascii_isspace (*setting))
setting++;
/* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */
if (!strcmp (setting, "wifi-sec") || !strcmp (setting, "wifi"))
setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
if (nm_setting_lookup_type (setting) == G_TYPE_INVALID) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid setting name in 'password' entry '%s'"), setting);
goto failure;
}
pwd_spec = g_strdup_printf ("%s.%s", setting, prop);
g_hash_table_insert (pwds_hash, pwd_spec, g_strdup (pwd));
}
g_strfreev (lines);
g_free (contents);
return pwds_hash;
failure:
g_strfreev (lines);
g_free (contents);
g_hash_table_destroy (pwds_hash);
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 static gboolean
nmc_activate_connection (NmCli *nmc, nmc_activate_connection (NmCli *nmc,
NMConnection *connection, NMConnection *connection,
const char *ifname, const char *ifname,
const char *ap, const char *ap,
const char *nsp, const char *nsp,
const char *pwds,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
GError **error) GError **error)
{ {
ActivateConnectionInfo *info; ActivateConnectionInfo *info;
GHashTable *pwds_hash;
NMDevice *device = NULL; NMDevice *device = NULL;
const char *spec_object = NULL; const char *spec_object = NULL;
gboolean device_found; gboolean device_found;
@ -1967,6 +2140,21 @@ nmc_activate_connection (NmCli *nmc,
return FALSE; return FALSE;
} }
/* Parse passwords given in passwords file */
pwds_hash = parse_passwords (pwds, &local);
if (local) {
g_propagate_error (error, local);
return FALSE;
}
if (nmc->pwds_hash)
g_hash_table_destroy (nmc->pwds_hash);
nmc->pwds_hash = pwds_hash;
/* 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 = g_malloc0 (sizeof (ActivateConnectionInfo));
info->nmc = nmc; info->nmc = nmc;
info->device = device; info->device = device;
@ -1988,6 +2176,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
const char *ifname = NULL; const char *ifname = NULL;
const char *ap = NULL; const char *ap = NULL;
const char *nsp = NULL; const char *nsp = NULL;
const char *pwds = NULL;
GError *error = NULL; GError *error = NULL;
const char *selector = NULL; const char *selector = NULL;
const char *name = NULL; const char *name = NULL;
@ -2055,6 +2244,15 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
nsp = *argv; nsp = *argv;
} }
#endif #endif
else if (strcmp (*argv, "passwd-file") == 0) {
if (next_arg (&argc, &argv) != 0) {
g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto error;
}
pwds = *argv;
}
else { else {
g_printerr (_("Unknown parameter: %s\n"), *argv); g_printerr (_("Unknown parameter: %s\n"), *argv);
} }
@ -2070,7 +2268,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
nmc->nowait_flag = (nmc->timeout == 0); nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE; nmc->should_wait = TRUE;
if (!nmc_activate_connection (nmc, connection, ifname, ap, nsp, activate_connection_cb, &error)) { if (!nmc_activate_connection (nmc, connection, ifname, ap, nsp, pwds, activate_connection_cb, &error)) {
g_string_printf (nmc->return_text, _("Error: %s."), g_string_printf (nmc->return_text, _("Error: %s."),
error ? error->message : _("unknown error")); error ? error->message : _("unknown error"));
nmc->return_value = error ? error->code : NMC_RESULT_ERROR_CON_ACTIVATION; nmc->return_value = error ? error->code : NMC_RESULT_ERROR_CON_ACTIVATION;
@ -5426,19 +5624,6 @@ uuid_display_hook (char **array, int len, int max_len)
rl_forced_update_display (); 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 * static char *
gen_nmcli_cmds_menu (const char *text, int state) gen_nmcli_cmds_menu (const char *text, int state)
{ {
@ -7654,7 +7839,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
nmc->nowait_flag = FALSE; nmc->nowait_flag = FALSE;
nmc->should_wait = TRUE; nmc->should_wait = TRUE;
nmc->print_output = NMC_PRINT_PRETTY; nmc->print_output = NMC_PRINT_PRETTY;
if (!nmc_activate_connection (nmc, NM_CONNECTION (rem_con), ifname, ap_nsp, ap_nsp, if (!nmc_activate_connection (nmc, NM_CONNECTION (rem_con), ifname, ap_nsp, ap_nsp, NULL,
activate_connection_editor_cb, &tmp_err)) { activate_connection_editor_cb, &tmp_err)) {
g_print (_("Error: Cannot activate connection: %s.\n"), tmp_err->message); g_print (_("Error: Cannot activate connection: %s.\n"), tmp_err->message);
g_clear_error (&tmp_err); g_clear_error (&tmp_err);

View file

@ -502,7 +502,8 @@ _nmcli_compl_ARGS()
user| \ user| \
username| \ username| \
service| \ service| \
password) password| \
passwd-file)
if [[ "${#words[@]}" -eq 2 ]]; then if [[ "${#words[@]}" -eq 2 ]]; then
return 0 return 0
fi fi
@ -845,9 +846,9 @@ _nmcli()
_nmcli_compl_ARGS_CONNECTION && return 0 _nmcli_compl_ARGS_CONNECTION && return 0
if [[ "$COMMAND_CONNECTION_TYPE" = "ifname" ]]; then if [[ "$COMMAND_CONNECTION_TYPE" = "ifname" ]]; then
OPTIONS=(ap nsp) OPTIONS=(ap nsp passwd-file)
else else
OPTIONS=(ifname ap nsp) OPTIONS=(ifname ap nsp passwd-file)
fi fi
_nmcli_compl_ARGS _nmcli_compl_ARGS
fi fi

View file

@ -500,6 +500,9 @@ nmc_init (NmCli *nmc)
nmc->connections = NULL; nmc->connections = NULL;
nmc->secret_agent = NULL;
nmc->pwds_hash = NULL;
nmc->should_wait = FALSE; nmc->should_wait = FALSE;
nmc->nowait_flag = TRUE; nmc->nowait_flag = TRUE;
nmc->print_output = NMC_PRINT_NORMAL; nmc->print_output = NMC_PRINT_NORMAL;
@ -525,6 +528,14 @@ nmc_cleanup (NmCli *nmc)
g_string_free (nmc->return_text, TRUE); 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);
}
if (nmc->pwds_hash)
g_hash_table_destroy (nmc->pwds_hash);
g_free (nmc->required_fields); g_free (nmc->required_fields);
nmc_empty_output_fields (nmc); nmc_empty_output_fields (nmc);
g_ptr_array_unref (nmc->output_data); g_ptr_array_unref (nmc->output_data);

View file

@ -112,6 +112,9 @@ typedef struct _NmCli {
const GPtrArray *connections; /* List of connections */ const GPtrArray *connections; /* List of connections */
NMSecretAgent *secret_agent; /* Secret agent */
GHashTable *pwds_hash; /* Hash table with passwords in passwd-file */
gboolean should_wait; /* Indication that nmcli should not end yet */ gboolean should_wait; /* Indication that nmcli should not end yet */
gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */ gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */
NMCPrintOutput print_output; /* Output mode */ NMCPrintOutput print_output; /* Output mode */

View file

@ -18,10 +18,10 @@
*/ */
/** /**
* SECTION:nmt-secret-agent * SECTION:nm-secret-agent-simple
* @short_description: A secret agent * @short_description: A simple secret agent for NetworkManager
* *
* #NmtSecretAgent is the secret agent used by nmtui-connect. * #NMSecretAgentSimple is the secret agent used by nmtui-connect and nmcli.
* *
* This is a stripped-down version of gnome-shell's ShellNetworkAgent, * This is a stripped-down version of gnome-shell's ShellNetworkAgent,
* with bits of the corresponding JavaScript code squished down into * with bits of the corresponding JavaScript code squished down into
@ -34,12 +34,11 @@
#include <string.h> #include <string.h>
#include <glib/gi18n-lib.h> #include <glib/gi18n-lib.h>
#include "nmt-secret-agent.h" #include "nm-secret-agent-simple.h"
#include "nmt-newt.h"
G_DEFINE_TYPE (NmtSecretAgent, nmt_secret_agent, NM_TYPE_SECRET_AGENT) G_DEFINE_TYPE (NMSecretAgentSimple, nm_secret_agent_simple, NM_TYPE_SECRET_AGENT)
#define NMT_SECRET_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_SECRET_AGENT, NmtSecretAgentPrivate)) #define NM_SECRET_AGENT_SIMPLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimplePrivate))
enum { enum {
REQUEST_SECRETS, REQUEST_SECRETS,
@ -50,45 +49,45 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
typedef struct { typedef struct {
NmtSecretAgent *self; NMSecretAgentSimple *self;
gchar *request_id; gchar *request_id;
NMConnection *connection; NMConnection *connection;
gchar **hints; gchar **hints;
NMSecretAgentGetSecretsFunc callback; NMSecretAgentGetSecretsFunc callback;
gpointer callback_data; gpointer callback_data;
} NmtSecretAgentRequest; } NMSecretAgentSimpleRequest;
typedef struct { typedef struct {
/* <char *request_id, NmtSecretAgentRequest *request> */ /* <char *request_id, NMSecretAgentSimpleRequest *request> */
GHashTable *requests; GHashTable *requests;
} NmtSecretAgentPrivate; } NMSecretAgentSimplePrivate;
static void static void
nmt_secret_agent_request_free (gpointer data) nm_secret_agent_simple_request_free (gpointer data)
{ {
NmtSecretAgentRequest *request = data; NMSecretAgentSimpleRequest *request = data;
g_object_unref (request->self); g_object_unref (request->self);
g_object_unref (request->connection); g_object_unref (request->connection);
g_strfreev (request->hints); g_strfreev (request->hints);
g_slice_free (NmtSecretAgentRequest, request); g_slice_free (NMSecretAgentSimpleRequest, request);
} }
static void static void
nmt_secret_agent_init (NmtSecretAgent *agent) nm_secret_agent_simple_init (NMSecretAgentSimple *agent)
{ {
NmtSecretAgentPrivate *priv = NMT_SECRET_AGENT_GET_PRIVATE (agent); NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (agent);
priv->requests = g_hash_table_new_full (g_str_hash, g_str_equal, priv->requests = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, nmt_secret_agent_request_free); g_free, nm_secret_agent_simple_request_free);
} }
static void static void
nmt_secret_agent_finalize (GObject *object) nm_secret_agent_simple_finalize (GObject *object)
{ {
NmtSecretAgentPrivate *priv = NMT_SECRET_AGENT_GET_PRIVATE (object); NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (object);
GError *error; GError *error;
GHashTableIter iter; GHashTableIter iter;
gpointer key; gpointer key;
@ -100,7 +99,7 @@ nmt_secret_agent_finalize (GObject *object)
g_hash_table_iter_init (&iter, priv->requests); g_hash_table_iter_init (&iter, priv->requests);
while (g_hash_table_iter_next (&iter, &key, &value)) { while (g_hash_table_iter_next (&iter, &key, &value)) {
NmtSecretAgentRequest *request = value; NMSecretAgentSimpleRequest *request = value;
request->callback (NM_SECRET_AGENT (object), request->callback (NM_SECRET_AGENT (object),
request->connection, request->connection,
@ -111,7 +110,7 @@ nmt_secret_agent_finalize (GObject *object)
g_hash_table_destroy (priv->requests); g_hash_table_destroy (priv->requests);
g_error_free (error); g_error_free (error);
G_OBJECT_CLASS (nmt_secret_agent_parent_class)->finalize (object); G_OBJECT_CLASS (nm_secret_agent_simple_parent_class)->finalize (object);
} }
static gboolean static gboolean
@ -129,7 +128,7 @@ strv_has (gchar **haystack,
} }
/** /**
* NmtSecretAgentSecret: * NMSecretAgentSimpleSecret:
* @name: the user-visible name of the secret. Eg, "WEP Passphrase". * @name: the user-visible name of the secret. Eg, "WEP Passphrase".
* @value: the value of the secret * @value: the value of the secret
* @password: %TRUE if this secret represents a password, %FALSE * @password: %TRUE if this secret represents a password, %FALSE
@ -139,38 +138,37 @@ strv_has (gchar **haystack,
*/ */
typedef struct { typedef struct {
NmtSecretAgentSecret base; NMSecretAgentSimpleSecret base;
NMSetting *setting; NMSetting *setting;
char *property; char *property;
} NMSecretAgentSimpleSecretReal;
NmtNewtEntryValidator validator;
gpointer validator_data;
} NmtSecretAgentSecretReal;
static void static void
nmt_secret_agent_secret_free (NmtSecretAgentSecret *secret) nm_secret_agent_simple_secret_free (NMSecretAgentSimpleSecret *secret)
{ {
NmtSecretAgentSecretReal *real = (NmtSecretAgentSecretReal *)secret; NMSecretAgentSimpleSecretReal *real = (NMSecretAgentSimpleSecretReal *)secret;
g_free (secret->name); g_free (secret->name);
g_free (secret->prop_name);
g_free (secret->value); g_free (secret->value);
g_free (real->property); g_free (real->property);
g_clear_object (&real->setting); g_clear_object (&real->setting);
g_slice_free (NmtSecretAgentSecretReal, real); g_slice_free (NMSecretAgentSimpleSecretReal, real);
} }
static NmtSecretAgentSecret * static NMSecretAgentSimpleSecret *
nmt_secret_agent_secret_new (const char *name, nm_secret_agent_simple_secret_new (const char *name,
NMSetting *setting, NMSetting *setting,
const char *property, const char *property,
gboolean password) gboolean password)
{ {
NmtSecretAgentSecretReal *real; NMSecretAgentSimpleSecretReal *real;
real = g_slice_new0 (NmtSecretAgentSecretReal); real = g_slice_new0 (NMSecretAgentSimpleSecretReal);
real->base.name = g_strdup (name); real->base.name = g_strdup (name);
real->base.prop_name = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property);
real->base.password = password; real->base.password = password;
if (setting) { if (setting) {
@ -184,12 +182,12 @@ nmt_secret_agent_secret_new (const char *name,
} }
static gboolean static gboolean
add_8021x_secrets (NmtSecretAgentRequest *request, add_8021x_secrets (NMSecretAgentSimpleRequest *request,
GPtrArray *secrets) GPtrArray *secrets)
{ {
NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x (request->connection); NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x (request->connection);
const char *eap_method; const char *eap_method;
NmtSecretAgentSecret *secret; NMSecretAgentSimpleSecret *secret;
eap_method = nm_setting_802_1x_get_eap_method (s_8021x, 0); eap_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
if (!eap_method) if (!eap_method)
@ -203,29 +201,29 @@ add_8021x_secrets (NmtSecretAgentRequest *request,
* is not visible here since we only care about phase2 authentication * is not visible here since we only care about phase2 authentication
* (and don't even care of which one) * (and don't even care of which one)
*/ */
secret = nmt_secret_agent_secret_new (_("Username"), secret = nm_secret_agent_simple_secret_new (_("Username"),
NM_SETTING (s_8021x), NM_SETTING (s_8021x),
NM_SETTING_802_1X_IDENTITY, NM_SETTING_802_1X_IDENTITY,
FALSE); FALSE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
secret = nmt_secret_agent_secret_new (_("Password"), secret = nm_secret_agent_simple_secret_new (_("Password"),
NM_SETTING (s_8021x), NM_SETTING (s_8021x),
NM_SETTING_802_1X_PASSWORD, NM_SETTING_802_1X_PASSWORD,
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
return TRUE; return TRUE;
} }
if (!strcmp (eap_method, "tls")) { if (!strcmp (eap_method, "tls")) {
secret = nmt_secret_agent_secret_new (_("Identity"), secret = nm_secret_agent_simple_secret_new (_("Identity"),
NM_SETTING (s_8021x), NM_SETTING (s_8021x),
NM_SETTING_802_1X_IDENTITY, NM_SETTING_802_1X_IDENTITY,
FALSE); FALSE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
secret = nmt_secret_agent_secret_new (_("Private key password"), secret = nm_secret_agent_simple_secret_new (_("Private key password"),
NM_SETTING (s_8021x), NM_SETTING (s_8021x),
NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
return TRUE; return TRUE;
} }
@ -234,21 +232,21 @@ add_8021x_secrets (NmtSecretAgentRequest *request,
} }
static gboolean static gboolean
add_wireless_secrets (NmtSecretAgentRequest *request, add_wireless_secrets (NMSecretAgentSimpleRequest *request,
GPtrArray *secrets) GPtrArray *secrets)
{ {
NMSettingWirelessSecurity *s_wsec = nm_connection_get_setting_wireless_security (request->connection); NMSettingWirelessSecurity *s_wsec = nm_connection_get_setting_wireless_security (request->connection);
const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
NmtSecretAgentSecret *secret; NMSecretAgentSimpleSecret *secret;
if (!key_mgmt) if (!key_mgmt)
return FALSE; return FALSE;
if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) { if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) {
secret = nmt_secret_agent_secret_new (_("Password"), secret = nm_secret_agent_simple_secret_new (_("Password"),
NM_SETTING (s_wsec), NM_SETTING (s_wsec),
NM_SETTING_WIRELESS_SECURITY_PSK, NM_SETTING_WIRELESS_SECURITY_PSK,
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
return TRUE; return TRUE;
} }
@ -259,26 +257,22 @@ add_wireless_secrets (NmtSecretAgentRequest *request,
index = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec); index = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
key = g_strdup_printf ("wep-key%d", index); key = g_strdup_printf ("wep-key%d", index);
secret = nmt_secret_agent_secret_new (_("Key"), secret = nm_secret_agent_simple_secret_new (_("Key"),
NM_SETTING (s_wsec), NM_SETTING (s_wsec),
key, key,
TRUE); TRUE);
g_free (key); g_free (key);
#if 0
nmt_secret_agent_secret_set_validator (secret, static_wep_key_validate,
nm_setting_wireless_security_get_wep_key_type (s_wsec));
#endif
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
return TRUE; return TRUE;
} }
if (!strcmp (key_mgmt, "iee8021x")) { if (!strcmp (key_mgmt, "iee8021x")) {
if (!g_strcmp0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) { if (!g_strcmp0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) {
secret = nmt_secret_agent_secret_new (_("Password"), secret = nm_secret_agent_simple_secret_new (_("Password"),
NM_SETTING (s_wsec), NM_SETTING (s_wsec),
NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
return TRUE; return TRUE;
} else } else
@ -292,40 +286,40 @@ add_wireless_secrets (NmtSecretAgentRequest *request,
} }
static gboolean static gboolean
add_pppoe_secrets (NmtSecretAgentRequest *request, add_pppoe_secrets (NMSecretAgentSimpleRequest *request,
GPtrArray *secrets) GPtrArray *secrets)
{ {
NMSettingPppoe *s_pppoe = nm_connection_get_setting_pppoe (request->connection); NMSettingPppoe *s_pppoe = nm_connection_get_setting_pppoe (request->connection);
NmtSecretAgentSecret *secret; NMSecretAgentSimpleSecret *secret;
secret = nmt_secret_agent_secret_new (_("Username"), secret = nm_secret_agent_simple_secret_new (_("Username"),
NM_SETTING (s_pppoe), NM_SETTING (s_pppoe),
NM_SETTING_PPPOE_USERNAME, NM_SETTING_PPPOE_USERNAME,
FALSE); FALSE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
secret = nmt_secret_agent_secret_new (_("Service"), secret = nm_secret_agent_simple_secret_new (_("Service"),
NM_SETTING (s_pppoe), NM_SETTING (s_pppoe),
NM_SETTING_PPPOE_SERVICE, NM_SETTING_PPPOE_SERVICE,
FALSE); FALSE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
secret = nmt_secret_agent_secret_new (_("Password"), secret = nm_secret_agent_simple_secret_new (_("Password"),
NM_SETTING (s_pppoe), NM_SETTING (s_pppoe),
NM_SETTING_PPPOE_PASSWORD, NM_SETTING_PPPOE_PASSWORD,
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
return TRUE; return TRUE;
} }
static void static void
request_secrets_from_ui (NmtSecretAgentRequest *request) request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
{ {
GPtrArray *secrets; GPtrArray *secrets;
NmtSecretAgentSecret *secret; NMSecretAgentSimpleSecret *secret;
const char *title; const char *title;
char *msg; char *msg;
gboolean ok = TRUE; gboolean ok = TRUE;
secrets = g_ptr_array_new_with_free_func ((GDestroyNotify) nmt_secret_agent_secret_free); secrets = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_secret_agent_simple_secret_free);
if (nm_connection_is_type (request->connection, NM_SETTING_WIRELESS_SETTING_NAME)) { if (nm_connection_is_type (request->connection, NM_SETTING_WIRELESS_SETTING_NAME)) {
NMSettingWireless *s_wireless; NMSettingWireless *s_wireless;
@ -349,10 +343,10 @@ request_secrets_from_ui (NmtSecretAgentRequest *request)
title = _("Wired 802.1X authentication"); title = _("Wired 802.1X authentication");
msg = NULL; msg = NULL;
secret = nmt_secret_agent_secret_new (_("Network name"), secret = nm_secret_agent_simple_secret_new (_("Network name"),
NM_SETTING (s_con), NM_SETTING (s_con),
NM_SETTING_CONNECTION_ID, NM_SETTING_CONNECTION_ID,
FALSE); FALSE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
ok = add_8021x_secrets (request, secrets); ok = add_8021x_secrets (request, secrets);
} else if (nm_connection_is_type (request->connection, NM_SETTING_PPPOE_SETTING_NAME)) { } else if (nm_connection_is_type (request->connection, NM_SETTING_PPPOE_SETTING_NAME)) {
@ -367,20 +361,20 @@ request_secrets_from_ui (NmtSecretAgentRequest *request)
title = _("PIN code required"); title = _("PIN code required");
msg = g_strdup (_("PIN code is needed for the mobile broadband device")); msg = g_strdup (_("PIN code is needed for the mobile broadband device"));
secret = nmt_secret_agent_secret_new (_("PIN"), secret = nm_secret_agent_simple_secret_new (_("PIN"),
NM_SETTING (s_gsm), NM_SETTING (s_gsm),
NM_SETTING_GSM_PIN, NM_SETTING_GSM_PIN,
FALSE); FALSE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
} else { } else {
title = _("Mobile broadband network password"); title = _("Mobile broadband network password");
msg = g_strdup_printf (_("A password is required to connect to '%s'."), msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection)); nm_connection_get_id (request->connection));
secret = nmt_secret_agent_secret_new (_("Password"), secret = nm_secret_agent_simple_secret_new (_("Password"),
NM_SETTING (s_gsm), NM_SETTING (s_gsm),
NM_SETTING_GSM_PASSWORD, NM_SETTING_GSM_PASSWORD,
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
} }
} else if (nm_connection_is_type (request->connection, NM_SETTING_CDMA_SETTING_NAME)) { } else if (nm_connection_is_type (request->connection, NM_SETTING_CDMA_SETTING_NAME)) {
@ -390,10 +384,10 @@ request_secrets_from_ui (NmtSecretAgentRequest *request)
msg = g_strdup_printf (_("A password is required to connect to '%s'."), msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection)); nm_connection_get_id (request->connection));
secret = nmt_secret_agent_secret_new (_("Password"), secret = nm_secret_agent_simple_secret_new (_("Password"),
NM_SETTING (s_cdma), NM_SETTING (s_cdma),
NM_SETTING_CDMA_PASSWORD, NM_SETTING_CDMA_PASSWORD,
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
} else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) { } else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
NMSetting *setting; NMSetting *setting;
@ -406,10 +400,10 @@ request_secrets_from_ui (NmtSecretAgentRequest *request)
msg = g_strdup_printf (_("A password is required to connect to '%s'."), msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection)); nm_connection_get_id (request->connection));
secret = nmt_secret_agent_secret_new (_("Password"), secret = nm_secret_agent_simple_secret_new (_("Password"),
setting, setting,
"password", "password",
TRUE); TRUE);
g_ptr_array_add (secrets, secret); g_ptr_array_add (secrets, secret);
} else } else
ok = FALSE; ok = FALSE;
@ -424,18 +418,18 @@ request_secrets_from_ui (NmtSecretAgentRequest *request)
} }
static void static void
nmt_secret_agent_get_secrets (NMSecretAgent *agent, nm_secret_agent_simple_get_secrets (NMSecretAgent *agent,
NMConnection *connection, NMConnection *connection,
const gchar *connection_path, const gchar *connection_path,
const gchar *setting_name, const gchar *setting_name,
const gchar **hints, const gchar **hints,
NMSecretAgentGetSecretsFlags flags, NMSecretAgentGetSecretsFlags flags,
NMSecretAgentGetSecretsFunc callback, NMSecretAgentGetSecretsFunc callback,
gpointer callback_data) gpointer callback_data)
{ {
NmtSecretAgent *self = NMT_SECRET_AGENT (agent); NMSecretAgentSimple *self = NM_SECRET_AGENT_SIMPLE (agent);
NmtSecretAgentPrivate *priv = NMT_SECRET_AGENT_GET_PRIVATE (self); NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self);
NmtSecretAgentRequest *request; NMSecretAgentSimpleRequest *request;
NMSettingConnection *s_con; NMSettingConnection *s_con;
const char *connection_type; const char *connection_type;
char *request_id; char *request_id;
@ -470,7 +464,7 @@ nmt_secret_agent_get_secrets (NMSecretAgent *agent,
goto nope; goto nope;
} }
request = g_slice_new (NmtSecretAgentRequest); request = g_slice_new (NMSecretAgentSimpleRequest);
request->self = g_object_ref (self); request->self = g_object_ref (self);
request->connection = g_object_ref (connection); request->connection = g_object_ref (connection);
request->hints = g_strdupv ((gchar **)hints); request->hints = g_strdupv ((gchar **)hints);
@ -483,33 +477,33 @@ nmt_secret_agent_get_secrets (NMSecretAgent *agent,
} }
/** /**
* nmt_secret_agent_response: * nm_secret_agent_simple_response:
* @self: the #NmtSecretAgent * @self: the #NMSecretAgentSimple
* @request_id: the request ID being responded to * @request_id: the request ID being responded to
* @secrets: (allow-none): the array of secrets, or %NULL * @secrets: (allow-none): the array of secrets, or %NULL
* *
* Response to a #NmtSecretAgent::get-secrets signal. * Response to a #NMSecretAgentSimple::get-secrets signal.
* *
* If the user provided secrets, the caller should set the * If the user provided secrets, the caller should set the
* corresponding <literal>value</literal> fields in the * corresponding <literal>value</literal> fields in the
* #NmtSecretAgentSecrets (freeing any initial values they had), and * #NMSecretAgentSimpleSecrets (freeing any initial values they had), and
* pass the array to nmt_secret_agent_response(). If the user * pass the array to nm_secret_agent_simple_response(). If the user
* cancelled the request, @secrets should be NULL. * cancelled the request, @secrets should be NULL.
*/ */
void void
nmt_secret_agent_response (NmtSecretAgent *self, nm_secret_agent_simple_response (NMSecretAgentSimple *self,
const char *request_id, const char *request_id,
GPtrArray *secrets) GPtrArray *secrets)
{ {
NmtSecretAgentPrivate *priv; NMSecretAgentSimplePrivate *priv;
NmtSecretAgentRequest *request; NMSecretAgentSimpleRequest *request;
GVariant *dict = NULL; GVariant *dict = NULL;
GError *error = NULL; GError *error = NULL;
int i; int i;
g_return_if_fail (NMT_IS_SECRET_AGENT (self)); g_return_if_fail (NM_IS_SECRET_AGENT_SIMPLE (self));
priv = NMT_SECRET_AGENT_GET_PRIVATE (self); priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self);
request = g_hash_table_lookup (priv->requests, request_id); request = g_hash_table_lookup (priv->requests, request_id);
g_return_if_fail (request != NULL); g_return_if_fail (request != NULL);
@ -521,7 +515,7 @@ nmt_secret_agent_response (NmtSecretAgent *self,
settings = g_hash_table_new (g_str_hash, g_str_equal); settings = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; i < secrets->len; i++) { for (i = 0; i < secrets->len; i++) {
NmtSecretAgentSecretReal *secret = secrets->pdata[i]; NMSecretAgentSimpleSecretReal *secret = secrets->pdata[i];
setting_builder = g_hash_table_lookup (settings, nm_setting_get_name (secret->setting)); setting_builder = g_hash_table_lookup (settings, nm_setting_get_name (secret->setting));
if (!setting_builder) { if (!setting_builder) {
@ -553,69 +547,71 @@ nmt_secret_agent_response (NmtSecretAgent *self,
} }
static void static void
nmt_secret_agent_cancel_get_secrets (NMSecretAgent *agent, nm_secret_agent_simple_cancel_get_secrets (NMSecretAgent *agent,
const gchar *connection_path, const gchar *connection_path,
const gchar *setting_name) const gchar *setting_name)
{ {
/* We don't support cancellation. Sorry! */ /* We don't support cancellation. Sorry! */
} }
static void static void
nmt_secret_agent_save_secrets (NMSecretAgent *agent, nm_secret_agent_simple_save_secrets (NMSecretAgent *agent,
NMConnection *connection, NMConnection *connection,
const gchar *connection_path, const gchar *connection_path,
NMSecretAgentSaveSecretsFunc callback, NMSecretAgentSaveSecretsFunc callback,
gpointer callback_data) gpointer callback_data)
{ {
/* We don't support secret storage */ /* We don't support secret storage */
callback (agent, connection, NULL, callback_data);} callback (agent, connection, NULL, callback_data);
}
static void static void
nmt_secret_agent_delete_secrets (NMSecretAgent *agent, nm_secret_agent_simple_delete_secrets (NMSecretAgent *agent,
NMConnection *connection, NMConnection *connection,
const gchar *connection_path, const gchar *connection_path,
NMSecretAgentDeleteSecretsFunc callback, NMSecretAgentDeleteSecretsFunc callback,
gpointer callback_data) gpointer callback_data)
{ {
/* We don't support secret storage, so there's nothing to delete. */ /* We don't support secret storage, so there's nothing to delete. */
callback (agent, connection, NULL, callback_data); callback (agent, connection, NULL, callback_data);
} }
void void
nmt_secret_agent_class_init (NmtSecretAgentClass *klass) nm_secret_agent_simple_class_init (NMSecretAgentSimpleClass *klass)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
NMSecretAgentClass *agent_class = NM_SECRET_AGENT_CLASS (klass); NMSecretAgentClass *agent_class = NM_SECRET_AGENT_CLASS (klass);
g_type_class_add_private (klass, sizeof (NmtSecretAgentPrivate)); g_type_class_add_private (klass, sizeof (NMSecretAgentSimplePrivate));
gobject_class->finalize = nmt_secret_agent_finalize; gobject_class->finalize = nm_secret_agent_simple_finalize;
agent_class->get_secrets = nmt_secret_agent_get_secrets; agent_class->get_secrets = nm_secret_agent_simple_get_secrets;
agent_class->cancel_get_secrets = nmt_secret_agent_cancel_get_secrets; agent_class->cancel_get_secrets = nm_secret_agent_simple_cancel_get_secrets;
agent_class->save_secrets = nmt_secret_agent_save_secrets; agent_class->save_secrets = nm_secret_agent_simple_save_secrets;
agent_class->delete_secrets = nmt_secret_agent_delete_secrets; agent_class->delete_secrets = nm_secret_agent_simple_delete_secrets;
/** /**
* NmtSecretAgent::request-secrets: * NMSecretAgentSimple::request-secrets:
* @agent: the #NmtSecretAgent * @agent: the #NMSecretAgentSimple
* @request_id: request ID, to eventually pass to * @request_id: request ID, to eventually pass to
* nmt_secret_agent_response(). * nm_secret_agent_simple_response().
* @title: a title for the password dialog * @title: a title for the password dialog
* @prompt: a prompt message for the password dialog * @prompt: a prompt message for the password dialog
* @secrets: (element-type #NmtSecretAgentSecret): array of secrets * @secrets: (element-type #NMSecretAgentSimpleSecret): array of secrets
* being requested. * being requested.
* *
* Emitted when the agent requires secrets from the user. * Emitted when the agent requires secrets from the user.
* *
* The application should create a password dialog (eg, * The application should ask user for the secrets. For example,
* #NmtPasswordDialog) with the given title and prompt, and an * nmtui should create a password dialog (#NmtPasswordDialog)
* entry for each element of @secrets. If any of the secrets * with the given title and prompt, and an entry for each
* already have a <literal>value</literal> filled in, the * element of @secrets. If any of the secrets already have a
* corresponding entry should be initialized to that value. * <literal>value</literal> filled in, the corresponding entry
* should be initialized to that value.
* *
* When the dialog is complete, the app must call * When the dialog is complete, the app must call
* nmt_secret_agent_response() with the results. * nm_secret_agent_simple_response() with the results.
*/ */
signals[REQUEST_SECRETS] = g_signal_new ("request-secrets", signals[REQUEST_SECRETS] = g_signal_new ("request-secrets",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
@ -629,16 +625,17 @@ nmt_secret_agent_class_init (NmtSecretAgentClass *klass)
} }
/** /**
* nmt_secret_agent_new: * nm_secret_agent_simple_new:
* @name: the identifier of secret agent
* *
* Creates a new #NmtSecretAgent. * Creates a new #NMSecretAgentSimple.
* *
* Returns: a new #NmtSecretAgent * Returns: a new #NMSecretAgentSimple
*/ */
NMSecretAgent * NMSecretAgent *
nmt_secret_agent_new (void) nm_secret_agent_simple_new (const char *name)
{ {
return g_initable_new (NMT_TYPE_SECRET_AGENT, NULL, NULL, return g_initable_new (NM_TYPE_SECRET_AGENT_SIMPLE, NULL, NULL,
NM_SECRET_AGENT_IDENTIFIER, "nmtui", NM_SECRET_AGENT_IDENTIFIER, name,
NULL); NULL);
} }

View file

@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2013 - 2014 Red Hat, Inc.
*/
#ifndef __NM_SECRET_AGENT_SIMPLE_H__
#define __NM_SECRET_AGENT_SIMPLE_H__
#include <NetworkManager.h>
G_BEGIN_DECLS
#define NM_TYPE_SECRET_AGENT_SIMPLE (nm_secret_agent_simple_get_type ())
#define NM_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgentSimple))
#define NM_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SECRET_AGENT, NMSecretAgentSimpleClass))
#define NM_IS_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SECRET_AGENT))
#define NM_IS_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT))
#define NM_SECRET_AGENT_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgentSimpleClass))
typedef struct {
NMSecretAgent parent;
} NMSecretAgentSimple;
typedef struct {
NMSecretAgentClass parent;
} NMSecretAgentSimpleClass;
typedef struct {
char *name, *prop_name, *value;
gboolean password;
} NMSecretAgentSimpleSecret;
GType nm_secret_agent_simple_get_type (void);
NMSecretAgent *nm_secret_agent_simple_new (const char *name);
void nm_secret_agent_simple_response (NMSecretAgentSimple *self,
const char *request_id,
GPtrArray *secrets);
G_END_DECLS
#endif /* __NM_SECRET_AGENT_SIMPLE_H__ */

View file

@ -10,6 +10,7 @@ AM_CPPFLAGS= \
-I$(top_srcdir)/libnm \ -I$(top_srcdir)/libnm \
-I$(top_builddir)/libnm \ -I$(top_builddir)/libnm \
-I$(srcdir)/newt \ -I$(srcdir)/newt \
-I$(top_srcdir)/clients/common \
$(GLIB_CFLAGS) \ $(GLIB_CFLAGS) \
$(NEWT_CFLAGS) \ $(NEWT_CFLAGS) \
$(GUDEV_CFLAGS) \ $(GUDEV_CFLAGS) \
@ -106,14 +107,14 @@ nmtui_SOURCES = \
nmt-route-entry.h \ nmt-route-entry.h \
nmt-route-table.c \ nmt-route-table.c \
nmt-route-table.h \ nmt-route-table.h \
nmt-secret-agent.c \
nmt-secret-agent.h \
nmt-slave-list.c \ nmt-slave-list.c \
nmt-slave-list.h \ nmt-slave-list.h \
nmt-utils.c \ nmt-utils.c \
nmt-utils.h \ nmt-utils.h \
nmt-widget-list.c \ nmt-widget-list.c \
nmt-widget-list.h \ nmt-widget-list.h \
$(srcdir)/../common/nm-secret-agent-simple.c \
$(srcdir)/../common/nm-secret-agent-simple.h \
$(NULL) $(NULL)
nmtui_LDADD = \ nmtui_LDADD = \

View file

@ -29,7 +29,7 @@
#include <glib/gi18n-lib.h> #include <glib/gi18n-lib.h>
#include "nmt-password-dialog.h" #include "nmt-password-dialog.h"
#include "nmt-secret-agent.h" #include "nm-secret-agent-simple.h"
#include "nmtui.h" #include "nmtui.h"
G_DEFINE_TYPE (NmtPasswordDialog, nmt_password_dialog, NMT_TYPE_NEWT_FORM) G_DEFINE_TYPE (NmtPasswordDialog, nmt_password_dialog, NMT_TYPE_NEWT_FORM)
@ -60,10 +60,10 @@ enum {
/** /**
* nmt_password_dialog_new: * nmt_password_dialog_new:
* @request_id: the request ID from the #NmtSecretAgent * @request_id: the request ID from the #NMSecretAgentSimple
* @title: the dialog title * @title: the dialog title
* @prompt: the prompt text to display * @prompt: the prompt text to display
* @secrets: (element-type #NmtSecretAgentSecret): the secrets requested * @secrets: (element-type #NMSecretAgentSimpleSecret): the secrets requested
* *
* Creates a new #NmtPasswordDialog to request passwords from * Creates a new #NmtPasswordDialog to request passwords from
* the user. * the user.
@ -109,7 +109,7 @@ maybe_save_input_and_exit (NmtNewtWidget *widget,
priv->succeeded = TRUE; priv->succeeded = TRUE;
for (i = 0; i < priv->secrets->len; i++) { for (i = 0; i < priv->secrets->len; i++) {
NmtSecretAgentSecret *secret = priv->secrets->pdata[i]; NMSecretAgentSimpleSecret *secret = priv->secrets->pdata[i];
g_free (secret->value); g_free (secret->value);
g_object_get (priv->entries->pdata[i], "text", &secret->value, NULL); g_object_get (priv->entries->pdata[i], "text", &secret->value, NULL);
@ -143,7 +143,7 @@ nmt_password_dialog_constructed (GObject *object)
secret_grid = NMT_NEWT_GRID (widget); secret_grid = NMT_NEWT_GRID (widget);
for (i = 0; i < priv->secrets->len; i++) { for (i = 0; i < priv->secrets->len; i++) {
NmtSecretAgentSecret *secret = priv->secrets->pdata[i]; NMSecretAgentSimpleSecret *secret = priv->secrets->pdata[i];
NmtNewtEntryFlags flags; NmtNewtEntryFlags flags;
widget = nmt_newt_label_new (secret->name); widget = nmt_newt_label_new (secret->name);
@ -258,7 +258,7 @@ nmt_password_dialog_class_init (NmtPasswordDialogClass *dialog_class)
/** /**
* NmtPasswordDialog:request-id: * NmtPasswordDialog:request-id:
* *
* The request ID from the #NmtSecretAgent * The request ID from the #NMSecretAgentSimple
*/ */
g_object_class_install_property g_object_class_install_property
(object_class, PROP_REQUEST_ID, (object_class, PROP_REQUEST_ID,
@ -284,7 +284,7 @@ nmt_password_dialog_class_init (NmtPasswordDialogClass *dialog_class)
* *
* The array of request secrets * The array of request secrets
* *
* Element-Type: #NmtSecretAgentSecret. * Element-Type: #NMSecretAgentSimpleSecret.
*/ */
g_object_class_install_property g_object_class_install_property
(object_class, PROP_SECRETS, (object_class, PROP_SECRETS,

View file

@ -1,57 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2013 Red Hat, Inc.
*/
#ifndef NMT_SECRET_AGENT_H
#define NMT_SECRET_AGENT_H
#include <NetworkManager.h>
G_BEGIN_DECLS
#define NMT_TYPE_SECRET_AGENT (nmt_secret_agent_get_type ())
#define NMT_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_SECRET_AGENT, NmtSecretAgent))
#define NMT_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_SECRET_AGENT, NmtSecretAgentClass))
#define NMT_IS_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_SECRET_AGENT))
#define NMT_IS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_SECRET_AGENT))
#define NMT_SECRET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_SECRET_AGENT, NmtSecretAgentClass))
typedef struct {
NMSecretAgent parent;
} NmtSecretAgent;
typedef struct {
NMSecretAgentClass parent;
} NmtSecretAgentClass;
typedef struct {
char *name, *value;
gboolean password;
} NmtSecretAgentSecret;
GType nmt_secret_agent_get_type (void);
NMSecretAgent *nmt_secret_agent_new (void);
void nmt_secret_agent_response (NmtSecretAgent *self,
const char *request_id,
GPtrArray *secrets);
G_END_DECLS
#endif /* NMT_SECRET_AGENT_H */

View file

@ -36,16 +36,16 @@
#include "nmtui-connect.h" #include "nmtui-connect.h"
#include "nmt-connect-connection-list.h" #include "nmt-connect-connection-list.h"
#include "nmt-password-dialog.h" #include "nmt-password-dialog.h"
#include "nmt-secret-agent.h" #include "nm-secret-agent-simple.h"
#include "nmt-utils.h" #include "nmt-utils.h"
static void static void
secrets_requested (NmtSecretAgent *agent, secrets_requested (NMSecretAgentSimple *agent,
const char *request_id, const char *request_id,
const char *title, const char *title,
const char *msg, const char *msg,
GPtrArray *secrets, GPtrArray *secrets,
gpointer user_data) gpointer user_data)
{ {
NmtNewtForm *form; NmtNewtForm *form;
@ -53,9 +53,9 @@ secrets_requested (NmtSecretAgent *agent,
nmt_newt_form_run_sync (form); nmt_newt_form_run_sync (form);
if (nmt_password_dialog_succeeded (NMT_PASSWORD_DIALOG (form))) if (nmt_password_dialog_succeeded (NMT_PASSWORD_DIALOG (form)))
nmt_secret_agent_response (agent, request_id, secrets); nm_secret_agent_simple_response (agent, request_id, secrets);
else else
nmt_secret_agent_response (agent, request_id, NULL); nm_secret_agent_simple_response (agent, request_id, NULL);
g_object_unref (form); g_object_unref (form);
} }
@ -145,7 +145,7 @@ activate_connection (NMConnection *connection,
label = nmt_newt_label_new (_("Connecting...")); label = nmt_newt_label_new (_("Connecting..."));
nmt_newt_form_set_content (form, label); nmt_newt_form_set_content (form, label);
agent = nmt_secret_agent_new (); agent = nm_secret_agent_simple_new ("nmtui");
g_signal_connect (agent, "request-secrets", G_CALLBACK (secrets_requested), NULL); g_signal_connect (agent, "request-secrets", G_CALLBACK (secrets_requested), NULL);
specific_object_path = specific_object ? nm_object_get_path (specific_object) : NULL; specific_object_path = specific_object ? nm_object_get_path (specific_object) : NULL;

View file

@ -131,6 +131,8 @@ incompatible versions may produce incorrect results.
.B \-a, \-\-ask .B \-a, \-\-ask
When using this option \fInmcli\fP will stop and ask for any missing required When using this option \fInmcli\fP will stop and ask for any missing required
arguments, so do not use this option for non-interactive purposes like scripts. arguments, so do not use this option for non-interactive purposes like scripts.
This option controls, for example, whether you will be prompted for a password
if it is required for connecting to a network.
.TP .TP
.B \-w, \-\-wait <seconds> .B \-w, \-\-wait <seconds>
This option sets a timeout period for which \fInmcli\fP will wait for \fINetworkManager\fP This option sets a timeout period for which \fInmcli\fP will wait for \fINetworkManager\fP
@ -327,10 +329,10 @@ When no command is given to the \fIconnection\fP object, the default action
is 'nmcli connection show'. is 'nmcli connection show'.
.RE .RE
.TP .TP
.B up [ id | uuid | path ] <ID> [ifname <ifname>] [ap <BSSID>] [nsp <name>] .B up [ id | uuid | path ] <ID> [ifname <ifname>] [ap <BSSID>] [nsp <name>] [passwd <file with passwords>]
.RE .RE
.RS .RS
.B up ifname <ifname> [ap <BSSID>] [nsp <name>] .B up ifname <ifname> [ap <BSSID>] [nsp <name>] [passwd <file with passwords>]
.RS .RS
.br .br
Activate a connection. The connection is identified by its name, UUID or D-Bus Activate a connection. The connection is identified by its name, UUID or D-Bus
@ -355,6 +357,26 @@ Available options are:
\(en BSSID of the AP which the command should connect to (for Wi\(hyFi connections) \(en BSSID of the AP which the command should connect to (for Wi\(hyFi connections)
.IP \fInsp\fP 13 .IP \fInsp\fP 13
\(en NSP (Network Service Provider) which the command should connect to (for WiMAX connections) \(en NSP (Network Service Provider) which the command should connect to (for WiMAX connections)
.IP \fIpasswd-file\fP 13
\(en some networks may require credentials during activation. You can give these
credentials using this option.
Each line of the file should contain one password in the form of
.br
\fBsetting_name.property_name:the password\fP
.br
For example, for WPA Wi-Fi with PSK, the line would be
.br
\fI802-11-wireless-security.psk:secret12345\fP
.br
For 802.1X password, the line would be
.br
\fI802-1x.password:my 1X password\fP
.br
nmcli also accepts "wifi-sec" and "wifi" strings instead of "802-11-wireless-security".
When NetworkManager requires a password and it is not given, nmcli will ask for it
when run with --ask. If --ask was not passed, NetworkManager can ask another secret
agent that may be running (typically a GUI secret agent, such as nm-applet or
gnome-shell).
.RE .RE
.RE .RE
.TP .TP

View file

@ -8,6 +8,7 @@ clients/cli/general.c
clients/cli/nmcli.c clients/cli/nmcli.c
clients/cli/settings.c clients/cli/settings.c
clients/cli/utils.c clients/cli/utils.c
clients/common/nm-secret-agent-simple.c
clients/nm-online.c clients/nm-online.c
clients/tui/newt/nmt-newt-utils.c clients/tui/newt/nmt-newt-utils.c
clients/tui/nm-editor-utils.c clients/tui/nm-editor-utils.c
@ -34,7 +35,6 @@ clients/tui/nmt-password-dialog.c
clients/tui/nmt-password-fields.c clients/tui/nmt-password-fields.c
clients/tui/nmt-route-editor.c clients/tui/nmt-route-editor.c
clients/tui/nmt-route-table.c clients/tui/nmt-route-table.c
clients/tui/nmt-secret-agent.c
clients/tui/nmt-slave-list.c clients/tui/nmt-slave-list.c
clients/tui/nmt-widget-list.c clients/tui/nmt-widget-list.c
clients/tui/nmtui-connect.c clients/tui/nmtui-connect.c