#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)
static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
char **s = userdata;
const char *n;
- int r;
if (json_variant_is_null(variant)) {
*s = mfree(*s);
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
n = json_variant_string(variant);
- if (!valid_gecos(n))
- return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible real name.", strna(name));
+ if (valid_gecos(n)) {
+ if (free_and_strdup(s, n) < 0)
+ return json_log_oom(variant, flags);
+ } else {
+ _cleanup_free_ char *m = NULL;
- r = free_and_strdup(s, n);
- if (r < 0)
- return json_log(variant, flags, r, "Failed to allocate string: %m");
+ json_log(variant, flags|JSON_DEBUG, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible string, mangling.", strna(name));
+
+ m = mangle_gecos(n);
+ if (!m)
+ return json_log_oom(variant, flags);
+
+ free_and_replace(*s, m);
+ }
return 0;
}