summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-11-23 14:51:16 +0100
committerThomas Haller <thaller@redhat.com>2017-11-23 14:51:21 +0100
commitca26d1ae07a4e8a7036051301d0103ab0822fd44 (patch)
tree77b91d60dc25cb9cd83d0fea0905d307535b3c41
parent8649fcf02ad0646ebbf2daea2ededd0ee4a5745a (diff)
parent272439cb2077a889485dd195bb6b99ca91d3e3bf (diff)
downloadNetworkManager-ca26d1ae07a4e8a7036051301d0103ab0822fd44.tar.gz
all: merge branch 'th/vpn-secrets-bgo790655'
https://bugzilla.gnome.org/show_bug.cgi?id=790655
-rw-r--r--Makefile.am3
-rw-r--r--clients/cli/agent.c2
-rw-r--r--clients/cli/common.c58
-rw-r--r--clients/common/nm-secret-agent-simple.c220
-rw-r--r--clients/common/nm-secret-agent-simple.h20
-rw-r--r--clients/tui/nmt-password-dialog.c4
-rw-r--r--clients/tui/nmtui-connect.c43
-rw-r--r--libnm-core/nm-setting-vpn.c149
-rw-r--r--libnm-core/nm-setting-vpn.h8
-rw-r--r--libnm-core/nm-setting.c25
-rw-r--r--libnm/libnm.ver2
-rw-r--r--libnm/nm-vpn-plugin-old.c123
-rw-r--r--libnm/nm-vpn-service-plugin.c74
-rw-r--r--shared/nm-utils/nm-compat.c88
-rw-r--r--shared/nm-utils/nm-compat.h53
-rw-r--r--shared/nm-utils/nm-macros-internal.h22
-rw-r--r--src/platform/nmp-object.c8
-rw-r--r--src/platform/nmp-object.h8
-rw-r--r--src/settings/nm-agent-manager.c2
-rw-r--r--src/settings/nm-agent-manager.h2
-rw-r--r--src/settings/nm-settings-connection.c2
-rw-r--r--src/settings/nm-settings-connection.h2
-rw-r--r--src/vpn/nm-vpn-connection.c32
23 files changed, 544 insertions, 406 deletions
diff --git a/Makefile.am b/Makefile.am
index ceba78422c..3f60ea5b3f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1066,6 +1066,7 @@ libnm_tests_test_remote_settings_client_CPPFLAGS = $(libnm_tests_cppflags)
libnm_tests_test_secret_agent_CPPFLAGS = $(libnm_tests_cppflags)
libnm_tests_test_general_SOURCES = \
+ shared/nm-utils/nm-compat.c \
libnm/tests/test-general.c
libnm_tests_test_nm_client_SOURCES = \
@@ -4565,6 +4566,8 @@ EXTRA_DIST += \
shared/nm-utils/c-list-util.c \
shared/nm-utils/c-list-util.h \
shared/nm-utils/gsystem-local-alloc.h \
+ shared/nm-utils/nm-compat.c \
+ shared/nm-utils/nm-compat.h \
shared/nm-utils/nm-glib.h \
shared/nm-utils/nm-jansson.h \
shared/nm-utils/nm-obj.h \
diff --git a/clients/cli/agent.c b/clients/cli/agent.c
index 656a58511d..2088648aa0 100644
--- a/clients/cli/agent.c
+++ b/clients/cli/agent.c
@@ -104,7 +104,7 @@ get_secrets_from_user (const char *request_id,
rl_startup_hook = set_deftext;
pre_input_deftext = g_strdup (secret->value);
}
- pwd = nmc_readline ("%s (%s): ", secret->name, secret->prop_name);
+ pwd = nmc_readline ("%s (%s): ", secret->pretty_name, secret->entry_id);
/* No password provided, cancel the secrets. */
if (!pwd)
diff --git a/clients/cli/common.c b/clients/cli/common.c
index 4f369f458b..f785e2c568 100644
--- a/clients/cli/common.c
+++ b/clients/cli/common.c
@@ -531,10 +531,10 @@ vpn_openconnect_get_secrets (NMConnection *connection, GPtrArray *secrets)
{
GError *error = NULL;
NMSettingVpn *s_vpn;
- const char *vpn_type, *gw, *port;
- char *cookie = NULL;
- char *gateway = NULL;
- char *gwcert = NULL;
+ const char *gw, *port;
+ gs_free char *cookie = NULL;
+ gs_free char *gateway = NULL;
+ gs_free char *gwcert = NULL;
int status = 0;
int i;
gboolean ret;
@@ -546,8 +546,7 @@ vpn_openconnect_get_secrets (NMConnection *connection, GPtrArray *secrets)
return FALSE;
s_vpn = nm_connection_get_setting_vpn (connection);
- vpn_type = nm_setting_vpn_get_service_type (s_vpn);
- if (g_strcmp0 (vpn_type, NM_DBUS_INTERFACE ".openconnect"))
+ if (!nm_streq0 (nm_setting_vpn_get_service_type (s_vpn), NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT))
return FALSE;
/* Get gateway and port */
@@ -570,34 +569,31 @@ vpn_openconnect_get_secrets (NMConnection *connection, GPtrArray *secrets)
/* Append port to the host value */
if (gateway && port) {
- char *tmp = gateway;
- gateway = g_strdup_printf ("%s%s", gateway, port);
- g_free (tmp);
+ gs_free char *tmp = gateway;
+
+ gateway = g_strdup_printf ("%s%s", tmp, port);
}
/* Fill secrets to the array */
for (i = 0; i < secrets->len; i++) {
NMSecretAgentSimpleSecret *secret = secrets->pdata[i];
- if (!g_strcmp0 (secret->vpn_type, vpn_type)) {
- if (!g_strcmp0 (secret->vpn_property, "cookie")) {
- g_free (secret->value);
- secret->value = cookie;
- cookie = NULL;
- } else if (!g_strcmp0 (secret->vpn_property, "gateway")) {
- g_free (secret->value);
- secret->value = gateway;
- gateway = NULL;
- } else if (!g_strcmp0 (secret->vpn_property, "gwcert")) {
- g_free (secret->value);
- secret->value = gwcert;
- gwcert = NULL;
- }
+ if (secret->secret_type != NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET)
+ continue;
+ if (!nm_streq0 (secret->vpn_type, NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT))
+ continue;
+
+ if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "cookie")) {
+ g_free (secret->value);
+ secret->value = g_steal_pointer (&cookie);
+ } else if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "gateway")) {
+ g_free (secret->value);
+ secret->value = g_steal_pointer (&gateway);
+ } else if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "gwcert")) {
+ g_free (secret->value);
+ secret->value = g_steal_pointer (&gwcert);
}
}
- g_free (cookie);
- g_free (gateway);
- g_free (gwcert);
return TRUE;
}
@@ -624,7 +620,7 @@ get_secrets_from_user (const char *request_id,
/* 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))) {
+ if (pwds_hash && (pwd = g_hash_table_lookup (pwds_hash, secret->entry_id))) {
pwd = g_strdup (pwd);
} else {
if (ask) {
@@ -640,8 +636,10 @@ get_secrets_from_user (const char *request_id,
}
if (msg)
g_print ("%s\n", msg);
- pwd = nmc_readline_echo (secret->password ? echo_on : TRUE,
- "%s (%s): ", secret->name, secret->prop_name);
+ pwd = nmc_readline_echo (secret->is_secret
+ ? echo_on
+ : TRUE,
+ "%s (%s): ", secret->pretty_name, secret->entry_id);
if (!pwd)
pwd = g_strdup ("");
} else {
@@ -649,7 +647,7 @@ get_secrets_from_user (const char *request_id,
g_print ("%s\n", msg);
g_printerr (_("Warning: password for '%s' not given in 'passwd-file' "
"and nmcli cannot ask without '--ask' option.\n"),
- secret->prop_name);
+ secret->entry_id);
}
}
/* No password provided, cancel the secrets. */
diff --git a/clients/common/nm-secret-agent-simple.c b/clients/common/nm-secret-agent-simple.c
index 21aaf99540..f3b377c12c 100644
--- a/clients/common/nm-secret-agent-simple.c
+++ b/clients/common/nm-secret-agent-simple.c
@@ -147,7 +147,6 @@ strv_has (gchar **haystack,
typedef struct {
NMSecretAgentSimpleSecret base;
-
NMSetting *setting;
char *property;
} NMSecretAgentSimpleSecretReal;
@@ -157,11 +156,10 @@ nm_secret_agent_simple_secret_free (NMSecretAgentSimpleSecret *secret)
{
NMSecretAgentSimpleSecretReal *real = (NMSecretAgentSimpleSecretReal *)secret;
- g_free (secret->name);
- g_free (secret->prop_name);
+ g_free ((char *) secret->pretty_name);
+ g_free ((char *) secret->entry_id);
g_free (secret->value);
- g_free (secret->vpn_property);
- g_free (secret->vpn_type);
+ g_free ((char *) secret->vpn_type);
g_free (real->property);
g_clear_object (&real->setting);
@@ -169,33 +167,45 @@ nm_secret_agent_simple_secret_free (NMSecretAgentSimpleSecret *secret)
}
static NMSecretAgentSimpleSecret *
-nm_secret_agent_simple_secret_new (const char *name,
+nm_secret_agent_simple_secret_new (NMSecretAgentSecretType secret_type,
+ const char *pretty_name,
NMSetting *setting,
const char *property,
- const char *vpn_property,
- const char *vpn_type,
- gboolean password)
+ const char *vpn_type)
{
NMSecretAgentSimpleSecretReal *real;
+ const char *vpn_prefix;
+ const char *value;
+
+ nm_assert (property);
+ nm_assert (NM_IS_SETTING (setting));
real = g_slice_new0 (NMSecretAgentSimpleSecretReal);
- real->base.name = g_strdup (name);
- real->base.prop_name = vpn_property ?
- g_strdup_printf ("%s.%s.%s", nm_setting_get_name (setting), property, vpn_property) :
- g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property);
- real->base.vpn_property = g_strdup (vpn_property);
- real->base.vpn_type = g_strdup (vpn_type);
- real->base.password = password;
-
- if (setting) {
- real->setting = g_object_ref (setting);
- real->property = g_strdup (property);
-
- if (vpn_property)
- real->base.value = g_strdup (nm_setting_vpn_get_secret (NM_SETTING_VPN (setting), vpn_property));
- else
- g_object_get (setting, property, &real->base.value, NULL);
+ *((NMSecretAgentSecretType *) &real->base.secret_type) = secret_type;
+ real->setting = g_object_ref (setting);
+ real->base.pretty_name = g_strdup (pretty_name);
+ real->property = g_strdup (property);
+ switch (secret_type) {
+ case NM_SECRET_AGENT_SECRET_TYPE_PROPERTY:
+ case NM_SECRET_AGENT_SECRET_TYPE_SECRET:
+ nm_assert (!vpn_type);
+ nm_assert (g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property));
+ nm_assert ((secret_type == NM_SECRET_AGENT_SECRET_TYPE_SECRET) == nm_setting_get_secret_flags (setting, property, NULL, NULL));
+ real->base.entry_id = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property);
+ g_object_get (setting, property, &real->base.value, NULL);
+ real->base.is_secret = (secret_type != NM_SECRET_AGENT_SECRET_TYPE_PROPERTY);
+ break;
+ case NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET:
+ vpn_prefix = NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET;
+ value = nm_setting_vpn_get_secret (NM_SETTING_VPN (setting), property);
+ real->base.entry_id = g_strdup_printf ("%s%s", vpn_prefix, property);
+ nm_assert (vpn_type);
+ real->base.vpn_type = g_strdup (vpn_type);
+ real->base.value = g_strdup (value);
+ real->base.is_secret = TRUE;
+ break;
}
+ nm_assert (real->base.entry_id);
return &real->base;
}
@@ -220,37 +230,33 @@ add_8021x_secrets (NMSecretAgentSimpleRequest *request,
* is not visible here since we only care about phase2 authentication
* (and don't even care of which one)
*/
- secret = nm_secret_agent_simple_secret_new (_("Username"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Username"),
NM_SETTING (s_8021x),
NM_SETTING_802_1X_IDENTITY,
- NULL,
- NULL,
- FALSE);
+ NULL);
g_ptr_array_add (secrets, secret);
- secret = nm_secret_agent_simple_secret_new (_("Password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
NM_SETTING (s_8021x),
NM_SETTING_802_1X_PASSWORD,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
return TRUE;
}
if (!strcmp (eap_method, "tls")) {
- secret = nm_secret_agent_simple_secret_new (_("Identity"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Identity"),
NM_SETTING (s_8021x),
NM_SETTING_802_1X_IDENTITY,
- NULL,
- NULL,
- FALSE);
+ NULL);
g_ptr_array_add (secrets, secret);
- secret = nm_secret_agent_simple_secret_new (_("Private key password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Private key password"),
NM_SETTING (s_8021x),
NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
return TRUE;
}
@@ -270,12 +276,11 @@ add_wireless_secrets (NMSecretAgentSimpleRequest *request,
return FALSE;
if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) {
- secret = nm_secret_agent_simple_secret_new (_("Password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
NM_SETTING (s_wsec),
NM_SETTING_WIRELESS_SECURITY_PSK,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
return TRUE;
}
@@ -286,12 +291,11 @@ add_wireless_secrets (NMSecretAgentSimpleRequest *request,
index = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
key = g_strdup_printf ("wep-key%d", index);
- secret = nm_secret_agent_simple_secret_new (_("Key"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Key"),
NM_SETTING (s_wsec),
key,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_free (key);
g_ptr_array_add (secrets, secret);
@@ -300,12 +304,11 @@ add_wireless_secrets (NMSecretAgentSimpleRequest *request,
if (!strcmp (key_mgmt, "iee8021x")) {
if (!g_strcmp0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) {
- secret = nm_secret_agent_simple_secret_new (_("Password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
NM_SETTING (s_wsec),
NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
return TRUE;
} else
@@ -325,26 +328,23 @@ add_pppoe_secrets (NMSecretAgentSimpleRequest *request,
NMSettingPppoe *s_pppoe = nm_connection_get_setting_pppoe (request->connection);
NMSecretAgentSimpleSecret *secret;
- secret = nm_secret_agent_simple_secret_new (_("Username"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Username"),
NM_SETTING (s_pppoe),
NM_SETTING_PPPOE_USERNAME,
- NULL,
- NULL,
- FALSE);
+ NULL);
g_ptr_array_add (secrets, secret);
- secret = nm_secret_agent_simple_secret_new (_("Service"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Service"),
NM_SETTING (s_pppoe),
NM_SETTING_PPPOE_SERVICE,
- NULL,
- NULL,
- FALSE);
+ NULL);
g_ptr_array_add (secrets, secret);
- secret = nm_secret_agent_simple_secret_new (_("Password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
NM_SETTING (s_pppoe),
NM_SETTING_PPPOE_PASSWORD,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
return TRUE;
}
@@ -369,23 +369,27 @@ add_vpn_secret_helper (GPtrArray *secrets, NMSettingVpn *s_vpn, const char *name
NMSettingSecretFlags flags;
int i;
- /* Check for duplicates */
- for (i = 0; i < secrets->len; i++) {
- secret = secrets->pdata[i];
-
- if (g_strcmp0 (secret->vpn_property, name) == 0)
- return;
- }
-
flags = get_vpn_secret_flags (s_vpn, name);
if ( flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED
|| flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
- secret = nm_secret_agent_simple_secret_new (ui_name,
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
+ ui_name,
NM_SETTING (s_vpn),
- NM_SETTING_VPN_SECRETS,
name,
- nm_setting_vpn_get_service_type (s_vpn),
- TRUE);
+ nm_setting_vpn_get_service_type (s_vpn));
+
+ /* Check for duplicates */
+ for (i = 0; i < secrets->len; i++) {
+ NMSecretAgentSimpleSecret *s = secrets->pdata[i];
+
+ if ( s->secret_type == secret->secret_type
+ && nm_streq0 (s->vpn_type, secret->vpn_type)
+ && nm_streq0 (s->entry_id, secret->entry_id)) {
+ nm_secret_agent_simple_secret_free (secret);
+ return;
+ }
+ }
+
g_ptr_array_add (secrets, secret);
}
}
@@ -489,24 +493,22 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
title = _("PIN code required");
msg = g_strdup (_("PIN code is needed for the mobile broadband device"));
- secret = nm_secret_agent_simple_secret_new (_("PIN"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("PIN"),
NM_SETTING (s_gsm),
NM_SETTING_GSM_PIN,
- NULL,
- NULL,
- FALSE);
+ NULL);
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));
- secret = nm_secret_agent_simple_secret_new (_("Password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
NM_SETTING (s_gsm),
NM_SETTING_GSM_PASSWORD,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
}
} else if (nm_connection_is_type (request->connection, NM_SETTING_MACSEC_SETTING_NAME)) {
@@ -517,12 +519,11 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
if (nm_setting_macsec_get_mode (s_macsec) == NM_SETTING_MACSEC_MODE_PSK) {
title = _("MACsec PSK authentication");
- secret = nm_secret_agent_simple_secret_new (_("MKA CAK"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("MKA CAK"),
NM_SETTING (s_macsec),
NM_SETTING_MACSEC_MKA_CAK,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
} else {
title = _("MACsec EAP authentication");
@@ -535,12 +536,11 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection));
- secret = nm_secret_agent_simple_secret_new (_("Password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
NM_SETTING (s_cdma),
NM_SETTING_CDMA_PASSWORD,
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
} else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
NMSetting *setting = NULL;
@@ -558,12 +558,11 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request)
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection));
- secret = nm_secret_agent_simple_secret_new (_("Password"),
+ secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
setting,
"password",
- NULL,
- NULL,
- TRUE);
+ NULL);
g_ptr_array_add (secrets, secret);
} else
ok = FALSE;
@@ -690,9 +689,7 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self,
GHashTable *settings;
GHashTableIter iter;
const char *name;
- const char *vpn_secrets_base_name = NULL;
-
- g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
+ gboolean has_vpn = FALSE;
settings = g_hash_table_new (nm_str_hash, g_str_equal);
for (i = 0; i < secrets->len; i++) {
@@ -705,22 +702,27 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self,
setting_builder);
}
- if (secret->base.vpn_property) {
- /* VPN secrets need slightly different treatment.
- * "secrets" property is actually a hash table of secrets. */
- vpn_secrets_base_name = secret->property;
- g_variant_builder_add (&vpn_secrets_builder, "{ss}",
- secret->base.vpn_property, secret->base.value);
- } else {
+ switch (secret->base.secret_type) {
+ case NM_SECRET_AGENT_SECRET_TYPE_PROPERTY:
+ case NM_SECRET_AGENT_SECRET_TYPE_SECRET:
g_variant_builder_add (setting_builder, "{sv}",
secret->property,
g_variant_new_string (secret->base.value));
+ break;
+ case NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET:
+ if (!has_vpn) {
+ g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
+ has_vpn = TRUE;
+ }
+ g_variant_builder_add (&vpn_secrets_builder, "{ss}",
+ secret->property, secret->base.value);
+ break;
}
}
- if (vpn_secrets_base_name) {
+ if (has_vpn) {
g_variant_builder_add (setting_builder, "{sv}",
- vpn_secrets_base_name,
+ "secrets",
g_variant_builder_end (&vpn_secrets_builder));
}
diff --git a/clients/common/nm-secret-agent-simple.h b/clients/common/nm-secret-agent-simple.h
index 2989723dbf..c0f6befcb4 100644
--- a/clients/common/nm-secret-agent-simple.h
+++ b/clients/common/nm-secret-agent-simple.h
@@ -42,13 +42,25 @@ typedef struct {
} NMSecretAgentSimpleClass;
+typedef enum {
+ NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
+} NMSecretAgentSecretType;
+
typedef struct {
- char *name, *prop_name, *value;
- char *vpn_property;
- char *vpn_type;
- gboolean password;
+ const NMSecretAgentSecretType secret_type;
+ const char *pretty_name;
+ const char *entry_id;
+ char *value;
+ const char *vpn_type;
+ gboolean is_secret;
} NMSecretAgentSimpleSecret;
+#define NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "vpn.secret."
+
+#define NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT NM_DBUS_INTERFACE".openconnect"
+
GType nm_secret_agent_simple_get_type (void);
NMSecretAgentOld *nm_secret_agent_simple_new (const char *name);
diff --git a/clients/tui/nmt-password-dialog.c b/clients/tui/nmt-password-dialog.c
index fb9567e691..16920fcf39 100644
--- a/clients/tui/nmt-password-dialog.c
+++ b/clients/tui/nmt-password-dialog.c
@@ -144,12 +144,12 @@ nmt_password_dialog_constructed (GObject *object)
NMSecretAgentSimpleSecret *secret = priv->secrets->pdata[i];
NmtNewtEntryFlags flags;
- widget = nmt_newt_label_new (secret->name);
+ widget = nmt_newt_label_new (secret->pretty_name);
nmt_newt_grid_add (secret_grid, widget, 0, i);
nmt_newt_widget_set_padding (widget, 4, 0, 1, 0);
flags = NMT_NEWT_ENTRY_NONEMPTY;
- if (secret->password)
+ if (secret->is_secret)
flags |= NMT_NEWT_ENTRY_PASSWORD;
widget = nmt_newt_entry_new (30, flags);
if (secret->value)
diff --git a/clients/tui/nmtui-connect.c b/clients/tui/nmtui-connect.c
index 086e4bd3fb..2a954fb8cb 100644
--- a/clients/tui/nmtui-connect.c
+++ b/clients/tui/nmtui-connect.c
@@ -100,41 +100,38 @@ secrets_requested (NMSecretAgentSimple *agent,
{
NmtNewtForm *form;
NMConnection *connection = NM_CONNECTION (user_data);
- char *cookie = NULL;
- char *gateway = NULL;
- char *gwcert = NULL;
int i;
/* Get secrets for OpenConnect VPN */
- if (connection && nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME)) {
+ if ( connection
+ && nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME)) {
NMSettingVpn *s_vpn = nm_connection_get_setting_vpn (connection);
- const char *vpn_type = nm_setting_vpn_get_service_type (s_vpn);
- if (!g_strcmp0 (vpn_type, NM_DBUS_INTERFACE ".openconnect")) {
+ if (nm_streq0 (nm_setting_vpn_get_service_type (s_vpn), NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT)) {
+ gs_free char *cookie = NULL;
+ gs_free char *gateway = NULL;
+ gs_free char *gwcert = NULL;
+
openconnect_authenticate (connection, &cookie, &gateway, &gwcert);
for (i = 0; i < secrets->len; i++) {
NMSecretAgentSimpleSecret *secret = secrets->pdata[i];
- if (!g_strcmp0 (secret->vpn_type, NM_DBUS_INTERFACE ".openconnect")) {
- if (!g_strcmp0 (secret->vpn_property, "cookie")) {
- g_free (secret->value);
- secret->value = cookie;
- cookie = NULL;
- } else if (!g_strcmp0 (secret->vpn_property, "gateway")) {
- g_free (secret->value);
- secret->value = gateway;
- gateway = NULL;
- } else if (!g_strcmp0 (secret->vpn_property, "gwcert")) {
- g_free (secret->value);
- secret->value = gwcert;
- gwcert = NULL;
- }
+ if (secret->secret_type != NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET)
+ continue;
+ if (!nm_streq0 (secret->vpn_type, NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT))
+ continue;
+ if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "cookie")) {
+ g_free (secret->value);
+ secret->value = g_steal_pointer (&cookie);
+ } else if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "gateway")) {
+ g_free (secret->value);
+ secret->value = g_steal_pointer (&gateway);
+ } else if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "gwcert")) {
+ g_free (secret->value);
+ secret->value = g_steal_pointer (&gwcert);
}
}
- g_free (cookie);
- g_free (gateway);
- g_free (gwcert);
}
}
diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c
index 343bd9aa30..79a7350bdb 100644
--- a/libnm-core/nm-setting-vpn.c
+++ b/libnm-core/nm-setting-vpn.c
@@ -155,6 +155,39 @@ nm_setting_vpn_get_persistent (NMSettingVpn *setting)
return NM_SETTING_VPN_GET_PRIVATE (setting)->persistent;
}
+static const char **
+_get_keys (NMSettingVpn *setting,
+ gboolean is_secrets,
+ guint *out_length)
+{
+ NMSettingVpnPrivate *priv;
+ GHashTable *hash;
+ const char **keys;
+ guint len;
+
+ nm_assert (NM_IS_SETTING_VPN (setting));
+
+ priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+
+ hash = is_secrets ? priv->secrets : priv->data;
+
+ if (!g_hash_table_size (hash)) {
+ NM_SET_OUT (out_length, 0);
+ return NULL;
+ }
+
+ keys = (const char **) g_hash_table_get_keys_as_array (hash, &len);
+ if (len > 1) {
+ g_qsort_with_data (keys,
+ len,
+ sizeof (const char *),
+ nm_strcmp_p_with_data,
+ NULL);
+ }
+ NM_SET_OUT (out_length, len);
+ return keys;
+}
+
/**
* nm_setting_vpn_get_num_data_items:
* @setting: the #NMSettingVpn
@@ -216,6 +249,28 @@ nm_setting_vpn_get_data_item (NMSettingVpn *setting, const char *key)
}
/**
+ * nm_setting_vpn_get_data_keys:
+ * @setting: the #NMSettingVpn
+ * @out_length: (allow-none): (out): the length of the returned array
+ *
+ * Retrieves every data key inside @setting, as an array.
+ *
+ * Returns: (array length=out_length) (transfer container): a
+ * %NULL-terminated array containing each data key or %NULL if
+ * there are no data items.
+ *
+ * Since: 1.12
+ */
+const char **
+nm_setting_vpn_get_data_keys (NMSettingVpn *setting,
+ guint *out_length)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return _get_keys (setting, FALSE, out_length);
+}
+
+/**
* nm_setting_vpn_remove_data_item:
* @setting: the #NMSettingVpn
* @key: the name of the data item to remove
@@ -240,32 +295,52 @@ nm_setting_vpn_remove_data_item (NMSettingVpn *setting, const char *key)
}
static void
-foreach_item_helper (GHashTable *hash,
+foreach_item_helper (NMSettingVpn *self,
+ gboolean is_secrets,
NMVpnIterFunc func,
gpointer user_data)
{
- GList *keys, *liter;
- GSList *copied = NULL, *siter;
+ NMSettingVpnPrivate *priv;
+ guint len, i;
+ gs_strfreev char **keys = NULL;
+ GHashTable *hash;
- g_return_if_fail (hash != NULL);
+ nm_assert (NM_IS_SETTING_VPN (self));
+ nm_assert (func);
- /* Grab keys and copy them so that the callback func can modify
- * the hash table items if it wants to.
- */
- keys = g_hash_table_get_keys (hash);
- for (liter = keys; liter; liter = g_list_next (liter))
- copied = g_slist_prepend (copied, g_strdup (liter->data));
- copied = g_slist_reverse (copied);
- g_list_free (keys);
+ priv = NM_SETTING_VPN_GET_PRIVATE (self);
- for (siter = copied; siter; siter = g_slist_next (siter)) {
- gpointer value;
+ if (is_secrets) {
+ keys = (char **) nm_setting_vpn_get_secret_keys (self, &len);
+ hash = priv->secrets;
+ } else {
+ keys = (char **) nm_setting_vpn_get_data_keys (self, &len);
+ hash = priv->data;
+ }
- value = g_hash_table_lookup (hash, siter->data);
- func (siter->data, value, user_data);
+ if (!len) {
+ nm_assert (!keys);
+ return;
}
- g_slist_free_full (copied, g_free);
+ for (i = 0; i < len; i++) {
+ nm_assert (keys[i]);
+ keys[i] = g_strdup (keys[i]);
+ }
+ nm_assert (!keys[i]);
+
+ for (i = 0; i < len; i++) {
+ const char *value;
+
+ value = g_hash_table_lookup (hash, keys[i]);
+ /* XXX: note that we call the function with a clone of @key,
+ * not with the actual key from the dictionary.
+ *
+ * The @value on the other hand, is actually inside our dictionary,
+ * it's not a clone. However, it might be %NULL, in case the key was
+ * deleted while iterating. */
+ func (keys[i], value, user_data);
+ }
}
/**
@@ -284,8 +359,9 @@ nm_setting_vpn_foreach_data_item (NMSettingVpn *setting,
gpointer user_data)
{
g_return_if_fail (NM_IS_SETTING_VPN (setting));
+ g_return_if_fail (func);
- foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->data, func, user_data);
+ foreach_item_helper (setting, FALSE, func, user_data);
}
/**
@@ -348,6 +424,28 @@ nm_setting_vpn_get_secret (NMSettingVpn *setting, const char *key)
}
/**
+ * nm_setting_vpn_get_secret_keys:
+ * @setting: the #NMSettingVpn
+ * @out_length: (allow-none): (out): the length of the returned array
+ *
+ * Retrieves every secret key inside @setting, as an array.
+ *
+ * Returns: (array length=out_length) (transfer container): a
+ * %NULL-terminated array containing each secret key or %NULL if
+ * there are no secrets.
+ *
+ * Since: 1.12
+ */
+const char **
+nm_setting_vpn_get_secret_keys (NMSettingVpn *setting,
+ guint *out_length)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return _get_keys (setting, TRUE, out_length);
+}
+
+/**
* nm_setting_vpn_remove_secret:
* @setting: the #NMSettingVpn
* @key: the name of the secret to remove
@@ -387,8 +485,9 @@ nm_setting_vpn_foreach_secret (NMSettingVpn *setting,
gpointer user_data)
{
g_return_if_fail (NM_IS_SETTING_VPN (setting));
+ g_return_if_fail (func);
- foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, func, user_data);
+ foreach_item_helper (setting, TRUE, func, user_data);
}
/**
@@ -708,22 +807,12 @@ clear_secrets_with_flags (NMSetting *setting,
}
static void
-destroy_one_secret (gpointer data)
-{
- char *secret = (char *) data;
-
- /* Don't leave the secret lying around in memory */
- memset (secret, 0, strlen (secret));
- g_free (secret);
-}
-
-static void
nm_setting_vpn_init (NMSettingVpn *setting)
{
NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
priv->data = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free);
- priv->secrets = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, destroy_one_secret);
+ priv->secrets = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
}
static void
diff --git a/libnm-core/nm-setting-vpn.h b/libnm-core/nm-setting-vpn.h
index 115aa8676e..1f1576fdfe 100644
--- a/libnm-core/nm-setting-vpn.h
+++ b/libnm-core/nm-setting-vpn.h
@@ -90,6 +90,9 @@ gboolean nm_setting_vpn_remove_data_item (NMSettingVpn *setting,
void nm_setting_vpn_foreach_data_item (NMSettingVpn *setting,
NMVpnIterFunc func,
gpointer user_data);
+NM_AVAILABLE_IN_1_12
+const char ** nm_setting_vpn_get_data_keys (NMSettingVpn *setting,
+ guint *out_length);
guint32 nm_setting_vpn_get_num_secrets (NMSettingVpn *setting);
void nm_setting_vpn_add_secret (NMSettingVpn *setting,
@@ -102,6 +105,11 @@ gboolean nm_setting_vpn_remove_secret (NMSettingVpn *setting,
void nm_setting_vpn_foreach_secret (NMSettingVpn *setting,
NMVpnIterFunc func,
gpointer user_data);
+NM_AVAILABLE_IN_1_12
+const char ** nm_setting_vpn_get_secret_keys (NMSettingVpn *setting,
+ guint *out_length);
+
+
NM_AVAILABLE_IN_1_2
guint32 nm_setting_vpn_get_timeout (NMSettingVpn *setting);
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
index 297887411d..5a06fd062b 100644
--- a/libnm-core/nm-setting.c
+++ b/libnm-core/nm-setting.c
@@ -1800,21 +1800,19 @@ get_secret_flags (NMSetting *setting,
NMSettingSecretFlags *out_flags,
GError **error)
{
- char *flags_prop;
+ gs_free char *name_to_free = NULL;
NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
if (verify_secret && !is_secret_prop (setting, secret_name, error)) {
- if (out_flags)
- *out_flags = NM_SETTING_SECRET_FLAG_NONE;
+ NM_SET_OUT (out_flags, NM_SETTING_SECRET_FLAG_NONE);
return FALSE;
}
- flags_prop = g_strdup_printf ("%s-flags", secret_name);
- g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL);
- g_free (flags_prop);
-
- if (out_flags)
- *out_flags = flags;
+ g_object_get (G_OBJECT (setting),
+ nm_construct_name_a ("%s-flags", secret_name, &name_to_free),
+ &flags,
+ NULL);
+ NM_SET_OUT (out_flags, flags);
return TRUE;
}
@@ -1850,14 +1848,15 @@ set_secret_flags (NMSetting *setting,
NMSettingSecretFlags flags,
GError **error)
{
- char *flags_prop;
+ gs_free char *name_to_free = NULL;
if (verify_secret)
g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE);
- flags_prop = g_strdup_printf ("%s-flags", secret_name);
- g_object_set (G_OBJECT (setting), flags_prop, flags, NULL);
- g_free (flags_prop);
+ g_object_set (G_OBJECT (setting),
+ nm_construct_name_a ("%s-flags", secret_name, &name_to_free),
+ flags,
+ NULL);
return TRUE;
}
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 5e9feaffc8..aad581698b 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1258,4 +1258,6 @@ global:
nm_setting_team_port_get_lacp_key;
nm_setting_team_remove_runner_tx_hash;
nm_setting_team_remove_runner_tx_hash_by_value;
+ nm_setting_vpn_get_data_keys;
+ nm_setting_vpn_get_secret_keys;
} libnm_1_10_0;
diff --git a/libnm/nm-vpn-plugin-old.c b/libnm/nm-vpn-plugin-old.c
index 1892c394b7..73d2b2abc0 100644
--- a/libnm/nm-vpn-plugin-old.c
+++ b/libnm/nm-vpn-plugin-old.c
@@ -33,6 +33,7 @@
#include "nm-dbus-helpers.h"
#include "nm-core-internal.h"
#include "nm-simple-connection.h"
+#include "nm-vpn-service-plugin.h"
#include "introspection/org.freedesktop.NetworkManager.VPN.Plugin.h"
@@ -683,20 +684,6 @@ nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin,
/*****************************************************************************/
-#define DATA_KEY_TAG "DATA_KEY="
-#define DATA_VAL_TAG "DATA_VAL="
-#define SECRET_KEY_TAG "SECRET_KEY="
-#define SECRET_VAL_TAG "SECRET_VAL="
-
-static void
-free_secret (gpointer data)
-{
- char *secret = data;
-
- memset (secret, 0, strlen (secret));
- g_free (secret);
-}
-
/**
* nm_vpn_plugin_old_read_vpn_details:
* @fd: file descriptor to read from, usually stdin (0)
@@ -717,87 +704,7 @@ nm_vpn_plugin_old_read_vpn_details (int fd,
GHashTable **out_data,
GHashTable **out_secrets)
{
- GHashTable *data, *secrets;
- gboolean success = FALSE;
- char *key = NULL, *val = NULL;
- GString *line;
- gchar c;
-
- if (out_data)
- g_return_val_if_fail (*out_data == NULL, FALSE);
- if (out_secrets)
- g_return_val_if_fail (*out_secrets == NULL, FALSE);
-
- data = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free);
- secrets = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, free_secret);
-
- line = g_string_new (NULL);
-
- /* Read stdin for data and secret items until we get a DONE */
- while (1) {
- ssize_t nr;
- GHashTable *hash = NULL;
-
- errno = 0;
- nr = read (fd, &c, 1);
- if (nr == -1) {
- if (errno == EAGAIN) {
- g_usleep (100);
- continue;
- }
- break;
- }
-
- if (c != '\n') {
- g_string_append_c (line, c);
- continue;
- }
-
- /* Check for the finish marker */
- if (strcmp (line->str, "DONE") == 0)
- break;
-
- /* Otherwise it's a data/secret item */
- if (strncmp (line->str, DATA_KEY_TAG, strlen (DATA_KEY_TAG)) == 0) {
- hash = data;
- key = g_strdup (line->str + strlen (DATA_KEY_TAG));
- } else if (strncmp (line->str, DATA_VAL_TAG, strlen (DATA_VAL_TAG)) == 0) {
- hash = data;
- val = g_strdup (line->str + strlen (DATA_VAL_TAG));
- } else if (strncmp (line->str, SECRET_KEY_TAG, strlen (SECRET_KEY_TAG)) == 0) {
- hash = secrets;
- key = g_strdup (line->str + strlen (SECRET_KEY_TAG));
- } else if (strncmp (line->str, SECRET_VAL_TAG, strlen (SECRET_VAL_TAG)) == 0) {
- hash = secrets;
- val = g_strdup (line->str + strlen (SECRET_VAL_TAG));
- }
- g_string_truncate (line, 0);
-
- if (key && val && hash) {
- g_hash_table_insert (hash, key, val);
- key = NULL;
- val = NULL;
- success = TRUE; /* Got at least one value */
- }
- }
-
- if (success) {
- if (out_data)
- *out_data = data;
- else
- g_hash_table_destroy (data);
-
- if (out_secrets)
- *out_secrets = secrets;
- else
- g_hash_table_destroy (secrets);
- } else {
- g_hash_table_destroy (data);
- g_hash_table_destroy (secrets);
- }
-
- g_string_free (line, TRUE);
- return success;
+ return nm_vpn_service_plugin_read_vpn_details (fd, out_data, out_secrets);
}
/**
@@ -820,31 +727,7 @@ nm_vpn_plugin_old_get_secret_flags (GHashTable *data,
const char *secret_name,
NMSettingSecretFlags *out_flags)
{
- char *flag_name;
- const char *val;
- unsigned long tmp;
- gboolean success = FALSE;
-
- g_return_val_if_fail (data != NULL, FALSE);
- g_return_val_if_fail (secret_name != NULL, FALSE);
- g_return_val_if_fail (out_flags != NULL, FALSE);
- g_return_val_if_fail (*out_flags == NM_SETTING_SECRET_FLAG_NONE, FALSE);
-
- flag_name = g_strdup_printf ("%s-flags", secret_name);
-
- /* Try new flags value first */
- val = g_hash_table_lookup (data, flag_name);
- if (val) {
- errno = 0;
- tmp = strtoul (val, NULL, 10);
- if (errno == 0 && tmp <= NM_SETTING_SECRET_FLAGS_ALL) {
- *out_flags = (NMSettingSecretFlags) tmp;
- success = TRUE;
- }
- }
-
- g_free (flag_name);
- return success;
+ return nm_vpn_service_plugin_get_secret_flags (data, secret_name, out_flags);
}
/*****************************************************************************/
diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c
index 79bd0f8193..b9e3992631 100644
--- a/libnm/nm-vpn-service-plugin.c
+++ b/libnm/nm-vpn-service-plugin.c
@@ -710,15 +710,6 @@ nm_vpn_service_plugin_secrets_required (NMVpnServicePlugin *plugin,
#define SECRET_KEY_TAG "SECRET_KEY="
#define SECRET_VAL_TAG "SECRET_VAL="
-static void
-free_secret (gpointer data)
-{
- char *secret = data;
-
- memset (secret, 0, strlen (secret));
- g_free (secret);
-}
-
/**
* nm_vpn_service_plugin_read_vpn_details:
* @fd: file descriptor to read from, usually stdin (0)
@@ -739,10 +730,11 @@ nm_vpn_service_plugin_read_vpn_details (int fd,
GHashTable **out_data,
GHashTable **out_secrets)
{
- GHashTable *data, *secrets;
+ gs_unref_hashtable GHashTable *data = NULL;
+ gs_unref_hashtable GHashTable *secrets = NULL;
gboolean success = FALSE;
char *key = NULL, *val = NULL;
- GString *line;
+ nm_auto_free_gstring GString *line = NULL;
gchar c;
if (out_data)
@@ -751,7 +743,7 @@ nm_vpn_service_plugin_read_vpn_details (int fd,
g_return_val_if_fail (*out_secrets == NULL, FALSE);
data = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free);
- secrets = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, free_secret);
+ secrets = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
line = g_string_new (NULL);
@@ -804,21 +796,9 @@ nm_vpn_service_plugin_read_vpn_details (int fd,
}
if (success) {
- if (out_data)
- *out_data = data;
- else
- g_hash_table_destroy (data);
-
- if (out_secrets)
- *out_secrets = secrets;
- else
- g_hash_table_destroy (secrets);
- } else {
- g_hash_table_destroy (data);
- g_hash_table_destroy (secrets);
+ NM_SET_OUT (out_data, g_steal_pointer (&data));
+ NM_SET_OUT (out_secrets, g_steal_pointer (&secrets));
}
-
- g_string_free (line, TRUE);
return success;
}
@@ -842,31 +822,29 @@ nm_vpn_service_plugin_get_secret_flags (GHashTable *data,
const char *secret_name,
NMSettingSecretFlags *out_flags)
{
- char *flag_name;
- const char *val;
- unsigned long tmp;
- gboolean success = FALSE;
-
- g_return_val_if_fail (data != NULL, FALSE);
- g_return_val_if_fail (secret_name != NULL, FALSE);
- g_return_val_if_fail (out_flags != NULL, FALSE);
- g_return_val_if_fail (*out_flags == NM_SETTING_SECRET_FLAG_NONE, FALSE);
+ gs_free char *flag_name_free = NULL;
+ const char *s;
+ gint64 t1;
+ NMSettingSecretFlags t0;
- flag_name = g_strdup_printf ("%s-flags", secret_name);
+ g_return_val_if_fail (data, FALSE);
+ g_return_val_if_fail (out_flags && *out_flags == NM_SETTING_SECRET_FLAG_NONE, FALSE);
+ if (!secret_name || !*secret_name)
+ g_return_val_if_reached (FALSE);
- /* Try new flags value first */
- val = g_hash_table_lookup (data, flag_name);
- if (val) {
- errno = 0;
- tmp = strtoul (val, NULL, 10);
- if (errno == 0 && tmp <= NM_SETTING_SECRET_FLAGS_ALL) {
- *out_flags = (NMSettingSecretFlags) tmp;
- success = TRUE;
- }
- }
- g_free (flag_name);
- return success;
+ s = g_hash_table_lookup (data,
+ nm_construct_name_a ("%s-flags", secret_name, &flag_name_free));
+ if (!s)
+ return FALSE;
+ t1 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXINT64, -1);
+ if (t1 == -1)
+ return FALSE;
+ t0 = (NMSettingSecretFlags) t1;
+ if ((gint64) t0 != t1)
+ return FALSE;
+ NM_SET_OUT (out_flags, t0);
+ return TRUE;
}
/*****************************************************************************/
diff --git a/shared/nm-utils/nm-compat.c b/shared/nm-utils/nm-compat.c
new file mode 100644
index 0000000000..22ab675de8
--- /dev/null
+++ b/shared/nm-utils/nm-compat.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2017 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-compat.h"
+
+/*****************************************************************************/
+
+static void
+_get_keys_cb (const char *key, const char *val, gpointer user_data)
+{
+ GPtrArray *a = user_data;
+
+ g_ptr_array_add (a, g_strdup (key));
+}
+
+static const char **
+_get_keys (NMSettingVpn *setting,
+ gboolean is_secrets,
+ guint *out_length)
+{
+ guint len;
+ const char **keys = NULL;
+ gs_unref_ptrarray GPtrArray *a = NULL;
+
+ nm_assert (NM_IS_SETTING_VPN (setting));
+
+ a = g_ptr_array_new ();
+ if (is_secrets)
+ nm_setting_vpn_foreach_secret (setting, _get_keys_cb, a);
+ else
+ nm_setting_vpn_foreach_data_item (setting, _get_keys_cb, a);
+ len = a->len;
+
+ if (a->len) {
+ g_ptr_array_sort (a, nm_strcmp_p);
+ g_ptr_array_add (a, NULL);
+ keys = (const char **) g_ptr_array_free (g_steal_pointer (&a), FALSE);
+
+ /* we need to cache the keys *somewhere*. */
+ g_object_set_qdata_full (G_OBJECT (setting),
+ is_secrets
+ ? NM_CACHED_QUARK ("libnm._nm_setting_vpn_get_secret_keys")
+ : NM_CACHED_QUARK ("libnm._nm_setting_vpn_get_data_keys"),
+ keys,
+ (GDestroyNotify) g_strfreev);
+ }
+
+ NM_SET_OUT (out_length, len);
+ return keys;
+}
+
+const char **
+_nm_setting_vpn_get_data_keys (NMSettingVpn *setting,
+ guint *out_length)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return _get_keys (setting, FALSE, out_length);
+}
+
+const char **
+_nm_setting_vpn_get_secret_keys (NMSettingVpn *setting,
+ guint *out_length)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return _get_keys (setting, TRUE, out_length);
+}
diff --git a/shared/nm-utils/nm-compat.h b/shared/nm-utils/nm-compat.h
new file mode 100644
index 0000000000..5234169033
--- /dev/null
+++ b/shared/nm-utils/nm-compat.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2017 Red Hat, Inc.
+ */
+
+#ifndef __NM_COMPAT_H__
+#define __NM_COMPAT_H__
+
+#include "nm-setting-vpn.h"
+
+const char **_nm_setting_vpn_get_data_keys (NMSettingVpn *setting,
+ guint *out_length);
+
+const char **_nm_setting_vpn_get_secret_keys (NMSettingVpn *setting,
+ guint *out_length);
+
+#if NM_CHECK_VERSION (1, 11, 0)
+#define nm_setting_vpn_get_data_keys(setting, out_length) \
+ ({ \
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+ nm_setting_vpn_get_data_keys (setting, out_length); \
+ G_GNUC_END_IGNORE_DEPRECATIONS \
+ })
+#define nm_setting_vpn_get_secret_keys(setting, out_length) \
+ ({ \
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+ nm_setting_vpn_get_secret_keys (setting, out_length); \
+ G_GNUC_END_IGNORE_DEPRECATIONS \
+ })
+#else
+#define nm_setting_vpn_get_data_keys(setting, out_length) \
+ _nm_setting_vpn_get_data_keys (setting, out_length)
+#define nm_setting_vpn_get_secret_keys(setting, out_length) \
+ _nm_setting_vpn_get_secret_keys (setting, out_length)
+#endif
+
+#endif /* __NM_COMPAT_H__ */
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index ce13d3a6fa..cf9142fe99 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -1172,6 +1172,28 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
_buf; \
})
+/* aims to alloca() a buffer and fill it with printf(format, name).
+ * Note that format must not contain any format specifier except
+ * "%s".
+ * If the resulting string would be too large for stack allocation,
+ * it allocates a buffer with g_malloc() and assigns it to *p_val_to_free. */
+#define nm_construct_name_a(format, name, p_val_to_free) \
+ ({ \
+ const char *const _name = (name); \
+ char **const _p_val_to_free = (p_val_to_free); \
+ const gsize _name_len = strlen (_name); \
+ char *_buf2; \
+ \
+ nm_assert (_p_val_to_free && !*_p_val_to_free); \
+ if (NM_STRLEN (format) + _name_len < 200) \
+ _buf2 = nm_sprintf_bufa (NM_STRLEN (format) + _name_len, format, _name); \
+ else { \
+ _buf2 = g_strdup_printf (format, _name); \
+ *_p_val_to_free = _buf2; \
+ } \
+ (const char *) _buf2; \
+ })
+
/*****************************************************************************/
/**
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 0c951dd4fc..ee4014ac3c 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -861,12 +861,6 @@ _vt_cmd_obj_cmp_lnk_vlan (const NMPObject *obj1, const NMPObject *obj2)
return c;
}
-gboolean
-nmp_object_equal (const NMPObject *obj1, const NMPObject *obj2)
-{
- return nmp_object_cmp (obj1, obj2) == 0;
-}
-
/* @src is a const object, which is not entirely correct for link types, where
* we increase the ref count for src->_link.udev.device.
* Hence, nmp_object_copy() can violate the const promise of @src.
@@ -1076,7 +1070,7 @@ nmp_object_id_hash (const NMPObject *obj)
NMHashState h;
if (!obj)
- return 0;
+ return nm_hash_static (914932607u);
nm_hash_init (&h, 914932607u);
nmp_object_id_hash_update (obj, &h);
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index 6db7573a99..d8fe60a60e 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -471,7 +471,13 @@ const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifinde
const char *nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size);
void nmp_object_hash_update (const NMPObject *obj, NMHashState *h);
int nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2);
-gboolean nmp_object_equal (const NMPObject *obj1, const NMPObject *obj2);
+
+static inline gboolean
+nmp_object_equal (const NMPObject *obj1, const NMPObject *obj2)
+{
+ return nmp_object_cmp (obj1, obj2) == 0;
+}
+
void nmp_object_copy (NMPObject *dst, const NMPObject *src, gboolean id_only);
NMPObject *nmp_object_clone (const NMPObject *obj, gboolean id_only);
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index bcd178435f..29abd71bd5 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -1213,7 +1213,7 @@ nm_agent_manager_get_secrets (NMAgentManager *self,
GVariant *existing_secrets,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
- const char **hints,
+ const char *const*hints,
NMAgentSecretsResultFunc callback,
gpointer callback_data)
{
diff --git a/src/settings/nm-agent-manager.h b/src/settings/nm-agent-manager.h
index 7f8126935f..c2a2ec1d8f 100644
--- a/src/settings/nm-agent-manager.h
+++ b/src/settings/nm-agent-manager.h
@@ -60,7 +60,7 @@ NMAgentManagerCallId nm_agent_manager_get_secrets (NMAgentManager *manager,
GVariant *existing_secrets,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
- const char **hints,
+ const char *const*hints,
NMAgentSecretsResultFunc callback,
gpointer callback_data);
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index ed69115c8b..1185aef905 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -1228,7 +1228,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
NMAuthSubject *subject,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
- const char **hints,
+ const char *const*hints,
NMSettingsConnectionSecretsFunc callback,
gpointer callback_data)
{
diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h
index faacd94909..7a9e383259 100644
--- a/src/settings/nm-settings-connection.h
+++ b/src/settings/nm-settings-connection.h
@@ -167,7 +167,7 @@ NMSettingsConnectionCallId nm_settings_connection_get_secrets (NMSettingsConnect
NMAuthSubject *subject,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
- const char **hints,
+ const char *const*hints,
NMSettingsConnectionSecretsFunc callback,
gpointer callback_data);
diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c
index 7122243d35..e441bbd051 100644
--- a/src/vpn/nm-vpn-connection.c
+++ b/src/vpn/nm-vpn-connection.c
@@ -185,13 +185,13 @@ static NMSettingsConnection *_get_settings_connection (NMVpnConnection *self,
static void get_secrets (NMVpnConnection *self,
SecretsReq secrets_idx,
- const char **hints);
+ const char *const*hints);
static guint32 get_route_table (NMVpnConnection *self, int addr_family, gboolean fallback_main);
static void plugin_interactive_secrets_required (NMVpnConnection *self,
const char *message,
- const char **secrets);
+ const char *const*secrets);
static void _set_vpn_state (NMVpnConnection *self,
VpnState vpn_state,
@@ -2047,7 +2047,7 @@ state_changed_cb (GDBusProxy *proxy,
static void
secrets_required_cb (GDBusProxy *proxy,
const char *message,
- const char **secrets,
+ const char *const*secrets,
gpointer user_data)
{
NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
@@ -2638,7 +2638,7 @@ get_secrets_cb (NMSettingsConnection *connection,
static void
get_secrets (NMVpnConnection *self,
SecretsReq secrets_idx,
- const char **hints)
+ const char *const*hints)
{
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE;
@@ -2683,12 +2683,13 @@ get_secrets (NMVpnConnection *self,
static void
plugin_interactive_secrets_required (NMVpnConnection *self,
const char *message,
- const char **secrets)
+ const char *const*secrets)
{
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
- guint32 secrets_len = secrets ? g_strv_length ((char **) secrets) : 0;
- char **hints;
- guint32 i;
+ const gsize secrets_len = NM_PTRARRAY_LEN (secrets);
+ gsize i;
+ gs_free const char **hints = NULL;
+ gs_free char *message_hint = NULL;
_LOGI ("VPN plugin: requested secrets; state %s (%d)",
vpn_state_to_string (priv->vpn_state), priv->vpn_state);
@@ -2700,14 +2701,17 @@ plugin_interactive_secrets_required (NMVpnConnection *self,
_set_vpn_state (self, STATE_NEED_AUTH, NM_ACTIVE_CONNECTION_STATE_REASON_NONE, FALSE);
/* Copy hints and add message to the end */
- hints = g_malloc0 (sizeof (char *) * (secrets_len + 2));
+ hints = g_new (const char *, secrets_len + 2);
for (i = 0; i < secrets_len; i++)
- hints[i] = g_strdup (secrets[i]);
- if (message)
- hints[i] = g_strdup_printf ("x-vpn-message:%s", message);
+ hints[i] = secrets[i];
+ if (message) {
+ message_hint = g_strdup_printf ("x-vpn-message:%s", message);
+ hints[i++] = message_hint;
+ }
+ hints[i] = NULL;
+ nm_assert (i < secrets_len + 2);
- get_secrets (self, SECRETS_REQ_INTERACTIVE, (const char **) hints);
- g_strfreev (hints);
+ get_secrets (self, SECRETS_REQ_INTERACTIVE, hints);
}
/*****************************************************************************/