Compare commits

...

14 Commits

Author SHA1 Message Date
Lennart Poettering 5fe63895b9 docs: introduce documentation category for user/group stuff
We have so many different docs on various facets of user/group stuff,
let's add our own category for it.
2020-04-11 18:03:24 +02:00
Zbigniew Jędrzejewski-Szmek bba97c98b8
Merge pull request #15376 from poettering/homed-btrfs-subvol-luks
homed: when doing luks homedir with btrfs inside, place subvol at top of fs
2020-04-11 16:26:01 +02:00
Zbigniew Jędrzejewski-Szmek 2d9123cebd
Merge pull request #15377 from poettering/userdb-no-shadow
don't try to access shadow from logind
2020-04-11 16:08:33 +02:00
Zbigniew Jędrzejewski-Szmek edc8dd26e2
Merge pull request #15392 from keszybz/flag-helper
Flag setting helper and some other minor cleanups
2020-04-11 16:05:11 +02:00
Zbigniew Jędrzejewski-Szmek 0da965037e Add yet another tiny helper to manipulate flags 2020-04-10 16:40:48 +02:00
Zbigniew Jędrzejewski-Szmek 7d6342e401 man: fix garbled paragraph in systemd.network(3)
The following message was emitted:

  "Element term in namespace  encountered in para, but no template matches."
2020-04-10 16:40:48 +02:00
Zbigniew Jędrzejewski-Szmek 16c347b3b6 busctl: wrap long lines 2020-04-10 16:40:48 +02:00
Zbigniew Jędrzejewski-Szmek 8722b297e5 busctl: use the pager everywhere
There is no reason to assume that the user doesn't want the pager
even if they are looking at xml output or such.
2020-04-10 16:40:29 +02:00
Lennart Poettering b062ca616c logind: avoid shadow lookups when doing userdb client side
Let's not trigger MACs needlessly.

Ideally everybody would turn on userdb, but if people insist in not
doing so, then let's not attempt to open shadow.

It's a bit ugly to implement this, since shadow information is more than
just passwords (but accound validity metadata), and thus userdb's own
"privieleged" scheme is orthogonal to this, but let's still do this for
the client side.

Fixes: #15105
2020-04-09 14:38:14 +02:00
Lennart Poettering ed30170ea0 userdb: when doing client-side NSS look-ups optionally avoid shadow look-ups 2020-04-09 14:38:02 +02:00
Lennart Poettering a1792d1ada pam-systemd-home: drop redundant newline 2020-04-09 14:37:50 +02:00
Lennart Poettering 0be94a199e homed: when creating home directory as btrfs inside luks volume, place subvol inside it
When managing a home directory as LUKS image we currently place a
directory at the top that contains the actual home directory (so that
the home directory of the user won't be cluttered by lost-found and
suchlike). On btrfs let's make that a subvol though. This is a good idea
so that possibly later on we can make use of this for automatic history
management.

Fixes: #15121
2020-04-09 12:13:11 +02:00
Lennart Poettering 82c4440ddd import: use our new btrfs_subvol_make_fallback() at two places 2020-04-09 12:13:08 +02:00
Lennart Poettering d78a95d751 btrfs-util: define helper that creates a btrfs subvol if we can, and a directory as fallback 2020-04-09 12:12:52 +02:00
29 changed files with 224 additions and 148 deletions

View File

@ -1,6 +1,6 @@
---
title: Converting Existing Users to systemd-homed
category: Interfaces
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1,6 +1,6 @@
---
title: JSON Group Records
category: Interfaces
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1,6 +1,6 @@
---
title: Home Directories
category: Concepts
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1,6 +1,6 @@
---
title: Users, Groups, UIDs and GIDs on systemd Systems
category: Concepts
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1,6 +1,6 @@
---
title: systemd-homed and JSON User/Group Record Support in Desktop Environments
category: Interfaces
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1,6 +1,6 @@
---
title: User/Group Record Lookup API via Varlink
category: Interfaces
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1,6 +1,6 @@
---
title: User/Group Name Syntax
category: Concepts
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1,6 +1,6 @@
---
title: JSON User Records
category: Interfaces
category: Users, Groups and Home Directories
layout: default
---

View File

@ -1930,10 +1930,9 @@
<varlistentry>
<term><varname>POP3Servers=</varname></term>
<listitem><para>Similar to the <varname>DNS=</varname> settings described above, these
settings configure whether and what POP3 server information shall be emitted as part of
the DHCP lease. The same syntax, propagation semantics and defaults apply as for
<term><varname>SMTPServers=</varname></term>
<listitem><para>Similar to the <varname>DNS=</varname> setting described above, this setting
configures whether and what POP3 server information shall be emitted as part of the DHCP lease. The
same syntax, propagation semantics and defaults apply as for
<varname>DNS=</varname>.</para></listitem>
</varlistentry>

View File

@ -160,6 +160,31 @@ int btrfs_subvol_make(const char *path) {
return btrfs_subvol_make_fd(fd, subvolume);
}
int btrfs_subvol_make_fallback(const char *path, mode_t mode) {
mode_t old, combined;
int r;
assert(path);
/* Let's work like mkdir(), i.e. take the specified mode, and mask it with the current umask. */
old = umask(~mode);
combined = old | ~mode;
if (combined != ~mode)
umask(combined);
r = btrfs_subvol_make(path);
umask(old);
if (r >= 0)
return 1; /* subvol worked */
if (r != -ENOTTY)
return r;
if (mkdir(path, mode) < 0)
return -errno;
return 0; /* plain directory */
}
int btrfs_subvol_set_read_only_fd(int fd, bool b) {
uint64_t flags, nflags;
struct stat st;
@ -175,11 +200,7 @@ int btrfs_subvol_set_read_only_fd(int fd, bool b) {
if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
return -errno;
if (b)
nflags = flags | BTRFS_SUBVOL_RDONLY;
else
nflags = flags & ~BTRFS_SUBVOL_RDONLY;
nflags = UPDATE_FLAG(flags, BTRFS_SUBVOL_RDONLY, b);
if (flags == nflags)
return 0;

View File

@ -66,6 +66,8 @@ int btrfs_quota_scan_ongoing(int fd);
int btrfs_subvol_make(const char *path);
int btrfs_subvol_make_fd(int fd, const char *subvolume);
int btrfs_subvol_make_fallback(const char *path, mode_t);
int btrfs_subvol_snapshot_fd_full(int old_fd, const char *new_path, BtrfsSnapshotFlags flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
static inline int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
return btrfs_subvol_snapshot_fd_full(old_fd, new_path, flags, NULL, NULL, NULL);

View File

@ -144,11 +144,7 @@ int fd_nonblock(int fd, bool nonblock) {
if (flags < 0)
return -errno;
if (nonblock)
nflags = flags | O_NONBLOCK;
else
nflags = flags & ~O_NONBLOCK;
nflags = UPDATE_FLAG(flags, O_NONBLOCK, nonblock);
if (nflags == flags)
return 0;
@ -167,11 +163,7 @@ int fd_cloexec(int fd, bool cloexec) {
if (flags < 0)
return -errno;
if (cloexec)
nflags = flags | FD_CLOEXEC;
else
nflags = flags & ~FD_CLOEXEC;
nflags = UPDATE_FLAG(flags, FD_CLOEXEC, cloexec);
if (nflags == flags)
return 0;

View File

@ -451,8 +451,10 @@ static inline int __coverity_check_and_return__(int condition) {
ans; \
})
#define UPDATE_FLAG(orig, flag, b) \
((b) ? ((orig) | (flag)) : ((orig) & ~(flag)))
#define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
(v) = UPDATE_FLAG(v, flag, b)
#define FLAGS_SET(v, flags) \
((~(v) & (flags)) == 0)

View File

@ -101,7 +101,8 @@ static int acquire_bus(bool set_monitor, sd_bus **ret) {
r = sd_bus_set_watch_bind(bus, arg_watch_bind);
if (r < 0)
return log_error_errno(r, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind));
return log_error_errno(r, "Failed to set watch-bind setting to '%s': %m",
yes_no(arg_watch_bind));
if (arg_address)
r = sd_bus_set_address(bus, arg_address);
@ -172,7 +173,9 @@ static int list_bus_names(int argc, char **argv, void *userdata) {
if (r < 0)
return r;
r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
r = sd_bus_list_names(bus,
(arg_acquired || arg_unique) ? &acquired : NULL,
arg_activatable ? &activatable : NULL);
if (r < 0)
return log_error_errno(r, "Failed to list names: %m");
@ -192,7 +195,16 @@ static int list_bus_names(int argc, char **argv, void *userdata) {
return log_error_errno(r, "Failed to add to hashmap: %m");
}
table = table_new("activatable", "name", "pid", "process", "user", "connection", "unit", "session", "description", "machine");
table = table_new("activatable",
"name",
"pid",
"process",
"user",
"connection",
"unit",
"session",
"description",
"machine");
if (!table)
return log_oom();
@ -354,11 +366,11 @@ static int list_bus_names(int argc, char **argv, void *userdata) {
return log_error_errno(r, "Failed to fill line: %m");
}
if (IN_SET(arg_json, JSON_OFF, JSON_PRETTY))
(void) pager_open(arg_pager_flags);
if (arg_json)
r = table_print_json(table, stdout, (arg_json == JSON_PRETTY ? JSON_FORMAT_PRETTY : JSON_FORMAT_NEWLINE) | JSON_FORMAT_COLOR_AUTO);
r = table_print_json(table, stdout,
(arg_json == JSON_PRETTY ? JSON_FORMAT_PRETTY : JSON_FORMAT_NEWLINE) | JSON_FORMAT_COLOR_AUTO);
else
r = table_print(table, stdout);
if (r < 0)
@ -405,7 +417,10 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
n++;
}
printf("%s%s%s\n", prefix, special_glyph(has_more ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT), *l);
printf("%s%s%s\n",
prefix,
special_glyph(has_more ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT),
*l);
print_subtree(has_more ? vertical : space, *l, l);
l = n;
@ -460,12 +475,16 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
const char *xml;
int r;
r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
r = sd_bus_call_method(bus, service, path,
"org.freedesktop.DBus.Introspectable", "Introspect",
&error, &reply, "");
if (r < 0) {
if (many)
printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r));
printf("Failed to introspect object %s of service %s: %s\n",
path, service, bus_error_message(&error, r));
else
log_error_errno(r, "Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
log_error_errno(r, "Failed to introspect object %s of service %s: %s",
path, service, bus_error_message(&error, r));
return r;
}
@ -994,9 +1013,12 @@ static int introspect(int argc, char **argv, void *userdata) {
if (!members)
return log_oom();
r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply_xml, "");
r = sd_bus_call_method(bus, argv[1], argv[2],
"org.freedesktop.DBus.Introspectable", "Introspect",
&error, &reply_xml, "");
if (r < 0)
return log_error_errno(r, "Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r));
return log_error_errno(r, "Failed to introspect object %s of service %s: %s",
argv[2], argv[1], bus_error_message(&error, r));
r = sd_bus_message_read(reply_xml, "s", &xml);
if (r < 0)
@ -1004,6 +1026,7 @@ static int introspect(int argc, char **argv, void *userdata) {
if (arg_xml_interface) {
/* Just dump the received XML and finish */
(void) pager_open(arg_pager_flags);
puts(xml);
return 0;
}
@ -1026,7 +1049,9 @@ static int introspect(int argc, char **argv, void *userdata) {
if (argv[3] && !streq(argv[3], m->interface))
continue;
r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface);
r = sd_bus_call_method(bus, argv[1], argv[2],
"org.freedesktop.DBus.Properties", "GetAll",
&error, &reply, "s", m->interface);
if (r < 0)
return log_error_errno(r, "Failed to get all properties on interface %s: %s",
m->interface, bus_error_message(&error, r));
@ -1088,17 +1113,14 @@ static int introspect(int argc, char **argv, void *userdata) {
return bus_log_parse_error(r);
}
(void) pager_open(arg_pager_flags);
name_width = STRLEN("NAME");
type_width = STRLEN("TYPE");
signature_width = STRLEN("SIGNATURE");
result_width = STRLEN("RESULT/VALUE");
name_width = strlen("NAME");
type_width = strlen("TYPE");
signature_width = strlen("SIGNATURE");
result_width = strlen("RESULT/VALUE");
sorted = newa(Member*, set_size(members));
SET_FOREACH(m, members, i) {
if (argv[3] && !streq(argv[3], m->interface))
continue;
@ -1123,6 +1145,8 @@ static int introspect(int argc, char **argv, void *userdata) {
typesafe_qsort(sorted, k, member_compare_funcp);
(void) pager_open(arg_pager_flags);
if (arg_legend) {
printf("%-*s %-*s %-*s %-*s %s\n",
(int) name_width, "NAME",
@ -1159,7 +1183,8 @@ static int introspect(int argc, char **argv, void *userdata) {
printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
is_interface ? ansi_highlight() : "",
is_interface ? "" : ".",
- !is_interface + (int) name_width, empty_to_dash(streq_ptr(m->type, "interface") ? m->interface : m->name),
- !is_interface + (int) name_width,
empty_to_dash(streq_ptr(m->type, "interface") ? m->interface : m->name),
is_interface ? ansi_normal() : "",
(int) type_width, empty_to_dash(m->type),
(int) signature_width, empty_to_dash(m->signature),
@ -1375,6 +1400,8 @@ static int status(int argc, char **argv, void *userdata) {
if (r < 0)
return r;
(void) pager_open(arg_pager_flags);
if (!isempty(argv[1])) {
r = parse_pid(argv[1], &pid);
if (r < 0)
@ -1402,7 +1429,8 @@ static int status(int argc, char **argv, void *userdata) {
r = sd_bus_get_bus_id(bus, &bus_id);
if (r >= 0)
printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal());
printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n",
ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal());
r = sd_bus_get_owner_creds(
bus,
@ -1562,7 +1590,6 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
return log_error_errno(r, "Invalid array signature: %m");
{
unsigned i;
char s[k + 1];
memcpy(s, signature, k);
s[k] = 0;
@ -1571,7 +1598,7 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
if (r < 0)
return bus_log_create_error(r);
for (i = 0; i < n; i++) {
for (unsigned i = 0; i < n; i++) {
r = message_append_cmdline(m, s, &p);
if (r < 0)
return r;
@ -1612,7 +1639,9 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
memcpy(s, signature + 1, k - 2);
s[k - 2] = 0;
r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
const char ctype = t == SD_BUS_TYPE_STRUCT_BEGIN ?
SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
r = sd_bus_message_open_container(m, ctype, s);
if (r < 0)
return bus_log_create_error(r);
@ -2033,7 +2062,8 @@ static int call(int argc, char **argv, void *userdata) {
return r;
if (*p)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many parameters for signature.");
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Too many parameters for signature.");
}
if (!arg_expect_reply) {
@ -2121,7 +2151,8 @@ static int emit_signal(int argc, char **argv, void *userdata) {
return r;
if (*p)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many parameters for signature.");
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Too many parameters for signature.");
}
r = sd_bus_send(bus, m, NULL);
@ -2146,7 +2177,9 @@ static int get_property(int argc, char **argv, void *userdata) {
const char *contents = NULL;
char type;
r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i);
r = sd_bus_call_method(bus, argv[1], argv[2],
"org.freedesktop.DBus.Properties", "Get",
&error, &reply, "ss", argv[3], *i);
if (r < 0)
return log_error_errno(r, "Failed to get property %s on interface %s: %s",
*i, argv[3],
@ -2208,7 +2241,8 @@ static int set_property(int argc, char **argv, void *userdata) {
if (r < 0)
return r;
r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set");
r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2],
"org.freedesktop.DBus.Properties", "Set");
if (r < 0)
return bus_log_create_error(r);

View File

@ -8,6 +8,7 @@
#include "blkid-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
#include "chattr-util.h"
#include "dm-util.h"
#include "errno-util.h"
@ -2037,8 +2038,10 @@ int home_create_luks(
goto fail;
}
if (mkdir(subdir, 0700) < 0) {
r = log_error_errno(errno, "Failed to create user directory in mounted image file: %m");
/* Prefer using a btrfs subvolume if we can, fall back to directory otherwise */
r = btrfs_subvol_make_fallback(subdir, 0700);
if (r < 0) {
log_error_errno(r, "Failed to create user directory in mounted image file: %m");
goto fail;
}

View File

@ -877,7 +877,6 @@ _public_ PAM_EXTERN int pam_sm_chauthtok(
if (FLAGS_SET(flags, PAM_PRELIM_CHECK))
return PAM_SUCCESS;
old_secret = user_record_new();
if (!old_secret)
return pam_log_oom(handle);

View File

@ -220,13 +220,10 @@ static int tar_import_fork_tar(TarImport *i) {
(void) mkdir_parents_label(i->temp_path, 0700);
r = btrfs_subvol_make(i->temp_path);
if (r == -ENOTTY) {
if (mkdir(i->temp_path, 0755) < 0)
return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path);
} else if (r < 0)
return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path);
else
r = btrfs_subvol_make_fallback(i->temp_path, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create directory/subvolume %s: %m", i->temp_path);
if (r > 0) /* actually btrfs subvol */
(void) import_assign_pool_quota_and_warn(i->temp_path);
i->tar_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);

View File

@ -415,13 +415,10 @@ static int tar_pull_job_on_open_disk_tar(PullJob *j) {
mkdir_parents_label(i->temp_path, 0700);
r = btrfs_subvol_make(i->temp_path);
if (r == -ENOTTY) {
if (mkdir(i->temp_path, 0755) < 0)
return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path);
} else if (r < 0)
return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path);
else
r = btrfs_subvol_make_fallback(i->temp_path, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create directory/subvolume %s: %m", i->temp_path);
if (r > 0) /* actually btrfs subvol */
(void) import_assign_pool_quota_and_warn(i->temp_path);
j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);

View File

@ -171,7 +171,7 @@ int manager_add_user_by_name(
assert(m);
assert(name);
r = userdb_by_name(name, 0, &ur);
r = userdb_by_name(name, USERDB_AVOID_SHADOW, &ur);
if (r < 0)
return r;
@ -189,7 +189,7 @@ int manager_add_user_by_uid(
assert(m);
assert(uid_is_valid(uid));
r = userdb_by_uid(uid, 0, &ur);
r = userdb_by_uid(uid, USERDB_AVOID_SHADOW, &ur);
if (r < 0)
return r;

View File

@ -482,7 +482,7 @@ enum nss_status _nss_systemd_getgrent_r(
}
}
r = nss_group_record_by_name(group_name, &gr);
r = nss_group_record_by_name(group_name, false, &gr);
if (r == -ESRCH)
continue;
if (r < 0) {

View File

@ -251,7 +251,7 @@ enum nss_status userdb_getgrnam(
if (lock_fd < 0 && lock_fd != -EBUSY)
return lock_fd;
r = nss_group_record_by_name(name, &g);
r = nss_group_record_by_name(name, false, &g);
if (r == -ESRCH)
return NSS_STATUS_NOTFOUND;
if (r < 0) {
@ -310,7 +310,7 @@ enum nss_status userdb_getgrgid(
if (lock_fd < 0 && lock_fd != -EBUSY)
return lock_fd;
r = nss_group_record_by_gid(gid, &g);
r = nss_group_record_by_gid(gid, false, &g);
if (r == -ESRCH)
return NSS_STATUS_NOTFOUND;

View File

@ -135,10 +135,7 @@ int efi_set_reboot_to_firmware(bool value) {
if (r < 0)
return r;
if (value)
b_new = b | EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
else
b_new = b & ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
b_new = UPDATE_FLAG(b, EFI_OS_INDICATIONS_BOOT_TO_FW_UI, value);
/* Avoid writing to efi vars store if we can due to firmware bugs. */
if (b != b_new)

View File

@ -106,12 +106,16 @@ int nss_sgrp_for_group(const struct group *grp, struct sgrp *ret_sgrp, char **re
}
}
int nss_group_record_by_name(const char *name, GroupRecord **ret) {
int nss_group_record_by_name(
const char *name,
bool with_shadow,
GroupRecord **ret) {
_cleanup_free_ char *buf = NULL, *sbuf = NULL;
struct group grp, *result;
bool incomplete = false;
size_t buflen = 4096;
struct sgrp sgrp;
struct sgrp sgrp, *sresult = NULL;
int r;
assert(name);
@ -141,13 +145,17 @@ int nss_group_record_by_name(const char *name, GroupRecord **ret) {
buf = mfree(buf);
}
if (with_shadow) {
r = nss_sgrp_for_group(result, &sgrp, &sbuf);
if (r < 0) {
log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name);
incomplete = ERRNO_IS_PRIVILEGE(r);
}
} else
sresult = &sgrp;
} else
incomplete = true;
r = nss_group_to_group_record(result, r >= 0 ? &sgrp : NULL, ret);
r = nss_group_to_group_record(result, sresult, ret);
if (r < 0)
return r;
@ -155,12 +163,16 @@ int nss_group_record_by_name(const char *name, GroupRecord **ret) {
return 0;
}
int nss_group_record_by_gid(gid_t gid, GroupRecord **ret) {
int nss_group_record_by_gid(
gid_t gid,
bool with_shadow,
GroupRecord **ret) {
_cleanup_free_ char *buf = NULL, *sbuf = NULL;
struct group grp, *result;
bool incomplete = false;
size_t buflen = 4096;
struct sgrp sgrp;
struct sgrp sgrp, *sresult = NULL;
int r;
assert(ret);
@ -188,13 +200,17 @@ int nss_group_record_by_gid(gid_t gid, GroupRecord **ret) {
buf = mfree(buf);
}
if (with_shadow) {
r = nss_sgrp_for_group(result, &sgrp, &sbuf);
if (r < 0) {
log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name);
incomplete = ERRNO_IS_PRIVILEGE(r);
}
} else
sresult = &sgrp;
} else
incomplete = true;
r = nss_group_to_group_record(result, r >= 0 ? &sgrp : NULL, ret);
r = nss_group_to_group_record(result, sresult, ret);
if (r < 0)
return r;

View File

@ -11,5 +11,5 @@
int nss_group_to_group_record(const struct group *grp, const struct sgrp *sgrp, GroupRecord **ret);
int nss_sgrp_for_group(const struct group *grp, struct sgrp *ret_sgrp, char **ret_buffer);
int nss_group_record_by_name(const char *name, GroupRecord **ret);
int nss_group_record_by_gid(gid_t gid, GroupRecord **ret);
int nss_group_record_by_name(const char *name, bool with_shadow, GroupRecord **ret);
int nss_group_record_by_gid(gid_t gid, bool with_shadow, GroupRecord **ret);

View File

@ -161,12 +161,16 @@ int nss_spwd_for_passwd(const struct passwd *pwd, struct spwd *ret_spwd, char **
}
}
int nss_user_record_by_name(const char *name, UserRecord **ret) {
int nss_user_record_by_name(
const char *name,
bool with_shadow,
UserRecord **ret) {
_cleanup_free_ char *buf = NULL, *sbuf = NULL;
struct passwd pwd, *result;
bool incomplete = false;
size_t buflen = 4096;
struct spwd spwd;
struct spwd spwd, *sresult = NULL;
int r;
assert(name);
@ -197,13 +201,17 @@ int nss_user_record_by_name(const char *name, UserRecord **ret) {
buf = mfree(buf);
}
if (with_shadow) {
r = nss_spwd_for_passwd(result, &spwd, &sbuf);
if (r < 0) {
log_debug_errno(r, "Failed to do shadow lookup for user %s, ignoring: %m", name);
incomplete = ERRNO_IS_PRIVILEGE(r);
}
} else
sresult = &spwd;
} else
incomplete = true;
r = nss_passwd_to_user_record(result, r >= 0 ? &spwd : NULL, ret);
r = nss_passwd_to_user_record(result, sresult, ret);
if (r < 0)
return r;
@ -211,12 +219,16 @@ int nss_user_record_by_name(const char *name, UserRecord **ret) {
return 0;
}
int nss_user_record_by_uid(uid_t uid, UserRecord **ret) {
int nss_user_record_by_uid(
uid_t uid,
bool with_shadow,
UserRecord **ret) {
_cleanup_free_ char *buf = NULL, *sbuf = NULL;
struct passwd pwd, *result;
bool incomplete = false;
size_t buflen = 4096;
struct spwd spwd;
struct spwd spwd, *sresult = NULL;
int r;
assert(ret);
@ -245,13 +257,17 @@ int nss_user_record_by_uid(uid_t uid, UserRecord **ret) {
buf = mfree(buf);
}
if (with_shadow) {
r = nss_spwd_for_passwd(result, &spwd, &sbuf);
if (r < 0) {
log_debug_errno(r, "Failed to do shadow lookup for UID " UID_FMT ", ignoring: %m", uid);
incomplete = ERRNO_IS_PRIVILEGE(r);
}
} else
sresult = &spwd;
} else
incomplete = true;
r = nss_passwd_to_user_record(result, r >= 0 ? &spwd : NULL, ret);
r = nss_passwd_to_user_record(result, sresult, ret);
if (r < 0)
return r;

View File

@ -11,5 +11,5 @@
int nss_passwd_to_user_record(const struct passwd *pwd, const struct spwd *spwd, UserRecord **ret);
int nss_spwd_for_passwd(const struct passwd *pwd, struct spwd *ret_spwd, char **ret_buffer);
int nss_user_record_by_name(const char *name, UserRecord **ret);
int nss_user_record_by_uid(uid_t uid, UserRecord **ret);
int nss_user_record_by_name(const char *name, bool with_shadow, UserRecord **ret);
int nss_user_record_by_uid(uid_t uid, bool with_shadow, UserRecord **ret);

View File

@ -614,7 +614,7 @@ int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
iterator->nss_lock = r;
/* Client-side NSS fallback */
r = nss_user_record_by_name(name, ret);
r = nss_user_record_by_name(name, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
return r;
}
@ -661,7 +661,7 @@ int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
iterator->nss_lock = r;
/* Client-side NSS fallback */
r = nss_user_record_by_uid(uid, ret);
r = nss_user_record_by_uid(uid, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
return r;
}
@ -819,7 +819,7 @@ int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
if (r >= 0 || r == -EBUSY) {
iterator->nss_lock = r;
r = nss_group_record_by_name(name, ret);
r = nss_group_record_by_name(name, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
return r;
}
@ -865,7 +865,7 @@ int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
if (r >= 0 || r == -EBUSY) {
iterator->nss_lock = r;
r = nss_group_record_by_gid(gid, ret);
r = nss_group_record_by_gid(gid, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
return r;
}
@ -1046,7 +1046,7 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **
return iterator->nss_lock;
/* We ignore all errors here, since the group might be defined by a userdb native service, and we queried them already above. */
(void) nss_group_record_by_name(name, &gr);
(void) nss_group_record_by_name(name, false, &gr);
if (gr) {
iterator->members_of_group = strv_copy(gr->members);
if (!iterator->members_of_group)

View File

@ -16,9 +16,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(UserDBIterator*, userdb_iterator_free);
typedef enum UserDBFlags {
USERDB_AVOID_NSS = 1 << 0, /* don't do client-side nor server-side NSS */
USERDB_AVOID_DYNAMIC_USER = 1 << 1, /* exclude looking up in io.systemd.DynamicUser */
USERDB_AVOID_MULTIPLEXER = 1 << 2, /* exclude looking up via io.systemd.Multiplexer */
USERDB_DONT_SYNTHESIZE = 1 << 3, /* don't synthesize root/nobody */
USERDB_AVOID_SHADOW = 1 << 1, /* don't do client-side shadow calls (server side might happen though) */
USERDB_AVOID_DYNAMIC_USER = 1 << 2, /* exclude looking up in io.systemd.DynamicUser */
USERDB_AVOID_MULTIPLEXER = 1 << 3, /* exclude looking up via io.systemd.Multiplexer */
USERDB_DONT_SYNTHESIZE = 1 << 4, /* don't synthesize root/nobody */
} UserDBFlags;
int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret);

View File

@ -137,9 +137,9 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
if (streq_ptr(p.service, "io.systemd.NameServiceSwitch")) {
if (uid_is_valid(p.uid))
r = nss_user_record_by_uid(p.uid, &hr);
r = nss_user_record_by_uid(p.uid, true, &hr);
else if (p.user_name)
r = nss_user_record_by_name(p.user_name, &hr);
r = nss_user_record_by_name(p.user_name, true, &hr);
else {
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
@ -324,9 +324,9 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
if (streq_ptr(p.service, "io.systemd.NameServiceSwitch")) {
if (gid_is_valid(p.gid))
r = nss_group_record_by_gid(p.gid, &g);
r = nss_group_record_by_gid(p.gid, true, &g);
else if (p.group_name)
r = nss_group_record_by_name(p.group_name, &g);
r = nss_group_record_by_name(p.group_name, true, &g);
else {
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
@ -467,7 +467,7 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
const char *last = NULL;
char **i;
r = nss_group_record_by_name(p.group_name, &g);
r = nss_group_record_by_name(p.group_name, true, &g);
if (r == -ESRCH)
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
if (r < 0)