mirror of
https://github.com/systemd/systemd
synced 2024-09-06 16:56:43 +00:00
Merge pull request #18971 from poettering/sysusers-creds
let's read LoadCredentials=/SetCredentials= style cred in sysusers/firstboot and when asking for passwords
This commit is contained in:
commit
f9d8325e69
5
TODO
5
TODO
|
@ -61,11 +61,6 @@ Features:
|
||||||
With all that in place if nspawn host and container payload are up-to-date
|
With all that in place if nspawn host and container payload are up-to-date
|
||||||
enough we have a very simple way to make host users available in containers.
|
enough we have a very simple way to make host users available in containers.
|
||||||
|
|
||||||
* systemd-sysusers: pick up passwords from credentials logic, so that users can
|
|
||||||
easily set root user pw. enable cred inheriting for root user from PID 1, so
|
|
||||||
that for containers we can configure the root pw automatically via nspawn's
|
|
||||||
--set-credential= switch. (Also do this for systemd-firstboot)
|
|
||||||
|
|
||||||
* whenever we receive fds via SCM_RIGHTS make sure none got dropped due to the
|
* whenever we receive fds via SCM_RIGHTS make sure none got dropped due to the
|
||||||
reception limit the kernel silently enforces.
|
reception limit the kernel silently enforces.
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,17 @@
|
||||||
directly. Example: <literal>--keyname=cryptsetup</literal></para></listitem>
|
directly. Example: <literal>--keyname=cryptsetup</literal></para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--credential=</option></term>
|
||||||
|
<listitem><para>Configure a credential to read the password from – if it exists. This may be used in
|
||||||
|
conjunction with the <varname>LoadCredential=</varname> and <varname>SetCredential=</varname>
|
||||||
|
settings in unit files. See
|
||||||
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||||
|
details. If not specified, defaults to <literal>password</literal>. This option has no effect if no
|
||||||
|
credentials directory is passed to the program (i.e. <varname>$CREDENTIALS_DIRECTORY</varname> is not
|
||||||
|
set) or if the no credential of the specified name exists.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--timeout=</option></term>
|
<term><option>--timeout=</option></term>
|
||||||
|
|
||||||
|
|
|
@ -283,7 +283,69 @@
|
||||||
<xi:include href="standard-options.xml" xpointer="help" />
|
<xi:include href="standard-options.xml" xpointer="help" />
|
||||||
<xi:include href="standard-options.xml" xpointer="version" />
|
<xi:include href="standard-options.xml" xpointer="version" />
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Credentials</title>
|
||||||
|
|
||||||
|
<para><command>systemd-firstboot</command> supports the service credentials logic as implemented by
|
||||||
|
<varname>LoadCredential=</varname>/<varname>SetCredential=</varname> (see
|
||||||
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
|
||||||
|
details). The following credentials are used when passed in:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>passwd.hashed-password.root</literal></term>
|
||||||
|
<term><literal>passwd.plaintext-password.root</literal></term>
|
||||||
|
|
||||||
|
<listitem><para>A hashed or plaintext version of the root password to use, in place of prompting the
|
||||||
|
user. These credentials are equivalent to the same ones defined for the
|
||||||
|
<citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
service.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>passwd.shell.root</literal></term>
|
||||||
|
|
||||||
|
<listitem><para>Specifies the shell binary to use for the the specified account when creating
|
||||||
|
it. Equivalent to the credential of the same name defined for the
|
||||||
|
<citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
service.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>firstboot.locale</literal></term>
|
||||||
|
<term><literal>firstboot.locale-messages</literal></term>
|
||||||
|
|
||||||
|
<listitem><para>These credentials specify the locale settings to set during first boot, in place of
|
||||||
|
prompting the user.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>firstboot.keymap</literal></term>
|
||||||
|
|
||||||
|
<listitem><para>This credential specifies the keyboard setting to set during first boot, in place of
|
||||||
|
prompting the user.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>firstboot.timezone</literal></term>
|
||||||
|
|
||||||
|
<listitem><para>This credential specifies the system timezone setting to set during first boot, in
|
||||||
|
place of prompting the user.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>Note that by default the <filename>systemd-firstboot.service</filename> unit file is set up to
|
||||||
|
inherit the listed credentials
|
||||||
|
from the service manager. Thus, when invoking a container with an unpopulated <filename>/etc/</filename>
|
||||||
|
for the first time it is possible to configure the root user's password to be <literal>systemd</literal>
|
||||||
|
like this:</para>
|
||||||
|
|
||||||
|
<para><programlisting># systemd-nspawn --image=… --set-credential=firstboot.locale:de_DE.UTF-8 …</programlisting></para>
|
||||||
|
|
||||||
|
<para>Note that these credentials are only read and applied during the first boot process. Once they are
|
||||||
|
applied they remain applied for subsequent boots, and the credentials are not considered anymore.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|
|
@ -1487,7 +1487,31 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
|
||||||
<para>In order to embed binary data into the credential data for <option>--set-credential=</option>
|
<para>In order to embed binary data into the credential data for <option>--set-credential=</option>
|
||||||
use C-style escaping (i.e. <literal>\n</literal> to embed a newline, or <literal>\x00</literal> to
|
use C-style escaping (i.e. <literal>\n</literal> to embed a newline, or <literal>\x00</literal> to
|
||||||
embed a <constant>NUL</constant> byte. Note that the invoking shell might already apply unescaping
|
embed a <constant>NUL</constant> byte. Note that the invoking shell might already apply unescaping
|
||||||
once, hence this might require double escaping!).</para></listitem>
|
once, hence this might require double escaping!).</para>
|
||||||
|
|
||||||
|
<para>The
|
||||||
|
<citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
and
|
||||||
|
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
|
services read credentials configured this way for the purpose of configuring the container's root
|
||||||
|
user's password and shell, as well as system locale, keymap and timezone during the first boot
|
||||||
|
process of the container. This is particularly useful in combination with
|
||||||
|
<option>--volatile=yes</option> where every single boot appears as first boot, since configuration
|
||||||
|
applied to <filename>/etc/</filename> is lost on container reboot cycles. See the respective man
|
||||||
|
pages for details. Example:</para>
|
||||||
|
|
||||||
|
<programlisting># systemd-nspawn -i image.raw \
|
||||||
|
--volatile=yes \
|
||||||
|
--set-credential=firstboot.locale:de_DE.UTF-8 \
|
||||||
|
--set-credential=passwd.hashed-password.root:'$y$j9T$yAuRJu1o5HioZAGDYPU5d.$F64ni6J2y2nNQve90M/p0ZP0ECP/qqzipNyaY9fjGpC' \
|
||||||
|
-b</programlisting>
|
||||||
|
|
||||||
|
<para>The above command line will invoke the specified image file <filename>image.raw</filename> in
|
||||||
|
volatile mode, i.e with an empty <filename>/etc/</filename> and <filename>/var/</filename>, so that
|
||||||
|
the container's payload recognizes this as first boot condition, and will invoke
|
||||||
|
<filename>systemd-firstboot.service</filename>, which then read the two passed credentials to
|
||||||
|
configure the system's initial locale and root password.</para>
|
||||||
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
|
@ -126,7 +126,60 @@
|
||||||
<xi:include href="standard-options.xml" xpointer="help" />
|
<xi:include href="standard-options.xml" xpointer="help" />
|
||||||
<xi:include href="standard-options.xml" xpointer="version" />
|
<xi:include href="standard-options.xml" xpointer="version" />
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Credentials</title>
|
||||||
|
|
||||||
|
<para><command>systemd-sysusers</command> supports the service credentials logic as implemented by
|
||||||
|
<varname>LoadCredential=</varname>/<varname>SetCredential=</varname> (see
|
||||||
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
|
||||||
|
details). The following credentials are used when passed in:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>passwd.hashed-password.<replaceable>user</replaceable></literal></term>
|
||||||
|
<listitem><para>A UNIX hashed password string to use for the specified user, when creating an entry
|
||||||
|
for it. This is particularly useful for the <literal>root</literal> user as it allows provisioning
|
||||||
|
the default root password to use via a unit file drop-in or from a container manager passing in this
|
||||||
|
credential. Note that setting this credential has no effect if the specified user account already
|
||||||
|
exists. This credential is hence primarily useful in first boot scenarios or systems that are fully
|
||||||
|
stateless and come up with an empty <filename>/etc/</filename> on every boot.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>passwd.plaintext-password.<replaceable>user</replaceable></literal></term>
|
||||||
|
|
||||||
|
<listitem><para>Similar to <literal>passwd.hashed-password.<replaceable>user</replaceable></literal>
|
||||||
|
but expect a literal, plaintext password, which is then automatically hashed before used for the user
|
||||||
|
account. If both the hashed and the plaintext credential are specified for the same user the
|
||||||
|
former takes precedence. It's generally recommended to specify the hashed version; however in test
|
||||||
|
environments with weaker requirements on security it might be easier to pass passwords in plaintext
|
||||||
|
instead.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>passwd.shell.<replaceable>user</replaceable></literal></term>
|
||||||
|
|
||||||
|
<listitem><para>Specifies the shell binary to use for the the specified account when creating it.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>Note that by default the <filename>systemd-sysusers.service</filename> unit file is set up to
|
||||||
|
inherit the <literal>passwd.hashed-password.root</literal>,
|
||||||
|
<literal>passwd.plaintext-password.root</literal> and <literal>passwd.shell.root</literal> credentials
|
||||||
|
from the service manager. Thus, when invoking a container with an unpopulated <filename>/etc/</filename>
|
||||||
|
for the first time it is possible to configure the root user's password to be <literal>systemd</literal>
|
||||||
|
like this:</para>
|
||||||
|
|
||||||
|
<para><programlisting># systemd-nspawn --image=… --set-credential=password.hashed-password.root:'$y$j9T$yAuRJu1o5HioZAGDYPU5d.$F64ni6J2y2nNQve90M/p0ZP0ECP/qqzipNyaY9fjGpC' …</programlisting></para>
|
||||||
|
|
||||||
|
<para>Note again that the data specified in these credentials is consulted only when creating an account
|
||||||
|
for the first time, it may not be used for changing the password or shell of an account that already
|
||||||
|
exists.</para>
|
||||||
|
|
||||||
|
<para>Use <citerefentry><refentrytitle>mkpasswd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
|
for generating UNIX password hashes from the command line.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -141,7 +194,9 @@
|
||||||
<para>
|
<para>
|
||||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||||
<ulink url="https://systemd.io/UIDS-GIDS">Users, Groups, UIDs and GIDs on systemd systems</ulink>
|
<ulink url="https://systemd.io/UIDS-GIDS">Users, Groups, UIDs and GIDs on systemd systems</ulink>,
|
||||||
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>mkpasswd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
|
@ -2821,7 +2821,7 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
|
||||||
<variablelist class='unit-directives'>
|
<variablelist class='unit-directives'>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>LoadCredential=</varname><replaceable>ID</replaceable>:<replaceable>PATH</replaceable></term>
|
<term><varname>LoadCredential=</varname><replaceable>ID</replaceable><optional>:<replaceable>PATH</replaceable></optional></term>
|
||||||
|
|
||||||
<listitem><para>Pass a credential to the unit. Credentials are limited-size binary or textual objects
|
<listitem><para>Pass a credential to the unit. Credentials are limited-size binary or textual objects
|
||||||
that may be passed to unit processes. They are primarily used for passing cryptographic keys (both
|
that may be passed to unit processes. They are primarily used for passing cryptographic keys (both
|
||||||
|
@ -2834,19 +2834,21 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
|
||||||
environment variable to the unit's processes.</para>
|
environment variable to the unit's processes.</para>
|
||||||
|
|
||||||
<para>The <varname>LoadCredential=</varname> setting takes a textual ID to use as name for a
|
<para>The <varname>LoadCredential=</varname> setting takes a textual ID to use as name for a
|
||||||
credential plus a file system path. The ID must be a short ASCII string suitable as filename in the
|
credential plus a file system path, separated by a colon. The ID must be a short ASCII string
|
||||||
filesystem, and may be chosen freely by the user. If the specified path is absolute it is opened as
|
suitable as filename in the filesystem, and may be chosen freely by the user. If the specified path
|
||||||
regular file and the credential data is read from it. If the absolute path refers to an
|
is absolute it is opened as regular file and the credential data is read from it. If the absolute
|
||||||
<constant>AF_UNIX</constant> stream socket in the file system a connection is made to it (only once
|
path refers to an <constant>AF_UNIX</constant> stream socket in the file system a connection is made
|
||||||
at unit start-up) and the credential data read from the connection, providing an easy IPC integration
|
to it (only once at unit start-up) and the credential data read from the connection, providing an
|
||||||
point for dynamically providing credentials from other services. If the specified path is not
|
easy IPC integration point for dynamically providing credentials from other services. If the
|
||||||
absolute and itself qualifies as valid credential identifier it is understood to refer to a
|
specified path is not absolute and itself qualifies as valid credential identifier it is understood
|
||||||
credential that the service manager itself received via the <varname>$CREDENTIALS_DIRECTORY</varname>
|
to refer to a credential that the service manager itself received via the
|
||||||
environment variable, which may be used to propagate credentials from an invoking environment (e.g. a
|
<varname>$CREDENTIALS_DIRECTORY</varname> environment variable, which may be used to propagate
|
||||||
container manager that invoked the service manager) into a service. The contents of the file/socket
|
credentials from an invoking environment (e.g. a container manager that invoked the service manager)
|
||||||
may be arbitrary binary or textual data, including newline characters and <constant>NUL</constant>
|
into a service. The contents of the file/socket may be arbitrary binary or textual data, including
|
||||||
bytes. This option may be used multiple times, each time defining an additional credential to pass to
|
newline characters and <constant>NUL</constant> bytes. If the file system path is omitted it is
|
||||||
the unit.</para>
|
chosen identical to the credential name, i.e. this is a terse way do declare credentials to inherit
|
||||||
|
from the service manager into a service. This option may be used multiple times, each time defining
|
||||||
|
an additional credential to pass to the unit.</para>
|
||||||
|
|
||||||
<para>The credential files/IPC sockets must be accessible to the service manager, but don't have to
|
<para>The credential files/IPC sockets must be accessible to the service manager, but don't have to
|
||||||
be directly accessible to the unit's processes: the credential data is read and copied into separate,
|
be directly accessible to the unit's processes: the credential data is read and copied into separate,
|
||||||
|
|
|
@ -12,10 +12,12 @@
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
#include "terminal-util.h"
|
||||||
|
|
||||||
static const char *arg_icon = NULL;
|
static const char *arg_icon = NULL;
|
||||||
static const char *arg_id = NULL;
|
static const char *arg_id = NULL; /* identifier for 'ask-password' protocol */
|
||||||
static const char *arg_keyname = NULL;
|
static const char *arg_key_name = NULL; /* name in kernel keyring */
|
||||||
|
static const char *arg_credential_name = NULL; /* name in $CREDENTIALS_DIRECTORY directory */
|
||||||
static char *arg_message = NULL;
|
static char *arg_message = NULL;
|
||||||
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
|
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
|
||||||
static bool arg_multiple = false;
|
static bool arg_multiple = false;
|
||||||
|
@ -32,21 +34,26 @@ static int help(void) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
printf("%s [OPTIONS...] MESSAGE\n\n"
|
printf("%1$s [OPTIONS...] MESSAGE\n\n"
|
||||||
"Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
|
"%3$sQuery the user for a system passphrase, via the TTY or an UI agent.%4$s\n\n"
|
||||||
" -h --help Show this help\n"
|
" -h --help Show this help\n"
|
||||||
" --icon=NAME Icon name\n"
|
" --icon=NAME Icon name\n"
|
||||||
" --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
|
" --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
|
||||||
" --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
|
" --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
|
||||||
|
" --credential=NAME\n"
|
||||||
|
" Credential name for LoadCredential=/SetCredential=\n"
|
||||||
|
" credentials\n"
|
||||||
" --timeout=SEC Timeout in seconds\n"
|
" --timeout=SEC Timeout in seconds\n"
|
||||||
" --echo Do not mask input (useful for usernames)\n"
|
" --echo Do not mask input (useful for usernames)\n"
|
||||||
" --no-tty Ask question via agent even on TTY\n"
|
" --no-tty Ask question via agent even on TTY\n"
|
||||||
" --accept-cached Accept cached passwords\n"
|
" --accept-cached Accept cached passwords\n"
|
||||||
" --multiple List multiple passwords if available\n"
|
" --multiple List multiple passwords if available\n"
|
||||||
" --no-output Do not print password to standard output\n"
|
" --no-output Do not print password to standard output\n"
|
||||||
"\nSee the %s for details.\n",
|
"\nSee the %2$s for details.\n",
|
||||||
program_invocation_short_name,
|
program_invocation_short_name,
|
||||||
link);
|
link,
|
||||||
|
ansi_highlight(),
|
||||||
|
ansi_normal());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +71,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
ARG_KEYNAME,
|
ARG_KEYNAME,
|
||||||
ARG_NO_OUTPUT,
|
ARG_NO_OUTPUT,
|
||||||
ARG_VERSION,
|
ARG_VERSION,
|
||||||
|
ARG_CREDENTIAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
|
@ -78,6 +86,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
{ "id", required_argument, NULL, ARG_ID },
|
{ "id", required_argument, NULL, ARG_ID },
|
||||||
{ "keyname", required_argument, NULL, ARG_KEYNAME },
|
{ "keyname", required_argument, NULL, ARG_KEYNAME },
|
||||||
{ "no-output", no_argument, NULL, ARG_NO_OUTPUT },
|
{ "no-output", no_argument, NULL, ARG_NO_OUTPUT },
|
||||||
|
{ "credential", required_argument, NULL, ARG_CREDENTIAL },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -128,13 +137,17 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_KEYNAME:
|
case ARG_KEYNAME:
|
||||||
arg_keyname = optarg;
|
arg_key_name = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_NO_OUTPUT:
|
case ARG_NO_OUTPUT:
|
||||||
arg_no_output = true;
|
arg_no_output = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_CREDENTIAL:
|
||||||
|
arg_credential_name = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -170,7 +183,7 @@ static int run(int argc, char *argv[]) {
|
||||||
else
|
else
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
|
|
||||||
r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l);
|
r = ask_password_auto(arg_message, arg_icon, arg_id, arg_key_name, arg_credential_name ?: "password", timeout, arg_flags, &l);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to query password: %m");
|
return log_error_errno(r, "Failed to query password: %m");
|
||||||
|
|
||||||
|
|
54
src/basic/creds-util.c
Normal file
54
src/basic/creds-util.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "creds-util.h"
|
||||||
|
#include "fd-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "path-util.h"
|
||||||
|
|
||||||
|
bool credential_name_valid(const char *s) {
|
||||||
|
/* We want that credential names are both valid in filenames (since that's our primary way to pass
|
||||||
|
* them around) and as fdnames (which is how we might want to pass them around eventually) */
|
||||||
|
return filename_is_valid(s) && fdname_is_valid(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_credentials_dir(const char **ret) {
|
||||||
|
const char *e;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
e = secure_getenv("CREDENTIALS_DIRECTORY");
|
||||||
|
if (!e)
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
|
if (!path_is_absolute(e) || !path_is_normalized(e))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*ret = e;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_credential(const char *name, void **ret, size_t *ret_size) {
|
||||||
|
_cleanup_free_ char *fn = NULL;
|
||||||
|
const char *d;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
if (!credential_name_valid(name))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
r = get_credentials_dir(&d);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
fn = path_join(d, name);
|
||||||
|
if (!fn)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return read_full_file_full(
|
||||||
|
AT_FDCWD, fn,
|
||||||
|
UINT64_MAX, SIZE_MAX,
|
||||||
|
READ_FULL_FILE_SECURE,
|
||||||
|
NULL,
|
||||||
|
(char**) ret, ret_size);
|
||||||
|
}
|
12
src/basic/creds-util.h
Normal file
12
src/basic/creds-util.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
bool credential_name_valid(const char *s);
|
||||||
|
|
||||||
|
int get_credentials_dir(const char **ret);
|
||||||
|
|
||||||
|
int read_credential(const char *name, void **ret, size_t *ret_size);
|
|
@ -35,6 +35,8 @@ basic_sources = files('''
|
||||||
conf-files.h
|
conf-files.h
|
||||||
copy.c
|
copy.c
|
||||||
copy.h
|
copy.h
|
||||||
|
creds-util.c
|
||||||
|
creds-util.h
|
||||||
def.h
|
def.h
|
||||||
device-nodes.c
|
device-nodes.c
|
||||||
device-nodes.h
|
device-nodes.h
|
||||||
|
|
|
@ -1190,9 +1190,3 @@ bool prefixed_path_strv_contains(char **l, const char *path) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool credential_name_valid(const char *s) {
|
|
||||||
/* We want that credential names are both valid in filenames (since that's our primary way to pass
|
|
||||||
* them around) and as fdnames (which is how we might want to pass them around eventually) */
|
|
||||||
return filename_is_valid(s) && fdname_is_valid(s);
|
|
||||||
}
|
|
||||||
|
|
|
@ -183,5 +183,3 @@ static inline const char *empty_to_root(const char *path) {
|
||||||
|
|
||||||
bool path_strv_contains(char **l, const char *path);
|
bool path_strv_contains(char **l, const char *path);
|
||||||
bool prefixed_path_strv_contains(char **l, const char *path);
|
bool prefixed_path_strv_contains(char **l, const char *path);
|
||||||
|
|
||||||
bool credential_name_valid(const char *s);
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "cap-list.h"
|
#include "cap-list.h"
|
||||||
#include "capability-util.h"
|
#include "capability-util.h"
|
||||||
#include "cpu-set-util.h"
|
#include "cpu-set-util.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "dbus-execute.h"
|
#include "dbus-execute.h"
|
||||||
#include "dbus-util.h"
|
#include "dbus-util.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
|
|
|
@ -2564,6 +2564,7 @@ static int acquire_credentials(
|
||||||
ReadFullFileFlags flags = READ_FULL_FILE_SECURE;
|
ReadFullFileFlags flags = READ_FULL_FILE_SECURE;
|
||||||
_cleanup_(erase_and_freep) char *data = NULL;
|
_cleanup_(erase_and_freep) char *data = NULL;
|
||||||
_cleanup_free_ char *j = NULL, *bindname = NULL;
|
_cleanup_free_ char *j = NULL, *bindname = NULL;
|
||||||
|
bool missing_ok = true;
|
||||||
const char *source;
|
const char *source;
|
||||||
size_t size, add;
|
size_t size, add;
|
||||||
|
|
||||||
|
@ -2577,6 +2578,8 @@ static int acquire_credentials(
|
||||||
if (asprintf(&bindname, "@%" PRIx64"/unit/%s/%s", random_u64(), unit, *id) < 0)
|
if (asprintf(&bindname, "@%" PRIx64"/unit/%s/%s", random_u64(), unit, *id) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
missing_ok = false;
|
||||||
|
|
||||||
} else if (params->received_credentials) {
|
} else if (params->received_credentials) {
|
||||||
/* If this is a relative path, take it relative to the credentials we received
|
/* If this is a relative path, take it relative to the credentials we received
|
||||||
* ourselves. We don't support the AF_UNIX stuff in this mode, since we are operating
|
* ourselves. We don't support the AF_UNIX stuff in this mode, since we are operating
|
||||||
|
@ -2589,16 +2592,23 @@ static int acquire_credentials(
|
||||||
} else
|
} else
|
||||||
source = NULL;
|
source = NULL;
|
||||||
|
|
||||||
|
|
||||||
if (source)
|
if (source)
|
||||||
r = read_full_file_full(AT_FDCWD, source, UINT64_MAX, SIZE_MAX, flags, bindname, &data, &size);
|
r = read_full_file_full(AT_FDCWD, source, UINT64_MAX, SIZE_MAX, flags, bindname, &data, &size);
|
||||||
else
|
else
|
||||||
r = -ENOENT;
|
r = -ENOENT;
|
||||||
if (r == -ENOENT &&
|
if (r == -ENOENT && (missing_ok || faccessat(dfd, *id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)) {
|
||||||
faccessat(dfd, *id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) /* If the source file doesn't exist, but we already acquired the key otherwise, then don't fail */
|
/* Make a missing inherited credential non-fatal, let's just continue. After all apps
|
||||||
|
* will get clear errors if we don't pass such a missing credential on as they
|
||||||
|
* themselves will get ENOENT when trying to read them, which should not be much
|
||||||
|
* worse than when we handle the error here and make it fatal.
|
||||||
|
*
|
||||||
|
* Also, if the source file doesn't exist, but we already acquired the key otherwise,
|
||||||
|
* then don't fail either. */
|
||||||
|
log_debug_errno(r, "Couldn't read inherited credential '%s', skipping: %m", *fn);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_debug_errno(r, "Failed to read credential '%s': %m", *fn);
|
||||||
|
|
||||||
add = strlen(*id) + size;
|
add = strlen(*id) + size;
|
||||||
if (add > left)
|
if (add > left)
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
#include "sd-messages.h"
|
#include "sd-messages.h"
|
||||||
|
|
||||||
#include "af-list.h"
|
#include "af-list.h"
|
||||||
#include "alloc-util.h"
|
|
||||||
#include "all-units.h"
|
#include "all-units.h"
|
||||||
|
#include "alloc-util.h"
|
||||||
#include "bpf-firewall.h"
|
#include "bpf-firewall.h"
|
||||||
#include "bus-error.h"
|
#include "bus-error.h"
|
||||||
#include "bus-internal.h"
|
#include "bus-internal.h"
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include "conf-parser.h"
|
#include "conf-parser.h"
|
||||||
#include "core-varlink.h"
|
#include "core-varlink.h"
|
||||||
#include "cpu-set-util.h"
|
#include "cpu-set-util.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
#include "errno-list.h"
|
#include "errno-list.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
|
@ -4607,14 +4608,23 @@ int config_parse_load_credential(
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential name \"%s\" not valid, ignoring.", k);
|
log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential name \"%s\" not valid, ignoring.", k);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
r = unit_full_printf(u, p, &q);
|
|
||||||
if (r < 0) {
|
if (isempty(p)) {
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p);
|
/* If only one field field is specified take it as shortcut for inheriting a credential named
|
||||||
return 0;
|
* the same way from our parent */
|
||||||
}
|
q = strdup(k);
|
||||||
if (path_is_absolute(q) ? !path_is_normalized(q) : !credential_name_valid(q)) {
|
if (!q)
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Credential source \"%s\" not valid, ignoring.", q);
|
return log_oom();
|
||||||
return 0;
|
} else {
|
||||||
|
r = unit_full_printf(u, p, &q);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (path_is_absolute(q) ? !path_is_normalized(q) : !credential_name_valid(q)) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r, "Credential source \"%s\" not valid, ignoring.", q);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = strv_consume_pair(&context->load_credentials, TAKE_PTR(k), TAKE_PTR(q));
|
r = strv_consume_pair(&context->load_credentials, TAKE_PTR(k), TAKE_PTR(q));
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "clean-ipc.h"
|
#include "clean-ipc.h"
|
||||||
#include "clock-util.h"
|
#include "clock-util.h"
|
||||||
#include "core-varlink.h"
|
#include "core-varlink.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "dbus-job.h"
|
#include "dbus-job.h"
|
||||||
#include "dbus-manager.h"
|
#include "dbus-manager.h"
|
||||||
#include "dbus-unit.h"
|
#include "dbus-unit.h"
|
||||||
|
@ -49,8 +50,8 @@
|
||||||
#include "install.h"
|
#include "install.h"
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "locale-setup.h"
|
|
||||||
#include "load-fragment.h"
|
#include "load-fragment.h"
|
||||||
|
#include "locale-setup.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
|
@ -852,8 +853,8 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
e = secure_getenv("CREDENTIALS_DIRECTORY");
|
r = get_credentials_dir(&e);
|
||||||
if (e) {
|
if (r >= 0) {
|
||||||
m->received_credentials = strdup(e);
|
m->received_credentials = strdup(e);
|
||||||
if (!m->received_credentials)
|
if (!m->received_credentials)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -57,7 +57,7 @@ int enroll_password(
|
||||||
if (!question)
|
if (!question)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY, 0, &passwords);
|
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to query password: %m");
|
return log_error_errno(r, "Failed to query password: %m");
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ int enroll_password(
|
||||||
if (!question)
|
if (!question)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY, 0, &passwords2);
|
r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords2);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to query password: %m");
|
return log_error_errno(r, "Failed to query password: %m");
|
||||||
|
|
||||||
|
|
|
@ -417,7 +417,7 @@ static int prepare_luks(
|
||||||
"Too many attempts, giving up:");
|
"Too many attempts, giving up:");
|
||||||
|
|
||||||
r = ask_password_auto(
|
r = ask_password_auto(
|
||||||
question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY,
|
question, "drive-harddisk", id, "cryptenroll", "cryptenroll.passphrase", USEC_INFINITY,
|
||||||
ask_password_flags,
|
ask_password_flags,
|
||||||
&passwords);
|
&passwords);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -88,7 +88,7 @@ int acquire_fido2_key(
|
||||||
|
|
||||||
pins = strv_free_erase(pins);
|
pins = strv_free_erase(pins);
|
||||||
|
|
||||||
r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", until, flags, &pins);
|
r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", "cryptsetup.fido2-pin", until, flags, &pins);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to ask for user password: %m");
|
return log_error_errno(r, "Failed to ask for user password: %m");
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ static int pkcs11_callback(
|
||||||
data->friendly_name,
|
data->friendly_name,
|
||||||
"drive-harddisk",
|
"drive-harddisk",
|
||||||
"pkcs11-pin",
|
"pkcs11-pin",
|
||||||
|
"cryptsetup.pkcs11-pin",
|
||||||
data->until,
|
data->until,
|
||||||
NULL);
|
NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -545,7 +545,7 @@ static int get_password(
|
||||||
|
|
||||||
id = strjoina("cryptsetup:", disk_path);
|
id = strjoina("cryptsetup:", disk_path);
|
||||||
|
|
||||||
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until,
|
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until,
|
||||||
ASK_PASSWORD_PUSH_CACHE | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED),
|
ASK_PASSWORD_PUSH_CACHE | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED),
|
||||||
&passwords);
|
&passwords);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -561,7 +561,7 @@ static int get_password(
|
||||||
|
|
||||||
id = strjoina("cryptsetup-verification:", disk_path);
|
id = strjoina("cryptsetup-verification:", disk_path);
|
||||||
|
|
||||||
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE, &passwords2);
|
r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until, ASK_PASSWORD_PUSH_CACHE, &passwords2);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to query verification password: %m");
|
return log_error_errno(r, "Failed to query verification password: %m");
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "ask-password-api.h"
|
#include "ask-password-api.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "dissect-image.h"
|
#include "dissect-image.h"
|
||||||
#include "env-file.h"
|
#include "env-file.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
@ -43,8 +44,8 @@
|
||||||
static char *arg_root = NULL;
|
static char *arg_root = NULL;
|
||||||
static char *arg_image = NULL;
|
static char *arg_image = NULL;
|
||||||
static char *arg_locale = NULL; /* $LANG */
|
static char *arg_locale = NULL; /* $LANG */
|
||||||
static char *arg_keymap = NULL;
|
|
||||||
static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
|
static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
|
||||||
|
static char *arg_keymap = NULL;
|
||||||
static char *arg_timezone = NULL;
|
static char *arg_timezone = NULL;
|
||||||
static char *arg_hostname = NULL;
|
static char *arg_hostname = NULL;
|
||||||
static sd_id128_t arg_machine_id = {};
|
static sd_id128_t arg_machine_id = {};
|
||||||
|
@ -232,11 +233,29 @@ static bool locale_is_ok(const char *name) {
|
||||||
|
|
||||||
static int prompt_locale(void) {
|
static int prompt_locale(void) {
|
||||||
_cleanup_strv_free_ char **locales = NULL;
|
_cleanup_strv_free_ char **locales = NULL;
|
||||||
|
bool acquired_from_creds = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (arg_locale || arg_locale_messages)
|
if (arg_locale || arg_locale_messages)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = read_credential("firstboot.locale", (void**) &arg_locale, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to read credential firstboot.locale, ignoring: %m");
|
||||||
|
else
|
||||||
|
acquired_from_creds = true;
|
||||||
|
|
||||||
|
r = read_credential("firstboot.locale-messages", (void**) &arg_locale_messages, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to read credential firstboot.locale-message, ignoring: %m");
|
||||||
|
else
|
||||||
|
acquired_from_creds = true;
|
||||||
|
|
||||||
|
if (acquired_from_creds) {
|
||||||
|
log_debug("Acquired locale from credentials.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!arg_prompt_locale)
|
if (!arg_prompt_locale)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -336,6 +355,14 @@ static int prompt_keymap(void) {
|
||||||
if (arg_keymap)
|
if (arg_keymap)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = read_credential("firstboot.keymap", (void**) &arg_keymap, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to read credential firstboot.keymap, ignoring: %m");
|
||||||
|
else {
|
||||||
|
log_debug("Acquired keymap from credential.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!arg_prompt_keymap)
|
if (!arg_prompt_keymap)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -407,6 +434,14 @@ static int prompt_timezone(void) {
|
||||||
if (arg_timezone)
|
if (arg_timezone)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = read_credential("firstboot.timezone", (void**) &arg_timezone, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to read credential firstboot.timezone, ignoring: %m");
|
||||||
|
else {
|
||||||
|
log_debug("Acquired timezone from credential.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!arg_prompt_timezone)
|
if (!arg_prompt_timezone)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -558,6 +593,22 @@ static int prompt_root_password(void) {
|
||||||
if (arg_root_password)
|
if (arg_root_password)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = read_credential("passwd.hashed-password.root", (void**) &arg_root_password, NULL);
|
||||||
|
if (r == -ENOENT) {
|
||||||
|
r = read_credential("passwd.plaintext-password.root", (void**) &arg_root_password, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Couldn't read credential 'passwd.{hashed|plaintext}-password.root', ignoring: %m");
|
||||||
|
else {
|
||||||
|
arg_root_password_is_hashed = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (r < 0)
|
||||||
|
log_debug_errno(r, "Couldn't read credential 'passwd.hashed-password.root', ignoring: %m");
|
||||||
|
else {
|
||||||
|
arg_root_password_is_hashed = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!arg_prompt_root_password)
|
if (!arg_prompt_root_password)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -631,7 +682,18 @@ static int find_shell(const char *path, const char *root) {
|
||||||
static int prompt_root_shell(void) {
|
static int prompt_root_shell(void) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (arg_root_shell || !arg_prompt_root_shell)
|
if (arg_root_shell)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = read_credential("passwd.shell.root", (void**) &arg_root_shell, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to read credential passwd.shell.root, ignoring: %m");
|
||||||
|
else {
|
||||||
|
log_debug("Acquired root shell from credential.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arg_prompt_root_shell)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
print_welcome();
|
print_welcome();
|
||||||
|
|
|
@ -221,7 +221,7 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
|
||||||
user_name) < 0)
|
user_name) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &password);
|
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.password", USEC_INFINITY, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &password);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire password: %m");
|
return log_error_errno(r, "Failed to acquire password: %m");
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* We never cache or use cached PINs, since usually there are only very few attempts allowed before the PIN is blocked */
|
/* We never cache or use cached PINs, since usually there are only very few attempts allowed before the PIN is blocked */
|
||||||
r = ask_password_auto(question, "user-home", NULL, "token-pin", USEC_INFINITY, 0, &pin);
|
r = ask_password_auto(question, "user-home", NULL, "token-pin", "home.token-pin", USEC_INFINITY, 0, &pin);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire security token PIN: %m");
|
return log_error_errno(r, "Failed to acquire security token PIN: %m");
|
||||||
|
|
||||||
|
@ -1010,7 +1010,7 @@ static int acquire_new_password(
|
||||||
if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0)
|
if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, 0, &first);
|
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.new-password", USEC_INFINITY, 0, &first);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire password: %m");
|
return log_error_errno(r, "Failed to acquire password: %m");
|
||||||
|
|
||||||
|
@ -1018,7 +1018,7 @@ static int acquire_new_password(
|
||||||
if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0)
|
if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, 0, &second);
|
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.new-password", USEC_INFINITY, 0, &second);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire password: %m");
|
return log_error_errno(r, "Failed to acquire password: %m");
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "cgroup-util.h"
|
#include "cgroup-util.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
#include "cpu-set-util.h"
|
#include "cpu-set-util.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "dev-setup.h"
|
#include "dev-setup.h"
|
||||||
#include "discover-image.h"
|
#include "discover-image.h"
|
||||||
#include "dissect-image.h"
|
#include "dissect-image.h"
|
||||||
|
@ -1592,9 +1593,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
else {
|
else {
|
||||||
const char *e;
|
const char *e;
|
||||||
|
|
||||||
e = getenv("CREDENTIALS_DIRECTORY");
|
r = get_credentials_dir(&e);
|
||||||
if (!e)
|
if (r < 0)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential not available (no credentials passed at all): %s", word);
|
return log_error_errno(r, "Credential not available (no credentials passed at all): %s", word);
|
||||||
|
|
||||||
j = path_join(e, p);
|
j = path_join(e, p);
|
||||||
if (!j)
|
if (!j)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "ask-password-api.h"
|
#include "ask-password-api.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
@ -971,11 +972,33 @@ finish:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ask_password_credential(const char *credential_name, AskPasswordFlags flags, char ***ret) {
|
||||||
|
_cleanup_(erase_and_freep) char *buffer = NULL;
|
||||||
|
size_t size;
|
||||||
|
char **l;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(credential_name);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
r = read_credential(credential_name, (void**) &buffer, &size);
|
||||||
|
if (IN_SET(r, -ENXIO, -ENOENT)) /* No credentials passed or this credential not defined? */
|
||||||
|
return -ENOKEY;
|
||||||
|
|
||||||
|
l = strv_parse_nulstr(buffer, size);
|
||||||
|
if (!l)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*ret = l;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ask_password_auto(
|
int ask_password_auto(
|
||||||
const char *message,
|
const char *message,
|
||||||
const char *icon,
|
const char *icon,
|
||||||
const char *id,
|
const char *id, /* id in "ask-password" protocol */
|
||||||
const char *keyname,
|
const char *key_name, /* name in kernel keyring */
|
||||||
|
const char *credential_name, /* name in $CREDENTIALS_DIRECTORY directory */
|
||||||
usec_t until,
|
usec_t until,
|
||||||
AskPasswordFlags flags,
|
AskPasswordFlags flags,
|
||||||
char ***ret) {
|
char ***ret) {
|
||||||
|
@ -984,20 +1007,26 @@ int ask_password_auto(
|
||||||
|
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
|
if (!(flags & ASK_PASSWORD_NO_CREDENTIAL) && credential_name) {
|
||||||
|
r = ask_password_credential(credential_name, flags, ret);
|
||||||
|
if (r != -ENOKEY)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if ((flags & ASK_PASSWORD_ACCEPT_CACHED) &&
|
if ((flags & ASK_PASSWORD_ACCEPT_CACHED) &&
|
||||||
keyname &&
|
key_name &&
|
||||||
((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
|
((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
|
||||||
(flags & ASK_PASSWORD_NO_AGENT)) {
|
(flags & ASK_PASSWORD_NO_AGENT)) {
|
||||||
r = ask_password_keyring(keyname, flags, ret);
|
r = ask_password_keyring(key_name, flags, ret);
|
||||||
if (r != -ENOKEY)
|
if (r != -ENOKEY)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
|
if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
|
||||||
return ask_password_tty(-1, message, keyname, until, flags, NULL, ret);
|
return ask_password_tty(-1, message, key_name, until, flags, NULL, ret);
|
||||||
|
|
||||||
if (!(flags & ASK_PASSWORD_NO_AGENT))
|
if (!(flags & ASK_PASSWORD_NO_AGENT))
|
||||||
return ask_password_agent(message, icon, id, keyname, until, flags, ret);
|
return ask_password_agent(message, icon, id, key_name, until, flags, ret);
|
||||||
|
|
||||||
return -EUNATCH;
|
return -EUNATCH;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,17 @@
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
|
|
||||||
typedef enum AskPasswordFlags {
|
typedef enum AskPasswordFlags {
|
||||||
ASK_PASSWORD_ACCEPT_CACHED = 1 << 0,
|
ASK_PASSWORD_ACCEPT_CACHED = 1 << 0, /* read from kernel keyring */
|
||||||
ASK_PASSWORD_PUSH_CACHE = 1 << 1,
|
ASK_PASSWORD_PUSH_CACHE = 1 << 1, /* write to kernel keyring after getting password from elsewhere */
|
||||||
ASK_PASSWORD_ECHO = 1 << 2, /* show the password literally while reading, instead of "*" */
|
ASK_PASSWORD_ECHO = 1 << 2, /* show the password literally while reading, instead of "*" */
|
||||||
ASK_PASSWORD_SILENT = 1 << 3, /* do no show any password at all while reading */
|
ASK_PASSWORD_SILENT = 1 << 3, /* do no show any password at all while reading */
|
||||||
ASK_PASSWORD_NO_TTY = 1 << 4,
|
ASK_PASSWORD_NO_TTY = 1 << 4, /* never ask for password on tty */
|
||||||
ASK_PASSWORD_NO_AGENT = 1 << 5,
|
ASK_PASSWORD_NO_AGENT = 1 << 5, /* never ask for password via agent */
|
||||||
ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */
|
ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */
|
||||||
|
ASK_PASSWORD_NO_CREDENTIAL = 1 << 7, /* never use $CREDENTIALS_DIRECTORY data */
|
||||||
} AskPasswordFlags;
|
} AskPasswordFlags;
|
||||||
|
|
||||||
int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
int ask_password_tty(int tty_fd, const char *message, const char *key_name, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
||||||
int ask_password_plymouth(const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
int ask_password_plymouth(const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
||||||
int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
|
int ask_password_agent(const char *message, const char *icon, const char *id, const char *key_name, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||||
int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
|
int ask_password_auto(const char *message, const char *icon, const char *id, const char *key_name, const char *credential_name, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||||
|
|
|
@ -2077,7 +2077,7 @@ int dissected_image_decrypt_interactively(
|
||||||
|
|
||||||
z = strv_free(z);
|
z = strv_free(z);
|
||||||
|
|
||||||
r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z);
|
r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", "dissect.passphrase", USEC_INFINITY, 0, &z);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to query for passphrase: %m");
|
return log_error_errno(r, "Failed to query for passphrase: %m");
|
||||||
|
|
||||||
|
|
|
@ -566,7 +566,7 @@ int fido2_generate_hmac_hash(
|
||||||
if (!has_client_pin)
|
if (!has_client_pin)
|
||||||
log_warning("Weird, device asked for client PIN, but does not advertise it as feature. Ignoring.");
|
log_warning("Weird, device asked for client PIN, but does not advertise it as feature. Ignoring.");
|
||||||
|
|
||||||
r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", USEC_INFINITY, 0, &pin);
|
r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", "fido2-pin", USEC_INFINITY, 0, &pin);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire user PIN: %m");
|
return log_error_errno(r, "Failed to acquire user PIN: %m");
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,8 @@ int pkcs11_token_login(
|
||||||
const CK_TOKEN_INFO *token_info,
|
const CK_TOKEN_INFO *token_info,
|
||||||
const char *friendly_name,
|
const char *friendly_name,
|
||||||
const char *icon_name,
|
const char *icon_name,
|
||||||
const char *keyname,
|
const char *key_name,
|
||||||
|
const char *credential_name,
|
||||||
usec_t until,
|
usec_t until,
|
||||||
char **ret_used_pin) {
|
char **ret_used_pin) {
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ int pkcs11_token_login(
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */
|
/* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */
|
||||||
r = ask_password_auto(text, icon_name, id, keyname, until, 0, &passwords);
|
r = ask_password_auto(text, icon_name, id, key_name, credential_name, until, 0, &passwords);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label);
|
return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label);
|
||||||
}
|
}
|
||||||
|
@ -959,7 +960,7 @@ static int pkcs11_acquire_certificate_callback(
|
||||||
|
|
||||||
/* Called for every token matching our URI */
|
/* Called for every token matching our URI */
|
||||||
|
|
||||||
r = pkcs11_token_login(m, session, slot_id, token_info, data->askpw_friendly_name, data->askpw_icon_name, "pkcs11-pin", UINT64_MAX, &pin_used);
|
r = pkcs11_token_login(m, session, slot_id, token_info, data->askpw_friendly_name, data->askpw_icon_name, "pkcs11-pin", "pkcs11-pin", UINT64_MAX, &pin_used);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ char *pkcs11_token_label(const CK_TOKEN_INFO *token_info);
|
||||||
char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info);
|
char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info);
|
||||||
char *pkcs11_token_model(const CK_TOKEN_INFO *token_info);
|
char *pkcs11_token_model(const CK_TOKEN_INFO *token_info);
|
||||||
|
|
||||||
int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *keyname, usec_t until, char **ret_used_pin);
|
int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, char **ret_used_pin);
|
||||||
|
|
||||||
int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
|
int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
|
||||||
#if HAVE_OPENSSL
|
#if HAVE_OPENSSL
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "conf-files.h"
|
#include "conf-files.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "dissect-image.h"
|
#include "dissect-image.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
@ -13,7 +14,9 @@
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
|
#include "libcrypt-util.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
|
#include "memory-util.h"
|
||||||
#include "mount-util.h"
|
#include "mount-util.h"
|
||||||
#include "nscd-flush.h"
|
#include "nscd-flush.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
|
@ -429,6 +432,8 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
|
||||||
}
|
}
|
||||||
|
|
||||||
ORDERED_HASHMAP_FOREACH(i, todo_uids) {
|
ORDERED_HASHMAP_FOREACH(i, todo_uids) {
|
||||||
|
_cleanup_free_ char *creds_shell = NULL, *cn = NULL;
|
||||||
|
|
||||||
struct passwd n = {
|
struct passwd n = {
|
||||||
.pw_name = i->name,
|
.pw_name = i->name,
|
||||||
.pw_uid = i->uid,
|
.pw_uid = i->uid,
|
||||||
|
@ -446,6 +451,17 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
|
||||||
.pw_shell = i->shell ?: (char*) default_shell(i->uid),
|
.pw_shell = i->shell ?: (char*) default_shell(i->uid),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Try to pick up the shell for this account via the credentials logic */
|
||||||
|
cn = strjoin("passwd.shell.", i->name);
|
||||||
|
if (!cn)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = read_credential(cn, (void**) &creds_shell, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
|
||||||
|
else
|
||||||
|
n.pw_shell = creds_shell;
|
||||||
|
|
||||||
r = putpwent_sane(&n, passwd);
|
r = putpwent_sane(&n, passwd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -530,6 +546,9 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
|
||||||
}
|
}
|
||||||
|
|
||||||
ORDERED_HASHMAP_FOREACH(i, todo_uids) {
|
ORDERED_HASHMAP_FOREACH(i, todo_uids) {
|
||||||
|
_cleanup_(erase_and_freep) char *creds_password = NULL;
|
||||||
|
_cleanup_free_ char *cn = NULL;
|
||||||
|
|
||||||
struct spwd n = {
|
struct spwd n = {
|
||||||
.sp_namp = i->name,
|
.sp_namp = i->name,
|
||||||
.sp_pwdp = (char*) "!*", /* lock this password, and make it invalid */
|
.sp_pwdp = (char*) "!*", /* lock this password, and make it invalid */
|
||||||
|
@ -542,6 +561,34 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
|
||||||
.sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
|
.sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Try to pick up the password for this account via the credentials logic */
|
||||||
|
cn = strjoin("passwd.hashed-password.", i->name);
|
||||||
|
if (!cn)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = read_credential(cn, (void**) &creds_password, NULL);
|
||||||
|
if (r == -ENOENT) {
|
||||||
|
_cleanup_(erase_and_freep) char *plaintext_password = NULL;
|
||||||
|
|
||||||
|
free(cn);
|
||||||
|
cn = strjoin("passwd.plaintext-password.", i->name);
|
||||||
|
if (!cn)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = read_credential(cn, (void**) &plaintext_password, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
|
||||||
|
else {
|
||||||
|
r = hash_password(plaintext_password, &creds_password);
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to hash password: %m");
|
||||||
|
}
|
||||||
|
} else if (r < 0)
|
||||||
|
log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
|
||||||
|
|
||||||
|
if (creds_password)
|
||||||
|
n.sp_pwdp = creds_password;
|
||||||
|
|
||||||
r = putspent_sane(&n, shadow);
|
r = putspent_sane(&n, shadow);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -13,7 +13,7 @@ Documentation=man:systemd-firstboot(1)
|
||||||
DefaultDependencies=no
|
DefaultDependencies=no
|
||||||
Conflicts=shutdown.target
|
Conflicts=shutdown.target
|
||||||
After=systemd-remount-fs.service
|
After=systemd-remount-fs.service
|
||||||
Before=systemd-sysusers.service sysinit.target first-boot-complete.target shutdown.target
|
Before=systemd-sysusers.service systemd-vconsole-setup.service sysinit.target first-boot-complete.target shutdown.target
|
||||||
Wants=first-boot-complete.target
|
Wants=first-boot-complete.target
|
||||||
ConditionPathIsReadWrite=/etc
|
ConditionPathIsReadWrite=/etc
|
||||||
ConditionFirstBoot=yes
|
ConditionFirstBoot=yes
|
||||||
|
@ -25,3 +25,14 @@ ExecStart=systemd-firstboot --prompt-locale --prompt-timezone --prompt-root-pass
|
||||||
StandardOutput=tty
|
StandardOutput=tty
|
||||||
StandardInput=tty
|
StandardInput=tty
|
||||||
StandardError=tty
|
StandardError=tty
|
||||||
|
|
||||||
|
# Optionally, pick up basic fields from credentials passed to the service
|
||||||
|
# manager. This is useful for importing this data from nspawn's
|
||||||
|
# --set-credential= switch.
|
||||||
|
LoadCredential=passwd.hashed-password.root
|
||||||
|
LoadCredential=passwd.plaintext-password.root
|
||||||
|
LoadCredential=passwd.shell.root
|
||||||
|
LoadCredential=firstboot.locale
|
||||||
|
LoadCredential=firstboot.locale-messages
|
||||||
|
LoadCredential=firstboot.keymap
|
||||||
|
LoadCredential=firstboot.timezone
|
||||||
|
|
|
@ -21,3 +21,10 @@ Type=oneshot
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
ExecStart=systemd-sysusers
|
ExecStart=systemd-sysusers
|
||||||
TimeoutSec=90s
|
TimeoutSec=90s
|
||||||
|
|
||||||
|
# Optionally, pick up a root password and shell for the root user from a
|
||||||
|
# credential passed to the service manager. This is useful for importing this
|
||||||
|
# data from nspawn's --set-credential= switch.
|
||||||
|
LoadCredential=passwd.hashed-password.root
|
||||||
|
LoadCredential=passwd.plaintext-password.root
|
||||||
|
LoadCredential=passwd.shell.root
|
||||||
|
|
Loading…
Reference in a new issue