static GckObject * secret_objects_lookup_gck_object_for_path (GkdSecretObjects *self, const gchar *sender, const gchar *path, GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; GList *objects; GckSession *session; gchar *c_ident; gchar *i_ident; GckObject *object = NULL; GError *error = NULL; g_return_val_if_fail (path, FALSE); if (!gkd_secret_util_parse_path (path, &c_ident, &i_ident) || !c_ident) goto out; /* The session we're using to access the object */ session = gkd_secret_service_get_pkcs11_session (self->service, sender); g_return_val_if_fail (session, FALSE); if (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 { 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, gck_builder_end (&builder), NULL, &error); g_free (c_ident); g_free (i_ident); if (error != NULL) { g_warning ("couldn't lookup object: %s: %s", path, egg_error_message (error)); g_clear_error (&error); } if (!objects) goto out; object = g_object_ref (objects->data); gck_list_unref_free (objects); out: if (!object) g_set_error (error_out, GKD_SECRET_ERROR, GKD_SECRET_ERROR_NO_SUCH_OBJECT, "The '%s' object does not exist", path); return object; }
static void prepare_generate (SeahorsePkcs11Generate *self) { CK_BYTE rsa_public_exponent[] = { 0x01, 0x00, 0x01 }; /* 65537 in bytes */ GckBuilder publi = GCK_BUILDER_INIT; GckBuilder priva = GCK_BUILDER_INIT; const gchar *label; g_assert (self->cancellable == NULL); g_assert (self->mechanism != NULL); gck_builder_add_ulong (&publi, CKA_CLASS, CKO_PUBLIC_KEY); gck_builder_add_ulong (&priva, CKA_CLASS, CKO_PRIVATE_KEY); gck_builder_add_boolean (&publi, CKA_TOKEN, TRUE); gck_builder_add_boolean (&priva, CKA_TOKEN, TRUE); gck_builder_add_boolean (&priva, CKA_PRIVATE, TRUE); gck_builder_add_boolean (&priva, CKA_SENSITIVE, TRUE); label = gtk_entry_get_text (self->label_entry); gck_builder_add_string (&publi, CKA_LABEL, label); gck_builder_add_string (&priva, CKA_LABEL, label); if (self->mechanism->type == CKM_RSA_PKCS_KEY_PAIR_GEN) { gck_builder_add_boolean (&publi, CKA_ENCRYPT, TRUE); gck_builder_add_boolean (&publi, CKA_VERIFY, TRUE); gck_builder_add_boolean (&publi, CKA_WRAP, TRUE); gck_builder_add_boolean (&priva, CKA_DECRYPT, TRUE); gck_builder_add_boolean (&priva, CKA_SIGN, TRUE); gck_builder_add_boolean (&priva, CKA_UNWRAP, TRUE); gck_builder_add_data (&publi, CKA_PUBLIC_EXPONENT, rsa_public_exponent, sizeof (rsa_public_exponent)); gck_builder_add_ulong (&publi, CKA_MODULUS_BITS, gtk_spin_button_get_value_as_int (self->bits_entry)); } else { g_warning ("currently no support for this mechanism"); } self->prv_attrs = gck_builder_steal (&priva); self->pub_attrs = gck_builder_steal (&publi); gck_builder_clear (&publi); gck_builder_clear (&priva); }
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; g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL); g_return_val_if_fail (caller, NULL); g_return_val_if_fail (path, NULL); if (!gkd_secret_util_parse_path (path, &collection, &identifier)) return NULL; /* The session we're using to access the object */ session = gkd_secret_service_get_pkcs11_session (self->service, caller); g_return_val_if_fail (session, NULL); 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, gck_builder_end (&builder), NULL, &error); g_free (identifier); g_free (collection); if (error != NULL) { g_warning ("couldn't lookup item: %s: %s", path, egg_error_message (error)); g_clear_error (&error); } if (objects) object = g_object_ref (objects->data); gck_list_unref_free (objects); return object; }
gboolean gkd_secret_lock_all (GckSession *session, DBusError *derr) { GckBuilder builder = GCK_BUILDER_INIT; GError *error = NULL; GList *objects, *l; /* Lock all the main collections */ gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL); gck_builder_add_boolean (&builder, CKA_GNOME_TRANSIENT, TRUE); objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't search for credential objects: %s", egg_error_message (error)); dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock service"); g_clear_error (&error); return FALSE; } for (l = objects; l; l = g_list_next (l)) { if (!gck_object_destroy (l->data, NULL, &error)) { g_warning ("couldn't destroy credential object: %s", egg_error_message (error)); g_clear_error (&error); } } /* Now delete all session objects */ gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); gck_builder_add_string (&builder, CKA_G_COLLECTION, "session"); objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't search for session items: %s", egg_error_message (error)); dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock service"); g_clear_error (&error); return FALSE; } for (l = objects; l; l = g_list_next (l)) { if (!gck_object_destroy (l->data, NULL, &error)) { g_warning ("couldn't destroy session item: %s", egg_error_message (error)); g_clear_error (&error); } } gck_list_unref_free (objects); return TRUE; }
static gboolean iter_get_string (GVariant *variant, gulong attr_type, GckBuilder *builder) { const char *value; g_assert (variant != NULL); g_assert (builder != NULL); value = g_variant_get_string (variant, NULL); if (value == NULL) value = ""; gck_builder_add_string (builder, attr_type, value); return TRUE; }
static gboolean iter_get_string (DBusMessageIter *iter, gulong attr_type, GckBuilder *builder) { const char *value; 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_builder_add_string (builder, attr_type, value); return TRUE; }
void gkd_secret_objects_foreach_item (GkdSecretObjects *self, const gchar *caller, const gchar *base, GkdSecretObjectsForeach callback, gpointer user_data) { GckBuilder builder = GCK_BUILDER_INIT; GckSession *session; GError *error = NULL; gchar *identifier; GList *items; g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); g_return_if_fail (base != NULL); g_return_if_fail (callback != NULL); /* The session we're using to access the object */ if (caller == NULL) { session = gkd_secret_service_internal_pkcs11_session (self->service); } else { session = gkd_secret_service_get_pkcs11_session (self->service, caller); } if (!gkd_secret_util_parse_path (base, &identifier, NULL)) g_return_if_reached (); 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, gck_builder_end (&builder), NULL, &error); if (error == NULL) { objects_foreach_item (self, items, base, callback, user_data); } else { g_warning ("couldn't lookup items in '%s' collection: %s", identifier, egg_error_message (error)); g_clear_error (&error); } gck_list_unref_free (items); g_free (identifier); }
static GckObject* collection_find_matching_item (GkdSecretObjects *self, GckSession *session, const gchar *identifier, const GckAttribute *fields) { GckBuilder builder = GCK_BUILDER_INIT; GckObject *result = NULL; GError *error = NULL; GckObject *search; gpointer data; gsize n_data; /* Find items matching the collection and fields */ gck_builder_add_attribute (&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, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't search for matching item: %s", egg_error_message (error)); g_clear_error (&error); return NULL; } /* Get the matched item handles, and delete the search object */ data = gck_object_get_data (search, CKA_G_MATCHED, NULL, &n_data, NULL); gck_object_destroy (search, NULL, NULL); g_object_unref (search); if (n_data >= sizeof (CK_OBJECT_HANDLE)) result = gck_object_from_handle (session, *((CK_OBJECT_HANDLE_PTR)data)); g_free (data); return result; }
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; }
gboolean gkd_secret_objects_handle_search_items (GkdSecretObjects *self, GDBusMethodInvocation *invocation, GVariant *attributes, const gchar *base, gboolean separate_locked) { GckBuilder builder = GCK_BUILDER_INIT; GckObject *search; GckSession *session; GError *error = NULL; gchar *identifier; gpointer data; gsize n_data; GList *locked, *unlocked; GList *items; GVariantBuilder result; if (!gkd_secret_property_parse_fields (attributes, &builder)) { gck_builder_clear (&builder); g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid data in attributes argument"); return TRUE; } if (base != NULL) { if (!gkd_secret_util_parse_path (base, &identifier, NULL)) g_return_val_if_reached (FALSE); gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier); g_free (identifier); } 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, g_dbus_method_invocation_get_sender (invocation)); g_return_val_if_fail (session, FALSE); /* Create the search object */ search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't search for items: %s", egg_error_message (error)); g_clear_error (&error); return TRUE; } /* Get the matched item handles, and delete the search object */ data = gck_object_get_data (search, CKA_G_MATCHED, NULL, &n_data, &error); gck_object_destroy (search, NULL, NULL); g_object_unref (search); if (error != NULL) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't retrieve matched items: %s", egg_error_message (error)); g_clear_error (&error); return TRUE; } /* Build a list of object handles */ items = gck_objects_from_handle_array (session, data, n_data / sizeof (CK_OBJECT_HANDLE)); g_free (data); /* Filter out the locked items */ if (separate_locked) { GVariant *unlocked_variant, *locked_variant; item_cleanup_search_results (session, items, &locked, &unlocked); g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); objects_foreach_item (self, unlocked, NULL, on_object_path_append_to_builder, &result); unlocked_variant = g_variant_builder_end (&result); g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); objects_foreach_item (self, locked, NULL, on_object_path_append_to_builder, &result); locked_variant = g_variant_builder_end (&result); g_list_free (locked); g_list_free (unlocked); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@ao@ao)", unlocked_variant, locked_variant)); } else { g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); objects_foreach_item (self, items, NULL, on_object_path_append_to_builder, &result); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@ao)", g_variant_builder_end (&result))); } gck_list_unref_free (items); return TRUE; }