Commit 501fc174 authored by Lennart Poettering's avatar Lennart Poettering
Browse files

systemctl: automatically spawn temporary password agent when we might need one

parent 0ddf1d3a
......@@ -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
......
......@@ -241,6 +241,29 @@
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>
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment