From a1792d1adaf3a6445d1ed242b5a88417375d0e3a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 9 Apr 2020 14:27:57 +0200 Subject: [PATCH 1/3] pam-systemd-home: drop redundant newline --- src/home/pam_systemd_home.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c index 440ed85e2c..a202de1785 100644 --- a/src/home/pam_systemd_home.c +++ b/src/home/pam_systemd_home.c @@ -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); From ed30170ea03195d491c59b1d161325275127d620 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 9 Apr 2020 14:28:34 +0200 Subject: [PATCH 2/3] userdb: when doing client-side NSS look-ups optionally avoid shadow look-ups --- src/nss-systemd/nss-systemd.c | 2 +- src/nss-systemd/userdb-glue.c | 4 +-- src/shared/group-record-nss.c | 48 +++++++++++++++++++++++------------ src/shared/group-record-nss.h | 4 +-- src/shared/user-record-nss.c | 48 +++++++++++++++++++++++------------ src/shared/user-record-nss.h | 4 +-- src/shared/userdb.c | 10 ++++---- src/shared/userdb.h | 7 ++--- src/userdb/userwork.c | 10 ++++---- 9 files changed, 85 insertions(+), 52 deletions(-) diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index 581b7959bd..058119742f 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 58915c3d23..a88b0d7502 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 77924f1c40..5c4fae865a 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 38b2995178..077c22d89f 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 0ff6d17117..f265a2af93 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 d5fb23ad2a..0eb78d5b52 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 92f8796768..11ab267b03 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 4288b0ff95..8af31aa86c 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 3bc5ecc1d0..053448a718 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) From b062ca616c778358d4da008a2950615fac74aa24 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 9 Apr 2020 14:28:56 +0200 Subject: [PATCH 3/3] 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 --- src/login/logind-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 22a42b077c..a9006d746a 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -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;