2013-12-02 16:20:26 -05:00
|
|
|
/* -*- 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 2011-2013 Red Hat, Inc.
|
|
|
|
|
* Copyright 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-14 12:37:00 +02:00
|
|
|
* SECTION:nm-secret-agent-simple
|
|
|
|
|
* @short_description: A simple secret agent for NetworkManager
|
2013-12-02 16:20:26 -05:00
|
|
|
*
|
2014-10-14 12:37:00 +02:00
|
|
|
* #NMSecretAgentSimple is the secret agent used by nmtui-connect and nmcli.
|
2013-12-02 16:20:26 -05:00
|
|
|
*
|
|
|
|
|
* This is a stripped-down version of gnome-shell's ShellNetworkAgent,
|
|
|
|
|
* with bits of the corresponding JavaScript code squished down into
|
|
|
|
|
* it. It is intended to eventually be generic enough that it could
|
|
|
|
|
* replace ShellNetworkAgent.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <glib/gi18n-lib.h>
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
#include "nm-secret-agent-simple.h"
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
G_DEFINE_TYPE (NMSecretAgentSimple, nm_secret_agent_simple, NM_TYPE_SECRET_AGENT)
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
#define NM_SECRET_AGENT_SIMPLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimplePrivate))
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
REQUEST_SECRETS,
|
|
|
|
|
|
|
|
|
|
LAST_SIGNAL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimple *self;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
gchar *request_id;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gchar **hints;
|
|
|
|
|
NMSecretAgentGetSecretsFunc callback;
|
|
|
|
|
gpointer callback_data;
|
2014-10-14 12:37:00 +02:00
|
|
|
} NMSecretAgentSimpleRequest;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
typedef struct {
|
2014-10-14 12:37:00 +02:00
|
|
|
/* <char *request_id, NMSecretAgentSimpleRequest *request> */
|
2013-12-02 16:20:26 -05:00
|
|
|
GHashTable *requests;
|
2014-11-11 13:15:19 +01:00
|
|
|
|
|
|
|
|
char *path;
|
2014-11-13 20:22:04 +01:00
|
|
|
gboolean enabled;
|
2014-10-14 12:37:00 +02:00
|
|
|
} NMSecretAgentSimplePrivate;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_request_free (gpointer data)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleRequest *request = data;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
g_object_unref (request->self);
|
|
|
|
|
g_object_unref (request->connection);
|
|
|
|
|
g_strfreev (request->hints);
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
g_slice_free (NMSecretAgentSimpleRequest, request);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_init (NMSecretAgentSimple *agent)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (agent);
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
priv->requests = g_hash_table_new_full (g_str_hash, g_str_equal,
|
2014-10-14 12:37:00 +02:00
|
|
|
g_free, nm_secret_agent_simple_request_free);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_finalize (GObject *object)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (object);
|
2013-12-02 16:20:26 -05:00
|
|
|
GError *error;
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
gpointer key;
|
|
|
|
|
gpointer value;
|
|
|
|
|
|
|
|
|
|
error = g_error_new (NM_SECRET_AGENT_ERROR,
|
|
|
|
|
NM_SECRET_AGENT_ERROR_AGENT_CANCELED,
|
|
|
|
|
"The secret agent is going away");
|
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, priv->requests);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleRequest *request = value;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
request->callback (NM_SECRET_AGENT (object),
|
|
|
|
|
request->connection,
|
|
|
|
|
NULL, error,
|
|
|
|
|
request->callback_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_hash_table_destroy (priv->requests);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
|
2014-11-11 13:15:19 +01:00
|
|
|
g_free (priv->path);
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
G_OBJECT_CLASS (nm_secret_agent_simple_parent_class)->finalize (object);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
strv_has (gchar **haystack,
|
|
|
|
|
gchar *needle)
|
|
|
|
|
{
|
|
|
|
|
gchar *iter;
|
|
|
|
|
|
|
|
|
|
for (iter = *haystack; iter; iter++) {
|
|
|
|
|
if (g_strcmp0 (iter, needle) == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-14 12:37:00 +02:00
|
|
|
* NMSecretAgentSimpleSecret:
|
2013-12-02 16:20:26 -05:00
|
|
|
* @name: the user-visible name of the secret. Eg, "WEP Passphrase".
|
|
|
|
|
* @value: the value of the secret
|
|
|
|
|
* @password: %TRUE if this secret represents a password, %FALSE
|
|
|
|
|
* if it represents non-secret data.
|
|
|
|
|
*
|
|
|
|
|
* A single "secret" being requested.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecret base;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
char *property;
|
2014-10-14 12:37:00 +02:00
|
|
|
} NMSecretAgentSimpleSecretReal;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_secret_free (NMSecretAgentSimpleSecret *secret)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecretReal *real = (NMSecretAgentSimpleSecretReal *)secret;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
g_free (secret->name);
|
2014-11-03 09:53:50 +01:00
|
|
|
g_free (secret->prop_name);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_free (secret->value);
|
|
|
|
|
g_free (real->property);
|
|
|
|
|
g_clear_object (&real->setting);
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
g_slice_free (NMSecretAgentSimpleSecretReal, real);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
static NMSecretAgentSimpleSecret *
|
|
|
|
|
nm_secret_agent_simple_secret_new (const char *name,
|
|
|
|
|
NMSetting *setting,
|
|
|
|
|
const char *property,
|
|
|
|
|
gboolean password)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecretReal *real;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
real = g_slice_new0 (NMSecretAgentSimpleSecretReal);
|
2013-12-02 16:20:26 -05:00
|
|
|
real->base.name = g_strdup (name);
|
2014-11-03 09:53:50 +01:00
|
|
|
real->base.prop_name = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property);
|
2013-12-02 16:20:26 -05:00
|
|
|
real->base.password = password;
|
|
|
|
|
|
|
|
|
|
if (setting) {
|
|
|
|
|
real->setting = g_object_ref (setting);
|
|
|
|
|
real->property = g_strdup (property);
|
|
|
|
|
|
|
|
|
|
g_object_get (setting, property, &real->base.value, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &real->base;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2014-10-14 12:37:00 +02:00
|
|
|
add_8021x_secrets (NMSecretAgentSimpleRequest *request,
|
|
|
|
|
GPtrArray *secrets)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
|
|
|
|
NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x (request->connection);
|
|
|
|
|
const char *eap_method;
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecret *secret;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
eap_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
|
|
|
|
|
if (!eap_method)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if ( !strcmp (eap_method, "md5")
|
|
|
|
|
|| !strcmp (eap_method, "leap")
|
|
|
|
|
|| !strcmp (eap_method, "ttls")
|
|
|
|
|
|| !strcmp (eap_method, "peap")) {
|
|
|
|
|
/* TTLS and PEAP are actually much more complicated, but this complication
|
|
|
|
|
* is not visible here since we only care about phase2 authentication
|
|
|
|
|
* (and don't even care of which one)
|
|
|
|
|
*/
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Username"),
|
|
|
|
|
NM_SETTING (s_8021x),
|
|
|
|
|
NM_SETTING_802_1X_IDENTITY,
|
|
|
|
|
FALSE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Password"),
|
|
|
|
|
NM_SETTING (s_8021x),
|
|
|
|
|
NM_SETTING_802_1X_PASSWORD,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp (eap_method, "tls")) {
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Identity"),
|
|
|
|
|
NM_SETTING (s_8021x),
|
|
|
|
|
NM_SETTING_802_1X_IDENTITY,
|
|
|
|
|
FALSE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Private key password"),
|
|
|
|
|
NM_SETTING (s_8021x),
|
|
|
|
|
NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2014-10-14 12:37:00 +02:00
|
|
|
add_wireless_secrets (NMSecretAgentSimpleRequest *request,
|
|
|
|
|
GPtrArray *secrets)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec = nm_connection_get_setting_wireless_security (request->connection);
|
|
|
|
|
const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecret *secret;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
if (!key_mgmt)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) {
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Password"),
|
|
|
|
|
NM_SETTING (s_wsec),
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_PSK,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp (key_mgmt, "none")) {
|
|
|
|
|
int index;
|
|
|
|
|
char *key;
|
|
|
|
|
|
|
|
|
|
index = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
|
|
|
|
|
key = g_strdup_printf ("wep-key%d", index);
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Key"),
|
|
|
|
|
NM_SETTING (s_wsec),
|
|
|
|
|
key,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_free (key);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp (key_mgmt, "iee8021x")) {
|
|
|
|
|
if (!g_strcmp0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) {
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Password"),
|
|
|
|
|
NM_SETTING (s_wsec),
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
return TRUE;
|
|
|
|
|
} else
|
|
|
|
|
return add_8021x_secrets (request, secrets);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp (key_mgmt, "wpa-eap"))
|
|
|
|
|
return add_8021x_secrets (request, secrets);
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2014-10-14 12:37:00 +02:00
|
|
|
add_pppoe_secrets (NMSecretAgentSimpleRequest *request,
|
|
|
|
|
GPtrArray *secrets)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMSettingPppoe *s_pppoe = nm_connection_get_setting_pppoe (request->connection);
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecret *secret;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Username"),
|
|
|
|
|
NM_SETTING (s_pppoe),
|
|
|
|
|
NM_SETTING_PPPOE_USERNAME,
|
|
|
|
|
FALSE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Service"),
|
|
|
|
|
NM_SETTING (s_pppoe),
|
|
|
|
|
NM_SETTING_PPPOE_SERVICE,
|
|
|
|
|
FALSE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Password"),
|
|
|
|
|
NM_SETTING (s_pppoe),
|
|
|
|
|
NM_SETTING_PPPOE_PASSWORD,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
|
|
|
|
GPtrArray *secrets;
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecret *secret;
|
2013-12-02 16:20:26 -05:00
|
|
|
const char *title;
|
|
|
|
|
char *msg;
|
|
|
|
|
gboolean ok = TRUE;
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
secrets = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_secret_agent_simple_secret_free);
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
if (nm_connection_is_type (request->connection, NM_SETTING_WIRELESS_SETTING_NAME)) {
|
|
|
|
|
NMSettingWireless *s_wireless;
|
2014-06-26 10:42:11 -04:00
|
|
|
GBytes *ssid;
|
2014-06-26 09:25:06 -04:00
|
|
|
char *ssid_utf8;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
s_wireless = nm_connection_get_setting_wireless (request->connection);
|
2014-06-26 09:25:06 -04:00
|
|
|
ssid = nm_setting_wireless_get_ssid (s_wireless);
|
2014-06-26 10:42:11 -04:00
|
|
|
ssid_utf8 = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
|
|
|
|
|
g_bytes_get_size (ssid));
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
title = _("Authentication required by wireless network");
|
2014-06-26 09:25:06 -04:00
|
|
|
msg = g_strdup_printf (_("Passwords or encryption keys are required to access the wireless network '%s'."), ssid_utf8);
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
ok = add_wireless_secrets (request, secrets);
|
|
|
|
|
} else if (nm_connection_is_type (request->connection, NM_SETTING_WIRED_SETTING_NAME)) {
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (request->connection);
|
|
|
|
|
|
|
|
|
|
title = _("Wired 802.1X authentication");
|
|
|
|
|
msg = NULL;
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Network name"),
|
|
|
|
|
NM_SETTING (s_con),
|
|
|
|
|
NM_SETTING_CONNECTION_ID,
|
|
|
|
|
FALSE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
ok = add_8021x_secrets (request, secrets);
|
|
|
|
|
} else if (nm_connection_is_type (request->connection, NM_SETTING_PPPOE_SETTING_NAME)) {
|
|
|
|
|
title = _("DSL authentication");
|
|
|
|
|
msg = NULL;
|
|
|
|
|
|
|
|
|
|
ok = add_pppoe_secrets (request, secrets);
|
|
|
|
|
} else if (nm_connection_is_type (request->connection, NM_SETTING_GSM_SETTING_NAME)) {
|
|
|
|
|
NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (request->connection);
|
|
|
|
|
|
|
|
|
|
if (strv_has (request->hints, "pin")) {
|
|
|
|
|
title = _("PIN code required");
|
|
|
|
|
msg = g_strdup (_("PIN code is needed for the mobile broadband device"));
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("PIN"),
|
|
|
|
|
NM_SETTING (s_gsm),
|
|
|
|
|
NM_SETTING_GSM_PIN,
|
|
|
|
|
FALSE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
} else {
|
|
|
|
|
title = _("Mobile broadband network password");
|
|
|
|
|
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
|
|
|
|
|
nm_connection_get_id (request->connection));
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Password"),
|
|
|
|
|
NM_SETTING (s_gsm),
|
|
|
|
|
NM_SETTING_GSM_PASSWORD,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
}
|
|
|
|
|
} else if (nm_connection_is_type (request->connection, NM_SETTING_CDMA_SETTING_NAME)) {
|
|
|
|
|
NMSettingCdma *s_cdma = nm_connection_get_setting_cdma (request->connection);
|
|
|
|
|
|
|
|
|
|
title = _("Mobile broadband network password");
|
|
|
|
|
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
|
|
|
|
|
nm_connection_get_id (request->connection));
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Password"),
|
|
|
|
|
NM_SETTING (s_cdma),
|
|
|
|
|
NM_SETTING_CDMA_PASSWORD,
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
} else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_GSM_SETTING_NAME);
|
|
|
|
|
if (!setting)
|
|
|
|
|
setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_CDMA_SETTING_NAME);
|
|
|
|
|
|
|
|
|
|
title = _("Mobile broadband network password");
|
|
|
|
|
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
|
|
|
|
|
nm_connection_get_id (request->connection));
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
secret = nm_secret_agent_simple_secret_new (_("Password"),
|
|
|
|
|
setting,
|
|
|
|
|
"password",
|
|
|
|
|
TRUE);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_ptr_array_add (secrets, secret);
|
|
|
|
|
} else
|
|
|
|
|
ok = FALSE;
|
|
|
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
|
g_ptr_array_unref (secrets);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_signal_emit (request->self, signals[REQUEST_SECRETS], 0,
|
|
|
|
|
request->request_id, title, msg, secrets);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_get_secrets (NMSecretAgent *agent,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
const gchar *connection_path,
|
|
|
|
|
const gchar *setting_name,
|
|
|
|
|
const gchar **hints,
|
|
|
|
|
NMSecretAgentGetSecretsFlags flags,
|
|
|
|
|
NMSecretAgentGetSecretsFunc callback,
|
|
|
|
|
gpointer callback_data)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimple *self = NM_SECRET_AGENT_SIMPLE (agent);
|
|
|
|
|
NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self);
|
|
|
|
|
NMSecretAgentSimpleRequest *request;
|
2013-12-02 16:20:26 -05:00
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
const char *connection_type;
|
|
|
|
|
char *request_id;
|
|
|
|
|
GError *error;
|
|
|
|
|
|
|
|
|
|
request_id = g_strdup_printf ("%s/%s", connection_path, setting_name);
|
2014-01-16 14:17:38 -05:00
|
|
|
if (g_hash_table_lookup (priv->requests, request_id) != NULL) {
|
2013-12-02 16:20:26 -05:00
|
|
|
/* We already have a request pending for this (connection, setting) */
|
libnm-core, libnm, settings: move NMSecretAgentError to nm-errors
Move the definition of NMSecretAgentError to nm-errors, register it
with D-Bus, and verify in the tests that it maps correctly.
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR is renamed to
NM_SECRET_AGENT_ERROR_FAILED, and NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED
to NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, for consistency with other
error domains. While NMSecretAgentError, unlike most other error
domains, has always been correctly mapped across D-Bus, the renaming
is not an ABI break, because the daemon never checks for either of
those values, so all versions of the daemon will treat
"org.freedesktop.NetworkManager.SecretAgent.InternalError" and
"org.freedesktop.NetworkManager.SecretAgent.Failed" the same (by just
ignoring the error name and keeping only the error message).
2014-10-15 15:27:25 -04:00
|
|
|
error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED,
|
2013-12-02 16:20:26 -05:00
|
|
|
"Request for %s secrets already pending", request_id);
|
|
|
|
|
nope:
|
2013-12-20 12:58:42 -05:00
|
|
|
callback (agent, connection, NULL, error, callback_data);
|
|
|
|
|
g_error_free (error);
|
2013-12-02 16:20:26 -05:00
|
|
|
g_free (request_id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
connection_type = nm_setting_connection_get_connection_type (s_con);
|
|
|
|
|
|
|
|
|
|
if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME)) {
|
|
|
|
|
/* We don't support VPN secrets yet */
|
|
|
|
|
error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_NO_SECRETS,
|
|
|
|
|
"VPN secrets not supported");
|
|
|
|
|
goto nope;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)) {
|
|
|
|
|
/* We don't do stored passwords */
|
|
|
|
|
error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_NO_SECRETS,
|
|
|
|
|
"Stored passwords not supported");
|
|
|
|
|
goto nope;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
request = g_slice_new (NMSecretAgentSimpleRequest);
|
2013-12-02 16:20:26 -05:00
|
|
|
request->self = g_object_ref (self);
|
|
|
|
|
request->connection = g_object_ref (connection);
|
|
|
|
|
request->hints = g_strdupv ((gchar **)hints);
|
|
|
|
|
request->callback = callback;
|
|
|
|
|
request->callback_data = callback_data;
|
|
|
|
|
request->request_id = request_id;
|
|
|
|
|
g_hash_table_replace (priv->requests, request->request_id, request);
|
|
|
|
|
|
2014-11-13 20:22:04 +01:00
|
|
|
if (priv->enabled)
|
|
|
|
|
request_secrets_from_ui (request);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-14 12:37:00 +02:00
|
|
|
* nm_secret_agent_simple_response:
|
|
|
|
|
* @self: the #NMSecretAgentSimple
|
2013-12-02 16:20:26 -05:00
|
|
|
* @request_id: the request ID being responded to
|
|
|
|
|
* @secrets: (allow-none): the array of secrets, or %NULL
|
|
|
|
|
*
|
2014-10-14 12:37:00 +02:00
|
|
|
* Response to a #NMSecretAgentSimple::get-secrets signal.
|
2013-12-02 16:20:26 -05:00
|
|
|
*
|
|
|
|
|
* If the user provided secrets, the caller should set the
|
|
|
|
|
* corresponding <literal>value</literal> fields in the
|
2014-10-14 12:37:00 +02:00
|
|
|
* #NMSecretAgentSimpleSecrets (freeing any initial values they had), and
|
|
|
|
|
* pass the array to nm_secret_agent_simple_response(). If the user
|
2013-12-02 16:20:26 -05:00
|
|
|
* cancelled the request, @secrets should be NULL.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_response (NMSecretAgentSimple *self,
|
|
|
|
|
const char *request_id,
|
|
|
|
|
GPtrArray *secrets)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimplePrivate *priv;
|
|
|
|
|
NMSecretAgentSimpleRequest *request;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict = NULL;
|
2013-12-02 16:20:26 -05:00
|
|
|
GError *error = NULL;
|
|
|
|
|
int i;
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
g_return_if_fail (NM_IS_SECRET_AGENT_SIMPLE (self));
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self);
|
2013-12-02 16:20:26 -05:00
|
|
|
request = g_hash_table_lookup (priv->requests, request_id);
|
|
|
|
|
g_return_if_fail (request != NULL);
|
|
|
|
|
|
|
|
|
|
if (secrets) {
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariantBuilder conn_builder, *setting_builder;
|
|
|
|
|
GHashTable *settings;
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
settings = g_hash_table_new (g_str_hash, g_str_equal);
|
2013-12-02 16:20:26 -05:00
|
|
|
for (i = 0; i < secrets->len; i++) {
|
2014-10-14 12:37:00 +02:00
|
|
|
NMSecretAgentSimpleSecretReal *secret = secrets->pdata[i];
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
setting_builder = g_hash_table_lookup (settings, nm_setting_get_name (secret->setting));
|
|
|
|
|
if (!setting_builder) {
|
|
|
|
|
setting_builder = g_variant_builder_new (NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_hash_table_insert (settings, (char *) nm_setting_get_name (secret->setting),
|
|
|
|
|
setting_builder);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_add (setting_builder, "{sv}",
|
|
|
|
|
secret->property,
|
|
|
|
|
g_variant_new_string (secret->base.value));
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
2014-08-16 10:09:48 -04:00
|
|
|
|
|
|
|
|
g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION);
|
|
|
|
|
g_hash_table_iter_init (&iter, settings);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &setting_builder))
|
|
|
|
|
g_variant_builder_add (&conn_builder, "{sa{sv}}", name, setting_builder);
|
|
|
|
|
dict = g_variant_builder_end (&conn_builder);
|
|
|
|
|
g_hash_table_destroy (settings);
|
2013-12-02 16:20:26 -05:00
|
|
|
} else {
|
|
|
|
|
error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_USER_CANCELED,
|
|
|
|
|
"User cancelled");
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
request->callback (NM_SECRET_AGENT (self), request->connection, dict, error, request->callback_data);
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
g_hash_table_remove (priv->requests, request_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_cancel_get_secrets (NMSecretAgent *agent,
|
|
|
|
|
const gchar *connection_path,
|
|
|
|
|
const gchar *setting_name)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
|
|
|
|
/* We don't support cancellation. Sorry! */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_save_secrets (NMSecretAgent *agent,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
const gchar *connection_path,
|
|
|
|
|
NMSecretAgentSaveSecretsFunc callback,
|
|
|
|
|
gpointer callback_data)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
|
|
|
|
/* We don't support secret storage */
|
2014-10-14 12:37:00 +02:00
|
|
|
callback (agent, connection, NULL, callback_data);
|
|
|
|
|
}
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
static void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_delete_secrets (NMSecretAgent *agent,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
const gchar *connection_path,
|
|
|
|
|
NMSecretAgentDeleteSecretsFunc callback,
|
|
|
|
|
gpointer callback_data)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
|
|
|
|
/* We don't support secret storage, so there's nothing to delete. */
|
|
|
|
|
callback (agent, connection, NULL, callback_data);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-13 20:22:04 +01:00
|
|
|
/**
|
|
|
|
|
* nm_secret_agent_simple_enable:
|
2014-11-20 11:55:54 -05:00
|
|
|
* @self: the #NMSecretAgentSimple
|
2014-11-20 16:00:34 -06:00
|
|
|
* @path: (allow-none): the path of the connection (if any) to handle secrets
|
|
|
|
|
* for. If %NULL, secrets for any connection will be handled.
|
2014-11-13 20:22:04 +01:00
|
|
|
*
|
2014-11-20 16:00:34 -06:00
|
|
|
* Enables servicing the requests including the already queued ones. If @path
|
|
|
|
|
* is given, the agent will only handle requests for connections that match
|
|
|
|
|
* @path.
|
2014-11-13 20:22:04 +01:00
|
|
|
*/
|
|
|
|
|
void
|
2014-11-20 16:00:34 -06:00
|
|
|
nm_secret_agent_simple_enable (NMSecretAgentSimple *self, const char *path)
|
2014-11-13 20:22:04 +01:00
|
|
|
{
|
2014-11-20 11:55:54 -05:00
|
|
|
NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self);
|
2014-11-13 20:22:04 +01:00
|
|
|
GList *requests, *iter;
|
|
|
|
|
GError *error;
|
|
|
|
|
|
2014-11-20 16:00:34 -06:00
|
|
|
if (g_strcmp0 (path, priv->path) != 0) {
|
|
|
|
|
g_free (priv->path);
|
|
|
|
|
priv->path = g_strdup (path);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-13 20:22:04 +01:00
|
|
|
if (priv->enabled)
|
|
|
|
|
return;
|
|
|
|
|
priv->enabled = TRUE;
|
|
|
|
|
|
|
|
|
|
/* Service pending secret requests. */
|
|
|
|
|
requests = g_hash_table_get_values (priv->requests);
|
|
|
|
|
for (iter = requests; iter; iter = g_list_next (iter)) {
|
|
|
|
|
NMSecretAgentSimpleRequest *request = iter->data;
|
|
|
|
|
|
2014-11-20 12:37:54 +01:00
|
|
|
if (g_str_has_prefix (request->request_id, priv->path)) {
|
2014-11-13 20:22:04 +01:00
|
|
|
request_secrets_from_ui (request);
|
|
|
|
|
} else {
|
|
|
|
|
/* We only handle requests for connection with @path if set. */
|
|
|
|
|
error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED,
|
|
|
|
|
"Request for %s secrets doesn't match path %s",
|
|
|
|
|
request->request_id, priv->path);
|
2014-11-20 16:00:34 -06:00
|
|
|
request->callback (NM_SECRET_AGENT (self), request->connection, NULL, error, request->callback_data);
|
2014-11-13 20:22:04 +01:00
|
|
|
g_hash_table_remove (priv->requests, request->request_id);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g_list_free (requests);
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-02 16:20:26 -05:00
|
|
|
void
|
2014-10-14 12:37:00 +02:00
|
|
|
nm_secret_agent_simple_class_init (NMSecretAgentSimpleClass *klass)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
NMSecretAgentClass *agent_class = NM_SECRET_AGENT_CLASS (klass);
|
|
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
g_type_class_add_private (klass, sizeof (NMSecretAgentSimplePrivate));
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
gobject_class->finalize = nm_secret_agent_simple_finalize;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2014-10-14 12:37:00 +02:00
|
|
|
agent_class->get_secrets = nm_secret_agent_simple_get_secrets;
|
|
|
|
|
agent_class->cancel_get_secrets = nm_secret_agent_simple_cancel_get_secrets;
|
|
|
|
|
agent_class->save_secrets = nm_secret_agent_simple_save_secrets;
|
|
|
|
|
agent_class->delete_secrets = nm_secret_agent_simple_delete_secrets;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
|
|
|
|
/**
|
2014-10-14 12:37:00 +02:00
|
|
|
* NMSecretAgentSimple::request-secrets:
|
|
|
|
|
* @agent: the #NMSecretAgentSimple
|
2013-12-02 16:20:26 -05:00
|
|
|
* @request_id: request ID, to eventually pass to
|
2014-10-14 12:37:00 +02:00
|
|
|
* nm_secret_agent_simple_response().
|
2013-12-02 16:20:26 -05:00
|
|
|
* @title: a title for the password dialog
|
|
|
|
|
* @prompt: a prompt message for the password dialog
|
2014-10-14 12:37:00 +02:00
|
|
|
* @secrets: (element-type #NMSecretAgentSimpleSecret): array of secrets
|
2013-12-02 16:20:26 -05:00
|
|
|
* being requested.
|
|
|
|
|
*
|
|
|
|
|
* Emitted when the agent requires secrets from the user.
|
|
|
|
|
*
|
2014-10-14 12:37:00 +02:00
|
|
|
* The application should ask user for the secrets. For example,
|
|
|
|
|
* nmtui should create a password dialog (#NmtPasswordDialog)
|
|
|
|
|
* with the given title and prompt, and an entry for each
|
|
|
|
|
* element of @secrets. If any of the secrets already have a
|
|
|
|
|
* <literal>value</literal> filled in, the corresponding entry
|
|
|
|
|
* should be initialized to that value.
|
2013-12-02 16:20:26 -05:00
|
|
|
*
|
|
|
|
|
* When the dialog is complete, the app must call
|
2014-10-14 12:37:00 +02:00
|
|
|
* nm_secret_agent_simple_response() with the results.
|
2013-12-02 16:20:26 -05:00
|
|
|
*/
|
|
|
|
|
signals[REQUEST_SECRETS] = g_signal_new ("request-secrets",
|
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
|
0, 0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE,
|
|
|
|
|
4,
|
|
|
|
|
G_TYPE_STRING, /* request_id */
|
|
|
|
|
G_TYPE_STRING, /* title */
|
|
|
|
|
G_TYPE_STRING, /* prompt */
|
|
|
|
|
G_TYPE_PTR_ARRAY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-14 12:37:00 +02:00
|
|
|
* nm_secret_agent_simple_new:
|
|
|
|
|
* @name: the identifier of secret agent
|
2013-12-02 16:20:26 -05:00
|
|
|
*
|
2014-11-13 20:22:04 +01:00
|
|
|
* Creates a new #NMSecretAgentSimple. It does not serve any requests until
|
|
|
|
|
* nm_secret_agent_simple_enable() is called.
|
2013-12-02 16:20:26 -05:00
|
|
|
*
|
2014-11-13 20:22:04 +01:00
|
|
|
* Returns: a new #NMSecretAgentSimple if the agent creation is successful
|
|
|
|
|
* or %NULL in case of a failure.
|
2013-12-02 16:20:26 -05:00
|
|
|
*/
|
|
|
|
|
NMSecretAgent *
|
2014-11-13 20:22:04 +01:00
|
|
|
nm_secret_agent_simple_new (const char *name)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2014-11-20 11:55:54 -05:00
|
|
|
return g_initable_new (NM_TYPE_SECRET_AGENT_SIMPLE, NULL, NULL,
|
2014-11-20 16:00:34 -06:00
|
|
|
NM_SECRET_AGENT_IDENTIFIER, name,
|
2014-11-20 11:55:54 -05:00
|
|
|
NULL);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|