[network-manager-netbook/MplPanelClient: 27/44] First-pass at NM 0.8 port (bgo #596755)



commit 4f77d49a98c01f34399ad6fbc121a845dfbacff0
Author: Bastien Nocera <hadess hadess net>
Date:   Tue Sep 29 17:08:49 2009 -0700

    First-pass at NM 0.8 port (bgo #596755)

 configure.in                             |    4 +-
 src/gconf-helpers/Makefile.am            |    7 +-
 src/gconf-helpers/gconf-helpers.c        | 1592 +++++++++++++++++++++---------
 src/gconf-helpers/gconf-helpers.h        |   82 ++-
 src/gconf-helpers/nma-gconf-connection.c |  908 +++++++++++++-----
 src/gconf-helpers/nma-gconf-connection.h |   42 +-
 src/gconf-helpers/nma-gconf-settings.c   |  222 +++--
 src/gconf-helpers/nma-gconf-settings.h   |   52 +-
 src/gconf-helpers/utils.c                |  856 ----------------
 src/gconf-helpers/utils.h                |   56 --
 src/marshallers/nma-marshal.list         |    7 +-
 src/nmn-applet.h                         |    4 +
 src/nmn-device-handler.c                 |   35 +-
 src/nmn-device-handler.h                 |    2 +-
 src/nmn-ethernet-handler.c               |    3 +-
 src/nmn-ethernet-item.c                  |   39 +-
 src/nmn-network-item.c                   |   41 +-
 src/nmn-network-item.h                   |    2 +-
 src/nmn-networks.c                       |    3 +-
 src/nmn-nm-data.c                        |   14 +-
 src/nmn-nm-data.h                        |    8 +-
 src/nmn-serial-handler.c                 |    3 +-
 src/nmn-wifi-handler.c                   |    5 +-
 src/nmn-wifi-item.c                      |   42 +-
 src/nmn-wifi-list.c                      |    4 +-
 src/utils.c                              |  246 ++---
 src/utils.h                              |    8 +-
 src/wireless-dialog.c                    |    1 -
 src/wireless-security/Makefile.am        |    1 +
 src/wireless-security/eap-method-peap.c  |   36 +-
 src/wireless-security/eap-method-tls.c   |  127 ++--
 src/wireless-security/eap-method-ttls.c  |   36 +-
 src/wireless-security/eap-method.c       |   17 +-
 src/wireless-security/eap-method.h       |    3 +-
 34 files changed, 2428 insertions(+), 2080 deletions(-)
---
diff --git a/configure.in b/configure.in
index 4987201..fe14a1c 100644
--- a/configure.in
+++ b/configure.in
@@ -22,7 +22,9 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package])
 IT_PROG_INTLTOOL([0.35.0])
 AM_GLIB_GNU_GETTEXT
 
-PKG_CHECK_MODULES(NMN, dbus-glib-1 >= 0.75 gtk+-2.0 gconf-2.0 gnome-keyring-1 libnm-util libnm_glib mobile-broadband-provider-info moblin-panel-gtk nbtk-gtk-1.0)
+NM_REQUIRED=0.7.996
+
+PKG_CHECK_MODULES(NMN, dbus-glib-1 >= 0.75 gtk+-2.0 gconf-2.0 gnome-keyring-1 libnm-util >= $NM_REQUIRED libnm-glib >= $NM_REQUIRED mobile-broadband-provider-info moblin-panel nbtk-gtk-1.2)
 
 GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
 AC_SUBST(GLIB_GENMARSHAL)
diff --git a/src/gconf-helpers/Makefile.am b/src/gconf-helpers/Makefile.am
index a840abf..0344b34 100644
--- a/src/gconf-helpers/Makefile.am
+++ b/src/gconf-helpers/Makefile.am
@@ -3,15 +3,16 @@ noinst_LTLIBRARIES = libgconf-helpers.la
 libgconf_helpers_la_SOURCES =	\
 	gconf-helpers.h		\
 	gconf-helpers.c		\
+	gconf-upgrade.h		\
+	gconf-upgrade.c		\
 	nma-gconf-connection.h	\
 	nma-gconf-connection.c	\
 	nma-gconf-settings.h	\
-	nma-gconf-settings.c    \
-	utils.h                 \
-	utils.c
+	nma-gconf-settings.c
 
 libgconf_helpers_la_CPPFLAGS = \
 	$(NMN_CFLAGS) \
+	-I${top_builddir}/src/ \
 	-I${top_builddir}/src/marshallers
 
 libgconf_helpers_la_LIBADD = \
diff --git a/src/gconf-helpers/gconf-helpers.c b/src/gconf-helpers/gconf-helpers.c
index 0449c1b..06b2a55 100644
--- a/src/gconf-helpers/gconf-helpers.c
+++ b/src/gconf-helpers/gconf-helpers.c
@@ -17,25 +17,40 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2005 - 2008 Red Hat, Inc.
+ * (C) Copyright 2005 - 2009 Red Hat, Inc.
  */
 
 #include <string.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <net/ethernet.h>
+#include <netinet/ether.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include <gconf/gconf.h>
 #include <gconf/gconf-client.h>
 #include <glib.h>
 #include <gnome-keyring.h>
 #include <dbus/dbus-glib.h>
+
+#include <nm-setting-bluetooth.h>
 #include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
 #include <nm-setting-8021x.h>
 #include <nm-setting-vpn.h>
 #include <nm-setting-ip4-config.h>
 #include <nm-utils.h>
-#include <nm-settings.h>
+#include <nm-settings-interface.h>
 
 #include "gconf-helpers.h"
+#include "gconf-upgrade.h"
+#include "utils.h"
+#include "nmn-applet.h"
 
 #define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH    (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH))
 #define DBUS_TYPE_G_ARRAY_OF_STRING         (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING))
@@ -46,8 +61,12 @@
 #define DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT   (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT))
 #define DBUS_TYPE_G_MAP_OF_STRING           (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
 #define DBUS_TYPE_G_LIST_OF_STRING          (dbus_g_type_get_collection ("GSList", G_TYPE_STRING))
+#define DBUS_TYPE_G_IP6_ADDRESS             (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
+#define DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS    (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_IP6_ADDRESS))
+#define DBUS_TYPE_G_IP6_ROUTE               (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
+#define DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE      (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_IP6_ROUTE))
 
-const char *applet_8021x_ignore_keys[] = {
+const char *applet_8021x_cert_keys[] = {
 	"ca-cert",
 	"client-cert",
 	"private-key",
@@ -73,7 +92,7 @@ nm_gconf_set_pre_keyring_callback (PreKeyringCallback func, gpointer user_data)
 	pre_keyring_user_data = user_data;
 }
 
-static void
+void
 pre_keyring_callback (void)
 {
 	GnomeKeyringInfo *info = NULL;
@@ -265,6 +284,70 @@ out:
 	return success;
 }
 
+typedef struct {
+	const char *setting_name;
+	const char *key_name;
+} MacAddressKey;
+
+static MacAddressKey mac_keys[] = {
+	{ NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR },
+	{ NM_SETTING_WIRED_SETTING_NAME,     NM_SETTING_WIRED_MAC_ADDRESS },
+	{ NM_SETTING_WIRELESS_SETTING_NAME,  NM_SETTING_WIRELESS_MAC_ADDRESS },
+	{ NULL, NULL }
+};
+
+static gboolean
+nm_gconf_get_mac_address_helper (GConfClient *client,
+                                 const char *path,
+                                 const char *key,
+                                 const char *setting,
+                                 GByteArray **value)
+{
+	char *gc_key;
+	GConfValue *gc_value;
+	gboolean success = FALSE;
+	MacAddressKey *tmp = &mac_keys[0];
+	gboolean found = FALSE;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	/* Match against know setting/key combos that can be MAC addresses */
+	while (tmp->setting_name) {
+		if (!strcmp (tmp->setting_name, setting) && !strcmp (tmp->key_name, key)) {
+			found = TRUE;
+			break;
+		}
+		tmp++;
+	}
+	if (!found)
+		return FALSE;
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!(gc_value = gconf_client_get (client, gc_key, NULL)))
+		goto out;
+
+	if (gc_value && (gc_value->type == GCONF_VALUE_STRING)) {
+		const char *str;
+		struct ether_addr *addr;
+
+		str = gconf_value_get_string (gc_value);
+		addr = ether_aton (str);
+		if (addr) {
+			*value = g_byte_array_sized_new (ETH_ALEN);
+			g_byte_array_append (*value, (const guint8 *) addr->ether_addr_octet, ETH_ALEN);
+			success = TRUE;
+		}
+	}
+
+out:
+	if (gc_value)
+		gconf_value_free (gc_value);
+	g_free (gc_key);
+	return success;
+}
+
 gboolean
 nm_gconf_get_bytearray_helper (GConfClient *client,
                                const char *path,
@@ -436,7 +519,7 @@ nm_gconf_get_valuehash_helper (GConfClient *client,
 		gc_key += prefix_len + 1; /* get rid of the full path */
 
 		add_property (*value, gc_key, gconf_entry_get_value (entry));
-		gconf_entry_free (entry);
+		gconf_entry_unref (entry);
 	}
 
 	g_slist_free (gconf_entries);
@@ -491,7 +574,7 @@ nm_gconf_get_stringhash_helper (GConfClient *client,
 					g_hash_table_insert (*value, gconf_unescape_key (gc_key, -1), g_strdup (gc_str));
 			}
 		}
-		gconf_entry_free (entry);
+		gconf_entry_unref (entry);
 	}
 
 	g_slist_free (gconf_entries);
@@ -560,6 +643,254 @@ out:
 }
 
 gboolean
+nm_gconf_get_ip6dns_array_helper (GConfClient *client,
+								  const char *path,
+								  const char *key,
+								  const char *setting,
+								  GPtrArray **value)
+{
+	char *gc_key;
+	GConfValue *gc_value = NULL;
+	GPtrArray *array;
+	gboolean success = FALSE;
+	GSList *values, *iter;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!(gc_value = gconf_client_get (client, gc_key, NULL)))
+		goto out;
+
+	if (   (gc_value->type != GCONF_VALUE_LIST)
+	    || (gconf_value_get_list_type (gc_value) != GCONF_VALUE_STRING))
+		goto out;
+
+	values = gconf_value_get_list (gc_value);
+	array = g_ptr_array_sized_new (1);
+	for (iter = values; iter; iter = g_slist_next (iter)) {
+		const char *straddr = gconf_value_get_string ((GConfValue *) iter->data);
+		struct in6_addr rawaddr;
+		GByteArray *ba;
+
+		if (inet_pton (AF_INET6, straddr, &rawaddr) <= 0) {
+			g_warning ("%s: %s contained bad address: %s",
+					   __func__, gc_key, straddr);
+			continue;
+		}
+
+		ba = g_byte_array_new ();
+		g_byte_array_append (ba, (guchar *)&rawaddr, sizeof (rawaddr));
+
+		g_ptr_array_add (array, ba);
+	}
+
+	*value = array;
+	success = TRUE;
+
+out:
+	if (gc_value)
+		gconf_value_free (gc_value);
+	g_free (gc_key);
+	return success;
+}
+
+gboolean
+nm_gconf_get_ip6addr_array_helper (GConfClient *client,
+								   const char *path,
+								   const char *key,
+								   const char *setting,
+								   GPtrArray **value)
+{
+	char *gc_key;
+	GConfValue *gc_value = NULL;
+	GPtrArray *array;
+	gboolean success = FALSE;
+	GSList *values, *iter;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!(gc_value = gconf_client_get (client, gc_key, NULL)))
+		goto out;
+
+	if (   (gc_value->type != GCONF_VALUE_LIST)
+	    || (gconf_value_get_list_type (gc_value) != GCONF_VALUE_STRING))
+		goto out;
+
+	values = gconf_value_get_list (gc_value);
+	array = g_ptr_array_sized_new (1);
+	for (iter = values; iter; iter = g_slist_next (iter)) {
+		const char *addr_prefix = gconf_value_get_string ((GConfValue *) iter->data);
+		char *addr, *p;
+		guint prefix;
+		struct in6_addr rawaddr;
+		GValueArray *valarr;
+		GValue element = {0, };
+		GByteArray *ba;
+
+		addr = g_strdup (addr_prefix);
+		p = strchr (addr, '/');
+		if (!p) {
+			g_warning ("%s: %s contained bad address/prefix: %s",
+					   __func__, gc_key, addr_prefix);
+			g_free (addr);
+			continue;
+		}
+		*p++ = '\0';
+		prefix = strtoul (p, NULL, 10);
+
+		if (inet_pton (AF_INET6, addr, &rawaddr) <= 0 && prefix > 128) {
+			g_warning ("%s: %s contained bad address: %s",
+					   __func__, gc_key, addr_prefix);
+			g_free (addr);
+			continue;
+		}
+		g_free (addr);
+
+		valarr = g_value_array_new (2);
+
+		g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+		ba = g_byte_array_new ();
+		g_byte_array_append (ba, (guint8 *) &rawaddr, 16);
+		g_value_take_boxed (&element, ba);
+		g_value_array_append (valarr, &element);
+		g_value_unset (&element);
+
+		g_value_init (&element, G_TYPE_UINT);
+		g_value_set_uint (&element, prefix);
+		g_value_array_append (valarr, &element);
+		g_value_unset (&element);
+
+		g_ptr_array_add (array, valarr);
+	}
+
+	*value = array;
+	success = TRUE;
+
+out:
+	if (gc_value)
+		gconf_value_free (gc_value);
+	g_free (gc_key);
+	return success;
+}
+
+gboolean
+nm_gconf_get_ip6route_array_helper (GConfClient *client,
+									const char *path,
+									const char *key,
+									const char *setting,
+									GPtrArray **value)
+{
+	char *gc_key;
+	GConfValue *gc_value = NULL;
+	GPtrArray *array;
+	gboolean success = FALSE;
+	GSList *values, *iter;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!(gc_value = gconf_client_get (client, gc_key, NULL)))
+		goto out;
+
+	if (   (gc_value->type != GCONF_VALUE_LIST)
+	    || (gconf_value_get_list_type (gc_value) != GCONF_VALUE_STRING))
+		goto out;
+
+	values = gconf_value_get_list (gc_value);
+	array = g_ptr_array_sized_new (1);
+	for (iter = values; iter; iter = g_slist_next (iter)) {
+		const char *route_str = gconf_value_get_string ((GConfValue *) iter->data);
+		char **parts, *addr, *p;
+		guint prefix, metric;
+		struct in6_addr rawaddr;
+		GValueArray *valarr;
+		GValue element = {0, };
+		GByteArray *dest, *next_hop;
+
+		parts = g_strsplit (route_str, ",", -1);
+		if (g_strv_length (parts) != 3) {
+			g_warning ("%s: %s contained bad route: %s",
+					   __func__, gc_key, route_str);
+			g_strfreev (parts);
+			continue;
+		}
+
+		addr = parts[0];
+		p = strchr (addr, '/');
+		if (!p) {
+			g_warning ("%s: %s contained bad address/prefix: %s",
+					   __func__, gc_key, addr);
+			g_strfreev (parts);
+			continue;
+		}
+		*p++ = '\0';
+		prefix = strtoul (p, NULL, 10);
+
+		if (inet_pton (AF_INET6, addr, &rawaddr) <= 0 && prefix > 128) {
+			g_warning ("%s: %s contained bad address: %s",
+					   __func__, gc_key, addr);
+			g_strfreev (parts);
+			continue;
+		}
+		dest = g_byte_array_new ();
+		g_byte_array_append (dest, (guint8 *) &rawaddr, 16);
+
+		if (inet_pton (AF_INET6, parts[1], &rawaddr) <= 0 && prefix > 128) {
+			g_warning ("%s: %s contained bad address: %s",
+					   __func__, gc_key, addr);
+			g_byte_array_free (dest, TRUE);
+			g_strfreev (parts);
+			continue;
+		}
+		next_hop = g_byte_array_new ();
+		g_byte_array_append (next_hop, (guint8 *) &rawaddr, 16);
+
+		metric = strtoul (parts[2], NULL, 10);
+
+		valarr = g_value_array_new (4);
+
+		g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+		g_value_take_boxed (&element, dest);
+		g_value_array_append (valarr, &element);
+		g_value_unset (&element);
+
+		g_value_init (&element, G_TYPE_UINT);
+		g_value_set_uint (&element, prefix);
+		g_value_array_append (valarr, &element);
+		g_value_unset (&element);
+
+		g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+		g_value_take_boxed (&element, next_hop);
+		g_value_array_append (valarr, &element);
+		g_value_unset (&element);
+
+		g_value_init (&element, G_TYPE_UINT);
+		g_value_set_uint (&element, metric);
+		g_value_array_append (valarr, &element);
+		g_value_unset (&element);
+
+		g_ptr_array_add (array, valarr);
+		g_strfreev (parts);
+	}
+
+	*value = array;
+	success = TRUE;
+
+out:
+	if (gc_value)
+		gconf_value_free (gc_value);
+	g_free (gc_key);
+	return success;
+}
+
+gboolean
 nm_gconf_set_int_helper (GConfClient *client,
                          const char *path,
                          const char *key,
@@ -675,6 +1006,51 @@ nm_gconf_set_stringlist_helper (GConfClient *client,
 	return TRUE;
 }
 
+static gboolean
+nm_gconf_set_mac_address_helper (GConfClient *client,
+                                 const char *path,
+                                 const char *key,
+                                 const char *setting,
+                                 GByteArray *value)
+{
+	char *gc_key;
+	MacAddressKey *tmp = &mac_keys[0];
+	gboolean found = FALSE;
+	char *str;
+
+	g_return_val_if_fail (path != NULL, FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+
+	/* Match against know setting/key combos that can be MAC addresses */
+	while (tmp->setting_name) {
+		if (!strcmp (tmp->setting_name, setting) && !strcmp (tmp->key_name, key)) {
+			found = TRUE;
+			break;
+		}
+		tmp++;
+	}
+	if (!found || !value)
+		return FALSE;
+
+	g_return_val_if_fail (value->len == ETH_ALEN, FALSE);
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!gc_key) {
+		g_warning ("Not enough memory to create gconf path");
+		return FALSE;
+	}
+
+	str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+	                       value->data[0], value->data[1], value->data[2],
+	                       value->data[3], value->data[4], value->data[5]);
+	gconf_client_set_string (client, gc_key, str, NULL);
+	g_free (str);
+
+	g_free (gc_key);
+	return TRUE;
+}
+
 gboolean
 nm_gconf_set_bytearray_helper (GConfClient *client,
                                const char *path,
@@ -864,7 +1240,7 @@ nm_gconf_set_stringhash_helper (GConfClient *client,
 		    && strcmp ((char *) basename, NM_SETTING_VPN_SERVICE_TYPE)
 			&& strcmp ((char *) basename, NM_SETTING_VPN_USER_NAME))
 			gconf_client_unset (client, entry->key, NULL);
-		gconf_entry_free (entry);
+		gconf_entry_unref (entry);
 		g_free (basename);
 	}
 	g_slist_free (existing);
@@ -926,10 +1302,239 @@ out:
 	return success;
 }
 
+gboolean
+nm_gconf_set_ip6dns_array_helper (GConfClient *client,
+								  const char *path,
+								  const char *key,
+								  const char *setting,
+								  GPtrArray *value)
+{
+	char *gc_key;
+	int i;
+	GSList *list = NULL, *l;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+
+	if (!value)
+		return TRUE;
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!gc_key) {
+		g_warning ("Not enough memory to create gconf path");
+		return FALSE;
+	}
+
+	for (i = 0; i < value->len; i++) {
+		GByteArray *ba = g_ptr_array_index (value, i);
+		char addr[INET6_ADDRSTRLEN];
+
+		if (!inet_ntop (AF_INET6, ba->data, addr, sizeof (addr))) {
+			g_warning ("%s: invalid IPv6 DNS server address!", __func__);
+			goto out;
+		}
+
+		list = g_slist_append (list, g_strdup (addr));
+	}
+
+	gconf_client_set_list (client, gc_key, GCONF_VALUE_STRING, list, NULL);
+	success = TRUE;
+
+out:
+	for (l = list; l; l = l->next)
+		g_free (l->data);
+	g_slist_free (list);
+	g_free (gc_key);
+	return success;
+}
+
+gboolean
+nm_gconf_set_ip6addr_array_helper (GConfClient *client,
+								   const char *path,
+								   const char *key,
+								   const char *setting,
+								   GPtrArray *value)
+{
+	char *gc_key;
+	int i;
+	GSList *list = NULL, *l;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+
+	if (!value)
+		return TRUE;
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!gc_key) {
+		g_warning ("Not enough memory to create gconf path");
+		return FALSE;
+	}
+
+	for (i = 0; i < value->len; i++) {
+		GValueArray *elements = (GValueArray *) g_ptr_array_index (value, i);
+		GValue *tmp;
+		GByteArray *ba;
+		guint prefix;
+		char addr[INET6_ADDRSTRLEN];
+
+		if (   (elements->n_values != 2)
+		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
+		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)) {
+			g_warning ("%s: invalid IPv6 address!", __func__);
+			goto out;
+		}
+
+		tmp = g_value_array_get_nth (elements, 0);
+		ba = g_value_get_boxed (tmp);
+		tmp = g_value_array_get_nth (elements, 1);
+		prefix = g_value_get_uint (tmp);
+		if (prefix > 128) {
+			g_warning ("%s: invalid IPv6 address prefix %u", __func__, prefix);
+			goto out;
+		}
+
+		if (!inet_ntop (AF_INET6, ba->data, addr, sizeof (addr))) {
+			g_warning ("%s: invalid IPv6 address!", __func__);
+			goto out;
+		}
+
+		list = g_slist_append (list, g_strdup_printf ("%s/%u", addr, prefix));
+	}
+
+	gconf_client_set_list (client, gc_key, GCONF_VALUE_STRING, list, NULL);
+	success = TRUE;
+
+out:
+	for (l = list; l; l = l->next)
+		g_free (l->data);
+	g_slist_free (list);
+	g_free (gc_key);
+	return success;
+}
+
+gboolean
+nm_gconf_set_ip6route_array_helper (GConfClient *client,
+									const char *path,
+									const char *key,
+									const char *setting,
+									GPtrArray *value)
+{
+	char *gc_key;
+	int i;
+	GSList *list = NULL, *l;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+
+	if (!value)
+		return TRUE;
+
+	gc_key = g_strdup_printf ("%s/%s/%s", path, setting, key);
+	if (!gc_key) {
+		g_warning ("Not enough memory to create gconf path");
+		return FALSE;
+	}
+
+	for (i = 0; i < value->len; i++) {
+		GValueArray *elements = (GValueArray *) g_ptr_array_index (value, i);
+		GValue *tmp;
+		GByteArray *ba;
+		guint prefix, metric;
+		char dest[INET6_ADDRSTRLEN], next_hop[INET6_ADDRSTRLEN];
+
+		if (   (elements->n_values != 4)
+		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
+		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)
+		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)
+		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 3)) != G_TYPE_UINT))
+ {
+			g_warning ("%s: invalid IPv6 route!", __func__);
+			goto out;
+		}
+
+		tmp = g_value_array_get_nth (elements, 0);
+		ba = g_value_get_boxed (tmp);
+		if (!inet_ntop (AF_INET6, ba->data, dest, sizeof (dest))) {
+			g_warning ("%s: invalid IPv6 dest address!", __func__);
+			goto out;
+		}
+		tmp = g_value_array_get_nth (elements, 1);
+		prefix = g_value_get_uint (tmp);
+		if (prefix > 128) {
+			g_warning ("%s: invalid IPv6 dest prefix %u", __func__, prefix);
+			goto out;
+		}
+		tmp = g_value_array_get_nth (elements, 2);
+		ba = g_value_get_boxed (tmp);
+		if (!inet_ntop (AF_INET6, ba->data, next_hop, sizeof (next_hop))) {
+			g_warning ("%s: invalid IPv6 next_hop address!", __func__);
+			goto out;
+		}
+		tmp = g_value_array_get_nth (elements, 3);
+		metric = g_value_get_uint (tmp);
+
+		list = g_slist_append (list,
+							   g_strdup_printf ("%s/%u,%s,%u", dest, prefix,
+												next_hop, metric));
+	}
+
+	gconf_client_set_list (client, gc_key, GCONF_VALUE_STRING, list, NULL);
+	success = TRUE;
+
+out:
+	for (l = list; l; l = l->next)
+		g_free (l->data);
+	g_slist_free (list);
+	g_free (gc_key);
+	return success;
+}
+
 GSList *
 nm_gconf_get_all_connections (GConfClient *client)
 {
-	return gconf_client_all_dirs (client, GCONF_PATH_CONNECTIONS, NULL);
+	GSList *connections;
+	guint32 stamp = 0;
+	GError *error = NULL;
+
+	stamp = (guint32) gconf_client_get_int (client, APPLET_PREFS_STAMP, &error);
+	if (error) {
+		g_error_free (error);
+		stamp = 0;
+	}
+
+	nm_gconf_migrate_0_7_connection_uuid (client);
+	nm_gconf_migrate_0_7_keyring_items (client);
+	nm_gconf_migrate_0_7_wireless_security (client);
+	nm_gconf_migrate_0_7_netmask_to_prefix (client);
+	nm_gconf_migrate_0_7_ip4_method (client);
+	nm_gconf_migrate_0_7_ignore_dhcp_dns (client);
+	nm_gconf_migrate_0_7_vpn_routes (client);
+	nm_gconf_migrate_0_7_vpn_properties (client);
+	nm_gconf_migrate_0_7_openvpn_properties (client);
+
+	if (stamp < 1) {
+		nm_gconf_migrate_0_7_vpn_never_default (client);
+		nm_gconf_migrate_0_7_autoconnect_default (client);
+	}
+
+	nm_gconf_migrate_0_7_ca_cert_ignore (client);
+	nm_gconf_migrate_0_7_certs (client);
+
+	connections = gconf_client_all_dirs (client, GCONF_PATH_CONNECTIONS, NULL);
+	if (!connections) {
+		nm_gconf_migrate_0_6_connections (client);
+		connections = gconf_client_all_dirs (client, GCONF_PATH_CONNECTIONS, NULL);
+	}
+
+	/* Update the applet GConf stamp */
+	if (stamp != APPLET_CURRENT_STAMP)
+		gconf_client_set_int (client, APPLET_PREFS_STAMP, APPLET_CURRENT_STAMP, NULL);
+
+	return connections;
 }
 
 static gboolean
@@ -950,6 +1555,18 @@ free_one_addr (gpointer data)
 	g_array_free ((GArray *) data, TRUE);
 }
 
+static void
+free_one_bytearray (gpointer data)
+{
+	g_byte_array_free (data, TRUE);
+}
+
+static void
+free_one_struct (gpointer data)
+{
+	g_value_array_free (data);
+}
+
 typedef struct ReadFromGConfInfo {
 	NMConnection *connection;
 	GConfClient *client;
@@ -957,6 +1574,8 @@ typedef struct ReadFromGConfInfo {
 	guint32 dir_len;
 } ReadFromGConfInfo;
 
+#define FILE_TAG "file://"
+
 static void
 read_one_setting_value_from_gconf (NMSetting *setting,
                                    const char *key,
@@ -975,7 +1594,8 @@ read_one_setting_value_from_gconf (NMSetting *setting,
 		return;
 
 	/* Secrets don't get stored in GConf */
-	if (flags & NM_SETTING_PARAM_SECRET)
+	if (   (flags & NM_SETTING_PARAM_SECRET)
+	    && !(NM_IS_SETTING_802_1X (setting) && string_in_list (key, applet_8021x_cert_keys)))
 		return;
 
 	/* Don't read the NMSettingConnection object's 'read-only' property */
@@ -988,15 +1608,32 @@ read_one_setting_value_from_gconf (NMSetting *setting,
 	/* Some keys (like certs) aren't read directly from GConf but are handled
 	 * separately.
 	 */
-	if (NM_IS_SETTING_802_1X (setting)) {
-		if (string_in_list (key, applet_8021x_ignore_keys))
-			return;
-	} else if (NM_IS_SETTING_VPN (setting)) {
+	/* Some VPN keys are ignored */
+	if (NM_IS_SETTING_VPN (setting)) {
 		if (string_in_list (key, vpn_ignore_keys))
 			return;
 	}
 
-	if (type == G_TYPE_STRING) {
+	if (   NM_IS_SETTING_802_1X (setting)
+	    && string_in_list (key, applet_8021x_cert_keys)
+	    && (type == DBUS_TYPE_G_UCHAR_ARRAY)) {
+	    char *str_val = NULL;
+
+		/* Certificate/key paths are stored as paths in GConf, but we need to
+		 * take that path and use the special functions to set them on the
+		 * setting.
+		 */
+		if (nm_gconf_get_string_helper (info->client, info->dir, key, setting_name, &str_val)) {
+			GByteArray *ba_val;
+
+			ba_val = g_byte_array_sized_new (strlen (FILE_TAG) + strlen (str_val) + 1);
+			g_byte_array_append (ba_val, (const guint8 *) FILE_TAG, strlen (FILE_TAG));
+			g_byte_array_append (ba_val, (const guint8 *) str_val, strlen (str_val) + 1);  /* +1 for the trailing NULL */
+			g_object_set (setting, key, ba_val, NULL);
+			g_byte_array_free (ba_val, TRUE);
+			g_free (str_val);
+		}
+	} else if (type == G_TYPE_STRING) {
 		char *str_val = NULL;
 
 		if (nm_gconf_get_string_helper (info->client, info->dir, key, setting_name, &str_val)) {
@@ -1044,8 +1681,13 @@ read_one_setting_value_from_gconf (NMSetting *setting,
 		}
 	} else if (type == DBUS_TYPE_G_UCHAR_ARRAY) {
 		GByteArray *ba_val = NULL;
+		gboolean success = FALSE;
+
+		success = nm_gconf_get_mac_address_helper (info->client, info->dir, key, setting_name, &ba_val);
+		if (!success)
+			success = nm_gconf_get_bytearray_helper (info->client, info->dir, key, setting_name, &ba_val);
 
-		if (nm_gconf_get_bytearray_helper (info->client, info->dir, key, setting_name, &ba_val)) {
+		if (success) {
 			g_object_set (setting, key, ba_val, NULL);
 			g_byte_array_free (ba_val, TRUE);
 		}
@@ -1094,62 +1736,33 @@ read_one_setting_value_from_gconf (NMSetting *setting,
 			g_ptr_array_foreach (pa_val, (GFunc) free_one_addr, NULL);
 			g_ptr_array_free (pa_val, TRUE);
 		}
-	} else {
-		g_warning ("Unhandled setting property type (read): '%s/%s' : '%s'",
-				 setting_name, key, G_VALUE_TYPE_NAME (value));
-	}
-}
-
-static void
-read_one_cert (ReadFromGConfInfo *info,
-               const char *setting_name,
-               const char *key)
-{
-	char *value = NULL;
-
-	if (!nm_gconf_get_string_helper (info->client, info->dir, key, setting_name, &value))
-		return;
-
-	g_object_set_data_full (G_OBJECT (info->connection),
-	                        key, value,
-	                        (GDestroyNotify) g_free);
-}
+	} else if (type == DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR) {
+		GPtrArray *pa_val = NULL;
 
-static void
-read_applet_private_values_from_gconf (NMSetting *setting,
-                                       ReadFromGConfInfo *info)
-{
-	if (NM_IS_SETTING_802_1X (setting)) {
-		const char *setting_name = nm_setting_get_name (setting);
-		gboolean value;
-
-		if (nm_gconf_get_bool_helper (info->client, info->dir,
-		                              NMA_CA_CERT_IGNORE_TAG,
-		                              setting_name, &value)) {
-			g_object_set_data (G_OBJECT (info->connection),
-			                   NMA_CA_CERT_IGNORE_TAG,
-			                   GUINT_TO_POINTER (value));
+		if (nm_gconf_get_ip6dns_array_helper (info->client, info->dir, key, setting_name, &pa_val)) {
+			g_object_set (setting, key, pa_val, NULL);
+			g_ptr_array_foreach (pa_val, (GFunc) free_one_bytearray, NULL);
+			g_ptr_array_free (pa_val, TRUE);
 		}
+	} else if (type == DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS) {
+		GPtrArray *pa_val = NULL;
 
-		if (nm_gconf_get_bool_helper (info->client, info->dir,
-		                              NMA_PHASE2_CA_CERT_IGNORE_TAG,
-		                              setting_name, &value)) {
-			g_object_set_data (G_OBJECT (info->connection),
-			                   NMA_PHASE2_CA_CERT_IGNORE_TAG,
-			                   GUINT_TO_POINTER (value));
+		if (nm_gconf_get_ip6addr_array_helper (info->client, info->dir, key, setting_name, &pa_val)) {
+			g_object_set (setting, key, pa_val, NULL);
+			g_ptr_array_foreach (pa_val, (GFunc) free_one_struct, NULL);
+			g_ptr_array_free (pa_val, TRUE);
 		}
+	} else if (type == DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE) {
+		GPtrArray *pa_val = NULL;
 
-		/* Binary certificate and key data doesn't get stored in GConf.  Instead,
-		 * the path to the certificate gets stored in a special key and the
-		 * certificate is read and stuffed into the setting right before
-		 * the connection is sent to NM
-		 */
-		read_one_cert (info, setting_name, NMA_PATH_CA_CERT_TAG);
-		read_one_cert (info, setting_name, NMA_PATH_CLIENT_CERT_TAG);
-		read_one_cert (info, setting_name, NMA_PATH_PRIVATE_KEY_TAG);
-		read_one_cert (info, setting_name, NMA_PATH_PHASE2_CA_CERT_TAG);
-		read_one_cert (info, setting_name, NMA_PATH_PHASE2_CLIENT_CERT_TAG);
-		read_one_cert (info, setting_name, NMA_PATH_PHASE2_PRIVATE_KEY_TAG);
+		if (nm_gconf_get_ip6route_array_helper (info->client, info->dir, key, setting_name, &pa_val)) {
+			g_object_set (setting, key, pa_val, NULL);
+			g_ptr_array_foreach (pa_val, (GFunc) free_one_struct, NULL);
+			g_ptr_array_free (pa_val, TRUE);
+		}
+	} else {
+		g_warning ("Unhandled setting property type (read): '%s/%s' : '%s'",
+				 setting_name, key, G_VALUE_TYPE_NAME (value));
 	}
 }
 
@@ -1168,7 +1781,6 @@ read_one_setting (gpointer data, gpointer user_data)
 		nm_setting_enumerate_values (setting,
 							    read_one_setting_value_from_gconf,
 							    info);
-		read_applet_private_values_from_gconf (setting, info);
 		nm_connection_add_setting (info->connection, setting);
 	}
 
@@ -1274,23 +1886,25 @@ write_one_secret_to_keyring (NMSetting *setting,
 	const char *secret;
 	const char *setting_name;
 
-	if (!(flags & NM_SETTING_PARAM_SECRET))
+	/* non-secrets and private key paths don't get stored in the keyring */
+	if (   !(flags & NM_SETTING_PARAM_SECRET)
+	    || (NM_IS_SETTING_802_1X (setting) && string_in_list (key, applet_8021x_cert_keys)))
 		return;
 
 	setting_name = nm_setting_get_name (setting);
 
-	if (type != G_TYPE_STRING) {
-		g_warning ("Unhandled setting secret type (write) '%s/%s' : '%s'", 
-				 setting_name, key, g_type_name (type));
-		return;
-	}
-
 	/* VPN secrets are handled by the VPN plugins */
 	if (   (type == DBUS_TYPE_G_MAP_OF_STRING)
 	    && NM_IS_SETTING_VPN (setting)
 	    && !strcmp (key, NM_SETTING_VPN_SECRETS))
 		return;
 
+	if (type != G_TYPE_STRING) {
+		g_warning ("Unhandled setting secret type (write) '%s/%s' : '%s'", 
+				 setting_name, key, g_type_name (type));
+		return;
+	}
+
 	secret = g_value_get_string (value);
 	if (secret && strlen (secret)) {
 		nm_gconf_add_keyring_item (info->connection_uuid,
@@ -1301,6 +1915,391 @@ write_one_secret_to_keyring (NMSetting *setting,
 	}
 }
 
+static gboolean
+write_secret_file (const char *path,
+                   const char *data,
+                   gsize len,
+                   GError **error)
+{
+	char *tmppath;
+	int fd = -1, written;
+	gboolean success = FALSE;
+
+	tmppath = g_malloc0 (strlen (path) + 10);
+	if (!tmppath) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+		             "Could not allocate memory for temporary file for '%s'",
+		             path);
+		return FALSE;
+	}
+
+	memcpy (tmppath, path, strlen (path));
+	strcat (tmppath, ".XXXXXX");
+
+	errno = 0;
+	fd = mkstemp (tmppath);
+	if (fd < 0) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+		             "Could not create temporary file for '%s': %d",
+		             path, errno);
+		goto out;
+	}
+
+	/* Only readable by root */
+	errno = 0;
+	if (fchmod (fd, S_IRUSR | S_IWUSR)) {
+		close (fd);
+		unlink (tmppath);
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+		             "Could not set permissions for temporary file '%s': %d",
+		             path, errno);
+		goto out;
+	}
+
+	errno = 0;
+	written = write (fd, data, len);
+	if (written != len) {
+		close (fd);
+		unlink (tmppath);
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+		             "Could not write temporary file for '%s': %d",
+		             path, errno);
+		goto out;
+	}
+	close (fd);
+
+	/* Try to rename */
+	errno = 0;
+	if (rename (tmppath, path)) {
+		unlink (tmppath);
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+		             "Could not rename temporary file to '%s': %d",
+		             path, errno);
+		goto out;
+	}
+	success = TRUE;
+
+out:
+	return success;
+}
+
+typedef NMSetting8021xCKScheme (*SchemeFunc)  (NMSetting8021x *setting);
+typedef const char *           (*PathFunc)    (NMSetting8021x *setting);
+typedef const GByteArray *     (*BlobFunc)    (NMSetting8021x *setting);
+typedef NMSetting8021xCKFormat (*FormatFunc)  (NMSetting8021x *setting);
+typedef const char *           (*PasswordFunc)(NMSetting8021x *setting);
+
+typedef struct ObjectType {
+	const char *setting_key;
+	gboolean p12_type;
+	SchemeFunc scheme_func;
+	PathFunc path_func;
+	BlobFunc blob_func;
+	FormatFunc format_func;
+	PasswordFunc password_func;
+	const char *privkey_password_key;
+	const char *suffix;
+} ObjectType;
+
+static const ObjectType ca_type = {
+	NM_SETTING_802_1X_CA_CERT,
+	FALSE,
+	nm_setting_802_1x_get_ca_cert_scheme,
+	nm_setting_802_1x_get_ca_cert_path,
+	nm_setting_802_1x_get_ca_cert_blob,
+	NULL,
+	NULL,
+	NULL,
+	"ca-cert.der"
+};
+
+static const ObjectType phase2_ca_type = {
+	NM_SETTING_802_1X_PHASE2_CA_CERT,
+	FALSE,
+	nm_setting_802_1x_get_phase2_ca_cert_scheme,
+	nm_setting_802_1x_get_phase2_ca_cert_path,
+	nm_setting_802_1x_get_phase2_ca_cert_blob,
+	NULL,
+	NULL,
+	NULL,
+	"inner-ca-cert.der"
+};
+
+static const ObjectType client_type = {
+	NM_SETTING_802_1X_CLIENT_CERT,
+	FALSE,
+	nm_setting_802_1x_get_client_cert_scheme,
+	nm_setting_802_1x_get_client_cert_path,
+	nm_setting_802_1x_get_client_cert_blob,
+	NULL,
+	NULL,
+	NULL,
+	"client-cert.der"
+};
+
+static const ObjectType phase2_client_type = {
+	NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
+	FALSE,
+	nm_setting_802_1x_get_phase2_client_cert_scheme,
+	nm_setting_802_1x_get_phase2_client_cert_path,
+	nm_setting_802_1x_get_phase2_client_cert_blob,
+	NULL,
+	NULL,
+	NULL,
+	"inner-client-cert.der"
+};
+
+static const ObjectType pk_type = {
+	NM_SETTING_802_1X_PRIVATE_KEY,
+	FALSE,
+	nm_setting_802_1x_get_private_key_scheme,
+	nm_setting_802_1x_get_private_key_path,
+	nm_setting_802_1x_get_private_key_blob,
+	nm_setting_802_1x_get_private_key_format,
+	nm_setting_802_1x_get_private_key_password,
+	NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+	"private-key.pem"
+};
+
+static const ObjectType phase2_pk_type = {
+	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+	FALSE,
+	nm_setting_802_1x_get_phase2_private_key_scheme,
+	nm_setting_802_1x_get_phase2_private_key_path,
+	nm_setting_802_1x_get_phase2_private_key_blob,
+	nm_setting_802_1x_get_phase2_private_key_format,
+	nm_setting_802_1x_get_phase2_private_key_password,
+	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
+	"inner-private-key.pem"
+};
+
+static const ObjectType p12_type = {
+	NM_SETTING_802_1X_PRIVATE_KEY,
+	TRUE,
+	nm_setting_802_1x_get_private_key_scheme,
+	nm_setting_802_1x_get_private_key_path,
+	nm_setting_802_1x_get_private_key_blob,
+	nm_setting_802_1x_get_private_key_format,
+	nm_setting_802_1x_get_private_key_password,
+	NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+	"private-key.p12"
+};
+
+static const ObjectType phase2_p12_type = {
+	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+	TRUE,
+	nm_setting_802_1x_get_phase2_private_key_scheme,
+	nm_setting_802_1x_get_phase2_private_key_path,
+	nm_setting_802_1x_get_phase2_private_key_blob,
+	nm_setting_802_1x_get_phase2_private_key_format,
+	nm_setting_802_1x_get_phase2_private_key_password,
+	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
+	"inner-private-key.p12"
+};
+
+static char *
+generate_cert_path (const char *id, const char *suffix)
+{
+	return g_strdup_printf ("%s/.ssh/%s-%s", g_get_home_dir (), id, suffix);
+}
+
+static gboolean
+write_object (GConfClient *client,
+              const char *dir,
+              const char *id,
+              NMSetting8021x *s_8021x,
+              const GByteArray *override_data,
+              const ObjectType *objtype,
+              GError **error)
+{
+	NMSetting8021xCKScheme scheme;
+	const char *path = NULL;
+	const GByteArray *blob = NULL;
+	const char *setting_name = nm_setting_get_name (NM_SETTING (s_8021x));
+
+	g_return_val_if_fail (objtype != NULL, FALSE);
+
+	if (override_data) {
+		/* if given explicit data to save, always use that instead of asking
+		 * the setting what to do.
+		 */
+		blob = override_data;
+	} else {
+		scheme = (*(objtype->scheme_func))(s_8021x);
+		switch (scheme) {
+		case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+			blob = (*(objtype->blob_func))(s_8021x);
+			break;
+		case NM_SETTING_802_1X_CK_SCHEME_PATH:
+			path = (*(objtype->path_func))(s_8021x);
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* If certificate/private key wasn't sent, the connection may no longer be
+	 * 802.1x and thus we clear out the paths and certs.
+	 */
+	if (!path && !blob) {
+		char *standard_file;
+		int ignored;
+
+		/* Since no cert/private key is now being used, delete any standard file
+		 * that was created for this connection, but leave other files alone.
+		 * Thus, for example, ~/.ssh/My Company Network-ca-cert.der will be
+		 * deleted, but /etc/pki/tls/cert.pem would not.
+		 */
+		standard_file = generate_cert_path (id, objtype->suffix);
+		if (g_file_test (standard_file, G_FILE_TEST_EXISTS))
+			ignored = unlink (standard_file);
+		g_free (standard_file);
+
+		/* Delete the key from GConf */
+		nm_gconf_set_string_helper (client, dir, objtype->setting_key, setting_name, NULL);
+		return TRUE;
+	}
+
+	/* If the object path was specified, prefer that over any raw cert data that
+	 * may have been sent.
+	 */
+	if (path) {
+		nm_gconf_set_string_helper (client, dir, objtype->setting_key, setting_name, path);
+		return TRUE;
+	}
+
+	/* If it's raw certificate data, write the cert data out to the standard file */
+	if (blob) {
+		gboolean success;
+		char *new_file;
+		GError *write_error = NULL;
+
+		new_file = generate_cert_path (id, objtype->suffix);
+		if (!new_file) {
+			g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+			             "Could not create file path for %s / %s",
+			             setting_name, objtype->setting_key);
+			return FALSE;
+		}
+
+		/* Write the raw certificate data out to the standard file so that we
+		 * can use paths from now on instead of pushing around the certificate
+		 * data itself.
+		 */
+		success = write_secret_file (new_file, (const char *) blob->data, blob->len, &write_error);
+		if (success) {
+			nm_gconf_set_string_helper (client, dir, objtype->setting_key, setting_name, new_file);
+			return TRUE;
+		} else {
+			g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+			             "Could not write certificate/key for %s / %s: %s",
+			             setting_name, objtype->setting_key,
+			             (write_error && write_error->message) ? write_error->message : "(unknown)");
+			g_clear_error (&write_error);
+		}
+		g_free (new_file);
+	}
+
+	return FALSE;
+}
+
+static gboolean
+write_one_certificate (GConfClient *client,
+                       const char *dir,
+                       const char *key,
+                       NMSetting8021x *s_8021x,
+                       NMConnection *connection,
+                       GError **error)
+{
+	const char *id;
+	NMSettingConnection *s_con;
+	const ObjectType *cert_objects[] = {
+		&ca_type,
+		&phase2_ca_type,
+		&client_type,
+		&phase2_client_type,
+		&pk_type,
+		&phase2_pk_type,
+		&p12_type,
+		&phase2_p12_type,
+		NULL
+	};
+	const ObjectType **obj = &cert_objects[0];
+	gboolean handled = FALSE, success = FALSE;
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	id = nm_setting_connection_get_id (s_con);
+	g_assert (id);
+
+	while (*obj && !handled) {
+		const GByteArray *blob = NULL;
+		GByteArray *enc_key = NULL;
+
+		if (strcmp (key, (*obj)->setting_key)) {
+			obj++;
+			continue;
+		}
+
+		/* Check for pkcs#12 format private keys; if the current ObjectType
+		 * structure isn't for a pkcs#12 key but the key actually is
+		 * pkcs#12, keep going to get the right pkcs#12 ObjectType.
+		 */
+		if (   (*obj)->format_func
+		    && ((*obj)->format_func (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
+		    && !(*obj)->p12_type) {
+			obj++;
+			continue;
+		}
+
+		if ((*obj)->scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+			blob = (*obj)->blob_func (s_8021x);
+
+		/* Only do the private key re-encrypt dance if we got the raw key data, which
+		 * by definition will be unencrypted.  If we're given a direct path to the
+		 * private key file, it'll be encrypted, so we don't need to re-encrypt.
+		 */
+		if (blob && !(*obj)->p12_type) {
+			const char *password;
+			char *generated_pw;
+
+			/* If the private key is an unencrypted blob, re-encrypt it with a
+			 * random password since we don't store unencrypted private keys on disk.
+			 */
+			password = (*obj)->password_func (s_8021x);
+
+			/* Encrypt the unencrypted private key */
+			enc_key = nm_utils_rsa_key_encrypt (blob, password, &generated_pw, error);
+			if (!enc_key)
+				goto out;
+
+			/* Save any generated private key back into the 802.1x setting so
+			 * it'll get stored when secrets are written to the keyring.
+			 */
+			if (generated_pw) {
+				g_object_set (G_OBJECT (s_8021x), (*obj)->privkey_password_key, generated_pw, NULL);
+				memset (generated_pw, 0, strlen (generated_pw));
+				g_free (generated_pw);
+			}
+		}
+
+		success = write_object (client, dir, id, s_8021x, enc_key ? enc_key : blob, *obj, error);
+		if (enc_key)
+			g_byte_array_free (enc_key, TRUE);
+
+		handled = TRUE;
+	}
+
+	if (!handled) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, 0,
+		             "Unhandled certificate/private-key item '%s'",
+		             key);
+	}
+
+out:
+	return success;
+}
+
 static void
 copy_one_setting_value_to_gconf (NMSetting *setting,
                                  const char *key,
@@ -1313,19 +2312,19 @@ copy_one_setting_value_to_gconf (NMSetting *setting,
 	GType type = G_VALUE_TYPE (value);
 	GParamSpec *pspec;
 
-	/* Some keys (like certs) aren't written directly to GConf but are handled
-	 * separately.
-	 */
-	if (NM_IS_SETTING_802_1X (setting)) {
-		if (string_in_list (key, applet_8021x_ignore_keys))
-			return;
-	} else if (NM_IS_SETTING_VPN (setting)) {
+	/* Some VPN keys are ignored */
+	if (NM_IS_SETTING_VPN (setting)) {
 		if (string_in_list (key, vpn_ignore_keys))
 			return;
 	}
 
-	/* Secrets don't get stored in GConf */
-	if (flags & NM_SETTING_PARAM_SECRET)
+	/* Secrets don't get stored in GConf; but the 802.1x private keys,
+	 * which are marked secret for backwards compat, do get stored in
+	 * GConf because as of NM 0.8, they are just paths and not the decrypted
+	 * private key blobs.
+	 */
+	if (   (flags & NM_SETTING_PARAM_SECRET)
+	    && !(NM_IS_SETTING_802_1X (setting) && string_in_list (key, applet_8021x_cert_keys)))
 		return;
 
 	/* Don't write the NMSettingConnection object's 'read-only' property */
@@ -1349,7 +2348,24 @@ copy_one_setting_value_to_gconf (NMSetting *setting,
 		}
 	}
 
-	if (type == G_TYPE_STRING) {
+	if (   NM_IS_SETTING_802_1X (setting)
+		&& string_in_list (key, applet_8021x_cert_keys)
+		&& (type == DBUS_TYPE_G_UCHAR_ARRAY)) {
+		GError *error = NULL;
+
+		if (!write_one_certificate (info->client,
+		                            info->dir,
+		                            key,
+		                            NM_SETTING_802_1X (setting),
+		                            info->connection,
+		                            &error)) {
+			g_warning ("%s: error saving certificate/private key '%s': (%d) %s",
+			           __func__,
+			           key,
+			           error ? error->code : -1,
+			           error && error->message ? error->message : "(unknown)");
+		}
+	} else if (type == G_TYPE_STRING) {
 		nm_gconf_set_string_helper (info->client, info->dir, key, setting_name, g_value_get_string (value));
 	} else if (type == G_TYPE_UINT) {
 		nm_gconf_set_int_helper (info->client, info->dir,
@@ -1376,9 +2392,10 @@ copy_one_setting_value_to_gconf (NMSetting *setting,
 							key, setting_name,
 							g_value_get_char (value));
 	} else if (type == DBUS_TYPE_G_UCHAR_ARRAY) {
-		nm_gconf_set_bytearray_helper (info->client, info->dir,
-								 key, setting_name,
-								 (GByteArray *) g_value_get_boxed (value));
+		GByteArray *ba_val = (GByteArray *) g_value_get_boxed (value);
+
+		if (!nm_gconf_set_mac_address_helper (info->client, info->dir, key, setting_name, ba_val))
+			nm_gconf_set_bytearray_helper (info->client, info->dir, key, setting_name, ba_val);
 	} else if (type == DBUS_TYPE_G_LIST_OF_STRING) {
 		nm_gconf_set_stringlist_helper (info->client, info->dir,
 								  key, setting_name,
@@ -1408,101 +2425,24 @@ copy_one_setting_value_to_gconf (NMSetting *setting,
 		nm_gconf_set_ip4_helper (info->client, info->dir,
 								  key, setting_name, tuple_len,
 								  (GPtrArray *) g_value_get_boxed (value));
+	} else if (type == DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR) {
+		nm_gconf_set_ip6dns_array_helper (info->client, info->dir,
+										  key, setting_name,
+										  (GPtrArray *) g_value_get_boxed (value));
+	} else if (type == DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS) {
+		nm_gconf_set_ip6addr_array_helper (info->client, info->dir,
+										   key, setting_name,
+										   (GPtrArray *) g_value_get_boxed (value));
+	} else if (type == DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE) {
+		nm_gconf_set_ip6route_array_helper (info->client, info->dir,
+											key, setting_name,
+											(GPtrArray *) g_value_get_boxed (value));
 	} else
 		g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'", 
 				 setting_name, key, g_type_name (type));
 }
 
 static void
-write_ignore_ca_cert_helper (CopyOneSettingValueInfo *info,
-                             const char *tag,
-                             const GByteArray *cert)
-{
-	g_return_if_fail (info != NULL);
-	g_return_if_fail (tag != NULL);
-
-	if (cert) {
-		char *key;
-
-		key = g_strdup_printf ("%s/%s/%s", info->dir, NM_SETTING_802_1X_SETTING_NAME, tag);
-		gconf_client_unset (info->client, key, NULL);
-		g_free (key);
-	} else {
-		if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (info->connection), tag)))
-			nm_gconf_set_bool_helper (info->client, info->dir, tag, NM_SETTING_802_1X_SETTING_NAME, TRUE);
-	}
-}
-
-static void
-write_one_private_string_value (CopyOneSettingValueInfo *info, const char *tag)
-{
-	const char *value;
-
-	g_return_if_fail (info != NULL);
-	g_return_if_fail (tag != NULL);
-
-	value = g_object_get_data (G_OBJECT (info->connection), tag);
-	nm_gconf_set_string_helper (info->client, info->dir, tag,
-						   NM_SETTING_802_1X_SETTING_NAME,
-						   value);
-}
-
-static void
-write_one_password (CopyOneSettingValueInfo *info, const char *tag)
-{
-	const char *value;
-
-	g_return_if_fail (info != NULL);
-	g_return_if_fail (tag != NULL);
-
-	value = g_object_get_data (G_OBJECT (info->connection), tag);
-	if (value) {
-		nm_gconf_add_keyring_item (info->connection_uuid,
-		                           info->connection_name,
-		                           NM_SETTING_802_1X_SETTING_NAME,
-		                           tag,
-		                           value);
-
-		/* Try not to leave the password lying around in memory */
-		g_object_set_data (G_OBJECT (info->connection), tag, NULL);
-	}
-}
-
-static void
-write_applet_private_values_to_gconf (CopyOneSettingValueInfo *info)
-{
-	NMSetting8021x *s_8021x;
-
-	g_return_if_fail (info != NULL);
-
-	/* Handle values private to the applet that are not supposed to
-	 * be sent to NetworkManager.
-	 */
-	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (info->connection, NM_TYPE_SETTING_802_1X));
-	if (s_8021x) {
-		write_ignore_ca_cert_helper (info, NMA_CA_CERT_IGNORE_TAG,
-		                             nm_setting_802_1x_get_ca_cert (s_8021x));
-		write_ignore_ca_cert_helper (info, NMA_PHASE2_CA_CERT_IGNORE_TAG,
-		                             nm_setting_802_1x_get_phase2_ca_cert (s_8021x));
-
-		/* Binary certificate and key data doesn't get stored in GConf.  Instead,
-		 * the path to the certificate gets stored in a special key and the
-		 * certificate is read and stuffed into the setting right before
-		 * the connection is sent to NM
-		 */
-		write_one_private_string_value (info, NMA_PATH_CA_CERT_TAG);
-		write_one_private_string_value (info, NMA_PATH_CLIENT_CERT_TAG);
-		write_one_private_string_value (info, NMA_PATH_PRIVATE_KEY_TAG);
-		write_one_private_string_value (info, NMA_PATH_PHASE2_CA_CERT_TAG);
-		write_one_private_string_value (info, NMA_PATH_PHASE2_CLIENT_CERT_TAG);
-		write_one_private_string_value (info, NMA_PATH_PHASE2_PRIVATE_KEY_TAG);
-
-		write_one_password (info, NMA_PRIVATE_KEY_PASSWORD_TAG);
-		write_one_password (info, NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG);
-	}
-}
-
-static void
 remove_leftovers (CopyOneSettingValueInfo *info)
 {
 	GSList *dirs;
@@ -1533,6 +2473,7 @@ nm_gconf_write_connection (NMConnection *connection,
 {
 	NMSettingConnection *s_con;
 	CopyOneSettingValueInfo info;
+	gboolean ignore;
 
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 	g_return_if_fail (client != NULL);
@@ -1557,289 +2498,58 @@ nm_gconf_write_connection (NMConnection *connection,
 	                                      write_one_secret_to_keyring,
 	                                      &info);
 
-	write_applet_private_values_to_gconf (&info);
-}
-
-static GValue *
-string_to_gvalue (const char *str)
-{
-	GValue *val;
-
-	val = g_slice_new0 (GValue);
-	g_value_init (val, G_TYPE_STRING);
-	g_value_set_string (val, str);
-
-	return val;
-}
-
-static GValue *
-byte_array_to_gvalue (const GByteArray *array)
-{
-	GValue *val;
-
-	val = g_slice_new0 (GValue);
-	g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY);
-	g_value_set_boxed (val, array);
-
-	return val;
-}
-
-static void
-destroy_gvalue (gpointer data)
-{
-	GValue *value = (GValue *) data;
+	/* Update ignore CA cert status */
+	ignore = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), IGNORE_CA_CERT_TAG));
+	nm_gconf_set_ignore_ca_cert (info.connection_uuid, FALSE, ignore);
 
-	g_value_unset (value);
-	g_slice_free (GValue, value);
+	ignore = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), IGNORE_PHASE2_CA_CERT_TAG));
+	nm_gconf_set_ignore_ca_cert (info.connection_uuid, TRUE, ignore);
 }
 
