static gboolean object_property_set (GkdSecretObjects *objects, GckObject *object, const gchar *prop_name, GVariant *value, GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; GError *error = NULL; gulong attr_type; /* What type of property is it? */ if (!gkd_secret_property_get_type (prop_name, &attr_type)) { g_set_error (error_out, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_PROPERTY, "Object does not have the '%s' property", prop_name); return FALSE; } /* Retrieve the actual attribute value */ if (!gkd_secret_property_parse_variant (value, prop_name, &builder)) { gck_builder_clear (&builder); g_set_error (error_out, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "The property type or value was invalid: %s", prop_name); return FALSE; } 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)) g_set_error (error_out, GKD_SECRET_ERROR, GKD_SECRET_ERROR_IS_LOCKED, "Cannot set property on a locked object"); else g_set_error (error_out, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't set '%s' property: %s", prop_name, egg_error_message (error)); g_clear_error (&error); return FALSE; } return TRUE; }
static gboolean collection_method_create_item (GkdExportedCollection *skeleton, GDBusMethodInvocation *invocation, GVariant *properties, GVariant *secret_variant, gboolean replace, GkdSecretObjects *self) { GckBuilder builder = GCK_BUILDER_INIT; GckSession *pkcs11_session = NULL; GkdSecretSecret *secret = NULL; GckAttributes *attrs = NULL; const GckAttribute *fields; GckObject *item = NULL; const gchar *base; GError *error = NULL; gchar *path = NULL; gchar *identifier; gboolean created = FALSE; GckObject *object; object = secret_objects_lookup_gck_object_for_invocation (self, invocation); if (!object) { return TRUE; } if (!gkd_secret_property_parse_all (properties, SECRET_ITEM_INTERFACE, &builder)) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid properties argument"); goto cleanup; } base = g_dbus_method_invocation_get_object_path (invocation); secret = gkd_secret_secret_parse (self->service, g_dbus_method_invocation_get_sender (invocation), secret_variant, &error); if (secret == NULL) { g_dbus_method_invocation_take_error (invocation, error); error = NULL; goto cleanup; } if (!gkd_secret_util_parse_path (base, &identifier, NULL)) g_return_val_if_reached (FALSE); g_return_val_if_fail (identifier, FALSE); pkcs11_session = gck_object_get_session (object); g_return_val_if_fail (pkcs11_session, FALSE); attrs = gck_attributes_ref_sink (gck_builder_end (&builder)); if (replace) { fields = gck_attributes_find (attrs, CKA_G_FIELDS); if (fields) item = collection_find_matching_item (self, pkcs11_session, identifier, fields); } /* Replace the item */ if (item) { if (!gck_object_set (item, attrs, NULL, &error)) goto cleanup; /* Create a new item */ } else { 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; } /* Set the secret */ if (!gkd_secret_session_set_item_secret (secret->session, item, secret, &error)) { if (created) /* If we created, then try to destroy on failure */ gck_object_destroy (item, NULL, NULL); goto cleanup; } path = object_path_for_item (base, item); gkd_secret_objects_emit_item_created (self, object, path); gkd_exported_collection_complete_create_item (skeleton, invocation, path, "/"); cleanup: if (error) { if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR, GKD_SECRET_ERROR_IS_LOCKED, "Cannot create an item in a locked collection"); else g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't create item: %s", egg_error_message (error)); g_clear_error (&error); } gkd_secret_secret_free (secret); gck_attributes_unref (attrs); if (item) g_object_unref (item); if (pkcs11_session) g_object_unref (pkcs11_session); g_free (path); g_object_unref (object); return TRUE; }
static gboolean change_or_create_login (GList *modules, const gchar *original, const gchar *master) { 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); /* Find the login object */ session = lookup_login_session (modules); login = lookup_login_keyring (session); /* Create the new credential we'll be changing to */ mcred = create_credential (session, NULL, master, &error); if (mcred == NULL) { g_warning ("couldn't create new login credential: %s", egg_error_message (error)); g_clear_error (&error); /* Create original credentials */ } else if (login) { ocred = create_credential (session, login, original, &error); if (ocred == NULL) { if (g_error_matches (error, GCK_ERROR, CKR_PIN_INCORRECT)) { g_message ("couldn't change login master password, " "original password was wrong: %s", egg_error_message (error)); } else { g_warning ("couldn't create original login credential: %s", egg_error_message (error)); } g_clear_error (&error); } } /* No keyring? try to create */ if (!login && mcred) { login = create_login_keyring (session, mcred, &error); if (login == NULL) { g_warning ("couldn't create login keyring: %s", egg_error_message (error)); g_clear_error (&error); } else { success = TRUE; } /* 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)) { 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) { gck_object_destroy (ocred, NULL, NULL); g_object_unref (ocred); } if (mcred) g_object_unref (mcred); if (login) g_object_unref (login); if (session) g_object_unref (session); return success; }