mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 02:03:37 +08:00
shell: define three system credentials we can propagate into shell prompts and welcome messages
This commit is contained in:
parent
8b29949a41
commit
229d4a9806
10
TODO
10
TODO
@ -130,14 +130,8 @@ Deprecations and removals:
|
|||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
* introduce a new system credential "shell.prompt.extra" or so that may contain
|
* maybe set shell.prompt.prefix credential in run0 to some warning emoji,
|
||||||
a string to include in $PS1. Inherit it down into gettys/logins and suchlike.
|
i.e. ⚠️ or ☢️ or ⚡ or 👊 or 🧑🔧 or so.
|
||||||
And provide an /etc/profile.d/*.sh drop-in which reads the credential if set,
|
|
||||||
and suffixes $PS1. Usecase: for wsl-like environments use this to include
|
|
||||||
additional information in prompts that is inherited from the execution
|
|
||||||
context. For example include 📦 emoji via this mechanism in the prompt. Or,
|
|
||||||
in run0 include a ☢️ emoji in the prompt. Or in mkosi include a 👷 emoji in
|
|
||||||
the prompt. You get the idea.
|
|
||||||
|
|
||||||
* introduce new structure Tpm2CombinedPolicy, that combines the various TPm2
|
* introduce new structure Tpm2CombinedPolicy, that combines the various TPm2
|
||||||
policy bits into one structure, i.e. public key info, pcr masks, pcrlock
|
policy bits into one structure, i.e. public key info, pcr masks, pcrlock
|
||||||
|
@ -268,6 +268,21 @@
|
|||||||
<xi:include href="version-info.xml" xpointer="v245"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v245"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>$SHELL_PROMPT_PREFIX</varname></term>
|
||||||
|
<term><varname>$SHELL_PROMPT_SUFFIX</varname></term>
|
||||||
|
<term><varname>$SHELL_WELCOME</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>These environment variables are initialized from the service credentials
|
||||||
|
<literal>shell.prompt.prefix</literal>, <literal>shell.prompt.suffix</literal> and
|
||||||
|
<literal>shell.welcome</literal> if set. They are passed to the invoked session processes, where they
|
||||||
|
are imported into any shell prompt (specifically <varname>$SHELL_PROMPT_PREFIX</varname> is added as
|
||||||
|
prefix to <varname>$PS1</varname>, and <varname>$SHELL_PROMPT_SUFFIX</varname> as suffix) or printed
|
||||||
|
on screen when a shell first initializes.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<para>The following environment variables are read by the module and may be used by the PAM service to pass
|
<para>The following environment variables are read by the module and may be used by the PAM service to pass
|
||||||
|
@ -334,6 +334,27 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>shell.prompt.prefix</varname></term>
|
||||||
|
<term><varname>shell.prompt.suffix</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Defines strings to prefix and suffix any interactive UNIX shell prompt with. For details see
|
||||||
|
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>shell.welcome</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Define a string to print when an interactive UNIX shell initializes. For details see
|
||||||
|
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>system.machine_id</varname></term>
|
<term><varname>system.machine_id</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
12
meson.build
12
meson.build
@ -188,7 +188,7 @@ mimepackagesdir = prefixdir / 'share/mime/packages'
|
|||||||
|
|
||||||
configfiledir = get_option('configfiledir')
|
configfiledir = get_option('configfiledir')
|
||||||
if configfiledir == ''
|
if configfiledir == ''
|
||||||
configfiledir= sysconfdir
|
configfiledir = sysconfdir
|
||||||
endif
|
endif
|
||||||
pkgconfigfiledir = configfiledir / 'systemd'
|
pkgconfigfiledir = configfiledir / 'systemd'
|
||||||
|
|
||||||
@ -228,6 +228,13 @@ if libcryptsetup_plugins_dir == ''
|
|||||||
libcryptsetup_plugins_dir = libdir / 'cryptsetup'
|
libcryptsetup_plugins_dir = libdir / 'cryptsetup'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
shellprofiledir = get_option('shellprofiledir')
|
||||||
|
if shellprofiledir == ''
|
||||||
|
shellprofiledir = sysconfdir / 'profile.d'
|
||||||
|
endif
|
||||||
|
conf.set10('LINK_SHELL_EXTRA_DROPIN', shellprofiledir != 'no' and not shellprofiledir.startswith('/usr/'))
|
||||||
|
conf.set('SHELLPROFILEDIR', shellprofiledir, description : 'shell profile directory')
|
||||||
|
|
||||||
memory_accounting_default = get_option('memory-accounting-default')
|
memory_accounting_default = get_option('memory-accounting-default')
|
||||||
status_unit_format_default = get_option('status-unit-format-default')
|
status_unit_format_default = get_option('status-unit-format-default')
|
||||||
if status_unit_format_default == 'auto'
|
if status_unit_format_default == 'auto'
|
||||||
@ -257,6 +264,7 @@ conf.set_quoted('RANDOM_SEED_DIR', randomseeddir)
|
|||||||
conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
|
conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
|
||||||
conf.set_quoted('SSHCONFDIR', sshconfdir)
|
conf.set_quoted('SSHCONFDIR', sshconfdir)
|
||||||
conf.set_quoted('SSHDCONFDIR', sshdconfdir)
|
conf.set_quoted('SSHDCONFDIR', sshdconfdir)
|
||||||
|
conf.set_quoted('SHELLPROFILEDIR', shellprofiledir)
|
||||||
conf.set_quoted('SYSCONF_DIR', sysconfdir)
|
conf.set_quoted('SYSCONF_DIR', sysconfdir)
|
||||||
conf.set_quoted('SYSCTL_DIR', sysctldir)
|
conf.set_quoted('SYSCTL_DIR', sysctldir)
|
||||||
conf.set_quoted('SYSTEMCTL_BINARY_PATH', bindir / 'systemctl')
|
conf.set_quoted('SYSTEMCTL_BINARY_PATH', bindir / 'systemctl')
|
||||||
@ -2701,6 +2709,7 @@ subdir('man')
|
|||||||
subdir('modprobe.d')
|
subdir('modprobe.d')
|
||||||
subdir('network')
|
subdir('network')
|
||||||
subdir('presets')
|
subdir('presets')
|
||||||
|
subdir('profile.d')
|
||||||
subdir('shell-completion/bash')
|
subdir('shell-completion/bash')
|
||||||
subdir('shell-completion/zsh')
|
subdir('shell-completion/zsh')
|
||||||
subdir('sysctl.d')
|
subdir('sysctl.d')
|
||||||
@ -2923,6 +2932,7 @@ summary({
|
|||||||
'ssh server privilege separation directory' : sshdprivsepdir,
|
'ssh server privilege separation directory' : sshdprivsepdir,
|
||||||
'ssh client configuration directory' : sshconfdir,
|
'ssh client configuration directory' : sshconfdir,
|
||||||
'libcryptsetup plugins directory' : libcryptsetup_plugins_dir,
|
'libcryptsetup plugins directory' : libcryptsetup_plugins_dir,
|
||||||
|
'Shell profile directory' : shellprofiledir,
|
||||||
'RPM macros directory' : rpmmacrosdir,
|
'RPM macros directory' : rpmmacrosdir,
|
||||||
'modprobe.d directory' : modprobedir,
|
'modprobe.d directory' : modprobedir,
|
||||||
'D-Bus policy directory' : dbuspolicydir,
|
'D-Bus policy directory' : dbuspolicydir,
|
||||||
|
@ -225,6 +225,8 @@ option('sshdprivsepdir', type : 'string',
|
|||||||
description : 'directory for SSH privilege separation ["no" disables]', value : '/run/sshd')
|
description : 'directory for SSH privilege separation ["no" disables]', value : '/run/sshd')
|
||||||
option('libcryptsetup-plugins-dir', type : 'string',
|
option('libcryptsetup-plugins-dir', type : 'string',
|
||||||
description : 'directory for libcryptsetup plugins')
|
description : 'directory for libcryptsetup plugins')
|
||||||
|
option('shellprofiledir', type : 'string',
|
||||||
|
description : 'directory for Shell profile drop-ins ["no" disables]')
|
||||||
option('docdir', type : 'string',
|
option('docdir', type : 'string',
|
||||||
description : 'documentation directory')
|
description : 'documentation directory')
|
||||||
option('install-sysconfdir', type : 'combo', choices : ['true', 'no-samples', 'false'], value : 'true',
|
option('install-sysconfdir', type : 'combo', choices : ['true', 'no-samples', 'false'], value : 'true',
|
||||||
|
25
profile.d/70-systemd-shell-extra.sh
Normal file
25
profile.d/70-systemd-shell-extra.sh
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# shellcheck shell=sh
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Import the additional shell prompt prefix and suffix strings into $PS1, and
|
||||||
|
# show the shell welcome string. These can be provisioned as system or service
|
||||||
|
# credentials shell.prompt.prefix, shell.prompt.suffix and shell.welcome, and
|
||||||
|
# are propagated into these environment variables by pam_systemd(8).
|
||||||
|
|
||||||
|
if [ -n "$SHELL_PROMPT_PREFIX" ]; then
|
||||||
|
PS1="$SHELL_PROMPT_PREFIX$PS1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SHELL_PROMPT_SUFFIX" ]; then
|
||||||
|
PS1="$PS1$SHELL_PROMPT_SUFFIX"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SHELL_WELCOME" ]; then
|
||||||
|
printf '%b\n' "$SHELL_WELCOME"
|
||||||
|
fi
|
10
profile.d/meson.build
Normal file
10
profile.d/meson.build
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
install_data('70-systemd-shell-extra.sh', install_dir : shellprofiledir.startswith('/usr/') ? shellprofiledir : libexecdir / 'profile.d')
|
||||||
|
|
||||||
|
if conf.get('LINK_SHELL_EXTRA_DROPIN') == 1
|
||||||
|
install_emptydir(shellprofiledir)
|
||||||
|
|
||||||
|
meson.add_install_script(sh, '-c',
|
||||||
|
ln_s.format(libexecdir / 'profile.d' / '70-systemd-shell-extra.sh', shellprofiledir / '70-systemd-shell-extra.sh'))
|
||||||
|
endif
|
@ -27,6 +27,7 @@
|
|||||||
#include "cap-list.h"
|
#include "cap-list.h"
|
||||||
#include "capability-util.h"
|
#include "capability-util.h"
|
||||||
#include "cgroup-setup.h"
|
#include "cgroup-setup.h"
|
||||||
|
#include "creds-util.h"
|
||||||
#include "devnum-util.h"
|
#include "devnum-util.h"
|
||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
@ -567,6 +568,31 @@ static int update_environment(pam_handle_t *handle, const char *key, const char
|
|||||||
return PAM_SUCCESS;
|
return PAM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int propagate_credential_to_environment(pam_handle_t *handle, const char *credential, const char *varname) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(handle);
|
||||||
|
assert(credential);
|
||||||
|
assert(varname);
|
||||||
|
|
||||||
|
_cleanup_free_ char *value = NULL;
|
||||||
|
|
||||||
|
/* Read a service credential, and propagate it into an environment variable */
|
||||||
|
|
||||||
|
r = read_credential(credential, (void**) &value, /* ret_size= */ NULL);
|
||||||
|
if (r < 0) {
|
||||||
|
log_debug_errno(r, "Failed to read credential '%s', ignoring: %m", credential);
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = pam_misc_setenv(handle, varname, value, 0);
|
||||||
|
if (r != PAM_SUCCESS)
|
||||||
|
return pam_syslog_pam_error(handle, LOG_ERR, r,
|
||||||
|
"Failed to set environment variable %s: @PAMERR@", varname);
|
||||||
|
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) {
|
static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
@ -1192,6 +1218,19 @@ _public_ PAM_EXTERN int pam_sm_open_session(
|
|||||||
if (r != PAM_SUCCESS)
|
if (r != PAM_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
static const char *const propagate[] = {
|
||||||
|
"shell.prompt.prefix", "SHELL_PROMPT_PREFIX",
|
||||||
|
"shell.prompt.suffix", "SHELL_PROMPT_SUFFIX",
|
||||||
|
"shell.welcome", "SHELL_WELCOME",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
STRV_FOREACH_PAIR(k, v, propagate) {
|
||||||
|
r = propagate_credential_to_environment(handle, *k, *v);
|
||||||
|
if (r != PAM_SUCCESS)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (vtnr > 0) {
|
if (vtnr > 0) {
|
||||||
char buf[DECIMAL_STR_MAX(vtnr)];
|
char buf[DECIMAL_STR_MAX(vtnr)];
|
||||||
sprintf(buf, "%u", vtnr);
|
sprintf(buf, "%u", vtnr);
|
||||||
|
12
tmpfiles.d/20-systemd-shell-extra.conf.in
Normal file
12
tmpfiles.d/20-systemd-shell-extra.conf.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
# See tmpfiles.d(5) for details
|
||||||
|
|
||||||
|
{% if LINK_SHELL_EXTRA_DROPIN %}
|
||||||
|
L {{SHELLPROFILEDIR}}/70-systemd-shell-extra.sh - - - - {{LIBEXECDIR}}/profile.d/70-systemd-shell-extra.sh
|
||||||
|
{% endif %}
|
@ -36,6 +36,7 @@ in_files = [['etc.conf', ''],
|
|||||||
['var.conf', ''],
|
['var.conf', ''],
|
||||||
['20-systemd-userdb.conf', 'ENABLE_SSH_USERDB_CONFIG'],
|
['20-systemd-userdb.conf', 'ENABLE_SSH_USERDB_CONFIG'],
|
||||||
['20-systemd-ssh-generator.conf', 'ENABLE_SSH_PROXY_CONFIG'],
|
['20-systemd-ssh-generator.conf', 'ENABLE_SSH_PROXY_CONFIG'],
|
||||||
|
['20-systemd-shell-extra.conf', 'LINK_SHELL_EXTRA_DROPIN'],
|
||||||
]
|
]
|
||||||
|
|
||||||
foreach pair : in_files
|
foreach pair : in_files
|
||||||
|
@ -40,6 +40,7 @@ ImportCredential=tty.console.agetty.*:agetty.
|
|||||||
ImportCredential=tty.console.login.*:login.
|
ImportCredential=tty.console.login.*:login.
|
||||||
ImportCredential=agetty.*
|
ImportCredential=agetty.*
|
||||||
ImportCredential=login.*
|
ImportCredential=login.*
|
||||||
|
ImportCredential=shell.*
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=getty.target
|
WantedBy=getty.target
|
||||||
|
@ -46,3 +46,4 @@ ImportCredential=tty.container.%I.agetty.*:agetty.
|
|||||||
ImportCredential=tty.container.%I.login.*:login.
|
ImportCredential=tty.container.%I.login.*:login.
|
||||||
ImportCredential=agetty.*
|
ImportCredential=agetty.*
|
||||||
ImportCredential=login.*
|
ImportCredential=login.*
|
||||||
|
ImportCredential=shell.*
|
||||||
|
@ -56,6 +56,7 @@ ImportCredential=tty.virtual.%I.agetty.*:agetty.
|
|||||||
ImportCredential=tty.virtual.%I.login.*:login.
|
ImportCredential=tty.virtual.%I.login.*:login.
|
||||||
ImportCredential=agetty.*
|
ImportCredential=agetty.*
|
||||||
ImportCredential=login.*
|
ImportCredential=login.*
|
||||||
|
ImportCredential=shell.*
|
||||||
|
|
||||||
# Unset locale for the console getty since the console has problems
|
# Unset locale for the console getty since the console has problems
|
||||||
# displaying some internationalized messages.
|
# displaying some internationalized messages.
|
||||||
|
@ -50,6 +50,7 @@ ImportCredential=tty.serial.%I.agetty.*:agetty.
|
|||||||
ImportCredential=tty.serial.%I.login.*:login.
|
ImportCredential=tty.serial.%I.login.*:login.
|
||||||
ImportCredential=agetty.*
|
ImportCredential=agetty.*
|
||||||
ImportCredential=login.*
|
ImportCredential=login.*
|
||||||
|
ImportCredential=shell.*
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=getty.target
|
WantedBy=getty.target
|
||||||
|
Loading…
Reference in New Issue
Block a user