Вопрос чайника по значкам
А, чёрт, Gnome3. Я просто щелкнул в эту тему из новостей, пардон.
Дык а если просто руками отредактировать *.desktop файлы соответствующие?
Да пребудет с нами Сила.
CPU Intel Core i9 10900-KF/RAM DDR4 128 Gb/NVidia GForce GTX 1080 Ti Turbo 11Gb/SSD M2 512 Gb/HDD Seagate SATA3 2 Tb/HDD Toshiba 3Tb/HDD Toshiba 6Tb
http://rusrailsim.org
Участник с: 09 января 2013
vufer
Куда копать? 🙂
Копай в сторону journalctl и лога иксов. Все, что откопаешь — в студию)
И скажи, какие значки используешь: стандартные или какой-то пакет с темой?
Участник с: 19 октября 2011
А, чёрт, Gnome3. Я просто щелкнул в эту тему из новостей, пардон.
Дык а если просто руками отредактировать *.desktop файлы соответствующие?
Именно часть системных значков. Те, что в панельке сверху, и в верхней части фалового менеджера.
Участник с: 19 октября 2011
vufer
Куда копать? 🙂
Копай в сторону journalctl и лога иксов. Все, что откопаешь — в студию)
И скажи, какие значки используешь: стандартные или какой-то пакет с темой?
-- Reboot -- мар 29 06:34:24 vuferbase pulseaudio[507]: [pulseaudio] sink.c: Default and alternate sample rates are the same. мар 29 06:34:24 vuferbase pulseaudio[507]: [pulseaudio] source.c: Default and alternate sample rates are the same. мар 29 06:34:24 vuferbase pulseaudio[507]: [pulseaudio] bluetooth-util.c: org.bluez.Manager.GetProperties() failed: org.freedeskt мар 29 06:34:25 vuferbase gnome-session[451]: WARNING: Failed to start app: Unable to start application: Не удалось выполнить про мар 29 06:34:32 vuferbase goa[606]: goa-daemon version 3.6.2 starting [main.c:112, main()] мар 29 06:35:15 vuferbase gnome-keyring-daemon[449]: keyring alias directory: /home/vufer/.local/share/keyrings lines 543-590/590 (END)
unixforum.org
У /etc/shadow права те, которые должны быть. Файла /lib/security/pam_gnome_keyring.so нет совсем, хотя pam_gnome_keyring.so числится в:
/etc/pam.d/gdm
/etc/pam.d/gnome-screensaver
До этого случайно сделал chown -R andrey /, восстанавливал владельца у файлов в /var.
Пакет libpam-gnome-keyring не установлен.
Спасибо сказали:
watashiwa_daredeska Бывший модератор Сообщения: 4038 Статус: Искусственный интеллект (pre-alpha) ОС: Debian GNU/Linux
Re: Решено: Не могу разблокировать экран
18.07.2010 15:39
Пакет libpam-gnome-keyring не установлен.
А установить?
Спасибо сказали:
AndreyMust19 Сообщения: 19 ОС: Windows XP
Re: Решено: Не могу разблокировать экран
Нет, тоже самое. Вот что добавилось в лог:
Jul 18 17:34:24 pool-125-224 gdm[11817]: pam_unix(gdm:session): session opened for user andrey by (uid=0) Jul 18 17:34:25 pool-125-224 dbus-daemon: Rejected send message, 3 matched rules; type="method_call", sender=":1.138" (uid=1000 pid=25431 comm="nautilus --sm-config-prefix /nautilus-tm2oe6/ --sm") interface="org.freedesktop.SystemToolsBackends" member="get" error name="(unset)" requested_reply=0 destination="org.freedesktop.SystemToolsBackends" (uid=0 pid=2606 comm="/usr/bin/system-tools-backends ")) Jul 18 17:34:25 pool-125-224 dbus-daemon: Rejected send message, 3 matched rules; type="method_call", sender=":1.138" (uid=1000 pid=25431 comm="nautilus --sm-config-prefix /nautilus-tm2oe6/ --sm") interface="org.freedesktop.SystemToolsBackends" member="get" error name="(unset)" requested_reply=0 destination="org.freedesktop.SystemToolsBackends" (uid=0 pid=2606 comm="/usr/bin/system-tools-backends ")) Jul 18 17:36:27 pool-125-224 sudo: andrey : TTY=pts/0; PWD=/home/andrey; USER=root; COMMAND=/usr/bin/aptitude Jul 18 17:37:54 pool-125-224 unix_chkpwd[25561]: check pass; user unknown Jul 18 17:37:54 pool-125-224 unix_chkpwd[25561]: password check failed for user (andrey) Jul 18 17:37:54 pool-125-224 gnome-screensaver-dialog: pam_unix(gnome-screensaver:auth): authentication failure; logname= uid=1000 euid=1000 tty=:0.0 ruser= rhost= user=andrey Jul 18 17:37:54 pool-125-224 gnome-screensaver-dialog: gkr-pam: created 'login' keyring Jul 18 17:37:59 pool-125-224 gnome-keyring-daemon[25411]: failed to shutdown HAL context: (null) Jul 18 17:37:59 pool-125-224 gdm[11817]: pam_unix(gdm:session): session closed for user andrey Jul 18 17:38:12 pool-125-224 gdm[25572]: pam_unix(gdm:session): session opened for user andrey by (uid=0) Jul 18 17:38:14 pool-125-224 dbus-daemon: Rejected send message, 3 matched rules; type="method_call", sender=":1.150" (uid=1000 pid=25669 comm="nautilus --sm-config-prefix /nautilus-tm2oe6/ --sm") interface="org.freedesktop.SystemToolsBackends" member="get" error name="(unset)" requested_reply=0 destination="org.freedesktop.SystemToolsBackends" (uid=0 pid=2606 comm="/usr/bin/system-tools-backends ")) Jul 18 17:38:14 pool-125-224 dbus-daemon: Rejected send message, 3 matched rules; type="method_call", sender=":1.150" (uid=1000 pid=25669 comm="nautilus --sm-config-prefix /nautilus-tm2oe6/ --sm") interface="org.freedesktop.SystemToolsBackends" member="get" error name="(unset)" requested_reply=0 destination="org.freedesktop.SystemToolsBackends" (uid=0 pid=2606 comm="/usr/bin/system-tools-backends ")) Jul 18 17:38:37 pool-125-224 sudo: andrey : TTY=pts/0; PWD=/home/andrey; USER=root; COMMAND=/usr/bin/less /var/log/auth.log
Возможно, проблемы с доступом к файлам в /var (папка dbus).
На виртуальной машине посмотрел владельцев файлов в /var. С владельцами все нормально. В остальных корневых папках (кроме /home) — владелец root. Может быть, в /etc какие-то настройки изменились? Или какой пакет повредился? Как обновить состояние установленных пакетов? Или еще какие логи посмотреть?
Chromium: Linux, keyrings && Secret Service, шифрование и хранение паролей
Одним из поводов настолько углубиться в keyrings (см. What is: Linux keyring, gnome-keyring, Secret Service, и D-Bus) был факт того, что Chromium, внезапно, при отсутствии keyring в Linux будет хранить пароли в “открытом виде”.
Собственно, давайте попробуем найти – как и где Chromium хранит пароли, и, самое важное – шифрует ли он их?
Chromium и keyring
On Linux, Chrome previously stored credentials directly in the user‘s Gnome Keyring or KWallet, but for technical reasons, it has switched to storing the credentials in “Login Data” in the Chrome user’s profile directory, but encrypted on disk with a key that is then stored in the user’s Gnome Keyring or KWallet. If there is no available Keyring or KWallet, the data is not encrypted when stored.
- пароли Chromium хранит в SQLite базе “Login Data” ( ‘/home/setevoy/.config/chromium/Default/Login Data’ )
- если gnome-keyring или KWallet установлены – то Chrome будет шифровать данные в базе с помощью пароля, который Chromium хранит в этом хранилище
- если их нет, и Secret Service не активен – то пароли будут храниться в открытом виде, plain text
Chromium без keyring
Попробуем получить пароль из базы с Chromium без keyring.
Что бы указать ему – какой бекенд использовать, можно использовать опцию google-chrome —password-store=basic – для хранения plain text.
Другие параметры – gnome или kwallet, см. man chromium :
--password-store=Set the password store to use. The default is to automatically detect based on the desktop environment. basic selects the built in, unencrypted password store. gnome selects Gnome keyring. kwallet selects (KDE) KWallet. (Note that KWallet may not work reliably outside KDE.)
Кроме того – проверим D-Bus сервисы, что бы убедиться, что никакой Secret Service сейчас не активен:
$ qdbus --session org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixProcessID org.freedesktop.secrets Error: org.freedesktop.DBus.Error.NameHasNoOwner Could not get PID of name 'org.freedesktop.secrets': no such name
Создаём каталог для данных Chromium:
$ mkdir /tmp/data-chrome-test-1
Запускаем браузер с указанием home на эту директорию и –password-store=basic, что бы сохрнаять пароли в открытом виде:
$ chromium --user-data-dir=/tmp/data-chrome-test-1 --password-store=basic
Логинимся куда-то, сохраняем пароль, закрываем браузер, проверяем базу:
$ sqlite3 /tmp/data-chrome-test-1/Default/Login\ Data 'select username_value, password_value from logins;' testuser|v10�#�c�yF�b�f���
Отлично – в поле password_value SQLite базы какой-то пароль есть.
Кстати, просмотреть все поля и их типы в таблице logins можно с помощью .schema :
$ sqlite3 ~/.config/chromium/Default/Login\ Data '.schema logins' CREATE TABLE IF NOT EXISTS "logins" (origin_url VARCHAR NOT NULL, action_url VARCHAR, \
username_element VARCHAR, username_value VARCHAR, password_element VARCHAR, password_value BLOB \
. )); CREATE INDEX logins_signon ON logins (signon_realm);
Chromium с keyring
Теперь попробуем получить пароль из SQLite базы с Chromium, который использует keyring. Для этого – включаем поддержку Secret Service в KeePass, который нам заменит “стандартный” gnome-keyring , и создаём второй каталог для данных Chromium:
$ mkdir /tmp/data-chrome-test-2
Запускаем браузер, но теперь указываем —password-store=gnome , и меняем user-data-dir , что бы использовать чистую SQLite базу с паролями:
$ chromium --user-data-dir=/tmp/data-chrome-test-2 --password-store=gnome
Ещё раз логинимся, сохраняем пароль, проверяем базу:
$ sqlite3 /tmp/data-chrome-test-2/Default/Login\ Data 'select username_value, password_value from logins;' testuser|v11���H!@���2�jA�
Во-первых – префикс тут v11, а не v10, во-вторых – строка явно длиннее.
Chromium passwords decrypt
Теперь попробуем разобраться:
- во-первых – пароль из “незашифрованого” хранилища отдаётся явно не plain text – почему?
- во-вторых – как получить пароль из “зашифрованого” хранилища?
Для проверки – поковыряем исходники.
Chrome v10 vs v11
Для начала – что за v10 и v11?
. // Password version. V10 means that the hardcoded password will be used. // V11 means that a password is/will be stored using an OS-level library (e.g // Libsecret). V11 will not be used if such a library is not available. // Used for array indexing. enum Version < V10 = 0, V11 = 1, >; .
Т.е. v10 – это префикс для незашифрованных паролей, а v11 – для зашифрованных.
Хотя при этом в обоих случаях выборка из SQLite возвращает нам набор символов, а не пароль в открытом виде…
Сейчас узнаем почему.
Начнём с конца файла, с функции DecryptString() :
-
DecryptString() : в version сохраняет версию (v10 или v11):
. if (base::StartsWith(ciphertext, kObfuscationPrefix[Version::V10], base::CompareCase::SENSITIVE)) < version = Version::V10; .
. std::unique_ptr encryption_key( GetEncryptionKey(version)); if (!encryption_key) < VLOG(1) .
. std::string* password = g_get_password[version](); if (!password) return nullptr; .
. std::string* (*g_get_password[])() = < &GetPasswordV10, &GetPasswordV11, >; .
. if (!g_cache.Get().password_v10_cache.get()) < g_cache.Get().password_v10_cache.reset(new std::string("peanuts")); >.
Так что всё оказалось намного проще:
- если keyring есть – то Chromium сгенерирует мастер-пароль, и сохранит в базе этого keyring-сервиса
- если keyring нет, и Secret Service отключен – то Chromium использует hardcoded мастер-пароль “peanuts“
И уже используя этот пароль – будет составлен key для шифрования паролей в SQLite базе данных.
Python скрипт для получения паролей
Теперь проверим всё это на практике, что бы “потрогать руками” и увидеть как оно в самом деле работает.
Среди прочего видим, что для шифрования используется AES 128 bit CBC:
. // Key size required for 128 bit AES. const size_t kDerivedKeySizeInBits = 128; .
Далее в функции GetEncryptionKey() смотрим, как создаётся ключ для шифрования:
. // Create an encryption key from our password and salt. std::unique_ptr encryption_key( crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2( crypto::SymmetricKey::AES, *password, salt, kEncryptionIterations, kDerivedKeySizeInBits)); DCHECK(encryption_key); return encryption_key; .
Следовательно, что бы расшифровать запись из базы данных – нам нужны такие данные, всё указано сразу в файле в переменных:
- мастер-пароль password – именно он возвращается в GetPasswordV10() или GetPasswordV11()
- соль – const char kSalt[] = "saltysalt"
- итерации – const size_t kEncryptionIterations = 1
- длина ключа – const size_t kDerivedKeySizeInBits = 128
Для декрипта паролей – нагуглился простой скрипт тут>>>, немного его переделаем под себя, получается такой:
#! /usr/bin/env python3 import sqlite3 from Crypto.Cipher import AES from Crypto.Protocol.KDF import PBKDF2 def get_encrypted_data(db_path): # choose a database conn = sqlite3.connect(db_path) cursor = conn.cursor() # connect and egt exncypted data data = cursor.execute('SELECT action_url, username_value, password_value FROM logins') return data # to get rid of padding def clean(x): return x[:-x[-1]].decode('utf8') def get_decrypted_data(encrypted_password): print("Decrypting the string: <>".format(encrypted_password)) # trim off the 'v10' that Chrome/ium prepends encrypted_password = encrypted_password[3:] # making the key salt = b'saltysalt' iv = b' ' * 16 length = 16 iterations = 1 pb_pass = "peanuts".encode('utf8') key = PBKDF2(pb_pass, salt, length, iterations) cipher = AES.new(key, AES.MODE_CBC, IV=iv) decrypted = cipher.decrypt(encrypted_password) print(clean(decrypted)) if __name__ == "__main__": db_path = '/tmp/data-chrome-test-1/Default/Login Data' for url, user, encrypted_password in get_encrypted_data(db_path): get_decrypted_data(encrypted_password)
$ ./get_chrome_pass.py Decrypting the string: b'v10\xd4#\xd6c\xabyF\xc6b\xdef\x06\xce\x14\xe3\xc5' test911911
Отлично – есть наш пароль.
В этот раз мы получили его из “незашифрованного” хранилища.
Chromium && Secret Service
Теперь – включаем поддержку Secret Storage в KeePass (см What is: Linux keyring, gnome-keyring, Secret Service, и D-Bus), что бы эмулировать установленный gnome-keepass , перезапускаем KeePass.
Добавляем папку для новой базы данных Chromium:
$ mkdir /tmp/data-chrome-test-2/
Запускаем Chromium с каталогом данных data-chrome-test-2 из неё и указываем --password-store=gnome :
$ chromium --user-data-dir=/tmp/data-chrome-test-2/ --password-store=gnome
Логинимся, сохраняем пароль ещё раз – и Chromium в KeePass создал нам две записи:
- Chrome Safe Storage Control
- Chromium Safe Storage
Смотрим их атрибуты – там всё указано:
Можно посмотреть через D-Bus и Secret Service, что бы проверить коллекцию:
$ secret-tool search Title 'Chromium Safe Storage' [/org/freedesktop/secrets/collection/Main/f0fdc4706ef44958b716e28c13d66bed] label = Chromium Safe Storage secret = P5pUwxbWaIBBVU0+LATOcw== .
schema = chrome_libsecret_os_crypt_password_v2 . attribute.Title = Chromium Safe Storage .
attribute.application = chromium . attribute.Path = /Chromium Safe Storage
Теперь попробуем использовать этот пароль (значение атрибута secret выше) из Chromium Safe Storage в качестве значения переменной pb_pass в нашем скрипте.
Выходим из Chromium, что бы разлочить базу, иначе будет ошибка вида:
$ ./get_chrome_pass.py Traceback (most recent call last): File "./get_chrome_pass.py", line 50, in for url, user, encrypted_password in get_encrypted_data(db_path): File "./get_chrome_pass.py", line 15, in get_encrypted_data data = cursor.execute('SELECT action_url, username_value, password_value FROM logins') sqlite3.OperationalError: database is locked
В скрипте меняем базу (путь к ней):
. if __name__ == "__main__": # db_path = '/tmp/data-chrome-test-1/Default/Login Data' db_path = '/tmp/data-chrome-test-2/Default/Login Data' for url, user, encrypted_password in get_encrypted_data(db_path): get_decrypted_data(encrypted_password)
Вместо “peanuts” подставляем в pb_pass значение из Chromium Safe Storage:
. # pb_pass = "peanuts".encode('utf8') pb_pass = "P5pUwxbWaIBBVU0+LATOcw= ez-toc-section" > Вывод
Собственно, самое важное – пароли в SQLite шифруются всегда. Просто для систем, в которых нет бекенда типа gnome-keyring с поддержкой Secret Service – то пароль для шифрования всегда будет один и тот же для всех пользователей Chromium, что, разумеется, нельзя рассматривать, как защиту.
What is: Linux keyring, gnome-keyring, Secret Service, и D-Bus
Очень длиннопост получился.
Я долго думал – собирать ли всё в одном посте, или всё-таки разбить на несколько, ведь с одной стороны keyrings – это одна тема, D-Bus – другая, а примеры работы с SecretServices – вообще третья.
Тем не менее – решил всё-таки оставить в одном, так как со всем этим разбирался по ходу дела, и все эти темы связаны друг с другом в обсуждаемом контесте хранения конфиденциальных данных.
Вообще история появления этого поста интересна сама по себе:
- началось всё с qtkeychain и Nextcloud (см. Linux: Nextcloud клиент, qtkeychain и ошибка «The name org.freedesktop.secrets was not provided by any .service files»)
- по ходу дела увидел, что пароли от RSA ключей для SSA можно хранить в keychain (см. SSH: RSA-ключи и ssh-agent — управление SSH-ключами и их паролями и Linux: KeePass, SSH и хранение паролей RSA-ключей)
Но когда попробовал использовать gnome-keyring на Arch Linux – стокнулся с проблемами при регистрации самого сервиса и доступа к нему через ssh-agent , что заставило углубиться в вопрос.
Собственно, в этом посте рассмотрим:
- что такое keyring вообще
- какая разница между Linux keyring и GNOME keyring, и связаны ли они друг с другом
- какие реализации keyring существуют
- что такое org.freedesktop SecretService, и какое он имеет отношение к GNOME keyring
- что такое D-Bus, и куда его можно потыкать веточкой, что бы увидеть работу keyring
- и несколько примеров работы с Linux Keyring, GNOME Keyring, KWallet и KeePass в роли keyring backends
Пост ни разу не является предметным “HowTo” – он чисто обзорный, что бы получить представление об всех упомянутых компонентах.
Конкретную работу с KeePass и, возможно, GNOME Keyring для хранения данных рассмотрим в другой раз.
Весь пост писался путём долгого-долгого гугления, поэтому и в самом тексте, и в конце, будет достаточно много ссылок на документацию и материалы, которые использовались в процессе подготовки материала.
Ну и помните, что от ошибок и неточностей никто не застрахован. Welcome to the comments, if any.
Выглядел процесс примерно так:
Что такое keyring
Для начала – что такое “keyring” вообще?
In cryptography, a keyring stores known encryption keys (and, in some cases, passwords).
Much like a keyring in real life allows you to keep certain sets of keys together, a keyring in Passwords and Keys allows you to keep passwords and keys in separate groups.
a keyring service that enables internal server components and plugins to securely store sensitive information for later retrieval
The Linux key-management facility is primarily a way for various kernel components to retain or cache security data, authentication keys, encryption keys, and other data in the kernel.
Итак, понятие keyring – это механизм или конкретный сервис, предназначенный для хранения какой-либо конфиденциальной информации.
Окей, тут разобрались.
Linux keyring vs gnome-keyring
- KERNEL KEY RETENTION SERVICE
- http://www.ict.griffith.edu.au/anthony/info/crypto/passwd_caching.txt
- http://www.ict.griffith.edu.au/anthony/info/crypto/
- https://wiki.gnome.org/Projects/GnomeKeyring
- https://wiki.archlinux.org/index.php/GNOME/Keyring
Теперь перейдём к рассмотрению разницы между Linux kernel keyring и GNOME Keyring: сначала сбило с толку, ибо предполагал, что GNOME Keyring каким-то образом использует механизм keyrings ядра, но нет – это просто разные вещи.
keyrings – in-kernel key management and retention facility
Т.е, Linux keyrings – это механизм ядра для хранения конфиденциальной информации.
GNOME Keyring is a collection of components in GNOME that store secrets, passwords, keys, certificates and make them available to applications.
А GNOME Keyring – коллекция компонентов ( gnome-keyring-daemon , библиотеки, пакет seahorse , etc) для хранения конфиденциальной информации. См. архитектуру GNOME Keyring.
Отличная подборка материалов тут – Tower Floor — Encryption, в частности см. документ Caching Passwords.
Резюме
Подведём итоги различий Linux keyrings и GNOME Keyring:
- ключевая разница:
- Linux keyring – механизм ядра для “кеширования паролей” – хранит их в памяти во время активной сессии системы/пользователя
- gnome-keyring – постоянное хранилище паролей, с хранением информации на диске
- Linux keyring – хранит в памяти, т.к. секреты доступны только во время сесии – их не надо хранить постоянно
- gnome-keyring – создаёт файл на диске, как правило в каталоге ~/.local/share/keyrings/
- Linux keyring – через системные вызовы из user space в kernel space
- gnome-keyring – через DBus
- Linux keyring – keyctl , systemd-ask-password , etc
- gnome-keyring – secret-tool , любая библиотека ( python-keyring ), seahorse , etc
Реализации keyrings
Кроме того, python-keyring упоминает:
- gsheet-keyring – a backend that stores secrets in a Google Sheet. For use with ipython-secrets.
- bitwarden-keyring – a backend that stores secrets in the BitWarden password manager.
И это далеко не все.
Клиенты для работы с такими хранилищами, опять-таки – список далеко не полный:
- libsecret
- python-keyring
- Java-клиент secret-service
- qtkeychain
- secret-tool
- библиотека SecretStorage
Перехват паролей из gnome-keyting
- клиент и сервис общаются по D-Bus
- клиент запрашивает данные у SecretService ( gnome-keyring в данном случае)
- сервис через D-Bus шлёт данные клиенту
- другой процесс слушает dbus-сообщения, читает пароль
Что такое Secret Service
Ещё одно понятие, на которое пришлось немного потратить время.
Что за “Secret Service”? Какое он имеет отношение к GNOME Keyring и к KWallet?
Что он делает в Linux, и как его пощупать?
The Secret Service API allows client applications to store secrets securely in a service running in the user’s login session.
Ага, т.е. Secret Service – это не какой-то конкретный сервис, а просто спецификация, такой себе RFC, составленный проектами GNOME и KDE для определения того, как они должны реализовать API для клиентов, которые хотят использовать GNOME Keyring и к KWallet для хранения секретов.
При этом поддержка Secret Service API имеется не только у GNOME Keyring и к KWallet, но и у, например, KeePass, и других приложений.
IMHO, немного сбивает с толку само название – Secret Service, т.е. “секретный сервис”. Назвали бы его Secrets Service, т.е. “сервис секретов” – было бы куда понятнее.
Понятия Secret Service
- secret: сам пароль, или любая другая конфиденциальная информация
- item: каждый секрет плюс набор его атрибутов представляют собой item
- collection: а набор таких items преставляет собой коллекцию (аналог понятий keyring и wallet)
- коллекции и items представлены объектами D-Bus, каждый со своим уникальным path
- default collection: клиентские приложения без специальных условий должны добавлять записи в коллекцию default, которая должна быть доступна по пути /org/freedesktop/secrets/aliases/default
D-Bus
Теперь пришло время попытаться вспомнить что же такое D-Bus, и как к нему вообще обращаться.
Итак, D-Bus – один из механизмов Linux kernel IPC – Inter Process Communication, позволяющий различным процессам внутри системы передавать другу другу данные или сигналы.
- документация – https://techbase.kde.org/Development/Tutorials/D-Bus/Introduction
- ещё одна: https://dbus.freedesktop.org/doc/dbus-tutorial.html
- про транспорты в D-Bus: https://dbus.freedesktop.org/doc/dbus-specification.html#transports
- D-Bus, quick recap
- Universal standard mapping between D-Bus and URI namespaces
- D-Bus Addresses — D-Bus connection endpoints
Кратко об основных понятиях и терминах D-Bus:
- D-Bus в общем: это шина для IPC, если в предыдущих примерах по SSH-агентам использовался UNIX-сокет, тот тут используется механизм bus, см. https://www.kernel.org/doc/html/latest/driver-api/driver-model/bus.html. В свою очередь D-Bus шины могут быть:
- шина сессии (session bus)
- системная шина (system bus)
- приватные шины (private bus)
- отправка сообщения как правило приводит к вызову метода и каким-либо действиям приложения, которое этот метод предоставялет
- сообщение может быть отправлено приложением самому себе
- т.к. различные приложения могут располагаться на одной шине (или “слушать одну шину“), и при этом одно приложение может предоставлять несколько объектов, которые могут получать сообщения, то требуется механизм адресации, такой адрес в D-Bus состоит из интерфейса + сервис + имя объекта
- пример namespace – org.freedesktop.dbus
- пример адреса – unix:tmpdir=/tmp/my-app-name
- большинство интерфейсов будут указывать непосредственно на соответствующие конструкции языка, на котором написано приложение, например на интерфейс Java или виртуальный класс С++
- пример интерфейса – org.freedesktop.Introspectable
- под service тут подразумевается имя шины (в оригинале – “well-known” Bus names), но стоит учитывать что под “именем шины” подразумевается именно имя подключения к шине, но НЕ имя шины
- если у приложения более одного подключения к шине, или если приложение запущено в нескольких экземплярах – у имени сервиса может бтыь добавлен, например, PID, что бы сделать его уникальным
- пример service – org.kde.screensaver
- см. https://dbus.freedesktop.org/doc/dbus-tutorial.html#objects
- методы – это messages, которые отправляются объекту, что бы вызвать операцию в приложении, которое этот объект создало
- методы могут передавать данные в input, например аргументы, и возвращать output с какими-либо значениями, которое вернёт приложение
- всегда имеют адрес отправителя и конкретный адрес получателя
- аналогичны методам, но не привязаны к конкретному destination, и могут быть приняты любым приложением на этой же шине
- генерируются приложением, которое екпортит интерфейс
D-Bus tools
- qdbus – просмотр объектов и отправка сообщений через D-Bus
- dbus-monitor – отслеживание активности на шине
- dbus-send – отправка сообщений через D-Bus
- qdbusviewer – просмотр объектов и сообщений, входит в набор qt5-tools
- d-feet – D-Bus debugger
- bustle – D-Bus message analyser and profiler
Пример d-feet , устанавливаем:
$ sudo pacman -S d-feet
Keyrings examples
И примеры работы с разными бекендами из Python или CLI утилит.
Linux keyring
Как уже говорилось выше, Linux keyring – такой себе кеширующий механизм ядра.
Для работы с ним используются keyctl из набора keyutils , и systemd-ask-password .
- Kernel key retention service doc
- keyctl doc
Each process subscribes to three keyrings: a thread-specific keyring, a process-specific keyring, and a session-specific keyring.
Посмотрим, какие keyring доступны в моей текущей сессии:
$ keyctl show @s Session Keyring 185597501 --alswrv 1000 1000 keyring: _ses 182944921 --alswrv 1000 65534 \_ keyring: _uid.1000
$ keyctl show @u Keyring 182944921 --alswrv 1000 65534 keyring: _uid.1000
Кроме того, в файле /proc/key-users можно получить информацию обо всех хранилищах и их статистике по каждому пользователю:
$ cat /proc/key-users 0: 43 42/42 34/1000000 768/25000000 971: 1 1/1 1/200 9/20000 1000: 4 4/4 4/200 46/20000
Доступные нашему процессу ( bash , который вызывает cat ) ключи:
$ cat /proc/keys 008f6a74 I--Q--- 1 perm 1f3f0000 1000 65534 keyring _uid_ses.1000: 1 0ae78499 I--Q--- 4 perm 1f3f0000 1000 65534 keyring _uid.1000: empty 0b0ffe3d I--Q--- 225 perm 3f030000 1000 1000 keyring _ses: 1 2a28e4fe I--Q--- 33 perm 3f030000 1000 1000 keyring _ses: 1
Кейринги пользователя в текущей сессии:
$ keyctl describe @us -5: -lswrvalswrv------------ 1000 65534 keyring: _uid_ses.1000
Ключи в текущем кейринге:
$ keyctl list @us 1 key in keyring: 182944921: --alswrv 1000 65534 keyring: _uid.1000
$ keyctl add user example-key example-data @u 546850615
$ keyctl request user example-key 546850615
Получаем его ID, читаем содержимое:
$ keyctl print 546850615 example-data
keyctl() syscall
Собственно, работа keyctl утилиты заключается в выполнении системногно вызова keyctl(2) :
$ strace -e keyctl keyctl print 546850615 keyctl(KEYCTL_READ, 546850615, NULL, 0) = 12 keyctl(KEYCTL_READ, 546850615, "example-data", 12) = 12 example-data +++ exited with 0 +++
В первом вызове – keyctl(KEYCTL_READ, 546850615, NULL, 0) = 12 – выполняем сам вызов keyctl() , которому передаём operation KEYCTL_READ и ID ключа.
Окей, тут более-менее просто и понятно.
- https://www.kernel.org/doc/Documentation/security/keys.txt
- https://www.ibm.com/developerworks/library/l-key-retention/
- http://man7.org/linux/man-pages/man7/keyrings.7.html
- http://man7.org/linux/man-pages/man1/keyctl.1.html
- http://man7.org/linux/man-pages/man2/keyctl.2.html
Перейдём к keyring storages.
gnome-keyring
Очень проблемный пакет, при этом наиболее широкоиспользуемый.
Устанавливаем, если не установлен:
$ sudo pacman -S gnome-keyring
Проверяем D-Bus сервисы – ищем org.freedesktop.secrets :
$ dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames . string "org.freedesktop.secrets" .
“Ага, вот эти ребята” (с)
$ dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/secrets org.freedesktop.DBus.Introspectable.Introspect .
Или с помощью qdbus – находим сам сервис:
$ qdbus | grep 'secrets\|keyring' org.freedesktop.secrets org.gnome.keyring
Читаем хелп qdbus :
$ qdbus --help . With 0 arguments, qdbus will list the services available on the bus With just the servicename, qdbus will list the object paths available on the service With service name and object path, qdbus will list the methods, signals and properties available on the object
Получаем описание сервиса:
$ qdbus org.freedesktop.secrets /org/freedesktop/secrets signal void org.freedesktop.DBus.Properties.PropertiesChanged(QString interface_name, QVariantMap changed_properties, QStringList invalidated_properties) method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name) method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name) method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value) method QString org.freedesktop.DBus.Introspectable.Introspect() method QString org.freedesktop.DBus.Peer.GetMachineId() method void org.freedesktop.DBus.Peer.Ping() .
D-Bus GetConnectionUnixProcessID
Собственно, мы хотим увидеть – кто “слушает” на том конце шины. Используем метод GetConnectionUnixProcessID :
$ qdbus --session org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixProcessID org.freedesktop.secrets 1278791
- выполняем вызов к сервису org.freedesktop.DBus
- передаём путь /
- вызываем метод org.freedesktop.DBus.GetConnectionUnixProcessID
- которому передаём аргументом имя сервиса, PID которого хотим узнать – org.freedesktop.secrets
И проверяем – кто такой 1278791:
$ ps xu | grep 1278791 setevoy 1278791 0.0 0.0 383876 8092 ? SLl Dec03 0:00 /usr/bin/gnome-keyring-daemon --start --foreground --components=secrets
Мы убедились, что роль Secret Service сейчас выполняет gnome-keyring . Давайте что-то подобавляем-поудаляем.
Используем python-keyring и secret-tool .
python-keyring
$ sudo pacman -S python-keyring
>>> import keyring >>> keyring.set_password("system", "username", "password") >>> keyring.get_password("system", "username") 'password'
В случае ошибок вида (может случится при первом запуске после установки gnome-keyring ):
>>> keyring.set_password("system", "username", "password") Traceback (most recent call last): . jeepney.wrappers.DBusErrorResponse: [org.freedesktop.DBus.Error.UnknownMethod] ('No such interface “org.freedesktop.DBus.Properties” on object at path /org/freedesktop/secrets/collection/login',)
Traceback (most recent call last): . raise PromptDismissedException('Prompt dismissed.') secretstorage.exceptions.PromptDismissedException: Prompt dismissed.
Выполняем скрипт /etc/X11/xinit/xinitrc.d/50-systemd-user.sh :
$ . /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
И создаём хранилище и пароль для него:
Смотрим в dbus-monitor , что происходит в D-Bus:
. method call time=1575542111.465749 sender=:1.576 -> destination=org.freedesktop.secrets serial=7 path=/org/freedesktop/secrets/aliases/default; interface=org.freedesktop.Secret.Collection; member=CreateItem array [ dict entry( string "org.freedesktop.Secret.Item.Attributes" variant array [ dict entry( string "application" string "Python keyring library" ) dict entry( string "service" string "system" ) dict entry( string "username" string "username" ) ] ) dict entry( string "org.freedesktop.Secret.Item.Label" variant string "Password for 'username' on 'system'" ) ] . struct < object path "/org/freedesktop/secrets/session/s14" >. signal time=1575542111.476006 sender=:1.220 -> destination=(null destination) serial=689 path=/org/freedesktop/secrets/collection/example_2dkeyring; interface=org.freedesktop.Secret.Collection; member=ItemCreated object path "/org/freedesktop/secrets/collection/example_2dkeyring/5" .
- sender=:1.576 – находим 1.576 в списке сервисов D-Bus – это наш Python:
- destination=org.freedesktop.secrets
наш /usr/bin/gnome-keyring-daemon , видели выше в выводе org.freedesktop.DBus.GetConnectionUnixProcessID
Проверяем в gnome-keyring с помощью, например, seahorse :
secret-tools
Ещё один вариант – использовать secret-tools .
$ secret-tool store --label=SecretToolExample username username service secret Password:
$ secret-tool lookup username username service secret password
Проверяем его в Seahorse:
KWallet
$ sudo pacman -S kwallet
$ qdbus --session org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixProcessID org.freedesktop.secrets 1278791 $ ps aux | grep 1278791 setevoy 1278791 0.0 0.0 384008 8048 ? SLl Dec03 0:00 /usr/bin/gnome-keyring-daemon --start --foreground --components=secrets
А почему не kwallet , почему до сих пор gnome-keyring ?
Окей, убиваем его:
$ kill 1278791
И сервис файл старый:
$ 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
Ладно – удалим gnome-keyring польностью:
$ sudo pacman -Rsn seahorse $ sudo pacman -Rsn gnome-keyring
Сервис-файла теперь нет:
$ cat /usr/share/dbus-1/services/org.freedesktop.secrets.service 2019/12/05 13:15:03 open /usr/share/dbus-1/services/org.freedesktop.secrets.service: no such file or directory
$ sudo pacman -S kwallet warning: kwallet-5.64.0-1 is up to date -- reinstalling .
Сервис-файл не создался:
$ qdbus --session org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixProcessID org.freedesktop.secrets Error: org.freedesktop.DBus.Error.NameHasNoOwner Could not get PID of name 'org.freedesktop.secrets': no such name
А D-Bus и Secret Service вообще подерживается в KWallet?
In brief, there is no longer a secret service implementation for KDE that I am aware of
И в документации ksecretsservice почти всё в ToDo…
Печаль. Лично мне нравятся Qt-based KDE приложения. Да и ещё более странен сам факт того, что Secret Service спецификация разрабатывалась GNOME и KDE проектами вместе, а реализована, получается, только в GNOME Keyring…
Still, мы можем использовать KWallet без Secret Service интеграции.
Запускаем менеджер кошельков:
$ kwalletmanager5
Создаём тестовый кошелёк:
Задаём пароль кошелька:
Но тут, понятноое дело, что ломается интеграция с Secret Service, например – наша Python-библиотека теперь говорит :
>>> keyring.set_password("system", "username", "password") Traceback (most recent call last): . raise value jeepney.wrappers.DBusErrorResponse: [org.freedesktop.DBus.Error.ServiceUnknown] ('The name org.freedesktop.secrets was not provided by any .service files',) The above exception was the direct cause of the following exception: Traceback (most recent call last): . raise SecretServiceNotAvailableException(data) from resp secretstorage.exceptions.SecretServiceNotAvailableException: The name org.freedesktop.secrets was not provided by any .service files During handling of the above exception, another exception occurred: Traceback (most recent call last): . raise RuntimeError("Unable to initialize SecretService: %s" % e) RuntimeError: Unable to initialize SecretService: The name org.freedesktop.secrets was not provided by any .service files
Но можно заменить keyring бекенд с SecretService и DBus на прямое указание kwallet5 , нагуглилось тут>>>:
>>> kwallet5 = keyring.backends.kwallet.DBusKeyring() >>> keyring.set_keyring(kwallet5) >>> keyring.get_keyring()
>>> keyring.set_password("system", "username", "password")
Проверяем D-Bus сообщения:
method call time=1575545736.524015 sender=:1.318 -> destination=:1.269 serial=38 path=/modules/kwalletd5; interface=org.kde.KWallet; member=writePassword int32 365838442 string "system" string "username" string "password" string "Python keyring library"
KeePass
Сам KeePass тоже может играть роль keyring backend используя Secret Storage спецификацию.
Если gnome-keyring не удалён – то будет ошибка вида “Another secret service is running“:
Удалям gnome-keyring , активируем Secret Service:
Проверяем активность D-Bus:
method call time=1575546064.021083 sender=:1.599 -> destination=org.freedesktop.DBus serial=26 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=RequestName string "org.freedesktop.secrets" uint32 4 signal time=1575546064.021157 sender=org.freedesktop.DBus -> destination=(null destination) serial=258 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged string "org.freedesktop.secrets" string "" string ":1.599" signal time=1575546064.021212 sender=org.freedesktop.DBus -> destination=:1.599 serial=16 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired string "org.freedesktop.secrets" method return time=1575546064.021245 sender=org.freedesktop.DBus -> destination=:1.599 serial=17 reply_serial=26 uint32 1
Проверяем кто слушает на org.freedesktop.secrets:
$ qdbus --session org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixProcessID org.freedesktop.secrets 4006761 $ ps aux | grep 4006761 setevoy 4006761 2.0 0.5 475888 89656 tty1 SLl 13:40 0:02 keepassxc
И запишем что-то в базу:
$ secret-tool store --label=SecretToolExample username username service secret Password: libsecret-Message: 13:45:13.448: Remote error from secret service: org.freedesktop.DBus.Error.UnknownObject: No such object path '/org/freedesktop/secrets/aliases/default' secret-tool: No such object path '/org/freedesktop/secrets/aliases/default'
Ага, надо в настройках базы настроить внутренний путь, см. комментарий тут>>>.
В самой базе добавим новую группу:
Далее идём в Database > Database settings, и указываем локальный путь к папке, которая будет использоваться в роли Secret Service storage:
Перезапускаем KeePass, в D-Bus видно, как добавляется коллекция:
signal time=1575546948.831195 sender=:1.613 -> destination=(null destination) serial=22 path=/org/freedesktop/secrets; interface=org.freedesktop.Secret.Service; member=CollectionCreated object path "/org/freedesktop/secrets/collection/Main" signal time=1575546982.884850 sender=:1.613 -> destination=(null destination) serial=23 path=/org/freedesktop/secrets; interface=org.freedesktop.Secret.Service; member=CollectionChanged object path "/org/freedesktop/secrets/collection/Main"
$ secret-tool store --label=SecretToolExample username username service secret Password:
. method call time=1575547056.148892 sender=:1.616 -> destination=org.freedesktop.secrets serial=10 path=/org/freedesktop/secrets/aliases/default; interface=org.freedesktop.Secret.Collection; member=CreateItem array [ dict entry( string "org.freedesktop.Secret.Item.Attributes" variant array [ dict entry( string "service" string "secret" ) dict entry( string "username" string "username" ) ] ) dict entry( string "org.freedesktop.Secret.Item.Label" variant string "SecretToolExample" ) ] .
И в самом KeePass:
Ссылки по теме
keyrings, Secret Service, etc
- GNOME Keyring – GNOME project docs
- GNOME/Keyring – Arch Linux Wiki
- KDE Wallet
- Python Keyring Lib
- Manage Passwords, Encryption Keys, And More With Seahorse
- secret-tool examples
- Keychain
- Using Linux keyring secrets from your scripts
- Secret Service API Draft
- Python bindings to FreeDesktop.org Secret Service API
- Python keyring lib
- Libsecret Library Reference Manual
- Credentials located in gnome-keyring can be compromised easily
- “Please enter password for encrypted keyring” when running Python script on Ubuntu
- Use keyring to store your credentials
- In KDE Plasma, keyring uses gnome-keyring by default – просто поулыбаться
- Get started with the Linux key retention service
D-Bus
- D-Bus Tutorial
- D-Bus/Introduction
- D-Bus Specification
- D-Bus API Design Guidelines
- Introspecting D-Bus from the command-line
- Understanding D-Bus
- dbus-python tutorial
- Universal standard mapping between D-Bus and URI namespaces
- D-Bus, quick recap