1
0
mirror of https://github.com/systemd/systemd synced 2026-03-14 17:14:49 +01:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Roman Beranek
ee3713b71d resolve: remove RRs from zones before an update
During an update of RRs, the records of each DNS-SD service are
replaced with new ones. However the old RRs can only be removed from
the mDNS scopes as long as they remain accessible from the DnssdService
structures, otherwise they remain stuck there.

Therefore the removal must take place before the update.
2021-05-10 12:29:48 +02:00
Samuel BF
c362a432af Wider range of options for selecting entries for systemd-journal-gatewayd
Introducing --user, --system, --merge and --file flags, like for journalctl
and systemd-journal-upload.
2021-05-10 12:20:27 +02:00
Harsh Barsaiyan
2c324dd161 hwdb: Add Asus TP550LA 2021-05-10 11:25:15 +02:00
Dimitri John Ledkov
67f7244928
Merge pull request #19436 from xnox/sbat
boot: add optional EFI SBAT support
2021-05-10 09:30:16 +01:00
Lennart Poettering
2baec39665
Merge pull request #19545 from poettering/nss-systemd-shadow
nss-systemd: also expose shadow/gshadow entries from userdb records
2021-05-10 09:46:49 +02:00
Lennart Poettering
f43a19ecd6 nss-systemd: synthesize NSS shadow/gshadow records from userdb, as well
This ensures we not only synthesize regular paswd/group records of
userdb records, but shadow records as well. This should make sure that
userdb can be used as comprehensive superset of the classic
passwd/group/shadow/gshadow functionality.
2021-05-08 14:35:28 +02:00
Lennart Poettering
09001dbdc8 nss-systemd: set USERDB_SUPPRESS_SHADOW flag when looking up user records
Setting the flags means we won#t try to read the data from /etc/shadow
when reading a user record, thus slightly making conversion quicker and
reducing the chance of generating MAC faults, because we needlessly
access a privileged resource. Previously, passing the flag didn't
matter, when converting our JSON records to NSS since the flag only had
an effect on whether to use NSS getspnam() and related calls or not. But
given that we turn off NSS anyway as backend for this conversion (since
we want to avoid NSS loops, where we turn NSS data to our JSON user
records, and then to NSS forever and ever) it was unnecessary to pass
it.

This changed in one of the previous commits however, where we added
support for reading user definitions from drop-in files, with separate
drop-in files for the shadow data.
2021-05-08 14:25:24 +02:00
Dimitri John Ledkov
9137c03c04
boot: add optional EFI SBAT support
Add SBAT support, when -Dsbat-distro value is specified. One can use
-Dsbat-distro=auto for autodetection of all sbat options. Many meson configure
options added to customize SBAT CSV values, but sensible defaults are auto
detected by default. SBAT support is required if shim v15+ is used to load
systemd-boot binary or kernel.efi (Type II BootLoaderSpec).

Fixes #19247
2021-05-07 14:38:48 +01:00
20 changed files with 661 additions and 29 deletions

View File

@ -2,7 +2,8 @@
passwd: compat systemd passwd: compat systemd
group: compat [SUCCESS=merge] systemd group: compat [SUCCESS=merge] systemd
shadow: compat shadow: compat systemd
gshadow: files systemd
hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns
networks: files networks: files

View File

@ -150,6 +150,7 @@ sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LJ:*
sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LAB:* sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LAB:*
sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LB:* sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LB:*
sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP550LA:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LD:* sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LD:*

View File

@ -91,7 +91,9 @@
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat systemd <programlisting>passwd: compat systemd
group: compat [SUCCESS=merge] systemd group: compat [SUCCESS=merge] systemd
shadow: compat shadow: compat systemd
gshadow: files systemd
# Either (untrusted network, see above): # Either (untrusted network, see above):
hosts: mymachines resolve [!UNAVAIL=return] files <command>myhostname</command> dns hosts: mymachines resolve [!UNAVAIL=return] files <command>myhostname</command> dns

View File

@ -57,7 +57,8 @@
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat systemd <programlisting>passwd: compat systemd
group: compat [SUCCESS=merge] systemd group: compat [SUCCESS=merge] systemd
shadow: compat shadow: compat systemd
gshadow: files systemd
hosts: <command>mymachines</command> resolve [!UNAVAIL=return] files myhostname dns hosts: <command>mymachines</command> resolve [!UNAVAIL=return] files myhostname dns
networks: files networks: files

View File

@ -63,7 +63,8 @@
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat systemd <programlisting>passwd: compat systemd
group: compat [SUCCESS=merge] systemd group: compat [SUCCESS=merge] systemd
shadow: compat shadow: compat systemd
gshadow: files systemd
hosts: mymachines <command>resolve [!UNAVAIL=return]</command> files myhostname dns hosts: mymachines <command>resolve [!UNAVAIL=return]</command> files myhostname dns
networks: files networks: files

View File

@ -47,11 +47,13 @@
for resolving users and groups, but also works without the service running.</para> for resolving users and groups, but also works without the service running.</para>
<para>To activate the NSS module, add <literal>systemd</literal> to the lines starting with <para>To activate the NSS module, add <literal>systemd</literal> to the lines starting with
<literal>passwd:</literal> and <literal>group:</literal> in <filename>/etc/nsswitch.conf</filename>.</para> <literal>passwd:</literal>, <literal>group:</literal>, <literal>shadow:</literal> and
<literal>gshadow:</literal> in <filename>/etc/nsswitch.conf</filename>.</para>
<para>It is recommended to place <literal>systemd</literal> after the <literal>files</literal> or <para>It is recommended to place <literal>systemd</literal> after the <literal>files</literal> or
<literal>compat</literal> entry of the <filename>/etc/nsswitch.conf</filename> lines so that <literal>compat</literal> entry of the <filename>/etc/nsswitch.conf</filename> lines so that
<filename>/etc/passwd</filename> and <filename>/etc/group</filename> based mappings take precedence.</para> <filename>/etc/passwd</filename>, <filename>/etc/group</filename>, <filename>/etc/shadow</filename> and
<filename>/etc/gshadow</filename> based mappings take precedence.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
@ -63,7 +65,8 @@
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat <command>systemd</command> <programlisting>passwd: compat <command>systemd</command>
group: compat [SUCCESS=merge] <command>systemd</command> group: compat [SUCCESS=merge] <command>systemd</command>
shadow: compat shadow: compat <command>systemd</command>
gshadow: files <command>systemd</command>
hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns
networks: files networks: files

