После установки Nextcloud (см. Nextcloud: запуск в Docker Compose на Debian с SSL от Let’s Encrypt), на следующий день его клиент запросил повторную аутентификацию.
Но после ввода логина и пароля он сообщает об ошибке:
Reading from keychain failed with error: ‘The name org.freedesktop.secrets was not provided by any .service files’
Гугление одним из первых результатов выдало ссылку на обсуждение этой проблемы тут>>>, где в первом же комментарием говорится:
Could be an upstream issue of the qtkeychain dependency frankosterfeld/qtkeychain#99, but I don’t have any KDE setup to test/debug this. Any help here is welcome.
Хорошо — отправная точка есть, дальше попробуем разобраться сами.
Содержание
Что такое qtkeychain
?
Из описания в README на Github:
QtKeychain is a Qt API to store passwords and other secret data securely.
Т.е. пакет предоставляет API для Qt-based приложений, используя которое они могут получить доступ к логинам/паролям, которые хранятся в системе.
Но при этом сам QtKeychain не хранит эти данные — он только транслирует запросы от приложений к системному хранилищу таких данных, что и указывается дальше в его README:
- Mac OS X: Passwords are stored in the OS X Keychain.
- Linux/Unix: If running, GNOME Keyring is used, otherwise qtkeychain tries to use KWallet (via D-Bus), if available.
Т.е. на Linux qtkeychain
постарается через D-Bus вызвать GNOME Keyring или KWallet.
Используя эту подсказку — D-Bus — открываем исходный код qtkeychain
, и посмотрим — как вообще это происходит.
Качаем исходники, и грепаем исходный код по слову dbus:
[simterm]
[setevoy@setevoy-arch-work /tmp/qtkeychain] [master*] $ grep -r dbus . ./qt5keychain.pri: QT += dbus ./org.kde.KWallet.xml:<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> ./keychain_unix.cpp: /* The secret service dbus api, accessible through libsecret, is supposed
[/simterm]
keychain_unix.cpp
— вполне говорящее само за себя название файла, явно именно то, что нам надо.
Открываем его, и снова ищем слово dbus — находим функцию с говорящим названием detectKeyringBackend()
:
static KeyringBackend detectKeyringBackend() { /* The secret service dbus api, accessible through libsecret, is supposed * to unify password services. * * Unfortunately at the time of Kubuntu 18.04 the secret service backend * in KDE is gnome-keyring-daemon - using it has several complications: * - the default collection isn't opened on session start, so users need * to manually unlock it when the first application uses it * - it's separate from the kwallet5 keyring, so switching to it means the * existing keyring data can't be accessed anymore * * Thus we still prefer kwallet backends on KDE even if libsecret is * available. */ switch (detectDesktopEnvironment()) { case DesktopEnv_Kde4: return Backend_Kwallet4; case DesktopEnv_Plasma5: if (isKwallet5Available()) { return Backend_Kwallet5; } if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } if (GnomeKeyring::isAvailable()) { return Backend_GnomeKeyring; } // During startup the keychain backend might just not have started yet return Backend_Kwallet5; case DesktopEnv_Gnome: case DesktopEnv_Unity: case DesktopEnv_Xfce: case DesktopEnv_Other: default: if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } if (GnomeKeyring::isAvailable()) { return Backend_GnomeKeyring; } if (isKwallet5Available()) { return Backend_Kwallet5; } ... }
Тут ещё интересен комментарий по поводу kwallet
vs gnome-keyring
, но сейчас это не важно.
Далее выполняется инициализация типа бекенда:
... static KeyringBackend getKeyringBackend() { static KeyringBackend backend = detectKeyringBackend(); return backend; } ...
И затем — попытка получить данные, например пароль:
... void ReadPasswordJobPrivate::scheduledStart() { switch ( getKeyringBackend() ) { case Backend_LibSecretKeyring: { if ( !LibSecretKeyring::findPassword(key, q->service(), this) ) { q->emitFinishedWithError( OtherError, tr("Unknown error") ); } } break; case Backend_GnomeKeyring: this->mode = JobPrivate::Text; if ( !GnomeKeyring::find_network_password( key.toUtf8().constData(), q->service().toUtf8().constData(), "plaintext", reinterpret_cast<GnomeKeyring::OperationGetStringCallback>( &JobPrivate::gnomeKeyring_readCb ), this, 0 ) ) q->emitFinishedWithError( OtherError, tr("Unknown error") ); break; case Backend_Kwallet4: kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd", "/modules/kwalletd", this); break; case Backend_Kwallet5: kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd5", "/modules/kwalletd5", this); break; } } ...
В нашем случае — будет вызвана:
... case Backend_LibSecretKeyring: { if ( !LibSecretKeyring::findPassword(key, q->service(), this) ) { ...
Можно почитать код дальше, но суть ясна — выполняется вызов к libsecret
.
Далее можно ещё закопаться в сам libsecret
— но уже не в этот раз, просто поищем где вообще libsecret
выполняет вызов к D-Bus, а потом можно будет повспоминать работу с D-Bus API.
В репозитории libsecret
grep
по dbus возвращает уже море результатов, потому что много файлов для тестирования, плюс пачка Python-скриптов.
Убираем их через grep -v
:
[simterm]
[setevoy@setevoy-arch-work /tmp/libsecret] [master*] $ grep -r "/org/freedesktop/secrets" . | grep -v "test\|.py" ./tool/secret-tool.c:#define SECRET_ALIAS_PREFIX "/org/freedesktop/secrets/aliases/" ./libsecret/secret-util.c: return g_strdup_printf ("/org/freedesktop/secrets/aliases/%s", collection); ./libsecret/secret-private.h:#define SECRET_ALIAS_PREFIX "/org/freedesktop/secrets/aliases/" ./libsecret/secret-private.h:#define SECRET_SERVICE_PATH "/org/freedesktop/secrets"
[/simterm]
./tool/secret-tool.c:#define SECRET_ALIAS_PREFIX "/org/freedesktop/secrets/aliases/"
— «Ага, вот эти ребята!» (с)
Итак, что просходит?
- у меня Arch Linux и Openbox Window Manager, а Desktop Environment нет
- значит — в
qtkeychain
в функцииdetectKeyringBackend()
срабатывает следующее условие:... case DesktopEnv_Other: default: if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } ...
qtkeychain
выполняет вызовlibsecret
, который пытается вызватьorg.freedesktop.secrets
, не находит его, и возвращаетSECRET_ERROR_NO_SUCH_OBJECT
А почему не находит?
Проверяем сервис-файлы D-Bus в каталоге /usr/share/dbus-1/services/
:
[simterm]
$ ls -l /usr/share/dbus-1/services/ total 196 ... -rw-r--r-- 1 root root 107 Sep 10 21:53 org.a11y.Bus.service -rw-r--r-- 1 root root 95 Oct 31 12:09 org.bluez.obex.service -rw-r--r-- 1 root root 116 Oct 9 12:26 org.freedesktop.ColorHelper.service -rw-r--r-- 1 root root 104 Oct 27 16:08 org.freedesktop.Telepathy.AccountManager.service -rw-r--r-- 1 root root 194 Nov 5 12:19 org.freedesktop.Telepathy.Client.KTp.Approver.service -rw-r--r-- 1 root root 91 Nov 5 12:21 org.freedesktop.Telepathy.Client.KTp.CallUi.service -rw-r--r-- 1 root root 106 Nov 5 12:20 org.freedesktop.Telepathy.Client.KTp.ConfAuthObserver.service -rw-r--r-- 1 root root 117 Nov 5 12:26 org.freedesktop.Telepathy.Client.KTp.FileTransferHandler.service -rw-r--r-- 1 root root 217 Nov 5 12:27 org.freedesktop.Telepathy.Client.KTp.KdedIntegrationModule.service -rw-r--r-- 1 root root 88 Nov 12 10:26 org.freedesktop.Telepathy.Client.KTp.Proxy.service -rw-r--r-- 1 root root 101 Nov 5 12:20 org.freedesktop.Telepathy.Client.KTp.SASLHandler.service -rw-r--r-- 1 root root 91 Nov 5 12:29 org.freedesktop.Telepathy.Client.KTp.TextUi.service -rw-r--r-- 1 root root 100 Nov 5 12:20 org.freedesktop.Telepathy.Client.KTp.TLSHandler.service -rw-r--r-- 1 root root 102 Nov 10 2018 org.freedesktop.Telepathy.Client.Logger.service -rw-r--r-- 1 root root 84 Sep 12 2018 org.freedesktop.Telepathy.Client.Vinagre.service -rw-r--r-- 1 root root 95 Nov 10 2018 org.freedesktop.Telepathy.Logger.service -rw-r--r-- 1 root root 188 Oct 27 16:08 org.freedesktop.Telepathy.MissionControl5.service -rw-r--r-- 1 root root 60 Oct 27 2018 org.gnome.GConf.service ...
[/simterm]
И вспоминаем саму ошибку — The name org.freedesktop.secrets was not provided by any .service files’: файла org.freedesktop.secrets.service
нет.
Решение
Проверяем установлен ли сам qtkeychain
:
[simterm]
[setevoy@setevoy-arch-work ~] $ pacman -Qi | grep qtkeychain Optional For : chromium qtkeychain Optional For : git qtkeychain Depends On : qtkeychain qt5-webkit hicolor-icon-theme xdg-utils Required By : appstream-qt... Name : qtkeychain URL : https://github.com/frankosterfeld/qtkeychain
[/simterm]
Да, установлен. Собственно — он указан в зависимостях nextcloud-client
, поэтому pacman
его установил вместе с самим клиентом.
Собственно, что нам надо — так это установить любой подходящий backend storage для хранения секретов, который создаст файл org.freedesktop.secrets
.
Устанавливаем gnome-keyring
:
[simterm]
[setevoy@setevoy-arch-work /tmp/qtkeychain] [master*] $ sudo pacman -S gnome-keyring
[/simterm]
Проверяем файлы D-Bus ещё раз:
[simterm]
[setevoy@setevoy-arch-work /tmp/qtkeychain] [master*] $ ls -l /usr/share/dbus-1/services/ | grep secret -rw-r--r-- 1 root root 122 Oct 29 11:38 org.freedesktop.secrets.service
[/simterm]
Проверяем его содержимое:
[simterm]
[setevoy@setevoy-arch-work /tmp/qtkeychain] [master*] $ cat /usr/share/dbus-1/services/org.freedesktop.secrets.service [D-BUS Service] Name=org.freedesktop.secrets Exec=/usr/bin/gnome-keyring-daemon --start --foreground --components=secrets
[/simterm]
И повторяем логин в Nexcloud-клиенте.
Готово.
P.S. тут ещё отдельный вопрос по работе Chrome/Chromium с хранилищами, но об этом, может быть, в другом посте.
Ссылки по теме
- GNOME/Keyring
- Python bindings to Freedesktop.org Secret Service API
- Specifications/ secret-storage-spec
- Using the DBUS C API
- libsecret
- Understanding D-Bus
- dbus-monitor — debug probe to print message bus messages
- How to modify a dbus service’s “Exec” line without losing the changes in case of upgrade