]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-nss-users.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "alloc-util.h"
9 #include "dlfcn-util.h"
10 #include "errno-list.h"
11 #include "format-util.h"
13 #include "main-func.h"
14 #include "nss-test-util.h"
16 #include "path-util.h"
17 #include "parse-util.h"
18 #include "stdio-util.h"
19 #include "string-util.h"
22 #include "user-util.h"
24 static size_t arg_bufsize
= 1024;
26 static void print_struct_passwd(const struct passwd
*pwd
) {
27 log_info(" \"%s\" / "UID_FMT
":"GID_FMT
,
28 pwd
->pw_name
, pwd
->pw_uid
, pwd
->pw_gid
);
29 log_info(" passwd=\"%s\"", pwd
->pw_passwd
);
30 log_info(" gecos=\"%s\"", pwd
->pw_gecos
);
31 log_info(" dir=\"%s\"", pwd
->pw_dir
);
32 log_info(" shell=\"%s\"", pwd
->pw_shell
);
35 static void print_struct_group(const struct group
*gr
) {
36 _cleanup_free_
char *members
= NULL
;
38 log_info(" \"%s\" / "GID_FMT
,
39 gr
->gr_name
, gr
->gr_gid
);
40 log_info(" passwd=\"%s\"", gr
->gr_passwd
);
42 assert_se(members
= strv_join(gr
->gr_mem
, ", "));
43 // FIXME: use shell_maybe_quote(SHELL_ESCAPE_EMPTY) when it becomes available
44 log_info(" members=%s", members
);
47 static void test_getpwnam_r(void *handle
, const char *module
, const char *name
) {
50 char buffer
[arg_bufsize
];
51 int errno1
= 999; /* nss-dns doesn't set those */
52 enum nss_status status
;
53 char pretty_status
[DECIMAL_STR_MAX(enum nss_status
)];
56 fname
= strjoina("_nss_", module
, "_getpwnam_r");
57 f
= dlsym(handle
, fname
);
58 log_debug("dlsym(0x%p, %s) → 0x%p", handle
, fname
, f
);
60 log_info("%s not defined", fname
);
64 status
= f(name
, &pwd
, buffer
, sizeof buffer
, &errno1
);
65 log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s",
67 nss_status_to_string(status
, pretty_status
, sizeof pretty_status
), "\n",
68 errno1
, errno_to_name(errno1
) ?: "---");
69 if (status
== NSS_STATUS_SUCCESS
)
70 print_struct_passwd(&pwd
);
73 static void test_getgrnam_r(void *handle
, const char *module
, const char *name
) {
76 char buffer
[arg_bufsize
];
77 int errno1
= 999; /* nss-dns doesn't set those */
78 enum nss_status status
;
79 char pretty_status
[DECIMAL_STR_MAX(enum nss_status
)];
82 fname
= strjoina("_nss_", module
, "_getgrnam_r");
83 f
= dlsym(handle
, fname
);
84 log_debug("dlsym(0x%p, %s) → 0x%p", handle
, fname
, f
);
86 log_info("%s not defined", fname
);
90 status
= f(name
, &gr
, buffer
, sizeof buffer
, &errno1
);
91 log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s",
93 nss_status_to_string(status
, pretty_status
, sizeof pretty_status
), "\n",
94 errno1
, errno_to_name(errno1
) ?: "---");
95 if (status
== NSS_STATUS_SUCCESS
)
96 print_struct_group(&gr
);
99 static void test_getpwuid_r(void *handle
, const char *module
, uid_t uid
) {
102 char buffer
[arg_bufsize
];
103 int errno1
= 999; /* nss-dns doesn't set those */
104 enum nss_status status
;
105 char pretty_status
[DECIMAL_STR_MAX(enum nss_status
)];
108 fname
= strjoina("_nss_", module
, "_getpwuid_r");
109 f
= dlsym(handle
, fname
);
110 log_debug("dlsym(0x%p, %s) → 0x%p", handle
, fname
, f
);
112 log_info("%s not defined", fname
);
116 status
= f(uid
, &pwd
, buffer
, sizeof buffer
, &errno1
);
117 log_info("%s("UID_FMT
") → status=%s%-20serrno=%d/%s",
119 nss_status_to_string(status
, pretty_status
, sizeof pretty_status
), "\n",
120 errno1
, errno_to_name(errno1
) ?: "---");
121 if (status
== NSS_STATUS_SUCCESS
)
122 print_struct_passwd(&pwd
);
125 static void test_getgrgid_r(void *handle
, const char *module
, gid_t gid
) {
128 char buffer
[arg_bufsize
];
129 int errno1
= 999; /* nss-dns doesn't set those */
130 enum nss_status status
;
131 char pretty_status
[DECIMAL_STR_MAX(enum nss_status
)];
134 fname
= strjoina("_nss_", module
, "_getgrgid_r");
135 f
= dlsym(handle
, fname
);
136 log_debug("dlsym(0x%p, %s) → 0x%p", handle
, fname
, f
);
138 log_info("%s not defined", fname
);
142 status
= f(gid
, &gr
, buffer
, sizeof buffer
, &errno1
);
143 log_info("%s("GID_FMT
") → status=%s%-20serrno=%d/%s",
145 nss_status_to_string(status
, pretty_status
, sizeof pretty_status
), "\n",
146 errno1
, errno_to_name(errno1
) ?: "---");
147 if (status
== NSS_STATUS_SUCCESS
)
148 print_struct_group(&gr
);
151 static void test_byname(void *handle
, const char *module
, const char *name
) {
152 test_getpwnam_r(handle
, module
, name
);
153 test_getgrnam_r(handle
, module
, name
);
157 static void test_byuid(void *handle
, const char *module
, uid_t uid
) {
158 test_getpwuid_r(handle
, module
, uid
);
159 test_getgrgid_r(handle
, module
, uid
);
163 static int test_one_module(const char *dir
,
167 log_info("======== %s ========", module
);
169 _cleanup_(dlclosep
) void *handle
= nss_open_handle(dir
, module
, RTLD_LAZY
|RTLD_NODELETE
);
173 STRV_FOREACH(name
, names
)
174 test_byname(handle
, module
, *name
);
176 STRV_FOREACH(name
, names
) {
179 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
180 /* We use safe_atou32 because we don't want to refuse invalid uids. */
181 if (safe_atou32(*name
, &uid
) < 0)
184 test_byuid(handle
, module
, uid
);
191 static int parse_argv(int argc
, char **argv
,
195 _cleanup_strv_free_
char **modules
= NULL
, **names
= NULL
;
199 p
= getenv("SYSTEMD_TEST_NSS_BUFSIZE");
201 r
= safe_atozu(p
, &arg_bufsize
);
203 return log_error_errno(r
, "Failed to parse $SYSTEMD_TEST_NSS_BUFSIZE");
207 modules
= strv_new(argv
[1]);
210 #if ENABLE_NSS_SYSTEMD
213 #if ENABLE_NSS_MYMACHINES
220 names
= strv_copy(strv_skip(argv
, 2));
222 names
= strv_new("root",
229 *the_modules
= TAKE_PTR(modules
);
230 *the_names
= TAKE_PTR(names
);
234 static int run(int argc
, char **argv
) {
235 _cleanup_free_
char *dir
= NULL
;
236 _cleanup_strv_free_
char **modules
= NULL
, **names
= NULL
;
239 test_setup_logging(LOG_INFO
);
241 r
= parse_argv(argc
, argv
, &modules
, &names
);
243 return log_error_errno(r
, "Failed to parse arguments: %m");
245 assert_se(path_extract_directory(argv
[0], &dir
) >= 0);
247 STRV_FOREACH(module
, modules
) {
248 r
= test_one_module(dir
, *module
, names
);
256 DEFINE_MAIN_FUNCTION(run
);