View File

@ -79,6 +79,30 @@
certificate from. The certificate must be in PEM format.</para></listitem> certificate from. The certificate must be in PEM format.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--system</option></term>
<term><option>--user</option></term>
<listitem><para>Limit served entries to entries from system
services and the kernel, or to entries from services of
current user. This has the same meaning as
<option>--system</option> and <option>--user</option> options
for
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. If
neither is specified, all accessible entries are served.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-m</option></term>
<term><option>--merge</option></term>
<listitem><para>Serve entries interleaved from all available
journals, including other machines. This has the same meaning
as <option>--merge</option> option for
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-D <replaceable>DIR</replaceable></option></term> <term><option>-D <replaceable>DIR</replaceable></option></term>
<term><option>--directory=<replaceable>DIR</replaceable></option></term> <term><option>--directory=<replaceable>DIR</replaceable></option></term>
@ -89,6 +113,19 @@
the default runtime and system journal paths.</para></listitem> the default runtime and system journal paths.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--file=<replaceable>GLOB</replaceable></option></term>
<listitem><para>Takes a file glob as an argument. Serve
entries from the specified journal files matching
<replaceable>GLOB</replaceable> instead of the default runtime
and system journal paths. May be specified multiple times, in
which case files will be suitably interleaved. This has the same meaning as
<option>--file=</option> option for
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" /> <xi:include href="standard-options.xml" xpointer="version" />
</variablelist> </variablelist>

View File

@ -370,6 +370,18 @@ option('efi-includedir', type : 'string', value : '/usr/include/efi',
description : 'path to the EFI header directory') description : 'path to the EFI header directory')
option('tpm-pcrindex', type : 'integer', value : 8, option('tpm-pcrindex', type : 'integer', value : 8,
description : 'TPM PCR register number to use') description : 'TPM PCR register number to use')
option('sbat-distro', type : 'string',
description : 'SBAT distribution ID, e.g. fedora, or auto for autodetection')
option('sbat-distro-generation', type : 'integer', value : 1,
description : 'SBAT distribution generation')
option('sbat-distro-summary', type : 'string',
description : 'SBAT distribution summary, e.g. Fedora')
option('sbat-distro-pkgname', type : 'string',
description : 'SBAT distribution package name, e.g. systemd')
option('sbat-distro-version', type : 'string',
description : 'SBAT distribution package version, e.g. 248-7.fc34')
option('sbat-distro-url', type : 'string',
description : 'SBAT distribution URL, e.g. https://src.fedoraproject.org/rpms/systemd')
option('bashcompletiondir', type : 'string', option('bashcompletiondir', type : 'string',
description : 'directory for bash completion scripts ["no" disables]') description : 'directory for bash completion scripts ["no" disables]')

View File

@ -18,8 +18,6 @@
# define _alloc_(...) __attribute__((__alloc_size__(__VA_ARGS__))) # define _alloc_(...) __attribute__((__alloc_size__(__VA_ARGS__)))
#endif #endif
#define _sentinel_ __attribute__((__sentinel__)) #define _sentinel_ __attribute__((__sentinel__))
#define _section_(x) __attribute__((__section__(x)))
#define _used_ __attribute__((__used__))
#define _destructor_ __attribute__((__destructor__)) #define _destructor_ __attribute__((__destructor__))
#define _deprecated_ __attribute__((__deprecated__)) #define _deprecated_ __attribute__((__deprecated__))
#define _packed_ __attribute__((__packed__)) #define _packed_ __attribute__((__packed__))
@ -30,7 +28,6 @@
#define _public_ __attribute__((__visibility__("default"))) #define _public_ __attribute__((__visibility__("default")))
#define _hidden_ __attribute__((__visibility__("hidden"))) #define _hidden_ __attribute__((__visibility__("hidden")))
#define _weakref_(x) __attribute__((__weakref__(#x))) #define _weakref_(x) __attribute__((__weakref__(#x)))
#define _align_(x) __attribute__((__aligned__(x)))
#define _alignas_(x) __attribute__((__aligned__(__alignof(x)))) #define _alignas_(x) __attribute__((__aligned__(__alignof(x))))
#define _alignptr_ __attribute__((__aligned__(sizeof(void*)))) #define _alignptr_ __attribute__((__aligned__(sizeof(void*))))
#if __GNUC__ >= 7 #if __GNUC__ >= 7
@ -138,9 +135,6 @@
/* automake test harness */ /* automake test harness */
#define EXIT_TEST_SKIP 77 #define EXIT_TEST_SKIP 77
#define XSTRINGIFY(x) #x
#define STRINGIFY(x) XSTRINGIFY(x)
/* builtins */ /* builtins */
#if __SIZEOF_INT__ == 4 #if __SIZEOF_INT__ == 4
#define BUILTIN_FFS_U32(x) __builtin_ffs(x); #define BUILTIN_FFS_U32(x) __builtin_ffs(x);

View File