-static gboolean
-get_one_private_key (NMConnection *connection,
-                     const char *setting_name,
-                     const char *tag,
-                     const char *password,
-                     gboolean include_password,
-                     GHashTable *secrets,
-                     GError **error)
+static char *
+get_ignore_path (const char *uuid, gboolean phase2)
 {
-	NMSettingConnection *s_con;
-	GByteArray *array = NULL;
-	const char *filename = NULL;
-	const char *secret_name;
-	const char *real_password_secret_name = NULL;
-	gboolean success = FALSE;
-	gboolean add_password = FALSE;
-
-	g_return_val_if_fail (connection != NULL, FALSE);
-	g_return_val_if_fail (tag != NULL, FALSE);
-	g_return_val_if_fail (password != NULL, FALSE);
-	g_return_val_if_fail (error != NULL, FALSE);
-	g_return_val_if_fail (*error == NULL, FALSE);
-
-	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
-
-	if (!strcmp (tag, NMA_PRIVATE_KEY_PASSWORD_TAG)) {
-		filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PRIVATE_KEY_TAG);
-		secret_name = NM_SETTING_802_1X_PRIVATE_KEY;
-		real_password_secret_name = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
-	} else if (!strcmp (tag, NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG)) {
-		filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PHASE2_PRIVATE_KEY_TAG);
-		secret_name = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY;
-		real_password_secret_name = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD;
-	} else {
-		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
-		             "%s.%d - %s/%s Unknown private key password type '%s'.",
-		             __FILE__, __LINE__, nm_setting_connection_get_id (s_con), setting_name, tag);
-		return FALSE;
-	}
-
-	if (filename) {
-		NMSetting8021x *setting;
-		const GByteArray *tmp = NULL;
-		NMSetting8021xCKType ck_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
-
-		setting = (NMSetting8021x *) nm_setting_802_1x_new ();
-		if (nm_setting_802_1x_set_private_key_from_file (setting, filename, password, &ck_type, error)) {
-			/* For PKCS#12 files, which don't get decrypted, add the private key
-			 * password to the secrets hash.
-			 */
-			if (ck_type == NM_SETTING_802_1X_CK_TYPE_PKCS12)
-				add_password = TRUE;
-
-			/* Steal the private key */
-			tmp = nm_setting_802_1x_get_private_key (setting);
-			g_assert (tmp);
-			array = g_byte_array_sized_new (tmp->len);
-			g_byte_array_append (array, tmp->data, tmp->len);
-		}
-		g_object_unref (setting);
-	}
-
-	if (*error) {
-		goto out;
-	} else if (!array || !array->len) {
-		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
-		             "%s.%d - %s/%s couldn't read private key.",
-		             __FILE__, __LINE__, nm_setting_connection_get_id (s_con), setting_name);
-		goto out;
-	}
-
-	g_hash_table_insert (secrets, g_strdup (secret_name), byte_array_to_gvalue (array));
-
-	if (include_password || add_password)
-		g_hash_table_insert (secrets, g_strdup (real_password_secret_name), string_to_gvalue (password));
-
-	success = TRUE;
-
-out:
-	if (array) {
-		/* Try not to leave the decrypted private key around in memory */
-		memset (array->data, 0, array->len);
-		g_byte_array_free (array, TRUE);
-	}
-	return success;
+	return g_strdup_printf (APPLET_PREFS_PATH "/%s/%s",
+	                        phase2 ? "ignore-phase2-ca-cert" : "ignore-ca-cert",
+	                        uuid);
 }
 
-GHashTable *
-nm_gconf_get_keyring_items (NMConnection *connection,
-                            const char *setting_name,
-                            gboolean include_private_passwords,
-                            GError **error)
+gboolean
+nm_gconf_get_ignore_ca_cert (const char *uuid, gboolean phase2)
 {
-	NMSettingConnection *s_con;
-	GHashTable *secrets;
-	GList *found_list = NULL;
-	GnomeKeyringResult ret;
-	GList *iter;
-	const char *connection_name;
-
-	g_return_val_if_fail (connection != NULL, NULL);
-	g_return_val_if_fail (setting_name != NULL, NULL);
-	g_return_val_if_fail (error != NULL, NULL);
-	g_return_val_if_fail (*error == NULL, NULL);
-
-	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
-	g_assert (s_con);
-
-	connection_name = nm_setting_connection_get_id (s_con);
-	g_assert (connection_name);
-
-	pre_keyring_callback ();
-
-	ret = gnome_keyring_find_itemsv_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET,
-	                                      &found_list,
-	                                      KEYRING_UUID_TAG,
-	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
-										  nm_setting_connection_get_uuid (s_con),
-	                                      KEYRING_SN_TAG,
-	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
-	                                      setting_name,
-	                                      NULL);
-	if ((ret != GNOME_KEYRING_RESULT_OK) || (g_list_length (found_list) == 0))
-		return NULL;
-
-	secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
-
-	for (iter = found_list; iter != NULL; iter = g_list_next (iter)) {
-		GnomeKeyringFound *found = (GnomeKeyringFound *) iter->data;
-		int i;
-		const char * key_name = NULL;
-
-		for (i = 0; i < found->attributes->len; i++) {
-			GnomeKeyringAttribute *attr;
-
-			attr = &(gnome_keyring_attribute_list_index (found->attributes, i));
-			if (   (strcmp (attr->name, "setting-key") == 0)
-			    && (attr->type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING)) {
-				key_name = attr->value.string;
-				break;
-			}
-		}
-
-		if (key_name == NULL) {
-			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
-			             "%s.%d - Internal error; keyring item '%s/%s' didn't "
-			             "have a 'setting-key' attribute.",
-			             __FILE__, __LINE__, connection_name, setting_name);
-			break;
-		}
-
-		if (   !strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME)
-		    && (   !strcmp (key_name, NMA_PRIVATE_KEY_PASSWORD_TAG)
-		        || !strcmp (key_name, NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG))) {
-			/* Private key passwords aren't passed to NM for "traditional"
-			 * OpenSSL private keys, but are passed to NM for PKCS#12 keys.
-			 */
-			if (!get_one_private_key (connection, setting_name, key_name,
-			                          found->secret, include_private_passwords, secrets, error)) {
-				if (!*error) {
-					g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
-					             "%s.%d - %s/%s unknown error from get_one_private_key().",
-					             __FILE__, __LINE__, connection_name, setting_name);
-				}
-				break;
-			}
-		} else {
-			/* Ignore older obsolete keyring keys that we don't want to leak
-			 * through to NM.
-			 */
-			if (   strcmp (key_name, "private-key-passwd")
-			    && strcmp (key_name, "phase2-private-key-passwd")) {
-				g_hash_table_insert (secrets,
-				                     g_strdup (key_name),
-				                     string_to_gvalue (found->secret));
-			}
-		}
-	}
+	GConfClient *client;
+	char *key = NULL;
+	gboolean ignore = FALSE;
 
-	if (*error) {
-		nm_warning ("%s: error reading secrets: (%d) %s", __func__,
-		            (*error)->code, (*error)->message);
-		g_hash_table_destroy (secrets);
-		secrets = NULL;
-	}
+	g_return_val_if_fail (uuid != NULL, FALSE);
 
-	gnome_keyring_found_list_free (found_list);
-	return secrets;
-}
+	client = gconf_client_get_default ();
 
-static inline void
-copy_str_item (NMConnection *dst, NMConnection *src, const char *tag)
-{
-	g_object_set_data_full (G_OBJECT (dst), tag, g_strdup (g_object_get_data (G_OBJECT (src), tag)), g_free);
-}
+	key = get_ignore_path (uuid, phase2);
+	ignore = gconf_client_get_bool (client, key, NULL);
+	g_free (key);
 
-void
-nm_gconf_copy_private_connection_values (NMConnection *dst, NMConnection *src)
-{
-	g_return_if_fail (NM_IS_CONNECTION (dst));
-	g_return_if_fail (NM_IS_CONNECTION (src));
-
-	g_object_set_data (G_OBJECT (dst), NMA_CA_CERT_IGNORE_TAG,
-	                   g_object_get_data (G_OBJECT (src), NMA_CA_CERT_IGNORE_TAG));
-	g_object_set_data (G_OBJECT (dst), NMA_PHASE2_CA_CERT_IGNORE_TAG,
-	                   g_object_get_data (G_OBJECT (src), NMA_PHASE2_CA_CERT_IGNORE_TAG));
-
-	copy_str_item (dst, src, NMA_PATH_CLIENT_CERT_TAG);
-	copy_str_item (dst, src, NMA_PATH_PHASE2_CLIENT_CERT_TAG);
-	copy_str_item (dst, src, NMA_PATH_CA_CERT_TAG);
-	copy_str_item (dst, src, NMA_PATH_PHASE2_CA_CERT_TAG);
-	copy_str_item (dst, src, NMA_PATH_PRIVATE_KEY_TAG);
-	copy_str_item (dst, src, NMA_PRIVATE_KEY_PASSWORD_TAG);
-	copy_str_item (dst, src, NMA_PATH_PHASE2_PRIVATE_KEY_TAG);
-	copy_str_item (dst, src, NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG);
+	g_object_unref (client);
+	return ignore;
 }
 
 void
-nm_gconf_clear_private_connection_values (NMConnection *connection)
+nm_gconf_set_ignore_ca_cert (const char *uuid, gboolean phase2, gboolean ignore)
 {
-	g_return_if_fail (NM_IS_CONNECTION (connection));
-
-	g_object_set_data (G_OBJECT (connection), NMA_CA_CERT_IGNORE_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PHASE2_CA_CERT_IGNORE_TAG, NULL);
-
-	g_object_set_data (G_OBJECT (connection), NMA_PATH_CLIENT_CERT_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PATH_PHASE2_CLIENT_CERT_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PATH_PHASE2_CA_CERT_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PATH_PRIVATE_KEY_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PRIVATE_KEY_PASSWORD_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PATH_PHASE2_PRIVATE_KEY_TAG, NULL);
-	g_object_set_data (G_OBJECT (connection), NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG, NULL);
-}
-
-NMConnection *
-nm_gconf_connection_duplicate (NMConnection *connection)
-{
-	NMConnection *dup;
+	GConfClient *client;
+	char *key = NULL;
 
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+	g_return_if_fail (uuid != NULL);
 
-	dup = nm_connection_duplicate (connection);
-	g_return_val_if_fail (NM_IS_CONNECTION (dup), NULL);
+	client = gconf_client_get_default ();
 
-	nm_gconf_copy_private_connection_values (dup, connection);
+	key = get_ignore_path (uuid, phase2);
+	if (ignore)
+		gconf_client_set_bool (client, key, ignore, NULL);
+	else
+		gconf_client_unset (client, key, NULL);
+	g_free (key);
 
-	return dup;
+	g_object_unref (client);
 }
 
diff --git a/src/gconf-helpers/gconf-helpers.h b/src/gconf-helpers/gconf-helpers.h
index df814f6..17d1ce8 100644
--- a/src/gconf-helpers/gconf-helpers.h
+++ b/src/gconf-helpers/gconf-helpers.h
@@ -27,28 +27,18 @@
 #include <glib.h>
 #include <nm-connection.h>
 
+#include "nma-gconf-connection.h"
+
 #define GCONF_PATH_CONNECTIONS "/system/networking/connections"
 
