2 * Tests for the NSS cash module
4 * Copyright (C) 2019 Simon Ruderich
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 #include "../cash_nss.h"
30 static void test_getgrent(void) {
37 // Test one setgrent/getgrent/endgrent round
39 s = _nss_cash_setgrent(0);
40 assert(s == NSS_STATUS_SUCCESS);
42 // Multiple calls with too small buffer don't advance any internal indices
43 s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
44 assert(s == NSS_STATUS_TRYAGAIN);
45 assert(errnop == ERANGE);
46 s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
47 assert(s == NSS_STATUS_TRYAGAIN);
48 assert(errnop == ERANGE);
49 s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
50 assert(s == NSS_STATUS_TRYAGAIN);
51 assert(errnop == ERANGE);
53 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
54 assert(s == NSS_STATUS_SUCCESS);
55 assert(!strcmp(g.gr_name, "root"));
56 assert(!strcmp(g.gr_passwd, "x"));
57 assert(g.gr_gid == 0);
58 assert(g.gr_mem != NULL);
59 assert(g.gr_mem[0] == NULL);
61 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
62 assert(s == NSS_STATUS_SUCCESS);
63 assert(!strcmp(g.gr_name, "daemon"));
64 assert(g.gr_gid == 1);
65 assert(g.gr_mem != NULL);
66 assert(!strcmp(g.gr_mem[0], "andariel"));
67 assert(!strcmp(g.gr_mem[1], "duriel"));
68 assert(!strcmp(g.gr_mem[2], "mephisto"));
69 assert(!strcmp(g.gr_mem[3], "diablo"));
70 assert(!strcmp(g.gr_mem[4], "baal"));
71 assert(g.gr_mem[5] == NULL);
72 for (int i = 0; i < 21; i++) {
73 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
74 assert(s == NSS_STATUS_SUCCESS);
76 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
77 assert(s == NSS_STATUS_SUCCESS);
78 assert(!strcmp(g.gr_name, "www-data"));
79 assert(!strcmp(g.gr_passwd, "x"));
80 assert(g.gr_gid == 33);
81 assert(g.gr_mem != NULL);
82 assert(!strcmp(g.gr_mem[0], "nobody"));
83 assert(g.gr_mem[1] == NULL);
84 for (int i = 0; i < 29; i++) {
85 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
86 assert(s == NSS_STATUS_SUCCESS);
88 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
89 assert(s == NSS_STATUS_SUCCESS);
90 assert(!strcmp(g.gr_name, "postfix"));
91 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
92 assert(s == NSS_STATUS_SUCCESS);
93 assert(!strcmp(g.gr_name, "postdrop"));
94 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
95 assert(s == NSS_STATUS_NOTFOUND);
96 assert(errnop == ENOENT);
98 s = _nss_cash_endgrent();
99 assert(s == NSS_STATUS_SUCCESS);
104 s = _nss_cash_setgrent(0);
105 assert(s == NSS_STATUS_SUCCESS);
107 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
108 assert(s == NSS_STATUS_SUCCESS);
109 assert(!strcmp(g.gr_name, "root"));
110 assert(!strcmp(g.gr_passwd, "x"));
111 assert(g.gr_gid == 0);
112 assert(g.gr_mem != NULL);
113 assert(g.gr_mem[0] == NULL);
115 s = _nss_cash_endgrent();
116 assert(s == NSS_STATUS_SUCCESS);
119 // Test proper reset the 2nd
121 s = _nss_cash_setgrent(0);
122 assert(s == NSS_STATUS_SUCCESS);
124 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
125 assert(s == NSS_STATUS_SUCCESS);
126 assert(!strcmp(g.gr_name, "root"));
127 assert(!strcmp(g.gr_passwd, "x"));
128 assert(g.gr_gid == 0);
129 assert(g.gr_mem != NULL);
130 assert(g.gr_mem[0] == NULL);
132 s = _nss_cash_endgrent();
133 assert(s == NSS_STATUS_SUCCESS);
136 // Test many rounds to check for open file leaks
137 for (int i = 0; i < 10000; i++) {
138 s = _nss_cash_setgrent(0);
139 assert(s == NSS_STATUS_SUCCESS);
141 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
142 assert(s == NSS_STATUS_SUCCESS);
143 assert(!strcmp(g.gr_name, "root"));
145 s = _nss_cash_endgrent();
146 assert(s == NSS_STATUS_SUCCESS);
150 // Test with cash file is not present
152 assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
153 s = _nss_cash_setgrent(0);
154 assert(s == NSS_STATUS_SUCCESS);
155 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
156 assert(s == NSS_STATUS_UNAVAIL);
157 assert(errnop == ENOENT);
158 s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
159 assert(s == NSS_STATUS_UNAVAIL);
160 assert(errnop == ENOENT);
161 s = _nss_cash_endgrent();
162 assert(s == NSS_STATUS_SUCCESS);
163 assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
166 static void test_getgrgid(void) {
173 s = _nss_cash_getgrgid_r(0, &g, tmp_small, sizeof(tmp_small), &errnop);
174 assert(s == NSS_STATUS_TRYAGAIN);
175 assert(errnop == ERANGE);
176 s = _nss_cash_getgrgid_r(14, &g, tmp_small, sizeof(tmp_small), &errnop);
177 assert(s == NSS_STATUS_NOTFOUND); // 14 does not exist
178 assert(errnop == ENOENT);
179 s = _nss_cash_getgrgid_r(65534, &g, tmp_small, sizeof(tmp_small), &errnop);
180 assert(s == NSS_STATUS_TRYAGAIN);
181 assert(errnop == ERANGE);
183 s = _nss_cash_getgrgid_r(0, &g, tmp, sizeof(tmp), &errnop);
184 assert(s == NSS_STATUS_SUCCESS);
185 assert(!strcmp(g.gr_name, "root"));
186 assert(!strcmp(g.gr_passwd, "x"));
187 assert(g.gr_gid == 0);
188 assert(g.gr_mem != NULL);
189 assert(g.gr_mem[0] == NULL);
191 s = _nss_cash_getgrgid_r(1, &g, tmp, sizeof(tmp), &errnop);
192 assert(s == NSS_STATUS_SUCCESS);
193 assert(!strcmp(g.gr_name, "daemon"));
194 assert(g.gr_gid == 1);
195 assert(g.gr_mem != NULL);
196 assert(!strcmp(g.gr_mem[0], "andariel"));
197 assert(!strcmp(g.gr_mem[1], "duriel"));
198 assert(!strcmp(g.gr_mem[2], "mephisto"));
199 assert(!strcmp(g.gr_mem[3], "diablo"));
200 assert(!strcmp(g.gr_mem[4], "baal"));
201 assert(g.gr_mem[5] == NULL);
203 s = _nss_cash_getgrgid_r(11, &g, tmp, sizeof(tmp), &errnop);
204 assert(s == NSS_STATUS_NOTFOUND);
205 assert(errnop == ENOENT);
207 s = _nss_cash_getgrgid_r(103, &g, tmp, sizeof(tmp), &errnop);
208 assert(s == NSS_STATUS_SUCCESS);
209 assert(!strcmp(g.gr_name, "systemd-network"));
210 assert(!strcmp(g.gr_passwd, "x"));
211 assert(g.gr_gid == 103);
212 assert(g.gr_mem != NULL);
213 assert(g.gr_mem[0] == NULL);
215 s = _nss_cash_getgrgid_r(107, &g, tmp, sizeof(tmp), &errnop);
216 assert(s == NSS_STATUS_SUCCESS);
217 assert(!strcmp(g.gr_name, "kvm"));
218 assert(!strcmp(g.gr_passwd, "x"));
219 assert(g.gr_gid == 107);
220 assert(g.gr_mem != NULL);
221 assert(g.gr_mem[0] == NULL);
223 s = _nss_cash_getgrgid_r(65534, &g, tmp, sizeof(tmp), &errnop);
224 assert(s == NSS_STATUS_SUCCESS);
225 assert(!strcmp(g.gr_name, "nogroup"));
226 assert(!strcmp(g.gr_passwd, "x"));
227 assert(g.gr_gid == 65534);
228 assert(g.gr_mem != NULL);
229 assert(g.gr_mem[0] == NULL);
231 s = _nss_cash_getgrgid_r(INT_MAX, &g, tmp, sizeof(tmp), &errnop);
232 assert(s == NSS_STATUS_NOTFOUND);
233 assert(errnop == ENOENT);
236 // Test with cash file is not present
238 assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
239 s = _nss_cash_getgrgid_r(0, &g, tmp, sizeof(tmp), &errnop);
240 assert(s == NSS_STATUS_UNAVAIL);
241 assert(errnop == ENOENT);
242 s = _nss_cash_getgrgid_r(14, &g, tmp, sizeof(tmp), &errnop);
243 assert(s == NSS_STATUS_UNAVAIL);
244 assert(errnop == ENOENT);
245 assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
248 static void test_getgrnam(void) {
255 s = _nss_cash_getgrnam_r("root", &g, tmp_small, sizeof(tmp_small), &errnop);
256 assert(s == NSS_STATUS_TRYAGAIN);
257 assert(errnop == ERANGE);
258 s = _nss_cash_getgrnam_r("nope", &g, tmp_small, sizeof(tmp_small), &errnop);
259 assert(s == NSS_STATUS_NOTFOUND); // does not exist
260 assert(errnop == ENOENT);
261 s = _nss_cash_getgrnam_r("nogroup", &g, tmp_small, sizeof(tmp_small), &errnop);
262 assert(s == NSS_STATUS_TRYAGAIN);
263 assert(errnop == ERANGE);
265 s = _nss_cash_getgrnam_r("root", &g, tmp, sizeof(tmp), &errnop);
266 assert(s == NSS_STATUS_SUCCESS);
267 assert(!strcmp(g.gr_name, "root"));
268 assert(!strcmp(g.gr_passwd, "x"));
269 assert(g.gr_gid == 0);
270 assert(g.gr_mem != NULL);
271 assert(g.gr_mem[0] == NULL);
273 s = _nss_cash_getgrnam_r("daemon", &g, tmp, sizeof(tmp), &errnop);
274 assert(s == NSS_STATUS_SUCCESS);
275 assert(!strcmp(g.gr_name, "daemon"));
276 assert(g.gr_gid == 1);
277 assert(g.gr_mem != NULL);
278 assert(!strcmp(g.gr_mem[0], "andariel"));
279 assert(!strcmp(g.gr_mem[1], "duriel"));
280 assert(!strcmp(g.gr_mem[2], "mephisto"));
281 assert(!strcmp(g.gr_mem[3], "diablo"));
282 assert(!strcmp(g.gr_mem[4], "baal"));
283 assert(g.gr_mem[5] == NULL);
285 s = _nss_cash_getgrnam_r("nope2", &g, tmp, sizeof(tmp), &errnop);
286 assert(s == NSS_STATUS_NOTFOUND);
287 assert(errnop == ENOENT);
289 s = _nss_cash_getgrnam_r("systemd-network", &g, tmp, sizeof(tmp), &errnop);
290 assert(s == NSS_STATUS_SUCCESS);
291 assert(!strcmp(g.gr_name, "systemd-network"));
292 assert(!strcmp(g.gr_passwd, "x"));
293 assert(g.gr_gid == 103);
294 assert(g.gr_mem != NULL);
295 assert(g.gr_mem[0] == NULL);
297 s = _nss_cash_getgrnam_r("postfix", &g, tmp, sizeof(tmp), &errnop);
298 assert(s == NSS_STATUS_SUCCESS);
299 assert(!strcmp(g.gr_name, "postfix"));
300 assert(!strcmp(g.gr_passwd, "x"));
301 assert(g.gr_gid == 114);
302 assert(g.gr_mem != NULL);
303 assert(g.gr_mem[0] == NULL);
305 s = _nss_cash_getgrnam_r("", &g, tmp, sizeof(tmp), &errnop);
306 assert(s == NSS_STATUS_NOTFOUND);
307 assert(errnop == ENOENT);
310 // Test with cash file is not present
312 assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
313 s = _nss_cash_getgrnam_r("root", &g, tmp, sizeof(tmp), &errnop);
314 assert(s == NSS_STATUS_UNAVAIL);
315 assert(errnop == ENOENT);
316 s = _nss_cash_getgrnam_r("nope", &g, tmp, sizeof(tmp), &errnop);
317 assert(s == NSS_STATUS_UNAVAIL);
318 assert(errnop == ENOENT);
319 assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);