void gkm_object_destroy (GkmObject *self, GkmTransaction *transaction) { GkmSession *session; GkmManager *manager; GkmModule *module; g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (self->pv->module); g_object_ref (self); session = gkm_session_for_session_object (self); if (session != NULL) { gkm_session_destroy_session_object (session, transaction, self); } else { manager = gkm_object_get_manager (self); module = gkm_object_get_module (self); if (manager == gkm_module_get_manager (module)) gkm_module_remove_token_object (module, transaction, self); } /* Forcefully dispose of the object once the transaction completes */ gkm_transaction_add (transaction, NULL, complete_destroy, g_object_ref (self)); g_object_unref (self); }
static gboolean begin_write_state (GkmMate2Storage *self, GkmTransaction *transaction) { g_assert (GKM_IS_MATE2_STORAGE (self)); g_assert (GKM_IS_TRANSACTION (transaction)); g_return_val_if_fail (!gkm_transaction_get_failed (transaction), FALSE); /* Already in write state for this transaction? */ if (self->transaction != NULL) { g_return_val_if_fail (self->transaction == transaction, FALSE); return TRUE; } /* Lock file for the transaction */ self->read_fd = begin_lock_file (self, transaction); if (self->read_fd == -1) return FALSE; gkm_transaction_add (transaction, self, complete_write_state, NULL); self->transaction = g_object_ref (transaction); /* Open the new file */ g_assert (self->write_fd == -1); self->write_path = g_strdup_printf ("%s.XXXXXX", self->filename); self->write_fd = g_mkstemp (self->write_path); if (self->write_fd == -1) { g_message ("couldn't open new temporary store file: %s: %s", self->write_path, g_strerror (errno)); gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return FALSE; } return TRUE; }
static GkmObject* factory_create_item (GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { GkmSecretCollection *collection = NULL; GkmSecretItem *item; GkmManager *m_manager; GkmManager *s_manager; CK_ATTRIBUTE *attr; gboolean is_token; gchar *identifier; g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL); g_return_val_if_fail (attrs || !n_attrs, NULL); /* See if a collection attribute was specified */ attr = gkm_attributes_find (attrs, n_attrs, CKA_G_COLLECTION); if (attr == NULL) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE); return NULL; } m_manager = gkm_module_get_manager (gkm_session_get_module (session)); s_manager = gkm_session_get_manager (session); gkm_attribute_consume (attr); if (!gkm_attributes_find_boolean (attrs, n_attrs, CKA_TOKEN, &is_token)) collection = gkm_secret_collection_find (session, attr, m_manager, s_manager, NULL); else if (is_token) collection = gkm_secret_collection_find (session, attr, m_manager, NULL); else collection = gkm_secret_collection_find (session, attr, s_manager, NULL); if (!collection) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT); return NULL; } /* If an ID was specified, then try and see if that ID already exists */ if (gkm_attributes_find_string (attrs, n_attrs, CKA_ID, &identifier)) { item = gkm_secret_collection_get_item (collection, identifier); if (item == NULL) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT); return NULL; } else { gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (item), FALSE, attrs, n_attrs); return g_object_ref (item); } } /* Create a new collection which will own the item */ item = gkm_secret_collection_create_item (collection, transaction); gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (item), TRUE, attrs, n_attrs); return g_object_ref (item); }
static gboolean begin_new_file (GkmTransaction *self, const gchar *filename) { g_assert (GKM_IS_TRANSACTION (self)); g_assert (!gkm_transaction_get_failed (self)); g_assert (filename); gkm_transaction_add (self, NULL, complete_new_file, g_strdup (filename)); return TRUE; }
static gint begin_lock_file (GkmMate2Storage *self, GkmTransaction *transaction) { guint tries = 0; gint fd = -1; /* * In this function we don't actually put the object into a 'write' state, * that's the callers job if necessary. */ g_assert (GKM_IS_MATE2_STORAGE (self)); g_assert (GKM_IS_TRANSACTION (transaction)); g_return_val_if_fail (!gkm_transaction_get_failed (transaction), -1); /* File lock retry loop */ for (tries = 0; TRUE; ++tries) { if (tries > MAX_LOCK_TRIES) { g_message ("couldn't write to store file: %s: file is locked", self->filename); gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return -1; } fd = open (self->filename, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) { g_message ("couldn't open store file: %s: %s", self->filename, g_strerror (errno)); gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return -1; } if (flock (fd, LOCK_EX | LOCK_NB) < 0) { if (errno != EWOULDBLOCK) { g_message ("couldn't lock store file: %s: %s", self->filename, g_strerror (errno)); close (fd); gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return -1; } close (fd); fd = -1; g_usleep (200000); continue; } /* Successfully opened file */; gkm_transaction_add (transaction, self, complete_lock_file, GINT_TO_POINTER (fd)); return fd; } g_assert_not_reached (); }
static void gkm_mate2_storage_real_write_value (GkmStore *base, GkmTransaction *transaction, GkmObject *object, CK_ATTRIBUTE_PTR attr) { GkmMate2Storage *self = GKM_MATE2_STORAGE (base); const gchar *identifier; GkmDataResult res; CK_RV rv; g_return_if_fail (GKM_IS_MATE2_STORAGE (self)); g_return_if_fail (GKM_IS_OBJECT (object)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (attr); identifier = g_hash_table_lookup (self->object_to_identifier, object); if (!identifier) { gkm_transaction_fail (transaction, CKR_ATTRIBUTE_READ_ONLY); return; } if (self->last_mtime == 0) { rv = gkm_mate2_storage_refresh (self); if (rv != CKR_OK) { gkm_transaction_fail (transaction, rv); return; } } res = gkm_mate2_file_write_value (self->file, identifier, attr->type, attr->pValue, attr->ulValueLen); switch (res) { case GKM_DATA_FAILURE: rv = CKR_FUNCTION_FAILED; break; case GKM_DATA_UNRECOGNIZED: rv = CKR_ATTRIBUTE_READ_ONLY; break; case GKM_DATA_LOCKED: rv = CKR_USER_NOT_LOGGED_IN; break; case GKM_DATA_SUCCESS: rv = CKR_OK; break; default: g_assert_not_reached (); } if (rv != CKR_OK) gkm_transaction_fail (transaction, rv); }
void gkm_object_set_attribute (GkmObject *self, GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attr) { g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (attr); g_assert (GKM_OBJECT_GET_CLASS (self)->set_attribute); /* Check that the value will actually change */ if (!gkm_object_match (self, session, attr)) GKM_OBJECT_GET_CLASS (self)->set_attribute (self, session, transaction, attr); }
void gkm_object_create_attributes (GkmObject *self, GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (GKM_IS_SESSION (session)); g_return_if_fail (attrs); g_assert (GKM_OBJECT_GET_CLASS (self)->create_attributes); /* Check that the value will actually change */ GKM_OBJECT_GET_CLASS (self)->create_attributes (self, session, transaction, attrs, n_attrs); }
static GkmObject* factory_create_credential (GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { CK_OBJECT_HANDLE handle; GkmCredential *cred; CK_ATTRIBUTE *attr; GkmManager *manager; GkmModule *module; GkmObject *object = NULL; CK_RV rv; g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL); g_return_val_if_fail (attrs || !n_attrs, NULL); /* The handle is optional */ if (gkm_attributes_find_ulong (attrs, n_attrs, CKA_G_OBJECT, &handle)) { rv = gkm_session_lookup_readable_object (session, handle, &object); if (rv != CKR_OK) { gkm_transaction_fail (transaction, rv); return NULL; } } else { object = NULL; } /* The value is optional */ attr = gkm_attributes_find (attrs, n_attrs, CKA_VALUE); gkm_attributes_consume (attrs, n_attrs, CKA_VALUE, CKA_G_OBJECT, G_MAXULONG); module = gkm_session_get_module (session); manager = gkm_manager_for_template (attrs, n_attrs, session); rv = gkm_credential_create (module, manager, object, attr ? attr->pValue : NULL, attr ? attr->ulValueLen : 0, &cred); if (rv == CKR_OK) { gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (cred), TRUE, attrs, n_attrs); return GKM_OBJECT (cred); } else { gkm_transaction_fail (transaction, rv); return NULL; } }
void gkm_xdg_trust_remove_assertion (GkmXdgTrust *self, GkmAssertion *assertion, GkmTransaction *transaction) { GBytes *key; g_return_if_fail (GKM_XDG_IS_TRUST (self)); g_return_if_fail (GKM_IS_ASSERTION (assertion)); g_return_if_fail (!transaction || GKM_IS_TRANSACTION (transaction)); key = lookup_assertion_key (assertion); g_return_if_fail (key); /* Assertion needs to be from this trust object */ g_return_if_fail (g_hash_table_lookup (self->pv->assertions, key) == assertion); remove_assertion_from_trust (self, assertion, transaction); }
void gkm_mate2_storage_destroy (GkmMate2Storage *self, GkmTransaction *transaction, GkmObject *object) { GkmDataResult res; gchar *identifier; gchar *path; g_return_if_fail (GKM_IS_MATE2_STORAGE (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (object); /* Lookup the object identifier */ identifier = g_hash_table_lookup (self->object_to_identifier, object); g_return_if_fail (identifier); if (!begin_modification_state (self, transaction)) return; /* First actually delete the file */ path = g_build_filename (self->directory, identifier, NULL); gkm_transaction_remove_file (transaction, path); g_free (path); if (gkm_transaction_get_failed (transaction)) return; /* Now delete the entry from our store */ res = gkm_mate2_file_destroy_entry (self->file, identifier); switch(res) { case GKM_DATA_FAILURE: case GKM_DATA_UNRECOGNIZED: gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return; case GKM_DATA_LOCKED: gkm_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN); return; case GKM_DATA_SUCCESS: break; default: g_assert_not_reached (); } /* Actual removal of object happened as a callback above */ g_return_if_fail (g_hash_table_lookup (self->object_to_identifier, object) == NULL); }
void gkm_xdg_trust_replace_assertion (GkmXdgTrust *self, GkmAssertion *assertion, GkmTransaction *transaction) { GkmAssertion *previous; GBytes *key; g_return_if_fail (GKM_XDG_IS_TRUST (self)); g_return_if_fail (GKM_IS_ASSERTION (assertion)); g_return_if_fail (!transaction || GKM_IS_TRANSACTION (transaction)); /* Build up a key if we don't have one */ key = lookup_or_create_assertion_key (assertion); /* Remove any previous assertion with this key */ previous = g_hash_table_lookup (self->pv->assertions, key); if (previous != NULL) remove_assertion_from_trust (self, previous, transaction); add_assertion_to_trust (self, assertion, transaction); }
static gboolean complete_write_state (GkmTransaction *transaction, GObject *object, gpointer unused) { GkmMate2Storage *self = GKM_MATE2_STORAGE (object); gboolean ret = TRUE; struct stat sb; g_return_val_if_fail (GKM_IS_MATE2_STORAGE (object), FALSE); g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), FALSE); g_return_val_if_fail (self->transaction == transaction, FALSE); /* Transaction succeeded, overwrite the old with the new */ if (!gkm_transaction_get_failed (transaction)) { if (g_rename (self->write_path, self->filename) == -1) { g_warning ("couldn't rename temporary store file: %s", self->write_path); ret = FALSE; } else { if (fstat (self->write_fd, &sb) >= 0) self->last_mtime = sb.st_mtime; } } /* read_fd is closed by complete_lock_file */ if (self->write_fd != -1) close (self->write_fd); self->write_fd = -1; g_free (self->write_path); self->write_path = NULL; g_object_unref (self->transaction); self->transaction = NULL; return ret; }
static GkmObject* factory_create_certificate (GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { CK_ATTRIBUTE_PTR attr; GkmCertificate *cert; g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL); g_return_val_if_fail (attrs || !n_attrs, NULL); /* Dig out the value */ attr = gkm_attributes_find (attrs, n_attrs, CKA_VALUE); if (attr == NULL) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE); return NULL; } cert = g_object_new (GKM_TYPE_CERTIFICATE, "module", gkm_session_get_module (session), "manager", gkm_manager_for_template (attrs, n_attrs, session), NULL); /* Load the certificate from the data specified */ if (!gkm_serializable_load (GKM_SERIALIZABLE (cert), NULL, attr->pValue, attr->ulValueLen)) { gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID); g_object_unref (cert); return NULL; } /* Note that we ignore the subject */ gkm_attributes_consume (attrs, n_attrs, CKA_VALUE, CKA_SUBJECT, G_MAXULONG); gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (cert), TRUE, attrs, n_attrs); return GKM_OBJECT (cert); }
static void store_object_hash (GkmMate2Storage *self, GkmTransaction *transaction, const gchar *identifier, const guchar *data, gsize n_data) { GkmDataResult res; gchar *digest; g_assert (GKM_IS_MATE2_STORAGE (self)); g_assert (GKM_IS_TRANSACTION (transaction)); g_assert (identifier); g_assert (data); digest = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, n_data); if (digest == NULL) { gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); g_return_if_reached (); } res = gkm_mate2_file_write_value (self->file, identifier, CKA_MATE_INTERNAL_SHA1, digest, strlen (digest)); g_free (digest); if (res != GKM_DATA_SUCCESS) gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); }
static gboolean begin_link_temporary_if_exists (GkmTransaction *self, const gchar *filename, gboolean *exists) { guint i = 0; g_assert (GKM_IS_TRANSACTION (self)); g_assert (!gkm_transaction_get_failed (self)); g_assert (filename); g_assert (exists); for (i = 0; i < MAX_TRIES; ++i) { struct stat sb; unsigned int nlink; int stat_failed = 0; *exists = TRUE; /* Try to link to random temporary file names. We try * to use a hardlink to create a copy but if that * fails (i.e. not supported by the FS), we copy the * entire file. The result should be the same except * that the file times will change if we need to * rollback the transaction. */ if (stat (filename, &sb)) { stat_failed = 1; } else { gchar *result; result = g_strdup_printf ("%s.temp-%d", filename, g_random_int_range (0, G_MAXINT)); nlink = (unsigned int)sb.st_nlink; /* The result code of link(2) is not reliable. * Unless it fails with EEXIST we stat the * file to check for success. Note that there * is a race here: If another process adds a * link to the source file between link and * stat, the check on the increased link count * will fail. Fortunately the case for * hardlinks are not working solves it. */ if (link (filename, result) && errno == EEXIST) { /* This is probably a valid error. * Let us try another temporary file. */ } else if (stat (filename, &sb)) { stat_failed = 1; } else { if ((sb.st_nlink == nlink + 1) || !copy_to_temp_file (result, filename)) { /* Either the link worked or * the copy succeeded. */ gkm_transaction_add (self, NULL, complete_link_temporary, result); return TRUE; } } g_free (result); } if (stat_failed && (errno == ENOENT || errno == ENOTDIR)) { /* The original file does not exist */ *exists = FALSE; return TRUE; } /* If exists, try again, otherwise fail */ if (errno != EEXIST) { g_warning ("couldn't create temporary file for: %s: %s", filename, g_strerror (errno)); gkm_transaction_fail (self, CKR_DEVICE_ERROR); return FALSE; } } g_assert_not_reached (); }
static void relock_object (GkmMate2Storage *self, GkmTransaction *transaction, const gchar *path, const gchar *identifier, GkmSecret *old_login, GkmSecret *new_login) { GError *error = NULL; GkmObject *object; gpointer data; gsize n_data; GType type; g_assert (GKM_IS_MATE2_STORAGE (self)); g_assert (GKM_IS_TRANSACTION (transaction)); g_assert (identifier); g_assert (path); g_assert (!gkm_transaction_get_failed (transaction)); /* Figure out the type of object */ type = type_from_identifier (identifier); if (type == 0) { g_warning ("don't know how to relock file in user store: %s", identifier); gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); return; } /* Create a dummy object for this identifier */ object = g_object_new (type, "unique", identifier, "module", self->module, NULL); if (!GKM_IS_SERIALIZABLE (object)) { g_warning ("cannot relock unserializable object for file in user store: %s", identifier); gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); return; } /* Read in the data for the object */ if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) { g_message ("couldn't load file in user store in order to relock: %s: %s", identifier, egg_error_message (error)); g_clear_error (&error); g_object_unref (object); gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); return; } /* Make sure the data matches the hash */ if (!check_object_hash (self, identifier, data, n_data)) { g_message ("file in data store doesn't match hash: %s", identifier); gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); return; } /* Load it into our temporary object */ if (!gkm_serializable_load (GKM_SERIALIZABLE (object), old_login, data, n_data)) { g_message ("unrecognized or invalid user store file: %s", identifier); gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); g_free (data); g_object_unref (object); return; } g_free (data); data = NULL; /* Read it out of our temporary object */ if (!gkm_serializable_save (GKM_SERIALIZABLE (object), new_login, &data, &n_data)) { g_warning ("unable to serialize data with new login: %s", identifier); gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); g_object_unref (object); g_free (data); return; } g_object_unref (object); /* And write it back out to the file */ gkm_transaction_write_file (transaction, path, data, n_data); /* Create and save the hash here */ if (!gkm_transaction_get_failed (transaction)) store_object_hash (self, transaction, identifier, data, n_data); g_free (data); }
void gkm_mate2_storage_create (GkmMate2Storage *self, GkmTransaction *transaction, GkmObject *object) { gboolean is_private; GkmDataResult res; gchar *identifier; gpointer data; gsize n_data; gchar *path; g_return_if_fail (GKM_IS_MATE2_STORAGE (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (GKM_IS_OBJECT (object)); /* Make sure we haven't already stored it */ identifier = g_hash_table_lookup (self->object_to_identifier, object); g_return_if_fail (identifier == NULL); /* Double check that the object is in fact serializable */ if (!GKM_IS_SERIALIZABLE (object)) { g_warning ("can't store object of type '%s' on token", G_OBJECT_TYPE_NAME (object)); gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); g_return_if_reached (); } /* Figure out whether this is a private object */ if (!gkm_object_get_attribute_boolean (object, NULL, CKA_PRIVATE, &is_private)) is_private = FALSE; /* Can't serialize private if we're not unlocked */ if (is_private && !self->login) { gkm_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN); return; } /* Hook ourselves into the transaction */ if (!begin_modification_state (self, transaction)) return; /* Create an identifier guaranteed unique by this transaction */ identifier = identifier_for_object (object); if (gkm_mate2_file_unique_entry (self->file, &identifier) != GKM_DATA_SUCCESS) { gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); g_return_if_reached (); } /* We don't want to get signals about this item being added */ g_signal_handlers_block_by_func (self->file, data_file_entry_added, self); g_signal_handlers_block_by_func (self->file, data_file_entry_changed, self); res = gkm_mate2_file_create_entry (self->file, identifier, is_private ? GKM_MATE2_FILE_SECTION_PRIVATE : GKM_MATE2_FILE_SECTION_PUBLIC); g_signal_handlers_unblock_by_func (self->file, data_file_entry_added, self); g_signal_handlers_unblock_by_func (self->file, data_file_entry_changed, self); switch(res) { case GKM_DATA_FAILURE: case GKM_DATA_UNRECOGNIZED: g_free (identifier); gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return; case GKM_DATA_LOCKED: g_free (identifier); gkm_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN); return; case GKM_DATA_SUCCESS: break; default: g_assert_not_reached (); } /* Serialize the object in question */ if (!gkm_serializable_save (GKM_SERIALIZABLE (object), is_private ? self->login : NULL, &data, &n_data)) { gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); g_return_if_reached (); } path = g_build_filename (self->directory, identifier, NULL); gkm_transaction_write_file (transaction, path, data, n_data); /* Make sure we write in the object hash */ if (!gkm_transaction_get_failed (transaction)) store_object_hash (self, transaction, identifier, data, n_data); /* Now we decide to own the object */ if (!gkm_transaction_get_failed (transaction)) take_object_ownership (self, identifier, object); g_free (identifier); g_free (path); g_free (data); }
void gkm_mate2_storage_relock (GkmMate2Storage *self, GkmTransaction *transaction, GkmSecret *old_login, GkmSecret *new_login) { GkmMate2File *file; GkmDataResult res; RelockArgs args; g_return_if_fail (GKM_IS_MATE2_STORAGE (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); /* Reload the file with the old password and start transaction */ if (!begin_write_state (self, transaction)) return; file = gkm_mate2_file_new (); /* Read in from the old file */ res = gkm_mate2_file_read_fd (file, self->read_fd, old_login); switch(res) { case GKM_DATA_FAILURE: case GKM_DATA_UNRECOGNIZED: gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return; case GKM_DATA_LOCKED: gkm_transaction_fail (transaction, CKR_PIN_INCORRECT); return; case GKM_DATA_SUCCESS: break; default: g_assert_not_reached (); } /* Write out to new path as new file */ res = gkm_mate2_file_write_fd (file, self->write_fd, new_login); switch(res) { case GKM_DATA_FAILURE: case GKM_DATA_UNRECOGNIZED: gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED); return; case GKM_DATA_LOCKED: gkm_transaction_fail (transaction, CKR_PIN_INCORRECT); return; case GKM_DATA_SUCCESS: break; default: g_assert_not_reached (); } /* Now go through all objects in the file, and load and reencode them */ args.transaction = transaction; args.old_login = old_login; args.new_login = new_login; gkm_mate2_file_foreach_entry (file, relock_each_object, &args); if (!gkm_transaction_get_failed (transaction) && self->login) { if (new_login) g_object_ref (new_login); g_object_unref (self->login); self->login = new_login; g_object_notify (G_OBJECT (self), "login"); } g_object_unref (file); }