-/* 
-   ATTENTION: Make sure to update nm_gconf_connection_duplicate() 
-   when new connection tag is added! Otherwise duplicating connection
-   will not work correctly.
-*/
-#define NMA_CA_CERT_IGNORE_TAG  "nma-ca-cert-ignore"
-#define NMA_PHASE2_CA_CERT_IGNORE_TAG  "nma-phase2-ca-cert-ignore"
-#define NMA_PATH_CLIENT_CERT_TAG "nma-path-client-cert"
-#define NMA_PATH_PHASE2_CLIENT_CERT_TAG "nma-path-phase2-client-cert"
-#define NMA_PATH_CA_CERT_TAG "nma-path-ca-cert"
-#define NMA_PATH_PHASE2_CA_CERT_TAG "nma-path-phase2-ca-cert"
-#define NMA_PATH_PRIVATE_KEY_TAG "nma-path-private-key"
-#define NMA_PRIVATE_KEY_PASSWORD_TAG "nma-private-key-password"
-#define NMA_PATH_PHASE2_PRIVATE_KEY_TAG "nma-path-phase2-private-key"
-#define NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG "nma-phase2-private-key-password"
-
-NMConnection *nm_gconf_connection_duplicate (NMConnection *connection);
-
-void nm_gconf_copy_private_connection_values (NMConnection *dst, NMConnection *src);
-void nm_gconf_clear_private_connection_values (NMConnection *connection);
+/* The stamp is a mechanism for determining which applet version last
+ * updated GConf for various GConf update tasks in newer applet versions.
+ */
+#define APPLET_CURRENT_STAMP 1
+#define APPLET_PREFS_STAMP "/apps/nm-applet/stamp"
+
+#define IGNORE_CA_CERT_TAG "ignore-ca-cert"
+#define IGNORE_PHASE2_CA_CERT_TAG "ignore-phase2-ca-cert"
 
 #define KEYRING_UUID_TAG "connection-uuid"
 #define KEYRING_SN_TAG "setting-name"
@@ -126,6 +116,27 @@ nm_gconf_get_ip4_helper (GConfClient *client,
 						  guint32 tuple_len,
 						  GPtrArray **value);
 
+gboolean
+nm_gconf_get_ip6dns_array_helper (GConfClient *client,
+								  const char *path,
+								  const char *key,
+								  const char *setting,
+								  GPtrArray **value);
+
+gboolean
+nm_gconf_get_ip6addr_array_helper (GConfClient *client,
+								   const char *path,
+								   const char *key,
+								   const char *setting,
+								   GPtrArray **value);
+
+gboolean
+nm_gconf_get_ip6route_array_helper (GConfClient *client,
+									const char *path,
+									const char *key,
+									const char *setting,
+									GPtrArray **value);
+
 /* Setters */
 
 gboolean
@@ -199,6 +210,27 @@ nm_gconf_set_ip4_helper (GConfClient *client,
 					  guint32 tuple_len,
 					  GPtrArray *value);
 
+gboolean
+nm_gconf_set_ip6dns_array_helper (GConfClient *client,
+								  const char *path,
+								  const char *key,
+								  const char *setting,
+								  GPtrArray *value);
+
+gboolean
+nm_gconf_set_ip6addr_array_helper (GConfClient *client,
+								   const char *path,
+								   const char *key,
+								   const char *setting,
+								   GPtrArray *value);
+
+gboolean
+nm_gconf_set_ip6route_array_helper (GConfClient *client,
+									const char *path,
+									const char *key,
+									const char *setting,
+									GPtrArray *value);
+
 GSList *
 nm_gconf_get_all_connections (GConfClient *client);
 
@@ -218,14 +250,12 @@ nm_gconf_add_keyring_item (const char *connection_uuid,
                            const char *setting_key,
                            const char *secret);
 
-GHashTable *
-nm_gconf_get_keyring_items (NMConnection *connection,
-                            const char *setting_name,
-                            gboolean include_private_passwords,
-                            GError **error);
-
 typedef void (*PreKeyringCallback) (gpointer user_data);
 void nm_gconf_set_pre_keyring_callback (PreKeyringCallback func, gpointer user_data);
+void pre_keyring_callback (void);
+
+gboolean nm_gconf_get_ignore_ca_cert (const char *uuid, gboolean phase2);
+void nm_gconf_set_ignore_ca_cert (const char *uuid, gboolean phase2, gboolean ignore);
 
 #endif	/* GCONF_HELPERS_H */
 
diff --git a/src/gconf-helpers/nma-gconf-connection.c b/src/gconf-helpers/nma-gconf-connection.c
index 4297d7c..51fe667 100644
--- a/src/gconf-helpers/nma-gconf-connection.c
+++ b/src/gconf-helpers/nma-gconf-connection.c
@@ -1,15 +1,50 @@
 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 - 2009 Red Hat, Inc.
+ */
 
 #include <string.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <gnome-keyring.h>
+
 #include <nm-setting-connection.h>
 #include <nm-setting-vpn.h>
+#include <nm-setting-8021x.h>
+
 #include "nma-gconf-connection.h"
-#include <nm-utils.h>
-#include "nma-marshal.h"
 #include "gconf-helpers.h"
+#include "nm-utils.h"
 #include "utils.h"
+#include "nma-marshal.h"
+#include "nm-settings-interface.h"
 
-G_DEFINE_TYPE (NMAGConfConnection, nma_gconf_connection, NM_TYPE_EXPORTED_CONNECTION)
+static NMSettingsConnectionInterface *parent_settings_connection_iface;
+
+static void settings_connection_interface_init (NMSettingsConnectionInterface *class);
+
+G_DEFINE_TYPE_EXTENDED (NMAGConfConnection, nma_gconf_connection, NM_TYPE_EXPORTED_CONNECTION, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
+                                               settings_connection_interface_init))
 
 #define NMA_GCONF_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMA_TYPE_GCONF_CONNECTION, NMAGConfConnectionPrivate))
 
@@ -60,106 +95,97 @@ nma_gconf_connection_new (GConfClient *client, const char *conf_dir)
 
 NMAGConfConnection *
 nma_gconf_connection_new_from_connection (GConfClient *client,
-								  const char *conf_dir,
-								  NMConnection *connection)
+                                          const char *conf_dir,
+                                          NMConnection *connection)
 {
+	GObject *object;
+	NMAGConfConnection *self;
+	GError *error = NULL;
+	gboolean success;
+	GHashTable *settings;
+
 	g_return_val_if_fail (GCONF_IS_CLIENT (client), NULL);
 	g_return_val_if_fail (conf_dir != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
-	return (NMAGConfConnection *) g_object_new (NMA_TYPE_GCONF_CONNECTION,
-									    NMA_GCONF_CONNECTION_CLIENT, client,
-									    NMA_GCONF_CONNECTION_DIR, conf_dir,
-									    NM_EXPORTED_CONNECTION_CONNECTION, connection,
-									    NULL);
-}
-
-const char *
-nma_gconf_connection_get_path (NMAGConfConnection *self)
-{
-	g_return_val_if_fail (NMA_IS_GCONF_CONNECTION (self), NULL);
+	/* Ensure the connection is valid first */
+	success = nm_connection_verify (connection, &error);
+	if (!success) {
+		g_warning ("Invalid connection %s: '%s' / '%s' invalid: %d",
+		           conf_dir,
+		           g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)),
+		           (error && error->message) ? error->message : "(unknown)",
+		           error ? error->code : -1);
+		g_clear_error (&error);
+		return NULL;
+	}
 
-	return NMA_GCONF_CONNECTION_GET_PRIVATE (self)->dir;
-}
+	object = g_object_new (NMA_TYPE_GCONF_CONNECTION,
+	                       NMA_GCONF_CONNECTION_CLIENT, client,
+	                       NMA_GCONF_CONNECTION_DIR, conf_dir,
+	                       NM_CONNECTION_SCOPE, NM_CONNECTION_SCOPE_USER,
+	                       NULL);
+	if (!object)
+		return NULL;
 
-/* FIXME: Remove and replace the callers with nm_exported_connection_update() */
-void
-nma_gconf_connection_save (NMAGConfConnection *self)
-{
-	NMAGConfConnectionPrivate *priv;
-	NMConnection *connection;
+	self = NMA_GCONF_CONNECTION (object);
 
-	g_return_if_fail (NMA_IS_GCONF_CONNECTION (self));
+	/* Fill certs so that the nm_connection_replace_settings verification works */
+	settings = nm_connection_to_hash (connection);
+	success = nm_connection_replace_settings (NM_CONNECTION (self), settings, NULL);
+	g_hash_table_destroy (settings);
 
-	priv = NMA_GCONF_CONNECTION_GET_PRIVATE (self);
+	/* Already verified the settings above, they had better be OK */
+	g_assert (success);
 
-	connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (self));
-	nm_gconf_write_connection (connection,
-	                           priv->client,
-	                           priv->dir);
-	gconf_client_notify (priv->client, priv->dir);
-	gconf_client_suggest_sync (priv->client, NULL);
+	return self;
 }
 
-static void
-fill_vpn_user_name (NMConnection *connection)
+const char *
+nma_gconf_connection_get_gconf_path (NMAGConfConnection *self)
 {
-	const char *user_name;
-	NMSettingVPN *s_vpn;
-
-	s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN));
-	if (!s_vpn)
-		return;
+	g_return_val_if_fail (NMA_IS_GCONF_CONNECTION (self), NULL);
 
-	user_name = g_get_user_name ();
-	g_assert (g_utf8_validate (user_name, -1, NULL));
-	g_object_set (s_vpn, NM_SETTING_VPN_USER_NAME, user_name, NULL);
+	return NMA_GCONF_CONNECTION_GET_PRIVATE (self)->dir;
 }
 
 gboolean
-nma_gconf_connection_changed (NMAGConfConnection *self)
+nma_gconf_connection_gconf_changed (NMAGConfConnection *self)
 {
-	NMAGConfConnectionPrivate *priv;
-	GHashTable *settings;
-	NMConnection *wrapped_connection;
-	NMConnection *gconf_connection;
+	NMAGConfConnectionPrivate *priv = NMA_GCONF_CONNECTION_GET_PRIVATE (self);
+	NMConnection *new;
 	GHashTable *new_settings;
 	GError *error = NULL;
+	gboolean success;
 
-	g_return_val_if_fail (NMA_IS_GCONF_CONNECTION (self), FALSE);
-
-	priv = NMA_GCONF_CONNECTION_GET_PRIVATE (self);
-	wrapped_connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (self));
-
-	gconf_connection = nm_gconf_read_connection (priv->client, priv->dir);
-	if (!gconf_connection) {
+	new = nm_gconf_read_connection (priv->client, priv->dir);
+	if (!new) {
 		g_warning ("No connection read from GConf at %s.", priv->dir);
 		goto invalid;
 	}
 
-	utils_fill_connection_certs (gconf_connection);
-	if (!nm_connection_verify (gconf_connection, &error)) {
-		utils_clear_filled_connection_certs (gconf_connection);
+	success = nm_connection_verify (new, &error);
+	if (!success) {
 		g_warning ("%s: Invalid connection %s: '%s' / '%s' invalid: %d",
 		           __func__, priv->dir,
 		           g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)),
 		           error->message, error->code);
+		g_object_unref (new);
 		goto invalid;
 	}
-	utils_clear_filled_connection_certs (gconf_connection);
 
 	/* Ignore the GConf update if nothing changed */
-	if (nm_connection_compare (wrapped_connection, gconf_connection, NM_SETTING_COMPARE_FLAG_EXACT))
+	if (nm_connection_compare (NM_CONNECTION (self), new, NM_SETTING_COMPARE_FLAG_EXACT)) {
+		g_object_unref (new);
 		return TRUE;
+	}
 
-	utils_fill_connection_certs (gconf_connection);
-	new_settings = nm_connection_to_hash (gconf_connection);
-	utils_clear_filled_connection_certs (gconf_connection);
-
-	if (!nm_connection_replace_settings (wrapped_connection, new_settings, &error)) {
-		utils_clear_filled_connection_certs (wrapped_connection);
-		g_hash_table_destroy (new_settings);
+	new_settings = nm_connection_to_hash (new);
+	success = nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error);
+	g_hash_table_destroy (new_settings);
+	g_object_unref (new);
 
+	if (!success) {
 		g_warning ("%s: '%s' / '%s' invalid: %d",
 		           __func__,
 		           error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)",
@@ -167,74 +193,271 @@ nma_gconf_connection_changed (NMAGConfConnection *self)
 		           error ? error->code : -1);
 		goto invalid;
 	}
-	g_object_unref (gconf_connection);
-	g_hash_table_destroy (new_settings);
 
-	fill_vpn_user_name (wrapped_connection);
-
-	settings = nm_connection_to_hash (wrapped_connection);
-	utils_clear_filled_connection_certs (wrapped_connection);
-
-	nm_exported_connection_signal_updated (NM_EXPORTED_CONNECTION (self), settings);
-	g_hash_table_destroy (settings);
+	nm_settings_connection_interface_emit_updated (NM_SETTINGS_CONNECTION_INTERFACE (self));
 	return TRUE;
 
 invalid:
 	g_clear_error (&error);
-	nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (self));
+	g_signal_emit_by_name (self, NM_SETTINGS_CONNECTION_INTERFACE_REMOVED);
 	return FALSE;
 }
 
+/******************************************************/
 
-static GHashTable *
-get_settings (NMExportedConnection *exported)
+static GValue *
+string_to_gvalue (const char *str)
 {
-	NMConnection *connection;
-	GHashTable *settings;
+	GValue *val;
 
-	connection = nm_exported_connection_get_connection (exported);
+	val = g_slice_new0 (GValue);
+	g_value_init (val, G_TYPE_STRING);
+	g_value_set_string (val, str);
 
-	utils_fill_connection_certs (connection);
-	settings = nm_connection_to_hash (connection);
-	utils_clear_filled_connection_certs (connection);
+	return val;
+}
 
-	return settings;
+#define FILE_TAG "file://"
+
+static GValue *
+path_to_gvalue (const char *path)
+{
+	GValue *val;
+	GByteArray *array;
+
+	array = g_byte_array_sized_new (strlen (FILE_TAG) + strlen (path) + 1);
+	g_byte_array_append (array, (guint8 *) FILE_TAG, strlen (FILE_TAG));
+	g_byte_array_append (array, (guint8 *) path, strlen (path) + 1);  /* +1 for the trailing NULL */
+
+	val = g_slice_new0 (GValue);
+	g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY);
+	g_value_take_boxed (val, array);
+
+	return val;
 }
 
 static void
-secrets_return_error (DBusGMethodInvocation *context, GError *error)
+destroy_gvalue (gpointer data)
 {
-	nm_warning ("Error getting secrets: %s", error->message);
-	dbus_g_method_return_error (context, error);
-	g_error_free (error);
+	GValue *value = (GValue *) data;
+
+	g_value_unset (value);
+	g_slice_free (GValue, value);
 }
 
-typedef struct {
-	gboolean found;
-	const char **hints;
-} FindHintsInfo;
+static GHashTable *
+nma_gconf_connection_get_keyring_items (NMAGConfConnection *self,
+                                        const char *setting_name,
+                                        GError **error)
+{
+	NMAGConfConnectionPrivate *priv;
+	NMSettingConnection *s_con;
+	GHashTable *secrets;
+	GList *found_list = NULL;
+	GnomeKeyringResult ret;
+	GList *iter;
+	const char *connection_name;
+	char *path = NULL;
+
+	g_return_val_if_fail (self != NULL, NULL);
+	g_return_val_if_fail (setting_name != NULL, NULL);
+	g_return_val_if_fail (error != NULL, NULL);
+	g_return_val_if_fail (*error == NULL, NULL);
+
+	priv = NMA_GCONF_CONNECTION_GET_PRIVATE (self);
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+
+	connection_name = nm_setting_connection_get_id (s_con);
+	g_assert (connection_name);
+
+	pre_keyring_callback ();
+
+	ret = gnome_keyring_find_itemsv_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	                                      &found_list,
+	                                      KEYRING_UUID_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+										  nm_setting_connection_get_uuid (s_con),
+	                                      KEYRING_SN_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      setting_name,
+	                                      NULL);
+	if ((ret != GNOME_KEYRING_RESULT_OK) || (g_list_length (found_list) == 0))
+		return NULL;
+
+	secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
+
+	for (iter = found_list; iter != NULL; iter = g_list_next (iter)) {
+		GnomeKeyringFound *found = (GnomeKeyringFound *) iter->data;
+		int i;
+		const char *key_name = NULL;
+
+		for (i = 0; i < found->attributes->len; i++) {
+			GnomeKeyringAttribute *attr;
+
+			attr = &(gnome_keyring_attribute_list_index (found->attributes, i));
+			if (   (strcmp (attr->name, KEYRING_SK_TAG) == 0)
+			    && (attr->type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING)) {
+				key_name = attr->value.string;
+				break;
+			}
+		}
+
+		if (key_name == NULL) {
+			g_set_error (error,
+			             NM_SETTINGS_INTERFACE_ERROR,
+			             NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE,
+			             "%s.%d - Internal error; keyring item '%s/%s' didn't "
+			             "have a 'setting-key' attribute.",
+			             __FILE__, __LINE__, connection_name, setting_name);
+			break;
+		}
+
+		g_hash_table_insert (secrets,
+		                     g_strdup (key_name),
+		                     string_to_gvalue (found->secret));
+	}
+
+	/* The phase1 and phase2 private key are still marked as 'secret' for
+	 * backwards compat, but since they don't get stored in the keyring since
+	 * they aren't really secret (because we now use paths everywhere and not
+	 * the decrypted private key like 0.7.x).  So we need to grab them out of
+	 * GConf and add them to the returned secret hash.
+	 */
+	/* Private key path */
+	path = NULL;
+	if (nm_gconf_get_string_helper (priv->client,
+	                                priv->dir,
+	                                NM_SETTING_802_1X_PRIVATE_KEY,
+	                                NM_SETTING_802_1X_SETTING_NAME,
+	                                &path)) {
+		g_hash_table_insert (secrets,
+		                     g_strdup (NM_SETTING_802_1X_PRIVATE_KEY),
+		                     path_to_gvalue (path));
+		g_free (path);
+	}
+
+	/* Phase2 private key path */
+	path = NULL;
+	if (nm_gconf_get_string_helper (priv->client,
+	                                priv->dir,
+	                                NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+	                                NM_SETTING_802_1X_SETTING_NAME,
+	                                &path)) {
+		g_hash_table_insert (secrets,
+		                     g_strdup (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY),
+		                     path_to_gvalue (path));
+		g_free (path);
+	}
+
+	if (*error) {
+		nm_warning ("%s: error reading secrets: (%d) %s", __func__,
+		            (*error)->code, (*error)->message);
+		g_hash_table_destroy (secrets);
+		secrets = NULL;
+	}
+
+	gnome_keyring_found_list_free (found_list);
+	return secrets;
+}
 
 static void
-find_hints_in_secrets (gpointer key, gpointer data, gpointer user_data)
+delete_done (GnomeKeyringResult result, gpointer user_data)
 {
-	FindHintsInfo *info = (FindHintsInfo *) user_data;
-	const char **iter;
+}
 
-	for (iter = info->hints; !info->found && *iter; iter++) {
-		if (!strcmp (*iter, (const char *) key) && data && G_IS_VALUE (data))
-			info->found = TRUE;
+static void
+clear_keyring_items (NMAGConfConnection *self)
+{
+	NMSettingConnection *s_con;
+	const char *uuid;
+	GList *found_list = NULL;
+	GnomeKeyringResult ret;
+	GList *iter;
+
+	g_return_if_fail (self != NULL);
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
+	g_return_if_fail (s_con != NULL);
+
+	uuid = nm_setting_connection_get_uuid (s_con);
+	g_return_if_fail (uuid != NULL);
+
+	pre_keyring_callback ();
+
+	ret = gnome_keyring_find_itemsv_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	                                      &found_list,
+	                                      KEYRING_UUID_TAG,
+	                                      GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+	                                      uuid,
+	                                      NULL);
+	if (ret == GNOME_KEYRING_RESULT_OK) {
+		for (iter = found_list; iter != NULL; iter = g_list_next (iter)) {
+			GnomeKeyringFound *found = (GnomeKeyringFound *) iter->data;
+
+			gnome_keyring_item_delete (found->keyring,
+			                           found->item_id,
+			                           delete_done,
+			                           NULL,
+			                           NULL);
+		}
+		gnome_keyring_found_list_free (found_list);
 	}
 }
 
