diff --git a/TODO b/TODO
index 37323e3a19..624ae2aafd 100644
--- a/TODO
+++ b/TODO
@@ -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.
diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml
index 0eb212341f..81e62484fd 100644
--- a/man/systemd-firstboot.xml
+++ b/man/systemd-firstboot.xml
@@ -150,18 +150,27 @@
+
- Sets the password of the system's root user.
- This creates a
+ Sets the password of the system's root user. This creates a
shadow5
- file. This setting exists in two forms:
- accepts the password to set
- directly on the command line, and
- 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
- ps1.
+ file. This setting exists in three forms: accepts the password to
+ set directly on the command line, reads it from a file and
+ accepts an already hashed password on the command line. See
+ shadow5
+ 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
+ ps1.
+
+
+
+
+
+
+ Sets the system's kernel command line. This controls the
+ /etc/kernel/cmdline file which is used by
+ kernel-install8.
+
@@ -221,6 +230,23 @@
.
+
+
+
+ systemd-firstboot doesn't modify existing files unless
+ is specified. For modifications to /etc/passwd and
+ /etc/shadow, systemd-firstboot only modifies the entry of the
+ root user instead of overwriting the entire file.
+
+
+
+
+
+ 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.
+
+
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 00dce02064..f2f1e1139f 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -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;
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index e6062121a3..e2830b7963 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -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);
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index f9fdf7b1d7..0c3ef3e2a7 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -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;
}
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 847aebc516..6fbd5985d3 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -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;