systemd 12 and newer support lightweight password agents which can be used to
query the user for system-level passwords or passphrases. These are
passphrases that are not related to a specific user, but to some kind of
hardware or service. This is used for encrypted hard-disk passphrases or to
query passphrases of SSL certificates at web server start-up time. The basic
idea is that a system component requesting a password entry can simply drop a
simple .ini-style file into /run/systemd/ask-password/
which multiple
different agents may watch via inotify()
, and query the user as necessary.
The answer is then sent back to the querier via an AF_UNIX
/SOCK_DGRAM
socket. Multiple agents might be running at the same time in which case they
all should query the user and the agent which answers first wins. Right now
systemd ships with the following passphrase agents:
wall(1)
agent which sends wall messages as soon as a password shall be entered.systemctl start
” (and similar commands) and asks passwords to the user during manual startup of a serviceIt is easy to write additional agents. The basic algorithm to follow looks like this:
/run/systemd/ask-password/
, watch for IN_CLOSE_WRITE|IN_MOVED_TO
ask.
”ask.xxxx
” shows up, read it. It’s a simple .ini
file that may be parsed with the usual parsers. The xxxx
suffix is randomized..ini
file keys in those files, so that we can easily extend the format later on.Message=
field in the [Ask]
section.
It is a single-line string in UTF-8, which might be internationalized (by the party that originally asks the question, not by the agent).Icon=
field in the [Ask]
sectionPID=
field in the [Ask]
section
(Before asking your question use kill(PID, 0)
and ignore the file if this returns ESRCH
;
there’s no need to show the data of this field but if you want to you may)Echo=
specifies whether the input should be obscured. If this field is missing or is Echo=0
, the input should not be shown.Socket=
in the [Ask]
section. It is a AF_UNIX
/SOCK_DGRAM
socket in the file system.NotAfter=
field in the [Ask]
section is in the past.
The time is specified in usecs, and refers to the CLOCK_MONOTONIC
clock. If NotAfter=
is 0
, no such check should take place.ask.xxxx
file is deleted, watch this with inotify. b) the NotAfter=
time elapses, if it is set != 0
./usr/bin/pkexec /usr/lib/systemd/systemd-reply-password 1 /path/to/socket
” or “/usr/bin/pkexec /usr/lib/systemd/systemd-reply-password 0 /path/to/socket
” and writing the password to its standard input.
Use ‘1
’ as argument if a password was entered by the user, or ‘0
’ if the user canceled the request.+
” or with “-
” depending on whether the password entry was successful or not.
You may but don’t have to include a final NUL
byte in your message.Again, it is essential that you stop showing the password
box/notification/status icon if the ask.xxxx
file is removed or when
NotAfter=
elapses (if it is set != 0
)!
It may happen that multiple password entries are pending at the same time. Your agent needs to be able to deal with that. Depending on your environment you may either choose to show all outstanding passwords at the same time or instead only one and as soon as the user has replied to that one go on to the next one.
If you write a system level agent, a smart way to activate it is using systemd
.path
units. This will ensure that systemd will watch the
/run/systemd/ask-password/
directory and spawn the agent as soon as that
directory becomes non-empty. In fact, the console, wall and Plymouth agents
are started like this. If systemd is used to maintain user sessions as well
you can use a similar scheme to automatically spawn your user password agent as
well.
It’s also easy to implement applications that want to query passwords this way
(i.e. client for the agents above). Simply bind an AF_UNIX
/SOCK_DGRAM
socket somewhere (suggestion: you can do this in /run/systemd/ask-password/
under a randomized socket name, not beginning with ask.
). Then, create an
/run/systemd/ask-password/ask.xxxx
(replace the xxxx
by some randomized
string) file, with the appropriate Message=
, PID=
, Icon=
, Echo=
,
NotAfter=
fields in the [Ask]
section. Most importantly, include Socket=
pointing to your socket entrypoint. Then, just wait until the password is
delivered to you on the socket. Finally, don’t forget to remove the file and
the socket once done.
You may test agents by manually invoking the “systemd-ask-password
” tool from
a shell. Pass --no-tty
to ensure the password is asked via the agent system.
You may test queriers by manually invoking the
“systemd-tty-ask-password-agent
” from a shell.
Starting with systemd v257 the scheme is extended to per-user password
agents. A second per-user directory $XDG_RUNTIME_DIR/systemd/ask-password/
is
now available, with the same protocol as the system-wide
counterpart. Unprivileged, per-directory agents should watch this directory in
parallel to the system-wide one. Unprivileged queriers (i.e. clients to these
agents) should pick the per-user directory to place their password request
files in.