-static void
-service_get_secrets (NMExportedConnection *exported,
-                     const gchar *setting_name,
-                     const gchar **hints,
-                     gboolean request_new,
-                     DBusGMethodInvocation *context)
+/******************************************************/
+
+static gboolean
+update (NMSettingsConnectionInterface *connection,
+	    NMSettingsConnectionInterfaceUpdateFunc callback,
+	    gpointer user_data)
 {
-	NMConnection *connection;
+	NMAGConfConnectionPrivate *priv = NMA_GCONF_CONNECTION_GET_PRIVATE (connection);
+
+	nm_gconf_write_connection (NM_CONNECTION (connection),
+	                           priv->client,
+	                           priv->dir);
+	gconf_client_notify (priv->client, priv->dir);
+	gconf_client_suggest_sync (priv->client, NULL);
+
+	return parent_settings_connection_iface->update (connection, callback, user_data);
+}
+
+static gboolean 
+do_delete (NMSettingsConnectionInterface *connection,
+	       NMSettingsConnectionInterfaceDeleteFunc callback,
+	       gpointer user_data)
+{
+	NMAGConfConnectionPrivate *priv = NMA_GCONF_CONNECTION_GET_PRIVATE (connection);
+	gboolean success;
 	GError *error = NULL;
+
+	/* Clean up keyring keys */
+	clear_keyring_items (NMA_GCONF_CONNECTION (connection));
+
+	success = gconf_client_recursive_unset (priv->client, priv->dir, 0, &error);
+	if (!success) {
+		callback (connection, error, user_data);
+		g_error_free (error);
+		return FALSE;
+	}
+	gconf_client_suggest_sync (priv->client, NULL);
+
+	return parent_settings_connection_iface->delete (connection, callback, user_data);
+}
+
+static gboolean
+internal_get_secrets (NMSettingsConnectionInterface *connection,
+                      const char *setting_name,
+                      const char **hints,
+                      gboolean request_new,
+                      gboolean local,
+                      NMANewSecretsRequestedFunc callback,
+                      gpointer callback_data,
+                      GError **error)
+{
+	NMAGConfConnection *self = NMA_GCONF_CONNECTION (connection);
 	GHashTable *settings = NULL;
 	GHashTable *secrets = NULL;
 	NMSettingConnection *s_con;
@@ -242,71 +465,92 @@ service_get_secrets (NMExportedConnection *exported,
 	const char *connection_id;
 	const char *connection_type;
 
-	connection = nm_exported_connection_get_connection (exported);
-
-	setting = nm_connection_get_setting_by_name (connection, setting_name);
+	setting = nm_connection_get_setting_by_name (NM_CONNECTION (self), setting_name);
 	if (!setting) {
-		g_set_error (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+		g_set_error (error,
+		             NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
 		             "%s.%d - Connection didn't have requested setting '%s'.",
 		             __FILE__, __LINE__, setting_name);
-		secrets_return_error (context, error);
-		return;
+		return FALSE;
 	}
 
-	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
-	connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
-	connection_type = s_con ? nm_setting_connection_get_connection_type (s_con) : NULL;
+	s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	connection_id = nm_setting_connection_get_id (s_con);
+	connection_type = nm_setting_connection_get_connection_type (s_con);
 
 	if (!s_con || !connection_id || !strlen (connection_id) || !connection_type) {
-		g_set_error (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+		g_set_error (error,
+		             NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
 		             "%s.%d - Connection didn't have required '"
 		             NM_SETTING_CONNECTION_SETTING_NAME
 		             "' setting , or the connection name was invalid.",
 		             __FILE__, __LINE__);
-		secrets_return_error (context, error);
-		return;
+		return FALSE;
 	}
 
-	/* VPN passwords are handled by the VPN plugin's auth dialog */
-	if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME))
-		goto get_secrets;
-
-	if (request_new) {
-		nm_info ("New secrets for %s/%s requested; ask the user",
-		         connection_id, setting_name);
-		nm_connection_clear_secrets (connection);
-		goto get_secrets;
-	}
+	/* Only try to get new secrets for D-Bus requests */
+	if (local) {
+		secrets = nma_gconf_connection_get_keyring_items (self, setting_name, error);
+		if (!secrets && error && *error)
+			return FALSE;
+	} else {
+		/* VPN passwords are handled by the VPN plugin's auth dialog */
+		if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME))
+			goto get_secrets;
 
-	secrets = nm_gconf_get_keyring_items (connection, setting_name, FALSE, &error);
-	if (!secrets) {
-		if (error) {
-			secrets_return_error (context, error);
-			return;
+		if (request_new) {
+			nm_info ("New secrets for %s/%s requested; ask the user",
+			         connection_id, setting_name);
+			nm_connection_clear_secrets (NM_CONNECTION (self));
+			goto get_secrets;
 		}
-		nm_info ("No keyring secrets found for %s/%s; asking user.",
-		         connection_id, setting_name);
-		goto get_secrets;
-	}
 
-	if (g_hash_table_size (secrets) == 0) {
-		g_hash_table_destroy (secrets);
-		nm_warning ("%s.%d - Secrets were found for setting '%s' but none"
-				  " were valid.", __FILE__, __LINE__, setting_name);
-		goto get_secrets;
-	}
+		secrets = nma_gconf_connection_get_keyring_items (self, setting_name, error);
+		if (!secrets) {
+			if (error && *error)
+				return FALSE;
 
-	/* If there were hints, and none of the hints were returned by the keyring,
-	 * get some new secrets.
-	 */
-	if (hints && g_strv_length ((char **) hints)) {
-		FindHintsInfo info = { .found = FALSE, .hints = hints };
+			nm_info ("No keyring secrets found for %s/%s; asking user.",
+			         connection_id, setting_name);
+			goto get_secrets;
+		}
 
-		g_hash_table_foreach (secrets, find_hints_in_secrets, &info);
-		if (info.found == FALSE) {
+		if (g_hash_table_size (secrets) == 0) {
 			g_hash_table_destroy (secrets);
+			nm_warning ("%s.%d - Secrets were found for setting '%s' but none"
+					  " were valid.", __FILE__, __LINE__, setting_name);
 			goto get_secrets;
 		}
+
+		/* If there were hints, and none of the hints were returned by the keyring,
+		 * get some new secrets.
+		 */
+		if (hints && g_strv_length ((char **) hints)) {
+			GHashTableIter iter;
+			gpointer key, value;
+			gboolean found = FALSE;
+
+			g_hash_table_iter_init (&iter, secrets);
+			while (g_hash_table_iter_next (&iter, &key, &value) && !found) {
+				const char **hint = hints;
+
+				while (!found && *hint) {
+					if (!strcmp (*hint, (const char *) key) && value && G_IS_VALUE (value)) {
+						found = TRUE;
+						break;
+					}
+					hint++;
+				}
+			}
+
+			if (!found) {
+				g_hash_table_destroy (secrets);
+				goto get_secrets;
+			}
+		}
 	}
 
 	/* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
@@ -315,65 +559,298 @@ service_get_secrets (NMExportedConnection *exported,
 	settings = g_hash_table_new_full (g_str_hash, g_str_equal,
 	                                  g_free,
 	                                  (GDestroyNotify) g_hash_table_destroy);
-	g_hash_table_insert (settings, g_strdup (setting_name), secrets);
-	dbus_g_method_return (context, settings);
+	if (secrets)
+		g_hash_table_insert (settings, g_strdup (setting_name), secrets);
+	callback (NM_SETTINGS_CONNECTION_INTERFACE (self), settings, NULL, callback_data);
 	g_hash_table_destroy (settings);
-	return;
+	return TRUE;
 
 get_secrets:
-	g_signal_emit (exported,
+	g_signal_emit (self,
 	               signals[NEW_SECRETS_REQUESTED],
 	               0,
 	               setting_name,
 	               hints,
 	               request_new,
-	               context);
+	               callback,
+	               callback_data);
+	return TRUE;
+}
+
+typedef struct {
+	NMSettingsConnectionInterfaceGetSecretsFunc callback;
+	gpointer callback_data;
+} GetSecretsInfo;
+
+static void
+get_secrets_cb (NMSettingsConnectionInterface *connection,
+                GHashTable *settings,
+                GError *error,
+                gpointer user_data)
+{
+	GetSecretsInfo *info = user_data;
+
+	info->callback (NM_SETTINGS_CONNECTION_INTERFACE (connection), settings, error, info->callback_data);
+	g_free (info);
 }
 
 static gboolean
-update (NMExportedConnection *exported, GHashTable *new_settings, GError **error)
+get_secrets (NMSettingsConnectionInterface *connection,
+	         const char *setting_name,
+             const char **hints,
+             gboolean request_new,
+             NMSettingsConnectionInterfaceGetSecretsFunc callback,
+             gpointer user_data)
 {
-	NMAGConfConnectionPrivate *priv = NMA_GCONF_CONNECTION_GET_PRIVATE (exported);
-	NMConnection *tmp;
-	GError *local_error = NULL;
+	GetSecretsInfo *info;
+	GError *error = NULL;
+
+	info = g_malloc0 (sizeof (GetSecretsInfo));
+	info->callback = callback;
+	info->callback_data = user_data;
+
+	if (!internal_get_secrets (connection,
+	                           setting_name,
+	                           hints,
+	                           request_new,
+	                           TRUE,
+	                           get_secrets_cb,
+	                           info,
+	                           &error)) {
+		callback (NM_SETTINGS_CONNECTION_INTERFACE (connection), NULL, error, user_data);
+		g_error_free (error);
+		g_free (info);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/******************************************************/
+
+static gboolean
+is_dbus_request_authorized (DBusGMethodInvocation *context,
+                            gboolean allow_user,
+                            GError **error)
+{
+	DBusGConnection *bus = NULL;
+	DBusConnection *connection = NULL;
+	char *sender = NULL;
+	gulong sender_uid = G_MAXULONG;
+	DBusError dbus_error;
 	gboolean success = FALSE;
 
-	tmp = nm_connection_new_from_hash (new_settings, &local_error);
-	if (!tmp) {
-		nm_warning ("%s: Invalid connection: '%s' / '%s' invalid: %d",
-		            __func__,
-		            g_type_name (nm_connection_lookup_setting_type_by_quark (local_error->domain)),
-		            local_error->message, local_error->code);
+	sender = dbus_g_method_get_sender (context);
+	if (!sender) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		             "%s", "Could not determine D-Bus requestor");
+		goto out;
+	}
 
-		g_propagate_error (error, local_error);
-	} else {
-		/* Copy private values to the connection that actually gets saved */
-		nm_gconf_copy_private_connection_values (tmp, nm_exported_connection_get_connection (exported));
+	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+	if (!bus) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		             "%s", "Could not get the system bus");
+		goto out;
+	}
+	connection = dbus_g_connection_get_connection (bus);
+	if (!connection) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		             "%s", "Could not get the D-Bus system bus");
+		goto out;
+	}
 
-		nm_gconf_write_connection (tmp, priv->client, priv->dir);
-		g_object_unref (tmp);
+	dbus_error_init (&dbus_error);
+	sender_uid = dbus_bus_get_unix_user (connection, sender, &dbus_error);
+	if (dbus_error_is_set (&dbus_error)) {
+		dbus_error_free (&dbus_error);
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED,
+		             "%s", "Could not determine the Unix user ID of the requestor");
+		goto out;
+	}
 
-		gconf_client_notify (priv->client, priv->dir);
-		gconf_client_suggest_sync (priv->client, NULL);
+	/* And finally, the actual UID check */
+	if (   (allow_user && (sender_uid == geteuid()))
+	    || (sender_uid == 0))
 		success = TRUE;
+	else {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED,
+		             "%s", "Requestor UID does not match the UID of the user settings service");
 	}
 
+out:
+	if (bus)
+		dbus_g_connection_unref (bus);
+	g_free (sender);
 	return success;
 }
 
-static gboolean
-do_delete (NMExportedConnection *exported, GError **err)
+static void
+con_update_cb (NMSettingsConnectionInterface *connection,
+               GError *error,
+               gpointer user_data)
 {
-	NMAGConfConnectionPrivate *priv = NMA_GCONF_CONNECTION_GET_PRIVATE (exported);
-	gboolean success;
+	DBusGMethodInvocation *context = user_data;
 
-	success = gconf_client_recursive_unset (priv->client, priv->dir, 0, err);
-	gconf_client_suggest_sync (priv->client, NULL);
+	if (error)
+		dbus_g_method_return_error (context, error);
+	else
+		dbus_g_method_return (context);
+}
 
-	return success;
+static void
+dbus_update (NMExportedConnection *exported,
+             GHashTable *new_settings,
+             DBusGMethodInvocation *context)
+{
+	NMAGConfConnection *self = NMA_GCONF_CONNECTION (exported);
+	NMConnection *new;
+	gboolean success = FALSE;
+	GError *error = NULL;
+
+	/* Restrict Update to execution by the current user and root for DBus invocation */
+	if (!is_dbus_request_authorized (context, TRUE, &error)) {
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	new = nm_connection_new_from_hash (new_settings, &error);
+	if (!new) {
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+	g_object_unref (new);
+	
+	success = nm_connection_replace_settings (NM_CONNECTION (self), new_settings, NULL);
+	/* Settings better be valid; we verified them above */
+	g_assert (success);
+
+	nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (self),
+	                                         con_update_cb,
+	                                         context);
 }
 
-/* GObject */
+static void
+con_delete_cb (NMSettingsConnectionInterface *connection,
+               GError *error,
+               gpointer user_data)
+{
+	DBusGMethodInvocation *context = user_data;
+
+	if (error)
+		dbus_g_method_return_error (context, error);
+	else
+		dbus_g_method_return (context);
+}
+
+static void
+dbus_delete (NMExportedConnection *exported,
+             DBusGMethodInvocation *context)
+{
+	NMAGConfConnection *self = NMA_GCONF_CONNECTION (exported);
+	GError *error = NULL;
+
+	/* Restrict Update to execution by the current user and root for DBus invocation */
+	if (!is_dbus_request_authorized (context, TRUE, &error)) {
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (self),
+	                                         con_delete_cb,
+	                                         context);
+}
+
+static void
+dbus_get_secrets_cb (NMSettingsConnectionInterface *connection,
+                     GHashTable *settings,
+                     GError *error,
+                     gpointer user_data)
+{
+	DBusGMethodInvocation *context = user_data;
+
+	if (error)
+		dbus_g_method_return_error (context, error);
+	else
+		dbus_g_method_return (context, settings);
+}
+
+static void
+dbus_get_secrets (NMExportedConnection *connection,
+                  const gchar *setting_name,
+                  const gchar **hints,
+                  gboolean request_new,
+                  DBusGMethodInvocation *context)
+{
+	GError *error = NULL;
+
+	/* Restrict GetSecrets to execution by root for DBus invocation */
+	if (!is_dbus_request_authorized (context, FALSE, &error)) {
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	if (!internal_get_secrets (NM_SETTINGS_CONNECTION_INTERFACE (connection),
+	                           setting_name,
+	                           hints,
+	                           request_new,
+	                           FALSE,
+	                           dbus_get_secrets_cb,
+	                           context,
+	                           &error)) {
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+	}
+}
+
+static GHashTable *
+dbus_get_settings (NMExportedConnection *connection, GError **error)
+{
+	GHashTable *settings;
+	const char *user_name;
+	NMSettingVPN *s_vpn;
+	gboolean added = FALSE;
+
+	/* Insert the default VPN username when NM gets the connection; it doesn't
+	 * get stored in GConf since it's always available and could change at any
+	 * time, so it's inserted on-the-fly.
+	 */
+	s_vpn = NM_SETTING_VPN (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_VPN));
+	if (s_vpn) {
+		user_name = g_get_user_name ();
+		g_assert (g_utf8_validate (user_name, -1, NULL));
+		g_object_set (s_vpn, NM_SETTING_VPN_USER_NAME, user_name, NULL);
+		added = TRUE;
+	}
+
+	settings = NM_EXPORTED_CONNECTION_CLASS (nma_gconf_connection_parent_class)->get_settings (connection, error);
+
+	if (added)
+		g_object_set (s_vpn, NM_SETTING_VPN_USER_NAME, NULL, NULL);
+
+	return settings;
+}
+
+/************************************************************/
+
+static void
+settings_connection_interface_init (NMSettingsConnectionInterface *iface)
+{
+	parent_settings_connection_iface = g_type_interface_peek_parent (iface);
+
+	iface->update = update;
+	iface->delete = do_delete;
+	iface->get_secrets = get_secrets;
+}
 
 static void
 nma_gconf_connection_init (NMAGConfConnection *connection)
@@ -382,14 +859,11 @@ nma_gconf_connection_init (NMAGConfConnection *connection)
 
 static GObject *
 constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
 {
 	GObject *object;
 	NMAGConfConnectionPrivate *priv;
-	NMConnection *connection;
-	DBusGConnection *bus;
-	GError *error = NULL;
 
 	object = G_OBJECT_CLASS (nma_gconf_connection_parent_class)->constructor (type, n_construct_params, construct_params);
 
@@ -400,47 +874,17 @@ constructor (GType type,
 
 	if (!priv->client) {
 		nm_warning ("GConfClient not provided.");
-		goto err;
+		g_object_unref (object);
+		return NULL;
 	}
 
 	if (!priv->dir) {
 		nm_warning ("GConf directory not provided.");
-		goto err;
-	}
-
-	connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (object));
-
-	utils_fill_connection_certs (connection);
-	if (!nm_connection_verify (connection, &error)) {
-		utils_clear_filled_connection_certs (connection);
-		g_warning ("Invalid connection: '%s' / '%s' invalid: %d",
-		           g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)),
-		           error->message, error->code);
-		g_error_free (error);
-		goto err;
-	}
-	utils_clear_filled_connection_certs (connection);
-
-	fill_vpn_user_name (connection);
-
-	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-	if (!bus) {
-		nm_warning ("Could not get the system bus: %s", error->message);
-		g_error_free (error);
-		goto err;
+		g_object_unref (object);
+		return NULL;
 	}
 
-	nm_exported_connection_register_object (NM_EXPORTED_CONNECTION (object),
-	                                        NM_CONNECTION_SCOPE_USER,
-	                                        bus);
-	dbus_g_connection_unref (bus);
-
 	return object;
-
- err:
-	g_object_unref (object);
-
-	return NULL;
 }
 
 static void
@@ -508,12 +952,12 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nma_gconf_connection_class_init (NMAGConfConnectionClass *gconf_connection_class)
+nma_gconf_connection_class_init (NMAGConfConnectionClass *class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (gconf_connection_class);
-	NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (gconf_connection_class);
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+	NMExportedConnectionClass *ec_class = NM_EXPORTED_CONNECTION_CLASS (class);
 
-	g_type_class_add_private (gconf_connection_class, sizeof (NMAGConfConnectionPrivate));
+	g_type_class_add_private (class, sizeof (NMAGConfConnectionPrivate));
 
 	/* Virtual methods */
 	object_class->constructor  = constructor;
@@ -522,10 +966,10 @@ nma_gconf_connection_class_init (NMAGConfConnectionClass *gconf_connection_class
 	object_class->dispose      = dispose;
 	object_class->finalize     = finalize;
 
-	connection_class->get_settings = get_settings;
-	connection_class->service_get_secrets = service_get_secrets;
-	connection_class->update       = update;
-	connection_class->do_delete    = do_delete;
+	ec_class->update = dbus_update;
+	ec_class->delete = dbus_delete;
+	ec_class->get_secrets = dbus_get_secrets;
+	ec_class->get_settings = dbus_get_settings;
 
 	/* Properties */
 	g_object_class_install_property
@@ -551,7 +995,7 @@ nma_gconf_connection_class_init (NMAGConfConnectionClass *gconf_connection_class
 				    G_SIGNAL_RUN_FIRST,
 				    G_STRUCT_OFFSET (NMAGConfConnectionClass, new_secrets_requested),
 				    NULL, NULL,
-				    nma_marshal_VOID__STRING_POINTER_BOOLEAN_POINTER,
-				    G_TYPE_NONE, 4,
-				    G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_POINTER);
+				    nma_marshal_VOID__STRING_POINTER_BOOLEAN_POINTER_POINTER,
+				    G_TYPE_NONE, 5,
+				    G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER);
 }
diff --git a/src/gconf-helpers/nma-gconf-connection.h b/src/gconf-helpers/nma-gconf-connection.h
index da23244..296ca58 100644
--- a/src/gconf-helpers/nma-gconf-connection.h
+++ b/src/gconf-helpers/nma-gconf-connection.h
@@ -1,11 +1,32 @@
-/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
 
 #ifndef NMA_GCONF_CONNECTION_H
 #define NMA_GCONF_CONNECTION_H
 
 #include <gconf/gconf-client.h>
 #include <dbus/dbus-glib.h>
-#include <nm-settings.h>
+#include <nm-connection.h>
+#include <nm-exported-connection.h>
+#include <nm-settings-connection-interface.h>
 
 G_BEGIN_DECLS
 
@@ -23,6 +44,11 @@ typedef struct {
 	NMExportedConnection parent;
 } NMAGConfConnection;
 
+typedef void (*NMANewSecretsRequestedFunc) (NMSettingsConnectionInterface *connection,
+                                            GHashTable *settings,
+                                            GError *error,
+                                            gpointer user_data);
+
 typedef struct {
 	NMExportedConnectionClass parent;
 
@@ -37,17 +63,15 @@ typedef struct {
 GType nma_gconf_connection_get_type (void);
 
 NMAGConfConnection *nma_gconf_connection_new  (GConfClient *client,
-									  const char *conf_dir);
+                                               const char *conf_dir);
 
 NMAGConfConnection *nma_gconf_connection_new_from_connection (GConfClient *client,
-												  const char *conf_dir,
-												  NMConnection *connection);
-
-const char         *nma_gconf_connection_get_path (NMAGConfConnection *self);
+                                                              const char *conf_dir,
+                                                              NMConnection *connection);
 
-void                nma_gconf_connection_save (NMAGConfConnection *self);
+gboolean nma_gconf_connection_gconf_changed (NMAGConfConnection *self);
 
-gboolean            nma_gconf_connection_changed (NMAGConfConnection *self);
+const char *nma_gconf_connection_get_gconf_path (NMAGConfConnection *self);
 
 G_END_DECLS
 
diff --git a/src/gconf-helpers/nma-gconf-settings.c b/src/gconf-helpers/nma-gconf-settings.c
index cbe4c17..986d947 100644
--- a/src/gconf-helpers/nma-gconf-settings.c
+++ b/src/gconf-helpers/nma-gconf-settings.c
@@ -1,13 +1,32 @@
-/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ */
 
 #include <string.h>
 #include <stdio.h>
-#include <nm-utils.h>
+
 #include "nma-gconf-settings.h"
 #include "gconf-helpers.h"
 #include "nma-marshal.h"
+#include "nm-utils.h"
 
-G_DEFINE_TYPE (NMAGConfSettings, nma_gconf_settings, NM_TYPE_SETTINGS)
+G_DEFINE_TYPE (NMAGConfSettings, nma_gconf_settings, NM_TYPE_SETTINGS_SERVICE)
 
 #define NMA_GCONF_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMA_TYPE_GCONF_SETTINGS, NMAGConfSettingsPrivate))
 
@@ -31,9 +50,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 
 NMAGConfSettings *
-nma_gconf_settings_new (void)
+nma_gconf_settings_new (DBusGConnection *bus)
 {
-	return (NMAGConfSettings *) g_object_new (NMA_TYPE_GCONF_SETTINGS, NULL);
+	return (NMAGConfSettings *) g_object_new (NMA_TYPE_GCONF_SETTINGS,
+	                                          NM_SETTINGS_SERVICE_SCOPE, NM_CONNECTION_SCOPE_USER,
+	                                          NM_SETTINGS_SERVICE_BUS, bus,
+	                                          NULL);
 }
 
 static void
@@ -41,7 +63,8 @@ connection_new_secrets_requested_cb (NMAGConfConnection *connection,
                                      const char *setting_name,
                                      const char **hints,
                                      gboolean ask_user,
-                                     DBusGMethodInvocation *context,
+                                     NMANewSecretsRequestedFunc callback,
+                                     gpointer callback_data,
                                      gpointer user_data)
 {
 	NMAGConfSettings *self = NMA_GCONF_SETTINGS (user_data);
@@ -56,33 +79,57 @@ connection_new_secrets_requested_cb (NMAGConfConnection *connection,
 	               setting_name,
 	               hints,
 	               ask_user,
-	               context);
+	               callback,
+	               callback_data);
 }
 
 static void
-connection_removed (NMAGConfConnection *connection,
-				gpointer user_data)
+connection_removed (NMExportedConnection *connection, gpointer user_data)
 {
 	NMAGConfSettingsPrivate *priv = NMA_GCONF_SETTINGS_GET_PRIVATE (user_data);
 
 	priv->connections = g_slist_remove (priv->connections, connection);
+	g_object_unref (connection);
 }
 
 static void
-add_connection_real (NMAGConfSettings *self, NMAGConfConnection *connection)
+internal_add_connection (NMAGConfSettings *self, NMAGConfConnection *connection)
 {
 	NMAGConfSettingsPrivate *priv = NMA_GCONF_SETTINGS_GET_PRIVATE (self);
+	DBusGConnection *bus = NULL;
+
+	g_return_if_fail (connection != NULL);
+	g_return_if_fail (NMA_IS_GCONF_CONNECTION (connection));
+
+	priv->connections = g_slist_prepend (priv->connections, connection);
+	g_signal_connect (connection, "new-secrets-requested",
+	                  G_CALLBACK (connection_new_secrets_requested_cb),
+	                  self);
+
+	g_signal_connect (connection, "removed", G_CALLBACK (connection_removed), self);
 
-	if (connection) {
-		priv->connections = g_slist_prepend (priv->connections, connection);
-		g_signal_connect (connection, "new-secrets-requested",
-					   G_CALLBACK (connection_new_secrets_requested_cb),
-					   self);
+	g_object_get (G_OBJECT (self), NM_SETTINGS_SERVICE_BUS, &bus, NULL);
+	if (bus) {
+		nm_settings_service_export_connection (NM_SETTINGS_SERVICE (self),
+		                                       NM_SETTINGS_CONNECTION_INTERFACE (connection));
+		dbus_g_connection_unref (bus);
+	}
 
-		g_signal_connect (connection, "removed", G_CALLBACK (connection_removed), self);
+	g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_NEW_CONNECTION, NM_CONNECTION (connection));
+	g_return_if_fail (NMA_IS_GCONF_CONNECTION (priv->connections->data));
+}
 
