[gnome-keyring] Update for GckBuilder changes in libgck



commit e10549d7f3a9ae2a649473cd771948914b15be79
Author: Stef Walter <stefw collabora co uk>
Date:   Tue Dec 6 21:34:13 2011 +0100

    Update for GckBuilder changes in libgck
    
     * Updated for builder and immutable GckAttributes
     * Remove deprecated functions

 configure.ac                             |    2 +-
 daemon/dbus/gkd-secret-change.c          |   16 ++-
 daemon/dbus/gkd-secret-create.c          |   28 ++--
 daemon/dbus/gkd-secret-lock.c            |   10 +-
 daemon/dbus/gkd-secret-objects.c         |  127 +++++++---------
 daemon/dbus/gkd-secret-property.c        |  111 ++++++++------
 daemon/dbus/gkd-secret-property.h        |    8 +-
 daemon/dbus/gkd-secret-service.c         |   22 ++--
 daemon/dbus/gkd-secret-session.c         |   56 +++----
 daemon/dbus/gkd-secret-unlock.c          |   45 +++---
 daemon/gpg-agent/gkd-gpg-agent-ops.c     |   83 +++++-----
 daemon/login/gkd-login.c                 |   60 +++-----
 daemon/ssh-agent/gkd-ssh-agent-ops.c     |  247 ++++++++++++++++--------------
 daemon/ssh-agent/gkd-ssh-agent-private.h |   28 ++--
 daemon/ssh-agent/gkd-ssh-agent-proto.c   |  128 +++++++++-------
 daemon/ssh-agent/gkd-ssh-agent.c         |    4 +-
 tool/gkr-tool-import.c                   |    2 +-
 17 files changed, 499 insertions(+), 478 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index ecb4772..82fd8b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -196,7 +196,7 @@ fi
 # --------------------------------------------------------------------
 # GCR and GCK libraries
 
-PKG_CHECK_MODULES(GCK, gck-1 >= 3.3.1)
+PKG_CHECK_MODULES(GCK, gck-1 >= 3.3.3)
 PKG_CHECK_MODULES(GCR, gcr-3 >= 3.3.1)
 PKG_CHECK_MODULES(GCR_BASE, gcr-base-3 >= 3.3.1)
 
diff --git a/daemon/dbus/gkd-secret-change.c b/daemon/dbus/gkd-secret-change.c
index 90f3ed5..bd51239 100644
--- a/daemon/dbus/gkd-secret-change.c
+++ b/daemon/dbus/gkd-secret-change.c
@@ -265,6 +265,7 @@ gboolean
 gkd_secret_change_with_secrets (GckObject *collection, GkdSecretSecret *original,
                                 GkdSecretSecret *master, DBusError *derr)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
 	GckAttributes *attrs = NULL;
 	gboolean result = FALSE;
@@ -272,22 +273,25 @@ gkd_secret_change_with_secrets (GckObject *collection, GkdSecretSecret *original
 	GckObject *mcred = NULL;
 
 	/* Create the new credential */
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_CREDENTIAL);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 	mcred = gkd_secret_session_create_credential (master->session, NULL, attrs, master, derr);
 	if (mcred == NULL)
 		goto cleanup;
 
+	gck_builder_add_all (&builder, attrs);
+	gck_attributes_unref (attrs);
+
 	/* Create the original credential, in order to make sure we can the collection */
-	gck_attributes_add_ulong (attrs, CKA_G_OBJECT, gck_object_get_handle (collection));
+	gck_builder_add_ulong (&builder, CKA_G_OBJECT, gck_object_get_handle (collection));
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 	ocred = gkd_secret_session_create_credential (original->session, NULL, attrs, original, derr);
 	if (ocred == NULL)
 		goto cleanup;
 
 	gck_attributes_unref (attrs);
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_G_CREDENTIAL, gck_object_get_handle (mcred));
+	gck_builder_add_ulong (&builder, CKA_G_CREDENTIAL, gck_object_get_handle (mcred));
 
 	/* Now set the collection credentials to the first one */
 	result = gck_object_set (collection, attrs, NULL, &error);
diff --git a/daemon/dbus/gkd-secret-create.c b/daemon/dbus/gkd-secret-create.c
index bdca3e2..a9c88d7 100644
--- a/daemon/dbus/gkd-secret-create.c
+++ b/daemon/dbus/gkd-secret-create.c
@@ -340,32 +340,28 @@ GckObject*
 gkd_secret_create_with_credential (GckSession *session, GckAttributes *attrs,
                                    GckObject *cred, GError **error)
 {
-	GckAttributes *atts;
-	GckAttribute *attr;
-	GckObject *collection;
+	GckBuilder builder = GCK_BUILDER_INIT;
+	const GckAttribute *attr;
 	gboolean token;
 
-	atts = gck_attributes_new ();
-	gck_attributes_add_ulong (atts, CKA_G_CREDENTIAL, gck_object_get_handle (cred));
-	gck_attributes_add_ulong (atts, CKA_CLASS, CKO_G_COLLECTION);
+	gck_builder_add_ulong (&builder, CKA_G_CREDENTIAL, gck_object_get_handle (cred));
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
 
 	attr = gck_attributes_find (attrs, CKA_LABEL);
 	if (attr != NULL)
-		gck_attributes_add (atts, attr);
+		gck_builder_add_owned (&builder, attr);
 	if (!gck_attributes_find_boolean (attrs, CKA_TOKEN, &token))
 		token = FALSE;
-	gck_attributes_add_boolean (atts, CKA_TOKEN, token);
-
-	collection = gck_session_create_object (session, atts, NULL, error);
-	gck_attributes_unref (atts);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, token);
 
-	return collection;
+	return gck_session_create_object (session, gck_builder_end (&builder), NULL, error);
 }
 
 gchar*
 gkd_secret_create_with_secret (GckAttributes *attrs, GkdSecretSecret *master,
                                DBusError *derr)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *atts;
 	GckObject *cred;
 	GckObject *collection;
@@ -379,15 +375,15 @@ gkd_secret_create_with_secret (GckAttributes *attrs, GkdSecretSecret *master,
 	if (!gck_attributes_find_boolean (attrs, CKA_TOKEN, &token))
 		token = FALSE;
 
-	atts = gck_attributes_new ();
-	gck_attributes_add_ulong (atts, CKA_CLASS, CKO_G_CREDENTIAL);
-	gck_attributes_add_boolean (atts, CKA_GNOME_TRANSIENT, TRUE);
-	gck_attributes_add_boolean (atts, CKA_TOKEN, token);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
+	gck_builder_add_boolean (&builder, CKA_GNOME_TRANSIENT, TRUE);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, token);
 
 	session = gkd_secret_session_get_pkcs11_session (master->session);
 	g_return_val_if_fail (session, NULL);
 
 	/* Create ourselves some credentials */
+	atts = gck_attributes_ref_sink (gck_builder_end (&builder));
 	cred = gkd_secret_session_create_credential (master->session, session, atts, master, derr);
 	gck_attributes_unref (atts);
 
diff --git a/daemon/dbus/gkd-secret-lock.c b/daemon/dbus/gkd-secret-lock.c
index ff7a080..9b68c46 100644
--- a/daemon/dbus/gkd-secret-lock.c
+++ b/daemon/dbus/gkd-secret-lock.c
@@ -33,21 +33,19 @@
 gboolean
 gkd_secret_lock (GckObject *collection, DBusError *derr)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
 	GList *objects, *l;
-	GckAttributes *atts;
 	GckSession *session;
 
-	atts = gck_attributes_new ();
-	gck_attributes_add_ulong (atts, CKA_CLASS, CKO_G_CREDENTIAL);
-	gck_attributes_add_ulong (atts, CKA_G_OBJECT, gck_object_get_handle (collection));
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
+	gck_builder_add_ulong (&builder, CKA_G_OBJECT, gck_object_get_handle (collection));
 
 	session = gck_object_get_session (collection);
 	g_return_val_if_fail (session, FALSE);
 
-	objects = gck_session_find_objects (session, atts, NULL, &error);
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
-	gck_attributes_unref (atts);
 	g_object_unref (session);
 
 	if (error != NULL) {
diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c
index a6657f9..28a243d 100644
--- a/daemon/dbus/gkd-secret-objects.c
+++ b/daemon/dbus/gkd-secret-objects.c
@@ -125,9 +125,8 @@ static DBusMessage*
 object_property_set (GckObject *object, DBusMessage *message,
                      DBusMessageIter *iter, const gchar *prop_name)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	DBusMessage *reply;
-	GckAttributes *attrs;
-	GckAttribute *attr;
 	GError *error = NULL;
 	gulong attr_type;
 
@@ -138,19 +137,14 @@ object_property_set (GckObject *object, DBusMessage *message,
 		return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED,
 		                                      "Object does not have the '%s' property", prop_name);
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_empty (attrs, attr_type);
-	attr = gck_attributes_at (attrs, 0);
-
 	/* Retrieve the actual attribute value */
-	if (!gkd_secret_property_parse_variant (iter, prop_name, attr)) {
-		gck_attributes_unref (attrs);
+	if (!gkd_secret_property_parse_variant (iter, prop_name, &builder)) {
+		gck_builder_clear (&builder);
 		return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED,
 		                                      "The property type or value was invalid: %s", prop_name);
 	}
 
-	gck_object_set (object, attrs, NULL, &error);
-	gck_attributes_unref (attrs);
+	gck_object_set (object, gck_builder_end (&builder), NULL, &error);
 
 	if (error != NULL) {
 		if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN))
@@ -508,10 +502,12 @@ collection_method_search_items (GkdSecretObjects *self, GckObject *object, DBusM
 }
 
 static GckObject*
