chiark / gitweb /
systemctl: automatically spawn temporary password agent when we might need one
authorLennart Poettering <lennart@poettering.net>
Tue, 26 Oct 2010 03:29:39 +0000 (05:29 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 26 Oct 2010 03:29:39 +0000 (05:29 +0200)
Makefile.am
man/systemctl.xml
src/systemctl.c

index 7f8df05da724bdd68a4d635cd17cdc8d38191080..b005f3aa6784117d7a009228495548f65e76b303 100644 (file)
@@ -53,9 +53,10 @@ AM_CPPFLAGS = \
        -DSYSTEMD_BINARY_PATH=\"$(rootbindir)/systemd\" \
        -DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \
        -DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \
+       -DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \
        -DRUNTIME_DIR=\"$(localstatedir)/run\" \
        -DRANDOM_SEED=\"$(localstatedir)/lib/random-seed\" \
-       -DKEXEC_BINARY_PATH=\"$(rootsbindir)/kexec\" \
+       -DKEXEC_BINARY_PATH=\"/sbin/kexec\" \
        -I $(top_srcdir)/src
 
 if TARGET_GENTOO
index cdf4f5cd2901587a4f6c7cee4ff9298848f0af7d..10e0f82441368eb8460b260e7692fbbb96963bd5 100644 (file)
                                 changes.</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><option>--no-ask-password</option></term>
+
+                                <listitem><para>When used with
+                                <command>start</command> and related
+                                commands, disables asking for
+                                passwords. Background services may
+                                require input of a password or
+                                passphrase string, for example to
+                                unlock system hard disks or
+                                cryptographic certificates. Unless
+                                this option is specified and the
+                                command is invoked from a terminal
+                                <command>systemctl</command> will
+                                query the user on the terminal for the
+                                necessary secrets. Use this option to
+                                switch this behaviour off. In this
+                                case the password must be supplied by
+                                some other means (for example
+                                graphical password agents) or the
+                                service might fail.</para></listitem>
+                        </varlistentry>
+
                         <varlistentry>
                                 <term><option>--kill-mode=</option></term>
 
index ffbe4db541ebe0be9f67c5eccd6c252e405b7bee..a4b83afcf7154a6e62b38356c0123099247c9caf 100644 (file)
@@ -32,6 +32,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <stddef.h>
+#include <sys/prctl.h>
 
 #include <dbus/dbus.h>
 
@@ -73,6 +74,7 @@ static bool arg_quiet = false;
 static bool arg_full = false;
 static bool arg_force = false;
 static bool arg_defaults = false;
+static bool arg_ask_password = false;
 static char **arg_wall = NULL;
 static const char *arg_kill_who = NULL;
 static const char *arg_kill_mode = NULL;
@@ -118,6 +120,47 @@ static bool on_tty(void) {
         return t;
 }
 
+static void spawn_ask_password_agent(void) {
+        pid_t parent, child;
+
+        /* We check STDIN here, not STDOUT, since this is about input,
+         * not output */
+        if (!isatty(STDIN_FILENO))
+                return;
+
+        if (!arg_ask_password)
+                return;
+
+        parent = getpid();
+
+        /* Spawns a temporary TTY agent, making sure it goes away when
+         * we go away */
+
+        if ((child = fork()) < 0)
+                return;
+
+        if (child == 0) {
+                /* In the child */
+
+                const char * const args[] = {
+                        SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH,
+                        "--watch",
+                        NULL
+                };
+
+                if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
+                        _exit(EXIT_FAILURE);
+
+                /* Check whether our parent died before we were able
+                 * to set the death signal */
+                if (getppid() != parent)
+                        _exit(EXIT_SUCCESS);
+
+                execv(args[0], (char **) args);
+                _exit(EXIT_FAILURE);
+        }
+}
+
 static const char *ansi_highlight(bool b) {
 
         if (!on_tty())
@@ -1269,6 +1312,8 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
 
         assert(bus);
 
+        spawn_ask_password_agent();
+
         if (arg_action == ACTION_SYSTEMCTL) {
                 method =
                         streq(args[0], "stop")                  ? "StopUnit" :
@@ -4010,6 +4055,8 @@ static int systemctl_help(void) {
                "     --global         Enable/disable unit files globally\n"
                "     --no-reload      When enabling/disabling unit files, don't reload daemon\n"
                "                      configuration\n"
+               "     --no-ask-password\n"
+               "                      Do not ask for system passwords\n"
                "     --kill-mode=MODE How to send signal\n"
                "     --kill-who=WHO   Who to send signal to\n"
                "  -s --signal=SIGNAL  Which signal to send\n"
@@ -4146,7 +4193,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_NO_RELOAD,
                 ARG_DEFAULTS,
                 ARG_KILL_MODE,
-                ARG_KILL_WHO
+                ARG_KILL_WHO,
+                ARG_NO_ASK_PASSWORD
         };
 
         static const struct option options[] = {
@@ -4171,6 +4219,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "kill-mode", required_argument, NULL, ARG_KILL_MODE },
                 { "kill-who",  required_argument, NULL, ARG_KILL_WHO  },
                 { "signal",    required_argument, NULL, 's'           },
+                { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
                 { NULL,        0,                 NULL, 0             }
         };
 
@@ -4179,6 +4228,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
+        /* Only when running as systemctl we ask for passwords */
+        arg_ask_password = true;
+
         while ((c = getopt_long(argc, argv, "ht:p:aqfs:", options, NULL)) >= 0) {
 
                 switch (c) {
@@ -4285,6 +4337,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         }
                         break;
 
+                case ARG_NO_ASK_PASSWORD:
+                        arg_ask_password = false;
+                        break;
+
                 case '?':
                         return -EINVAL;