-		nm_settings_signal_new_connection (NM_SETTINGS (self),
-									NM_EXPORTED_CONNECTION (connection));
+static void
+update_cb (NMSettingsConnectionInterface *connection,
+           GError *error,
+           gpointer user_data)
+{
+	if (error) {
+		g_warning ("%s: %s:%d error updating connection %s: (%d) %s",
+		           __func__, __FILE__, __LINE__,
+		           nma_gconf_connection_get_gconf_path (NMA_GCONF_CONNECTION (connection)),
+		           error ? error->code : -1,
+		           (error && error->message) ? error->message : "(unknown)");
 	}
 }
 
@@ -117,44 +164,45 @@ nma_gconf_settings_add_connection (NMAGConfSettings *self, NMConnection *connect
 
 	exported = nma_gconf_connection_new_from_connection (priv->client, path, connection);
 	g_free (path);
-	if (!exported)
-		return NULL;
-
-	add_connection_real (self, exported);
+	if (exported) {
+		internal_add_connection (self, exported);
 
-	/* Must save connection to GConf _after_ adding it to the connections
-	 * list to avoid races with GConf notifications.
-	 */
-	nma_gconf_connection_save (exported);
+		/* Must save connection to GConf _after_ adding it to the connections
+		 * list to avoid races with GConf notifications.
+		 */
+		nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported), update_cb, NULL);
+	}
 
 	return exported;
 }
 
-NMAGConfConnection *
-nma_gconf_settings_get_by_path (NMAGConfSettings *self, const char *path)
+static void
+add_connection (NMSettingsService *settings,
+                NMConnection *connection,
+                DBusGMethodInvocation *context, /* Only present for D-Bus calls */
+                NMSettingsAddConnectionFunc callback,
+                gpointer user_data)
 {
-	NMAGConfSettingsPrivate *priv;
-	GSList *iter;
-
-	g_return_val_if_fail (NMA_IS_GCONF_SETTINGS (self), NULL);
-	g_return_val_if_fail (path != NULL, NULL);
+	NMAGConfSettings *self = NMA_GCONF_SETTINGS (settings);
 
-	priv = NMA_GCONF_SETTINGS_GET_PRIVATE (self);
-	for (iter = priv->connections; iter; iter = iter->next) {
-		NMAGConfConnection *connection = NMA_GCONF_CONNECTION (iter->data);
-		const char *gconf_path;
+	/* For now, we don't support additions via D-Bus until we figure out
+	 * the security implications.
+	 */
+	if (context) {
+		GError *error;
 
-		gconf_path = nma_gconf_connection_get_path (connection);
-		if (gconf_path && !strcmp (gconf_path, path))
-			return connection;
+		error = g_error_new (0, 0, "%s: adding connections via D-Bus is not (yet) supported", __func__);
+		callback (NM_SETTINGS_INTERFACE (settings), error, user_data);
+		g_error_free (error);
+		return;
 	}
 
-	return NULL;
+	nma_gconf_settings_add_connection (self, connection);
+	callback (NM_SETTINGS_INTERFACE (settings), NULL, user_data);
 }
 
-NMAGConfConnection *
-nma_gconf_settings_get_by_dbus_path (NMAGConfSettings *self,
-							  const char *path)
+static NMAGConfConnection *
+get_connection_by_gconf_path (NMAGConfSettings *self, const char *path)
 {
 	NMAGConfSettingsPrivate *priv;
 	GSList *iter;
@@ -165,42 +213,16 @@ nma_gconf_settings_get_by_dbus_path (NMAGConfSettings *self,
 	priv = NMA_GCONF_SETTINGS_GET_PRIVATE (self);
 	for (iter = priv->connections; iter; iter = iter->next) {
 		NMAGConfConnection *connection = NMA_GCONF_CONNECTION (iter->data);
-		NMConnection *wrapped;
-		const char *sc_path;
-
-		wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
-		sc_path = nm_connection_get_path (wrapped);
+		const char *gconf_path;
 
-		if (sc_path && !strcmp (sc_path, path))
+		gconf_path = nma_gconf_connection_get_gconf_path (connection);
+		if (gconf_path && !strcmp (gconf_path, path))
 			return connection;
 	}
 
 	return NULL;
 }
 
-NMAGConfConnection *
-nma_gconf_settings_get_by_connection (NMAGConfSettings *self,
-							   NMConnection *connection)
-{
-	NMAGConfSettingsPrivate *priv;
-	GSList *iter;
-
-	g_return_val_if_fail (NMA_IS_GCONF_SETTINGS (self), NULL);
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	priv = NMA_GCONF_SETTINGS_GET_PRIVATE (self);
-
-	for (iter = priv->connections; iter; iter = iter->next) {
-		NMConnection *wrapped;
-
-		wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (iter->data));
-		if (connection == wrapped)
-			return NMA_GCONF_CONNECTION (iter->data);
-	}
-
-	return NULL;
-}
-
 static void
 read_connections (NMAGConfSettings *settings)
 {
@@ -214,8 +236,11 @@ read_connections (NMAGConfSettings *settings)
 
 	for (iter = dir_list; iter; iter = iter->next) {
 		char *dir = (char *) iter->data;
+		NMAGConfConnection *connection;
 
-		add_connection_real (settings, nma_gconf_connection_new (priv->client, dir));
+		connection = nma_gconf_connection_new (priv->client, dir);
+		if (connection)
+			internal_add_connection (settings, connection);
 		g_free (dir);
 	}
 
@@ -233,7 +258,7 @@ read_connections_cb (gpointer data)
 }
 
 static GSList *
-list_connections (NMSettings *settings)
+list_connections (NMSettingsService *settings)
 {
 	NMAGConfSettingsPrivate *priv = NMA_GCONF_SETTINGS_GET_PRIVATE (settings);
 
@@ -268,15 +293,16 @@ connection_changes_done (gpointer data)
 	NMAGConfSettingsPrivate *priv = NMA_GCONF_SETTINGS_GET_PRIVATE (info->settings);
 	NMAGConfConnection *connection;
 
-	connection = nma_gconf_settings_get_by_path (info->settings, info->path);
+	connection = get_connection_by_gconf_path (info->settings, info->path);
 	if (!connection) {
 		/* New connection */
 		connection = nma_gconf_connection_new (priv->client, info->path);
-		add_connection_real (info->settings, connection);
+		if (connection)
+			internal_add_connection (info->settings, connection);
 	} else {
 		if (gconf_client_dir_exists (priv->client, info->path, NULL)) {
 			/* Updated connection */
-			if (!nma_gconf_connection_changed (connection))
+			if (!nma_gconf_connection_gconf_changed (connection))
 				priv->connections = g_slist_remove (priv->connections, connection);
 		}
 	}
@@ -336,12 +362,12 @@ remove_pending_change (gpointer data)
 	g_source_remove (GPOINTER_TO_UINT (data));
 }
 
-/* GObject */
+/************************************************************/
 
 static void
-nma_gconf_settings_init (NMAGConfSettings *settings)
+nma_gconf_settings_init (NMAGConfSettings *self)
 {
-	NMAGConfSettingsPrivate *priv = NMA_GCONF_SETTINGS_GET_PRIVATE (settings);
+	NMAGConfSettingsPrivate *priv = NMA_GCONF_SETTINGS_GET_PRIVATE (self);
 
 	priv->client = gconf_client_get_default ();
 	priv->pending_changes = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, remove_pending_change);
@@ -352,10 +378,10 @@ nma_gconf_settings_init (NMAGConfSettings *settings)
 	                      NULL);
 
 	priv->conf_notify_id = gconf_client_notify_add (priv->client,
-										   GCONF_PATH_CONNECTIONS,
-										   (GConfClientNotifyFunc) connections_changed_cb,
-										   settings,
-										   NULL, NULL);
+	                                                GCONF_PATH_CONNECTIONS,
+	                                                (GConfClientNotifyFunc) connections_changed_cb,
+	                                                self,
+	                                                NULL, NULL);
 }
 
 static GObject *
@@ -364,17 +390,10 @@ constructor (GType type,
 		   GObjectConstructParam *construct_params)
 {
 	GObject *object;
-	NMAGConfSettingsPrivate *priv;
 
 	object = G_OBJECT_CLASS (nma_gconf_settings_parent_class)->constructor (type, n_construct_params, construct_params);
-
-	if (!object)
-		return NULL;
-
-	priv = NMA_GCONF_SETTINGS_GET_PRIVATE (object);
-
-	priv->read_connections_id = g_idle_add (read_connections_cb, object);
-
+	if (object)
+		NMA_GCONF_SETTINGS_GET_PRIVATE (object)->read_connections_id = g_idle_add (read_connections_cb, object);
 	return object;
 }
 
@@ -407,18 +426,19 @@ dispose (GObject *object)
 }
 
 static void
-nma_gconf_settings_class_init (NMAGConfSettingsClass *gconf_settings_class)
+nma_gconf_settings_class_init (NMAGConfSettingsClass *class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (gconf_settings_class);
-	NMSettingsClass *settings_class = NM_SETTINGS_CLASS (gconf_settings_class);
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+	NMSettingsServiceClass *settings_class = NM_SETTINGS_SERVICE_CLASS (class);
 
-	g_type_class_add_private (gconf_settings_class, sizeof (NMAGConfSettingsPrivate));
+	g_type_class_add_private (class, sizeof (NMAGConfSettingsPrivate));
 
 	/* Virtual methods */
 	object_class->constructor = constructor;
 	object_class->dispose = dispose;
 
 	settings_class->list_connections = list_connections;
+	settings_class->add_connection = add_connection;
 
 	/* Signals */
 	signals[NEW_SECRETS_REQUESTED] =
@@ -427,7 +447,7 @@ nma_gconf_settings_class_init (NMAGConfSettingsClass *gconf_settings_class)
 				    G_SIGNAL_RUN_FIRST,
 				    G_STRUCT_OFFSET (NMAGConfSettingsClass, new_secrets_requested),
 				    NULL, NULL,
-				    nma_marshal_VOID__OBJECT_STRING_POINTER_BOOLEAN_POINTER,
-				    G_TYPE_NONE, 5,
-				    G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_POINTER);
+				    nma_marshal_VOID__OBJECT_STRING_POINTER_BOOLEAN_POINTER_POINTER,
+				    G_TYPE_NONE, 6,
+				    G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER);
 }
diff --git a/src/gconf-helpers/nma-gconf-settings.h b/src/gconf-helpers/nma-gconf-settings.h
index 2011081..d197a35 100644
--- a/src/gconf-helpers/nma-gconf-settings.h
+++ b/src/gconf-helpers/nma-gconf-settings.h
@@ -1,11 +1,29 @@
-/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ */
 
 #ifndef NMA_GCONF_SETTINGS_H
 #define NMA_GCONF_SETTINGS_H
 
-#include <dbus/dbus-glib.h>
 #include <nm-connection.h>
-#include <nm-settings.h>
+#include <nm-settings-service.h>
+
 #include "nma-gconf-connection.h"
 
 G_BEGIN_DECLS
@@ -18,36 +36,28 @@ G_BEGIN_DECLS
 #define NMA_GCONF_SETTINGS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_GCONF_SETTINGS, NMAGConfSettingsClass))
 
 typedef struct {
-	NMSettings parent;
+	NMSettingsService parent;
 } NMAGConfSettings;
 
 typedef struct {
-	NMSettingsClass parent;
+	NMSettingsServiceClass parent;
 
 	/* Signals */
 	void (*new_secrets_requested) (NMAGConfSettings *self,
-							 NMAGConfConnection *exported,
-							 const char *setting_name,
-							 const char **hints,
-							 gboolean ask_user,
-							 DBusGMethodInvocation *context);
+	                               NMAGConfConnection *exported,
+	                               const char *setting_name,
+	                               const char **hints,
+	                               gboolean ask_user,
+	                               NMANewSecretsRequestedFunc callback,
+	                               gpointer callback_data);
 } NMAGConfSettingsClass;
 
 GType nma_gconf_settings_get_type (void);
 
-NMAGConfSettings *nma_gconf_settings_new (void);
+NMAGConfSettings *nma_gconf_settings_new (DBusGConnection *bus);
 
 NMAGConfConnection *nma_gconf_settings_add_connection (NMAGConfSettings *self,
-											NMConnection *connection);
-
-NMAGConfConnection *nma_gconf_settings_get_by_path (NMAGConfSettings *self,
-										  const char *path);
-
-NMAGConfConnection *nma_gconf_settings_get_by_dbus_path (NMAGConfSettings *self,
-											  const char *path);
-
-NMAGConfConnection *nma_gconf_settings_get_by_connection (NMAGConfSettings *self,
-											   NMConnection *connection);
+                                                       NMConnection *connection);
 
 G_END_DECLS
 
diff --git a/src/marshallers/nma-marshal.list b/src/marshallers/nma-marshal.list
index 8cb2830..4cf3524 100644
--- a/src/marshallers/nma-marshal.list
+++ b/src/marshallers/nma-marshal.list
@@ -1,4 +1,7 @@
 VOID:POINTER
 VOID:STRING,STRING,STRING
-VOID:STRING,POINTER,BOOLEAN,POINTER
-VOID:OBJECT,STRING,POINTER,BOOLEAN,POINTER
+VOID:STRING,POINTER,BOOLEAN,POINTER,POINTER
+VOID:OBJECT,STRING,POINTER,BOOLEAN,POINTER,POINTER
+VOID:POINTER,POINTER
+VOID:INT,POINTER
+
diff --git a/src/nmn-applet.h b/src/nmn-applet.h
index 314ffa7..48a3c65 100644
--- a/src/nmn-applet.h
+++ b/src/nmn-applet.h
@@ -26,6 +26,10 @@
 
 G_BEGIN_DECLS
 
+#define APPLET_PREFS_PATH "/apps/nm-applet"
+#define PREF_DISABLE_CONNECTED_NOTIFICATIONS	APPLET_PREFS_PATH "/disable-connected-notifications"
+#define PREF_DISABLE_DISCONNECTED_NOTIFICATIONS	APPLET_PREFS_PATH "/disable-disconnected-notifications"
+
 #define NMN_TYPE_APPLET            (nmn_applet_get_type ())
 #define NMN_APPLET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMN_TYPE_APPLET, NmnApplet))
 #define NMN_APPLET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NMN_TYPE_APPLET, NmnAppletClass))
diff --git a/src/nmn-device-handler.c b/src/nmn-device-handler.c
index 75fd5c2..d48f78a 100644
--- a/src/nmn-device-handler.c
+++ b/src/nmn-device-handler.c
@@ -17,6 +17,8 @@
  * (C) Copyright 2009 Novell, Inc.
  */
 
+#include <nm-settings-interface.h>
+#include <nm-setting-connection.h>
 #include "nmn-device-handler.h"
 
 G_DEFINE_TYPE (NmnDeviceHandler, nmn_device_handler, G_TYPE_OBJECT)
@@ -44,14 +46,13 @@ typedef struct {
     GSList *items;
     gboolean started;
     gulong device_state_changed_id;
-    gulong user_connection_added_id;
-    gulong system_connection_added_id;
+    gulong connection_added_id;
 
     gboolean disposed;
 } NmnDeviceHandlerPrivate;
 
 static void
-connection_added (NMSettings *settings,
+connection_added (NMSettingConnection *settings,
                   NMExportedConnection *exported,
                   gpointer user_data)
 {
@@ -101,7 +102,7 @@ device_state_changed (NMDevice *device,
 void
 nmn_device_handler_start (NmnDeviceHandler *self)
 {
-    NMSettings *settings;
+    NMSettingsInterface *settings;
     NmnDeviceHandlerPrivate *priv;
 
     g_return_if_fail (NMN_IS_DEVICE_HANDLER (self));
@@ -117,13 +118,8 @@ nmn_device_handler_start (NmnDeviceHandler *self)
 
     settings = nmn_nm_data_get_user_settings (priv->nm_data);
     if (settings)
-        priv->user_connection_added_id = g_signal_connect (settings, "new-connection",
-                                                           G_CALLBACK (connection_added), self);
-
-    settings = nmn_nm_data_get_system_settings (priv->nm_data);
-    if (settings)
-        priv->system_connection_added_id = g_signal_connect (settings, "new-connection",
-                                                             G_CALLBACK (connection_added), self);
+        priv->connection_added_id = g_signal_connect (settings, "new-connection",
+						      G_CALLBACK (connection_added), self);
 
     nmn_device_handler_add_items (self);
 }
@@ -180,7 +176,7 @@ GSList *
 nmn_device_handler_get_connections (NmnDeviceHandler *self)
 {
     NmnDeviceHandlerPrivate *priv;
-    NMSettings *settings;
+    NMSettingsInterface *settings;
     GSList *list = NULL;
 
     g_return_val_if_fail (NMN_IS_DEVICE_HANDLER (self), NULL);
@@ -189,11 +185,7 @@ nmn_device_handler_get_connections (NmnDeviceHandler *self)
 
     settings = nmn_nm_data_get_user_settings (priv->nm_data);
     if (settings)
-        list = nm_settings_list_connections (settings);
-
-    settings = nmn_nm_data_get_system_settings (priv->nm_data);
-    if (settings)
-        list = g_slist_concat (list, nm_settings_list_connections (settings));
+        list = nm_settings_interface_list_connections (settings);
 
     return list;
 }
@@ -210,7 +202,7 @@ nmn_device_handler_get_item_for_connection (NmnDeviceHandler *self,
 
     list = GET_PRIVATE (self)->items;
     for (iter = list; iter; iter = iter->next) {
-        if (nmn_network_item_get_connection (NMN_NETWORK_ITEM (iter->data)) == connection)
+        if (nmn_network_item_get_connection (NMN_NETWORK_ITEM (iter->data)) == NM_EXPORTED_CONNECTION (connection))
             return NMN_NETWORK_ITEM (iter->data);
     }
 
@@ -310,7 +302,7 @@ static void
 dispose (GObject *object)
 {
     NmnDeviceHandlerPrivate *priv = GET_PRIVATE (object);
-    NMSettings *settings;
+    NMSettingsInterface *settings;
 
     if (priv->disposed)
         return;
@@ -318,10 +310,7 @@ dispose (GObject *object)
     g_signal_handler_disconnect (priv->device, priv->device_state_changed_id);
 
     settings = nmn_nm_data_get_user_settings (priv->nm_data);
-    g_signal_handler_disconnect (settings, priv->user_connection_added_id);
-
-    settings = nmn_nm_data_get_system_settings (priv->nm_data);
-    g_signal_handler_disconnect (settings, priv->system_connection_added_id);
+    g_signal_handler_disconnect (settings, priv->connection_added_id);
 
     g_slist_foreach (priv->items, (GFunc) g_object_unref, NULL);
     g_slist_free (priv->items);
diff --git a/src/nmn-device-handler.h b/src/nmn-device-handler.h
index 7ffa0f5..15d4b9b 100644
--- a/src/nmn-device-handler.h
+++ b/src/nmn-device-handler.h
@@ -22,7 +22,7 @@
 
 #include <glib-object.h>
 #include <nm-device.h>
-#include <nm-settings.h>
+#include <nm-exported-connection.h>
 #include "nmn-nm-data.h"
 #include "nmn-network-item.h"
 
diff --git a/src/nmn-ethernet-handler.c b/src/nmn-ethernet-handler.c
index d8430c7..aca4de6 100644
--- a/src/nmn-ethernet-handler.c
+++ b/src/nmn-ethernet-handler.c
@@ -18,7 +18,6 @@
  */
 
 #include <string.h>
-#include <nm-settings.h>
 #include "nmn-ethernet-handler.h"
 #include "nmn-ethernet-item.h"
 #include "utils.h"
@@ -75,7 +74,7 @@ connection_added (NmnDeviceHandler *handler,
     if (!nm_device_ethernet_get_carrier (device))
         return;
 
-    wrapped = nm_exported_connection_get_connection (exported);
+    wrapped = NM_CONNECTION (exported);
     if (utils_connection_valid_for_device (wrapped, NM_DEVICE (device), NULL) &&
         !have_item_for_connection (handler, exported)) {
         item = nmn_ethernet_item_new (nmn_device_handler_get_nm_data (handler), device);
diff --git a/src/nmn-ethernet-item.c b/src/nmn-ethernet-item.c
index 692ac11..c1d4edf 100644
--- a/src/nmn-ethernet-item.c
+++ b/src/nmn-ethernet-item.c
@@ -65,34 +65,45 @@ nmn_ethernet_item_new (NmnNMData *nm_data,
                                      NULL));
 }
 
+static void
+update_cb (NMSettingsConnectionInterface *connection,
+	   GError *error,
+	   gpointer data)
+{
+	NMSettingConnection *s_con;
+	NmnNetworkItem *item = data;
+
+	if (error != NULL) {
+		g_warning ("Updating auto-connect for ethernet failed: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+	s_con = NM_SETTING_CONNECTION (connection);
+	if (nm_setting_connection_get_autoconnect (s_con) == TRUE) {
+		NMN_NETWORK_ITEM_CLASS (nmn_ethernet_item_parent_class)->connect (item);
+	} else {
+		NMN_NETWORK_ITEM_CLASS (nmn_ethernet_item_parent_class)->disconnect (item);
+	}
+}
+
 static gboolean
 update_autoconnect (NmnNetworkItem *item, gboolean connect_automatically)
 {
     NMExportedConnection *exported;
     NMConnection *wrapped;
     NMSettingConnection *s_con;
-    GHashTable *new_settings;
     GError *error = NULL;
 
     exported = nmn_network_item_get_connection (item);
-    wrapped = nm_exported_connection_get_connection (exported);
+    wrapped = NM_CONNECTION (exported);
     s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION));
 
     if (nm_setting_connection_get_autoconnect (s_con) == connect_automatically)
         return FALSE;
 
     g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, connect_automatically, NULL);
-    new_settings = nm_connection_to_hash (wrapped);
-
-    if (!nm_exported_connection_update (exported, new_settings, &error)) {
-        if (error) {
-            g_warning ("Couldn't update ethernet connection: %s", error->message);
-            g_error_free (error);
-        } else
-            g_warning ("Couldn't update ethernet connection: no details");
-    }
-
-    g_hash_table_unref (new_settings);
+    nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (s_con),
+    					     update_cb, item);
 
     return TRUE;
 }
@@ -101,7 +112,6 @@ static void
 connect (NmnNetworkItem *item)
 {
     update_autoconnect (NMN_NETWORK_ITEM (item), TRUE);
-    NMN_NETWORK_ITEM_CLASS (nmn_ethernet_item_parent_class)->connect (item);
 }
 
 static void
@@ -109,7 +119,6 @@ disconnect (NmnNetworkItem *item)
 {
     /* Turn off autoconnect, otherwise it would reconnect right back. */
     update_autoconnect (item, FALSE);
-    NMN_NETWORK_ITEM_CLASS (nmn_ethernet_item_parent_class)->disconnect (item);
 }
 
 static guint
diff --git a/src/nmn-network-item.c b/src/nmn-network-item.c
index 55dd055..63410ee 100644
--- a/src/nmn-network-item.c
+++ b/src/nmn-network-item.c
@@ -119,7 +119,7 @@ update_details (NmnNetworkItem *self)
     if (!priv->details || !priv->connection)
         return;
 
-    connection = nm_exported_connection_get_connection (priv->connection);
+    connection = NM_CONNECTION (priv->connection);
     setting = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
 
     if (nm_device_get_state (priv->device) == NM_DEVICE_STATE_ACTIVATED)
@@ -195,7 +195,7 @@ update_item (NmnNetworkItem *self)
 
     g_assert (priv->connection);
 
-    wrapped = nm_exported_connection_get_connection (priv->connection);
+    wrapped = NM_CONNECTION (priv->connection);
     s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION));
 
     nmn_item_set_name (item, nm_setting_connection_get_id (s_con));
@@ -319,7 +319,7 @@ connection_secrets_requested_cb (NMExportedConnection *connection,
     else {
         GError *error = NULL;
 
-        g_set_error_literal (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
+        g_set_error_literal (&error, NM_SETTINGS_INTERFACE_ERROR, NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE,
                              G_STRLOC "no secrets found");
 
         g_warning ("%s", error->message);
@@ -336,8 +336,10 @@ connect_cb (gpointer user_data,
     /* FIXME: Report the error somewhere */
 }
 
-static gboolean
-delayed_connect (gpointer data)
+static void
+update_cb (NMSettingsConnectionInterface *connection,
+	   GError *error,
+	   gpointer data)
 {
     NmnItem *item = NMN_ITEM (data);
     NmnNetworkItemPrivate *priv = GET_PRIVATE (item);
@@ -347,7 +349,13 @@ delayed_connect (gpointer data)
     const char *specific_object;
     NMConnectionScope scope;
 
-    wrapped = nm_exported_connection_get_connection (priv->connection);
+    if (error != NULL) {
+    	    g_warning ("Updating settings failed: %s", error->message);
+    	    g_error_free (error);
+    	    return;
+    }
+
+    wrapped = NM_CONNECTION (priv->connection);
     path = nm_connection_get_path (wrapped);
     scope = nm_connection_get_scope (wrapped);
 
@@ -366,8 +374,13 @@ delayed_connect (gpointer data)
                                    specific_object,
                                    connect_cb,
                                    NULL);
+}
 
-    return FALSE;
+static gboolean
+delayed_connect (gpointer data)
+{
+	update_cb (NULL, NULL, data);
+	return FALSE;
 }
 
 static void
@@ -386,21 +399,16 @@ connect (NmnNetworkItem *item)
         NMSetting *current_config;
         NMSetting *new_config;
 
-        wrapped = nm_exported_connection_get_connection (priv->connection);
+        wrapped = NM_CONNECTION (priv->connection);
         current_config = nm_connection_get_setting (wrapped, NM_TYPE_SETTING_IP4_CONFIG);
         new_config = NM_SETTING (nmn_connection_details_get_data (NMN_CONNECTION_DETAILS (details)));
         g_assert (new_config);
 
         if (current_config == NULL || nm_setting_compare (current_config, new_config, 0) == FALSE) {
-            GHashTable *new_settings;
-
             nm_connection_add_setting (wrapped, new_config);
-            new_settings = nm_connection_to_hash (wrapped);
-            nm_exported_connection_update (priv->connection, new_settings, NULL);
-            g_hash_table_unref (new_settings);
+            nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (new_config),
+            					     update_cb, item);
 
-            /* Ugh... Give NM a bit of time to get the new values */
-            g_timeout_add_seconds (1, delayed_connect, item);
             return;
         }
     }
@@ -539,7 +547,8 @@ item_delete (NmnNetworkItem *item)
     NMExportedConnection *exported = nmn_network_item_get_connection (item);
 
     if (exported)
-        nm_exported_connection_delete (exported, NULL);
+    	nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (exported),
+    						 NULL, NULL);
 }
 
 static guint
