]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/userdb.c
mkosi: update arch commit reference
[thirdparty/systemd.git] / src / shared / userdb.c
index a77eff4407a49c7c12d316328d6d4749788619f3..c893876eaffc8399cf487440d5badb93e0f03260 100644 (file)
@@ -2,12 +2,15 @@
 
 #include <sys/auxv.h>
 
 
 #include <sys/auxv.h>
 
+#include "sd-varlink.h"
+
 #include "conf-files.h"
 #include "dirent-util.h"
 #include "dlfcn-util.h"
 #include "errno-util.h"
 #include "fd-util.h"
 #include "format-util.h"
 #include "conf-files.h"
 #include "dirent-util.h"
 #include "dlfcn-util.h"
 #include "errno-util.h"
 #include "fd-util.h"
 #include "format-util.h"
+#include "json-util.h"
 #include "missing_syscall.h"
 #include "parse-util.h"
 #include "set.h"
 #include "missing_syscall.h"
 #include "parse-util.h"
 #include "set.h"
@@ -17,9 +20,8 @@
 #include "user-util.h"
 #include "userdb-dropin.h"
 #include "userdb.h"
 #include "user-util.h"
 #include "userdb-dropin.h"
 #include "userdb.h"
-#include "varlink.h"
 
 
-DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(link_hash_ops, void, trivial_hash_func, trivial_compare_func, Varlink, varlink_unref);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(link_hash_ops, void, trivial_hash_func, trivial_compare_func, sd_varlink, sd_varlink_unref);
 
 typedef enum LookupWhat {
         LOOKUP_USER,
 
 typedef enum LookupWhat {
         LOOKUP_USER,
@@ -138,19 +140,29 @@ static int userdb_iterator_block_nss_systemd(UserDBIterator *iterator) {
 }
 
 struct user_group_data {
 }
 
 struct user_group_data {
-        JsonVariant *record;
+        sd_json_variant *record;
         bool incomplete;
 };
 
         bool incomplete;
 };
 
-static void user_group_data_release(struct user_group_data *d) {
-        json_variant_unref(d->record);
+static void user_group_data_done(struct user_group_data *d) {
+        sd_json_variant_unref(d->record);
+}
+
+struct membership_data {
+        char *user_name;
+        char *group_name;
+};
+
+static void membership_data_done(struct membership_data *d) {
+        free(d->user_name);
+        free(d->group_name);
 }
 
 static int userdb_on_query_reply(
 }
 
 static int userdb_on_query_reply(
-                Varlink *link,
-                JsonVariant *parameters,
+                sd_varlink *link,
+                sd_json_variant *parameters,
                 const char *error_id,
                 const char *error_id,
-                VarlinkReplyFlags flags,
+                sd_varlink_reply_flags_t flags,
                 void *userdata) {
 
         UserDBIterator *iterator = ASSERT_PTR(userdata);
                 void *userdata) {
 
         UserDBIterator *iterator = ASSERT_PTR(userdata);
@@ -167,7 +179,7 @@ static int userdb_on_query_reply(
                         r = -EHOSTDOWN;
                 else if (streq(error_id, "io.systemd.UserDatabase.EnumerationNotSupported"))
                         r = -EOPNOTSUPP;
                         r = -EHOSTDOWN;
                 else if (streq(error_id, "io.systemd.UserDatabase.EnumerationNotSupported"))
                         r = -EOPNOTSUPP;
-                else if (streq(error_id, VARLINK_ERROR_TIMEOUT))
+                else if (streq(error_id, SD_VARLINK_ERROR_TIMEOUT))
                         r = -ETIMEDOUT;
                 else
                         r = -EIO;
                         r = -ETIMEDOUT;
                 else
                         r = -EIO;
@@ -178,18 +190,18 @@ static int userdb_on_query_reply(
         switch (iterator->what) {
 
         case LOOKUP_USER: {
         switch (iterator->what) {
 
         case LOOKUP_USER: {
-                _cleanup_(user_group_data_release) struct user_group_data user_data = {};
+                _cleanup_(user_group_data_done) struct user_group_data user_data = {};
 
 
-                static const JsonDispatch dispatch_table[] = {
-                        { "record",     _JSON_VARIANT_TYPE_INVALID, json_dispatch_variant, offsetof(struct user_group_data, record),     0 },
-                        { "incomplete", JSON_VARIANT_BOOLEAN,       json_dispatch_boolean, offsetof(struct user_group_data, incomplete), 0 },
+                static const sd_json_dispatch_field dispatch_table[] = {
+                        { "record",     _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_variant, offsetof(struct user_group_data, record),     0 },
+                        { "incomplete", SD_JSON_VARIANT_BOOLEAN,       sd_json_dispatch_stdbool, offsetof(struct user_group_data, incomplete), 0 },
                         {}
                 };
                 _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
 
                 assert_se(!iterator->found_user);
 
                         {}
                 };
                 _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
 
                 assert_se(!iterator->found_user);
 
-                r = json_dispatch(parameters, dispatch_table, NULL, 0, &user_data);
+                r = sd_json_dispatch(parameters, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &user_data);
                 if (r < 0)
                         goto finish;
 
                 if (r < 0)
                         goto finish;
 
@@ -226,7 +238,7 @@ static int userdb_on_query_reply(
                 iterator->n_found++;
 
                 /* More stuff coming? then let's just exit cleanly here */
                 iterator->n_found++;
 
                 /* More stuff coming? then let's just exit cleanly here */
-                if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                if (FLAGS_SET(flags, SD_VARLINK_REPLY_CONTINUES))
                         return 0;
 
                 /* Otherwise, let's remove this link and exit cleanly then */
                         return 0;
 
                 /* Otherwise, let's remove this link and exit cleanly then */
@@ -235,18 +247,18 @@ static int userdb_on_query_reply(
         }
 
         case LOOKUP_GROUP: {
         }
 
         case LOOKUP_GROUP: {
-                _cleanup_(user_group_data_release) struct user_group_data group_data = {};
+                _cleanup_(user_group_data_done) struct user_group_data group_data = {};
 
 
-                static const JsonDispatch dispatch_table[] = {
-                        { "record",     _JSON_VARIANT_TYPE_INVALID, json_dispatch_variant, offsetof(struct user_group_data, record),     0 },
-                        { "incomplete", JSON_VARIANT_BOOLEAN,       json_dispatch_boolean, offsetof(struct user_group_data, incomplete), 0 },
+                static const sd_json_dispatch_field dispatch_table[] = {
+                        { "record",     _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_variant, offsetof(struct user_group_data, record),     0 },
+                        { "incomplete", SD_JSON_VARIANT_BOOLEAN,       sd_json_dispatch_stdbool, offsetof(struct user_group_data, incomplete), 0 },
                         {}
                 };
                 _cleanup_(group_record_unrefp) GroupRecord *g = NULL;
 
                 assert_se(!iterator->found_group);
 
                         {}
                 };
                 _cleanup_(group_record_unrefp) GroupRecord *g = NULL;
 
                 assert_se(!iterator->found_group);
 
-                r = json_dispatch(parameters, dispatch_table, NULL, 0, &group_data);
+                r = sd_json_dispatch(parameters, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &group_data);
                 if (r < 0)
                         goto finish;
 
                 if (r < 0)
                         goto finish;
 
@@ -280,7 +292,7 @@ static int userdb_on_query_reply(
                 iterator->found_group = TAKE_PTR(g);
                 iterator->n_found++;
 
                 iterator->found_group = TAKE_PTR(g);
                 iterator->n_found++;
 
-                if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                if (FLAGS_SET(flags, SD_VARLINK_REPLY_CONTINUES))
                         return 0;
 
                 r = 0;
                         return 0;
 
                 r = 0;
@@ -288,42 +300,26 @@ static int userdb_on_query_reply(
         }
 
         case LOOKUP_MEMBERSHIP: {
         }
 
         case LOOKUP_MEMBERSHIP: {
-                struct membership_data {
-                        const char *user_name;
-                        const char *group_name;
-                } membership_data = {};
-
-                static const JsonDispatch dispatch_table[] = {
-                        { "userName",  JSON_VARIANT_STRING, json_dispatch_user_group_name, offsetof(struct membership_data, user_name),  JSON_RELAX },
-                        { "groupName", JSON_VARIANT_STRING, json_dispatch_user_group_name, offsetof(struct membership_data, group_name), JSON_RELAX },
+                _cleanup_(membership_data_done) struct membership_data membership_data = {};
+
+                static const sd_json_dispatch_field dispatch_table[] = {
+                        { "userName",  SD_JSON_VARIANT_STRING, json_dispatch_user_group_name, offsetof(struct membership_data, user_name),  SD_JSON_RELAX },
+                        { "groupName", SD_JSON_VARIANT_STRING, json_dispatch_user_group_name, offsetof(struct membership_data, group_name), SD_JSON_RELAX },
                         {}
                 };
 
                 assert(!iterator->found_user_name);
                 assert(!iterator->found_group_name);
 
                         {}
                 };
 
                 assert(!iterator->found_user_name);
                 assert(!iterator->found_group_name);
 
-                r = json_dispatch(parameters, dispatch_table, NULL, 0, &membership_data);
+                r = sd_json_dispatch(parameters, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &membership_data);
                 if (r < 0)
                         goto finish;
 
                 if (r < 0)
                         goto finish;
 
-                iterator->found_user_name = mfree(iterator->found_user_name);
-                iterator->found_group_name = mfree(iterator->found_group_name);
-
-                iterator->found_user_name = strdup(membership_data.user_name);
-                if (!iterator->found_user_name) {
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-                iterator->found_group_name = strdup(membership_data.group_name);
-                if (!iterator->found_group_name) {
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
+                iterator->found_user_name = TAKE_PTR(membership_data.user_name);
+                iterator->found_group_name = TAKE_PTR(membership_data.group_name);
                 iterator->n_found++;
 
                 iterator->n_found++;
 
-                if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                if (FLAGS_SET(flags, SD_VARLINK_REPLY_CONTINUES))
                         return 0;
 
                 r = 0;
                         return 0;
 
                 r = 0;
@@ -341,7 +337,7 @@ finish:
                 iterator->error = -r;
 
         assert_se(set_remove(iterator->links, link) == link);
                 iterator->error = -r;
 
         assert_se(set_remove(iterator->links, link) == link);
-        link = varlink_unref(link);
+        link = sd_varlink_unref(link);
         return 0;
 }
 
         return 0;
 }
 
@@ -350,20 +346,20 @@ static int userdb_connect(
                 const char *path,
                 const char *method,
                 bool more,
                 const char *path,
                 const char *method,
                 bool more,
-                JsonVariant *query) {
+                sd_json_variant *query) {
 
 
-        _cleanup_(varlink_unrefp) Varlink *vl = NULL;
+        _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
         int r;
 
         assert(iterator);
         assert(path);
         assert(method);
 
         int r;
 
         assert(iterator);
         assert(path);
         assert(method);
 
-        r = varlink_connect_address(&vl, path);
+        r = sd_varlink_connect_address(&vl, path);
         if (r < 0)
                 return log_debug_errno(r, "Unable to connect to %s: %m", path);
 
         if (r < 0)
                 return log_debug_errno(r, "Unable to connect to %s: %m", path);
 
-        varlink_set_userdata(vl, iterator);
+        sd_varlink_set_userdata(vl, iterator);
 
         if (!iterator->event) {
                 r = sd_event_new(&iterator->event);
 
         if (!iterator->event) {
                 r = sd_event_new(&iterator->event);
@@ -371,20 +367,20 @@ static int userdb_connect(
                         return log_debug_errno(r, "Unable to allocate event loop: %m");
         }
 
                         return log_debug_errno(r, "Unable to allocate event loop: %m");
         }
 
-        r = varlink_attach_event(vl, iterator->event, SD_EVENT_PRIORITY_NORMAL);
+        r = sd_varlink_attach_event(vl, iterator->event, SD_EVENT_PRIORITY_NORMAL);
         if (r < 0)
                 return log_debug_errno(r, "Failed to attach varlink connection to event loop: %m");
 
         if (r < 0)
                 return log_debug_errno(r, "Failed to attach varlink connection to event loop: %m");
 
-        (void) varlink_set_description(vl, path);
+        (void) sd_varlink_set_description(vl, path);
 
 
-        r = varlink_bind_reply(vl, userdb_on_query_reply);
+        r = sd_varlink_bind_reply(vl, userdb_on_query_reply);
         if (r < 0)
                 return log_debug_errno(r, "Failed to bind reply callback: %m");
 
         if (more)
         if (r < 0)
                 return log_debug_errno(r, "Failed to bind reply callback: %m");
 
         if (more)
-                r = varlink_observe(vl, method, query);
+                r = sd_varlink_observe(vl, method, query);
         else
         else
-                r = varlink_invoke(vl, method, query);
+                r = sd_varlink_invoke(vl, method, query);
         if (r < 0)
                 return log_debug_errno(r, "Failed to invoke varlink method: %m");
 
         if (r < 0)
                 return log_debug_errno(r, "Failed to invoke varlink method: %m");
 
@@ -398,11 +394,11 @@ static int userdb_start_query(
                 UserDBIterator *iterator,
                 const char *method,
                 bool more,
                 UserDBIterator *iterator,
                 const char *method,
                 bool more,
-                JsonVariant *query,
+                sd_json_variant *query,
                 UserDBFlags flags) {
 
                 UserDBFlags flags) {
 
-        _cleanup_(strv_freep) char **except = NULL, **only = NULL;
-        _cleanup_(closedirp) DIR *d = NULL;
+        _cleanup_strv_free_ char **except = NULL, **only = NULL;
+        _cleanup_closedir_ DIR *d = NULL;
         const char *e;
         int r, ret = 0;
 
         const char *e;
         int r, ret = 0;
 
@@ -435,9 +431,9 @@ static int userdb_start_query(
         if ((flags & (USERDB_AVOID_MULTIPLEXER|USERDB_EXCLUDE_DYNAMIC_USER|USERDB_EXCLUDE_NSS|USERDB_EXCLUDE_DROPIN|USERDB_DONT_SYNTHESIZE)) == 0 &&
             !strv_contains(except, "io.systemd.Multiplexer") &&
             (!only || strv_contains(only, "io.systemd.Multiplexer"))) {
         if ((flags & (USERDB_AVOID_MULTIPLEXER|USERDB_EXCLUDE_DYNAMIC_USER|USERDB_EXCLUDE_NSS|USERDB_EXCLUDE_DROPIN|USERDB_DONT_SYNTHESIZE)) == 0 &&
             !strv_contains(except, "io.systemd.Multiplexer") &&
             (!only || strv_contains(only, "io.systemd.Multiplexer"))) {
-                _cleanup_(json_variant_unrefp) JsonVariant *patched_query = json_variant_ref(query);
+                _cleanup_(sd_json_variant_unrefp) sd_json_variant *patched_query = sd_json_variant_ref(query);
 
 
-                r = json_variant_set_field_string(&patched_query, "service", "io.systemd.Multiplexer");
+                r = sd_json_variant_set_field_string(&patched_query, "service", "io.systemd.Multiplexer");
                 if (r < 0)
                         return log_debug_errno(r, "Unable to set service JSON field: %m");
 
                 if (r < 0)
                         return log_debug_errno(r, "Unable to set service JSON field: %m");
 
@@ -458,7 +454,7 @@ static int userdb_start_query(
         }
 
         FOREACH_DIRENT(de, d, return -errno) {
         }
 
         FOREACH_DIRENT(de, d, return -errno) {
-                _cleanup_(json_variant_unrefp) JsonVariant *patched_query = NULL;
+                _cleanup_(sd_json_variant_unrefp) sd_json_variant *patched_query = NULL;
                 _cleanup_free_ char *p = NULL;
                 bool is_nss, is_dropin;
 
                 _cleanup_free_ char *p = NULL;
                 bool is_nss, is_dropin;
 
@@ -492,8 +488,8 @@ static int userdb_start_query(
                 if (!p)
                         return -ENOMEM;
 
                 if (!p)
                         return -ENOMEM;
 
-                patched_query = json_variant_ref(query);
-                r = json_variant_set_field_string(&patched_query, "service", de->d_name);
+                patched_query = sd_json_variant_ref(query);
+                r = sd_json_variant_set_field_string(&patched_query, "service", de->d_name);
                 if (r < 0)
                         return log_debug_errno(r, "Unable to set service JSON field: %m");
 
                 if (r < 0)
                         return log_debug_errno(r, "Unable to set service JSON field: %m");
 
@@ -597,34 +593,33 @@ static int userdb_process(
 static int synthetic_root_user_build(UserRecord **ret) {
         return user_record_build(
                         ret,
 static int synthetic_root_user_build(UserRecord **ret) {
         return user_record_build(
                         ret,
-                        JSON_BUILD_OBJECT(JSON_BUILD_PAIR("userName", JSON_BUILD_CONST_STRING("root")),
-                                          JSON_BUILD_PAIR("uid", JSON_BUILD_UNSIGNED(0)),
-                                          JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(0)),
-                                          JSON_BUILD_PAIR("homeDirectory", JSON_BUILD_CONST_STRING("/root")),
-                                          JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
+                        SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("userName", JSON_BUILD_CONST_STRING("root")),
+                                          SD_JSON_BUILD_PAIR("uid", SD_JSON_BUILD_UNSIGNED(0)),
+                                          SD_JSON_BUILD_PAIR("gid", SD_JSON_BUILD_UNSIGNED(0)),
+                                          SD_JSON_BUILD_PAIR("homeDirectory", JSON_BUILD_CONST_STRING("/root")),
+                                          SD_JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
 }
 
 static int synthetic_nobody_user_build(UserRecord **ret) {
         return user_record_build(
                         ret,
 }
 
 static int synthetic_nobody_user_build(UserRecord **ret) {
         return user_record_build(
                         ret,
-                        JSON_BUILD_OBJECT(JSON_BUILD_PAIR("userName", JSON_BUILD_CONST_STRING(NOBODY_USER_NAME)),
-                                          JSON_BUILD_PAIR("uid", JSON_BUILD_UNSIGNED(UID_NOBODY)),
-                                          JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(GID_NOBODY)),
-                                          JSON_BUILD_PAIR("shell", JSON_BUILD_CONST_STRING(NOLOGIN)),
-                                          JSON_BUILD_PAIR("locked", JSON_BUILD_BOOLEAN(true)),
-                                          JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
+                        SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("userName", JSON_BUILD_CONST_STRING(NOBODY_USER_NAME)),
+                                          SD_JSON_BUILD_PAIR("uid", SD_JSON_BUILD_UNSIGNED(UID_NOBODY)),
+                                          SD_JSON_BUILD_PAIR("gid", SD_JSON_BUILD_UNSIGNED(GID_NOBODY)),
+                                          SD_JSON_BUILD_PAIR("shell", JSON_BUILD_CONST_STRING(NOLOGIN)),
+                                          SD_JSON_BUILD_PAIR("locked", SD_JSON_BUILD_BOOLEAN(true)),
+                                          SD_JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
 }
 
 int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
 }
 
 int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
-        _cleanup_(json_variant_unrefp) JsonVariant *query = NULL;
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL;
         int r;
 
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
         int r;
 
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
-        r = json_build(&query, JSON_BUILD_OBJECT(
-                                       JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(name))));
+        r = sd_json_buildo(&query, SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(name)));
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
@@ -670,14 +665,13 @@ int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
 
 int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
 
 int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
-        _cleanup_(json_variant_unrefp) JsonVariant *query = NULL;
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL;
         int r;
 
         if (!uid_is_valid(uid))
                 return -EINVAL;
 
         int r;
 
         if (!uid_is_valid(uid))
                 return -EINVAL;
 
-        r = json_build(&query, JSON_BUILD_OBJECT(
-                                       JSON_BUILD_PAIR("uid", JSON_BUILD_UNSIGNED(uid))));
+        r = sd_json_buildo(&query, SD_JSON_BUILD_PAIR("uid", SD_JSON_BUILD_UNSIGNED(uid)));
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
@@ -875,29 +869,28 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
 static int synthetic_root_group_build(GroupRecord **ret) {
         return group_record_build(
                         ret,
 static int synthetic_root_group_build(GroupRecord **ret) {
         return group_record_build(
                         ret,
-                        JSON_BUILD_OBJECT(JSON_BUILD_PAIR("groupName", JSON_BUILD_CONST_STRING("root")),
-                                          JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(0)),
-                                          JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
+                        SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("groupName", JSON_BUILD_CONST_STRING("root")),
+                                          SD_JSON_BUILD_PAIR("gid", SD_JSON_BUILD_UNSIGNED(0)),
+                                          SD_JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
 }
 
 static int synthetic_nobody_group_build(GroupRecord **ret) {
         return group_record_build(
                         ret,
 }
 
 static int synthetic_nobody_group_build(GroupRecord **ret) {
         return group_record_build(
                         ret,
-                        JSON_BUILD_OBJECT(JSON_BUILD_PAIR("groupName", JSON_BUILD_CONST_STRING(NOBODY_GROUP_NAME)),
-                                          JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(GID_NOBODY)),
-                                          JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
+                        SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("groupName", JSON_BUILD_CONST_STRING(NOBODY_GROUP_NAME)),
+                                          SD_JSON_BUILD_PAIR("gid", SD_JSON_BUILD_UNSIGNED(GID_NOBODY)),
+                                          SD_JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("intrinsic"))));
 }
 
 int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
 }
 
 int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
-        _cleanup_(json_variant_unrefp) JsonVariant *query = NULL;
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL;
         int r;
 
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
         int r;
 
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
-        r = json_build(&query, JSON_BUILD_OBJECT(
-                                       JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(name))));
+        r = sd_json_buildo(&query, SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(name)));
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
@@ -941,14 +934,13 @@ int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
 
 int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
 
 int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
-        _cleanup_(json_variant_unrefp) JsonVariant *query = NULL;
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL;
         int r;
 
         if (!gid_is_valid(gid))
                 return -EINVAL;
 
         int r;
 
         if (!gid_is_valid(gid))
                 return -EINVAL;
 
-        r = json_build(&query, JSON_BUILD_OBJECT(
-                                       JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(gid))));
+        r = sd_json_buildo(&query, SD_JSON_BUILD_PAIR("gid", SD_JSON_BUILD_UNSIGNED(gid)));
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
@@ -1147,7 +1139,7 @@ static void discover_membership_dropins(UserDBIterator *i, UserDBFlags flags) {
 
 int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
 
 int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
-        _cleanup_(json_variant_unrefp) JsonVariant *query = NULL;
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL;
         int r, qr;
 
         assert(ret);
         int r, qr;
 
         assert(ret);
@@ -1155,8 +1147,7 @@ int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **r
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
-        r = json_build(&query, JSON_BUILD_OBJECT(
-                                       JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(name))));
+        r = sd_json_buildo(&query, SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(name)));
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
@@ -1193,7 +1184,7 @@ int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **r
 
 int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
 
 int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **ret) {
         _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
-        _cleanup_(json_variant_unrefp) JsonVariant *query = NULL;
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL;
         int r, qr;
 
         assert(ret);
         int r, qr;
 
         assert(ret);
@@ -1201,8 +1192,7 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
         if (!valid_user_group_name(name, VALID_USER_RELAX))
                 return -EINVAL;
 
-        r = json_build(&query, JSON_BUILD_OBJECT(
-                                       JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(name))));
+        r = sd_json_buildo(&query, SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(name)));
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
@@ -1441,8 +1431,7 @@ int membershipdb_by_group_strv(const char *name, UserDBFlags flags, char ***ret)
                         return r;
         }
 
                         return r;
         }
 
-        strv_sort(members);
-        strv_uniq(members);
+        strv_sort_uniq(members);
 
         *ret = TAKE_PTR(members);
         return 0;
 
         *ret = TAKE_PTR(members);
         return 0;
@@ -1454,14 +1443,16 @@ int userdb_block_nss_systemd(int b) {
 
         /* Note that we might be called from libnss_systemd.so.2 itself, but that should be fine, really. */
 
 
         /* Note that we might be called from libnss_systemd.so.2 itself, but that should be fine, really. */
 
-        dl = dlopen(ROOTLIBDIR "/libnss_systemd.so.2", RTLD_LAZY|RTLD_NODELETE);
+        dl = dlopen(LIBDIR "/libnss_systemd.so.2", RTLD_LAZY|RTLD_NODELETE);
         if (!dl) {
                 /* If the file isn't installed, don't complain loudly */
                 log_debug("Failed to dlopen(libnss_systemd.so.2), ignoring: %s", dlerror());
                 return 0;
         }
 
         if (!dl) {
                 /* If the file isn't installed, don't complain loudly */
                 log_debug("Failed to dlopen(libnss_systemd.so.2), ignoring: %s", dlerror());
                 return 0;
         }
 
-        call = (int (*)(bool b)) dlsym(dl, "_nss_systemd_block");
+        log_debug("Loaded '%s' via dlopen()", LIBDIR "/libnss_systemd.so.2");
+
+        call = dlsym(dl, "_nss_systemd_block");
         if (!call)
                 /* If the file is installed but lacks the symbol we expect, things are weird, let's complain */
                 return log_debug_errno(SYNTHETIC_ERRNO(ELIBBAD),
         if (!call)
                 /* If the file is installed but lacks the symbol we expect, things are weird, let's complain */
                 return log_debug_errno(SYNTHETIC_ERRNO(ELIBBAD),