Merge pull request #15893 from DaanDeMeyer/firstboot-overwrite

systemd-firstboot: Add --force, --delete-root-password and --root-password-is-hashed options
This commit is contained in:
Lennart Poettering
2020-05-27 22:51:02 +02:00
committed by GitHub
6 changed files with 353 additions and 136 deletions
-2
View File
@@ -256,8 +256,6 @@ Features:
* systemd-firstboot: teach it dissector magic, so that you can point it to some
disk image and it will just set everything in it all behind the scenes.
* systemd-firstboot: add --force mode that replaces existing configuration.
* We should probably replace /var/log/README, /etc/rc.d/README with symlinks
that are linked to these places instead of copied. After all they are
constant vendor data.
+36 -10
View File
@@ -150,18 +150,27 @@
<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>
<term><option>--kernel-command-line=<replaceable>CMDLINE</replaceable></option></term>
<listitem><para>Sets the system's kernel command line. This controls the
<filename>/etc/kernel/cmdline</filename> file which is used by
<citerefentry><refentrytitle>kernel-install</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
@@ -221,6 +230,23 @@
<option>--root=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--force</option></term>
<listitem><para>systemd-firstboot doesn't modify existing files unless <option>--force</option>
is specified. For modifications to <filename>/etc/passwd</filename> and
<filename>/etc/shadow</filename>, systemd-firstboot only modifies the entry of the
<literal>root</literal> user instead of overwriting the entire file.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--delete-root-password</option></term>
<listitem><para>Removes the password of the system's root user, enabling login as root without a
password unless the root account is locked. Note that this is extremely insecure and hence this
option should not be used lightly.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
+22
View File
@@ -1187,3 +1187,25 @@ int warn_file_is_world_accessible(const char *filename, struct stat *st, const c
filename, st->st_mode & 07777);
return 0;
}
int sync_rights(int from, int to) {
struct stat st;
if (fstat(from, &st) < 0)
return -errno;
return fchmod_and_chown(to, st.st_mode & 07777, st.st_uid, st.st_gid);
}
int rename_and_apply_smack_floor_label(const char *from, const char *to) {
int r = 0;
if (rename(from, to) < 0)
return -errno;
#ifdef SMACK_RUN_LABEL
r = mac_smack_apply(to, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL);
if (r < 0)
return r;
#endif
return r;
}
+4
View File
@@ -106,3 +106,7 @@ static inline int read_nul_string(FILE *f, size_t limit, char **ret) {
int safe_fgetc(FILE *f, char *ret);
int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line);
int sync_rights(int from, int to);
int rename_and_apply_smack_floor_label(const char *temp_path, const char *dest_path);
+283 -94
View File
@@ -30,6 +30,7 @@
#include "strv.h"
#include "terminal-util.h"
#include "time-util.h"
#include "tmpfile-util-label.h"
#include "umask-util.h"
#include "user-util.h"
@@ -41,6 +42,7 @@ static char *arg_timezone = NULL;
static char *arg_hostname = NULL;
static sd_id128_t arg_machine_id = {};
static char *arg_root_password = NULL;
static char *arg_kernel_cmdline = NULL;
static bool arg_prompt_locale = false;
static bool arg_prompt_keymap = false;
static bool arg_prompt_timezone = false;
@@ -50,6 +52,9 @@ static bool arg_copy_locale = false;
static bool arg_copy_keymap = false;
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);
@@ -273,7 +278,7 @@ static int process_locale(void) {
int r;
etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf");
if (laccess(etc_localeconf, F_OK) >= 0)
if (laccess(etc_localeconf, F_OK) >= 0 && !arg_force)
return 0;
if (arg_copy_locale && arg_root) {
@@ -340,7 +345,7 @@ static int process_keymap(void) {
int r;
etc_vconsoleconf = prefix_roota(arg_root, "/etc/vconsole.conf");
if (laccess(etc_vconsoleconf, F_OK) >= 0)
if (laccess(etc_vconsoleconf, F_OK) >= 0 && !arg_force)
return 0;
if (arg_copy_keymap && arg_root) {
@@ -412,7 +417,7 @@ static int process_timezone(void) {
int r;
etc_localtime = prefix_roota(arg_root, "/etc/localtime");
if (laccess(etc_localtime, F_OK) >= 0)
if (laccess(etc_localtime, F_OK) >= 0 && !arg_force)
return 0;
if (arg_copy_timezone && arg_root) {
@@ -492,7 +497,7 @@ static int process_hostname(void) {
int r;
etc_hostname = prefix_roota(arg_root, "/etc/hostname");
if (laccess(etc_hostname, F_OK) >= 0)
if (laccess(etc_hostname, F_OK) >= 0 && !arg_force)
return 0;
r = prompt_hostname();
@@ -503,7 +508,8 @@ static int process_hostname(void) {
return 0;
r = write_string_file(etc_hostname, arg_hostname,
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755);
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 |
(arg_force ? WRITE_STRING_FILE_ATOMIC : 0));
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_hostname);
@@ -517,14 +523,15 @@ static int process_machine_id(void) {
int r;
etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
if (laccess(etc_machine_id, F_OK) >= 0)
if (laccess(etc_machine_id, F_OK) >= 0 && !arg_force)
return 0;
if (sd_id128_is_null(arg_machine_id))
return 0;
r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id),
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755);
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 |
(arg_force ? WRITE_STRING_FILE_ATOMIC : 0));
if (r < 0)
return log_error_errno(r, "Failed to write machine id: %m");
@@ -533,7 +540,7 @@ static int process_machine_id(void) {
}
static int prompt_root_password(void) {
const char *msg1, *msg2, *etc_shadow;
const char *msg1, *msg2;
int r;
if (arg_root_password)
@@ -542,10 +549,6 @@ static int prompt_root_password(void) {
if (!arg_prompt_root_password)
return 0;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
if (laccess(etc_shadow, F_OK) >= 0)
return 0;
print_welcome();
putchar('\n');
@@ -586,45 +589,145 @@ static int prompt_root_password(void) {
return 0;
}
static int write_root_shadow(const char *path, const struct spwd *p) {
_cleanup_fclose_ FILE *f = NULL;
static int write_root_passwd(const char *passwd_path, const char *password) {
_cleanup_fclose_ FILE *original = NULL, *passwd = NULL;
_cleanup_(unlink_and_freep) char *passwd_tmp = NULL;
int r;
assert(path);
assert(p);
RUN_WITH_UMASK(0777)
f = fopen(path, "wex");
if (!f)
return -errno;
r = putspent_sane(p, f);
r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp);
if (r < 0)
return r;
return fflush_sync_and_check(f);
original = fopen(passwd_path, "re");
if (original) {
struct passwd *i;
r = sync_rights(fileno(original), fileno(passwd));
if (r < 0)
return r;
while ((r = fgetpwent_sane(original, &i)) > 0) {
if (streq(i->pw_name, "root"))
i->pw_passwd = (char *) password;
r = putpwent_sane(i, passwd);
if (r < 0)
return r;
}
if (r < 0)
return r;
} else {
struct passwd root = {
.pw_name = (char *) "root",
.pw_passwd = (char *) password,
.pw_uid = 0,
.pw_gid = 0,
.pw_gecos = (char *) "Super User",
.pw_dir = (char *) "/root",
.pw_shell = (char *) "/bin/sh",
};
if (errno != ENOENT)
return -errno;
r = fchmod(fileno(passwd), 0000);
if (r < 0)
return -errno;
r = putpwent_sane(&root, passwd);
if (r < 0)
return r;
}
r = fflush_sync_and_check(passwd);
if (r < 0)
return r;
r = rename_and_apply_smack_floor_label(passwd_tmp, passwd_path);
if (r < 0)
return r;
return 0;
}
static int write_root_shadow(const char *shadow_path, const char *hashed_password) {
_cleanup_fclose_ FILE *original = NULL, *shadow = NULL;
_cleanup_(unlink_and_freep) char *shadow_tmp = NULL;
int r;
r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp);
if (r < 0)
return r;
original = fopen(shadow_path, "re");
if (original) {
struct spwd *i;
r = sync_rights(fileno(original), fileno(shadow));
if (r < 0)
return r;
while ((r = fgetspent_sane(original, &i)) > 0) {
if (streq(i->sp_namp, "root")) {
i->sp_pwdp = (char *) hashed_password;
i->sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
}
r = putspent_sane(i, shadow);
if (r < 0)
return r;
}
if (r < 0)
return r;
} else {
struct spwd root = {
.sp_namp = (char*) "root",
.sp_pwdp = (char *) hashed_password,
.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY),
.sp_min = -1,
.sp_max = -1,
.sp_warn = -1,
.sp_inact = -1,
.sp_expire = -1,
.sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
};
if (errno != ENOENT)
return -errno;
r = fchmod(fileno(shadow), 0000);
if (r < 0)
return -errno;
r = putspent_sane(&root, shadow);
if (r < 0)
return r;
}
r = fflush_sync_and_check(shadow);
if (r < 0)
return r;
r = rename_and_apply_smack_floor_label(shadow_tmp, shadow_path);
if (r < 0)
return r;
return 0;
}
static int process_root_password(void) {
struct spwd item = {
.sp_namp = (char*) "root",
.sp_min = -1,
.sp_max = -1,
.sp_warn = -1,
.sp_inact = -1,
.sp_expire = -1,
.sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
};
_cleanup_free_ char *salt = NULL;
_cleanup_close_ int lock = -1;
struct crypt_data cd = {};
const char *hashed_password;
const char *etc_shadow;
int r;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
if (laccess(etc_shadow, F_OK) >= 0)
if (laccess(etc_shadow, F_OK) >= 0 && !arg_force)
return 0;
(void) mkdir_parents(etc_shadow, 0755);
@@ -633,6 +736,21 @@ static int process_root_password(void) {
if (lock < 0)
return log_error_errno(lock, "Failed to take a lock: %m");
if (arg_delete_root_password) {
const char *etc_passwd;
/* Mixing alloca() and other stuff that touches the stack in one expression is not portable. */
etc_passwd = prefix_roota(arg_root, "/etc/passwd");
r = write_root_passwd(etc_passwd, "");
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_passwd);
log_info("%s written", etc_passwd);
return 0;
}
if (arg_copy_root_password && arg_root) {
struct spwd *p;
@@ -646,7 +764,7 @@ static int process_root_password(void) {
return log_error_errno(errno, "Failed to find shadow entry for root: %m");
}
r = write_root_shadow(etc_shadow, p);
r = write_root_shadow(etc_shadow, p->sp_pwdp);
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_shadow);
@@ -662,19 +780,24 @@ 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. */
errno = 0;
item.sp_pwdp = crypt_r(arg_root_password, salt, &cd);
if (!item.sp_pwdp)
return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno,
"Failed to encrypt password: %m");
r = make_salt(&salt);
if (r < 0)
return log_error_errno(r, "Failed to get salt: %m");
item.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
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, &item);
r = write_root_shadow(etc_shadow, hashed_password);
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_shadow);
@@ -682,6 +805,27 @@ static int process_root_password(void) {
return 0;
}
static int process_kernel_cmdline(void) {
const char *etc_kernel_cmdline;
int r;
etc_kernel_cmdline = prefix_roota(arg_root, "/etc/kernel/cmdline");
if (laccess(etc_kernel_cmdline, F_OK) >= 0 && !arg_force)
return 0;
if (!arg_kernel_cmdline)
return 0;
r = write_string_file(etc_kernel_cmdline, arg_kernel_cmdline,
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 |
(arg_force ? WRITE_STRING_FILE_ATOMIC : 0));
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_kernel_cmdline);
log_info("%s written.", etc_kernel_cmdline);
return 0;
}
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@@ -692,29 +836,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"
" -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
@@ -736,6 +883,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_MACHINE_ID,
ARG_ROOT_PASSWORD,
ARG_ROOT_PASSWORD_FILE,
ARG_ROOT_PASSWORD_HASHED,
ARG_KERNEL_COMMAND_LINE,
ARG_PROMPT,
ARG_PROMPT_LOCALE,
ARG_PROMPT_KEYMAP,
@@ -748,32 +897,38 @@ static int parse_argv(int argc, char *argv[]) {
ARG_COPY_TIMEZONE,
ARG_COPY_ROOT_PASSWORD,
ARG_SETUP_MACHINE_ID,
ARG_FORCE,
ARG_DELETE_ROOT_PASSWORD,
};
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 },
{ "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 },
{ "kernel-command-line", required_argument, NULL, ARG_KERNEL_COMMAND_LINE },
{ "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 },
{}
};
@@ -838,6 +993,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:
@@ -847,6 +1004,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:
@@ -868,6 +1034,13 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_KERNEL_COMMAND_LINE:
r = free_and_strdup(&arg_kernel_cmdline, optarg);
if (r < 0)
return log_oom();
break;
case ARG_PROMPT:
arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true;
break;
@@ -920,6 +1093,14 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_FORCE:
arg_force = true;
break;
case ARG_DELETE_ROOT_PASSWORD:
arg_delete_root_password = true;
break;
case '?':
return -EINVAL;
@@ -935,6 +1116,10 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_locale_messages && !locale_is_ok(arg_locale_messages))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale_messages);
if (arg_delete_root_password && (arg_copy_root_password || arg_root_password || arg_prompt_root_password))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--delete-root-password cannot be combined with other root password options");
return 1;
}
@@ -980,6 +1165,10 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
r = process_kernel_cmdline();
if (r < 0)
return r;
return 0;
}
+8 -30
View File
@@ -345,28 +345,6 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
}
#endif
static int sync_rights(FILE *from, const char *to) {
struct stat st;
if (fstat(fileno(from), &st) < 0)
return -errno;
return chmod_and_chown_unsafe(to, st.st_mode & 07777, st.st_uid, st.st_gid);
}
static int rename_and_apply_smack(const char *temp_path, const char *dest_path) {
int r = 0;
if (rename(temp_path, dest_path) < 0)
return -errno;
#ifdef SMACK_RUN_LABEL
r = mac_smack_apply(dest_path, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL);
if (r < 0)
return r;
#endif
return r;
}
static const char* default_shell(uid_t uid) {
return uid == 0 ? "/bin/sh" : NOLOGIN;
}
@@ -389,7 +367,7 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
original = fopen(passwd_path, "re");
if (original) {
r = sync_rights(original, passwd_tmp);
r = sync_rights(fileno(original), fileno(passwd));
if (r < 0)
return r;
@@ -491,7 +469,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
original = fopen(shadow_path, "re");
if (original) {
r = sync_rights(original, shadow_tmp);
r = sync_rights(fileno(original), fileno(shadow));
if (r < 0)
return r;
@@ -588,7 +566,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
original = fopen(group_path, "re");
if (original) {
r = sync_rights(original, group_tmp);
r = sync_rights(fileno(original), fileno(group));
if (r < 0)
return r;
@@ -687,7 +665,7 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
if (original) {
struct sgrp *sg;
r = sync_rights(original, gshadow_tmp);
r = sync_rights(fileno(original), fileno(gshadow));
if (r < 0)
return r;
@@ -794,14 +772,14 @@ static int write_files(void) {
/* And make the new files count */
if (group) {
r = rename_and_apply_smack(group_tmp, group_path);
r = rename_and_apply_smack_floor_label(group_tmp, group_path);
if (r < 0)
return r;
group_tmp = mfree(group_tmp);
}
if (gshadow) {
r = rename_and_apply_smack(gshadow_tmp, gshadow_path);
r = rename_and_apply_smack_floor_label(gshadow_tmp, gshadow_path);
if (r < 0)
return r;
@@ -809,14 +787,14 @@ static int write_files(void) {
}
if (passwd) {
r = rename_and_apply_smack(passwd_tmp, passwd_path);
r = rename_and_apply_smack_floor_label(passwd_tmp, passwd_path);
if (r < 0)
return r;
passwd_tmp = mfree(passwd_tmp);
}
if (shadow) {
r = rename_and_apply_smack(shadow_tmp, shadow_path);
r = rename_and_apply_smack_floor_label(shadow_tmp, shadow_path);
if (r < 0)
return r;