diff --git a/src/nmn-network-item.h b/src/nmn-network-item.h
index 497376e..726baaf 100644
--- a/src/nmn-network-item.h
+++ b/src/nmn-network-item.h
@@ -22,7 +22,7 @@
 
 #include <gtk/gtk.h>
 #include <dbus/dbus-glib.h>
-#include <nm-settings.h>
+#include <nm-exported-connection.h>
 #include "nmn-item.h"
 #include "nmn-connection-details.h"
 #include "nmn-nm-data.h"
diff --git a/src/nmn-networks.c b/src/nmn-networks.c
index 7ae135e..fc26945 100644
--- a/src/nmn-networks.c
+++ b/src/nmn-networks.c
@@ -20,7 +20,6 @@
 #include <string.h>
 #include <glib/gi18n.h>
 #include <NetworkManager.h>
-#include <nm-settings.h>
 #include <nm-device-ethernet.h>
 #include <nm-device-wifi.h>
 #include "nmn-networks.h"
@@ -172,7 +171,7 @@ find_ac_for_item (NmnNetworks *self, NmnNetworkItem *item)
     int i;
 
     acs = nm_client_get_active_connections (NM_CLIENT (priv->nm_data));
-    connection = nm_exported_connection_get_connection (nmn_network_item_get_connection (item));
+    connection = NM_CONNECTION (nmn_network_item_get_connection (item));
     path = nm_connection_get_path (connection);
     scope = nm_connection_get_scope (connection);
 
diff --git a/src/nmn-nm-data.c b/src/nmn-nm-data.c
index f095888..ac02135 100644
--- a/src/nmn-nm-data.c
+++ b/src/nmn-nm-data.c
@@ -17,7 +17,7 @@
  * (C) Copyright 2009 Novell, Inc.
  */
 
-#include <nm-dbus-settings-system.h>
+#include <nm-remote-settings.h>
 #include "nmn-nm-data.h"
 #include "nma-gconf-settings.h"
 
@@ -37,8 +37,8 @@ static guint signals[LAST_SIGNAL];
 #define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NMN_TYPE_NM_DATA, NmnNMDataPrivate))
 
 typedef struct {
-    NMSettings *user_settings;
-    NMSettings *system_settings;
+    NMSettingsInterface *user_settings;
+    NMSettingsInterface *system_settings;
 
     gboolean ethernet_active;
     gboolean wifi_active;
@@ -57,7 +57,7 @@ nmn_nm_data_new (DBusGConnection *bus)
                                       NULL));
 }
 
-NMSettings *
+NMSettingsInterface *
 nmn_nm_data_get_user_settings (NmnNMData *self)
 {
     g_return_val_if_fail (NMN_IS_NM_DATA (self), NULL);
@@ -65,7 +65,7 @@ nmn_nm_data_get_user_settings (NmnNMData *self)
     return GET_PRIVATE (self)->user_settings;
 }
 
-NMSettings *
+NMSettingsInterface *
 nmn_nm_data_get_system_settings (NmnNMData *self)
 {
     g_return_val_if_fail (NMN_IS_NM_DATA (self), NULL);
@@ -235,8 +235,8 @@ constructor (GType type,
 	priv = GET_PRIVATE (object);
 
     bus = nm_object_get_connection (NM_OBJECT (object));
-    priv->user_settings = NM_SETTINGS (nma_gconf_settings_new ());
-    priv->system_settings = NM_SETTINGS (nm_dbus_settings_system_new (bus));
+    priv->user_settings = NM_SETTINGS_INTERFACE (nma_gconf_settings_new (bus));
+    priv->system_settings = NM_SETTINGS_INTERFACE (nm_remote_settings_new (bus, NM_CONNECTION_SCOPE_SYSTEM));
 
     g_signal_connect (object,
                       "notify::" NM_CLIENT_STATE,
diff --git a/src/nmn-nm-data.h b/src/nmn-nm-data.h
index 894da91..c099661 100644
--- a/src/nmn-nm-data.h
+++ b/src/nmn-nm-data.h
@@ -22,7 +22,7 @@
 
 #include <dbus/dbus-glib.h>
 #include <nm-client.h>
-#include <nm-settings.h>
+#include <nm-settings-interface.h>
 
 #define NMN_TYPE_NM_DATA            (nmn_nm_data_get_type ())
 #define NMN_NM_DATA(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMN_TYPE_NM_DATA, NmnNMData))
@@ -55,9 +55,9 @@ typedef struct {
 
 GType nmn_nm_data_get_type (void);
 
-NmnNMData  *nmn_nm_data_new                     (DBusGConnection *bus);
-NMSettings *nmn_nm_data_get_user_settings       (NmnNMData *data);
-NMSettings *nmn_nm_data_get_system_settings     (NmnNMData *data);
+NmnNMData  *nmn_nm_data_new                              (DBusGConnection *bus);
+NMSettingsInterface *nmn_nm_data_get_user_settings       (NmnNMData *data);
+NMSettingsInterface *nmn_nm_data_get_system_settings     (NmnNMData *data);
 
 gboolean    nmn_nm_data_ethernet_get_active     (NmnNMData *self); 
 void        nmn_nm_data_ethernet_toggled        (NmnNMData *self,
diff --git a/src/nmn-serial-handler.c b/src/nmn-serial-handler.c
index 0fe7fd4..53d2b12 100644
--- a/src/nmn-serial-handler.c
+++ b/src/nmn-serial-handler.c
@@ -17,7 +17,6 @@
  * (C) Copyright 2009 Novell, Inc.
  */
 
-#include <nm-settings.h>
 #include "nmn-serial-handler.h"
 #include "nmn-serial-item.h"
 #include "utils.h"
@@ -53,7 +52,7 @@ connection_added (NmnDeviceHandler *handler,
     NMDevice *device;
     GtkWidget *item;
 
-    wrapped = nm_exported_connection_get_connection (exported);
+    wrapped = NM_CONNECTION (exported);
     device = nmn_device_handler_get_device (handler);
 
     if (!utils_connection_valid_for_device (wrapped, device, NULL))
diff --git a/src/nmn-wifi-handler.c b/src/nmn-wifi-handler.c
index 27c8bfc..1ba8098 100644
--- a/src/nmn-wifi-handler.c
+++ b/src/nmn-wifi-handler.c
@@ -18,7 +18,6 @@
  */
 
 #include <string.h>
-#include <nm-settings.h>
 #include <nm-setting-connection.h>
 #include <nm-setting-wireless.h>
 #include "nmn-wifi-handler.h"
@@ -101,7 +100,7 @@ find_best_ap_for_connection (NMDeviceWifi *device,
     NMAccessPoint *best_ap = NULL;
     int i;
 
-    wrapped = nm_exported_connection_get_connection (connection);
+    wrapped = NM_CONNECTION (connection);
     aps = nm_device_wifi_get_access_points (device);
     for (i = 0; aps && i < aps->len; i++) {
         NMAccessPoint *ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i));
@@ -189,7 +188,7 @@ connection_added (NmnDeviceHandler *handler,
     NMAccessPoint *ap;
     GtkWidget *item;
 
-    wrapped = nm_exported_connection_get_connection (exported);
+    wrapped = NM_CONNECTION (exported);
     s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION));
     connection_type = nm_setting_connection_get_connection_type (s_con);
 
diff --git a/src/nmn-wifi-item.c b/src/nmn-wifi-item.c
index 0ee9d2c..a1c9713 100644
--- a/src/nmn-wifi-item.c
+++ b/src/nmn-wifi-item.c
@@ -428,6 +428,27 @@ wireless_dialog_response_cb (NMAWirelessDialog *dialog,
     gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
+static void
+update_cb (NMSettingsConnectionInterface *connection,
+	   GError *error,
+	   gpointer data)
+{
+	NMSettingConnection *s_con;
+	NmnNetworkItem *item = data;
+
+	if (error != NULL) {
+		g_warning ("Updating auto-connect for wifi failed: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+	s_con = NM_SETTING_CONNECTION (connection);
+	if (nm_setting_connection_get_autoconnect (s_con) == TRUE) {
+		NMN_NETWORK_ITEM_CLASS (nmn_wifi_item_parent_class)->connect (item);
+	} else {
+		NMN_NETWORK_ITEM_CLASS (nmn_wifi_item_parent_class)->disconnect (item);
+	}
+}
+
 static gboolean
 update_autoconnect (NmnNetworkItem *item, gboolean connect_automatically)
 {
@@ -437,17 +458,16 @@ update_autoconnect (NmnNetworkItem *item, gboolean connect_automatically)
     GHashTable *new_settings;
 
     exported = nmn_network_item_get_connection (item);
-    wrapped = nm_exported_connection_get_connection (exported);
+    wrapped = NM_CONNECTION (exported);
     s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION));
 
     if (nm_setting_connection_get_autoconnect (s_con) == connect_automatically)
         return FALSE;
 
     g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, connect_automatically, NULL);
-    new_settings = nm_connection_to_hash (wrapped);
 
-    nm_exported_connection_update (exported, new_settings, NULL);
-    g_hash_table_unref (new_settings);
+    nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (s_con),
+    					     update_cb, item);
 
     return TRUE;
 }
@@ -517,14 +537,12 @@ add_one_setting (GHashTable *settings,
 {
     GHashTable *secrets;
 
-    utils_fill_connection_certs (connection);
     secrets = nm_setting_to_hash (setting);
-    utils_clear_filled_connection_certs (connection);
 
     if (secrets) {
         g_hash_table_insert (settings, g_strdup (nm_setting_get_name (setting)), secrets);
     } else {
-        g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INTERNAL_ERROR,
+        g_set_error (error, NM_SETTINGS_INTERFACE_ERROR, NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
                      G_STRLOC ": failed to hash setting '%s'.",
                      nm_setting_get_name (setting));
     }
@@ -550,17 +568,17 @@ secrets_requested_response_cb (NMAWirelessDialog *dialog,
     GError *error = NULL;
 
     if (response != GTK_RESPONSE_OK) {
-        g_set_error_literal (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED,
+        g_set_error_literal (&error, NM_SETTINGS_INTERFACE_ERROR, NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED,
                              G_STRLOC ": canceled");
         goto done;
     }
 
-    wrapped = nm_exported_connection_get_connection (info->exported);
+    wrapped = NM_CONNECTION (info->exported);
 
     /* Second-guess which setting NM wants secrets for. */
     s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_WIRELESS_SECURITY));
     if (!s_wireless_sec) {
-        g_set_error_literal (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+        g_set_error_literal (&error, NM_SETTINGS_INTERFACE_ERROR, NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
                              G_STRLOC ": requested setting '802-11-wireless-security'"
                              " didn't exist in the connection.");
         goto done;  /* Unencrypted */
@@ -589,7 +607,7 @@ secrets_requested_response_cb (NMAWirelessDialog *dialog,
 
             s_8021x = (NMSetting8021x *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_802_1X);
             if (!s_8021x) {
-                g_set_error_literal (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+                g_set_error_literal (&error, NM_SETTINGS_INTERFACE_ERROR, NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
                                      G_STRLOC ": requested setting '802-1x' didn't"
                                      " exist in the connection.");
                 goto done;
@@ -643,7 +661,7 @@ secrets_requested (NmnNetworkItem *network_item,
 
     exported = nmn_network_item_get_connection (network_item);
     dialog = nma_wireless_dialog_new (NM_CLIENT (nmn_network_item_get_nm_data (network_item)),
-                                      nm_exported_connection_get_connection (exported),
+                                      NM_CONNECTION (exported),
                                       nmn_network_item_get_device (network_item),
                                       nmn_wifi_item_get_ap (NMN_WIFI_ITEM (network_item)));
 
diff --git a/src/nmn-wifi-list.c b/src/nmn-wifi-list.c
index 3cdbf5c..662b34e 100644
--- a/src/nmn-wifi-list.c
+++ b/src/nmn-wifi-list.c
@@ -74,9 +74,9 @@ matching_connection_exists (NmnWifiList *list, NMDevice *device, NMAccessPoint *
     GSList *iter;
     gboolean exists = FALSE;
 
-    connections = nm_settings_list_connections (nmn_nm_data_get_user_settings (priv->nm_data));
+    connections = nm_settings_interface_list_connections (nmn_nm_data_get_user_settings (priv->nm_data));
     for (iter = connections; iter; iter = iter->next) {
-        NMConnection *connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (iter->data));
+        NMConnection *connection = NM_CONNECTION (NM_EXPORTED_CONNECTION (iter->data));
 
         if (utils_connection_valid_for_device (connection, device, ap)) {
             exists = TRUE;
diff --git a/src/utils.c b/src/utils.c
index 0486678..575f94b 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -27,6 +27,7 @@
 #include <moblin-panel/mpl-panel-client.h>
 #include <nm-device-ethernet.h>
 #include <nm-device-wifi.h>
+#include <nm-device-bt.h>
 #include <nm-gsm-device.h>
 #include <nm-cdma-device.h>
 #include <nm-access-point.h>
@@ -38,6 +39,7 @@
 #include <nm-setting-gsm.h>
 #include <nm-setting-cdma.h>
 #include <nm-setting-pppoe.h>
+#include <nm-setting-bluetooth.h>
 #include <nm-utils.h>
 
 #include "utils.h"
@@ -81,6 +83,7 @@ static char *ignored_words[] = {
 	"Components",
 	"Corporation",
 	"Communications",
+	"Company",
 	"Corp.",
 	"Corp",
 	"Co.",
@@ -93,6 +96,7 @@ static char *ignored_words[] = {
 	"adapter",
 	"[hex]",
 	"NDIS",
+	"Module",
 	NULL
 };
 
@@ -114,6 +118,7 @@ static char *ignored_phrases[] = {
 	"Communication S.p.A.",
 	"Business Mobile Networks BV",
 	"Mobile Broadband Minicard Composite Device",
+	"Mobile Communications AB",
 	NULL
 };
 
@@ -133,12 +138,11 @@ fixup_desc_string (const char *desc)
 
 	/* Attempt to shorten ID by ignoring certain phrases */
 	for (item = ignored_phrases; *item; item++) {
-		guint32 temp_len = strlen (temp);
 		guint32 ignored_len = strlen (*item);
 
 		p = strstr (temp, *item);
 		if (p)
-			memmove (p, p + ignored_len, temp_len - (p - temp));
+			memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */
 	}
 
 	/* Attmept to shorten ID by ignoring certain individual words */
@@ -218,142 +222,6 @@ utils_get_device_description (NMDevice *device)
 	return description;
 }
 
-static GByteArray *
-file_to_g_byte_array (const char *filename)
-{
-	char *contents = NULL;
-	GByteArray *array = NULL;
-	gsize length = 0;
-
-	if (!g_file_get_contents (filename, &contents, &length, NULL))
-		return NULL;
-
-	array = g_byte_array_sized_new (length);
-	if (!array) {
-		g_free (contents);
-		return NULL;
-	}
-
-	g_byte_array_append (array, (unsigned char *) contents, length);
-	return array;
-}
-
-static gboolean
-fill_one_private_key (NMConnection *connection,
-                      const char *pk_tag,
-                      const char *pk_prop,
-                      const char *cc_prop)
-{
-	const char *filename;
-	NMSetting8021x *tmp;
-	NMSetting8021xCKType pk_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
-	gboolean need_client_cert = TRUE;
-
-	/* If the private key is PKCS#12, don't set the client cert */
-	filename = g_object_get_data (G_OBJECT (connection), pk_tag);
-	if (!filename)
-		return TRUE;
-
-	tmp = NM_SETTING_802_1X (nm_setting_802_1x_new ());
-	nm_setting_802_1x_set_private_key_from_file (tmp, filename, NULL, &pk_type, NULL);
-	if (pk_type == NM_SETTING_802_1X_CK_TYPE_PKCS12) {
-		GByteArray *array;
-
-		array = file_to_g_byte_array (filename);
-		if (array) {
-			NMSetting *s_8021x = nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
-
-			g_object_set (s_8021x,
-			              pk_prop, array,
-			              cc_prop, array,
-			              NULL);
-			g_byte_array_free (array, TRUE);
-			need_client_cert = FALSE;
-		}
-	}
-	g_object_unref (tmp);
-	return need_client_cert;
-}
-
-void
-utils_fill_connection_certs (NMConnection *connection)
-{
-	NMSetting8021x *s_8021x;
-	const char *filename;
-	GError *error = NULL;
-	gboolean need_client_cert = TRUE;
-
-	g_return_if_fail (connection != NULL);
-
-	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X));
-	if (!s_8021x)
-		return;
-
-	filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG);
-	if (filename) {
-		if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, filename, NULL, &error))
-			g_warning ("%s: couldn't read CA certificate: %d %s", __func__, error->code, error->message);
-		g_clear_error (&error);
-	}
-
-	/* If the private key is PKCS#12, don't set the client cert */
-	need_client_cert = fill_one_private_key (connection,
-	                                         NMA_PATH_PRIVATE_KEY_TAG,
-	                                         NM_SETTING_802_1X_PRIVATE_KEY,
-	                                         NM_SETTING_802_1X_CLIENT_CERT);
-	if (need_client_cert) {
-		filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CLIENT_CERT_TAG);
-		if (filename) {
-			if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, filename, NULL, &error))
-				g_warning ("%s: couldn't read client certificate: %d %s", __func__, error->code, error->message);
-			g_clear_error (&error);
-		}
-	}
-
-	filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PHASE2_CA_CERT_TAG);
-	if (filename) {
-		if (!nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, filename, NULL, &error))
-			g_warning ("%s: couldn't read phase2 CA certificate: %d %s", __func__, error->code, error->message);
-		g_clear_error (&error);
-	}
-
-	/* If the private key is PKCS#12, don't set the client cert */
-	need_client_cert = fill_one_private_key (connection,
-	                                         NMA_PATH_PHASE2_PRIVATE_KEY_TAG,
-	                                         NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
-	                                         NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
-	if (need_client_cert) {
-		filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PHASE2_CLIENT_CERT_TAG);
-		if (filename) {
-			if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, filename, NULL, &error))
-				g_warning ("%s: couldn't read phase2 client certificate: %d %s", __func__, error->code, error->message);
-			g_clear_error (&error);
-		}
-	}
-}
-
-void
-utils_clear_filled_connection_certs (NMConnection *connection)
-{
-	NMSetting8021x *s_8021x;
-
-	g_return_if_fail (connection != NULL);
-
-	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X));
-	if (!s_8021x)
-		return;
-
-	g_object_set (s_8021x,
-	              NM_SETTING_802_1X_CA_CERT, NULL,
-	              NM_SETTING_802_1X_CLIENT_CERT, NULL,
-	              NM_SETTING_802_1X_PRIVATE_KEY, NULL,
-	              NM_SETTING_802_1X_PHASE2_CA_CERT, NULL,
-	              NM_SETTING_802_1X_PHASE2_CLIENT_CERT, NULL,
-	              NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, NULL,
-	              NULL);
-}
-
-
 struct cf_pair {
 	guint32 chan;
 	guint32 freq;
@@ -773,6 +641,66 @@ connection_valid_for_cdma (NMConnection *connection,
 	return TRUE;
 }
 
+static guint32
+get_connection_bt_type (NMConnection *connection)
+{
+	NMSettingBluetooth *s_bt;
+	const char *bt_type;
+
+	s_bt = (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
+	if (!s_bt)
+		return NM_BT_CAPABILITY_NONE;
+
+	bt_type = nm_setting_bluetooth_get_connection_type (s_bt);
+	g_assert (bt_type);
+
+	if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN))
+		return NM_BT_CAPABILITY_DUN;
+	else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU))
+		return NM_BT_CAPABILITY_NAP;
+
+	return NM_BT_CAPABILITY_NONE;
+}
+
+static gboolean
+connection_valid_for_bt (NMConnection *connection,
+                         NMSettingConnection *s_con,
+                         NMDevice *device,
+                         gpointer specific_object)
+{
+	NMSettingBluetooth *s_bt;
+	const GByteArray *array;
+	char *str;
+	const char *hw_addr;
+	int addr_match = FALSE;
+	guint32 bt_type;
+
+	if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME))
+		return FALSE;
+
+	s_bt = NM_SETTING_BLUETOOTH (nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH));
+	if (!s_bt)
+		return FALSE;
+
+	array = nm_setting_bluetooth_get_bdaddr (s_bt);
+	if (!array || (array->len != ETH_ALEN))
+		return FALSE;
+
+	bt_type = get_connection_bt_type (connection);
+	if (!(bt_type & nm_device_bt_get_capabilities (NM_DEVICE_BT (device))))
+		return FALSE;
+
+	str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+	                       array->data[0], array->data[1], array->data[2],
+	                       array->data[3], array->data[4], array->data[5]);
+	hw_addr = nm_device_bt_get_hw_address (NM_DEVICE_BT (device));
+	if (hw_addr)
+		addr_match = !g_ascii_strcasecmp (hw_addr, str);
+	g_free (str);
+
+	return addr_match;
+}
+
 gboolean
 utils_connection_valid_for_device (NMConnection *connection,
                                    NMDevice *device,
@@ -795,6 +723,8 @@ utils_connection_valid_for_device (NMConnection *connection,
 		return connection_valid_for_gsm (connection, s_con, device, specific_object);
 	else if (NM_IS_CDMA_DEVICE (device))
 		return connection_valid_for_cdma (connection, s_con, device, specific_object);
+	else if (NM_IS_DEVICE_BT (device))
+		return connection_valid_for_bt (connection, s_con, device, specific_object);
 	else
 		g_warning ("Unknown device type '%s'", g_type_name (G_OBJECT_TYPE(device)));
 
@@ -858,6 +788,46 @@ utils_ether_ntop (const struct ether_addr *mac)
 	                        mac->ether_addr_octet[4], mac->ether_addr_octet[5]);
 }
 
