]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
firstboot: fix root params with creds and prompting disabled 33876/head
authorDan Nicholson <dbn@endlessos.org>
Tue, 30 Jul 2024 13:37:40 +0000 (07:37 -0600)
committerDan Nicholson <dbn@endlessos.org>
Wed, 31 Jul 2024 10:02:43 +0000 (04:02 -0600)
Remove an early return that prevents --prompt-root-password or
--prompt-root-shell and systemd.firstboot=off using credentials. In that case,
arg_prompt_root_password and arg_prompt_root_shell will be false, but the
prompt helpers still need to be called to read the credentials. Furthermore, if
only the root shell has been set, don't overwrite the root password.

src/firstboot/firstboot.c
test/units/TEST-74-AUX-UTILS.firstboot.sh

index b6512b05a4d9d3b2ef4b936ea004000708506d75..c452ca5975695d3902f2e17f7d93fa79a6bb99fe 100644 (file)
@@ -910,8 +910,6 @@ static int write_root_passwd(int rfd, int etc_fd, const char *password, const ch
         int r;
         bool found = false;
 
-        assert(password);
-
         r = fopen_temporary_at_label(etc_fd, "passwd", "passwd", &passwd, &passwd_tmp);
         if (r < 0)
                 return r;
@@ -930,7 +928,8 @@ static int write_root_passwd(int rfd, int etc_fd, const char *password, const ch
                 while ((r = fgetpwent_sane(original, &i)) > 0) {
 
                         if (streq(i->pw_name, "root")) {
-                                i->pw_passwd = (char *) password;
+                                if (password)
+                                        i->pw_passwd = (char *) password;
                                 if (shell)
                                         i->pw_shell = (char *) shell;
                                 found = true;
@@ -952,7 +951,7 @@ static int write_root_passwd(int rfd, int etc_fd, const char *password, const ch
         if (!found) {
                 struct passwd root = {
                         .pw_name = (char *) "root",
-                        .pw_passwd = (char *) password,
+                        .pw_passwd = (char *) (password ?: PASSWORD_SEE_SHADOW),
                         .pw_uid = 0,
                         .pw_gid = 0,
                         .pw_gecos = (char *) "Super User",
@@ -985,8 +984,6 @@ static int write_root_shadow(int etc_fd, const char *hashed_password) {
         int r;
         bool found = false;
 
-        assert(hashed_password);
-
         r = fopen_temporary_at_label(etc_fd, "shadow", "shadow", &shadow, &shadow_tmp);
         if (r < 0)
                 return r;
@@ -1005,8 +1002,10 @@ static int write_root_shadow(int etc_fd, const char *hashed_password) {
                 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);
+                                if (hashed_password) {
+                                        i->sp_pwdp = (char *) hashed_password;
+                                        i->sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
+                                }
                                 found = true;
                         }
 
@@ -1026,7 +1025,7 @@ static int write_root_shadow(int etc_fd, const char *hashed_password) {
         if (!found) {
                 struct spwd root = {
                         .sp_namp = (char*) "root",
-                        .sp_pwdp = (char *) hashed_password,
+                        .sp_pwdp = (char *) (hashed_password ?: PASSWORD_LOCKED_AND_INVALID),
                         .sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY),
                         .sp_min = -1,
                         .sp_max = -1,
@@ -1089,13 +1088,6 @@ static int process_root_account(int rfd) {
                 return 0;
         }
 
-        /* Don't create/modify passwd and shadow if not asked */
-        if (!(arg_root_password || arg_prompt_root_password || arg_copy_root_password || arg_delete_root_password ||
-              arg_root_shell || arg_prompt_root_shell || arg_copy_root_shell)) {
-                log_debug("Initialization of root account was not requested, skipping.");
-                return 0;
-        }
-
         r = make_lock_file_at(pfd, ETC_PASSWD_LOCK_FILENAME, LOCK_EX, &lock);
         if (r < 0)
                 return log_error_errno(r, "Failed to take a lock on /etc/passwd: %m");
@@ -1153,9 +1145,18 @@ static int process_root_account(int rfd) {
         } else if (arg_delete_root_password) {
                 password = PASSWORD_SEE_SHADOW;
                 hashed_password = PASSWORD_NONE;
-        } else {
+        } else if (!arg_root_password && arg_prompt_root_password) {
+                /* If the user was prompted, but no password was supplied, lock the account. */
                 password = PASSWORD_SEE_SHADOW;
                 hashed_password = PASSWORD_LOCKED_AND_INVALID;
+        } else
+                /* Leave the password as is. */
+                password = hashed_password = NULL;
+
+        /* Don't create/modify passwd and shadow if there's nothing to do. */
+        if (!(password || hashed_password || arg_root_shell)) {
+                log_debug("Initialization of root account was not requested, skipping.");
+                return 0;
         }
 
         r = write_root_passwd(rfd, pfd, password, arg_root_shell);
index 7617b01bca7bdd178868459c9b8fa38a54a80d79..d9e5f594268b307d6c8702eb8c0a75cad1bc64c6 100755 (executable)
@@ -112,8 +112,14 @@ systemd-firstboot --root="$ROOT" --root-password=foo
 grep -q "^root:x:0:0:" "$ROOT/etc/passwd"
 grep -q "^root:[^!*]" "$ROOT/etc/shadow"
 rm -fv "$ROOT/etc/passwd" "$ROOT/etc/shadow"
-# Set the shell together with the password, as firstboot won't touch
-# /etc/passwd if it already exists
+systemd-firstboot --root="$ROOT" --root-password-hashed="$ROOT_HASHED_PASSWORD1"
+grep -q "^root:x:0:0:" "$ROOT/etc/passwd"
+grep -q "^root:$ROOT_HASHED_PASSWORD1:" "$ROOT/etc/shadow"
+rm -fv "$ROOT/etc/passwd" "$ROOT/etc/shadow"
+systemd-firstboot --root="$ROOT" --root-shell=/bin/fooshell
+grep -q "^root:x:0:0:.*:/bin/fooshell$" "$ROOT/etc/passwd"
+grep -q "^root:!\*:" "$ROOT/etc/shadow"
+rm -fv "$ROOT/etc/passwd" "$ROOT/etc/shadow"
 systemd-firstboot --root="$ROOT" --root-password-hashed="$ROOT_HASHED_PASSWORD1" --root-shell=/bin/fooshell
 grep -q "^root:x:0:0:.*:/bin/fooshell$" "$ROOT/etc/passwd"
 grep -q "^root:$ROOT_HASHED_PASSWORD1:" "$ROOT/etc/shadow"