summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2020-05-25 19:24:07 +0200
committerDaan De Meyer <daan.j.demeyer@gmail.com>2020-05-27 18:54:26 +0200
commit676339a1910a35a31f79d7bb00a6f603f18f4aa8 (patch)
tree34b900b2575a673b6c5ace8e2377df398ad0cb53
parentRemove systemd-firstboot --force entry from TODO (diff)
downloadsystemd-676339a1910a35a31f79d7bb00a6f603f18f4aa8.tar.xz
systemd-676339a1910a35a31f79d7bb00a6f603f18f4aa8.zip
firstboot: Add --root-password-hashed option
-rw-r--r--man/systemd-firstboot.xml20
-rw-r--r--src/firstboot/firstboot.c139
2 files changed, 90 insertions, 69 deletions
diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml
index cf87249c4d..88d90e405a 100644
--- a/man/systemd-firstboot.xml
+++ b/man/systemd-firstboot.xml
@@ -150,18 +150,18 @@
<varlistentry>
<term><option>--root-password=<replaceable>PASSWORD</replaceable></option></term>
<term><option>--root-password-file=<replaceable>PATH</replaceable></option></term>
+ <term><option>--root-password-hashed=<replaceable>HASHED_PASSWORD</replaceable></option></term>
- <listitem><para>Sets the password of the system's root user.
- This creates a
+ <listitem><para>Sets the password of the system's root user. This creates a
<citerefentry project='die-net'><refentrytitle>shadow</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- file. This setting exists in two forms:
- <option>--root-password=</option> accepts the password to set
- directly on the command line, and
- <option>--root-password-file=</option> reads it from a file.
- Note that it is not recommended to specify passwords on the
- command line, as other users might be able to see them simply
- by invoking
- <citerefentry project='die-net'><refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para></listitem>
+ file. This setting exists in three forms: <option>--root-password=</option> accepts the password to
+ set directly on the command line, <option>--root-password-file=</option> reads it from a file and
+ <option>--root-password-hashed=</option> accepts an already hashed password on the command line. See
+ <citerefentry project='die-net'><refentrytitle>shadow</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more information on the format of the hashed password. Note that it is not recommended to specify
+ plaintext passwords on the command line, as other users might be able to see them simply by invoking
+ <citerefentry project='die-net'><refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ </para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index b9b7512805..b3a416af18 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -53,6 +53,7 @@ static bool arg_copy_timezone = false;
static bool arg_copy_root_password = false;
static bool arg_force = false;
static bool arg_delete_root_password = false;
+static bool arg_root_password_is_hashed = false;
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_locale, freep);
@@ -718,7 +719,6 @@ static int write_root_shadow(const char *shadow_path, const char *hashed_passwor
}
static int process_root_password(void) {
- _cleanup_free_ char *salt = NULL;
_cleanup_close_ int lock = -1;
struct crypt_data cd = {};
const char *hashed_password;
@@ -779,15 +779,22 @@ static int process_root_password(void) {
if (!arg_root_password)
return 0;
- r = make_salt(&salt);
- if (r < 0)
- return log_error_errno(r, "Failed to get salt: %m");
+ if (arg_root_password_is_hashed)
+ hashed_password = arg_root_password;
+ else {
+ _cleanup_free_ char *salt = NULL;
+ /* hashed_password points inside cd after crypt_r returns so cd has function scope. */
+
+ r = make_salt(&salt);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get salt: %m");
- errno = 0;
- hashed_password = crypt_r(arg_root_password, salt, &cd);
- if (!hashed_password)
- return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno,
- "Failed to encrypt password: %m");
+ errno = 0;
+ hashed_password = crypt_r(arg_root_password, salt, &cd);
+ if (!hashed_password)
+ return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno,
+ "Failed to encrypt password: %m");
+ }
r = write_root_shadow(etc_shadow, hashed_password);
if (r < 0)
@@ -807,31 +814,32 @@ static int help(void) {
printf("%s [OPTIONS...]\n\n"
"Configures basic settings of the system.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --root=PATH Operate on an alternate filesystem root\n"
- " --locale=LOCALE Set primary locale (LANG=)\n"
- " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n"
- " --keymap=KEYMAP Set keymap\n"
- " --timezone=TIMEZONE Set timezone\n"
- " --hostname=NAME Set hostname\n"
- " --machine-ID=ID Set machine ID\n"
- " --root-password=PASSWORD Set root password\n"
- " --root-password-file=FILE Set root password from file\n"
- " --prompt-locale Prompt the user for locale settings\n"
- " --prompt-keymap Prompt the user for keymap settings\n"
- " --prompt-timezone Prompt the user for timezone\n"
- " --prompt-hostname Prompt the user for hostname\n"
- " --prompt-root-password Prompt the user for root password\n"
- " --prompt Prompt for all of the above\n"
- " --copy-locale Copy locale from host\n"
- " --copy-keymap Copy keymap from host\n"
- " --copy-timezone Copy timezone from host\n"
- " --copy-root-password Copy root password from host\n"
- " --copy Copy locale, keymap, timezone, root password\n"
- " --setup-machine-id Generate a new random machine ID\n"
- " --force Overwrite existing files\n"
- " --delete-root-password Delete root password\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --root=PATH Operate on an alternate filesystem root\n"
+ " --locale=LOCALE Set primary locale (LANG=)\n"
+ " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n"
+ " --keymap=KEYMAP Set keymap\n"
+ " --timezone=TIMEZONE Set timezone\n"
+ " --hostname=NAME Set hostname\n"
+ " --machine-ID=ID Set machine ID\n"
+ " --root-password=PASSWORD Set root password from plaintext password\n"
+ " --root-password-file=FILE Set root password from file\n"
+ " --root-password-hashed=HASHED_PASSWORD Set root password from hashed password\n"
+ " --prompt-locale Prompt the user for locale settings\n"
+ " --prompt-keymap Prompt the user for keymap settings\n"
+ " --prompt-timezone Prompt the user for timezone\n"
+ " --prompt-hostname Prompt the user for hostname\n"
+ " --prompt-root-password Prompt the user for root password\n"
+ " --prompt Prompt for all of the above\n"
+ " --copy-locale Copy locale from host\n"
+ " --copy-keymap Copy keymap from host\n"
+ " --copy-timezone Copy timezone from host\n"
+ " --copy-root-password Copy root password from host\n"
+ " --copy Copy locale, keymap, timezone, root password\n"
+ " --setup-machine-id Generate a new random machine ID\n"
+ " --force Overwrite existing files\n"
+ " --delete-root-password Delete root password\n"
"\nSee the %s for details.\n"
, program_invocation_short_name
, link
@@ -853,6 +861,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_MACHINE_ID,
ARG_ROOT_PASSWORD,
ARG_ROOT_PASSWORD_FILE,
+ ARG_ROOT_PASSWORD_HASHED,
ARG_PROMPT,
ARG_PROMPT_LOCALE,
ARG_PROMPT_KEYMAP,
@@ -870,31 +879,32 @@ static int parse_argv(int argc, char *argv[]) {
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "root", required_argument, NULL, ARG_ROOT },
- { "locale", required_argument, NULL, ARG_LOCALE },
- { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES },
- { "keymap", required_argument, NULL, ARG_KEYMAP },
- { "timezone", required_argument, NULL, ARG_TIMEZONE },
- { "hostname", required_argument, NULL, ARG_HOSTNAME },
- { "machine-id", required_argument, NULL, ARG_MACHINE_ID },
- { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD },
- { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE },
- { "prompt", no_argument, NULL, ARG_PROMPT },
- { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE },
- { "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP },
- { "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE },
- { "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME },
- { "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD },
- { "copy", no_argument, NULL, ARG_COPY },
- { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE },
- { "copy-keymap", no_argument, NULL, ARG_COPY_KEYMAP },
- { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE },
- { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD },
- { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID },
- { "force", no_argument, NULL, ARG_FORCE },
- { "delete-root-password", no_argument, NULL, ARG_DELETE_ROOT_PASSWORD },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "root", required_argument, NULL, ARG_ROOT },
+ { "locale", required_argument, NULL, ARG_LOCALE },
+ { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES },
+ { "keymap", required_argument, NULL, ARG_KEYMAP },
+ { "timezone", required_argument, NULL, ARG_TIMEZONE },
+ { "hostname", required_argument, NULL, ARG_HOSTNAME },
+ { "machine-id", required_argument, NULL, ARG_MACHINE_ID },
+ { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD },
+ { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE },
+ { "root-password-hashed", required_argument, NULL, ARG_ROOT_PASSWORD_HASHED },
+ { "prompt", no_argument, NULL, ARG_PROMPT },
+ { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE },
+ { "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP },
+ { "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE },
+ { "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME },
+ { "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD },
+ { "copy", no_argument, NULL, ARG_COPY },
+ { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE },
+ { "copy-keymap", no_argument, NULL, ARG_COPY_KEYMAP },
+ { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE },
+ { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD },
+ { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID },
+ { "force", no_argument, NULL, ARG_FORCE },
+ { "delete-root-password", no_argument, NULL, ARG_DELETE_ROOT_PASSWORD },
{}
};
@@ -959,6 +969,8 @@ static int parse_argv(int argc, char *argv[]) {
r = free_and_strdup(&arg_root_password, optarg);
if (r < 0)
return log_oom();
+
+ arg_root_password_is_hashed = false;
break;
case ARG_ROOT_PASSWORD_FILE:
@@ -968,6 +980,15 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to read %s: %m", optarg);
+ arg_root_password_is_hashed = false;
+ break;
+
+ case ARG_ROOT_PASSWORD_HASHED:
+ r = free_and_strdup(&arg_root_password, optarg);
+ if (r < 0)
+ return log_oom();
+
+ arg_root_password_is_hashed = true;
break;
case ARG_HOSTNAME: