From 4ab5b89de84c8ae6254e11330b783a42e2c40121 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Mon, 27 Dec 2021 19:53:00 +0100 Subject: [PATCH] The temprary "session" collection might not exist in Secret Service * doc/misc/auth.texi (Secret Service API): * test/lisp/net/secrets-tests.el (secrets--test-delete-all-session-items) (secrets-test02-collections, secrets-test03-items) (secrets-test04-search): The temporary "session" collection might not exist. * lisp/net/secrets.el (secrets-struct-secret-content-type): Remove compatibility hack. (secrets-create-item): Adapt accordingly. --- doc/misc/auth.texi | 6 +++- lisp/net/secrets.el | 51 +++++----------------------------- test/lisp/net/secrets-tests.el | 11 ++++++-- 3 files changed, 20 insertions(+), 48 deletions(-) diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi index 034004d1df4..6602f9dc2e4 100644 --- a/doc/misc/auth.texi +++ b/doc/misc/auth.texi @@ -370,6 +370,10 @@ items should not live longer than Emacs. The session collection can be specified either by the string @code{"session"}, or by @code{nil}, whenever a collection parameter is needed in the following functions. +However, not all Secret Service provider create this temporary +@code{"session"} collection, like KeePassXC. You shall check first +that this collection exists, before you use it. + @defun secrets-list-items collection Returns all the item labels of @var{collection} as a list. @end defun @@ -382,7 +386,7 @@ pairs set for the created item. The keys are keyword symbols, starting with a colon. Example: @example -;;; The session is "session", the label is "my item" +;;; The collection is "session", the label is "my item" ;;; and the secret (password) is "geheim". (secrets-create-item "session" "my item" "geheim" :method "sudo" :user "joe" :host "remote-host") diff --git a/lisp/net/secrets.el b/lisp/net/secrets.el index 4217c219ad9..25802f2c463 100644 --- a/lisp/net/secrets.el +++ b/lisp/net/secrets.el @@ -263,6 +263,7 @@ It returns t if not." ;; ;; +;; This is not guaranteed to exist. For example, KeePassXC does not offer this. (defconst secrets-session-collection-path "/org/freedesktop/secrets/collection/session" "The D-Bus temporary session collection object path.") @@ -311,43 +312,8 @@ It returns t if not." (defconst secrets-interface-item-type-generic "org.freedesktop.Secret.Generic" "The default item type we are using.") -;; We cannot use introspection, because some servers, like -;; mate-keyring-daemon, don't provide relevant data. Once the dust -;; has settled, we shall assume the new interface, and get rid of the test. -(defconst secrets-struct-secret-content-type - (ignore-errors - (let ((content-type "text/plain") - (path (cadr - (dbus-call-method - :session secrets-service secrets-path - secrets-interface-service - "OpenSession" "plain" '(:variant "")))) - result) - ;; Create a dummy item. - (setq result - (dbus-call-method - :session secrets-service secrets-session-collection-path - secrets-interface-collection "CreateItem" - ;; Properties. - `(:array - (:dict-entry ,(concat secrets-interface-item ".Label") - (:variant " "))) - ;; Secret. - `(:struct :object-path ,path - (:array :signature "y") - ,(dbus-string-to-byte-array " ") - :string ,content-type) - ;; Don't replace. - nil)) - ;; Remove it. - (dbus-call-method - :session secrets-service (car result) - secrets-interface-item "Delete") - ;; Result. - `(,content-type))) - "The content_type of a secret struct. -It must be wrapped as list, because we add it via `append'. This -is an interface introduced in 2011.") +(defconst secrets-struct-secret-content-type "text/plain" + "The content_type of a secret struct.") (defconst secrets-interface-session "org.freedesktop.Secret.Session" "A session tracks state between the service and a client application.") @@ -696,13 +662,10 @@ The object path of the created item is returned." `((:dict-entry ,(concat secrets-interface-item ".Attributes") (:variant ,(append '(:array) props)))))) ;; Secret. - (append - `(:struct :object-path ,secrets-session-path - (:array :signature "y") ;; No parameters. - ,(dbus-string-to-byte-array password)) - ;; We add the content_type. In backward compatibility - ;; mode, nil is appended, which means nothing. - secrets-struct-secret-content-type) + `(:struct :object-path ,secrets-session-path + (:array :signature "y") ;; No parameters. + ,(dbus-string-to-byte-array password) + ,secrets-struct-secret-content-type) ;; Do not replace. Replace does not seem to work. nil)) (secrets-prompt (cadr result)) diff --git a/test/lisp/net/secrets-tests.el b/test/lisp/net/secrets-tests.el index b392c4d1847..03d3e26faa6 100644 --- a/test/lisp/net/secrets-tests.el +++ b/test/lisp/net/secrets-tests.el @@ -57,8 +57,11 @@ (defun secrets--test-delete-all-session-items () "Delete all items of collection \"session\" bound to this Emacs." - (dolist (item (secrets-list-items "session")) - (secrets-delete-item "session" item))) + ;; If the "session" collection does not exist, a `dbus-error' is + ;; fired, which we ignore. + (dbus-ignore-errors + (dolist (item (secrets-list-items "session")) + (secrets-delete-item "session" item)))) (ert-deftest secrets-test01-sessions () "Test opening / closing a secrets session." @@ -93,7 +96,7 @@ (unwind-protect (progn (should (secrets-open-session)) - (should (member "session" (secrets-list-collections))) + (skip-unless (member "session" (secrets-list-collections))) ;; Create a random collection. This asks for a password ;; outside our control, so we make it in the interactive case @@ -153,6 +156,7 @@ (unwind-protect (let (item-path) (should (secrets-open-session)) + (skip-unless (member "session" (secrets-list-collections))) ;; Cleanup. There could be items in the "session" collection. (secrets--test-delete-all-session-items) @@ -214,6 +218,7 @@ (unwind-protect (progn (should (secrets-open-session)) + (skip-unless (member "session" (secrets-list-collections))) ;; Cleanup. There could be items in the "session" collection. (secrets--test-delete-all-session-items) -- 2.39.2