diff options
Diffstat (limited to 'packages/gnome-keyring')
4 files changed, 422 insertions, 0 deletions
diff --git a/packages/gnome-keyring/0001-daemon-Add-Cinnamon-to-autostart-files.patch b/packages/gnome-keyring/0001-daemon-Add-Cinnamon-to-autostart-files.patch new file mode 100644 index 0000000..980d537 --- /dev/null +++ b/packages/gnome-keyring/0001-daemon-Add-Cinnamon-to-autostart-files.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jan Alexander Steffens (heftig)" <heftig@archlinux.org> +Date: Sat, 21 May 2022 18:47:23 +0000 +Subject: [PATCH] daemon: Add Cinnamon to autostart files + +Cinnamon also wants to use gnome-keyring-daemon. +--- + daemon/gnome-keyring-pkcs11.desktop.in.in | 2 +- + daemon/gnome-keyring-secrets.desktop.in.in | 2 +- + daemon/gnome-keyring-ssh.desktop.in.in | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/daemon/gnome-keyring-pkcs11.desktop.in.in b/daemon/gnome-keyring-pkcs11.desktop.in.in +index 3e36603fac70..bb729caddfd1 100644 +--- a/daemon/gnome-keyring-pkcs11.desktop.in.in ++++ b/daemon/gnome-keyring-pkcs11.desktop.in.in +@@ -3,7 +3,7 @@ Type=Application + Name=Certificate and Key Storage + Comment=GNOME Keyring: PKCS#11 Component + Exec=@bindir@/gnome-keyring-daemon --start --components=pkcs11 +-OnlyShowIn=GNOME;Unity;MATE; ++OnlyShowIn=GNOME;Unity;MATE;Cinnamon; + NoDisplay=true + X-GNOME-Autostart-Phase=PreDisplayServer + X-GNOME-AutoRestart=false +diff --git a/daemon/gnome-keyring-secrets.desktop.in.in b/daemon/gnome-keyring-secrets.desktop.in.in +index 799caeea4306..6c836a2a7ec9 100644 +--- a/daemon/gnome-keyring-secrets.desktop.in.in ++++ b/daemon/gnome-keyring-secrets.desktop.in.in +@@ -3,7 +3,7 @@ Type=Application + Name=Secret Storage Service + Comment=GNOME Keyring: Secret Service + Exec=@bindir@/gnome-keyring-daemon --start --components=secrets +-OnlyShowIn=GNOME;Unity;MATE; ++OnlyShowIn=GNOME;Unity;MATE;Cinnamon; + NoDisplay=true + X-GNOME-Autostart-Phase=PreDisplayServer + X-GNOME-AutoRestart=false +diff --git a/daemon/gnome-keyring-ssh.desktop.in.in b/daemon/gnome-keyring-ssh.desktop.in.in +index fd7657a4d0cc..8f9847033507 100644 +--- a/daemon/gnome-keyring-ssh.desktop.in.in ++++ b/daemon/gnome-keyring-ssh.desktop.in.in +@@ -3,7 +3,7 @@ Type=Application + Name=SSH Key Agent + Comment=GNOME Keyring: SSH Agent + Exec=@bindir@/gnome-keyring-daemon --start --components=ssh +-OnlyShowIn=GNOME;Unity;MATE; ++OnlyShowIn=GNOME;Unity;MATE;Cinnamon; + X-GNOME-Autostart-Phase=PreDisplayServer + X-GNOME-AutoRestart=false + X-GNOME-Autostart-Notify=true diff --git a/packages/gnome-keyring/0002-secret-service-missing-client.patch b/packages/gnome-keyring/0002-secret-service-missing-client.patch new file mode 100644 index 0000000..9ef298b --- /dev/null +++ b/packages/gnome-keyring/0002-secret-service-missing-client.patch @@ -0,0 +1,275 @@ +diff -ruN a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c +--- a/daemon/dbus/gkd-secret-objects.c 2026-09-17 15:41:00.000000000 -0500 ++++ b/daemon/dbus/gkd-secret-objects.c 2026-10-17 06:47:19.275009074 -0500 +@@ -430,7 +430,11 @@ + + /* 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 (session == NULL) { ++ g_free (c_ident); ++ g_free (i_ident); ++ goto out; ++ } + + if (i_ident) { + gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); +@@ -1055,17 +1059,23 @@ + if (!gkd_secret_util_parse_path (path, &identifier, NULL)) + return NULL; + +- if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX)) +- real_identifier = gkd_secret_service_get_alias (self->service, identifier); +- else +- real_identifier = identifier; +- +- /* The session we're using to access the object */ ++ /* The session we're using to access the object. Resolve it before the ++ * alias: fetching a caller's session may register the caller, which ++ * refreshes the default alias and frees the string the alias table ++ * held, so an alias looked up earlier would dangle here. */ + if (caller == NULL) + session = gkd_secret_service_internal_pkcs11_session (self->service); + else + session = gkd_secret_service_get_pkcs11_session (self->service, caller); +- g_return_val_if_fail (session, NULL); ++ if (session == NULL) { ++ g_free (identifier); ++ return NULL; ++ } ++ ++ if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX)) ++ real_identifier = gkd_secret_service_get_alias (self->service, identifier); ++ else ++ real_identifier = identifier; + + gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION); + gck_builder_add_string (&builder, CKA_ID, real_identifier); +diff -ruN a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c +--- a/daemon/dbus/gkd-secret-service.c 2026-09-17 15:41:00.000000000 -0500 ++++ b/daemon/dbus/gkd-secret-service.c 2026-10-17 06:47:19.274715149 -0500 +@@ -137,6 +137,9 @@ + GHashTable *clients; + GkdSecretObjects *objects; + GHashTable *aliases; ++ /* The message filter reads aliases on the GDBus worker thread while ++ * the main thread updates them; every access goes through this lock. */ ++ GMutex aliases_lock; + GckSession *internal_session; + gchar *default_path; + }; +@@ -190,6 +193,18 @@ + return g_build_filename (alias_directory, "default", NULL); + } + ++/* An owned copy of an alias, safe to call from any thread. */ ++static gchar * ++lookup_alias_copy (GkdSecretService *self, const gchar *alias) ++{ ++ gchar *copy; ++ ++ g_mutex_lock (&self->aliases_lock); ++ copy = g_strdup (g_hash_table_lookup (self->aliases, alias)); ++ g_mutex_unlock (&self->aliases_lock); ++ return copy; ++} ++ + static void + update_default (GkdSecretService *self) + { +@@ -206,21 +221,31 @@ + /* Default to to 'login' if no default keyring */ + if (contents == NULL) + contents = g_strdup ("login"); +- g_hash_table_replace (self->aliases, g_strdup ("default"), contents); ++ ++ /* Replace only on a real change: callers on the main thread hold the ++ * previous value borrowed, and the common case (another client ++ * registering) must not free it out from under them. */ ++ g_mutex_lock (&self->aliases_lock); ++ if (g_strcmp0 (g_hash_table_lookup (self->aliases, "default"), contents) == 0) ++ g_free (contents); ++ else ++ g_hash_table_replace (self->aliases, g_strdup ("default"), contents); ++ g_mutex_unlock (&self->aliases_lock); + } + + static void + store_default (GkdSecretService *self) + { + GError *error = NULL; +- const gchar *identifier; ++ gchar *identifier; + +- identifier = g_hash_table_lookup (self->aliases, "default"); ++ identifier = lookup_alias_copy (self, "default"); + if (!identifier) + return; + + if (!g_file_set_contents (self->default_path, identifier, -1, &error)) + g_message ("couldn't store default keyring: %s", egg_error_message (error)); ++ g_free (identifier); + } + + static gboolean +@@ -331,7 +356,7 @@ + GDBusMessage *message) + { + const char *path = g_dbus_message_get_path (message); +- const char *replace; ++ char *replace; + char *collection = NULL, *item = NULL; + char *collection_path, *item_path; + GDBusMessage *rewritten; +@@ -346,7 +371,9 @@ + if (!gkd_secret_util_parse_path (path, &collection, &item)) + return message; + +- replace = gkd_secret_service_get_alias (self, collection); ++ /* This runs on the GDBus worker thread: take a copy under the lock ++ * rather than borrowing from a table the main thread may be updating. */ ++ replace = lookup_alias_copy (self, collection); + if (!replace) { + g_free (item); + g_free (collection); +@@ -356,6 +383,9 @@ + rewritten = g_dbus_message_copy (message, &error); + if (error != NULL) { + g_error_free (error); ++ g_free (replace); ++ g_free (item); ++ g_free (collection); + return message; + } + +@@ -372,6 +402,7 @@ + } + + g_free (collection_path); ++ g_free (replace); + g_free (item); + g_free (collection); + g_object_unref (message); +@@ -424,18 +455,30 @@ + GError *error = NULL; + const gchar *caller; + GVariant *input_payload; ++ gboolean opened; + + caller = g_dbus_method_invocation_get_sender (invocation); + + /* Now we can create a session with this information */ + session = gkd_secret_session_new (self, caller); + input_payload = g_variant_get_variant (input); +- gkd_secret_session_handle_open (session, algorithm, input_payload, +- &output, &result, +- &error); ++ opened = gkd_secret_session_handle_open (session, algorithm, input_payload, ++ &output, &result, ++ &error); + g_variant_unref (input_payload); + +- if (error != NULL) { ++ /* Branch on the return value, not on the error alone: a negotiate helper ++ * that bails out through g_return_val_if_fail() reports failure without ++ * ever setting one, and completing the call with a NULL body makes ++ * g_variant_new() abort the whole daemon. */ ++ if (!opened || output == NULL || result == NULL) { ++ if (error == NULL) ++ g_set_error_literal (&error, G_DBUS_ERROR, ++ G_DBUS_ERROR_FAILED, ++ "Couldn't open a session for this caller."); ++ if (output != NULL) ++ g_variant_unref (g_variant_ref_sink (output)); ++ g_free (result); + g_dbus_method_invocation_take_error (invocation, error); + } else { + gkd_secret_service_publish_dispatch (self, caller, +@@ -986,6 +1029,7 @@ + static void + gkd_secret_service_init_aliases (GkdSecretService *self) + { ++ g_mutex_init (&self->aliases_lock); + self->aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + g_hash_table_insert (self->aliases, g_strdup ("session"), g_strdup ("session")); + /* TODO: We should be using CKA_G_LOGIN_COLLECTION */ +@@ -1151,6 +1195,7 @@ + + g_hash_table_destroy (self->aliases); + self->aliases = NULL; ++ g_mutex_clear (&self->aliases_lock); + + g_free (self->default_path); + self->default_path = NULL; +@@ -1283,7 +1328,18 @@ + g_return_val_if_fail (caller, NULL); + + client = g_hash_table_lookup (self->clients, caller); +- g_return_val_if_fail (client, NULL); ++ if (client == NULL) { ++ /* The record is normally created by a high priority idle queued from ++ * the message filter, but that idle is not ordered against the method ++ * call that queued it: a peer which connects and calls straight away ++ * can reach us first. Create it here instead of failing the call -- ++ * it is a hash table insert, not I/O. Callers must not hold borrowed ++ * alias strings across this call: registering a client refreshes the ++ * default alias. */ ++ gkd_secret_service_ensure_client (self, caller); ++ client = g_hash_table_lookup (self->clients, caller); ++ g_return_val_if_fail (client, NULL); ++ } + + /* Open a new session if necessary */ + if (!client->pkcs11_session) { +@@ -1399,7 +1455,9 @@ + g_return_if_fail (GKD_SECRET_IS_SERVICE (self)); + g_return_if_fail (alias); + ++ g_mutex_lock (&self->aliases_lock); + g_hash_table_replace (self->aliases, g_strdup (alias), g_strdup (identifier)); ++ g_mutex_unlock (&self->aliases_lock); + + if (g_str_equal (alias, "default")) + store_default (self); +@@ -1418,6 +1476,10 @@ + + /* Take ownership of the session */ + client = g_hash_table_lookup (self->clients, caller); ++ if (client == NULL) { ++ gkd_secret_service_ensure_client (self, caller); ++ client = g_hash_table_lookup (self->clients, caller); ++ } + g_return_if_fail (client); + path = gkd_secret_dispatch_get_object_path (object); + g_return_if_fail (!g_hash_table_lookup (client->dispatch, path)); +diff -ruN a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c +--- a/daemon/dbus/gkd-secret-session.c 2026-09-17 15:41:00.000000000 -0500 ++++ b/daemon/dbus/gkd-secret-session.c 2026-10-17 06:47:19.270295281 -0500 +@@ -183,7 +183,12 @@ + gboolean ret; + + session = gkd_secret_service_get_pkcs11_session (self->service, self->caller); +- g_return_val_if_fail (session, FALSE); ++ if (session == NULL) { ++ g_set_error_literal (error_out, G_DBUS_ERROR, ++ G_DBUS_ERROR_FAILED, ++ "Couldn't open a session for this caller."); ++ return FALSE; ++ } + + if (!aes_create_dh_keys (session, "ietf-ike-grp-modp-1024", &pub, &priv)) { + g_set_error_literal (error_out, G_DBUS_ERROR, +@@ -250,7 +255,12 @@ + GckSession *session; + + session = gkd_secret_service_get_pkcs11_session (self->service, self->caller); +- g_return_val_if_fail (session, FALSE); ++ if (session == NULL) { ++ g_set_error_literal (error_out, G_DBUS_ERROR, ++ G_DBUS_ERROR_FAILED, ++ "Couldn't open a session for this caller."); ++ return FALSE; ++ } + + gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); + gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_G_NULL); diff --git a/packages/gnome-keyring/PKGBUILD b/packages/gnome-keyring/PKGBUILD new file mode 100644 index 0000000..a8e32a2 --- /dev/null +++ b/packages/gnome-keyring/PKGBUILD @@ -0,0 +1,82 @@ +# Local rebuild of Arch's gnome-keyring 1:51.1-1 with the Secret Service +# missing-client fix applied. I build from GNOME's release tarball (checksum +# published by GNOME) instead of the signed git tag so the build does not need +# the maintainer's key in the keyring of whichever machine builds it. pkgrel +# 1.1 sorts above the stock 1:51.1-1 and below any future 1:51.1-2, so the +# next upstream or Arch fix replaces it on a normal upgrade. +# Maintainer: Jan Alexander Steffens (heftig) <heftig@archlinux.org> +# Contributor: Jan De Groot <jgc@archlinux.org> + +pkgname=gnome-keyring +pkgver=51.1 +pkgrel=1.1 +epoch=1 +pkgdesc="Stores passwords and encryption keys (Secret Service missing-client fix)" +url="https://gitlab.gnome.org/GNOME/gnome-keyring" +arch=(x86_64) +license=( + GPL-2.0-or-later + LGPL-2.1-or-later +) +depends=( + dconf + gcr + gcr-4 + glib2 + glibc + libcap-ng + libgcc + libgcrypt + pam + systemd-libs +) +makedepends=( + docbook-xsl + git + glib2-devel + meson + p11-kit + python +) +provides=(org.freedesktop.secrets) +groups=(gnome) +install=gnome-keyring.install +source=( + "https://download.gnome.org/sources/gnome-keyring/${pkgver%%.*}/gnome-keyring-$pkgver.tar.xz" + 0001-daemon-Add-Cinnamon-to-autostart-files.patch + 0002-secret-service-missing-client.patch +) +sha256sums=('dfe7adc5876ef0670e7eba2907799bdbb8875ce58bb4208e1a52169bd16a47ca' + '138ad9a41dcbf9faede3a8b7fcb61dd5894ca8b66599802e58f8bb81e9607eb2' + '2463bf109af415412bf99e9aca98c51f215cfdcc9de728bbf7155db861bf79d7') + +prepare() { + cd gnome-keyring-$pkgver + + # Autolaunch in Cinnamon (Arch's own patch, unchanged) + patch -Np1 -i ../0001-daemon-Add-Cinnamon-to-autostart-files.patch + # Register Secret Service clients at the point of use, return real errors + # instead of completing OpenSession with a NULL body, and resolve the + # collection alias only after the caller's session exists. + patch -Np1 -i ../0002-secret-service-missing-client.patch +} + +build() { + local meson_options=( + -D selinux=disabled + ) + + arch-meson gnome-keyring-$pkgver build "${meson_options[@]}" + meson compile -C build +} + +check() { + # Secure memory tests fail + dbus-run-session meson test -C build --print-errorlogs || : +} + +package() { + meson install -C build --no-rebuild --destdir "$pkgdir" +} + +# vim:set sw=2 sts=-1 et: diff --git a/packages/gnome-keyring/gnome-keyring.install b/packages/gnome-keyring/gnome-keyring.install new file mode 100644 index 0000000..6143dd1 --- /dev/null +++ b/packages/gnome-keyring/gnome-keyring.install @@ -0,0 +1,14 @@ +post_install() { + # Enable socket by default + systemctl --global enable gnome-keyring-daemon.socket +} + +post_upgrade() { + if (( $(vercmp $2 1:42.0-1) < 0)); then + systemctl --global enable gnome-keyring-daemon.socket + fi +} + +pre_remove() { + systemctl --global disable gnome-keyring-daemon.socket +} |
