X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fshared%2Fuserdb.c;h=75dece3442935ae71f658f23105ff8f31d2e03c0;hb=HEAD;hp=3e08b339f5b861aabf0a21d1b598d56d671f0d00;hpb=85f088abe8d8069c67a55d25f4415516c9a6f01a;p=thirdparty%2Fsystemd.git diff --git a/src/shared/userdb.c b/src/shared/userdb.c index 3e08b339f5b..2eff470ec99 100644 --- a/src/shared/userdb.c +++ b/src/shared/userdb.c @@ -8,6 +8,7 @@ #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" @@ -90,7 +91,7 @@ UserDBIterator* userdb_iterator_free(UserDBIterator *iterator) { break; default: - assert_not_reached("Unexpected state?"); + assert_not_reached(); } sd_event_unref(iterator->event); @@ -114,6 +115,8 @@ static UserDBIterator* userdb_iterator_new(LookupWhat what, UserDBFlags flags) { *i = (UserDBIterator) { .what = what, .flags = flags, + .synthesize_root = !FLAGS_SET(flags, USERDB_DONT_SYNTHESIZE), + .synthesize_nobody = !FLAGS_SET(flags, USERDB_DONT_SYNTHESIZE), }; return i; @@ -136,26 +139,34 @@ static int userdb_iterator_block_nss_systemd(UserDBIterator *iterator) { } struct user_group_data { - JsonVariant *record; + sd_json_variant *record; 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( Varlink *link, - JsonVariant *parameters, + sd_json_variant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) { - UserDBIterator *iterator = userdata; + UserDBIterator *iterator = ASSERT_PTR(userdata); int r; - assert(iterator); - if (error_id) { log_debug("Got lookup error: %s", error_id); @@ -178,18 +189,18 @@ static int userdb_on_query_reply( 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); - 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; @@ -235,18 +246,18 @@ static int userdb_on_query_reply( } 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); - 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; @@ -288,39 +299,23 @@ static int userdb_on_query_reply( } 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_const_string, offsetof(struct membership_data, user_name), JSON_SAFE }, - { "groupName", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(struct membership_data, group_name), JSON_SAFE }, + _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); - 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; - 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++; if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES)) @@ -331,7 +326,7 @@ static int userdb_on_query_reply( } default: - assert_not_reached("unexpected lookup"); + assert_not_reached(); } finish: @@ -350,7 +345,7 @@ static int userdb_connect( const char *path, const char *method, bool more, - JsonVariant *query) { + sd_json_variant *query) { _cleanup_(varlink_unrefp) Varlink *vl = NULL; int r; @@ -398,12 +393,11 @@ static int userdb_start_query( UserDBIterator *iterator, const char *method, bool more, - JsonVariant *query, + sd_json_variant *query, UserDBFlags flags) { - _cleanup_(strv_freep) char **except = NULL, **only = NULL; - _cleanup_(closedirp) DIR *d = NULL; - struct dirent *de; + _cleanup_strv_free_ char **except = NULL, **only = NULL; + _cleanup_closedir_ DIR *d = NULL; const char *e; int r, ret = 0; @@ -436,9 +430,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"))) { - _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"); @@ -459,7 +453,7 @@ static int userdb_start_query( } 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; @@ -470,7 +464,7 @@ static int userdb_start_query( streq(de->d_name, "io.systemd.DynamicUser")) continue; - /* Avoid NSS is this is requested. Note that we also skip NSS when we were asked to skip the + /* Avoid NSS if this is requested. Note that we also skip NSS when we were asked to skip the * multiplexer, since in that case it's safer to do NSS in the client side emulation below * (and when we run as part of systemd-userdbd.service we don't want to talk to ourselves * anyway). */ @@ -493,8 +487,8 @@ static int userdb_start_query( 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"); @@ -510,7 +504,7 @@ static int userdb_start_query( } if (set_isempty(iterator->links)) - return ret; /* propagate last error we saw if we couldn't connect to anything. */ + return ret < 0 ? ret : -ESRCH; /* propagate last error we saw if we couldn't connect to anything. */ /* We connected to some services, in this case, ignore the ones we failed on */ return 0; @@ -598,34 +592,33 @@ static int userdb_process( static int synthetic_root_user_build(UserRecord **ret) { return user_record_build( ret, - JSON_BUILD_OBJECT(JSON_BUILD_PAIR("userName", JSON_BUILD_STRING("root")), - JSON_BUILD_PAIR("uid", JSON_BUILD_UNSIGNED(0)), - JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(0)), - JSON_BUILD_PAIR("homeDirectory", JSON_BUILD_STRING("/root")), - JSON_BUILD_PAIR("disposition", JSON_BUILD_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, - JSON_BUILD_OBJECT(JSON_BUILD_PAIR("userName", JSON_BUILD_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_STRING(NOLOGIN)), - JSON_BUILD_PAIR("locked", JSON_BUILD_BOOLEAN(true)), - JSON_BUILD_PAIR("disposition", JSON_BUILD_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; - _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; - 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; @@ -671,14 +664,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; - _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; - 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; @@ -730,8 +722,6 @@ int userdb_all(UserDBFlags flags, UserDBIterator **ret) { if (!iterator) return -ENOMEM; - iterator->synthesize_root = iterator->synthesize_nobody = !FLAGS_SET(flags, USERDB_DONT_SYNTHESIZE); - qr = userdb_start_query(iterator, "io.systemd.UserDatabase.GetUserRecord", true, NULL, flags); if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && (qr < 0 || !iterator->nss_covered)) { @@ -878,29 +868,28 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) { static int synthetic_root_group_build(GroupRecord **ret) { return group_record_build( ret, - JSON_BUILD_OBJECT(JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING("root")), - JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(0)), - JSON_BUILD_PAIR("disposition", JSON_BUILD_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, - JSON_BUILD_OBJECT(JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(NOBODY_GROUP_NAME)), - JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(GID_NOBODY)), - JSON_BUILD_PAIR("disposition", JSON_BUILD_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; - _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; - 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; @@ -944,14 +933,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; - _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; - 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; @@ -1002,8 +990,6 @@ int groupdb_all(UserDBFlags flags, UserDBIterator **ret) { if (!iterator) return -ENOMEM; - iterator->synthesize_root = iterator->synthesize_nobody = !FLAGS_SET(flags, USERDB_DONT_SYNTHESIZE); - qr = userdb_start_query(iterator, "io.systemd.UserDatabase.GetGroupRecord", true, NULL, flags); if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && (qr < 0 || !iterator->nss_covered)) { @@ -1152,7 +1138,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; - _cleanup_(json_variant_unrefp) JsonVariant *query = NULL; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL; int r, qr; assert(ret); @@ -1160,8 +1146,7 @@ int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **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; @@ -1198,7 +1183,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; - _cleanup_(json_variant_unrefp) JsonVariant *query = NULL; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *query = NULL; int r, qr; assert(ret); @@ -1206,8 +1191,7 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator ** 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; @@ -1446,8 +1430,7 @@ int membershipdb_by_group_strv(const char *name, UserDBFlags flags, char ***ret) return r; } - strv_sort(members); - strv_uniq(members); + strv_sort_uniq(members); *ret = TAKE_PTR(members); return 0; @@ -1459,14 +1442,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. */ - 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; } - 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),