Commit d7a86ffd authored by Dan Williams's avatar Dan Williams

libnm-util: fix VPN update_one_secret()

The old function took a string value, which wasn't really correct as
the property type is a GHashTable of string:string.  For whatever
reason this is how nm-applet passed VPN secrets back to NM in the return
from the GetSecrets() D-Bus call.  This was probably easier or
something but it was a special case that's magic and quite unclear.

Since we use nm_connection_update_secrets() more these days, and we
depend on the GValue types we pass into it matching the property
types of the setting property the secret is for, we need to fix that
up for VPN connections.  But keep the old code for backwards
compatibility.

In the future secret agents should pass back VPN secrets in the same
form as the VPN setting specifies them for the "secrets" property:
a GHashTable of string:string.  But the old mechanism of just dumping
the key/value pairs into the returned VPN hash as string:string will
still work.
parent b94fb031
......@@ -264,34 +264,91 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
}
static gboolean
update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
update_secret_string (NMSetting *setting,
const char *key,
const char *value,
GError **error)
{
NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
char *str;
g_return_val_if_fail (key != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
if (!G_VALUE_HOLDS_STRING (value)) {
if (!value || !strlen (value)) {
g_set_error (error, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"%s", key);
"Secret %s was empty", key);
return FALSE;
}
str = g_value_dup_string (value);
if (!str || !strlen (str)) {
g_set_error (error, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"Secret %s was empty", key);
g_free (str);
return FALSE;
g_hash_table_insert (priv->secrets, g_strdup (key), g_strdup (value));
return TRUE;
}
static gboolean
update_secret_hash (NMSetting *setting,
GHashTable *secrets,
GError **error)
{
NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
GHashTableIter iter;
const char *name, *value;
g_return_val_if_fail (secrets != NULL, FALSE);
/* Make sure the items are valid */
g_hash_table_iter_init (&iter, secrets);
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &value)) {
if (!name || !strlen (name)) {
g_set_error_literal (error, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"Secret name was empty");
return FALSE;
}
if (!value || !strlen (value)) {
g_set_error (error, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"Secret %s value was empty", name);
return FALSE;
}
}
g_hash_table_insert (priv->secrets, g_strdup (key), str);
/* Now add the items to the settings' secrets list */
g_hash_table_iter_init (&iter, secrets);
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &value))
g_hash_table_insert (priv->secrets, g_strdup (name), g_strdup (value));
return TRUE;
}
static gboolean
update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
{
gboolean success = FALSE;
g_return_val_if_fail (key != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
if (G_VALUE_HOLDS_STRING (value)) {
/* Passing the string properties individually isn't correct, and won't
* produce the correct result, but for some reason that's how it used
* to be done. So even though it's not correct, keep the code around
* for compatibility's sake.
*/
success = update_secret_string (setting, key, g_value_get_string (value), error);
} else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_MAP_OF_STRING)) {
if (strcmp (key, NM_SETTING_VPN_SECRETS) != 0) {
g_set_error (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_NOT_SECRET,
"Property %s not a secret property", key);
} else
success = update_secret_hash (setting, g_value_get_boxed (value), error);
} else
g_set_error_literal (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, key);
return success;
}
static gboolean
get_secret_flags (NMSetting *setting,
const char *secret_name,
......
......@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 - 2010 Red Hat, Inc.
* Copyright (C) 2008 - 2011 Red Hat, Inc.
*
*/
......@@ -131,6 +131,65 @@ test_setting_vpn_items (void)
g_object_unref (s_vpn);
}
static void
test_setting_vpn_update_secrets (void)
{
NMConnection *connection;
NMSettingVPN *s_vpn;
GHashTable *settings, *vpn, *secrets;
GValue val = { 0 };
gboolean success;
GError *error = NULL;
const char *tmp;
const char *key1 = "foobar";
const char *key2 = "blahblah";
const char *val1 = "value1";
const char *val2 = "value2";
connection = nm_connection_new ();
ASSERT (connection != NULL,
"vpn-update-secrets",
"error creating connection");
s_vpn = (NMSettingVPN *) nm_setting_vpn_new ();
ASSERT (s_vpn != NULL,
"vpn-update-secrets",
"error creating vpn setting");
nm_connection_add_setting (connection, NM_SETTING (s_vpn));
settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_destroy);
vpn = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_value_unset);
g_hash_table_insert (settings, NM_SETTING_VPN_SETTING_NAME, vpn);
secrets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
g_value_init (&val, DBUS_TYPE_G_MAP_OF_STRING);
g_value_take_boxed (&val, secrets);
g_hash_table_insert (vpn, NM_SETTING_VPN_SECRETS, &val);
/* Add some secrets */
g_hash_table_insert (secrets, (char *) key1, (char *) val1);
g_hash_table_insert (secrets, (char *) key2, (char *) val2);
success = nm_connection_update_secrets (connection, NM_SETTING_VPN_SETTING_NAME, settings, &error);
ASSERT (success == TRUE,
"vpn-update-secrets", "failed to update VPN secrets: %s", error->message);
/* Read the secrets back out */
tmp = nm_setting_vpn_get_secret (s_vpn, key1);
ASSERT (tmp != NULL,
"vpn-update-secrets", "unexpected failure getting key #1");
ASSERT (strcmp (tmp, val1) == 0,
"vpn-update-secrets", "unexpected key #1 value");
tmp = nm_setting_vpn_get_secret (s_vpn, key2);
ASSERT (tmp != NULL,
"vpn-update-secrets", "unexpected failure getting key #2");
ASSERT (strcmp (tmp, val2) == 0,
"vpn-update-secrets", "unexpected key #2 value");
g_object_unref (connection);
}
#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
......@@ -617,6 +676,7 @@ int main (int argc, char **argv)
/* The tests */
test_setting_vpn_items ();
test_setting_vpn_update_secrets ();
test_setting_ip6_config_old_address_array ();
test_setting_gsm_apn_spaces ();
test_setting_gsm_apn_bad_chars ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment