It’s a really long-read post and I wast sure if it’s better to split it into three parts or put them together. On the one side, there are keyrings, from another – D-Bus, and finally, there is a Secret Service.
Eventually, I decided to keep them here together as I googled all it in the same scope and the are related to each other.
So, in this post we will speak about the next:
- what is the keyring at all
- what is the difference between the Linux keyring and GNOME keyring, and do they relate to each other
- what keyring implementations are
- what is the
org.freedesktop
Secret Service and how it relates to the GNOME keyring - what is D-Bus, and how we can use it to see how a keyring service is working
- and a couple of examples with Linux Keyring, GNOME Keyring, KWallet, and KeePass as a keyring backend
This post is absolutely not kind of “tutorial” with “HowTo Configure it” but instead – just an overview of the components mentioned above to try to understand what they are and how they can be used.
See also:
This post was written by a long-long googling, so here will be a lot of links to documents and other materials that were used.
I may confuse something or even understood in a wrong way, so please welcome to the comments, if you’ll see any errors.
The post’s writing process was like this:
What is the Keyring?
To start what the “keyring” word means at all?
Let’s start with Wikipedia – https://en.wikipedia.org/wiki/Keyring_(cryptography):
In cryptography, a keyring stores known encryption keys (and, in some cases, passwords).
Then, let’s proceed with the GNOME project documentation – https://help.gnome.org/users/seahorse/stable/keyring.html.en:
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.
And even let’s take a look at the MySQL documentation – https://dev.mysql.com/doc/refman/5.7/en/keyring-service.html:
a keyring service that enables internal server components and plugins to securely store sensitive information for later retrieval
Finally, take a look at the keyrings(7) man-page – http://man7.org/linux/man-pages/man7/keyrings.7.html:
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.
So, the keyring concept – it is some mechanism, or facility, or a concrete application, intended to store some confidential data.
Good, let’s go deeper.
Linux keyring vs gnome-keyring
Useful links used:
Now, let’s speak about the difference between the Linux kernel keyring and the GNOME Keyring: at first, I was confused as I suggested that GNOME Keyring somehow uses kernel’s keyrings facility, but now – it’s just different things.
Let’s go back to the man 7 Linux keyrings:
keyrings – in-kernel key management and retention facility
I.e. Linux keyrings – it’s is kernel’s mechanism providing the ability to store secret information.
Now, let’s read the gnome-keyring
documentation:
GNOME Keyring is a collection of components in GNOME that store secrets, passwords, keys, certificates and make them available to applications.
So, GNOME Keyring – is a collection of utilities (gnome-keyring-daemon
, libraries, the seahorse
package, etc) to store confidential data. See also GNOME Keyring architecture.
Good documents also can be found here – Tower Floor — Encryption, in particular, see the Caching Passwords document.
Summary
Let’s summarize the key differences between Linux keyrings and GNOME Keyring:
- main():
- Linux kernel – is a kernel’s facility for “passwords caching” – it stores them in a computer’s memory during an active user’s/system session
gnome-keyring
– is persistent storage with keeping data on a hard disk
- storing:
- Linux keyring – store in RAM, thus passwords are available only during a session, there is no need to store them always
gnome-keyring
– creates a file on a disk, usually, in the~/.local/share/keyrings/
- accessing:
- Linux keyring – via syscalls from the user space into the kernel space
gnome-keyring
– via DBus
- applications to access:
Keyrings implementations
Beside that, python-keyring
mention:
And this list is not full.
Also, there a bunch of client applications to be used with those keyrings, again the list is not full:
Passwords interception from the gnome-keyting
During googling, found an interesting bug discussion here – https://bugs.launchpad.net/ubuntu/+source/gnome-keyring/+bug/1780365
In short:
- a client and a service communicates via D-Bus
- a client ask for some data from the Secret Service (
gnome-keyring
in this case) - the service via D-Bus send a confidential data
- another, “bad”, process listens dbus-messages and intercepts a password
What is the Secret Service?
Another one concept I had to google about: what is the “Secret Service”? How it relates to the GNOME Keyring and to the KWallet?
What is it doing in the Linux and how can I touch it?
Well, let’s go to the documentation again – https://specifications.freedesktop.org/secret-service/latest/ch01.html:
The Secret Service API allows client applications to store secrets securely in a service running in the user’s login session.
Aha, i.e. Secret Service – it’s not some particular service or an application, but it’s a specification, kind of an RFC created by the GNOME and KDE projects to determine how this API must be realized for a client which wants to use GNOME Keyring or KWallet to store their secrets.
Also, the Secret Service API supported not only by the GNOME Keyring and KWallet but also for example by the KeePass and other applications.
IMHO, a bit confusing is the Secret Service name itself – “a hidden service”. If it would be called Secrets Service, i.e. “service of a secrets data” – it would be much more clear.
The Secret Service glossary
In short terms:
- secret: a password itself, or any other secret data
- item: each such a secret plus its set of attributes makes up an item
- collection: a set of such items makes a collection (similar to the keyring or wallet concepts)
- collections and items represented by D-Bus objects, each with its unique path
- default collection: client applications without special conditions have to save items to the default collection which has to be accessible via the
/org/freedesktop/secrets/aliases/default
D-Bus path
D-Bus
Oookay…
Not its time to try to recall with is the D-Bus so often mentioned in the previous parts, and how to deal with it.
So, the D-Bus on of the Linux kernel IPC – Inter-Process Communication – mechanisms, allowing for separate processes inside of an operating system to communicate with each other.
Useful links:
And in short about main concepts and terms in D-Bus:
- D-Bus in general: it’s a “bus” for IPC, i.e. if in the previous SSH examples (see the SSH: RSA keys, and ssh-agent for SSH keys and their passwords management post) a UNIX socket was used, this time we are using the bus mechanism, see the https://www.kernel.org/doc/html/latest/driver-api/driver-model/bus.html. In its turn, those buses can be
- a session bus
- a system bus
- private buses
- messages: a base communication unit, data transfer similar to the TCP/IP, just in the D-Bus all data of a message is included to the message and not split over TCP-packets
- when a message is sent usually it leads to some method to be called to execute some actions by an application providing this method
- a message can be sent by an application to itself
- namespaces and addresses:
- as various applications can be placed on the same bus (or “listen to the same bus”) and during that the same application can provide various objects which can accept messages, then need to have some way to address those messages. In D-Bus, such an address consists of an interface name + service + an object name
- a namespace example – org.freedesktop.dbus
- an address example – unix:tmpdir=/tmp/my-app-name
- interface: a set of methods and signals on a particular bus f a particular object. You can think of interfaces as named methods and signals group.
- most of the interfaces will lead to the concrete construction of a language used for an application, for example, it can be a Java interface or a virtual class in С++
- an interface example – org.freedesktop.Introspectable
- service: represents a concrete connection of a particular application to a bus
- under the service here means a bus name (in the origin – “well-known” Bus names), but keep in mind that the “bus name” here implies a particular connection name but not the bus name
- if an application has more then one connection to a bus, or if the application is running in multitype instances – expanded by a PID number, for example, to make it unique
- a service example – org.kde.screensaver
- objects: the same application can provide access to its multiple objects using paths to separate those objects. Each such a path associated with a service represents a dedicated object, for example
/MainInterface
or/Documents/Doc1
. Objects allow access to interfaces and the same object can provide such access to multiple interfaces at the same time - methods: each object has members of the two types – methods and signals
- methods – ate messages sent to an object to trigger some action in an application, who created this object
- methods can pass data to an application’s input and can return an output with some values from the application
- methods always have a sender and receiver addresses
- signals:
- are similar to the methods, but are not tied to any specific destination and can be accepted by any application on the same bus
- are generated by an application which exported an interface
D-Bus tools
CLI:
qdbus
– watch and send messages via D-Busdbus-monitor
– view a bus activitydbus-send
– send messages via D-Bus
GUI:
qdbusviewer
– view objects and messages, is a part of theqt5-tools
setd-feet
– D-Bus debuggerbustle
– D-Bus message analyzer and profiler
For example d-feet
, install it:
Run it:
Keyrings examples
And a few examples of how those backends can be used from a Python or CLI utilities.
Linux keyring
As already mentioned, the Linux keyring is a kind of “caching service” in the kernel.
You can use the keyctl
utility from the keyutils
, and systemd-ask-password
.
To read about:
And from the documentation:
Each process subscribes to three keyrings: a thread-specific keyring, a process-specific keyring, and a session-specific keyring.
Let’s see which keyrings are available for my current session:
keyctl show @s
Session Keyring
185597501 --alswrv 1000 1000 keyring: _ses
182944921 --alswrv 1000 65534 \_ keyring: _uid.1000
Or for my user:
keyctl show @u
Keyring
182944921 --alswrv 1000 65534 keyring: _uid.1000
Also, in the /proc/key-users
you can get information about all keyrings and their statistics by each user:
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
And keys available for reading by our process (thebash
which called the 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
A user’s keyrings in the current session:
keyctl describe @us
-5: -lswrvalswrv------------ 1000 65534 keyring: _uid_ses.1000
Keys in the current keyring:
keyctl list @us
1 key in keyring:
182944921: --alswrv 1000 65534 keyring: _uid.1000
Add a key:
keyctl add user example-key example-data @u
546850615
Find it:
keyctl request user example-key
546850615
Got its ID and now can read its content using this ID:
keyctl print 546850615
example-data
keyctl()
syscall
Actually, the keyctl
utility just executes the keyctl(2)
system call:
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 +++
In the first call here – keyctl(KEYCTL_READ, 546850615, NULL, 0) = 12
– we performed the keyctl()
syscall with passing the KEYCTL_READ
operation and a key ID.
Okay – more or less clear here.
Materials used here:
Let’s go to the keyring storages.
gnome-keyring
Really problematic package, as for me, but still it is most widely used.
Install if not present yet:
sudo pacman -S gnome-keyring
Check D-Bus services – look for the 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"
...
“Aha, here we are” (c)
Now we can get the service description by using the org.freedesktop.DBus.Introspectable.Introspect
method:
dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/secrets org.freedesktop.DBus.Introspectable.Introspect
...
<node>
<interface name="org.freedesktop.DBus">
<method name="Hello">
<arg direction="out" type="s"/>
</method>
<method name="RequestName">
<arg direction="in" type="s"/>
<arg direction="in" type="u"/>
<arg direction="out" type="u"/>
</method>
<method name="ReleaseName">
<arg direction="in" type="s"/>
<arg direction="out" type="u"/>
</method>
...
Or with the qdbus
, fid the service first:
qdbus | grep 'secrets\|keyring'
org.freedesktop.secrets
org.gnome.keyring
Read the qdbus
help:
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
And get the full service’s description:
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
Actually, I want to see who is listening on the another side of the bus. Let’s use the GetConnectionUnixProcessID
method for this:
qdbus --session org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixProcessID org.freedesktop.secrets
1278791
Here we did:
- a call to the org.freedesktop.DBus service
- passing the / path
- called the
org.freedesktop.DBus.GetConnectionUnixProcessID
method - and passing the service org.freedesktop.secrets name to the method to get its PID
Check what is the 1278791 PID:
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
Nice.
So, now we are knowing that the Secret Service role is played by the gnome-keyring
application. Let’s try to add and remove some data using thepython-keyring
and secret-tool
.
python-keyring
Start with the python-keyring
.
Install it:
sudo pacman -S python-keyring
Check:
>>> import keyring
>>> keyring.set_password("system", "username", "password")
>>> keyring.get_password("system", "username")
'password'
In case of errors like (can happen on the first run after installation on Arch Linux, for example):
>>> 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',)
Or:
Traceback (most recent call last):
...
raise PromptDismissedException('Prompt dismissed.')
secretstorage.exceptions.PromptDismissedException: Prompt dismissed.
You need to execute the /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
script:
. /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
And create a new keyring and set a password for it:
Let’s check the dbus-monitor
, to see what’s is going on in the 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"
...
Here:
- sender=:1.576 – find the 1.576 in the D-Bus services list – it’s our Python (
cmd: python
):
- destination=org.freedesktop.secrets
our/usr/bin/gnome-keyring-daemon
, already seen in theorg.freedesktop.DBus.GetConnectionUnixProcessID
output
Check the gnome-keyring
storage with the seahorse
utility for example:
Okay, “It works!” (c).
secret-tools
Another way can be to use secret-tools
utility.
Add a new secret:
secret-tool store --label=SecretToolExample username username service secret
Password:
Retrieve it:
secret-tool lookup username username service secret
password
Check with the Seahorse in the storage:
KWallet
Install:
Check the D-Bus:
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
Er…
Why not the kwallet
, why still the gnome-keyring
?
Try to kill it:
And the service-file is still old:
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
Okay, fully delete the gnome-keyring
:
sudo pacman -Rsn seahorse
sudo pacman -Rsn gnome-keyring
And no service file now:
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
Reinstall kwallet
:
sudo pacman -S kwallet
warning: kwallet-5.64.0-1 is up to date -- reinstalling
...
No new service file:
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
That’s weird…
Does D-Bus and Secret Service are supported by the KWallet at all?
Reddit says it’s not:
In brief, there is no longer a secret service implementation for KDE that I am aware of
And the ksecretsservice
documentation is just full of ToDo’s…
It’s a pity. I do like Qt-based KDE applications.
And the more strange is the fact that the Secret Service specification was written by both GNOME and KDE projects together, but it’s supported by the GNOME Keyring only…
Still, we can use KWallet without the Secret Service integration.
Run the KDE’s wallets manager:
Create a wallet:
Set its password:
Obviously, now our Python lib will stop working as no Secret Service now is available:
>>> 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
But you can configure a keyring
backend and set the kwallet5
directly, googled it here>>>:
>>> kwallet5 = keyring.backends.kwallet.DBusKeyring()
>>> keyring.set_keyring(kwallet5)
>>> keyring.get_keyring()
<keyring.backends.kwallet.DBusKeyring object at 0x7f7efba66fa0>
Add a password:
>>> keyring.set_password("system", "username", "password")
Check the D-Bus messages:
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"
And the KWallet:
KeePass
Also, KeePass can act as a keyring backend service using the Secret Storage specification.
If the gnome-keyring
is still running – you’ll get the “Another secret service is running” error from the KeePass:
Remove the gnome-keyring
, and activate Secret Service:
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
Check, who is listening to the 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
Okay – this is our KeePass.
Add something to the database:
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'
Er…
Aha, need to configure an internal path in the KeePass database, see this>>> comment.
Add a new group in the database:
Next, go to the Database > Database settings and specify local path to a directory which will be used to store data when acting as a Secret Service storage:
Restart KeePass and check the D-Bus – can see now how the collection was added now:
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"
Add a record:
secret-tool store --label=SecretToolExample username username service secret
Password:
Check the D-Bus:
...
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"
)
]
...
And the KeePass itself:
That’s all for now.
Useful links
keyrings, Secret Service, etc
D-Bus
Also published on Medium.
from Hacker News https://ift.tt/cgm8Gst
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.