]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
userdb: when doing client-side NSS look-ups optionally avoid shadow look-ups
authorLennart Poettering <lennart@poettering.net>
Thu, 9 Apr 2020 12:28:34 +0000 (14:28 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 9 Apr 2020 12:38:02 +0000 (14:38 +0200)
src/nss-systemd/nss-systemd.c
src/nss-systemd/userdb-glue.c
src/shared/group-record-nss.c
src/shared/group-record-nss.h
src/shared/user-record-nss.c
src/shared/user-record-nss.h
src/shared/userdb.c
src/shared/userdb.h
src/userdb/userwork.c

index 581b7959bd06a27c94288a49c03b2f5dedd3e243..058119742f85db9804818c8e490a5df9b857c9f0 100644 (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) {
index 58915c3d23dde6f75e301b6b4ce08fb72d06f12d..a88b0d750234f33890f8fe11cab8679b19850594 100644 (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;
 
index 77924f1c4067e077f9af65ef510d10726968d701..5c4fae865aefa0700d038598819c4d1b0f0f7a48 100644 (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);
         }
 
-        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);
-        }
-
-        r = nss_group_to_group_record(result, r >= 0 ? &sgrp : NULL, ret);
+        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, 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);
-        }
-
-        r = nss_group_to_group_record(result, r >= 0 ? &sgrp : NULL, ret);
+        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, sresult, ret);
         if (r < 0)
                 return r;
 
index 38b2995178ff7d90629e829e62d35698d49fd9fb..077c22d89f12b4a65476a8e7f9fe2a55b60a1a61 100644 (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);
index 0ff6d1711753d189bcac907c199da1846979a5b6..f265a2af9333e24457cd634b77cbb77ab0840090 100644 (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);
         }
 
-        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;
 
index d5fb23ad2a294f66e3a468be2e08254f959c954b..0eb78d5b52a374a0f89e7363f90759be57e88af4 100644 (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);
index 92f8796768d7f9a24df65ee88c9c267bfba84343..11ab267b03b36e4eb89760b1b029f6ed48a3cd5f 100644 (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)
index 4288b0ff95dfc85634039ee198af9d0544cdb856..8af31aa86c62a810b05ee7ee772baa2690de6ec9 100644 (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);
index 3bc5ecc1d0393d47ceffac5e34c8393c181bd617..053448a7184010ac940e9cd4a0866cc484f4f587 100644 (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)