-collection_find_matching_item (GkdSecretObjects *self, GckSession *session,
-                               const gchar *identifier, GckAttribute *fields)
+collection_find_matching_item (GkdSecretObjects *self,
+                               GckSession *session,
+                               const gchar *identifier,
+                               const GckAttribute *fields)
 {
-	GckAttributes *attrs;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckObject *result = NULL;
 	GError *error = NULL;
 	GckObject *search;
@@ -519,15 +515,13 @@ collection_find_matching_item (GkdSecretObjects *self, GckSession *session,
 	gsize n_data;
 
 	/* Find items matching the collection and fields */
-	attrs = gck_attributes_new ();
-	gck_attributes_add (attrs, fields);
-	gck_attributes_add_string (attrs, CKA_G_COLLECTION, identifier);
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_SEARCH);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
+	gck_builder_add_owned (&builder, fields);
+	gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
 
 	/* Create the search object */
-	search = gck_session_create_object (session, attrs, NULL, &error);
-	gck_attributes_unref (attrs);
+	search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
 
 	if (error != NULL) {
 		g_warning ("couldn't search for matching item: %s", egg_error_message (error));
@@ -587,12 +581,13 @@ object_path_for_item (const gchar *base,
 static DBusMessage*
 collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMessage *message)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckSession *pkcs11_session = NULL;
 	DBusError derr = DBUS_ERROR_INIT;
 	GkdSecretSecret *secret = NULL;
 	dbus_bool_t replace = FALSE;
 	GckAttributes *attrs = NULL;
-	GckAttribute *fields;
+	const GckAttribute *fields;
 	DBusMessageIter iter, array;
 	GckObject *item = NULL;
 	const gchar *prompt;
@@ -608,9 +603,8 @@ collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMe
 		return NULL;
 	if (!dbus_message_iter_init (message, &iter))
 		g_return_val_if_reached (NULL);
-	attrs = gck_attributes_new ();
 	dbus_message_iter_recurse (&iter, &array);
-	if (!gkd_secret_property_parse_all (&array, SECRET_ITEM_INTERFACE, attrs)) {
+	if (!gkd_secret_property_parse_all (&array, SECRET_ITEM_INTERFACE, &builder)) {
 		reply = dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
 		                                "Invalid properties argument");
 		goto cleanup;
@@ -632,6 +626,8 @@ collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMe
 	pkcs11_session = gck_object_get_session (object);
 	g_return_val_if_fail (pkcs11_session, NULL);
 
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
+
 	if (replace) {
 		fields = gck_attributes_find (attrs, CKA_G_FIELDS);
 		if (fields)
@@ -645,9 +641,10 @@ collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMe
 
 	/* Create a new item */
 	} else {
-		gck_attributes_add_string (attrs, CKA_G_COLLECTION, identifier);
-		gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-		item = gck_session_create_object (pkcs11_session, attrs, NULL, &error);
+		gck_builder_add_all (&builder, attrs);
+		gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
+		gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+		item = gck_session_create_object (pkcs11_session, gck_builder_end (&builder), NULL, &error);
 		if (item == NULL)
 			goto cleanup;
 		created = TRUE;
@@ -916,6 +913,7 @@ gkd_secret_objects_get_pkcs11_slot (GkdSecretObjects *self)
 DBusMessage*
 gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	DBusMessage *reply = NULL;
 	GError *error = NULL;
 	GList *objects;
@@ -924,7 +922,6 @@ gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message)
 	gchar *i_ident;
 	gboolean is_item;
 	const char *path;
-	GckAttributes *attrs;
 
 	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
 	g_return_val_if_fail (message, NULL);
@@ -939,22 +936,19 @@ gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message)
 	session = gkd_secret_service_get_pkcs11_session (self->service, dbus_message_get_sender (message));
 	g_return_val_if_fail (session, NULL);
 
-	attrs = gck_attributes_new ();
-
 	if (i_ident) {
 		is_item = TRUE;
-		gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-		gck_attributes_add_string (attrs, CKA_G_COLLECTION, c_ident);
-		gck_attributes_add_string (attrs, CKA_ID, i_ident);
+		gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+		gck_builder_add_string (&builder, CKA_G_COLLECTION, c_ident);
+		gck_builder_add_string (&builder, CKA_ID, i_ident);
 	} else {
 		is_item = FALSE;
-		gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
-		gck_attributes_add_string (attrs, CKA_ID, c_ident);
+		gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
+		gck_builder_add_string (&builder, CKA_ID, c_ident);
 	}
 
-	objects = gck_session_find_objects (session, attrs, NULL, &error);
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
-	gck_attributes_unref (attrs);
 	g_free (c_ident);
 	g_free (i_ident);
 
@@ -979,12 +973,12 @@ GckObject*
 gkd_secret_objects_lookup_collection (GkdSecretObjects *self, const gchar *caller,
                                       const gchar *path)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckObject *object = NULL;
 	GError *error = NULL;
 	GList *objects;
 	GckSession *session;
 	gchar *identifier;
-	GckAttributes *attrs;
 
 	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
 	g_return_val_if_fail (caller, NULL);
@@ -997,13 +991,11 @@ gkd_secret_objects_lookup_collection (GkdSecretObjects *self, const gchar *calle
 	session = gkd_secret_service_get_pkcs11_session (self->service, caller);
 	g_return_val_if_fail (session, NULL);
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
-	gck_attributes_add_string (attrs, CKA_ID, identifier);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
+	gck_builder_add_string (&builder, CKA_ID, identifier);
 
-	objects = gck_session_find_objects (session, attrs, NULL, &error);
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
-	gck_attributes_unref (attrs);
 	g_free (identifier);
 
 	if (error != NULL) {
@@ -1022,13 +1014,13 @@ GckObject*
 gkd_secret_objects_lookup_item (GkdSecretObjects *self, const gchar *caller,
                                 const gchar *path)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckObject *object = NULL;
 	GError *error = NULL;
 	GList *objects;
 	GckSession *session;
 	gchar *collection;
 	gchar *identifier;
-	GckAttributes *attrs;
 
 	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
 	g_return_val_if_fail (caller, NULL);
@@ -1041,14 +1033,12 @@ gkd_secret_objects_lookup_item (GkdSecretObjects *self, const gchar *caller,
 	session = gkd_secret_service_get_pkcs11_session (self->service, caller);
 	g_return_val_if_fail (session, NULL);
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	gck_attributes_add_string (attrs, CKA_ID, identifier);
-	gck_attributes_add_string (attrs, CKA_G_COLLECTION, collection);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	gck_builder_add_string (&builder, CKA_ID, identifier);
+	gck_builder_add_string (&builder, CKA_G_COLLECTION, collection);
 
-	objects = gck_session_find_objects (session, attrs, NULL, &error);
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
-	gck_attributes_unref (attrs);
 	g_free (identifier);
 	g_free (collection);
 
@@ -1088,11 +1078,11 @@ gkd_secret_objects_foreach_item (GkdSecretObjects *self,
                                  GkdSecretObjectsForeach callback,
                                  gpointer user_data)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckSession *session;
 	GError *error = NULL;
 	gchar *identifier;
 	GList *items;
-	GckAttributes *attrs;
 
 	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
 	g_return_if_fail (base != NULL);
@@ -1105,13 +1095,10 @@ gkd_secret_objects_foreach_item (GkdSecretObjects *self,
 	if (!parse_object_path (self, base, &identifier, NULL))
 		g_return_if_reached ();
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	gck_attributes_add_string (attrs, CKA_G_COLLECTION, identifier);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
 
-	items = gck_session_find_objects (session, attrs, NULL, &error);
-
-	gck_attributes_unref (attrs);
+	items = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
 	if (error == NULL) {
 		objects_foreach_item (self, items, base, callback, user_data);
@@ -1165,8 +1152,8 @@ gkd_secret_objects_foreach_collection (GkdSecretObjects *self,
                                        GkdSecretObjectsForeach callback,
                                        gpointer user_data)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckSession *session;
-	GckAttributes *attrs;
 	GError *error = NULL;
 	GList *collections, *l;
 	gpointer identifier;
@@ -1180,12 +1167,9 @@ gkd_secret_objects_foreach_collection (GkdSecretObjects *self,
 	session = gkd_secret_service_get_pkcs11_session (self->service, dbus_message_get_sender (message));
 	g_return_if_fail (session);
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
 
-	collections = gck_session_find_objects (session, attrs, NULL, &error);
-
-	gck_attributes_unref (attrs);
+	collections = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
 	if (error != NULL) {
 		g_warning ("couldn't lookup collections: %s", egg_error_message (error));
@@ -1236,8 +1220,7 @@ DBusMessage*
 gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *message,
                                         const gchar *base)
 {
-	GckAttributes *attrs;
-	GckAttribute *attr;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	DBusMessageIter iter;
 	DBusMessageIter array;
 	GckObject *search;
@@ -1256,12 +1239,9 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
 	if (!dbus_message_has_signature (message, "a{ss}"))
 		return NULL;
 
-	attrs = gck_attributes_new ();
-	attr = gck_attributes_add_empty (attrs, CKA_G_FIELDS);
-
 	dbus_message_iter_init (message, &iter);
-	if (!gkd_secret_property_parse_fields (&iter, attr)) {
-		gck_attributes_unref (attrs);
+	if (!gkd_secret_property_parse_fields (&iter, &builder)) {
+		gck_builder_clear (&builder);
 		return dbus_message_new_error (message, DBUS_ERROR_FAILED,
 		                               "Invalid data in attributes argument");
 	}
@@ -1269,20 +1249,19 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
 	if (base != NULL) {
 		if (!parse_object_path (self, base, &identifier, NULL))
 			g_return_val_if_reached (NULL);
-		gck_attributes_add_string (attrs, CKA_G_COLLECTION, identifier);
+		gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
 		g_free (identifier);
 	}
 
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_SEARCH);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
 
 	/* The session we're using to access the object */
 	session = gkd_secret_service_get_pkcs11_session (self->service, dbus_message_get_sender (message));
 	g_return_val_if_fail (session, NULL);
 
 	/* Create the search object */
-	search = gck_session_create_object (session, attrs, NULL, &error);
-	gck_attributes_unref (attrs);
+	search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
 
 	if (error != NULL) {
 		reply = dbus_message_new_error_printf (message, DBUS_ERROR_FAILED,
diff --git a/daemon/dbus/gkd-secret-property.c b/daemon/dbus/gkd-secret-property.c
index fa1fc07..590836c 100644
--- a/daemon/dbus/gkd-secret-property.c
+++ b/daemon/dbus/gkd-secret-property.c
@@ -148,11 +148,12 @@ attribute_to_property (CK_ATTRIBUTE_TYPE attr_type, const gchar **prop_name, Dat
 	return TRUE;
 }
 
-typedef void (*IterAppendFunc) (DBusMessageIter*, GckAttribute*);
-typedef gboolean (*IterGetFunc) (DBusMessageIter*, GckAttribute*);
+typedef void (*IterAppendFunc) (DBusMessageIter*, const GckAttribute *);
+typedef gboolean (*IterGetFunc) (DBusMessageIter*, gulong, GckBuilder *);
 
 static void
-iter_append_string (DBusMessageIter *iter, GckAttribute *attr)
+iter_append_string (DBusMessageIter *iter,
+                    const GckAttribute *attr)
 {
 	gchar *value;
 
@@ -170,23 +171,26 @@ iter_append_string (DBusMessageIter *iter, GckAttribute *attr)
 }
 
 static gboolean
-iter_get_string (DBusMessageIter *iter, GckAttribute* attr)
+iter_get_string (DBusMessageIter *iter,
+                 gulong attr_type,
+                 GckBuilder *builder)
 {
 	const char *value;
 
-	g_assert (iter);
-	g_assert (attr);
+	g_assert (iter != NULL);
+	g_assert (builder != NULL);
 
 	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING, FALSE);
 	dbus_message_iter_get_basic (iter, &value);
 	if (value == NULL)
 		value = "";
-	gck_attribute_init_string (attr, attr->type, value);
+	gck_builder_add_string (builder, attr_type, value);
 	return TRUE;
 }
 
 static void
-iter_append_bool (DBusMessageIter *iter, GckAttribute *attr)
+iter_append_bool (DBusMessageIter *iter,
+                  const GckAttribute *attr)
 {
 	dbus_bool_t value;
 
@@ -198,21 +202,25 @@ iter_append_bool (DBusMessageIter *iter, GckAttribute *attr)
 }
 
 static gboolean
-iter_get_bool (DBusMessageIter *iter, GckAttribute* attr)
+iter_get_bool (DBusMessageIter *iter,
+               gulong attr_type,
+               GckBuilder *builder)
 {
 	dbus_bool_t value;
 
-	g_assert (iter);
-	g_assert (attr);
+	g_assert (iter != NULL);
+	g_assert (builder != NULL);
 
 	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN, FALSE);
 	dbus_message_iter_get_basic (iter, &value);
-	gck_attribute_init_boolean (attr, attr->type, value ? TRUE : FALSE);
+
+	gck_builder_add_boolean (builder, attr_type, value ? TRUE : FALSE);
 	return TRUE;
 }
 
 static void
-iter_append_time (DBusMessageIter *iter, GckAttribute *attr)
+iter_append_time (DBusMessageIter *iter,
+                  const GckAttribute *attr)
 {
 	gint64 value;
 	struct tm tm;
@@ -250,20 +258,22 @@ iter_append_time (DBusMessageIter *iter, GckAttribute *attr)
 }
 
 static gboolean
-iter_get_time (DBusMessageIter *iter, GckAttribute* attr)
+iter_get_time (DBusMessageIter *iter,
+               gulong attr_type,
+               GckBuilder *builder)
 {
 	time_t time;
 	struct tm tm;
 	gchar buf[20];
 	gint64 value;
 
-	g_assert (iter);
-	g_assert (attr);
+	g_assert (iter != NULL);
+	g_assert (builder != NULL);
 
 	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT64, FALSE);
 	dbus_message_iter_get_basic (iter, &value);
 	if (value < 0) {
-		gck_attribute_init_empty (attr, attr->type);
+		gck_builder_add_empty (builder, attr_type);
 		return TRUE;
 	}
 
@@ -274,12 +284,13 @@ iter_get_time (DBusMessageIter *iter, GckAttribute* attr)
 	if (!strftime (buf, sizeof (buf), "%Y%m%d%H%M%S00", &tm))
 		g_return_val_if_reached (FALSE);
 
-	gck_attribute_init (attr, attr->type, (const guchar *)buf, 16);
+	gck_builder_add_data (builder, attr_type, (const guchar *)buf, 16);
 	return TRUE;
 }
 
 static void
-iter_append_fields (DBusMessageIter *iter, GckAttribute *attr)
+iter_append_fields (DBusMessageIter *iter,
+                    const GckAttribute *attr)
 {
 	DBusMessageIter array;
 	DBusMessageIter dict;
@@ -334,14 +345,17 @@ iter_append_fields (DBusMessageIter *iter, GckAttribute *attr)
 }
 
 static gboolean
-iter_get_fields (DBusMessageIter *iter, GckAttribute* attr)
+iter_get_fields (DBusMessageIter *iter,
+                 gulong attr_type,
+                 GckBuilder *builder)
 {
 	DBusMessageIter array;
 	DBusMessageIter dict;
 	GString *result;
 	const gchar *string;
 
-	g_assert (iter);
+	g_assert (iter != NULL);
+	g_assert (builder != NULL);
 
 	result = g_string_new ("");
 
@@ -368,13 +382,15 @@ iter_get_fields (DBusMessageIter *iter, GckAttribute* attr)
 		dbus_message_iter_next (&array);
 	}
 
-	gck_attribute_init (attr, attr->type, (const guchar *)result->str, result->len);
+	gck_builder_add_data (builder, attr_type, (const guchar *)result->str, result->len);
 	g_string_free (result, TRUE);
 	return TRUE;
 }
 
 static void
-iter_append_variant (DBusMessageIter *iter, DataType data_type, GckAttribute *attr)
+iter_append_variant (DBusMessageIter *iter,
+                     DataType data_type,
+                     const GckAttribute *attr)
 {
 	DBusMessageIter sub;
 	IterAppendFunc func = NULL;
@@ -411,7 +427,10 @@ iter_append_variant (DBusMessageIter *iter, DataType data_type, GckAttribute *at
 }
 
 static gboolean
-iter_get_variant (DBusMessageIter *iter, DataType data_type, GckAttribute *attr)
+iter_get_variant (DBusMessageIter *iter,
+                  DataType data_type,
+                  gulong attr_type,
+                  GckBuilder *builder)
 {
 	DBusMessageIter variant;
 	IterGetFunc func = NULL;
@@ -419,8 +438,8 @@ iter_get_variant (DBusMessageIter *iter, DataType data_type, GckAttribute *attr)
 	const gchar *sig = NULL;
 	char *signature;
 
-	g_assert (iter);
-	g_assert (attr);
+	g_assert (iter != NULL);
+	g_assert (builder != NULL);
 
 	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_VARIANT, FALSE);
 	dbus_message_iter_recurse (iter, &variant);
@@ -455,7 +474,7 @@ iter_get_variant (DBusMessageIter *iter, DataType data_type, GckAttribute *attr)
 	if (ret == FALSE)
 		return FALSE;
 
-	return (func) (&variant, attr);
+	return (func) (&variant, attr_type, builder);
 }
 
 /* -----------------------------------------------------------------------------
@@ -474,17 +493,17 @@ gkd_secret_property_get_type (const gchar *property, CK_ATTRIBUTE_TYPE *type)
 }
 
 gboolean
-gkd_secret_property_parse_all (DBusMessageIter *array, const gchar *interface,
-                               GckAttributes *attrs)
+gkd_secret_property_parse_all (DBusMessageIter *array,
+                               const gchar *interface,
+                               GckBuilder *builder)
 {
 	DBusMessageIter dict;
 	CK_ATTRIBUTE_TYPE attr_type;
-	GckAttribute *attr;
 	const char *name;
 	DataType data_type;
 
-	g_return_val_if_fail (array, FALSE);
-	g_return_val_if_fail (attrs, FALSE);
+	g_return_val_if_fail (array != NULL, FALSE);
+	g_return_val_if_fail (builder != NULL, FALSE);
 
 	while (dbus_message_iter_get_arg_type (array) == DBUS_TYPE_DICT_ENTRY) {
 		dbus_message_iter_recurse (array, &dict);
@@ -499,8 +518,7 @@ gkd_secret_property_parse_all (DBusMessageIter *array, const gchar *interface,
 
 		/* Property value */
 		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_VARIANT, FALSE);
-		attr = gck_attributes_add_empty (attrs, attr_type);
-		if (!iter_get_variant (&dict, data_type, attr))
+		if (!iter_get_variant (&dict, data_type, attr_type, builder))
 			return FALSE;
 
 		dbus_message_iter_next (array);
@@ -513,7 +531,7 @@ gboolean
 gkd_secret_property_append_all (DBusMessageIter *array, GckAttributes *attrs)
 {
 	DBusMessageIter dict;
-	GckAttribute *attr;
+	const GckAttribute *attr;
 	DataType data_type;
 	const gchar *name;
 	gulong num, i;
@@ -537,7 +555,8 @@ gkd_secret_property_append_all (DBusMessageIter *array, GckAttributes *attrs)
 }
 
 gboolean
-gkd_secret_property_append_variant (DBusMessageIter *iter, GckAttribute *attr)
+gkd_secret_property_append_variant (DBusMessageIter *iter,
+                                    const GckAttribute *attr)
 {
 	const gchar *property;
 	DataType data_type;
@@ -552,29 +571,29 @@ gkd_secret_property_append_variant (DBusMessageIter *iter, GckAttribute *attr)
 }
 
 gboolean
-gkd_secret_property_parse_variant (DBusMessageIter *iter, const gchar *property,
-                                   GckAttribute *attr)
+gkd_secret_property_parse_variant (DBusMessageIter *iter,
+                                   const gchar *property,
+                                   GckBuilder *builder)
 {
 	CK_ATTRIBUTE_TYPE attr_type;
 	DataType data_type;
 
-	g_return_val_if_fail (attr, FALSE);
 	g_return_val_if_fail (iter, FALSE);
 	g_return_val_if_fail (property, FALSE);
+	g_return_val_if_fail (builder != NULL, FALSE);
 
 	if (!property_to_attribute (property, NULL, &attr_type, &data_type))
 		return FALSE;
 
-	attr->type = attr_type;
-	return iter_get_variant (iter, data_type, attr);
+	return iter_get_variant (iter, data_type, attr_type, builder);
 }
 
 gboolean
-gkd_secret_property_parse_fields (DBusMessageIter *iter, GckAttribute *attr)
+gkd_secret_property_parse_fields (DBusMessageIter *iter,
+                                  GckBuilder *builder)
 {
-	g_return_val_if_fail (attr, FALSE);
-	g_return_val_if_fail (iter, FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+	g_return_val_if_fail (builder != NULL, FALSE);
 
-	attr->type = CKA_G_FIELDS;
-	return iter_get_fields (iter, attr);
+	return iter_get_fields (iter, CKA_G_FIELDS, builder);
 }
diff --git a/daemon/dbus/gkd-secret-property.h b/daemon/dbus/gkd-secret-property.h
index bdcaba5..5c3702e 100644
--- a/daemon/dbus/gkd-secret-property.h
+++ b/daemon/dbus/gkd-secret-property.h
@@ -32,20 +32,20 @@ gboolean               gkd_secret_property_get_type               (const gchar *
                                                                    CK_ATTRIBUTE_TYPE *type);
 
 gboolean               gkd_secret_property_append_variant         (DBusMessageIter *iter,
-                                                                   GckAttribute *attr);
+                                                                   const GckAttribute *attr);
 
 gboolean               gkd_secret_property_append_all             (DBusMessageIter *array,
                                                                    GckAttributes *attrs);
 
 gboolean               gkd_secret_property_parse_variant          (DBusMessageIter *iter,
                                                                    const gchar *property,
-                                                                   GckAttribute *attr);
+                                                                   GckBuilder *builder);
 
 gboolean               gkd_secret_property_parse_fields           (DBusMessageIter *iter,
-                                                                   GckAttribute *attr);
+                                                                   GckBuilder *builder);
 
 gboolean               gkd_secret_property_parse_all              (DBusMessageIter *array,
                                                                    const gchar *interface,
-                                                                   GckAttributes *attrs);
+                                                                   GckBuilder *builder);
 
 #endif /* __GKD_SECRET_PROPERTY_H__ */
diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
index 741a1b7..d5724fc 100644
--- a/daemon/dbus/gkd-secret-service.c
+++ b/daemon/dbus/gkd-secret-service.c
@@ -394,6 +394,7 @@ service_method_open_session (GkdSecretService *self, DBusMessage *message)
 static DBusMessage*
 service_method_create_collection (GkdSecretService *self, DBusMessage *message)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	DBusMessageIter iter, array;
 	GckAttributes *attrs;
 	GkdSecretCreate *create;
@@ -408,10 +409,9 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
 		return NULL;
 	if (!dbus_message_iter_init (message, &iter))
 		g_return_val_if_reached (NULL);
-	attrs = gck_attributes_new ();
 	dbus_message_iter_recurse (&iter, &array);
-	if (!gkd_secret_property_parse_all (&array, SECRET_COLLECTION_INTERFACE, attrs)) {
-		gck_attributes_unref (attrs);
+	if (!gkd_secret_property_parse_all (&array, SECRET_COLLECTION_INTERFACE, &builder)) {
+		gck_builder_clear (&builder);
 		return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS,
 		                                      "Invalid properties");
 	}
@@ -424,13 +424,14 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
 		if (!alias[0]) {
 			alias = NULL;
 		} else if (!g_str_equal (alias, "default")) {
-			gck_attributes_unref (attrs);
+			gck_builder_clear (&builder);
 			return dbus_message_new_error (message, DBUS_ERROR_NOT_SUPPORTED,
 			                               "Only the 'default' alias is supported");
 		}
 	}
 
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
 	/* Create the prompt object, for the password */
 	caller = dbus_message_get_sender (message);
@@ -663,6 +664,7 @@ service_method_set_alias (GkdSecretService *self, DBusMessage *message)
 static DBusMessage*
 service_method_create_with_master_password (GkdSecretService *self, DBusMessage *message)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	DBusError derr = DBUS_ERROR_INIT;
 	DBusMessageIter iter, array;
 	DBusMessage *reply = NULL;
@@ -675,21 +677,21 @@ service_method_create_with_master_password (GkdSecretService *self, DBusMessage
 		return NULL;
 	if (!dbus_message_iter_init (message, &iter))
 		g_return_val_if_reached (NULL);
-	attrs = gck_attributes_new ();
 	dbus_message_iter_recurse (&iter, &array);
-	if (!gkd_secret_property_parse_all (&array, SECRET_COLLECTION_INTERFACE, attrs)) {
-		gck_attributes_unref (attrs);
+	if (!gkd_secret_property_parse_all (&array, SECRET_COLLECTION_INTERFACE, &builder)) {
+		gck_builder_clear (&builder);
 		return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
 		                               "Invalid properties argument");
 	}
 	dbus_message_iter_next (&iter);
 	secret = gkd_secret_secret_parse (self, message, &iter, &derr);
 	if (secret == NULL) {
-		gck_attributes_unref (attrs);
+		gck_builder_clear (&builder);
 		return gkd_secret_error_to_reply (message, &derr);
 	}
 
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 	path = gkd_secret_create_with_secret (attrs, secret, &derr);
 	gck_attributes_unref (attrs);
 	gkd_secret_secret_free (secret);
diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c
index d59d8f2..8316998 100644
--- a/daemon/dbus/gkd-secret-session.c
+++ b/daemon/dbus/gkd-secret-session.c
@@ -84,6 +84,7 @@ static gboolean
 aes_create_dh_keys (GckSession *session, const gchar *group,
                     GckObject **pub_key, GckObject **priv_key)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	gconstpointer prime, base;
 	gsize n_prime, n_base;
@@ -95,9 +96,9 @@ aes_create_dh_keys (GckSession *session, const gchar *group,
 		return FALSE;
 	}
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_data (attrs, CKA_PRIME, prime, n_prime);
-	gck_attributes_add_data (attrs, CKA_BASE, base, n_base);
+	gck_builder_add_data (&builder, CKA_PRIME, prime, n_prime);
+	gck_builder_add_data (&builder, CKA_BASE, base, n_base);
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
 	/* Perform the DH key generation */
 	ret = gck_session_generate_key_pair (session, CKM_DH_PKCS_KEY_PAIR_GEN, attrs, attrs,
@@ -118,9 +119,9 @@ static gboolean
 aes_derive_key (GckSession *session, GckObject *priv_key,
                 gconstpointer input, gsize n_input, GckObject **aes_key)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
 	GckMechanism mech;
-	GckAttributes *attrs;
 	GckObject *dh_key;
 
 	/*
@@ -132,13 +133,9 @@ aes_derive_key (GckSession *session, GckObject *priv_key,
 	mech.parameter = input;
 	mech.n_parameter = n_input;
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_GENERIC_SECRET);
-
-	dh_key = gck_session_derive_key_full (session, priv_key, &mech, attrs, NULL, &error);
-
-	gck_attributes_unref (attrs);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_GENERIC_SECRET);
+	dh_key = gck_session_derive_key_full (session, priv_key, &mech, gck_builder_end (&builder), NULL, &error);
 
 	if (!dh_key) {
 		g_warning ("couldn't derive key from dh key pair: %s", egg_error_message (error));
@@ -154,13 +151,11 @@ aes_derive_key (GckSession *session, GckObject *priv_key,
 	mech.parameter = NULL;
 	mech.n_parameter = 0;
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_VALUE_LEN, 16UL);
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_AES);
+	gck_builder_add_ulong (&builder, CKA_VALUE_LEN, 16UL);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_AES);
 
-	*aes_key = gck_session_derive_key_full (session, dh_key, &mech, attrs, NULL, &error);
-	gck_attributes_unref (attrs);
+	*aes_key = gck_session_derive_key_full (session, dh_key, &mech, gck_builder_end (&builder), NULL, &error);
 	g_object_unref (dh_key);
 
 	if (!*aes_key) {
@@ -233,24 +228,21 @@ aes_negotiate (GkdSecretSession *self, DBusMessage *message, gconstpointer input
 static DBusMessage*
 plain_negotiate (GkdSecretSession *self, DBusMessage *message)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	DBusMessageIter iter, variant;
 	GError *error = NULL;
 	const char *output = "";
 	DBusMessage *reply;
 	GckObject *key;
 	GckSession *session;
-	GckAttributes *attrs;
 
 	session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
 	g_return_val_if_fail (session, NULL);
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_G_NULL);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_G_NULL);
 
-	key = gck_session_create_object (session, attrs, NULL, &error);
-
-	gck_attributes_unref (attrs);
+	key = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
 
 	if (key == NULL) {
 		g_warning ("couldn't create null key: %s", egg_error_message (error));
@@ -652,6 +644,7 @@ gboolean
 gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item,
                                     GkdSecretSecret *secret, DBusError *derr)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckMechanism mech;
 	GckObject *object;
 	GckSession *session;
@@ -676,7 +669,9 @@ gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item,
 		g_clear_error (&error);
 		return FALSE;
 	}
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
+	gck_builder_add_all (&builder, attrs);
+	gck_attributes_unref (attrs);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
 
 	session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
 	g_return_val_if_fail (session, FALSE);
@@ -686,9 +681,7 @@ gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item,
 	mech.n_parameter = secret->n_parameter;
 
 	object = gck_session_unwrap_key_full (session, self->key, &mech, secret->value,
-	                                      secret->n_value, attrs, NULL, &error);
-
-	gck_attributes_unref (attrs);
+	                                      secret->n_value, gck_builder_end (&builder), NULL, &error);
 
 	if (object == NULL) {
 		if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) {
@@ -723,6 +716,7 @@ gkd_secret_session_create_credential (GkdSecretSession *self, GckSession *sessio
                                       GckAttributes *attrs, GkdSecretSecret *secret,
                                       DBusError *derr)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *alloc = NULL;
 	GckMechanism mech;
 	GckObject *object;
@@ -736,9 +730,9 @@ gkd_secret_session_create_credential (GkdSecretSession *self, GckSession *sessio
 	g_return_val_if_fail (session, NULL);
 
 	if (attrs == NULL) {
-		alloc = attrs = gck_attributes_new ();
-		gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_CREDENTIAL);
-		gck_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
+		gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
+		gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
+		alloc = attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 	}
 
 	mech.type = self->mech_type;
diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c
index 928e924..4161396 100644
--- a/daemon/dbus/gkd-secret-unlock.c
+++ b/daemon/dbus/gkd-secret-unlock.c
@@ -117,12 +117,13 @@ check_locked_collection (GckObject *collection, gboolean *locked)
 }
 
 static void
-common_unlock_attributes (GckAttributes *attrs, GckObject *collection)
+common_unlock_attributes (GckBuilder *builder,
+                          GckObject *collection)
 {
-	g_assert (attrs);
+	g_assert (builder != NULL);
 	g_assert (GCK_IS_OBJECT (collection));
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_CREDENTIAL);
-	gck_attributes_add_ulong (attrs, CKA_G_OBJECT, gck_object_get_handle (collection));
+	gck_builder_add_ulong (builder, CKA_CLASS, CKO_G_CREDENTIAL);
+	gck_builder_add_ulong (builder, CKA_G_OBJECT, gck_object_get_handle (collection));
 }
 
 static gboolean
@@ -224,8 +225,8 @@ on_unlock_complete (GObject *object, GAsyncResult *res, gpointer user_data)
 static void
 perform_next_unlock (GkdSecretUnlock *self)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckObject *collection;
-	GckAttributes *template;
 	GckSession *session;
 	gboolean locked;
 	gboolean proceed;
@@ -268,14 +269,13 @@ perform_next_unlock (GkdSecretUnlock *self)
 		 * pops us back off the unlock prompt queue
 		 */
 		if (proceed) {
-			template = gck_attributes_new ();
-			common_unlock_attributes (template, collection);
-			gck_attributes_add_data (template, CKA_VALUE, NULL, 0);
+			common_unlock_attributes (&builder, collection);
+			gck_builder_add_data (&builder, CKA_VALUE, NULL, 0);
 
 			session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
-			gck_session_create_object_async (session, template, self->cancellable, on_unlock_complete,
-							 g_object_ref (self));
-			gck_attributes_unref (template);
+			gck_session_create_object_async (session, gck_builder_end (&builder),
+			                                 self->cancellable, on_unlock_complete,
+			                                 g_object_ref (self));
 			self->current = objpath;
 			break;
 		}
@@ -628,6 +628,7 @@ gboolean
 gkd_secret_unlock_with_secret (GckObject *collection, GkdSecretSecret *master,
                                DBusError *derr)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	GckObject *cred;
 	gboolean locked;
@@ -639,10 +640,10 @@ gkd_secret_unlock_with_secret (GckObject *collection, GkdSecretSecret *master,
 	if (check_locked_collection (collection, &locked) && !locked)
 		return TRUE;
 
-	attrs = gck_attributes_new ();
-	common_unlock_attributes (attrs, collection);
-	gck_attributes_add_boolean (attrs, CKA_GNOME_TRANSIENT, TRUE);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+	common_unlock_attributes (&builder, collection);
+	gck_builder_add_boolean (&builder, CKA_GNOME_TRANSIENT, TRUE);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
 	cred = gkd_secret_session_create_credential (master->session, NULL, attrs, master, derr);
 
@@ -657,7 +658,7 @@ gboolean
 gkd_secret_unlock_with_password (GckObject *collection, const guchar *password,
                                  gsize n_password, DBusError *derr)
 {
-	GckAttributes *attrs;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
 	GckSession *session;
 	GckObject *cred;
@@ -672,13 +673,13 @@ gkd_secret_unlock_with_password (GckObject *collection, const guchar *password,
 	session = gck_object_get_session (collection);
 	g_return_val_if_fail (session, FALSE);
 
-	attrs = gck_attributes_new_full (egg_secure_realloc);
-	common_unlock_attributes (attrs, collection);
-	gck_attributes_add_boolean (attrs, CKA_GNOME_TRANSIENT, TRUE);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
-	gck_attributes_add_data (attrs, CKA_VALUE, password, n_password);
+	gck_builder_init_full (&builder, GCK_BUILDER_SECURE_MEMORY);
+	common_unlock_attributes (&builder, collection);
+	gck_builder_add_boolean (&builder, CKA_GNOME_TRANSIENT, TRUE);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
+	gck_builder_add_data (&builder, CKA_VALUE, password, n_password);
 
-	cred = gck_session_create_object (session, attrs, NULL, &error);
+	cred = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
 	if (cred == NULL) {
 		if (g_error_matches (error, GCK_ERROR, CKR_PIN_INCORRECT)) {
 			dbus_set_error_const (derr, INTERNAL_ERROR_DENIED, "The password was incorrect.");
diff --git a/daemon/gpg-agent/gkd-gpg-agent-ops.c b/daemon/gpg-agent/gkd-gpg-agent-ops.c
index 42ddffb..d2d6423 100644
--- a/daemon/gpg-agent/gkd-gpg-agent-ops.c
+++ b/daemon/gpg-agent/gkd-gpg-agent-ops.c
@@ -51,7 +51,8 @@ EGG_SECURE_DECLARE (gpg_agent_ops);
  */
 
 static void
-keyid_to_field_attribute (const gchar *keyid, GckAttributes *attrs)
+keyid_to_field_attribute (const gchar *keyid,
+                          GckBuilder *attrs)
 {
 	GString *fields = g_string_sized_new (128);
 
@@ -70,7 +71,7 @@ keyid_to_field_attribute (const gchar *keyid, GckAttributes *attrs)
 	g_string_append (fields, "gnome-keyring:gpg-agent");
 	g_string_append_c (fields, '\0');
 
-	gck_attributes_add_data (attrs, CKA_G_FIELDS, (const guchar *)fields->str, fields->len);
+	gck_builder_add_data (attrs, CKA_G_FIELDS, (const guchar *)fields->str, fields->len);
 	g_string_free (fields, TRUE);
 }
 
@@ -111,29 +112,26 @@ calculate_label_for_key (const gchar *keyid, const gchar *description)
 static GList*
 find_saved_items (GckSession *session, GckAttributes *attrs)
 {
-	GckAttributes *template;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
-	GckAttribute *attr;
+	const GckAttribute *attr;
 	GckObject *search;
 	GList *results;
 	gpointer data;
 	gsize n_data;
 
-	template = gck_attributes_new ();
-	gck_attributes_add_ulong (template, CKA_CLASS, CKO_G_SEARCH);
-	gck_attributes_add_boolean (template, CKA_TOKEN, FALSE);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
 
 	attr = gck_attributes_find (attrs, CKA_G_COLLECTION);
 	if (attr != NULL)
-		gck_attributes_add (template, attr);
+		gck_builder_add_owned (&builder, attr);
 
 	attr = gck_attributes_find (attrs, CKA_G_FIELDS);
 	g_return_val_if_fail (attr != NULL, NULL);
-	gck_attributes_add (template, attr);
-
-	search = gck_session_create_object (session, template, NULL, &error);
-	gck_attributes_unref (template);
+	gck_builder_add_owned (&builder, attr);
 
+	search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
 	if (search == NULL) {
 		g_warning ("couldn't perform search for gpg agent stored passphrases: %s",
 		           egg_error_message (error));
@@ -162,6 +160,7 @@ static void
 do_save_password (GckSession *session, const gchar *keyid, const gchar *description,
                   const gchar *password, GckAttributes *options)
 {
+	GckBuilder builder;
 	GckAttributes *attrs;
 	gpointer identifier;
 	gsize n_identifier;
@@ -179,37 +178,40 @@ do_save_password (GckSession *session, const gchar *keyid, const gchar *descript
 		return;
 
 	/* Sending a password, needs to be secure */
-	attrs = gck_attributes_new_full (egg_secure_realloc);
+	gck_builder_init_full (&builder, GCK_BUILDER_SECURE_MEMORY);
 
 	/* Build up basic set of attributes */
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	keyid_to_field_attribute (keyid, attrs);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	keyid_to_field_attribute (keyid, &builder);
 
 	/* Bring in all the unlock options */
 	for (i = 0; options && i < gck_attributes_count (options); ++i)
-		gck_attributes_add (attrs, gck_attributes_at (options, i));
+		gck_builder_add_owned (&builder, gck_attributes_at (options, i));
 
 	/* Find a previously stored object like this, and replace if so */
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 	previous = find_saved_items (session, attrs);
 	if (previous) {
 		identifier = gck_object_get_data (previous->data, CKA_ID, NULL, &n_identifier, NULL);
 		if (identifier != NULL)
-			gck_attributes_add_data (attrs, CKA_ID, identifier, n_identifier);
+			gck_builder_add_data (&builder, CKA_ID, identifier, n_identifier);
 		g_free (identifier);
 		gck_list_unref_free (previous);
 	}
 
+	gck_attributes_unref (attrs);
+
 	text = calculate_label_for_key (keyid, description);
 	label = g_strdup_printf (_("PGP Key: %s"), text);
 	g_free (text);
 
 	/* Put in the remainder of the attributes */
-	gck_attributes_add_string (attrs, CKA_VALUE, password);
-	gck_attributes_add_string (attrs, CKA_LABEL, label);
+	gck_builder_add_string (&builder, CKA_VALUE, password);
+	gck_builder_add_string (&builder, CKA_LABEL, label);
 	g_free (label);
 
-	item = gck_session_create_object (session, attrs, NULL, &error);
+	item = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
 	if (item == NULL) {
 		g_warning ("couldn't store gpg agent password: %s", egg_error_message (error));
 		g_clear_error (&error);
@@ -217,20 +219,20 @@ do_save_password (GckSession *session, const gchar *keyid, const gchar *descript
 
 	if (item != NULL)
 		g_object_unref (item);
-	gck_attributes_unref (attrs);
 }
 
 static gboolean
 do_clear_password (GckSession *session, const gchar *keyid)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	GList *objects, *l;
 	GError *error = NULL;
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	keyid_to_field_attribute (keyid, attrs);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	keyid_to_field_attribute (keyid, &builder);
 
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 	objects = find_saved_items (session, attrs);
 	gck_attributes_unref (attrs);
 
@@ -255,6 +257,7 @@ do_clear_password (GckSession *session, const gchar *keyid)
 static gchar*
 do_lookup_password (GckSession *session, const gchar *keyid)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	GList *objects, *l;
 	GError *error = NULL;
@@ -264,10 +267,10 @@ do_lookup_password (GckSession *session, const gchar *keyid)
 	if (keyid == NULL)
 		return NULL;
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
-	keyid_to_field_attribute (keyid, attrs);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
+	keyid_to_field_attribute (keyid, &builder);
 
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 	objects = find_saved_items (session, attrs);
 	gck_attributes_unref (attrs);
 
@@ -343,11 +346,11 @@ static GkuPrompt*
 prepare_password_prompt (GckSession *session, const gchar *keyid, const gchar *errmsg,
                          const gchar *prompt_text, const gchar *description, gboolean confirm)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GkuPrompt *prompt;
 	GError *error = NULL;
 	gboolean auto_unlock;
 	GList *objects;
-	GckAttributes *attrs;
 
 	g_assert (GCK_IS_SESSION (session));
 
@@ -377,14 +380,12 @@ prepare_password_prompt (GckSession *session, const gchar *keyid, const gchar *e
 
 		auto_unlock = FALSE;
 
-		attrs = gck_attributes_new ();
-		gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
-		gck_attributes_add_string (attrs, CKA_ID, "login");
-		gck_attributes_add_boolean (attrs, CKA_G_LOCKED, FALSE);
+		gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
+		gck_builder_add_string (&builder, CKA_ID, "login");
+		gck_builder_add_boolean (&builder, CKA_G_LOCKED, FALSE);
 
 		/* Check if the login keyring is usable */
-		objects = gck_session_find_objects (session, attrs, NULL, &error);
-		gck_attributes_unref (attrs);
+		objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
 		if (error) {
 			g_warning ("gpg agent couldn't lookup for login keyring: %s", egg_error_message (error));
@@ -417,6 +418,7 @@ static gchar*
 do_get_password (GckSession *session, const gchar *keyid, const gchar *errmsg,
                  const gchar *prompt_text, const gchar *description, gboolean confirm)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	gchar *password = NULL;
 	GkuPrompt *prompt;
@@ -441,24 +443,23 @@ do_get_password (GckSession *session, const gchar *keyid, const gchar *errmsg,
 		g_return_val_if_fail (password, NULL);
 
 		if (keyid != NULL) {
-			attrs = gck_attributes_new ();
-
 			/* Load up the save options */
 			choice = gku_prompt_get_unlock_choice (prompt);
 			ttl = gku_prompt_get_unlock_ttl (prompt);
 
 			if (g_str_equal (choice, GCR_UNLOCK_OPTION_ALWAYS))
-				gck_attributes_add_string (attrs, CKA_G_COLLECTION, "login");
+				gck_builder_add_string (&builder, CKA_G_COLLECTION, "login");
 			else
-				gck_attributes_add_string (attrs, CKA_G_COLLECTION, "session");
+				gck_builder_add_string (&builder, CKA_G_COLLECTION, "session");
 
 			if (g_str_equal (choice, GCR_UNLOCK_OPTION_IDLE))
-				gck_attributes_add_ulong (attrs, CKA_G_DESTRUCT_IDLE, ttl);
+				gck_builder_add_ulong (&builder, CKA_G_DESTRUCT_IDLE, ttl);
 
 			else if (g_str_equal (choice, GCR_UNLOCK_OPTION_TIMEOUT))
-				gck_attributes_add_ulong (attrs, CKA_G_DESTRUCT_AFTER, ttl);
+				gck_builder_add_ulong (&builder, CKA_G_DESTRUCT_AFTER, ttl);
 
 			/* Now actually save the password */
+			attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 			do_save_password (session, keyid, description, password, attrs);
 			gck_attributes_unref (attrs);
 
diff --git a/daemon/login/gkd-login.c b/daemon/login/gkd-login.c
index d94115e..dc6e170 100644
--- a/daemon/login/gkd-login.c
+++ b/daemon/login/gkd-login.c
@@ -98,7 +98,7 @@ lookup_login_session (GList *modules)
 static GckObject*
 lookup_login_keyring (GckSession *session)
 {
-	GckAttributes *atts;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
 	GckObject *login = NULL;
 	GList *objects;
@@ -106,13 +106,11 @@ lookup_login_keyring (GckSession *session)
 
 	g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
 
-	atts = gck_attributes_new ();
-	gck_attributes_add_ulong (atts, CKA_CLASS, CKO_G_COLLECTION);
-	gck_attributes_add_boolean (atts, CKA_TOKEN, TRUE);
-	gck_attributes_add_string (atts, CKA_ID, "login");
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
+	gck_builder_add_string (&builder, CKA_ID, "login");
 
-	objects = gck_session_find_objects (session, atts, NULL, &error);
-	gck_attributes_unref (atts);
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
 	if (error) {
 		g_warning ("couldn't search for login keyring: %s", egg_error_message (error));
@@ -133,33 +131,27 @@ lookup_login_keyring (GckSession *session)
 static GckObject*
 create_login_keyring (GckSession *session, GckObject *cred, GError **error)
 {
-	GckObject *login;
-	GckAttributes *atts;
+	GckBuilder builder = GCK_BUILDER_INIT;
 
 	g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
 	g_return_val_if_fail (GCK_IS_OBJECT (cred), NULL);
 
-	atts = gck_attributes_new ();
-	gck_attributes_add_ulong (atts, CKA_CLASS, CKO_G_COLLECTION);
-	gck_attributes_add_string (atts, CKA_ID, "login");
-	gck_attributes_add_ulong (atts, CKA_G_CREDENTIAL, gck_object_get_handle (cred));
-	gck_attributes_add_boolean (atts, CKA_TOKEN, TRUE);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
+	gck_builder_add_string (&builder, CKA_ID, "login");
+	gck_builder_add_ulong (&builder, CKA_G_CREDENTIAL, gck_object_get_handle (cred));
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
 
 	/* TRANSLATORS: This is the display label for the login keyring */
-	gck_attributes_add_string (atts, CKA_LABEL, _("Login"));
-
-	login = gck_session_create_object (session, atts, NULL, error);
-	gck_attributes_unref (atts);
+	gck_builder_add_string (&builder, CKA_LABEL, _("Login"));
 
-	return login;
+	return gck_session_create_object (session, gck_builder_end (&builder), NULL, error);
 }
 
 static GckObject*
 create_credential (GckSession *session, GckObject *object,
                    const gchar *secret, GError **error)
 {
-	GckAttributes *attrs;
-	GckObject *cred;
+	GckBuilder builder = GCK_BUILDER_INIT;
 
 	g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
 	g_return_val_if_fail (!object || GCK_IS_OBJECT (object), NULL);
@@ -167,20 +159,16 @@ create_credential (GckSession *session, GckObject *object,
 	if (!secret)
 		secret = "";
 
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_CREDENTIAL);
-	gck_attributes_add_string (attrs, CKA_VALUE, secret);
-	gck_attributes_add_boolean (attrs, CKA_GNOME_TRANSIENT, TRUE);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
+	gck_builder_add_string (&builder, CKA_VALUE, secret);
+	gck_builder_add_boolean (&builder, CKA_GNOME_TRANSIENT, TRUE);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
 
 	if (object)
-		gck_attributes_add_ulong (attrs, CKA_G_OBJECT,
-		                          gck_object_get_handle (object));
-
-	cred = gck_session_create_object (session, attrs, NULL, error);
-	gck_attributes_unref (attrs);
+		gck_builder_add_ulong (&builder, CKA_G_OBJECT,
+		                       gck_object_get_handle (object));
 
-	return cred;
+	return gck_session_create_object (session, gck_builder_end (&builder), NULL, error);
 }
 
 static gboolean
@@ -289,13 +277,13 @@ gkd_login_unlock (const gchar *master)
 static gboolean
 change_or_create_login (GList *modules, const gchar *original, const gchar *master)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
 	GckSession *session;
 	GckObject *login = NULL;
 	GckObject *ocred = NULL;
 	GckObject *mcred = NULL;
 	gboolean success = FALSE;
-	GckAttributes *atts;
 
 	g_return_val_if_fail (original, FALSE);
 	g_return_val_if_fail (master, FALSE);
@@ -338,15 +326,13 @@ change_or_create_login (GList *modules, const gchar *original, const gchar *mast
 
 	/* Change the master password */
 	} else if (login && ocred && mcred) {
-		atts = gck_attributes_new ();
-		gck_attributes_add_ulong (atts, CKA_G_CREDENTIAL, gck_object_get_handle (mcred));
-		if (!gck_object_set (login, atts, NULL, &error)) {
+		gck_builder_add_ulong (&builder, CKA_G_CREDENTIAL, gck_object_get_handle (mcred));
+		if (!gck_object_set (login, gck_builder_end (&builder), NULL, &error)) {
 			g_warning ("couldn't change login master password: %s", egg_error_message (error));
 			g_clear_error (&error);
 		} else {
 			success = TRUE;
 		}
-		gck_attributes_unref (atts);
 	}
 
 	if (ocred) {
diff --git a/daemon/ssh-agent/gkd-ssh-agent-ops.c b/daemon/ssh-agent/gkd-ssh-agent-ops.c
index 2e35e90..22c61ef 100644
--- a/daemon/ssh-agent/gkd-ssh-agent-ops.c
+++ b/daemon/ssh-agent/gkd-ssh-agent-ops.c
@@ -49,16 +49,18 @@ EGG_SECURE_DECLARE (ssh_agent_ops);
 
 
 static void
-copy_attribute (GckAttributes *original, CK_ATTRIBUTE_TYPE type, GckAttributes *dest)
+copy_attribute (GckAttributes *original,
+                CK_ATTRIBUTE_TYPE type,
+                GckBuilder *dest)
 {
-	GckAttribute *attr;
+	const GckAttribute *attr;
 
 	g_assert (original);
 	g_assert (dest);
 
 	attr = gck_attributes_find (original, type);
 	if (attr)
-		gck_attributes_add (dest, attr);
+		gck_builder_add_owned (dest, attr);
 }
 
 static gboolean
@@ -84,7 +86,7 @@ login_session (GckSession *session)
 static GckAttributes*
 build_like_attributes (GckAttributes *attrs, CK_OBJECT_CLASS klass)
 {
-	GckAttributes *search;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	gulong key_type;
 
 	g_assert (attrs);
@@ -93,22 +95,21 @@ build_like_attributes (GckAttributes *attrs, CK_OBJECT_CLASS klass)
 	if (!gck_attributes_find_ulong (attrs, CKA_KEY_TYPE, &key_type))
 		g_return_val_if_reached (NULL);
 
-	search = gck_attributes_new ();
-	gck_attributes_add_ulong (search, CKA_CLASS, klass);
-	copy_attribute (attrs, CKA_KEY_TYPE, search);
-	copy_attribute (attrs, CKA_TOKEN, search);
+	gck_builder_add_ulong (&builder, CKA_CLASS, klass);
+	copy_attribute (attrs, CKA_KEY_TYPE, &builder);
+	copy_attribute (attrs, CKA_TOKEN, &builder);
 
 	switch (key_type) {
 	case CKK_RSA:
-		copy_attribute (attrs, CKA_MODULUS, search);
-		copy_attribute (attrs, CKA_PUBLIC_EXPONENT, search);
+		copy_attribute (attrs, CKA_MODULUS, &builder);
+		copy_attribute (attrs, CKA_PUBLIC_EXPONENT, &builder);
 		break;
 
 	case CKK_DSA:
-		copy_attribute (attrs, CKA_PRIME, search);
-		copy_attribute (attrs, CKA_SUBPRIME, search);
-		copy_attribute (attrs, CKA_BASE, search);
-		copy_attribute (attrs, CKA_VALUE, search);
+		copy_attribute (attrs, CKA_PRIME, &builder);
+		copy_attribute (attrs, CKA_SUBPRIME, &builder);
+		copy_attribute (attrs, CKA_BASE, &builder);
+		copy_attribute (attrs, CKA_VALUE, &builder);
 		break;
 
 	default:
@@ -116,7 +117,7 @@ build_like_attributes (GckAttributes *attrs, CK_OBJECT_CLASS klass)
 		break;
 	}
 
-	return search;
+	return gck_attributes_ref_sink (gck_builder_end (&builder));
 }
 
 static void
@@ -205,13 +206,13 @@ static gboolean
 return_private_matching (GckObject *object, gpointer user_data)
 {
 	GckObject **result = (GckObject**)user_data;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckSession *session;
 	GckAttributes *attrs;
-	GckAttribute *attr;
+	const GckAttribute *attr;
 	gboolean token;
 	GList *objects;
 	GError *error = NULL;
-	GckAttributes *atts;
 
 	g_return_val_if_fail (GCK_IS_OBJECT (object), FALSE);
 	g_return_val_if_fail (result != NULL, FALSE);
@@ -238,14 +239,12 @@ return_private_matching (GckObject *object, gpointer user_data)
 	if (!login_session (session))
 		return FALSE;
 
-	atts = gck_attributes_new ();
-	gck_attributes_add (atts, attr);
-	gck_attributes_add_ulong (atts, CKA_CLASS, CKO_PRIVATE_KEY);
-	gck_attributes_add_boolean (atts, CKA_TOKEN, token);
+	gck_builder_add_owned (&builder, attr);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PRIVATE_KEY);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, token);
 
 	/* Search for the matching private key */
-	objects = gck_session_find_objects (session, atts, NULL, NULL);
-	gck_attributes_unref (atts);
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, NULL);
 	gck_attributes_unref (attrs);
 
 	/* Keep searching, not found */
@@ -296,7 +295,7 @@ static gboolean
 load_identity_v2_attributes (GckObject *object, gpointer user_data)
 {
 	GckAttributes *attrs;
-	GckAttribute *attr;
+	const GckAttribute *attr;
 	GError *error = NULL;
 	gboolean valid = TRUE;
 	gboolean token;
@@ -372,7 +371,7 @@ remove_key_pair (GckSession *session, GckObject *priv, GckObject *pub)
 static void
 lock_key_pair (GckSession *session, GckObject *priv, GckObject *pub)
 {
-	GckAttributes *atts;
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GError *error = NULL;
 	GList *objects, *l;
 
@@ -383,13 +382,11 @@ lock_key_pair (GckSession *session, GckObject *priv, GckObject *pub)
 	if (!login_session (session))
 		return;
 
-	atts = gck_attributes_new ();
-	gck_attributes_add_ulong (atts, CKA_CLASS, CKO_G_CREDENTIAL);
-	gck_attributes_add_ulong (atts, CKA_G_OBJECT, gck_object_get_handle (priv));
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
+	gck_builder_add_ulong (&builder, CKA_G_OBJECT, gck_object_get_handle (priv));
 
 	/* Delete any authenticator objects */
-	objects = gck_session_find_objects (session, atts, NULL, &error);
-	gck_attributes_unref (atts);
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
 
 	if (error) {
 		g_warning ("couldn't search for authenticator objects: %s", egg_error_message (error));
@@ -410,6 +407,7 @@ lock_key_pair (GckSession *session, GckObject *priv, GckObject *pub)
 static void
 remove_by_public_key (GckSession *session, GckObject *pub, gboolean exclude_v1)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	GError *error = NULL;
 	GList *objects;
@@ -444,10 +442,12 @@ remove_by_public_key (GckSession *session, GckObject *pub, gboolean exclude_v1)
 		token = FALSE;
 
 	/* Search for exactly the same attributes but with a private key class */
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PRIVATE_KEY);
-	objects = gck_session_find_objects (session, attrs, NULL, &error);
+	gck_builder_add_all (&builder, attrs);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PRIVATE_KEY);
 	gck_attributes_unref (attrs);
 
+	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
+
 	if (error) {
 		g_warning ("couldn't search for related key: %s", egg_error_message (error));
 		g_clear_error (&error);
@@ -521,33 +521,41 @@ destroy_replaced_keys (GckSession *session, GList *keys)
 }
 
 static gboolean
-replace_key_pair (GckSession *session, GckAttributes *priv, GckAttributes *pub)
+replace_key_pair (GckSession *session,
+                  GckBuilder *priv,
+                  GckBuilder *pub)
 {
 	GList *priv_prev, *pub_prev;
+	GckAttributes *priv_atts, *pub_atts;
 
 	g_assert (GCK_IS_SESSION (session));
-	g_assert (priv);
-	g_assert (pub);
+	g_assert (priv != NULL);
+	g_assert (pub != NULL);
 
 	if (!login_session (session))
 		return FALSE;
 
-	gck_attributes_add_boolean (priv, CKA_TOKEN, FALSE);
-	gck_attributes_add_boolean (pub, CKA_TOKEN, FALSE);
+	gck_builder_set_boolean (priv, CKA_TOKEN, FALSE);
+	priv_atts = gck_attributes_ref_sink (gck_builder_end (priv));
+
+	gck_builder_set_boolean (pub, CKA_TOKEN, FALSE);
+	pub_atts = gck_attributes_ref_sink (gck_builder_end (pub));
 
 	/* Find the previous keys that match the same description */
 	priv_prev = pub_prev = NULL;
-	search_keys_like_attributes (NULL, session, priv, CKO_PRIVATE_KEY, list_all_matching, &priv_prev);
-	search_keys_like_attributes (NULL, session, priv, CKO_PUBLIC_KEY, list_all_matching, &pub_prev);
+	search_keys_like_attributes (NULL, session, priv_atts, CKO_PRIVATE_KEY, list_all_matching, &priv_prev);
+	search_keys_like_attributes (NULL, session, pub_atts, CKO_PUBLIC_KEY, list_all_matching, &pub_prev);
 
 	/* Now try and create the new keys */
-	if (create_key_pair (session, priv, pub)) {
+	if (create_key_pair (session, priv_atts, pub_atts)) {
 
 		/* Delete the old keys */
 		destroy_replaced_keys (session, priv_prev);
 		destroy_replaced_keys (session, pub_prev);
 	}
 
+	gck_attributes_unref (priv_atts);
+	gck_attributes_unref (pub_atts);
 	gck_list_unref_free (priv_prev);
 	gck_list_unref_free (pub_prev);
 
@@ -555,8 +563,11 @@ replace_key_pair (GckSession *session, GckAttributes *priv, GckAttributes *pub)
 }
 
 static gboolean
-load_contraints (EggBuffer *buffer, gsize offset, gsize *next_offset,
-                 GckAttributes *priv, GckAttributes *pub)
+load_contraints (EggBuffer *buffer,
+                 gsize offset,
+                 gsize *next_offset,
+                 GckBuilder *priv,
+                 GckBuilder *pub)
 {
 	guchar constraint;
 	guint32 lifetime;
@@ -575,8 +586,8 @@ load_contraints (EggBuffer *buffer, gsize offset, gsize *next_offset,
 			if (!egg_buffer_get_uint32 (buffer, offset, &offset, &lifetime))
 				return FALSE;
 
-			gck_attributes_add_ulong (pub, CKA_G_DESTRUCT_AFTER, lifetime);
-			gck_attributes_add_ulong (priv, CKA_G_DESTRUCT_AFTER, lifetime);
+			gck_builder_add_ulong (pub, CKA_G_DESTRUCT_AFTER, lifetime);
+			gck_builder_add_ulong (priv, CKA_G_DESTRUCT_AFTER, lifetime);
 			break;
 
 		case GKD_SSH_FLAG_CONSTRAIN_CONFIRM:
@@ -601,8 +612,8 @@ load_contraints (EggBuffer *buffer, gsize offset, gsize *next_offset,
 static gboolean
 op_add_identity (GkdSshAgentCall *call)
 {
-	GckAttributes *pub;
-	GckAttributes *priv;
+	GckBuilder pub;
+	GckBuilder priv;
 	GckSession *session;
 	gchar *stype = NULL;
 	gchar *comment = NULL;
@@ -621,15 +632,15 @@ op_add_identity (GkdSshAgentCall *call)
 	}
 
 	g_free (stype);
-	priv = gck_attributes_new_full ((GckAllocator)egg_secure_realloc);
-	pub = gck_attributes_new_full (g_realloc);
+	gck_builder_init_full (&pub, GCK_BUILDER_SECURE_MEMORY);
+	gck_builder_init_full (&priv, GCK_BUILDER_NONE);
 
 	switch (algo) {
 	case CKK_RSA:
-		ret = gkd_ssh_agent_proto_read_pair_rsa (call->req, &offset, priv, pub);
+		ret = gkd_ssh_agent_proto_read_pair_rsa (call->req, &offset, &priv, &pub);
 		break;
 	case CKK_DSA:
-		ret = gkd_ssh_agent_proto_read_pair_dsa (call->req, &offset, priv, pub);
+		ret = gkd_ssh_agent_proto_read_pair_dsa (call->req, &offset, &priv, &pub);
 		break;
 	default:
 		g_assert_not_reached ();
@@ -638,26 +649,26 @@ op_add_identity (GkdSshAgentCall *call)
 
 	if (!ret) {
 		g_warning ("couldn't read incoming SSH private key");
-		gck_attributes_unref (pub);
-		gck_attributes_unref (priv);
+		gck_builder_clear (&pub);
+		gck_builder_clear (&priv);
 		return FALSE;
 	}
 
 	/* Get the comment */
 	if (!egg_buffer_get_string (call->req, offset, &offset, &comment, (EggBufferAllocator)g_realloc)) {
-		gck_attributes_unref (pub);
-		gck_attributes_unref (priv);
+		gck_builder_clear (&pub);
+		gck_builder_clear (&priv);
 		return FALSE;
 	}
 
-	gck_attributes_add_string (pub, CKA_LABEL, comment);
-	gck_attributes_add_string (priv, CKA_LABEL, comment);
+	gck_builder_add_string (&pub, CKA_LABEL, comment);
+	gck_builder_add_string (&priv, CKA_LABEL, comment);
 	g_free (comment);
 
 	/* Any constraints on loading the key */
-	if (!load_contraints (call->req, offset, &offset, priv, pub)) {
-		gck_attributes_unref (pub);
-		gck_attributes_unref (priv);
+	if (!load_contraints (call->req, offset, &offset, &priv, &pub)) {
+		gck_builder_clear (&pub);
+		gck_builder_clear (&priv);
 		return FALSE;
 	}
 
@@ -669,12 +680,12 @@ op_add_identity (GkdSshAgentCall *call)
 	session = gkd_ssh_agent_checkout_main_session ();
 	g_return_val_if_fail (session, FALSE);
 
-	ret = replace_key_pair (session, priv, pub);
+	ret = replace_key_pair (session, &priv, &pub);
 
 	gkd_ssh_agent_checkin_main_session (session);
 
-	gck_attributes_unref (priv);
-	gck_attributes_unref (pub);
+	gck_builder_clear (&priv);
+	gck_builder_clear (&pub);
 
 	egg_buffer_add_byte (call->resp, ret ? GKD_SSH_RES_SUCCESS : GKD_SSH_RES_FAILURE);
 	return TRUE;
@@ -683,7 +694,7 @@ op_add_identity (GkdSshAgentCall *call)
 static gboolean
 op_v1_add_identity (GkdSshAgentCall *call)
 {
-	GckAttributes *pub, *priv;
+	GckBuilder pub, priv;
 	GckSession *session;
 	gchar *comment = NULL;
 	gboolean ret;
@@ -693,32 +704,32 @@ op_v1_add_identity (GkdSshAgentCall *call)
 	if (!egg_buffer_get_uint32 (call->req, offset, &offset, &unused))
 		return FALSE;
 
-	priv = gck_attributes_new_full ((GckAllocator)egg_secure_realloc);
-	pub = gck_attributes_new_full (g_realloc);
+	gck_builder_init_full (&priv, GCK_BUILDER_SECURE_MEMORY);
+	gck_builder_init_full (&pub, GCK_BUILDER_NONE);
 
-	if (!gkd_ssh_agent_proto_read_pair_v1 (call->req, &offset, priv, pub)) {
+	if (!gkd_ssh_agent_proto_read_pair_v1 (call->req, &offset, &priv, &pub)) {
 		g_warning ("couldn't read incoming SSH private key");
-		gck_attributes_unref (pub);
-		gck_attributes_unref (priv);
+		gck_builder_clear (&pub);
+		gck_builder_clear (&priv);
 		return FALSE;
 	}
 
 	/* Get the comment */
 	if (!egg_buffer_get_string (call->req, offset, &offset, &comment, (EggBufferAllocator)g_realloc)) {
-		gck_attributes_unref (pub);
-		gck_attributes_unref (priv);
+		gck_builder_clear (&pub);
+		gck_builder_clear (&priv);
 		return FALSE;
 	}
 
 	g_free (comment);
 
-	gck_attributes_add_string (priv, CKA_LABEL, V1_LABEL);
-	gck_attributes_add_string (pub, CKA_LABEL, V1_LABEL);
+	gck_builder_add_string (&priv, CKA_LABEL, V1_LABEL);
+	gck_builder_add_string (&pub, CKA_LABEL, V1_LABEL);
 
 	/* Any constraints on loading the key */
-	if (!load_contraints (call->req, offset, &offset, priv, pub)) {
-		gck_attributes_unref (pub);
-		gck_attributes_unref (priv);
+	if (!load_contraints (call->req, offset, &offset, &priv, &pub)) {
+		gck_builder_clear (&pub);
+		gck_builder_clear (&priv);
 		return FALSE;
 	}
 
@@ -730,12 +741,12 @@ op_v1_add_identity (GkdSshAgentCall *call)
 	session = gkd_ssh_agent_checkout_main_session ();
 	g_return_val_if_fail (session, FALSE);
 
-	ret = replace_key_pair (session, priv, pub);
+	ret = replace_key_pair (session, &priv, &pub);
 
 	gkd_ssh_agent_checkin_main_session (session);
 
-	gck_attributes_unref (priv);
-	gck_attributes_unref (pub);
+	gck_builder_clear (&pub);
+	gck_builder_clear (&priv);
 
 	egg_buffer_add_byte (call->resp, ret ? GKD_SSH_RES_SUCCESS : GKD_SSH_RES_FAILURE);
 	return TRUE;
@@ -744,6 +755,7 @@ op_v1_add_identity (GkdSshAgentCall *call)
 static gboolean
 op_request_identities (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckEnumerator *en;
 	GckObject *obj;
 	GError *error = NULL;
@@ -753,12 +765,11 @@ op_request_identities (GkdSshAgentCall *call)
 	gchar *comment;
 
 	/* TODO: Check SSH purpose */
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
 
 	/* Find all the keys (we filter out v1 later) */
-	en = gck_modules_enumerate_objects (call->modules, attrs, GCK_SESSION_AUTHENTICATE | GCK_SESSION_READ_WRITE);
-	gck_attributes_unref (attrs);
+	en = gck_modules_enumerate_objects (call->modules, gck_builder_end (&builder),
+	                                    GCK_SESSION_AUTHENTICATE | GCK_SESSION_READ_WRITE);
 	g_return_val_if_fail (en, FALSE);
 
 	all_attrs = NULL;
@@ -811,6 +822,7 @@ op_request_identities (GkdSshAgentCall *call)
 static gboolean
 op_v1_request_identities (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GList *all_attrs, *l;
 	GckAttributes *attrs;
 	GError *error = NULL;
@@ -818,15 +830,13 @@ op_v1_request_identities (GkdSshAgentCall *call)
 	GckObject *obj;
 
 	/* TODO: Check SSH purpose */
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
-	gck_attributes_add_string (attrs, CKA_LABEL, V1_LABEL);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
+	gck_builder_add_string (&builder, CKA_LABEL, V1_LABEL);
 
 	/* Find all the keys not on token, and are V1 */
-	en = gck_modules_enumerate_objects (call->modules, attrs, GCK_SESSION_AUTHENTICATE | GCK_SESSION_READ_WRITE);
-	gck_attributes_unref (attrs);
-	g_return_val_if_fail (en, FALSE);
+	en = gck_modules_enumerate_objects (call->modules, gck_builder_end (&builder),
+	                                    GCK_SESSION_AUTHENTICATE | GCK_SESSION_READ_WRITE);
 
 	all_attrs = NULL;
 	do {
@@ -936,6 +946,7 @@ static guchar*
 unlock_and_sign (GckSession *session, GckObject *key, gulong mech_type, const guchar *input,
                  gsize n_input, gsize *n_result, GError **err)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	GckObject *cred;
 	gboolean always;
@@ -952,14 +963,12 @@ unlock_and_sign (GckSession *session, GckObject *key, gulong mech_type, const gu
 	gck_attributes_unref (attrs);
 
 	if (always == TRUE) {
-		attrs = gck_attributes_new ();
-		gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_CREDENTIAL);
-		gck_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
-		gck_attributes_add_empty (attrs, CKA_VALUE);
-		gck_attributes_add_ulong (attrs, CKA_G_OBJECT, gck_object_get_handle (key));
+		gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
+		gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
+		gck_builder_add_empty (&builder, CKA_VALUE);
+		gck_builder_add_ulong (&builder, CKA_G_OBJECT, gck_object_get_handle (key));
 
-		cred = gck_session_create_object (session, attrs, NULL, err);
-		gck_attributes_unref (attrs);
+		cred = gck_session_create_object (session, gck_builder_end (&builder), NULL, err);
 
 		if (cred == NULL)
 			return NULL;
@@ -974,6 +983,7 @@ unlock_and_sign (GckSession *session, GckObject *key, gulong mech_type, const gu
 static gboolean
 op_sign_request (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	GError *error = NULL;
 	GckObject *key = NULL;
@@ -998,9 +1008,12 @@ op_sign_request (GkdSshAgentCall *call)
 		return FALSE;
 
 	/* The key itself */
-	attrs = gck_attributes_new ();
-	if (!gkd_ssh_agent_proto_read_public (call->req, &offset, attrs, &algo))
+	if (!gkd_ssh_agent_proto_read_public (call->req, &offset, &builder, &algo)) {
+		gck_builder_clear (&builder);
 		return FALSE;
+	}
+
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
 	/* Validate the key type / mechanism */
 	if (algo == CKK_RSA)
@@ -1090,6 +1103,7 @@ op_sign_request (GkdSshAgentCall *call)
 static gboolean
 op_v1_challenge (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	gsize offset, n_data, n_result, n_hash;
 	GckSession *session;
 	GckAttributes *attrs;
@@ -1106,12 +1120,13 @@ op_v1_challenge (GkdSshAgentCall *call)
 
 	offset = 5;
 
-	attrs = gck_attributes_new ();
-	if (!gkd_ssh_agent_proto_read_public_v1 (call->req, &offset, attrs)) {
-		gck_attributes_unref (attrs);
+	if (!gkd_ssh_agent_proto_read_public_v1 (call->req, &offset, &builder)) {
+		gck_builder_clear (&builder);
 		return FALSE;
 	}
 
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
+
 	/* Read the entire challenge */
 	data = gkd_ssh_agent_proto_read_challenge_v1 (call->req, &offset, &n_data);
 
@@ -1187,6 +1202,7 @@ op_v1_challenge (GkdSshAgentCall *call)
 static gboolean
 op_remove_identity (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckAttributes *attrs;
 	GckSession *session;
 	GckObject *key = NULL;
@@ -1200,12 +1216,13 @@ op_remove_identity (GkdSshAgentCall *call)
 		return FALSE;
 
 	/* The public key itself */
-	attrs = gck_attributes_new ();
-	if (!gkd_ssh_agent_proto_read_public (call->req, &offset, attrs, NULL)) {
-		gck_attributes_unref (attrs);
+	if (!gkd_ssh_agent_proto_read_public (call->req, &offset, &builder, NULL)) {
+		gck_builder_clear (&builder);
 		return FALSE;
 	}
 
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
+
 	/*
 	 * This is the session that owns these objects. Only
 	 * one thread can use it at a time.
@@ -1232,6 +1249,7 @@ op_remove_identity (GkdSshAgentCall *call)
 static gboolean
 op_v1_remove_identity (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckSession *session;
 	GckAttributes *attrs;
 	GckObject *key = NULL;
@@ -1239,12 +1257,13 @@ op_v1_remove_identity (GkdSshAgentCall *call)
 
 	offset = 5;
 
-	attrs = gck_attributes_new ();
-	if (!gkd_ssh_agent_proto_read_public_v1 (call->req, &offset, attrs)) {
-		gck_attributes_unref (attrs);
+	if (!gkd_ssh_agent_proto_read_public_v1 (call->req, &offset, &builder)) {
+		gck_builder_clear (&builder);
 		return FALSE;
 	}
 
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
+
 	/*
 	 * This is the session that owns these objects. Only
 	 * one thread can use it at a time.
@@ -1270,6 +1289,7 @@ op_v1_remove_identity (GkdSshAgentCall *call)
 static gboolean
 op_remove_all_identities (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckSession *session;
 	GList *objects, *l;
 	GError *error = NULL;
@@ -1284,8 +1304,8 @@ op_remove_all_identities (GkdSshAgentCall *call)
 	g_return_val_if_fail (session, FALSE);
 
 	/* Find all session SSH public keys */
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
 	objects = gck_session_find_objects (session, attrs, NULL, &error);
 	gck_attributes_unref (attrs);
@@ -1309,6 +1329,7 @@ op_remove_all_identities (GkdSshAgentCall *call)
 static gboolean
 op_v1_remove_all_identities (GkdSshAgentCall *call)
 {
+	GckBuilder builder = GCK_BUILDER_INIT;
 	GckSession *session;
 	GList *objects, *l;
 	GError *error = NULL;
@@ -1323,10 +1344,10 @@ op_v1_remove_all_identities (GkdSshAgentCall *call)
 	g_return_val_if_fail (session, FALSE);
 
 	/* Find all session SSH v1 public keys */
-	attrs = gck_attributes_new ();
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_boolean (attrs, CKA_TOKEN, FALSE);
-	gck_attributes_add_string (attrs, CKA_LABEL, V1_LABEL);
+	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
+	gck_builder_add_string (&builder, CKA_LABEL, V1_LABEL);
+	attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
 
 	objects = gck_session_find_objects (session, attrs, NULL, &error);
 	gck_attributes_unref (attrs);
diff --git a/daemon/ssh-agent/gkd-ssh-agent-private.h b/daemon/ssh-agent/gkd-ssh-agent-private.h
index 2fe598f..efdc969 100644
--- a/daemon/ssh-agent/gkd-ssh-agent-private.h
+++ b/daemon/ssh-agent/gkd-ssh-agent-private.h
@@ -107,12 +107,12 @@ const gchar*          gkd_ssh_agent_proto_algo_to_keytype           (gulong algo
 
 gboolean              gkd_ssh_agent_proto_read_mpi                  (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *attrs,
+                                                                     GckBuilder *attrs,
                                                                      CK_ATTRIBUTE_TYPE type);
 
 gboolean              gkd_ssh_agent_proto_read_mpi_v1               (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *attrs,
+                                                                     GckBuilder *attrs,
                                                                      CK_ATTRIBUTE_TYPE type);
 
 const guchar*         gkd_ssh_agent_proto_read_challenge_v1         (EggBuffer *req,
@@ -120,42 +120,42 @@ const guchar*         gkd_ssh_agent_proto_read_challenge_v1         (EggBuffer *
                                                                      gsize *n_challenge);
 
 gboolean              gkd_ssh_agent_proto_write_mpi                 (EggBuffer *resp,
-                                                                     GckAttribute *attr);
+                                                                     const GckAttribute *attr);
 
 gboolean              gkd_ssh_agent_proto_write_mpi_v1              (EggBuffer *resp,
-                                                                     GckAttribute *attr);
+                                                                     const GckAttribute *attr);
 
 gboolean              gkd_ssh_agent_proto_read_public               (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *attrs,
+                                                                     GckBuilder *attrs,
                                                                      gulong *algo);
 
 gboolean              gkd_ssh_agent_proto_read_public_rsa           (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *attrs);
+                                                                     GckBuilder *attrs);
 
 gboolean              gkd_ssh_agent_proto_read_public_dsa           (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *attrs);
+                                                                     GckBuilder *attrs);
 
 gboolean              gkd_ssh_agent_proto_read_public_v1            (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *attrs);
+                                                                     GckBuilder *attrs);
 
 gboolean              gkd_ssh_agent_proto_read_pair_rsa             (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *priv_attrs,
-                                                                     GckAttributes *pub_attrs);
+                                                                     GckBuilder *priv,
+                                                                     GckBuilder *pub);
 
 gboolean              gkd_ssh_agent_proto_read_pair_dsa             (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *priv_attrs,
-                                                                     GckAttributes *pub_attrs);
+                                                                     GckBuilder *priv,
+                                                                     GckBuilder *pub);
 
 gboolean              gkd_ssh_agent_proto_read_pair_v1              (EggBuffer *req,
                                                                      gsize *offset,
-                                                                     GckAttributes *priv_attrs,
-                                                                     GckAttributes *pub_attrs);
+                                                                     GckBuilder *priv,
+                                                                     GckBuilder *pub);
 
 gboolean              gkd_ssh_agent_proto_write_public              (EggBuffer *resp,
                                                                      GckAttributes *attrs);
diff --git a/daemon/ssh-agent/gkd-ssh-agent-proto.c b/daemon/ssh-agent/gkd-ssh-agent-proto.c
index b6de1bc..0377fcf 100644
--- a/daemon/ssh-agent/gkd-ssh-agent-proto.c
+++ b/daemon/ssh-agent/gkd-ssh-agent-proto.c
@@ -54,7 +54,8 @@ gkd_ssh_agent_proto_algo_to_keytype (gulong algo)
 }
 
 gboolean
-gkd_ssh_agent_proto_read_mpi (EggBuffer *req, gsize *offset, GckAttributes *attrs,
+gkd_ssh_agent_proto_read_mpi (EggBuffer *req, gsize *offset,
+                              GckBuilder *builder,
                               CK_ATTRIBUTE_TYPE type)
 {
 	const guchar *data;
@@ -69,12 +70,14 @@ gkd_ssh_agent_proto_read_mpi (EggBuffer *req, gsize *offset, GckAttributes *attr
 		--len;
 	}
 
-	gck_attributes_add_data (attrs, type, data, len);
+	gck_builder_add_data (builder, type, data, len);
 	return TRUE;
 }
 
 gboolean
-gkd_ssh_agent_proto_read_mpi_v1 (EggBuffer *req, gsize *offset, GckAttributes *attrs,
+gkd_ssh_agent_proto_read_mpi_v1 (EggBuffer *req,
+                                 gsize *offset,
+                                 GckBuilder *attrs,
                                  CK_ATTRIBUTE_TYPE type)
 {
 	const guchar *data;
@@ -96,12 +99,13 @@ gkd_ssh_agent_proto_read_mpi_v1 (EggBuffer *req, gsize *offset, GckAttributes *a
 	data = req->buf + *offset;
 	*offset += bytes;
 
-	gck_attributes_add_data (attrs, type, data, bytes);
+	gck_builder_add_data (attrs, type, data, bytes);
 	return TRUE;
 }
 
 gboolean
-gkd_ssh_agent_proto_write_mpi (EggBuffer *resp, GckAttribute *attr)
+gkd_ssh_agent_proto_write_mpi (EggBuffer *resp,
+                               const GckAttribute *attr)
 {
 	const guchar *value;
 	guchar *data;
@@ -126,7 +130,8 @@ gkd_ssh_agent_proto_write_mpi (EggBuffer *resp, GckAttribute *attr)
 }
 
 gboolean
-gkd_ssh_agent_proto_write_mpi_v1 (EggBuffer *resp, GckAttribute *attr)
+gkd_ssh_agent_proto_write_mpi_v1 (EggBuffer *resp,
+                                  const GckAttribute *attr)
 {
 	guchar *data;
 
@@ -168,7 +173,10 @@ gkd_ssh_agent_proto_read_challenge_v1 (EggBuffer *req, gsize *offset, gsize *n_c
 }
 
 gboolean
-gkd_ssh_agent_proto_read_public (EggBuffer *req, gsize *offset, GckAttributes* attrs, gulong *algo)
+gkd_ssh_agent_proto_read_public (EggBuffer *req,
+                                 gsize *offset,
+                                 GckBuilder *attrs,
+                                 gulong *algo)
 {
 	gboolean ret;
 	gchar *stype;
@@ -212,10 +220,12 @@ gkd_ssh_agent_proto_read_public (EggBuffer *req, gsize *offset, GckAttributes* a
 }
 
 gboolean
-gkd_ssh_agent_proto_read_pair_rsa (EggBuffer *req, gsize *offset,
-                                   GckAttributes *priv_attrs, GckAttributes *pub_attrs)
+gkd_ssh_agent_proto_read_pair_rsa (EggBuffer *req,
+                                   gsize *offset,
+                                   GckBuilder *priv_attrs,
+                                   GckBuilder *pub_attrs)
 {
-	GckAttribute *attr;
+	const GckAttribute *attr;
 
 	g_assert (req);
 	g_assert (offset);
@@ -231,25 +241,27 @@ gkd_ssh_agent_proto_read_pair_rsa (EggBuffer *req, gsize *offset,
 		return FALSE;
 
 	/* Copy attributes to the public key */
-	attr = gck_attributes_find (priv_attrs, CKA_MODULUS);
-	gck_attributes_add (pub_attrs, attr);
-	attr = gck_attributes_find (priv_attrs, CKA_PUBLIC_EXPONENT);
-	gck_attributes_add (pub_attrs, attr);
+	attr = gck_builder_find (priv_attrs, CKA_MODULUS);
+	gck_builder_add_owned (pub_attrs, attr);
+	attr = gck_builder_find (priv_attrs, CKA_PUBLIC_EXPONENT);
+	gck_builder_add_owned (pub_attrs, attr);
 
 	/* Add in your basic other required attributes */
-	gck_attributes_add_ulong (priv_attrs, CKA_CLASS, CKO_PRIVATE_KEY);
-	gck_attributes_add_ulong (priv_attrs, CKA_KEY_TYPE, CKK_RSA);
-	gck_attributes_add_ulong (pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_ulong (pub_attrs, CKA_KEY_TYPE, CKK_RSA);
+	gck_builder_add_ulong (priv_attrs, CKA_CLASS, CKO_PRIVATE_KEY);
+	gck_builder_add_ulong (priv_attrs, CKA_KEY_TYPE, CKK_RSA);
+	gck_builder_add_ulong (pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (pub_attrs, CKA_KEY_TYPE, CKK_RSA);
 
 	return TRUE;
 }
 
 gboolean
-gkd_ssh_agent_proto_read_pair_v1 (EggBuffer *req, gsize *offset,
-                                  GckAttributes *priv_attrs, GckAttributes *pub_attrs)
+gkd_ssh_agent_proto_read_pair_v1 (EggBuffer *req,
+                                  gsize *offset,
+                                  GckBuilder *priv_attrs,
+                                  GckBuilder *pub_attrs)
 {
-	GckAttribute *attr;
+	const GckAttribute *attr;
 
 	g_assert (req);
 	g_assert (offset);
@@ -265,22 +277,24 @@ gkd_ssh_agent_proto_read_pair_v1 (EggBuffer *req, gsize *offset,
 		return FALSE;
 
 	/* Copy attributes to the public key */
-	attr = gck_attributes_find (priv_attrs, CKA_MODULUS);
-	gck_attributes_add (pub_attrs, attr);
-	attr = gck_attributes_find (priv_attrs, CKA_PUBLIC_EXPONENT);
-	gck_attributes_add (pub_attrs, attr);
+	attr = gck_builder_find (priv_attrs, CKA_MODULUS);
+	gck_builder_add_owned (pub_attrs, attr);
+	attr = gck_builder_find (priv_attrs, CKA_PUBLIC_EXPONENT);
+	gck_builder_add_owned (pub_attrs, attr);
 
 	/* Add in your basic other required attributes */
-	gck_attributes_add_ulong (priv_attrs, CKA_CLASS, CKO_PRIVATE_KEY);
-	gck_attributes_add_ulong (priv_attrs, CKA_KEY_TYPE, CKK_RSA);
-	gck_attributes_add_ulong (pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_ulong (pub_attrs, CKA_KEY_TYPE, CKK_RSA);
+	gck_builder_add_ulong (priv_attrs, CKA_CLASS, CKO_PRIVATE_KEY);
+	gck_builder_add_ulong (priv_attrs, CKA_KEY_TYPE, CKK_RSA);
+	gck_builder_add_ulong (pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (pub_attrs, CKA_KEY_TYPE, CKK_RSA);
 
 	return TRUE;
 }
 
 gboolean
-gkd_ssh_agent_proto_read_public_rsa (EggBuffer *req, gsize *offset, GckAttributes *attrs)
+gkd_ssh_agent_proto_read_public_rsa (EggBuffer *req,
+                                     gsize *offset,
+                                     GckBuilder *attrs)
 {
 	g_assert (req);
 	g_assert (offset);
@@ -291,14 +305,16 @@ gkd_ssh_agent_proto_read_public_rsa (EggBuffer *req, gsize *offset, GckAttribute
 		return FALSE;
 
 	/* Add in your basic other required attributes */
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_RSA);
+	gck_builder_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (attrs, CKA_KEY_TYPE, CKK_RSA);
 
 	return TRUE;
 }
 
 gboolean
-gkd_ssh_agent_proto_read_public_v1 (EggBuffer *req, gsize *offset, GckAttributes *attrs)
+gkd_ssh_agent_proto_read_public_v1 (EggBuffer *req,
+                                    gsize *offset,
+                                    GckBuilder *attrs)
 {
 	guint32 bits;
 
@@ -314,17 +330,19 @@ gkd_ssh_agent_proto_read_public_v1 (EggBuffer *req, gsize *offset, GckAttributes
 		return FALSE;
 
 	/* Add in your basic other required attributes */
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_RSA);
+	gck_builder_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (attrs, CKA_KEY_TYPE, CKK_RSA);
 
 	return TRUE;
 }
 
 gboolean
-gkd_ssh_agent_proto_read_pair_dsa (EggBuffer *req, gsize *offset,
-                                   GckAttributes *priv_attrs, GckAttributes *pub_attrs)
+gkd_ssh_agent_proto_read_pair_dsa (EggBuffer *req,
+                                   gsize *offset,
+                                   GckBuilder *priv_attrs,
+                                   GckBuilder *pub_attrs)
 {
-	GckAttribute *attr;
+	const GckAttribute *attr;
 
 	g_assert (req);
 	g_assert (offset);
@@ -339,24 +357,26 @@ gkd_ssh_agent_proto_read_pair_dsa (EggBuffer *req, gsize *offset,
 		return FALSE;
 
 	/* Copy attributes to the public key */
-	attr = gck_attributes_find (priv_attrs, CKA_PRIME);
-	gck_attributes_add (pub_attrs, attr);
-	attr = gck_attributes_find (priv_attrs, CKA_SUBPRIME);
-	gck_attributes_add (pub_attrs, attr);
-	attr = gck_attributes_find (priv_attrs, CKA_BASE);
-	gck_attributes_add (pub_attrs, attr);
+	attr = gck_builder_find (priv_attrs, CKA_PRIME);
+	gck_builder_add_owned (pub_attrs, attr);
+	attr = gck_builder_find (priv_attrs, CKA_SUBPRIME);
+	gck_builder_add_owned (pub_attrs, attr);
+	attr = gck_builder_find (priv_attrs, CKA_BASE);
+	gck_builder_add_owned (pub_attrs, attr);
 
 	/* Add in your basic other required attributes */
-	gck_attributes_add_ulong (priv_attrs, CKA_CLASS, CKO_PRIVATE_KEY);
-	gck_attributes_add_ulong (priv_attrs, CKA_KEY_TYPE, CKK_DSA);
-	gck_attributes_add_ulong (pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_ulong (pub_attrs, CKA_KEY_TYPE, CKK_DSA);
+	gck_builder_add_ulong (priv_attrs, CKA_CLASS, CKO_PRIVATE_KEY);
+	gck_builder_add_ulong (priv_attrs, CKA_KEY_TYPE, CKK_DSA);
+	gck_builder_add_ulong (pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (pub_attrs, CKA_KEY_TYPE, CKK_DSA);
 
 	return TRUE;
 }
 
 gboolean
-gkd_ssh_agent_proto_read_public_dsa (EggBuffer *req, gsize *offset, GckAttributes *attrs)
+gkd_ssh_agent_proto_read_public_dsa (EggBuffer *req,
+                                     gsize *offset,
+                                     GckBuilder *attrs)
 {
 	g_assert (req);
 	g_assert (offset);
@@ -369,8 +389,8 @@ gkd_ssh_agent_proto_read_public_dsa (EggBuffer *req, gsize *offset, GckAttribute
 		return FALSE;
 
 	/* Add in your basic other required attributes */
-	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_DSA);
+	gck_builder_add_ulong (attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+	gck_builder_add_ulong (attrs, CKA_KEY_TYPE, CKK_DSA);
 
 	return TRUE;
 }
@@ -412,7 +432,7 @@ gkd_ssh_agent_proto_write_public (EggBuffer *resp, GckAttributes *attrs)
 gboolean
 gkd_ssh_agent_proto_write_public_rsa (EggBuffer *resp, GckAttributes *attrs)
 {
-	GckAttribute *attr;
+	const GckAttribute *attr;
 
 	g_assert (resp);
 	g_assert (attrs);
@@ -435,7 +455,7 @@ gkd_ssh_agent_proto_write_public_rsa (EggBuffer *resp, GckAttributes *attrs)
 gboolean
 gkd_ssh_agent_proto_write_public_dsa (EggBuffer *resp, GckAttributes *attrs)
 {
-	GckAttribute *attr;
+	const GckAttribute *attr;
 
 	g_assert (resp);
 	g_assert (attrs);
@@ -470,7 +490,7 @@ gkd_ssh_agent_proto_write_public_dsa (EggBuffer *resp, GckAttributes *attrs)
 gboolean
 gkd_ssh_agent_proto_write_public_v1 (EggBuffer *resp, GckAttributes *attrs)
 {
-	GckAttribute *attr;
+	const GckAttribute *attr;
 	gulong bits;
 
 	g_assert (resp);
diff --git a/daemon/ssh-agent/gkd-ssh-agent.c b/daemon/ssh-agent/gkd-ssh-agent.c
index 7ac1cc9..aa1fd54 100644
--- a/daemon/ssh-agent/gkd-ssh-agent.c
+++ b/daemon/ssh-agent/gkd-ssh-agent.c
@@ -377,7 +377,7 @@ gkd_ssh_agent_initialize_with_module (GckModule *module)
 {
 	GckSession *session = NULL;
 	GList *slots, *l;
-	GckMechanisms *mechs;
+	GArray *mechs;
 	GError *error = NULL;
 
 	g_assert (GCK_IS_MODULE (module));
@@ -398,7 +398,7 @@ gkd_ssh_agent_initialize_with_module (GckModule *module)
 			}
 		}
 
-		gck_mechanisms_free (mechs);
+		g_array_unref (mechs);
 	}
 
 	gck_list_unref_free (slots);
diff --git a/tool/gkr-tool-import.c b/tool/gkr-tool-import.c
index 7c0049a..b8574f2 100644
--- a/tool/gkr-tool-import.c
+++ b/tool/gkr-tool-import.c
@@ -52,7 +52,7 @@ imported_object (GckObject *object,
 {
 	gulong attr_types[3];
 	GckAttributes *attrs;
-	GckAttribute *id;
+	const GckAttribute *id;
 	CK_OBJECT_CLASS klass;
 	const gchar *message;
 	GError *err = NULL;



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