@ -127,6 +127,20 @@ enum nss_status _nss_##module##_getpwuid_r( \
char *buffer, size_t buflen, \ char *buffer, size_t buflen, \
int *errnop) _public_ int *errnop) _public_
#define NSS_GETSP_PROTOTYPES(module) \
enum nss_status _nss_##module##_getspnam_r( \
const char *name, \
struct spwd *spwd, \
char *buffer, size_t buflen, \
int *errnop) _public_
#define NSS_GETSG_PROTOTYPES(module) \
enum nss_status _nss_##module##_getsgnam_r( \
const char *name, \
struct sgrp *sgrp, \
char *buffer, size_t buflen, \
int *errnop) _public_
#define NSS_GETGR_PROTOTYPES(module) \ #define NSS_GETGR_PROTOTYPES(module) \
enum nss_status _nss_##module##_getgrnam_r( \ enum nss_status _nss_##module##_getgrnam_r( \
const char *name, \ const char *name, \
@ -150,6 +164,17 @@ enum nss_status _nss_##module##_getpwent_r( \
size_t buflen, \ size_t buflen, \
int *errnop) _public_; int *errnop) _public_;
#define NSS_SPENT_PROTOTYPES(module) \
enum nss_status _nss_##module##_endspent( \
void) _public_; \
enum nss_status _nss_##module##_setspent( \
int stayopen) _public_; \
enum nss_status _nss_##module##_getspent_r( \
struct spwd *spwd, \
char *buffer, \
size_t buflen, \
int *errnop) _public_;
#define NSS_GRENT_PROTOTYPES(module) \ #define NSS_GRENT_PROTOTYPES(module) \
enum nss_status _nss_##module##_endgrent( \ enum nss_status _nss_##module##_endgrent( \
void) _public_; \ void) _public_; \
@ -161,6 +186,17 @@ enum nss_status _nss_##module##_getgrent_r( \
size_t buflen, \ size_t buflen, \
int *errnop) _public_; int *errnop) _public_;
#define NSS_SGENT_PROTOTYPES(module) \
enum nss_status _nss_##module##_endsgent( \
void) _public_; \
enum nss_status _nss_##module##_setsgent( \
int stayopen) _public_; \
enum nss_status _nss_##module##_getsgent_r( \
struct sgrp *sgrp, \
char *buffer, \
size_t buflen, \
int *errnop) _public_;
#define NSS_INITGROUPS_PROTOTYPE(module) \ #define NSS_INITGROUPS_PROTOTYPE(module) \
enum nss_status _nss_##module##_initgroups_dyn( \ enum nss_status _nss_##module##_initgroups_dyn( \
const char *user, \ const char *user, \

View File

@ -102,6 +102,42 @@ if have_gnu_efi
efi_conf.set10('ENABLE_TPM', get_option('tpm')) efi_conf.set10('ENABLE_TPM', get_option('tpm'))
efi_conf.set('SD_TPM_PCR', get_option('tpm-pcrindex')) efi_conf.set('SD_TPM_PCR', get_option('tpm-pcrindex'))
if get_option('sbat-distro') != ''
efi_conf.set_quoted('SBAT_PROJECT', meson.project_name())
efi_conf.set_quoted('PROJECT_VERSION', substs.get('PROJECT_VERSION'))
efi_conf.set_quoted('PROJECT_URL', substs.get('PROJECT_URL'))
if get_option('sbat-distro-generation') < 1
error('SBAT Distro Generation must be a positive integer')
endif
efi_conf.set('SBAT_DISTRO_GENERATION', get_option('sbat-distro-generation'))
sbatvars = [['sbat-distro', 'ID'],
['sbat-distro-summary', 'NAME'],
['sbat-distro-url', 'BUG_REPORT_URL']]
foreach sbatvar : sbatvars
value = get_option(sbatvar[0])
if value == '' or value == 'auto'
value = run_command('sh', '-c', 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $' + sbatvar[1]).stdout().strip()
endif
if value == ''
error('Required @0@ option not set and autodetection failed'.format(sbatvar[0]))
endif
efi_conf.set_quoted(sbatvar[0].underscorify().to_upper(), value)
endforeach
pkgname = get_option('sbat-distro-pkgname')
if pkgname == ''
pkgname = meson.project_name()
endif
efi_conf.set_quoted('SBAT_DISTRO_PKGNAME', pkgname)
pkgver = get_option('sbat-distro-version')
if pkgver == ''
efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION')
else
efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver)
endif
endif
efi_config_h = configure_file( efi_config_h = configure_file(
output : 'efi_config.h', output : 'efi_config.h',
configuration : efi_conf) configuration : efi_conf)
@ -244,6 +280,7 @@ if have_gnu_efi
command : [objcopy, command : [objcopy,
'-j', '.text', '-j', '.text',
'-j', '.sdata', '-j', '.sdata',
'-j', '.sbat',
'-j', '.data', '-j', '.data',
'-j', '.dynamic', '-j', '.dynamic',
'-j', '.dynsym', '-j', '.dynsym',

View File

@ -11,3 +11,10 @@ BOOLEAN secure_boot_enabled(void) {
return !EFI_ERROR(err) && secure; return !EFI_ERROR(err) && secure;
} }
#ifdef SBAT_DISTRO
static const char sbat[] _used_ _section_ (".sbat") _align_ (512) =
"sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md\n"
SBAT_PROJECT ",1,The systemd Developers," SBAT_PROJECT "," PROJECT_VERSION "," PROJECT_URL "\n"
SBAT_PROJECT "." SBAT_DISTRO "," STRINGIFY(SBAT_DISTRO_GENERATION) "," SBAT_DISTRO_SUMMARY "," SBAT_DISTRO_PKGNAME "," SBAT_DISTRO_VERSION "," SBAT_DISTRO_URL "\n";
#endif

View File

@ -7,11 +7,17 @@
#include "type.h" #include "type.h"
#define _align_(x) __attribute__((__aligned__(x)))
#define _const_ __attribute__((__const__)) #define _const_ __attribute__((__const__))
#define _pure_ __attribute__((__pure__)) #define _pure_ __attribute__((__pure__))
#define _section_(x) __attribute__((__section__(x)))
#define _used_ __attribute__((__used__))
#define _unused_ __attribute__((__unused__)) #define _unused_ __attribute__((__unused__))
#define _cleanup_(x) __attribute__((__cleanup__(x))) #define _cleanup_(x) __attribute__((__cleanup__(x)))
#define XSTRINGIFY(x) #x
#define STRINGIFY(x) XSTRINGIFY(x)
#ifndef __COVERITY__ #ifndef __COVERITY__
# define VOID_0 ((void)0) # define VOID_0 ((void)0)
#else #else

View File

@ -18,6 +18,7 @@
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "glob-util.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "log.h" #include "log.h"
#include "logs-show.h" #include "logs-show.h"
@ -36,7 +37,10 @@
static char *arg_key_pem = NULL; static char *arg_key_pem = NULL;
static char *arg_cert_pem = NULL; static char *arg_cert_pem = NULL;
static char *arg_trust_pem = NULL; static char *arg_trust_pem = NULL;
static bool arg_merge = false;
static int arg_journal_type = 0;
static const char *arg_directory = NULL; static const char *arg_directory = NULL;
static char **arg_file = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_key_pem, erase_and_freep); STATIC_DESTRUCTOR_REGISTER(arg_key_pem, erase_and_freep);
STATIC_DESTRUCTOR_REGISTER(arg_cert_pem, freep); STATIC_DESTRUCTOR_REGISTER(arg_cert_pem, freep);
@ -110,9 +114,11 @@ static int open_journal(RequestMeta *m) {
return 0; return 0;
if (arg_directory) if (arg_directory)
return sd_journal_open_directory(&m->journal, arg_directory, 0); return sd_journal_open_directory(&m->journal, arg_directory, arg_journal_type);
else if (arg_file)
return sd_journal_open_files(&m->journal, (const char**) arg_file, 0);
else else
return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM); return sd_journal_open(&m->journal, (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) | arg_journal_type);
} }
static int request_meta_ensure_tmp(RequestMeta *m) { static int request_meta_ensure_tmp(RequestMeta *m) {
@ -860,7 +866,11 @@ static int help(void) {
" --cert=CERT.PEM Server certificate in PEM format\n" " --cert=CERT.PEM Server certificate in PEM format\n"
" --key=KEY.PEM Server key in PEM format\n" " --key=KEY.PEM Server key in PEM format\n"
" --trust=CERT.PEM Certificate authority certificate in PEM format\n" " --trust=CERT.PEM Certificate authority certificate in PEM format\n"
" --system Serve system journal\n"
" --user Serve the user journal for the current user\n"
" -m --merge Serve all available journals\n"
" -D --directory=PATH Serve journal files in directory\n" " -D --directory=PATH Serve journal files in directory\n"
" --file=PATH Serve this journal file\n"
"\nSee the %s for details.\n", "\nSee the %s for details.\n",
program_invocation_short_name, program_invocation_short_name,
link); link);
@ -874,6 +884,10 @@ static int parse_argv(int argc, char *argv[]) {
ARG_KEY, ARG_KEY,
ARG_CERT, ARG_CERT,
ARG_TRUST, ARG_TRUST,
ARG_USER,
ARG_SYSTEM,
ARG_MERGE,
ARG_FILE,
}; };
int r, c; int r, c;
@ -884,7 +898,11 @@ static int parse_argv(int argc, char *argv[]) {
{ "key", required_argument, NULL, ARG_KEY }, { "key", required_argument, NULL, ARG_KEY },
{ "cert", required_argument, NULL, ARG_CERT }, { "cert", required_argument, NULL, ARG_CERT },
{ "trust", required_argument, NULL, ARG_TRUST }, { "trust", required_argument, NULL, ARG_TRUST },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "merge", no_argument, NULL, 'm' },
{ "directory", required_argument, NULL, 'D' }, { "directory", required_argument, NULL, 'D' },
{ "file", required_argument, NULL, ARG_FILE },
{} {}
}; };
@ -947,10 +965,29 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Option --trust= is not available."); "Option --trust= is not available.");
#endif #endif
case ARG_SYSTEM:
arg_journal_type |= SD_JOURNAL_SYSTEM;
break;
case ARG_USER:
arg_journal_type |= SD_JOURNAL_CURRENT_USER;
break;
case 'm':
arg_merge = true;
break;
case 'D': case 'D':
arg_directory = optarg; arg_directory = optarg;
break; break;
case ARG_FILE:
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
if (r < 0)
return log_error_errno(r, "Failed to add paths: %m");
break;
case '?': case '?':
return -EINVAL; return -EINVAL;

View File

@ -803,7 +803,7 @@ static int open_journal(sd_journal **j) {
r = sd_journal_open_container(j, arg_machine, 0); r = sd_journal_open_container(j, arg_machine, 0);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} else } else
r = sd_journal_open(j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type); r = sd_journal_open(j, (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) | arg_journal_type);
if (r < 0) if (r < 0)
log_error_errno(r, "Failed to open %s: %m", log_error_errno(r, "Failed to open %s: %m",
arg_directory ? arg_directory : arg_file ? "files" : "journal"); arg_directory ? arg_directory : arg_file ? "files" : "journal");

View File

@ -28,6 +28,18 @@ static const struct passwd root_passwd = {
.pw_shell = (char*) "/bin/sh", .pw_shell = (char*) "/bin/sh",
}; };
static const struct spwd root_spwd = {
.sp_namp = (char*) "root",
.sp_pwdp = (char*) PASSWORD_LOCKED_AND_INVALID,
.sp_lstchg = -1,
.sp_min = -1,
.sp_max = -1,
.sp_warn = -1,
.sp_inact = -1,
.sp_expire = -1,
.sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
};
static const struct passwd nobody_passwd = { static const struct passwd nobody_passwd = {
.pw_name = (char*) NOBODY_USER_NAME, .pw_name = (char*) NOBODY_USER_NAME,
.pw_passwd = (char*) PASSWORD_LOCKED_AND_INVALID, .pw_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
@ -38,6 +50,18 @@ static const struct passwd nobody_passwd = {
.pw_shell = (char*) NOLOGIN, .pw_shell = (char*) NOLOGIN,
}; };
static const struct spwd nobody_spwd = {
.sp_namp = (char*) NOBODY_USER_NAME,
.sp_pwdp = (char*) PASSWORD_LOCKED_AND_INVALID,
.sp_lstchg = -1,
.sp_min = -1,
.sp_max = -1,
.sp_warn = -1,
.sp_inact = -1,
.sp_expire = -1,
.sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
};
static const struct group root_group = { static const struct group root_group = {
.gr_name = (char*) "root", .gr_name = (char*) "root",
.gr_gid = 0, .gr_gid = 0,
@ -45,6 +69,11 @@ static const struct group root_group = {
.gr_mem = (char*[]) { NULL }, .gr_mem = (char*[]) { NULL },
}; };
static const struct sgrp root_sgrp = {
.sg_namp = (char*) "root",
.sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
};
static const struct group nobody_group = { static const struct group nobody_group = {
.gr_name = (char*) NOBODY_GROUP_NAME, .gr_name = (char*) NOBODY_GROUP_NAME,
.gr_gid = GID_NOBODY, .gr_gid = GID_NOBODY,
@ -52,6 +81,11 @@ static const struct group nobody_group = {
.gr_mem = (char*[]) { NULL }, .gr_mem = (char*[]) { NULL },
}; };
static const struct sgrp nobody_sgrp = {
.sg_namp = (char*) NOBODY_GROUP_NAME,
.sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
};
typedef struct GetentData { typedef struct GetentData {
/* As explained in NOTES section of getpwent_r(3) as 'getpwent_r() is not really reentrant since it /* As explained in NOTES section of getpwent_r(3) as 'getpwent_r() is not really reentrant since it
* shares the reading position in the stream with all other threads', we need to protect the data in * shares the reading position in the stream with all other threads', we need to protect the data in
@ -66,11 +100,19 @@ typedef struct GetentData {
} GetentData; } GetentData;
static GetentData getpwent_data = { static GetentData getpwent_data = {
.mutex = PTHREAD_MUTEX_INITIALIZER .mutex = PTHREAD_MUTEX_INITIALIZER,
}; };
static GetentData getgrent_data = { static GetentData getgrent_data = {
.mutex = PTHREAD_MUTEX_INITIALIZER .mutex = PTHREAD_MUTEX_INITIALIZER,
};
static GetentData getspent_data = {
.mutex = PTHREAD_MUTEX_INITIALIZER,
};
static GetentData getsgent_data = {
.mutex = PTHREAD_MUTEX_INITIALIZER,
}; };
static void setup_logging(void) { static void setup_logging(void) {
@ -88,9 +130,13 @@ static void setup_logging_once(void) {
setup_logging_once() setup_logging_once()
NSS_GETPW_PROTOTYPES(systemd); NSS_GETPW_PROTOTYPES(systemd);
NSS_GETSP_PROTOTYPES(systemd);
NSS_GETGR_PROTOTYPES(systemd); NSS_GETGR_PROTOTYPES(systemd);
NSS_GETSG_PROTOTYPES(systemd);
NSS_PWENT_PROTOTYPES(systemd); NSS_PWENT_PROTOTYPES(systemd);
NSS_SPENT_PROTOTYPES(systemd);
NSS_GRENT_PROTOTYPES(systemd); NSS_GRENT_PROTOTYPES(systemd);
NSS_SGENT_PROTOTYPES(systemd);
NSS_INITGROUPS_PROTOTYPE(systemd); NSS_INITGROUPS_PROTOTYPE(systemd);
enum nss_status _nss_systemd_getpwnam_r( enum nss_status _nss_systemd_getpwnam_r(
@ -191,6 +237,54 @@ enum nss_status _nss_systemd_getpwuid_r(
return status; return status;
} }
enum nss_status _nss_systemd_getspnam_r(
const char *name,
struct spwd *spwd,
char *buffer, size_t buflen,
int *errnop) {
enum nss_status status;
int e;
PROTECT_ERRNO;
NSS_ENTRYPOINT_BEGIN;
assert(name);
assert(spwd);
assert(errnop);
if (!valid_user_group_name(name, VALID_USER_RELAX))
return NSS_STATUS_NOTFOUND;
/* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
if (streq(name, root_spwd.sp_namp)) {
*spwd = root_spwd;
return NSS_STATUS_SUCCESS;
}
if (streq(name, nobody_spwd.sp_namp)) {
if (!synthesize_nobody())
return NSS_STATUS_NOTFOUND;
*spwd = nobody_spwd;
return NSS_STATUS_SUCCESS;
}
} else if (STR_IN_SET(name, root_spwd.sp_namp, nobody_spwd.sp_namp))
return NSS_STATUS_NOTFOUND;
status = userdb_getspnam(name, spwd, buffer, buflen, &e);
if (IN_SET(status, NSS_STATUS_UNAVAIL, NSS_STATUS_TRYAGAIN)) {
UNPROTECT_ERRNO;
*errnop = e;
return status;
}
return status;
}
#pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess" #pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess"
enum nss_status _nss_systemd_getgrnam_r( enum nss_status _nss_systemd_getgrnam_r(
@ -288,6 +382,54 @@ enum nss_status _nss_systemd_getgrgid_r(
return status; return status;
} }
enum nss_status _nss_systemd_getsgnam_r(
const char *name,
struct sgrp *sgrp,
char *buffer, size_t buflen,
int *errnop) {
enum nss_status status;
int e;
PROTECT_ERRNO;
NSS_ENTRYPOINT_BEGIN;
assert(name);
assert(sgrp);
assert(errnop);
if (!valid_user_group_name(name, VALID_USER_RELAX))
return NSS_STATUS_NOTFOUND;
/* Synthesize records for root and nobody, in case they are missing from /etc/group */
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
if (streq(name, root_sgrp.sg_namp)) {
*sgrp = root_sgrp;
return NSS_STATUS_SUCCESS;
}
if (streq(name, nobody_sgrp.sg_namp)) {
if (!synthesize_nobody())
return NSS_STATUS_NOTFOUND;
*sgrp = nobody_sgrp;
return NSS_STATUS_SUCCESS;
}
} else if (STR_IN_SET(name, root_sgrp.sg_namp, nobody_sgrp.sg_namp))
return NSS_STATUS_NOTFOUND;
status = userdb_getsgnam(name, sgrp, buffer, buflen, &e);
if (IN_SET(status, NSS_STATUS_UNAVAIL, NSS_STATUS_TRYAGAIN)) {
UNPROTECT_ERRNO;
*errnop = e;
return status;
}
return status;
}
static enum nss_status nss_systemd_endent(GetentData *p) { static enum nss_status nss_systemd_endent(GetentData *p) {
PROTECT_ERRNO; PROTECT_ERRNO;
NSS_ENTRYPOINT_BEGIN; NSS_ENTRYPOINT_BEGIN;
@ -307,10 +449,18 @@ enum nss_status _nss_systemd_endpwent(void) {
return nss_systemd_endent(&getpwent_data); return nss_systemd_endent(&getpwent_data);
} }
enum nss_status _nss_systemd_endspent(void) {
return nss_systemd_endent(&getspent_data);
}
enum nss_status _nss_systemd_endgrent(void) { enum nss_status _nss_systemd_endgrent(void) {
return nss_systemd_endent(&getgrent_data); return nss_systemd_endent(&getgrent_data);
} }
enum nss_status _nss_systemd_endsgent(void) {
return nss_systemd_endent(&getsgent_data);
}
enum nss_status _nss_systemd_setpwent(int stayopen) { enum nss_status _nss_systemd_setpwent(int stayopen) {
int r; int r;
@ -355,6 +505,46 @@ enum nss_status _nss_systemd_setgrent(int stayopen) {
return r < 0 ? NSS_STATUS_UNAVAIL : NSS_STATUS_SUCCESS; return r < 0 ? NSS_STATUS_UNAVAIL : NSS_STATUS_SUCCESS;
} }
enum nss_status _nss_systemd_setspent(int stayopen) {
int r;
PROTECT_ERRNO;
NSS_ENTRYPOINT_BEGIN;
if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getspent_data.mutex);
(void) _l; /* make llvm shut up about _l not being used. */
getspent_data.iterator = userdb_iterator_free(getspent_data.iterator);
getspent_data.by_membership = false;
/* See _nss_systemd_setpwent() for an explanation why we use USERDB_DONT_SYNTHESIZE here */
r = userdb_all(nss_glue_userdb_flags() | USERDB_DONT_SYNTHESIZE, &getspent_data.iterator);
return r < 0 ? NSS_STATUS_UNAVAIL : NSS_STATUS_SUCCESS;
}
enum nss_status _nss_systemd_setsgent(int stayopen) {
int r;
PROTECT_ERRNO;
NSS_ENTRYPOINT_BEGIN;
if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getsgent_data.mutex);
(void) _l; /* make llvm shut up about _l not being used. */
getsgent_data.iterator = userdb_iterator_free(getsgent_data.iterator);
getsgent_data.by_membership = false;
/* See _nss_systemd_setpwent() for an explanation why we use USERDB_DONT_SYNTHESIZE here */
r = groupdb_all(nss_glue_userdb_flags() | USERDB_DONT_SYNTHESIZE, &getsgent_data.iterator);
return r < 0 ? NSS_STATUS_UNAVAIL : NSS_STATUS_SUCCESS;
}
enum nss_status _nss_systemd_getpwent_r( enum nss_status _nss_systemd_getpwent_r(
struct passwd *result, struct passwd *result,
char *buffer, size_t buflen, char *buffer, size_t buflen,
@ -527,6 +717,110 @@ enum nss_status _nss_systemd_getgrent_r(
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} }
enum nss_status _nss_systemd_getspent_r(
struct spwd *result,
char *buffer, size_t buflen,
int *errnop) {
_cleanup_(user_record_unrefp) UserRecord *ur = NULL;
int r;
PROTECT_ERRNO;
NSS_ENTRYPOINT_BEGIN;
assert(result);
assert(errnop);
if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getspent_data.mutex);
(void) _l; /* make llvm shut up about _l not being used. */
if (!getspent_data.iterator) {
UNPROTECT_ERRNO;
*errnop = EHOSTDOWN;
return NSS_STATUS_UNAVAIL;
}
for (;;) {
r = userdb_iterator_get(getspent_data.iterator, &ur);
if (r == -ESRCH)
return NSS_STATUS_NOTFOUND;
if (r < 0) {
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
if (!ur->incomplete) /* don't synthesize shadow records for records where we couldn't read shadow data */
break;
ur = user_record_unref(ur);
}
r = nss_pack_user_record_shadow(ur, result, buffer, buflen);
if (r < 0) {
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
}
enum nss_status _nss_systemd_getsgent_r(
struct sgrp *result,
char *buffer, size_t buflen,
int *errnop) {
_cleanup_(group_record_unrefp) GroupRecord *gr = NULL;
int r;
PROTECT_ERRNO;
NSS_ENTRYPOINT_BEGIN;
assert(result);
assert(errnop);
if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getsgent_data.mutex);
(void) _l; /* make llvm shut up about _l not being used. */
if (!getsgent_data.iterator) {
UNPROTECT_ERRNO;
*errnop = EHOSTDOWN;
return NSS_STATUS_UNAVAIL;
}
for (;;) {
r = groupdb_iterator_get(getsgent_data.iterator, &gr);
if (r == -ESRCH)
return NSS_STATUS_NOTFOUND;
if (r < 0) {
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
if (!gr->incomplete) /* don't synthesize shadow records for records where we couldn't read shadow data */
break;
gr = group_record_unref(gr);
}
r = nss_pack_group_record_shadow(gr, result, buffer, buflen);
if (r < 0) {
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
}
enum nss_status _nss_systemd_initgroups_dyn( enum nss_status _nss_systemd_initgroups_dyn(
const char *user_name, const char *user_name,
gid_t gid, gid_t gid,

View File

@ -10,15 +10,23 @@
{ {
global: global:
_nss_systemd_getpwnam_r; _nss_systemd_getpwnam_r;
_nss_systemd_getspnam_r;
_nss_systemd_getpwuid_r; _nss_systemd_getpwuid_r;
_nss_systemd_endpwent; _nss_systemd_endpwent;
_nss_systemd_setpwent; _nss_systemd_setpwent;
_nss_systemd_getpwent_r; _nss_systemd_getpwent_r;
_nss_systemd_endspent;
_nss_systemd_setspent;
_nss_systemd_getspent_r;
_nss_systemd_getgrnam_r; _nss_systemd_getgrnam_r;
_nss_systemd_getsgnam_r;
_nss_systemd_getgrgid_r; _nss_systemd_getgrgid_r;
_nss_systemd_endgrent; _nss_systemd_endgrent;
_nss_systemd_setgrent; _nss_systemd_setgrent;
_nss_systemd_getgrent_r; _nss_systemd_getgrent_r;
_nss_systemd_endsgent;
_nss_systemd_setsgent;
_nss_systemd_getsgent_r;
_nss_systemd_initgroups_dyn; _nss_systemd_initgroups_dyn;
/* These two are not used by glibc, but can be used by apps to explicitly disable nss-systemd for the calling thread. */ /* These two are not used by glibc, but can be used by apps to explicitly disable nss-systemd for the calling thread. */

View File

@ -32,7 +32,7 @@ int nss_pack_user_record(
assert(hr); assert(hr);
assert(pwd); assert(pwd);
assert_se(hr->user_name); assert(hr->user_name);
required = strlen(hr->user_name) + 1; required = strlen(hr->user_name) + 1;
assert_se(rn = user_record_real_name(hr)); assert_se(rn = user_record_real_name(hr));
@ -79,7 +79,7 @@ enum nss_status userdb_getpwnam(
if (_nss_systemd_is_blocked()) if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
r = userdb_by_name(name, nss_glue_userdb_flags(), &hr); r = userdb_by_name(name, nss_glue_userdb_flags()|USERDB_SUPPRESS_SHADOW, &hr);
if (r == -ESRCH) if (r == -ESRCH)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
if (r < 0) { if (r < 0) {
@ -112,7 +112,7 @@ enum nss_status userdb_getpwuid(
if (_nss_systemd_is_blocked()) if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
r = userdb_by_uid(uid, nss_glue_userdb_flags(), &hr); r = userdb_by_uid(uid, nss_glue_userdb_flags()|USERDB_SUPPRESS_SHADOW, &hr);
if (r == -ESRCH) if (r == -ESRCH)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
if (r < 0) { if (r < 0) {
@ -129,6 +129,85 @@ enum nss_status userdb_getpwuid(
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} }
int nss_pack_user_record_shadow(
UserRecord *hr,
struct spwd *spwd,
char *buffer,
size_t buflen) {
const char *hashed;
size_t required;
assert(hr);
assert(spwd);
assert(hr->user_name);
required = strlen(hr->user_name) + 1;
assert_se(hashed = strv_isempty(hr->hashed_password) ? PASSWORD_LOCKED_AND_INVALID : hr->hashed_password[0]);
required += strlen(hashed) + 1;
if (buflen < required)
return -ERANGE;
*spwd = (struct spwd) {
.sp_namp = buffer,
.sp_lstchg = hr->last_password_change_usec == 0 ? 1 : /* map 0 to 1, since 0 means please change pasword on next login */
hr->last_password_change_usec == UINT64_MAX ? -1 :
(long int) (hr->last_password_change_usec / USEC_PER_DAY),
.sp_min = hr->password_change_min_usec != UINT64_MAX ? (long int) (hr->password_change_min_usec / USEC_PER_DAY) : -1,
.sp_max = hr->password_change_max_usec != UINT64_MAX ? (long int) (hr->password_change_max_usec / USEC_PER_DAY) : -1,
.sp_warn = hr->password_change_warn_usec != UINT64_MAX ? (long int) (hr->password_change_warn_usec / USEC_PER_DAY) : -1,
.sp_inact = hr->password_change_inactive_usec != UINT64_MAX ? (long int) (hr->password_change_inactive_usec / USEC_PER_DAY) : -1,
.sp_expire = hr->locked > 0 || hr->not_after_usec == 0 ? 1 : /* already expired/locked */
hr->not_after_usec == UINT64_MAX ? -1 :
(long int) (hr->not_after_usec / USEC_PER_DAY),
.sp_flag = ULONG_MAX,
};
assert(buffer);
spwd->sp_pwdp = stpcpy(spwd->sp_namp, hr->user_name) + 1;
strcpy(spwd->sp_pwdp, hashed);
return 0;
}
enum nss_status userdb_getspnam(
const char *name,
struct spwd *spwd,
char *buffer, size_t buflen,
int *errnop) {
_cleanup_(user_record_unrefp) UserRecord *hr = NULL;
int r;
assert(spwd);
assert(errnop);
if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
r = userdb_by_name(name, nss_glue_userdb_flags(), &hr);
if (r == -ESRCH)
return NSS_STATUS_NOTFOUND;
if (r < 0) {
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
if (hr->incomplete) /* protected records missing? */
return NSS_STATUS_NOTFOUND;
r = nss_pack_user_record_shadow(hr, spwd, buffer, buflen);
if (r < 0) {
*errnop = -r;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
}
int nss_pack_group_record( int nss_pack_group_record(
GroupRecord *g, GroupRecord *g,
char **extra_members, char **extra_members,
@ -142,7 +221,7 @@ int nss_pack_group_record(
assert(g); assert(g);
assert(gr); assert(gr);
assert_se(g->group_name); assert(g->group_name);
required = strlen(g->group_name) + 1; required = strlen(g->group_name) + 1;
STRV_FOREACH(m, g->members) { STRV_FOREACH(m, g->members) {
@ -209,13 +288,13 @@ enum nss_status userdb_getgrnam(
if (_nss_systemd_is_blocked()) if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
r = groupdb_by_name(name, nss_glue_userdb_flags(), &g); r = groupdb_by_name(name, nss_glue_userdb_flags()|USERDB_SUPPRESS_SHADOW, &g);
if (r < 0 && r != -ESRCH) { if (r < 0 && r != -ESRCH) {
*errnop = -r; *errnop = -r;
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
} }
r = membershipdb_by_group_strv(name, nss_glue_userdb_flags(), &members); r = membershipdb_by_group_strv(name, nss_glue_userdb_flags()|USERDB_SUPPRESS_SHADOW, &members);
if (r < 0 && r != -ESRCH) { if (r < 0 && r != -ESRCH) {
*errnop = -r; *errnop = -r;
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
@ -277,7 +356,7 @@ enum nss_status userdb_getgrgid(
if (_nss_systemd_is_blocked()) if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
r = groupdb_by_gid(gid, nss_glue_userdb_flags(), &g); r = groupdb_by_gid(gid, nss_glue_userdb_flags()|USERDB_SUPPRESS_SHADOW, &g);
if (r < 0 && r != -ESRCH) { if (r < 0 && r != -ESRCH) {
*errnop = -r; *errnop = -r;
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
@ -308,7 +387,7 @@ enum nss_status userdb_getgrgid(
} else } else
from_nss = false; from_nss = false;
r = membershipdb_by_group_strv(g->group_name, nss_glue_userdb_flags(), &members); r = membershipdb_by_group_strv(g->group_name, nss_glue_userdb_flags()|USERDB_SUPPRESS_SHADOW, &members);
if (r < 0 && r != -ESRCH) { if (r < 0 && r != -ESRCH) {
*errnop = -r; *errnop = -r;
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
@ -327,3 +406,71 @@ enum nss_status userdb_getgrgid(
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} }
int nss_pack_group_record_shadow(
GroupRecord *hr,
struct sgrp *sgrp,
char *buffer,
size_t buflen) {
const char *hashed;
size_t required;
assert(hr);
assert(sgrp);
assert(hr->group_name);
required = strlen(hr->group_name) + 1;
assert_se(hashed = strv_isempty(hr->hashed_password) ? PASSWORD_LOCKED_AND_INVALID : hr->hashed_password[0]);
required += strlen(hashed) + 1;
if (buflen < required)
return -ERANGE;
*sgrp = (struct sgrp) {
.sg_namp = buffer,
};
assert(buffer);
sgrp->sg_passwd = stpcpy(sgrp->sg_namp, hr->group_name) + 1;
strcpy(sgrp->sg_passwd, hashed);
return 0;
}
enum nss_status userdb_getsgnam(
const char *name,
struct sgrp *sgrp,
char *buffer, size_t buflen,
int *errnop) {
_cleanup_(group_record_unrefp) GroupRecord *hr = NULL;
int r;
assert(sgrp);
assert(errnop);
if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
r = groupdb_by_name(name, nss_glue_userdb_flags(), &hr);
if (r == -ESRCH)
return NSS_STATUS_NOTFOUND;
if (r < 0) {
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
if (hr->incomplete) /* protected records missing? */
return NSS_STATUS_NOTFOUND;
r = nss_pack_group_record_shadow(hr, sgrp, buffer, buflen);
if (r < 0) {
*errnop = -r;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
}

View File

@ -13,8 +13,15 @@ UserDBFlags nss_glue_userdb_flags(void);
int nss_pack_user_record(UserRecord *hr, struct passwd *pwd, char *buffer, size_t buflen); int nss_pack_user_record(UserRecord *hr, struct passwd *pwd, char *buffer, size_t buflen);
int nss_pack_group_record(GroupRecord *g, char **extra_members, struct group *gr, char *buffer, size_t buflen); int nss_pack_group_record(GroupRecord *g, char **extra_members, struct group *gr, char *buffer, size_t buflen);
int nss_pack_user_record_shadow(UserRecord *hr, struct spwd *spwd, char *buffer, size_t buflen);
int nss_pack_group_record_shadow(GroupRecord *hr, struct sgrp *sgrp, char *buffer,size_t buflen);
enum nss_status userdb_getpwnam(const char *name, struct passwd *pwd, char *buffer, size_t buflen, int *errnop); enum nss_status userdb_getpwnam(const char *name, struct passwd *pwd, char *buffer, size_t buflen, int *errnop);
enum nss_status userdb_getpwuid(uid_t uid, struct passwd *pwd, char *buffer, size_t buflen, int *errnop); enum nss_status userdb_getpwuid(uid_t uid, struct passwd *pwd, char *buffer, size_t buflen, int *errnop);
enum nss_status userdb_getspnam(const char *name, struct spwd *spwd, char *buffer, size_t buflen, int *errnop);
enum nss_status userdb_getgrnam(const char *name, struct group *gr, char *buffer, size_t buflen, int *errnop); enum nss_status userdb_getgrnam(const char *name, struct group *gr, char *buffer, size_t buflen, int *errnop);
enum nss_status userdb_getgrgid(gid_t gid, struct group *gr, char *buffer, size_t buflen, int *errnop); enum nss_status userdb_getgrgid(gid_t gid, struct group *gr, char *buffer, size_t buflen, int *errnop);
enum nss_status userdb_getsgnam(const char *name, struct sgrp *sgrp, char *buffer, size_t buflen, int *errnop);

View File

@ -1141,15 +1141,16 @@ void manager_refresh_rrs(Manager *m) {
m->mdns_host_ipv4_key = dns_resource_key_unref(m->mdns_host_ipv4_key); m->mdns_host_ipv4_key = dns_resource_key_unref(m->mdns_host_ipv4_key);
m->mdns_host_ipv6_key = dns_resource_key_unref(m->mdns_host_ipv6_key); m->mdns_host_ipv6_key = dns_resource_key_unref(m->mdns_host_ipv6_key);
HASHMAP_FOREACH(l, m->links)
link_add_rrs(l, true);
if (m->mdns_support == RESOLVE_SUPPORT_YES) if (m->mdns_support == RESOLVE_SUPPORT_YES)
HASHMAP_FOREACH(s, m->dnssd_services) HASHMAP_FOREACH(s, m->dnssd_services)
if (dnssd_update_rrs(s) < 0) if (dnssd_update_rrs(s) < 0)
log_warning("Failed to refresh DNS-SD service '%s'", s->name); log_warning("Failed to refresh DNS-SD service '%s'", s->name);
HASHMAP_FOREACH(l, m->links) { HASHMAP_FOREACH(l, m->links)
link_add_rrs(l, true);
link_add_rrs(l, false); link_add_rrs(l, false);
}
} }
static int manager_next_random_name(const char *old, char **ret_new) { static int manager_next_random_name(const char *old, char **ret_new) {