#include "libcrypt-util.h"
#include "strv.h"
#include "user-record-nss.h"
+#include "user-util.h"
#define SET_IF(field, condition, value, fallback) \
field = (condition) ? (value) : (fallback)
if (r < 0)
return r;
- r = free_and_strdup(&hr->real_name,
- streq_ptr(pwd->pw_gecos, hr->user_name) ? NULL : empty_to_null(pwd->pw_gecos));
- if (r < 0)
- return r;
+ /* Some bad NSS modules synthesize GECOS fields with embedded ":" or "\n" characters, which are not
+ * something we can output in /etc/passwd compatible format, since these are record separators
+ * there. We normally refuse that, but we need to maintain compatibility with arbitrary NSS modules,
+ * hence let's do what glibc does: mangle the data to fit the format. */
+ if (isempty(pwd->pw_gecos) || streq_ptr(pwd->pw_gecos, hr->user_name))
+ hr->real_name = mfree(hr->real_name);
+ else if (valid_gecos(pwd->pw_gecos)) {
+ r = free_and_strdup(&hr->real_name, pwd->pw_gecos);
+ if (r < 0)
+ return r;
+ } else {
+ _cleanup_free_ char *mangled = NULL;
+
+ mangled = mangle_gecos(pwd->pw_gecos);
+ if (!mangled)
+ return -ENOMEM;
+
+ free_and_replace(hr->real_name, mangled);
+ }
r = free_and_strdup(&hr->home_directory, empty_to_null(pwd->pw_dir));
if (r < 0)
}
}
-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);
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;
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);
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;