keepassxc as libsecret provider/daemon makes emacs hang/time out on dbus connection

Created on 26 Oct 2019  路  17Comments  路  Source: keepassxreboot/keepassxc

Since switching to keepassxc as my libsecret daemon (as soon as the commit was pushed a few months ago), secrets in emacs have stopped working.

Expected Behavior

List passwords in the keepass password database (="Keyring") folder (="Keyring") that's marked as exposed to libsecret.

Current Behavior

Emacs times out with

Debugger entered--Lisp error: (dbus-error "call timed out")
  signal(dbus-error ("call timed out"))
  dbus-call-method(:session "org.freedesktop.secrets" "/org/freedesktop/secrets" "org.freedesktop.Secret.Service" "OpenSession" "plain" (:variant ""))
  secrets-open-session()
  secrets-get-items("/org/freedesktop/secrets/collection/keyring")
  secrets-list-items("Keyring Login")
  eval((secrets-list-items "Keyring") nil)
  elisp--eval-last-sexp(nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  call-interactively(eval-last-sexp nil nil)
  command-execute(eval-last-sexp)

Possible Solution

python-keyring stopped working as well, iirc because it assumed different keys in the exposed data?
Because that stopped working, I wrote my own minimal implementation : https://github.com/hrehfeld/python-keyring-minimal/blob/master/keyring

Steps to Reproduce

  1. create a db named Keyring, expose a folder via libsecret
  2. emacs -Q
  3. eval (C-x C-e): (require 'secrets)
  4. eval: (secrets-list-items "Keyring")

Context

GNU Emacs 26.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.10) of 2019-08-29

Debug Info

KeePassXC - Version 2.5.0-snapshot
Build Type: Snapshot
Revision: 6ae27fa

Qt 5.13.1
Debugging mode is disabled.

Operating system: Arch Linux
CPU architecture: x86_64
Kernel: linux 5.3.7-arch1-1-ARCH

Enabled extensions:
- Auto-Type
- Browser Integration
- SSH Agent
- KeeShare (signed and unsigned sharing)
- YubiKey

Cryptographic libraries:
 libgcrypt 1.8.5

bug Secret Service

Most helpful comment

I just fixed an error causing no reply gets sent when opening non-encrypted sessions, could you try my branch at https://github.com/Aetf/keepassxc/tree/fdo-secrets-fixes?

Also, I can explain why other database names appear in your log:

Emacs first tries to resolve the provided DB name Keyring as an alias. If not found, it then gets a list of all current collections (database) and does a match on Label, which is exposed as database name in KeepassXC.

All 17 comments

python-keyring is working fine here and actually that's the tool I used for debugging in development. If you have more info about the error I may be able to fix it.

For emacs, could you help me debug the error since I'm not familiar with emacs at all? It looks like either no one is listening on the DBus, or something bad happened in KeepassXC that it can't even send back an error reply.

The following command checks for the first situation and it should print string "org.freedesktop.secrets" if KeepassXC is listening

dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply  /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep 'org.freedesktop.secrets'

When doing step 4, have the following command running to capture all dbus messages related to libsecret. Note that the password will be captured so use a new db.

dbus-monitor "interface='org.freedesktop.Secret.Service'" "interface='org.freedesktop.Secret.Collection'" "interface='org.freedesktop.Secret.Item'" "interface='org.freedesktop.Secret.Prompt'" > dbus.log
  1. command works fine.
  2. command output:
    $ dbus-monitor "interface='org.freedesktop.Secret.Service'" "interface='org.freedesktop.Secret.Collection'" "interface='org.freedesktop.Secret.Item'" "interface='org.freedesktop.Secret.Prompt'"
    signal time=1572340258.106216 sender=org.freedesktop.DBus -> destination=:1.255 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
       string ":1.255"
    signal time=1572340258.106272 sender=org.freedesktop.DBus -> destination=:1.255 serial=4 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost
       string ":1.255"
    method call time=1572340266.011337 sender=:1.257 -> destination=org.freedesktop.secrets serial=4 path=/org/freedesktop/secrets; interface=org.freedesktop.Secret.Service; member=OpenSession
       string "plain"
       variant       string ""
    method call time=1572340291.020592 sender=:1.257 -> destination=org.freedesktop.secrets serial=11 path=/org/freedesktop/secrets; interface=org.freedesktop.Secret.Service; member=ReadAlias
       string "Keyring"
    method call time=1572340291.024260 sender=:1.257 -> destination=org.freedesktop.secrets serial=14 path=/org/freedesktop/secrets; interface=org.freedesktop.Secret.Service; member=Unlock
       array [
          object path "/org/freedesktop/secrets/collection/keyring_2Donline"
       ]
    method call time=1572340291.027924 sender=:1.257 -> destination=org.freedesktop.secrets serial=17 path=/org/freedesktop/secrets/prompt/<someid>; interface=org.freedesktop.Secret.Prompt; member=Prompt
       string "<string>"
    signal time=1572340291.028278 sender=:1.20 -> destination=(null destination) serial=1101 path=/org/freedesktop/secrets/prompt/<someid>; interface=org.freedesktop.Secret.Prompt; member=Completed
       boolean false
       variant       array [
          ]
    method call time=1572340291.030431 sender=:1.257 -> destination=org.freedesktop.secrets serial=19 path=/org/freedesktop/secrets; interface=org.freedesktop.Secret.Service; member=OpenSession
       string "plain"
       variant       string ""

Interestingly, this references some other keyring "Keyring Online", which is either from some old keyring database configuration, or the title of one of my autoopen entries. Changing the title doesn't change the dbus output.

Btw, I have two keyrings/libsecret exposed folders from two keepass databases open at the same time.

Also, testing is quite easy. Just install emacs, and then:

$ emacs -Q --eval "(progn (require 'secrets) (secrets-list-items \"Keyring\"))"

Replace Keyring with the name of your keyring.

How do you use python-keyring?

/usr/bin/keyring get 'Keyring' '<my entry title>'

or

/usr/bin/keyring get '<my entry title>' '<my username>'

Just doesn't work.

python-keyring maybe defaults to a different backend on your system. I'm using the following script:

Setting:

import keyring
keyring.set_keyring(keyring.backends.SecretService.Keyring())
keyring.set_password('Test service_name', 'user', 'password')

Getting:

import keyring
keyring.set_keyring(keyring.backends.SecretService.Keyring())
p = keyring.get_password('Test service_name', 'user')
print(p)

Also note that the first argument isn't an entry title shown in KeepassXC, but an additional attribute service, which seems to be used by many gtk applications to distinguish passwords from different applications.

emacs indeed behaves weirdly. Although I'm not getting any timeout error message from emacs, it feels like so. I'm working on this.

If you want to see emacs backtraces, use:

$  emacs -Q --eval "(progn (toggle-debug-on-error) (require 'secrets) (secrets-list-items \"Keyring\"))"  

(foo a b) is a function call like in foo(a, b);

(progn BODY...) just evaluates some expressions and returns the result of the last one, i.e. converts a list of expressions to a single expression -- not possible in C, but quite similar to something like [&] () { BODY... }()

-Q just disables loading of any user configuration.

I just fixed an error causing no reply gets sent when opening non-encrypted sessions, could you try my branch at https://github.com/Aetf/keepassxc/tree/fdo-secrets-fixes?

Also, I can explain why other database names appear in your log:

Emacs first tries to resolve the provided DB name Keyring as an alias. If not found, it then gets a list of all current collections (database) and does a match on Label, which is exposed as database name in KeepassXC.

Seems to work! Emacs can list the contents of the database just fine now, and it doesn't hang.

Great! What about python-keyring? Does it work for you now?

python-keyring works only if I manually add the custom properties service and username. The usual ui field for username is exposed as UserName on libsecret, and service is not present :frowning_face:

In the Freedesktop Secret Storage standard, an secret entry contains a textual Label (maps to title) and a binary secret data (maps to password if plain/text, protected attachment otherwise). All other things are custom attributes which are completely up to the application to interpret. For example, some applications may don't have the notion of an user name and just wants to save a secret key.

So in general, while everything is in the same database, there's little we can expect for interoperability among entries created by different applications.

Yep, but wouldn't it a good idea to emulate what gnome-keyring, etc. is doing instead of reinventing key names?

(feel free to close this once #3761 is merged.)

Yep, but wouldn't it a good idea to emulate what gnome-keyring, etc. is doing instead of reinventing key names?

I wanted the same thing but gnome-keyring isn't doing anything special in this regard. It's just a daemon saving whatever attributes other applications give to it. I checked a few existing applications:

  • Seahorse set the description as the label, and sets an additional xdg:schema => org.gnome.keyring.Note when creating passwords through UI.
  • Secret-tool lets you specify the label, and any additional attributes.
  • Chrome saves its secrets with application => chrome and xdg:schema => chrome_libsecret_os_crypt_password_v2
  • python-keyring uses application => Python keyring library, service, and username

So there seems not to be a consistent usage of attributes in existing applications :(

I'm open to suggestions to improve the compatibility though.

Fixed by #3761

Awesome, it seems to work now. Thanks a bunch! :+1:

Was this page helpful?
0 / 5 - 0 ratings