systemctl: automatically spawn temporary password agent when we might need one
This commit is contained in:
parent
0ddf1d3aa5
commit
501fc174c2
|
@ -53,9 +53,10 @@ AM_CPPFLAGS = \
|
||||||
-DSYSTEMD_BINARY_PATH=\"$(rootbindir)/systemd\" \
|
-DSYSTEMD_BINARY_PATH=\"$(rootbindir)/systemd\" \
|
||||||
-DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \
|
-DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \
|
||||||
-DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \
|
-DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \
|
||||||
|
-DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \
|
||||||
-DRUNTIME_DIR=\"$(localstatedir)/run\" \
|
-DRUNTIME_DIR=\"$(localstatedir)/run\" \
|
||||||
-DRANDOM_SEED=\"$(localstatedir)/lib/random-seed\" \
|
-DRANDOM_SEED=\"$(localstatedir)/lib/random-seed\" \
|
||||||
-DKEXEC_BINARY_PATH=\"$(rootsbindir)/kexec\" \
|
-DKEXEC_BINARY_PATH=\"/sbin/kexec\" \
|
||||||
-I $(top_srcdir)/src
|
-I $(top_srcdir)/src
|
||||||
|
|
||||||
if TARGET_GENTOO
|
if TARGET_GENTOO
|
||||||
|
|
|
@ -241,6 +241,29 @@
|
||||||
changes.</para></listitem>
|
changes.</para></listitem>
|
||||||
</varlistentry>
|
</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>
|
<varlistentry>
|
||||||
<term><option>--kill-mode=</option></term>
|
<term><option>--kill-mode=</option></term>
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include <dbus/dbus.h>
|
#include <dbus/dbus.h>
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ static bool arg_quiet = false;
|
||||||
static bool arg_full = false;
|
static bool arg_full = false;
|
||||||
static bool arg_force = false;
|
static bool arg_force = false;
|
||||||
static bool arg_defaults = false;
|
static bool arg_defaults = false;
|
||||||
|
static bool arg_ask_password = false;
|
||||||
static char **arg_wall = NULL;
|
static char **arg_wall = NULL;
|
||||||
static const char *arg_kill_who = NULL;
|
static const char *arg_kill_who = NULL;
|
||||||
static const char *arg_kill_mode = NULL;
|
static const char *arg_kill_mode = NULL;
|
||||||
|
@ -118,6 +120,47 @@ static bool on_tty(void) {
|
||||||
return t;
|
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) {
|
static const char *ansi_highlight(bool b) {
|
||||||
|
|
||||||
if (!on_tty())
|
if (!on_tty())
|
||||||
|
@ -1269,6 +1312,8 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
|
||||||
|
|
||||||
assert(bus);
|
assert(bus);
|
||||||
|
|
||||||
|
spawn_ask_password_agent();
|
||||||
|
|
||||||
if (arg_action == ACTION_SYSTEMCTL) {
|
if (arg_action == ACTION_SYSTEMCTL) {
|
||||||
method =
|
method =
|
||||||
streq(args[0], "stop") ? "StopUnit" :
|
streq(args[0], "stop") ? "StopUnit" :
|
||||||
|
@ -4010,6 +4055,8 @@ static int systemctl_help(void) {
|
||||||
" --global Enable/disable unit files globally\n"
|
" --global Enable/disable unit files globally\n"
|
||||||
" --no-reload When enabling/disabling unit files, don't reload daemon\n"
|
" --no-reload When enabling/disabling unit files, don't reload daemon\n"
|
||||||
" configuration\n"
|
" configuration\n"
|
||||||
|
" --no-ask-password\n"
|
||||||
|
" Do not ask for system passwords\n"
|
||||||
" --kill-mode=MODE How to send signal\n"
|
" --kill-mode=MODE How to send signal\n"
|
||||||
" --kill-who=WHO Who to send signal to\n"
|
" --kill-who=WHO Who to send signal to\n"
|
||||||
" -s --signal=SIGNAL Which signal to send\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_NO_RELOAD,
|
||||||
ARG_DEFAULTS,
|
ARG_DEFAULTS,
|
||||||
ARG_KILL_MODE,
|
ARG_KILL_MODE,
|
||||||
ARG_KILL_WHO
|
ARG_KILL_WHO,
|
||||||
|
ARG_NO_ASK_PASSWORD
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
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-mode", required_argument, NULL, ARG_KILL_MODE },
|
||||||
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
|
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
|
||||||
{ "signal", required_argument, NULL, 's' },
|
{ "signal", required_argument, NULL, 's' },
|
||||||
|
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4179,6 +4228,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||||
assert(argc >= 0);
|
assert(argc >= 0);
|
||||||
assert(argv);
|
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) {
|
while ((c = getopt_long(argc, argv, "ht:p:aqfs:", options, NULL)) >= 0) {
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -4285,6 +4337,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_NO_ASK_PASSWORD:
|
||||||
|
arg_ask_password = false;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue