diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index 581b7959bd0..058119742f8 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -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) { diff --git a/src/nss-systemd/userdb-glue.c b/src/nss-systemd/userdb-glue.c index 58915c3d23d..a88b0d75023 100644 --- a/src/nss-systemd/userdb-glue.c +++ b/src/nss-systemd/userdb-glue.c @@ -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; diff --git a/src/shared/group-record-nss.c b/src/shared/group-record-nss.c index 77924f1c406..5c4fae865ae 100644 --- a/src/shared/group-record-nss.c +++ b/src/shared/group-record-nss.c @@ -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); } - 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); - } + 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); } - 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); - } + 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; diff --git a/src/shared/group-record-nss.h b/src/shared/group-record-nss.h index 38b2995178f..077c22d89f1 100644 --- a/src/shared/group-record-nss.h +++ b/src/shared/group-record-nss.h @@ -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); diff --git a/src/shared/user-record-nss.c b/src/shared/user-record-nss.c index 0ff6d171175..f265a2af933 100644 --- a/src/shared/user-record-nss.c +++ b/src/shared/user-record-nss.c @@ -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); } - 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); - } + 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); } - 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); - } + 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; diff --git a/src/shared/user-record-nss.h b/src/shared/user-record-nss.h index d5fb23ad2a2..0eb78d5b52a 100644 --- a/src/shared/user-record-nss.h +++ b/src/shared/user-record-nss.h @@ -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); diff --git a/src/shared/userdb.c b/src/shared/userdb.c index 92f8796768d..11ab267b03b 100644 --- a/src/shared/userdb.c +++ b/src/shared/userdb.c @@ -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) diff --git a/src/shared/userdb.h b/src/shared/userdb.h index 4288b0ff95d..8af31aa86c6 100644 --- a/src/shared/userdb.h +++ b/src/shared/userdb.h @@ -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); diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c index 3bc5ecc1d03..053448a7184 100644 --- a/src/userdb/userwork.c +++ b/src/userdb/userwork.c @@ -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)