]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
firstboot: Add --root-shell option 16496/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 21 Jul 2020 21:35:21 +0000 (22:35 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 22 Jul 2020 20:22:46 +0000 (21:22 +0100)
man/systemd-firstboot.xml
src/firstboot/firstboot.c

index 8c9ea80f15fcc5aebb97a8e276cfd435cf58644e..0976394b662e2de92994745c0085bd0ea97c414b 100644 (file)
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--root-shell=<replaceable>SHELL</replaceable></option></term>
+
+        <listitem><para>Sets the shell of the system's root user. This creates/modifies the
+        <citerefentry project='die-net'><refentrytitle>passwd</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        file.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--kernel-command-line=<replaceable>CMDLINE</replaceable></option></term>
 
         <term><option>--prompt-timezone</option></term>
         <term><option>--prompt-hostname</option></term>
         <term><option>--prompt-root-password</option></term>
+        <term><option>--prompt-root-shell</option></term>
 
         <listitem><para>Prompt the user interactively for a specific
         basic setting. Note that any explicit configuration settings
         <option>--prompt-keymap</option>,
         <option>--prompt-timezone</option>,
         <option>--prompt-hostname</option>,
-        <option>--prompt-root-password</option> in combination.</para>
+        <option>--prompt-root-password</option>,
+        <option>--prompt-root-shell</option> in combination.</para>
         </listitem>
       </varlistentry>
 
         <term><option>--copy-keymap</option></term>
         <term><option>--copy-timezone</option></term>
         <term><option>--copy-root-password</option></term>
+        <term><option>--copy-root-shell</option></term>
 
         <listitem><para>Copy a specific basic setting from the host.
         This only works in combination with <option>--root=</option>
         <option>--copy-locale</option>,
         <option>--copy-keymap</option>,
         <option>--copy-timezone</option>,
-        <option>--copy-root-password</option> in combination.</para>
+        <option>--copy-root-password</option>,
+        <option>--copy-root-shell</option> in combination.</para>
         </listitem>
       </varlistentry>
 
index 61565145dd3836e8cfb185c67936fc52c7059ef5..82cd4040f9cfd1935e382eec8738f723128335ef 100644 (file)
@@ -49,16 +49,19 @@ 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_root_shell = 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;
 static bool arg_prompt_hostname = false;
 static bool arg_prompt_root_password = false;
+static bool arg_prompt_root_shell = false;
 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_copy_root_shell = false;
 static bool arg_force = false;
 static bool arg_delete_root_password = false;
 static bool arg_root_password_is_hashed = false;
@@ -601,7 +604,40 @@ static int prompt_root_password(void) {
         return 0;
 }
 
-static int write_root_passwd(const char *passwd_path, const char *password) {
+static int prompt_root_shell(void) {
+        int r;
+
+        if (arg_root_shell || !arg_prompt_root_shell)
+                return 0;
+
+        print_welcome();
+        putchar('\n');
+
+        for (;;) {
+                _cleanup_free_ char *s = NULL;
+
+                r = ask_string(&s, "%s Please enter root shell for new system (empty to skip): ", special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET));
+                if (r < 0)
+                        return log_error_errno(r, "Failed to query root shell: %m");
+
+                if (isempty(s)) {
+                        log_warning("No shell entered, skipping.");
+                        break;
+                }
+
+                if (!valid_shell(s)) {
+                        log_error("Specified shell invalid.");
+                        continue;
+                }
+
+                arg_root_shell = TAKE_PTR(s);
+                break;
+        }
+
+        return 0;
+}
+
+static int write_root_passwd(const char *passwd_path, const char *password, const char *shell) {
         _cleanup_fclose_ FILE *original = NULL, *passwd = NULL;
         _cleanup_(unlink_and_freep) char *passwd_tmp = NULL;
         int r;
@@ -622,8 +658,11 @@ static int write_root_passwd(const char *passwd_path, const char *password) {
 
                 while ((r = fgetpwent_sane(original, &i)) > 0) {
 
-                        if (streq(i->pw_name, "root"))
+                        if (streq(i->pw_name, "root")) {
                                 i->pw_passwd = (char *) password;
+                                if (shell)
+                                        i->pw_shell = (char *) shell;
+                        }
 
                         r = putpwent_sane(i, passwd);
                         if (r < 0)
@@ -640,7 +679,7 @@ static int write_root_passwd(const char *passwd_path, const char *password) {
                         .pw_gid = 0,
                         .pw_gecos = (char *) "Super User",
                         .pw_dir = (char *) "/root",
-                        .pw_shell = (char *) "/bin/sh",
+                        .pw_shell = (char *) (shell ?: "/bin/sh"),
                 };
 
                 if (errno != ENOENT)
@@ -735,7 +774,7 @@ static int write_root_shadow(const char *shadow_path, const char *hashed_passwor
         return 0;
 }
 
-static int process_root_password(void) {
+static int process_root_args(void) {
         _cleanup_close_ int lock = -1;
         struct crypt_data cd = {};
         const char *password, *hashed_password;
@@ -757,6 +796,23 @@ static int process_root_password(void) {
         if (lock < 0)
                 return log_error_errno(lock, "Failed to take a lock on %s: %m", etc_passwd);
 
+        if (arg_copy_root_shell && arg_root) {
+                struct passwd *p;
+
+                errno = 0;
+                p = getpwnam("root");
+                if (!p)
+                        return log_error_errno(errno_or_else(EIO), "Failed to find passwd entry for root: %m");
+
+                r = free_and_strdup(&arg_root_shell, p->pw_shell);
+                if (r < 0)
+                        return log_oom();
+        }
+
+        r = prompt_root_shell();
+        if (r < 0)
+                return r;
+
         if (arg_copy_root_password && arg_root) {
                 struct spwd *p;
 
@@ -799,7 +855,7 @@ static int process_root_password(void) {
         else
                 password = hashed_password = "!";
 
-        r = write_root_passwd(etc_passwd, password);
+        r = write_root_passwd(etc_passwd, password, arg_root_shell);
         if (r < 0)
                 return log_error_errno(r, "Failed to write %s: %m", etc_passwd);
 
@@ -964,6 +1020,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ROOT_PASSWORD,
                 ARG_ROOT_PASSWORD_FILE,
                 ARG_ROOT_PASSWORD_HASHED,
+                ARG_ROOT_SHELL,
                 ARG_KERNEL_COMMAND_LINE,
                 ARG_PROMPT,
                 ARG_PROMPT_LOCALE,
@@ -971,11 +1028,13 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_PROMPT_TIMEZONE,
                 ARG_PROMPT_HOSTNAME,
                 ARG_PROMPT_ROOT_PASSWORD,
+                ARG_PROMPT_ROOT_SHELL,
                 ARG_COPY,
                 ARG_COPY_LOCALE,
                 ARG_COPY_KEYMAP,
                 ARG_COPY_TIMEZONE,
                 ARG_COPY_ROOT_PASSWORD,
+                ARG_COPY_ROOT_SHELL,
                 ARG_SETUP_MACHINE_ID,
                 ARG_FORCE,
                 ARG_DELETE_ROOT_PASSWORD,
@@ -996,6 +1055,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "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    },
+                { "root-shell",              required_argument, NULL, ARG_ROOT_SHELL              },
                 { "kernel-command-line",     required_argument, NULL, ARG_KERNEL_COMMAND_LINE     },
                 { "prompt",                  no_argument,       NULL, ARG_PROMPT                  },
                 { "prompt-locale",           no_argument,       NULL, ARG_PROMPT_LOCALE           },
@@ -1003,11 +1063,13 @@ static int parse_argv(int argc, char *argv[]) {
                 { "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    },
+                { "prompt-root-shell",       no_argument,       NULL, ARG_PROMPT_ROOT_SHELL       },
                 { "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      },
+                { "copy-root-shell",         no_argument,       NULL, ARG_COPY_ROOT_SHELL         },
                 { "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    },
@@ -1104,6 +1166,17 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_root_password_is_hashed = true;
                         break;
 
+                case ARG_ROOT_SHELL:
+                        if (!valid_shell(optarg))
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "%s is not a valid shell path", optarg);
+
+                        r = free_and_strdup(&arg_root_shell, optarg);
+                        if (r < 0)
+                                return log_oom();
+
+                        break;
+
                 case ARG_HOSTNAME:
                         if (!hostname_is_valid(optarg, true))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@@ -1131,7 +1204,8 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_PROMPT:
-                        arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true;
+                        arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname =
+                                arg_prompt_root_password = arg_prompt_root_shell = true;
                         break;
 
                 case ARG_PROMPT_LOCALE:
@@ -1154,8 +1228,13 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_prompt_root_password = true;
                         break;
 
+                case ARG_PROMPT_ROOT_SHELL:
+                        arg_prompt_root_shell = true;
+                        break;
+
                 case ARG_COPY:
-                        arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password = true;
+                        arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password =
+                                arg_copy_root_shell = true;
                         break;
 
                 case ARG_COPY_LOCALE:
@@ -1174,6 +1253,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_copy_root_password = true;
                         break;
 
+                case ARG_COPY_ROOT_SHELL:
+                        arg_copy_root_shell = true;
+                        break;
+
                 case ARG_SETUP_MACHINE_ID:
                         r = sd_id128_randomize(&arg_machine_id);
                         if (r < 0)
@@ -1274,7 +1357,7 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return r;
 
-        r = process_root_password();
+        r = process_root_args();
         if (r < 0)
                 return r;