+char *
+utils_next_available_name (GSList *connections, const char *format)
+{
+	GSList *names = NULL, *iter;
+	char *cname = NULL;
+	int i = 0;
+
+	for (iter = connections; iter; iter = g_slist_next (iter)) {
+		NMConnection *candidate = NM_CONNECTION (iter->data);
+		NMSettingConnection *s_con;
+		const char *id;
+
+		s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION));
+		id = nm_setting_connection_get_id (s_con);
+		g_assert (id);
+		names = g_slist_append (names, (gpointer) id);
+	}	
+
+	/* Find the next available unique connection name */
+	while (!cname && (i++ < 10000)) {
+		char *temp;
+		gboolean found = FALSE;
+
+		temp = g_strdup_printf (format, i);
+		for (iter = names; iter; iter = g_slist_next (iter)) {
+			if (!strcmp (iter->data, temp)) {
+				found = TRUE;
+				break;
+			}
+		}
+		if (!found)
+			cname = temp;
+		else
+			g_free (temp);
+	}
+
+	g_slist_free (names);
+	return cname;
+}
+
 static MplPanelClient *main_widget = NULL;
 
 static void
diff --git a/src/utils.h b/src/utils.h
index 396b2b1..d4dd553 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -31,11 +31,7 @@
 
 char * utils_bin2hexstr (const char *bytes, int len, int final_len);
 
-const char * utils_get_device_description (NMDevice *device);
-
-void utils_fill_connection_certs (NMConnection *connection);
-
-void utils_clear_filled_connection_certs (NMConnection *connection);
+const char *utils_get_device_description (NMDevice *device);
 
 guint32 utils_freq_to_channel (guint32 freq);
 guint32 utils_channel_to_freq (guint32 channel, char *band);
@@ -53,6 +49,8 @@ char *utils_ether_ntop (const struct ether_addr *mac);
 
 gboolean utils_mac_valid (const struct ether_addr *addr);
 
+char *utils_next_available_name (GSList *connections, const char *format);
+
 /* Ugh, please avert your eyes... */
 void utils_set_main_widget (GObject *panel_client);
 void utils_hide_main_widget (void);
diff --git a/src/wireless-dialog.c b/src/wireless-dialog.c
index 6b5788e..aa860ac 100644
--- a/src/wireless-dialog.c
+++ b/src/wireless-dialog.c
@@ -37,7 +37,6 @@
 #include <nm-setting-connection.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-ip4-config.h>
-#include <nm-settings.h>
 
 #include "wireless-dialog.h"
 #include "wireless-security.h"
diff --git a/src/wireless-security/Makefile.am b/src/wireless-security/Makefile.am
index 4e6aea1..ad019d7 100644
--- a/src/wireless-security/Makefile.am
+++ b/src/wireless-security/Makefile.am
@@ -33,6 +33,7 @@ libwireless_security_la_SOURCES = \
 libwireless_security_la_CPPFLAGS = \
 	$(NMN_CFLAGS) \
 	-I${top_srcdir}/src/gconf-helpers \
+	-I${top_srcdir}/src/ \
 	-DUIDIR=\""$(uidir)"\"
 
 libwireless_security_la_LIBADD = \
diff --git a/src/wireless-security/eap-method-peap.c b/src/wireless-security/eap-method-peap.c
index 7d3b1e9..893c1c8 100644
--- a/src/wireless-security/eap-method-peap.c
+++ b/src/wireless-security/eap-method-peap.c
@@ -22,6 +22,7 @@
 #include <glib/gi18n.h>
 #include <ctype.h>
 #include <string.h>
+#include <nm-setting-connection.h>
 #include <nm-setting-8021x.h>
 
 #include "eap-method.h"
@@ -108,7 +109,9 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 static void
 fill_connection (EAPMethod *parent, NMConnection *connection)
 {
+	NMSettingConnection *s_con;
 	NMSetting8021x *s_8021x;
+	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 	GtkWidget *widget;
 	const char *text;
 	char *filename;
@@ -116,6 +119,10 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	GtkTreeModel *model;
 	GtkTreeIter iter;
 	int peapver_active = 0;
+	GError *error = NULL;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
 
 	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X));
 	g_assert (s_8021x);
@@ -131,19 +138,14 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
 	g_assert (widget);
 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
-	if (filename) {
-		g_object_set_data_full (G_OBJECT (connection),
-		                        NMA_PATH_CA_CERT_TAG, g_strdup (filename),
-		                        (GDestroyNotify) g_free);
-		g_free (filename);
-	} else {
-		g_object_set_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG, NULL);
+	if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+		g_clear_error (&error);
 	}
 
-	if (eap_method_get_ignore_ca_cert (parent))
-		g_object_set_data (G_OBJECT (connection), NMA_CA_CERT_IGNORE_TAG, GUINT_TO_POINTER (TRUE));
-	else
-		g_object_set_data (G_OBJECT (connection), NMA_CA_CERT_IGNORE_TAG, NULL);
+	nm_gconf_set_ignore_ca_cert (nm_setting_connection_get_uuid (s_con),
+	                             FALSE,
+	                             eap_method_get_ignore_ca_cert (parent));
 
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
 	peapver_active = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
@@ -275,7 +277,7 @@ eap_method_peap_new (WirelessSecurity *parent,
 
 	builder = EAP_METHOD (method)->builder;
 
-	eap_method_nag_init (EAP_METHOD (method), "ca-nag-dialog.ui", "eap_peap_ca_cert_button", connection);
+	eap_method_nag_init (EAP_METHOD (method), "ca-nag-dialog.ui", "eap_peap_ca_cert_button", connection, FALSE);
 
 	method->sec_parent = parent;
 
@@ -292,10 +294,12 @@ eap_method_peap_new (WirelessSecurity *parent,
 	                  parent);
 	filter = eap_method_default_file_chooser_filter_new (FALSE);
 	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
-	if (connection) {
-		filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG);
-		if (filename)
-			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+	if (connection && s_8021x) {
+		if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+			filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+			if (filename)
+				gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+		}
 	}
 
 	widget = inner_auth_combo_init (method, connection);
diff --git a/src/wireless-security/eap-method-tls.c b/src/wireless-security/eap-method-tls.c
index 62448c9..707d43e 100644
--- a/src/wireless-security/eap-method-tls.c
+++ b/src/wireless-security/eap-method-tls.c
@@ -24,6 +24,7 @@
 #include <glib/gi18n.h>
 #include <ctype.h>
 #include <string.h>
+#include <nm-setting-connection.h>
 #include <nm-setting-8021x.h>
 
 #include "gconf-helpers.h"
@@ -131,12 +132,17 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 {
 	EAPMethodTLS *method = (EAPMethodTLS *) parent;
 	NMSetting8021xCKType key_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
+	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 	NMSetting8021x *s_8021x;
+	NMSettingConnection *s_con;
 	GtkWidget *widget;
 	char *filename, *pk_filename, *cc_filename;
 	char *password = NULL;
 	GError *error = NULL;
 
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+
 	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X));
 	g_assert (s_8021x);
 
@@ -149,37 +155,24 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	g_assert (widget);
 	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
 
+
+	/* TLS private key */
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
 	g_assert (widget);
 	password = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
-	if (method->phase2) {
-		g_object_set_data_full (G_OBJECT (connection),
-		                        NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG,
-		                        password,
-		                        (GDestroyNotify) free_password);
-	} else {
-		g_object_set_data_full (G_OBJECT (connection),
-		                        NMA_PRIVATE_KEY_PASSWORD_TAG,
-		                        password,
-		                        (GDestroyNotify) free_password);
-	}
 
-	/* TLS private key */
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
 	g_assert (widget);
 	pk_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
 	g_assert (pk_filename);
-	g_object_set_data_full (G_OBJECT (connection),
-	                        method->phase2 ? NMA_PATH_PHASE2_PRIVATE_KEY_TAG : NMA_PATH_PRIVATE_KEY_TAG,
-	                        g_strdup (pk_filename),
-	                        (GDestroyNotify) g_free);
+
 	if (method->phase2) {
-		if (!nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, pk_filename, password, &key_type, &error)) {
+		if (!nm_setting_802_1x_set_phase2_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
 			g_warning ("Couldn't read phase2 private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
 			g_clear_error (&error);
 		}
 	} else {
-		if (!nm_setting_802_1x_set_private_key_from_file (s_8021x, pk_filename, password, &key_type, &error)) {
+		if (!nm_setting_802_1x_set_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
 			g_warning ("Couldn't read private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
 			g_clear_error (&error);
 		}
@@ -196,10 +189,17 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	}
 
 	g_assert (cc_filename);
-	g_object_set_data_full (G_OBJECT (connection),
-	                        method->phase2 ? NMA_PATH_PHASE2_CLIENT_CERT_TAG : NMA_PATH_CLIENT_CERT_TAG,
-	                        g_strdup (cc_filename),
-	                        (GDestroyNotify) g_free);
+	if (method->phase2) {
+		if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read phase2 client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
+	} else {
+		if (!nm_setting_802_1x_set_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
+	}
 	g_free (cc_filename);
 	g_free (pk_filename);
 
@@ -207,27 +207,23 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_button"));
 	g_assert (widget);
 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
-	if (filename) {
-		g_object_set_data_full (G_OBJECT (connection),
-		                        method->phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG,
-		                        g_strdup (filename),
-		                        (GDestroyNotify) g_free);
-		g_free (filename);
-	} else {
-		g_object_set_data (G_OBJECT (connection),
-		                   method->phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG,
-		                   NULL);
-	}
 
-	if (eap_method_get_ignore_ca_cert (parent)) {
-		g_object_set_data (G_OBJECT (connection),
-		                   method->phase2 ? NMA_PHASE2_CA_CERT_IGNORE_TAG : NMA_CA_CERT_IGNORE_TAG,
-		                   GUINT_TO_POINTER (TRUE));
+	format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	if (method->phase2) {
+		if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read phase2 CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
 	} else {
-		g_object_set_data (G_OBJECT (connection),
-		                   method->phase2 ? NMA_PHASE2_CA_CERT_IGNORE_TAG : NMA_CA_CERT_IGNORE_TAG,
-		                   NULL);
+		if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
 	}
+
+	nm_gconf_set_ignore_ca_cert (nm_setting_connection_get_uuid (s_con),
+				     method->phase2,
+				     eap_method_get_ignore_ca_cert (parent));
 }
 
 static void
@@ -276,48 +272,50 @@ static void reset_filter (GtkWidget *widget, GParamSpec *spec, gpointer user_dat
 	}
 }
 
+typedef const char * (*PathFunc) (NMSetting8021x *setting);
+typedef NMSetting8021xCKScheme (*SchemeFunc)  (NMSetting8021x *setting);
+
 static void
 setup_filepicker (GtkBuilder *builder,
                   const char *name,
                   const char *title,
                   WirelessSecurity *parent,
                   EAPMethodTLS *method,
-                  NMConnection *connection,
-                  const char *tag)
+                  NMSetting8021x *s_8021x,
+                  SchemeFunc scheme_func,
+                  PathFunc path_func,
+                  gboolean privkey,
+                  gboolean client_cert)
 {
 	GtkWidget *widget;
 	GtkFileFilter *filter;
 	const char *filename = NULL;
-	gboolean privkey = FALSE, client_cert = FALSE;
-
-	if (!strcmp (tag, NMA_PATH_PHASE2_PRIVATE_KEY_TAG) || !strcmp (tag, NMA_PATH_PRIVATE_KEY_TAG))
-		privkey = TRUE;
-	if (!strcmp (tag, NMA_PATH_PHASE2_CLIENT_CERT_TAG) || !strcmp (tag, NMA_PATH_CLIENT_CERT_TAG))
-		client_cert = TRUE;
 
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, name));
 	g_assert (widget);
 	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
 	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget), title);
 
-	if (connection && tag) {
-		filename = g_object_get_data (G_OBJECT (connection), tag);
-		if (filename)
-			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+	if (s_8021x && path_func && scheme_func) {
+		if (scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+			filename = path_func (s_8021x);
+			if (filename)
+				gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+		}
 	}
 
 	/* Connect a special handler for private keys to intercept PKCS#12 key types
 	 * and desensitize the user cert button.
 	 */
 	if (privkey) {
-		g_signal_connect (G_OBJECT (widget), "file-set",
+		g_signal_connect (G_OBJECT (widget), "selection-changed",
 		                  (GCallback) private_key_picker_file_set_cb,
 		                  method);
 		if (filename)
 			private_key_picker_helper ((EAPMethod *) method, filename, FALSE);
 	}
 
-	g_signal_connect (G_OBJECT (widget), "file-set",
+	g_signal_connect (G_OBJECT (widget), "selection-changed",
 	                  (GCallback) wireless_security_changed_cb,
 	                  parent);
 
@@ -352,7 +350,7 @@ eap_method_tls_new (WirelessSecurity *parent,
 
 	builder = EAP_METHOD (method)->builder;
 
-	eap_method_nag_init (EAP_METHOD (method), "ca-nag-dialog.ui", "eap_tls_ca_cert_button", connection);
+	eap_method_nag_init (EAP_METHOD (method), "ca-nag-dialog.ui", "eap_tls_ca_cert_button", connection, phase2);
 
 	method->phase2 = phase2;
 
@@ -385,20 +383,25 @@ eap_method_tls_new (WirelessSecurity *parent,
 	g_signal_connect (G_OBJECT (widget), "changed",
 	                  (GCallback) wireless_security_changed_cb,
 	                  parent);
-
 	setup_filepicker (builder, "eap_tls_user_cert_button",
 	                  _("Choose your personal certificate..."),
-	                  parent, method, connection,
-	                  phase2 ? NMA_PATH_PHASE2_CLIENT_CERT_TAG : NMA_PATH_CLIENT_CERT_TAG);
+	                  parent, method, s_8021x,
+	                  phase2 ? nm_setting_802_1x_get_phase2_client_cert_scheme : nm_setting_802_1x_get_client_cert_scheme,
+	                  phase2 ? nm_setting_802_1x_get_phase2_client_cert_path : nm_setting_802_1x_get_client_cert_path,
+	                  FALSE, TRUE);
 	setup_filepicker (builder, "eap_tls_ca_cert_button",
 	                  _("Choose a Certificate Authority certificate..."),
-	                  parent, method, connection,
-	                  phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG);
+	                  parent, method, s_8021x,
+	                  phase2 ? nm_setting_802_1x_get_phase2_ca_cert_scheme : nm_setting_802_1x_get_ca_cert_scheme,
+	                  phase2 ? nm_setting_802_1x_get_phase2_ca_cert_path : nm_setting_802_1x_get_ca_cert_path,
+	                  FALSE, FALSE);
 	setup_filepicker (builder,
 	                  "eap_tls_private_key_button",
 	                  _("Choose your private key..."),
-	                  parent, method, connection,
-	                  phase2 ? NMA_PATH_PHASE2_PRIVATE_KEY_TAG : NMA_PATH_PRIVATE_KEY_TAG);
+	                  parent, method, s_8021x,
+	                  phase2 ? nm_setting_802_1x_get_phase2_private_key_scheme : nm_setting_802_1x_get_private_key_scheme,
+	                  phase2 ? nm_setting_802_1x_get_phase2_private_key_path : nm_setting_802_1x_get_private_key_path,
+	                  TRUE, FALSE);
 
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "eap_tls_show_checkbutton"));
 	g_assert (widget);
diff --git a/src/wireless-security/eap-method-ttls.c b/src/wireless-security/eap-method-ttls.c
index 1852fe9..d53f61e 100644
--- a/src/wireless-security/eap-method-ttls.c
+++ b/src/wireless-security/eap-method-ttls.c
@@ -22,6 +22,7 @@
 #include <glib/gi18n.h>
 #include <ctype.h>
 #include <string.h>
+#include <nm-setting-connection.h>
 #include <nm-setting-8021x.h>
 
 #include "eap-method.h"
@@ -104,13 +105,19 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 static void
 fill_connection (EAPMethod *parent, NMConnection *connection)
 {
+	NMSettingConnection *s_con;
 	NMSetting8021x *s_8021x;
+	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 	GtkWidget *widget;
 	const char *text;
 	char *filename;
 	EAPMethod *eap = NULL;
 	GtkTreeModel *model;
 	GtkTreeIter iter;
+	GError *error = NULL;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
 
 	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X));
 	g_assert (s_8021x);
@@ -126,19 +133,14 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
 	g_assert (widget);
 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
-	if (filename) {
-		g_object_set_data_full (G_OBJECT (connection),
-		                        NMA_PATH_CA_CERT_TAG, g_strdup (filename),
-		                        (GDestroyNotify) g_free);
-		g_free (filename);
-	} else {
-		g_object_set_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG, NULL);
+	if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+		g_clear_error (&error);
 	}
 
-	if (eap_method_get_ignore_ca_cert (parent))
-		g_object_set_data (G_OBJECT (connection), NMA_CA_CERT_IGNORE_TAG, GUINT_TO_POINTER (TRUE));
-	else
-		g_object_set_data (G_OBJECT (connection), NMA_CA_CERT_IGNORE_TAG, NULL);
+	nm_gconf_set_ignore_ca_cert (nm_setting_connection_get_uuid (s_con),
+	                             FALSE,
+	                             eap_method_get_ignore_ca_cert (parent));
 
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
@@ -305,7 +307,7 @@ eap_method_ttls_new (WirelessSecurity *parent,
 
 	builder = EAP_METHOD (method)->builder;
 
-	eap_method_nag_init (EAP_METHOD (method), "ca-nag-dialog.ui", "eap_ttls_ca_cert_button", connection);
+	eap_method_nag_init (EAP_METHOD (method), "ca-nag-dialog.ui", "eap_ttls_ca_cert_button", connection, FALSE);
 
 	method->sec_parent = parent;
 
@@ -322,10 +324,12 @@ eap_method_ttls_new (WirelessSecurity *parent,
 	                  parent);
 	filter = eap_method_default_file_chooser_filter_new (FALSE);
 	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
-	if (connection) {
-		filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG);
-		if (filename)
-			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+	if (connection && s_8021x) {
+		if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+			filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+			if (filename)
+				gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+		}
 	}
 
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "eap_ttls_anon_identity_entry"));
diff --git a/src/wireless-security/eap-method.c b/src/wireless-security/eap-method.c
index 6339f59..edf4eaa 100644
--- a/src/wireless-security/eap-method.c
+++ b/src/wireless-security/eap-method.c
@@ -31,6 +31,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <nm-setting-connection.h>
 #include <nm-setting-8021x.h>
 #include "eap-method.h"
 #include "gconf-helpers.h"
@@ -139,7 +140,8 @@ gboolean
 eap_method_nag_init (EAPMethod *method,
 				 const char *ui_file,
                      const char *ca_cert_chooser,
-                     NMConnection *connection)
+                     NMConnection *connection,
+                     gboolean phase2)
 {
 	GtkWidget *dialog;
 	char *path;
@@ -165,8 +167,17 @@ eap_method_nag_init (EAPMethod *method,
 	g_free (path);
 
 	method->ca_cert_chooser = g_strdup (ca_cert_chooser);
-	if (connection)
-		method->ignore_ca_cert = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), NMA_CA_CERT_IGNORE_TAG));
+	if (connection) {
+		NMSettingConnection *s_con;
+		const char *uuid;
+
+		s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+		g_assert (s_con);
+		uuid = nm_setting_connection_get_uuid (s_con);
+		g_assert (uuid);
+
+		method->ignore_ca_cert = nm_gconf_get_ignore_ca_cert (uuid, phase2);
+	}
 
 	dialog = GTK_WIDGET (gtk_builder_get_object (method->builder, "nag_user_dialog"));
 	g_assert (dialog);
diff --git a/src/wireless-security/eap-method.h b/src/wireless-security/eap-method.h
index 3ebb5ac..0263cc1 100644
--- a/src/wireless-security/eap-method.h
+++ b/src/wireless-security/eap-method.h
@@ -101,7 +101,8 @@ gboolean eap_method_validate_filepicker (GtkBuilder *builder,
 gboolean eap_method_nag_init (EAPMethod *method,
 			      const char *ui_file,
                               const char *ca_cert_chooser,
-                              NMConnection *connection);
+                              NMConnection *connection,
+                              gboolean phase2);
 
 gboolean eap_method_get_ignore_ca_cert (EAPMethod *method);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]