mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge 9db8c687f9
into ccaa76ac48
This commit is contained in:
commit
aa579d5b9a
@ -5,16 +5,23 @@
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "ask-password-api.h"
|
||||
#include "build.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "constants.h"
|
||||
#include "json-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "main-func.h"
|
||||
#include "parse-argument.h"
|
||||
#include "pretty-print.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "varlink-io.systemd.AskPassword.h"
|
||||
#include "varlink-util.h"
|
||||
|
||||
static const char *arg_icon = NULL;
|
||||
static const char *arg_id = NULL; /* identifier for 'ask-password' protocol */
|
||||
@ -26,6 +33,7 @@ static bool arg_multiple = false;
|
||||
static bool arg_no_output = false;
|
||||
static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
|
||||
static bool arg_newline = true;
|
||||
static bool arg_varlink = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
|
||||
|
||||
@ -213,7 +221,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
else {
|
||||
r = parse_boolean_argument("--emoji=", emoji, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return r;
|
||||
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, !r);
|
||||
}
|
||||
@ -232,9 +240,162 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m");
|
||||
if (r > 0)
|
||||
arg_varlink = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef enum EchoMode {
|
||||
ECHO_OFF,
|
||||
ECHO_ON,
|
||||
ECHO_MASKED,
|
||||
_ECHO_MODE_MAX,
|
||||
_ECHO_MODE_INVALID = -EINVAL,
|
||||
} EchoMode;
|
||||
|
||||
static const char* echo_mode_table[_ECHO_MODE_MAX] = {
|
||||
[ECHO_OFF] = "off",
|
||||
[ECHO_ON] = "on",
|
||||
[ECHO_MASKED] = "masked",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(echo_mode, EchoMode, ECHO_ON);
|
||||
|
||||
static JSON_DISPATCH_ENUM_DEFINE(dispatch_echo_mode, EchoMode, echo_mode_from_string);
|
||||
|
||||
typedef struct MethodAskParameters {
|
||||
const char *message;
|
||||
const char *keyring;
|
||||
const char *icon;
|
||||
const char *id;
|
||||
uint64_t timeout_usec;
|
||||
uint64_t until_usec;
|
||||
int accept_cached;
|
||||
int push_cache;
|
||||
EchoMode echo_mode;
|
||||
} MethodAskParameters;
|
||||
|
||||
static int vl_method_ask(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "message", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodAskParameters, message), 0 },
|
||||
{ "keyname", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodAskParameters, keyring), 0 },
|
||||
{ "icon", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodAskParameters, icon), 0 },
|
||||
{ "id", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MethodAskParameters, id), 0 },
|
||||
{ "timeoutUSec", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodAskParameters, timeout_usec), 0 },
|
||||
{ "untilUSec", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodAskParameters, until_usec), 0 },
|
||||
{ "acceptCached", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(MethodAskParameters, accept_cached), 0 },
|
||||
{ "pushCache", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(MethodAskParameters, push_cache) , 0 },
|
||||
{ "echo", SD_JSON_VARIANT_STRING, dispatch_echo_mode, offsetof(MethodAskParameters, echo_mode), 0 },
|
||||
VARLINK_DISPATCH_POLKIT_FIELD,
|
||||
{}
|
||||
};
|
||||
|
||||
Hashmap **polkit_registry = ASSERT_PTR(userdata);
|
||||
MethodAskParameters p = {
|
||||
.timeout_usec = DEFAULT_TIMEOUT_USEC,
|
||||
.until_usec = UINT64_MAX,
|
||||
.accept_cached = -1,
|
||||
.push_cache = -1,
|
||||
.echo_mode = _ECHO_MODE_INVALID,
|
||||
};
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
/* bus= */ NULL,
|
||||
"io.systemd.ask-password.ask",
|
||||
/* details= */ NULL,
|
||||
/* good_user= */ FLAGS_SET(arg_flags, ASK_PASSWORD_USER) ? getuid() : UID_INVALID,
|
||||
/* flags= */ 0,
|
||||
polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = p.message ?: arg_message,
|
||||
.icon = p.icon ?: arg_icon,
|
||||
.id = p.id ?: arg_id,
|
||||
.keyring = p.keyring ?: arg_key_name,
|
||||
.credential = arg_credential_name,
|
||||
.hup_fd = sd_varlink_get_input_fd(link),
|
||||
};
|
||||
|
||||
if (p.timeout_usec != 0 && p.until_usec != 0)
|
||||
req.until = MIN(usec_add(now(CLOCK_MONOTONIC), p.timeout_usec), p.until_usec);
|
||||
|
||||
/* If the timeout is set to zero, don't ask agents, just stick to cache */
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_NO_AGENT, req.until == 0);
|
||||
|
||||
if (p.accept_cached >= 0)
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_ACCEPT_CACHED, p.accept_cached);
|
||||
|
||||
if (p.push_cache >= 0)
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_PUSH_CACHE, p.push_cache);
|
||||
|
||||
if (p.echo_mode >= 0) {
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_ECHO, p.echo_mode == ECHO_ON);
|
||||
SET_FLAG(arg_flags, ASK_PASSWORD_SILENT, p.echo_mode == ECHO_OFF);
|
||||
}
|
||||
|
||||
_cleanup_strv_free_erase_ char **l = NULL;
|
||||
r = ask_password_auto(&req, arg_flags, &l);
|
||||
if (r == -EUNATCH)
|
||||
return sd_varlink_error(link, "io.systemd.AskPassword.NoPasswordAvailable", NULL);
|
||||
if (r == -ETIME)
|
||||
return sd_varlink_error(link, "io.systemd.AskPassword.TimeoutReached", NULL);
|
||||
if (r == -ECONNRESET) { /* POLLHUP on the varlink fd we passed in via .hup_fd */
|
||||
sd_varlink_close(link);
|
||||
return 1;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *vl = NULL;
|
||||
r = sd_json_variant_new_array_strv(&vl, l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sd_json_variant_sensitive(vl);
|
||||
|
||||
return sd_varlink_replybo(link, SD_JSON_BUILD_PAIR("passwords", SD_JSON_BUILD_VARIANT(vl)));
|
||||
}
|
||||
|
||||
static int vl_server(void) {
|
||||
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;
|
||||
_cleanup_(hashmap_freep) Hashmap *polkit_registry = NULL;
|
||||
int r;
|
||||
|
||||
r = varlink_server_new(&varlink_server, SD_VARLINK_SERVER_INHERIT_USERDATA, /* userdata= */ &polkit_registry);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate Varlink server: %m");
|
||||
|
||||
r = sd_varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_AskPassword);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add Varlink interface: %m");
|
||||
|
||||
r = sd_varlink_server_bind_method(varlink_server, "io.systemd.AskPassword.Ask", vl_method_ask);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind Varlink method: %m");
|
||||
|
||||
r = sd_varlink_server_loop_auto(varlink_server);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to run Varlink event loop: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_strv_free_erase_ char **l = NULL;
|
||||
usec_t timeout;
|
||||
@ -249,17 +410,23 @@ static int run(int argc, char *argv[]) {
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (arg_varlink)
|
||||
return vl_server(); /* Invocation as Varlink service */
|
||||
|
||||
timeout = arg_timeout > 0 ? usec_add(now(CLOCK_MONOTONIC), arg_timeout) : 0;
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = arg_message,
|
||||
.icon = arg_icon,
|
||||
.id = arg_id,
|
||||
.keyring = arg_key_name,
|
||||
.credential = arg_credential_name ?: "password",
|
||||
.until = timeout,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, timeout, arg_flags, &l);
|
||||
r = ask_password_auto(&req, arg_flags, &l);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
|
31
src/ask-password/io.systemd.ask-password.policy
Normal file
31
src/ask-password/io.systemd.ask-password.policy
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
|
||||
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
"https://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
This file is part of systemd.
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
-->
|
||||
|
||||
<policyconfig>
|
||||
|
||||
<vendor>The systemd Project</vendor>
|
||||
<vendor_url>https://systemd.io</vendor_url>
|
||||
|
||||
<action id="io.systemd.ask-password.ask">
|
||||
<description gettext-domain="systemd">Allow to query the user interactively for a password</description>
|
||||
<message gettext-domain="systemd">Authentication is required for an application to ask the user interactively for a password.</message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin_keep</allow_any>
|
||||
<allow_inactive>auth_admin_keep</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
@ -984,9 +984,12 @@ int verb_install(int argc, char *argv[], void *userdata) {
|
||||
arg_private_key_source,
|
||||
arg_private_key,
|
||||
&(AskPasswordRequest) {
|
||||
.tty_fd = -EBADF,
|
||||
.id = "bootctl-private-key-pin",
|
||||
.keyring = arg_private_key,
|
||||
.credential = "bootctl.private-key-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
},
|
||||
&private_key,
|
||||
&ui);
|
||||
|
@ -55,11 +55,14 @@ int load_volume_key_password(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = question,
|
||||
.icon = "drive-harddisk",
|
||||
.id = id,
|
||||
.keyring = "cryptenroll",
|
||||
.credential = "cryptenroll.passphrase",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
@ -69,7 +72,7 @@ int load_volume_key_password(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOKEY),
|
||||
"Too many attempts, giving up.");
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, ask_password_flags, &passwords);
|
||||
r = ask_password_auto(&req, ask_password_flags, &passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
@ -130,10 +133,13 @@ int enroll_password(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.icon = "drive-harddisk",
|
||||
.id = id,
|
||||
.keyring = "cryptenroll",
|
||||
.credential = "cryptenroll.new-passphrase",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
@ -150,7 +156,7 @@ int enroll_password(
|
||||
|
||||
req.message = question;
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &passwords);
|
||||
r = ask_password_auto(&req, /* flags= */ 0, &passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
@ -163,7 +169,7 @@ int enroll_password(
|
||||
|
||||
req.message = question;
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &passwords2);
|
||||
r = ask_password_auto(&req, /* flags= */ 0, &passwords2);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
|
@ -119,16 +119,18 @@ static int get_pin(char **ret_pin_str, TPM2Flags *ret_flags) {
|
||||
SYNTHETIC_ERRNO(ENOKEY), "Too many attempts, giving up.");
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = "Please enter TPM2 PIN:",
|
||||
.icon = "drive-harddisk",
|
||||
.keyring = "tpm2-pin",
|
||||
.credential = "cryptenroll.new-tpm2-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
pin = strv_free_erase(pin);
|
||||
r = ask_password_auto(
|
||||
&req,
|
||||
/* until= */ USEC_INFINITY,
|
||||
/* flags= */ 0,
|
||||
&pin);
|
||||
if (r < 0)
|
||||
@ -139,7 +141,6 @@ static int get_pin(char **ret_pin_str, TPM2Flags *ret_flags) {
|
||||
|
||||
r = ask_password_auto(
|
||||
&req,
|
||||
USEC_INFINITY,
|
||||
/* flags= */ 0,
|
||||
&pin2);
|
||||
if (r < 0)
|
||||
|
@ -906,17 +906,20 @@ static int get_password(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = text,
|
||||
.icon = "drive-harddisk",
|
||||
.id = id,
|
||||
.keyring = "cryptsetup",
|
||||
.credential = "cryptsetup.passphrase",
|
||||
.until = until,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
if (ignore_cached)
|
||||
flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
|
||||
r = ask_password_auto(&req, until, flags, &passwords);
|
||||
r = ask_password_auto(&req, flags, &passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
@ -937,7 +940,7 @@ static int get_password(
|
||||
req.message = text;
|
||||
req.id = id;
|
||||
|
||||
r = ask_password_auto(&req, until, flags, &passwords2);
|
||||
r = ask_password_auto(&req, flags, &passwords2);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query verification password: %m");
|
||||
|
||||
@ -1422,13 +1425,16 @@ static int crypt_activate_by_token_pin_ask_password(
|
||||
pins = strv_free_erase(pins);
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = message,
|
||||
.icon = "drive-harddisk",
|
||||
.keyring = keyring,
|
||||
.credential = credential,
|
||||
.until = until,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, until, flags, &pins);
|
||||
r = ask_password_auto(&req, flags, &pins);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -735,10 +735,13 @@ static int prompt_root_password(int rfd) {
|
||||
_cleanup_free_ char *error = NULL;
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = msg1,
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_tty(-EBADF, &req, /* until= */ 0, /* flags= */ 0, /* flag_file= */ NULL, &a);
|
||||
r = ask_password_tty(&req, /* flags= */ 0, &a);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query root password: %m");
|
||||
if (strv_length(a) != 1)
|
||||
@ -760,7 +763,7 @@ static int prompt_root_password(int rfd) {
|
||||
|
||||
req.message = msg2;
|
||||
|
||||
r = ask_password_tty(-EBADF, &req, /* until= */ 0, /* flags= */ 0, /* flag_file= */ NULL, &b);
|
||||
r = ask_password_tty(&req, /* flags= */ 0, &b);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query root password: %m");
|
||||
if (strv_length(b) != 1)
|
||||
|
@ -263,13 +263,16 @@ static int acquire_existing_password(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = question,
|
||||
.icon = "user-home",
|
||||
.keyring = "home-password",
|
||||
.credential = "home.password",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, flags, &password);
|
||||
r = ask_password_auto(&req, flags, &password);
|
||||
if (r == -EUNATCH) { /* EUNATCH is returned if no password was found and asking interactively was
|
||||
* disabled via the flags. Not an error for us. */
|
||||
log_debug_errno(r, "No passwords acquired.");
|
||||
@ -321,13 +324,16 @@ static int acquire_recovery_key(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = question,
|
||||
.icon = "user-home",
|
||||
.keyring = "home-recovery-key",
|
||||
.credential = "home.recovery-key",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, flags, &recovery_key);
|
||||
r = ask_password_auto(&req, flags, &recovery_key);
|
||||
if (r == -EUNATCH) { /* EUNATCH is returned if no recovery key was found and asking interactively was
|
||||
* disabled via the flags. Not an error for us. */
|
||||
log_debug_errno(r, "No recovery keys acquired.");
|
||||
@ -375,13 +381,16 @@ static int acquire_token_pin(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = question,
|
||||
.icon = "user-home",
|
||||
.keyring = "token-pin",
|
||||
.credential = "home.token-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, flags, &pin);
|
||||
r = ask_password_auto(&req, flags, &pin);
|
||||
if (r == -EUNATCH) { /* EUNATCH is returned if no PIN was found and asking interactively was disabled
|
||||
* via the flags. Not an error for us. */
|
||||
log_debug_errno(r, "No security token PINs acquired.");
|
||||
@ -1229,15 +1238,17 @@ static int acquire_new_password(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = question,
|
||||
.icon = "user-home",
|
||||
.keyring = "home-password",
|
||||
.credential = "home.new-password",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(
|
||||
&req,
|
||||
USEC_INFINITY,
|
||||
/* flags= */ 0, /* no caching, we want to collect a new password here after all */
|
||||
&first);
|
||||
if (r < 0)
|
||||
@ -1253,7 +1264,6 @@ static int acquire_new_password(
|
||||
|
||||
r = ask_password_auto(
|
||||
&req,
|
||||
USEC_INFINITY,
|
||||
/* flags= */ 0, /* no caching */
|
||||
&second);
|
||||
if (r < 0)
|
||||
|
@ -182,9 +182,12 @@ static int verb_validate(int argc, char *argv[], void *userdata) {
|
||||
arg_private_key_source,
|
||||
arg_private_key,
|
||||
&(AskPasswordRequest) {
|
||||
.tty_fd = -EBADF,
|
||||
.id = "keyutil-private-key-pin",
|
||||
.keyring = arg_private_key,
|
||||
.credential = "keyutil.private-key-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
},
|
||||
&private_key,
|
||||
&ui);
|
||||
@ -238,9 +241,12 @@ static int verb_public(int argc, char *argv[], void *userdata) {
|
||||
arg_private_key_source,
|
||||
arg_private_key,
|
||||
&(AskPasswordRequest) {
|
||||
.tty_fd = -EBADF,
|
||||
.id = "keyutil-private-key-pin",
|
||||
.keyring = arg_private_key,
|
||||
.credential = "keyutil.private-key-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
},
|
||||
&private_key,
|
||||
&ui);
|
||||
|
@ -1062,8 +1062,10 @@ global:
|
||||
|
||||
LIBSYSTEMD_258 {
|
||||
global:
|
||||
sd_device_enumerator_add_all_parents;
|
||||
sd_json_variant_type_from_string;
|
||||
sd_json_variant_type_to_string;
|
||||
sd_varlink_get_input_fd;
|
||||
sd_varlink_get_output_fd;
|
||||
sd_varlink_reset_fds;
|
||||
sd_device_enumerator_add_all_parents;
|
||||
} LIBSYSTEMD_257;
|
||||
|
@ -1673,6 +1673,30 @@ _public_ int sd_varlink_get_fd(sd_varlink *v) {
|
||||
return v->input_fd;
|
||||
}
|
||||
|
||||
_public_ int sd_varlink_get_input_fd(sd_varlink *v) {
|
||||
|
||||
assert_return(v, -EINVAL);
|
||||
|
||||
if (v->state == VARLINK_DISCONNECTED)
|
||||
return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected.");
|
||||
if (v->input_fd < 0)
|
||||
return varlink_log_errno(v, SYNTHETIC_ERRNO(EBADF), "No valid input fd.");
|
||||
|
||||
return v->input_fd;
|
||||
}
|
||||
|
||||
_public_ int sd_varlink_get_output_fd(sd_varlink *v) {
|
||||
|
||||
assert_return(v, -EINVAL);
|
||||
|
||||
if (v->state == VARLINK_DISCONNECTED)
|
||||
return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected.");
|
||||
if (v->output_fd < 0)
|
||||
return varlink_log_errno(v, SYNTHETIC_ERRNO(EBADF), "No valid output fd.");
|
||||
|
||||
return v->output_fd;
|
||||
}
|
||||
|
||||
_public_ int sd_varlink_get_events(sd_varlink *v) {
|
||||
int ret = 0;
|
||||
|
||||
|
@ -888,9 +888,12 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
arg_private_key_source,
|
||||
arg_private_key,
|
||||
&(AskPasswordRequest) {
|
||||
.tty_fd = -EBADF,
|
||||
.id = "measure-private-key-pin",
|
||||
.keyring = arg_private_key,
|
||||
.credential = "measure.private-key-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
},
|
||||
&privkey,
|
||||
&ui);
|
||||
|
@ -297,6 +297,29 @@ static int vl_method_extend(sd_varlink *link, sd_json_variant *parameters, sd_va
|
||||
return sd_varlink_reply(link, NULL);
|
||||
}
|
||||
|
||||
static int vl_server(void) {
|
||||
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;
|
||||
int r;
|
||||
|
||||
r = varlink_server_new(&varlink_server, SD_VARLINK_SERVER_ROOT_ONLY, /* userdata= */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate Varlink server: %m");
|
||||
|
||||
r = sd_varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_PCRExtend);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add Varlink interface: %m");
|
||||
|
||||
r = sd_varlink_server_bind_method(varlink_server, "io.systemd.PCRExtend.Extend", vl_method_extend);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind Varlink method: %m");
|
||||
|
||||
r = sd_varlink_server_loop_auto(varlink_server);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to run Varlink event loop: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
Tpm2UserspaceEventType event;
|
||||
@ -308,29 +331,8 @@ static int run(int argc, char *argv[]) {
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (arg_varlink) {
|
||||
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;
|
||||
|
||||
/* Invocation as Varlink service */
|
||||
|
||||
r = varlink_server_new(&varlink_server, SD_VARLINK_SERVER_ROOT_ONLY, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate Varlink server: %m");
|
||||
|
||||
r = sd_varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_PCRExtend);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add Varlink interface: %m");
|
||||
|
||||
r = sd_varlink_server_bind_method(varlink_server, "io.systemd.PCRExtend.Extend", vl_method_extend);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind Varlink method: %m");
|
||||
|
||||
r = sd_varlink_server_loop_auto(varlink_server);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to run Varlink event loop: %m");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (arg_varlink)
|
||||
return vl_server(); /* Invocation as Varlink service */
|
||||
|
||||
if (arg_file_system) {
|
||||
if (optind != argc)
|
||||
|
@ -4550,14 +4550,16 @@ static int make_policy(bool force, RecoveryPinMode recovery_pin_mode) {
|
||||
_cleanup_(strv_free_erasep) char **l = NULL;
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = "Recovery PIN",
|
||||
.id = "pcrlock-recovery-pin",
|
||||
.credential = "pcrlock.recovery-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(
|
||||
&req,
|
||||
/* until= */ 0,
|
||||
/* flags= */ 0,
|
||||
&l);
|
||||
if (r < 0)
|
||||
|
@ -8572,9 +8572,12 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY *
|
||||
arg_private_key_source,
|
||||
arg_private_key,
|
||||
&(AskPasswordRequest) {
|
||||
.tty_fd = -EBADF,
|
||||
.id = "repart-private-key-pin",
|
||||
.keyring = arg_private_key,
|
||||
.credential = "repart.private-key-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
},
|
||||
&private_key,
|
||||
&ui);
|
||||
|
@ -203,9 +203,12 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||||
arg_private_key_source,
|
||||
arg_private_key,
|
||||
&(AskPasswordRequest) {
|
||||
.tty_fd = -EBADF,
|
||||
.id = "sbsign-private-key-pin",
|
||||
.keyring = arg_private_key,
|
||||
.credential = "sbsign.private-key-pin",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
},
|
||||
&private_key,
|
||||
&ui);
|
||||
|
@ -309,9 +309,7 @@ static int backspace_string(int ttyfd, const char *str) {
|
||||
|
||||
int ask_password_plymouth(
|
||||
const AskPasswordRequest *req,
|
||||
usec_t until,
|
||||
AskPasswordFlags flags,
|
||||
const char *flag_file,
|
||||
char ***ret) {
|
||||
|
||||
_cleanup_close_ int fd = -EBADF, inotify_fd = -EBADF;
|
||||
@ -328,12 +326,12 @@ int ask_password_plymouth(
|
||||
|
||||
const char *message = req && req->message ? req->message : "Password:";
|
||||
|
||||
if (flag_file) {
|
||||
if (req->flag_file) {
|
||||
inotify_fd = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
|
||||
if (inotify_fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (inotify_add_watch(inotify_fd, flag_file, IN_ATTRIB) < 0) /* for the link count */
|
||||
if (inotify_add_watch(inotify_fd, req->flag_file, IN_ATTRIB) < 0) /* for the link count */
|
||||
return -errno;
|
||||
}
|
||||
|
||||
@ -357,25 +355,40 @@ int ask_password_plymouth(
|
||||
|
||||
enum {
|
||||
POLL_SOCKET,
|
||||
POLL_INOTIFY, /* Must be last, because optional */
|
||||
POLL_TWO,
|
||||
POLL_THREE,
|
||||
_POLL_MAX,
|
||||
};
|
||||
|
||||
struct pollfd pollfd[_POLL_MAX] = {
|
||||
[POLL_SOCKET] = { .fd = fd, .events = POLLIN },
|
||||
[POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN },
|
||||
[POLL_SOCKET] = {
|
||||
.fd = fd,
|
||||
.events = POLLIN,
|
||||
},
|
||||
};
|
||||
size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX-1;
|
||||
size_t n_pollfd = POLL_SOCKET + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX;
|
||||
if (inotify_fd >= 0)
|
||||
pollfd[inotify_idx = n_pollfd++] = (struct pollfd) {
|
||||
.fd = inotify_fd,
|
||||
.events = POLLIN,
|
||||
};
|
||||
if (req->hup_fd >= 0)
|
||||
pollfd[hup_fd_idx = n_pollfd++] = (struct pollfd) {
|
||||
.fd = req->hup_fd,
|
||||
.events = POLLHUP,
|
||||
};
|
||||
|
||||
assert(n_pollfd <= _POLL_MAX);
|
||||
|
||||
for (;;) {
|
||||
usec_t timeout;
|
||||
|
||||
if (until > 0)
|
||||
timeout = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
|
||||
if (req->until > 0)
|
||||
timeout = usec_sub_unsigned(req->until, now(CLOCK_MONOTONIC));
|
||||
else
|
||||
timeout = USEC_INFINITY;
|
||||
|
||||
if (flag_file && access(flag_file, F_OK) < 0)
|
||||
if (req->flag_file && access(req->flag_file, F_OK) < 0)
|
||||
return -errno;
|
||||
|
||||
r = ppoll_usec(pollfd, n_pollfd, timeout);
|
||||
@ -386,7 +399,10 @@ int ask_password_plymouth(
|
||||
if (r == 0)
|
||||
return -ETIME;
|
||||
|
||||
if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0)
|
||||
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP)
|
||||
return -ECONNRESET;
|
||||
|
||||
if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0)
|
||||
(void) flush_fd(inotify_fd);
|
||||
|
||||
if (pollfd[POLL_SOCKET].revents == 0)
|
||||
@ -464,11 +480,8 @@ int ask_password_plymouth(
|
||||
#define SKIPPED "(skipped)"
|
||||
|
||||
int ask_password_tty(
|
||||
int ttyfd,
|
||||
const AskPasswordRequest *req,
|
||||
usec_t until,
|
||||
AskPasswordFlags flags,
|
||||
const char *flag_file,
|
||||
char ***ret) {
|
||||
|
||||
bool reset_tty = false, dirty = false, use_color = false, press_tab_visible = false;
|
||||
@ -493,15 +506,14 @@ int ask_password_tty(
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_HIDE_EMOJI) && emoji_enabled())
|
||||
message = strjoina(special_glyph(SPECIAL_GLYPH_LOCK_AND_KEY), " ", message);
|
||||
|
||||
if (flag_file || (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyring)) {
|
||||
if (req->flag_file || (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && keyring)) {
|
||||
inotify_fd = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
|
||||
if (inotify_fd < 0)
|
||||
return -errno;
|
||||
}
|
||||
if (flag_file) {
|
||||
if (inotify_add_watch(inotify_fd, flag_file, IN_ATTRIB /* for the link count */) < 0)
|
||||
if (req->flag_file)
|
||||
if (inotify_add_watch(inotify_fd, req->flag_file, IN_ATTRIB /* for the link count */) < 0)
|
||||
return -errno;
|
||||
}
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && req && keyring) {
|
||||
r = ask_password_keyring(req, flags, ret);
|
||||
if (r >= 0)
|
||||
@ -529,8 +541,11 @@ int ask_password_tty(
|
||||
CLEANUP_ERASE(passphrase);
|
||||
|
||||
/* If the caller didn't specify a TTY, then use the controlling tty, if we can. */
|
||||
if (ttyfd < 0)
|
||||
int ttyfd;
|
||||
if (req->tty_fd < 0)
|
||||
ttyfd = cttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC);
|
||||
else
|
||||
ttyfd = req->tty_fd;
|
||||
|
||||
if (ttyfd >= 0) {
|
||||
if (tcgetattr(ttyfd, &old_termios) < 0)
|
||||
@ -570,28 +585,44 @@ int ask_password_tty(
|
||||
|
||||
enum {
|
||||
POLL_TTY,
|
||||
POLL_INOTIFY, /* Must be last, because optional */
|
||||
POLL_TWO,
|
||||
POLL_THREE,
|
||||
_POLL_MAX,
|
||||
};
|
||||
|
||||
struct pollfd pollfd[_POLL_MAX] = {
|
||||
[POLL_TTY] = { .fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO, .events = POLLIN },
|
||||
[POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN },
|
||||
[POLL_TTY] = {
|
||||
.fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO,
|
||||
.events = POLLIN,
|
||||
},
|
||||
};
|
||||
size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX-1;
|
||||
size_t n_pollfd = POLL_TTY + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX;
|
||||
|
||||
if (inotify_fd >= 0)
|
||||
pollfd[inotify_idx = n_pollfd++] = (struct pollfd) {
|
||||
.fd = inotify_fd,
|
||||
.events = POLLIN,
|
||||
};
|
||||
if (req->hup_fd >= 0)
|
||||
pollfd[hup_fd_idx = n_pollfd++] = (struct pollfd) {
|
||||
.fd = req->hup_fd,
|
||||
.events = POLLHUP,
|
||||
};
|
||||
|
||||
assert(n_pollfd <= _POLL_MAX);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(erase_char) char c;
|
||||
usec_t timeout;
|
||||
ssize_t n;
|
||||
|
||||
if (until > 0)
|
||||
timeout = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
|
||||
if (req->until > 0)
|
||||
timeout = usec_sub_unsigned(req->until, now(CLOCK_MONOTONIC));
|
||||
else
|
||||
timeout = USEC_INFINITY;
|
||||
|
||||
if (flag_file) {
|
||||
r = RET_NERRNO(access(flag_file, F_OK));
|
||||
if (req->flag_file) {
|
||||
r = RET_NERRNO(access(req->flag_file, F_OK));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
@ -606,7 +637,12 @@ int ask_password_tty(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyring) {
|
||||
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) {
|
||||
r = -ECONNRESET;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0 && keyring) {
|
||||
(void) flush_fd(inotify_fd);
|
||||
|
||||
r = ask_password_keyring(req, flags, ret);
|
||||
@ -800,7 +836,6 @@ static int create_socket(const char *askpwdir, char **ret) {
|
||||
|
||||
int ask_password_agent(
|
||||
const AskPasswordRequest *req,
|
||||
usec_t until,
|
||||
AskPasswordFlags flags,
|
||||
char ***ret) {
|
||||
|
||||
@ -820,6 +855,10 @@ int ask_password_agent(
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT))
|
||||
return -EUNATCH;
|
||||
|
||||
/* We don't support the flag file concept for now when querying via the agent logic */
|
||||
if (req->flag_file)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
assert_se(sigemptyset(&mask) >= 0);
|
||||
assert_se(sigset_add_many(&mask, SIGINT, SIGTERM) >= 0);
|
||||
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0);
|
||||
@ -891,7 +930,7 @@ int ask_password_agent(
|
||||
socket_name,
|
||||
FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED),
|
||||
FLAGS_SET(flags, ASK_PASSWORD_ECHO),
|
||||
until,
|
||||
req->until,
|
||||
FLAGS_SET(flags, ASK_PASSWORD_SILENT));
|
||||
|
||||
if (req) {
|
||||
@ -924,16 +963,29 @@ int ask_password_agent(
|
||||
enum {
|
||||
POLL_SOCKET,
|
||||
POLL_SIGNAL,
|
||||
POLL_INOTIFY, /* Must be last, because optional */
|
||||
POLL_THREE,
|
||||
POLL_FOUR,
|
||||
_POLL_MAX
|
||||
};
|
||||
|
||||
struct pollfd pollfd[_POLL_MAX] = {
|
||||
[POLL_SOCKET] = { .fd = socket_fd, .events = POLLIN },
|
||||
[POLL_SIGNAL] = { .fd = signal_fd, .events = POLLIN },
|
||||
[POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN },
|
||||
};
|
||||
size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX - 1;
|
||||
size_t n_pollfd = POLL_SIGNAL + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX;
|
||||
|
||||
if (inotify_fd >= 0)
|
||||
pollfd[inotify_idx = n_pollfd++] = (struct pollfd) {
|
||||
.fd = inotify_fd,
|
||||
.events = POLLIN,
|
||||
};
|
||||
if (req->hup_fd >= 0)
|
||||
pollfd[hup_fd_idx = n_pollfd ++] = (struct pollfd) {
|
||||
.fd = req->hup_fd,
|
||||
.events = POLLHUP,
|
||||
};
|
||||
|
||||
assert(n_pollfd <= _POLL_MAX);
|
||||
|
||||
for (;;) {
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
@ -943,8 +995,8 @@ int ask_password_agent(
|
||||
usec_t timeout;
|
||||
ssize_t n;
|
||||
|
||||
if (until > 0)
|
||||
timeout = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
|
||||
if (req->until > 0)
|
||||
timeout = usec_sub_unsigned(req->until, now(CLOCK_MONOTONIC));
|
||||
else
|
||||
timeout = USEC_INFINITY;
|
||||
|
||||
@ -963,7 +1015,10 @@ int ask_password_agent(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0) {
|
||||
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP)
|
||||
return -ECONNRESET;
|
||||
|
||||
if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) {
|
||||
(void) flush_fd(inotify_fd);
|
||||
|
||||
if (req && req->keyring) {
|
||||
@ -1103,7 +1158,6 @@ static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFla
|
||||
|
||||
int ask_password_auto(
|
||||
const AskPasswordRequest *req,
|
||||
usec_t until,
|
||||
AskPasswordFlags flags,
|
||||
char ***ret) {
|
||||
|
||||
@ -1111,6 +1165,17 @@ int ask_password_auto(
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* Returns the following well-known errors:
|
||||
*
|
||||
* -ETIME → a timeout was specified and hit
|
||||
* -EUNATCH → couldn't ask interactively and no cached password available either
|
||||
* -ENOENT → the specified flag file disappeared
|
||||
* -ECANCELED → the user explicitly cancelled the request
|
||||
* -EINTR → SIGINT/SIGTERM where received during the query
|
||||
* -ENOEXEC → headless mode was requested but no password could be acquired non-interactively
|
||||
* -ECONNRESET → a POLLHUP has been seen on the specified hup_fd
|
||||
*/
|
||||
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_NO_CREDENTIAL) && req && req->credential) {
|
||||
r = ask_password_credential(req, flags, ret);
|
||||
if (r != -ENOKEY)
|
||||
@ -1127,10 +1192,10 @@ int ask_password_auto(
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_NO_TTY) && isatty_safe(STDIN_FILENO))
|
||||
return ask_password_tty(-EBADF, req, until, flags, NULL, ret);
|
||||
return ask_password_tty(req, flags, ret);
|
||||
|
||||
if (!FLAGS_SET(flags, ASK_PASSWORD_NO_AGENT))
|
||||
return ask_password_agent(req, until, flags, ret);
|
||||
return ask_password_agent(req, flags, ret);
|
||||
|
||||
return -EUNATCH;
|
||||
}
|
||||
|
@ -26,11 +26,15 @@ typedef struct AskPasswordRequest {
|
||||
const char *icon; /* freedesktop icon spec name */
|
||||
const char *id; /* some identifier used for this prompt for the "ask-password" protocol */
|
||||
const char *credential; /* $CREDENTIALS_DIRECTORY credential name */
|
||||
const char *flag_file; /* Once this flag file disappears abort the query */
|
||||
int tty_fd; /* If querying on a TTY, the TTY to query on (or -EBADF) */
|
||||
usec_t until; /* CLOCK_MONOTONIC time until which to show the prompt */
|
||||
int hup_fd; /* An extra fd to watch for POLLHUP, in which case to abort the query */
|
||||
} AskPasswordRequest;
|
||||
|
||||
int ask_password_tty(int tty_fd, const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
||||
int ask_password_plymouth(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
|
||||
int ask_password_agent(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||
int ask_password_auto(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret);
|
||||
int ask_password_tty(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret);
|
||||
int ask_password_plymouth(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret);
|
||||
int ask_password_agent(const AskPasswordRequest *req, AskPasswordFlags flag, char ***ret);
|
||||
int ask_password_auto(const AskPasswordRequest *req, AskPasswordFlags flag, char ***ret);
|
||||
|
||||
int acquire_user_ask_password_directory(char **ret);
|
||||
|
@ -111,15 +111,18 @@ int acquire_fido2_key(
|
||||
if (FLAGS_SET(askpw_flags, ASK_PASSWORD_HEADLESS))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the '$PIN' environment variable.");
|
||||
|
||||
static const AskPasswordRequest req = {
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = "Please enter security token PIN:",
|
||||
.icon = "drive-harddisk",
|
||||
.keyring = "fido2-pin",
|
||||
.credential = "cryptsetup.fido2-pin",
|
||||
.until = until,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
pins = strv_free_erase(pins);
|
||||
r = ask_password_auto(&req, until, askpw_flags, &pins);
|
||||
r = ask_password_auto(&req, askpw_flags, &pins);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to ask for user password: %m");
|
||||
|
||||
|
@ -35,14 +35,17 @@ static int get_pin(
|
||||
"Use the '$PIN' environment variable.");
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = "Please enter TPM2 PIN:",
|
||||
.icon = "drive-harddisk",
|
||||
.keyring = "tpm2-pin",
|
||||
.credential = askpw_credential,
|
||||
.until = until,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
pin = strv_free_erase(pin);
|
||||
r = ask_password_auto(&req, until, askpw_flags, &pin);
|
||||
r = ask_password_auto(&req, askpw_flags, &pin);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to ask for user pin: %m");
|
||||
assert(strv_length(pin) == 1);
|
||||
|
@ -3077,13 +3077,16 @@ int dissected_image_decrypt_interactively(
|
||||
z = strv_free_erase(z);
|
||||
|
||||
static const AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = "Please enter image passphrase:",
|
||||
.id = "dissect",
|
||||
.keyring = "dissect",
|
||||
.credential = "dissect.passphrase",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &z);
|
||||
r = ask_password_auto(&req, /* flags= */ 0, &z);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query for passphrase: %m");
|
||||
|
||||
|
@ -857,13 +857,16 @@ int fido2_generate_hmac_hash(
|
||||
for (;;) {
|
||||
_cleanup_strv_free_erase_ char **pin = NULL;
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = "Please enter security token PIN:",
|
||||
.icon = askpw_icon,
|
||||
.keyring = "fido2-pin",
|
||||
.credential = askpw_credential,
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &pin);
|
||||
r = ask_password_auto(&req, /* flags= */ 0, &pin);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire user PIN: %m");
|
||||
|
||||
|
@ -177,6 +177,7 @@ shared_sources = files(
|
||||
'userdb-dropin.c',
|
||||
'userdb.c',
|
||||
'varlink-idl-common.c',
|
||||
'varlink-io.systemd.AskPassword.c',
|
||||
'varlink-io.systemd.BootControl.c',
|
||||
'varlink-io.systemd.Credentials.c',
|
||||
'varlink-io.systemd.Hostname.c',
|
||||
|
@ -1399,7 +1399,7 @@ static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) {
|
||||
req->message = UI_get0_output_string(uis);
|
||||
|
||||
_cleanup_(strv_freep) char **l = NULL;
|
||||
r = ask_password_auto(req, /*until=*/ 0, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &l);
|
||||
r = ask_password_auto(req, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &l);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to query for PIN: %m");
|
||||
return 0;
|
||||
|
@ -380,15 +380,18 @@ int pkcs11_token_login(
|
||||
return log_oom();
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = text,
|
||||
.icon = askpw_icon,
|
||||
.id = id,
|
||||
.keyring = askpw_keyring,
|
||||
.credential = askpw_credential,
|
||||
.until = until,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
/* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */
|
||||
r = ask_password_auto(&req, until, askpw_flags, &passwords);
|
||||
r = ask_password_auto(&req, askpw_flags, &passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label);
|
||||
}
|
||||
|
53
src/shared/varlink-io.systemd.AskPassword.c
Normal file
53
src/shared/varlink-io.systemd.AskPassword.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "bus-polkit.h"
|
||||
#include "varlink-io.systemd.AskPassword.h"
|
||||
|
||||
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||
EchoMode,
|
||||
SD_VARLINK_FIELD_COMMENT("Request that the password is prompted for without any visual feedback"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(off),
|
||||
SD_VARLINK_FIELD_COMMENT("Show the password in plaintext as it is typed in"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(on),
|
||||
SD_VARLINK_FIELD_COMMENT("Provide visual feedback as the password is typed, but mask the password plaintext"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(masked));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
Ask,
|
||||
SD_VARLINK_FIELD_COMMENT("The message to show when prompting for the password"),
|
||||
SD_VARLINK_DEFINE_INPUT(message, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("The name for the kernel keyring entry used for caching"),
|
||||
SD_VARLINK_DEFINE_INPUT(keyname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("The icon name to display, following the freedesktop.org icon naming specification"),
|
||||
SD_VARLINK_DEFINE_INPUT(icon, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("An recognizable id for the password prompt"),
|
||||
SD_VARLINK_DEFINE_INPUT(id, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Timeout in µs (relative, CLOCK_MONOTONIC)"),
|
||||
SD_VARLINK_DEFINE_INPUT(timeoutUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Timeout in µs (absolute, CLOCK_MONOTONIC; if both timeoutUSec and untilUSec are specified the earlier of the two is used)"),
|
||||
SD_VARLINK_DEFINE_INPUT(untilUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Whether to accept cached passwords from the kernel keyring"),
|
||||
SD_VARLINK_DEFINE_INPUT(acceptCached, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Whether to push acquired passwords into the kernel keyring"),
|
||||
SD_VARLINK_DEFINE_INPUT(pushCache, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Whether to give visual feedback when typing in the password"),
|
||||
SD_VARLINK_DEFINE_INPUT_BY_TYPE(echo, EchoMode, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_POLKIT_INPUT,
|
||||
SD_VARLINK_FIELD_COMMENT("List of acquired passwords. This typically contains one entry, but might contain more in case multiple passwords were previously cached."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(passwords, SD_VARLINK_STRING, SD_VARLINK_ARRAY));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(NoPasswordAvailable);
|
||||
static SD_VARLINK_DEFINE_ERROR(TimeoutReached);
|
||||
|
||||
SD_VARLINK_DEFINE_INTERFACE(
|
||||
io_systemd_AskPassword,
|
||||
"io.systemd.AskPassword",
|
||||
SD_VARLINK_INTERFACE_COMMENT("An interface for interactively asking the user for a password"),
|
||||
SD_VARLINK_SYMBOL_COMMENT("Encodes whether to provide visual feedback as the password is typed in"),
|
||||
&vl_type_EchoMode,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Interactively ask the user for a password, or answer from a previously cached entry"),
|
||||
&vl_method_Ask,
|
||||
SD_VARLINK_SYMBOL_COMMENT("No password available, because none was provided in the cache, and no agent was asked"),
|
||||
&vl_error_NoPasswordAvailable,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Query timeout reached, user did not provide a password in time"),
|
||||
&vl_error_TimeoutReached);
|
6
src/shared/varlink-io.systemd.AskPassword.h
Normal file
6
src/shared/varlink-io.systemd.AskPassword.h
Normal file
@ -0,0 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-varlink-idl.h"
|
||||
|
||||
extern const sd_varlink_interface vl_interface_io_systemd_AskPassword;
|
@ -96,6 +96,8 @@ sd_varlink* sd_varlink_ref(sd_varlink *link);
|
||||
sd_varlink* sd_varlink_unref(sd_varlink *v);
|
||||
|
||||
int sd_varlink_get_fd(sd_varlink *v);
|
||||
int sd_varlink_get_input_fd(sd_varlink *v);
|
||||
int sd_varlink_get_output_fd(sd_varlink *v);
|
||||
int sd_varlink_get_events(sd_varlink *v);
|
||||
int sd_varlink_get_timeout(sd_varlink *v, uint64_t *ret);
|
||||
|
||||
|
@ -9,11 +9,14 @@ TEST(ask_password) {
|
||||
int r;
|
||||
|
||||
static const AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = "hello?",
|
||||
.keyring = "da key",
|
||||
.until = USEC_INFINITY,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_tty(-EBADF, &req, /* until= */ 0, /* flags= */ ASK_PASSWORD_CONSOLE_COLOR, /* flag_file= */ NULL, &ret);
|
||||
r = ask_password_tty(&req, /* flags= */ ASK_PASSWORD_CONSOLE_COLOR, &ret);
|
||||
if (r == -ECANCELED)
|
||||
ASSERT_NULL(ret);
|
||||
else {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "varlink-idl-util.h"
|
||||
#include "varlink-io.systemd.h"
|
||||
#include "varlink-io.systemd.BootControl.h"
|
||||
#include "varlink-io.systemd.AskPassword.h"
|
||||
#include "varlink-io.systemd.Credentials.h"
|
||||
#include "varlink-io.systemd.Import.h"
|
||||
#include "varlink-io.systemd.Journal.h"
|
||||
@ -194,6 +195,8 @@ TEST(parse_format) {
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_MachineImage);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_io_systemd_AskPassword);
|
||||
print_separator();
|
||||
test_parse_format_one(&vl_interface_xyz_test);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "build.h"
|
||||
#include "conf-parser.h"
|
||||
#include "constants.h"
|
||||
#include "daemon-util.h"
|
||||
#include "devnum-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "exit-status.h"
|
||||
@ -147,10 +148,14 @@ static int agent_ask_password_tty(
|
||||
}
|
||||
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = tty_fd,
|
||||
.message = message,
|
||||
.flag_file = flag_file,
|
||||
.until = until,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_tty(tty_fd, &req, until, flags, flag_file, ret);
|
||||
r = ask_password_tty(&req, flags, ret);
|
||||
|
||||
if (arg_console) {
|
||||
assert(tty_fd >= 0);
|
||||
@ -243,20 +248,32 @@ static int process_one_password_file(const char *filename, FILE *f) {
|
||||
SET_FLAG(flags, ASK_PASSWORD_ECHO, echo);
|
||||
SET_FLAG(flags, ASK_PASSWORD_SILENT, silent);
|
||||
|
||||
if (arg_plymouth) {
|
||||
AskPasswordRequest req = {
|
||||
.message = message,
|
||||
};
|
||||
/* Allow providing a password via env var, for debugging purposes */
|
||||
const char *e = secure_getenv("SYSTEMD_ASK_PASSWORD_AGENT_PASSWORD");
|
||||
if (e) {
|
||||
passwords = strv_new(e);
|
||||
if (!passwords)
|
||||
return log_oom();
|
||||
} else {
|
||||
if (arg_plymouth) {
|
||||
AskPasswordRequest req = {
|
||||
.tty_fd = -EBADF,
|
||||
.message = message,
|
||||
.flag_file = filename,
|
||||
.until = not_after,
|
||||
.hup_fd = -EBADF,
|
||||
};
|
||||
|
||||
r = ask_password_plymouth(&req, not_after, flags, filename, &passwords);
|
||||
} else
|
||||
r = agent_ask_password_tty(message, not_after, flags, filename, &passwords);
|
||||
if (r < 0) {
|
||||
/* If the query went away, that's OK */
|
||||
if (IN_SET(r, -ETIME, -ENOENT))
|
||||
return 0;
|
||||
r = ask_password_plymouth(&req, flags, &passwords);
|
||||
} else
|
||||
r = agent_ask_password_tty(message, not_after, flags, filename, &passwords);
|
||||
if (r < 0) {
|
||||
/* If the query went away, that's OK */
|
||||
if (IN_SET(r, -ETIME, -ENOENT))
|
||||
return 0;
|
||||
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
}
|
||||
}
|
||||
|
||||
assert(!strv_isempty(passwords));
|
||||
@ -385,6 +402,9 @@ static int process_and_watch_password_files(bool watch) {
|
||||
pollfd[FD_INOTIFY] = (struct pollfd) { .fd = notify, .events = POLLIN };
|
||||
}
|
||||
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop =
|
||||
notify_start(NOTIFY_READY, NOTIFY_STOPPING);
|
||||
|
||||
for (;;) {
|
||||
usec_t timeout = USEC_INFINITY;
|
||||
|
||||
|
24
test/units/TEST-74-AUX-UTILS.ask-password.sh
Executable file
24
test/units/TEST-74-AUX-UTILS.ask-password.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
# shellcheck source=test/units/util.sh
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
at_exit() {
|
||||
set +e
|
||||
systemctl stop waldo-ask-pw-agent.service
|
||||
}
|
||||
|
||||
trap at_exit EXIT
|
||||
|
||||
systemd-ask-password --help
|
||||
systemd-tty-ask-password-agent --list
|
||||
|
||||
varlinkctl introspect /run/systemd/io.systemd.AskPassword
|
||||
|
||||
# Spawn an agent that always replies all ask password requests with "waldo"
|
||||
systemd-run -u waldo-ask-pw-agent.service -p Environment=SYSTEMD_ASK_PASSWORD_AGENT_PASSWORD=waldo -p Type=notify /usr/bin/systemd-tty-ask-password-agent --watch --console=/dev/console
|
||||
assert_eq "$(systemd-ask-password --no-tty)" "waldo"
|
||||
assert_eq "$(varlinkctl call /usr/bin/systemd-ask-password io.systemd.AskPassword.Ask '{"message":"foobar"}' | jq '.passwords[0]')" "\"waldo\""
|
@ -245,6 +245,11 @@ units = [
|
||||
{ 'file' : 'system-update-cleanup.service' },
|
||||
{ 'file' : 'system-update-pre.target' },
|
||||
{ 'file' : 'system-update.target' },
|
||||
{
|
||||
'file' : 'systemd-ask-password.socket',
|
||||
'symlinks' : ['sockets.target.wants/']
|
||||
},
|
||||
{ 'file' : 'systemd-ask-password@.service' },
|
||||
{
|
||||
'file' : 'systemd-ask-password-console.path',
|
||||
'symlinks' : ['sysinit.target.wants/'],
|
||||
|
@ -22,4 +22,5 @@ Before=shutdown.target initrd-switch-root.target
|
||||
|
||||
[Service]
|
||||
ExecStart=systemd-tty-ask-password-agent --watch --console
|
||||
Type=notify
|
||||
SystemCallArchitectures=native
|
||||
|
@ -15,4 +15,5 @@ After=systemd-user-sessions.service
|
||||
[Service]
|
||||
ExecStartPre=-systemctl stop systemd-ask-password-console.path systemd-ask-password-console.service systemd-ask-password-plymouth.path systemd-ask-password-plymouth.service
|
||||
ExecStart=systemd-tty-ask-password-agent --wall
|
||||
Type=notify
|
||||
SystemCallArchitectures=native
|
||||
|
21
units/systemd-ask-password.socket
Normal file
21
units/systemd-ask-password.socket
Normal file
@ -0,0 +1,21 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Query the User Interactively for a Password
|
||||
Documentation=man:systemd-ask-password(1)
|
||||
DefaultDependencies=no
|
||||
Before=sockets.target
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/systemd/io.systemd.AskPassword
|
||||
FileDescriptorName=varlink
|
||||
SocketMode=0666
|
||||
Accept=yes
|
||||
MaxConnectionsPerSource=16
|
16
units/systemd-ask-password@.service
Normal file
16
units/systemd-ask-password@.service
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Query the User Interactively for a Password
|
||||
Documentation=man:systemd-ask-password(1)
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
ExecStart=-systemd-ask-password --system --no-tty
|
@ -1,34 +1,64 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
units = [
|
||||
'app.slice',
|
||||
'background.slice',
|
||||
'basic.target',
|
||||
'bluetooth.target',
|
||||
'capsule@.target',
|
||||
'default.target',
|
||||
'exit.target',
|
||||
'graphical-session-pre.target',
|
||||
'graphical-session.target',
|
||||
'paths.target',
|
||||
'printer.target',
|
||||
'session.slice',
|
||||
'shutdown.target',
|
||||
'smartcard.target',
|
||||
'sockets.target',
|
||||
'sound.target',
|
||||
'systemd-exit.service',
|
||||
'systemd-tmpfiles-clean.service',
|
||||
'systemd-tmpfiles-clean.timer',
|
||||
'systemd-tmpfiles-setup.service',
|
||||
'timers.target',
|
||||
{ 'file' : 'app.slice' },
|
||||
{ 'file' : 'background.slice' },
|
||||
{ 'file' : 'basic.target' },
|
||||
{ 'file' : 'bluetooth.target' },
|
||||
{ 'file' : 'capsule@.target' },
|
||||
{ 'file' : 'default.target' },
|
||||
{ 'file' : 'exit.target' },
|
||||
{ 'file' : 'graphical-session-pre.target' },
|
||||
{ 'file' : 'graphical-session.target' },
|
||||
{ 'file' : 'paths.target' },
|
||||
{ 'file' : 'printer.target' },
|
||||
{ 'file' : 'session.slice' },
|
||||
{ 'file' : 'shutdown.target' },
|
||||
{ 'file' : 'smartcard.target' },
|
||||
{ 'file' : 'sockets.target' },
|
||||
{ 'file' : 'sound.target' },
|
||||
{
|
||||
'file' : 'systemd-ask-password.socket',
|
||||
'symlinks' : ['sockets.target.wants/']
|
||||
},
|
||||
{ 'file' : 'systemd-ask-password@.service' },
|
||||
{ 'file' : 'systemd-exit.service' },
|
||||
{ 'file' : 'systemd-tmpfiles-clean.service' },
|
||||
{ 'file' : 'systemd-tmpfiles-clean.timer' },
|
||||
{ 'file' : 'systemd-tmpfiles-setup.service' },
|
||||
{ 'file' : 'timers.target' },
|
||||
{
|
||||
'file' : 'xdg-desktop-autostart.target',
|
||||
'conditions': ['ENABLE_XDG_AUTOSTART'],
|
||||
}
|
||||
]
|
||||
|
||||
if conf.get('ENABLE_XDG_AUTOSTART') == 1
|
||||
units += 'xdg-desktop-autostart.target'
|
||||
endif
|
||||
foreach unit : units
|
||||
file = unit.get('file')
|
||||
|
||||
foreach file : units
|
||||
install_data(file,
|
||||
install_dir : userunitdir)
|
||||
install = true
|
||||
foreach cond : unit.get('conditions', [])
|
||||
if conf.get(cond) != 1
|
||||
install = false
|
||||
break
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if install
|
||||
install_data(file,
|
||||
install_dir : userunitdir)
|
||||
|
||||
foreach target : unit.get('symlinks', [])
|
||||
if target.endswith('/')
|
||||
install_emptydir(userunitdir / target)
|
||||
meson.add_install_script(sh, '-c',
|
||||
ln_s.format(userunitdir / file,
|
||||
userunitdir / target / file))
|
||||
else
|
||||
meson.add_install_script(sh, '-c',
|
||||
ln_s.format(userunitdir / file,
|
||||
userunitdir / target))
|
||||
endif
|
||||
endforeach
|
||||
endif
|
||||
endforeach
|
||||
|
20
units/user/systemd-ask-password.socket
Normal file
20
units/user/systemd-ask-password.socket
Normal file
@ -0,0 +1,20 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Query the User Interactively for a Password
|
||||
Documentation=man:systemd-ask-password(1)
|
||||
DefaultDependencies=no
|
||||
Before=sockets.target
|
||||
|
||||
[Socket]
|
||||
ListenStream=%t/systemd/io.systemd.AskPassword
|
||||
FileDescriptorName=varlink
|
||||
SocketMode=0600
|
||||
Accept=yes
|
16
units/user/systemd-ask-password@.service
Normal file
16
units/user/systemd-ask-password@.service
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Query the User Interactively for a Password
|
||||
Documentation=man:systemd-ask-password(1)
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
ExecStart=-systemd-ask-password --user --no-tty
|
Loading…
Reference in New Issue
Block a user