Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : local testing of the nss wrapper
5 :
6 : Copyright (C) Guenther Deschner 2009-2010
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 :
24 : #include "torture/torture.h"
25 : #include "torture/local/proto.h"
26 : #include "lib/replace/system/passwd.h"
27 :
28 806 : static bool copy_passwd(struct torture_context *tctx,
29 : const struct passwd *pwd,
30 : struct passwd *p)
31 : {
32 806 : p->pw_name = talloc_strdup(tctx, pwd->pw_name);
33 806 : torture_assert(tctx, (p->pw_name != NULL || pwd->pw_name == NULL), __location__);
34 806 : p->pw_passwd = talloc_strdup(tctx, pwd->pw_passwd);
35 806 : torture_assert(tctx, (p->pw_passwd != NULL || pwd->pw_passwd == NULL), __location__);
36 806 : p->pw_uid = pwd->pw_uid;
37 806 : p->pw_gid = pwd->pw_gid;
38 806 : p->pw_gecos = talloc_strdup(tctx, pwd->pw_gecos);
39 806 : torture_assert(tctx, (p->pw_gecos != NULL || pwd->pw_gecos == NULL), __location__);
40 806 : p->pw_dir = talloc_strdup(tctx, pwd->pw_dir);
41 806 : torture_assert(tctx, (p->pw_dir != NULL || pwd->pw_dir == NULL), __location__);
42 806 : p->pw_shell = talloc_strdup(tctx, pwd->pw_shell);
43 806 : torture_assert(tctx, (p->pw_shell != NULL || pwd->pw_shell == NULL), __location__);
44 :
45 806 : return true;
46 : }
47 :
48 682 : static void print_passwd(struct passwd *pwd)
49 : {
50 1364 : printf("%s:%s:%lu:%lu:%s:%s:%s\n",
51 : pwd->pw_name,
52 : pwd->pw_passwd,
53 682 : (unsigned long)pwd->pw_uid,
54 682 : (unsigned long)pwd->pw_gid,
55 : pwd->pw_gecos,
56 : pwd->pw_dir,
57 : pwd->pw_shell);
58 682 : }
59 :
60 :
61 124 : static bool test_getpwnam(struct torture_context *tctx,
62 : const char *name,
63 : struct passwd *pwd_p)
64 : {
65 : struct passwd *pwd;
66 : int ret;
67 :
68 124 : torture_comment(tctx, "Testing getpwnam: %s\n", name);
69 :
70 124 : errno = 0;
71 124 : pwd = getpwnam(name);
72 124 : ret = errno;
73 124 : torture_assert(tctx, (pwd != NULL), talloc_asprintf(tctx,
74 : "getpwnam(%s) failed - %d - %s",
75 : name, ret, strerror(ret)));
76 :
77 124 : if (pwd_p != NULL) {
78 124 : torture_assert(tctx, copy_passwd(tctx, pwd, pwd_p), __location__);
79 : }
80 :
81 124 : return true;
82 : }
83 :
84 124 : static bool test_getpwnam_r(struct torture_context *tctx,
85 : const char *name,
86 : struct passwd *pwd_p)
87 : {
88 : struct passwd pwd, *pwdp;
89 : char buffer[4096];
90 : int ret;
91 :
92 124 : torture_comment(tctx, "Testing getpwnam_r: %s\n", name);
93 :
94 124 : ret = getpwnam_r(name, &pwd, buffer, sizeof(buffer), &pwdp);
95 124 : torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
96 : "getpwnam_r(%s) failed - %d - %s",
97 : name, ret, strerror(ret)));
98 :
99 124 : print_passwd(&pwd);
100 :
101 124 : if (pwd_p != NULL) {
102 124 : torture_assert(tctx, copy_passwd(tctx, &pwd, pwd_p), __location__);
103 : }
104 :
105 124 : return true;
106 : }
107 :
108 124 : static bool test_getpwuid(struct torture_context *tctx,
109 : uid_t uid,
110 : struct passwd *pwd_p)
111 : {
112 : struct passwd *pwd;
113 : int ret;
114 :
115 124 : torture_comment(tctx, "Testing getpwuid: %lu\n", (unsigned long)uid);
116 :
117 124 : errno = 0;
118 124 : pwd = getpwuid(uid);
119 124 : ret = errno;
120 124 : torture_assert(tctx, (pwd != NULL), talloc_asprintf(tctx,
121 : "getpwuid(%lu) failed - %d - %s",
122 : (unsigned long)uid, ret, strerror(ret)));
123 :
124 124 : print_passwd(pwd);
125 :
126 124 : if (pwd_p != NULL) {
127 124 : torture_assert(tctx, copy_passwd(tctx, pwd, pwd_p), __location__);
128 : }
129 :
130 124 : return true;
131 : }
132 :
133 124 : static bool test_getpwuid_r(struct torture_context *tctx,
134 : uid_t uid,
135 : struct passwd *pwd_p)
136 : {
137 : struct passwd pwd, *pwdp;
138 : char buffer[4096];
139 : int ret;
140 :
141 124 : torture_comment(tctx, "Testing getpwuid_r: %lu\n", (unsigned long)uid);
142 :
143 124 : ret = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &pwdp);
144 124 : torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
145 : "getpwuid_r(%lu) failed - %d - %s",
146 : (unsigned long)uid, ret, strerror(ret)));
147 :
148 124 : print_passwd(&pwd);
149 :
150 124 : if (pwd_p != NULL) {
151 124 : torture_assert(tctx, copy_passwd(tctx, &pwd, pwd_p), __location__);
152 : }
153 :
154 124 : return true;
155 : }
156 :
157 :
158 762 : static bool copy_group(struct torture_context *tctx,
159 : const struct group *grp,
160 : struct group *g)
161 : {
162 : int i;
163 :
164 762 : g->gr_name = talloc_strdup(tctx, grp->gr_name);
165 762 : torture_assert(tctx, (g->gr_name != NULL || grp->gr_name == NULL), __location__);
166 762 : g->gr_passwd = talloc_strdup(tctx, grp->gr_passwd);
167 762 : torture_assert(tctx, (g->gr_passwd != NULL || grp->gr_passwd == NULL), __location__);
168 762 : g->gr_gid = grp->gr_gid;
169 762 : g->gr_mem = NULL;
170 :
171 874 : for (i=0; grp->gr_mem && grp->gr_mem[i]; i++) {
172 112 : g->gr_mem = talloc_realloc(tctx, g->gr_mem, char *, i + 2);
173 112 : torture_assert(tctx, (g->gr_mem != NULL), __location__);
174 112 : g->gr_mem[i] = talloc_strdup(g->gr_mem, grp->gr_mem[i]);
175 112 : torture_assert(tctx, (g->gr_mem[i] != NULL), __location__);
176 112 : g->gr_mem[i+1] = NULL;
177 : }
178 :
179 762 : return true;
180 : }
181 :
182 832 : static void print_group(struct group *grp)
183 : {
184 : int i;
185 832 : printf("%s:%s:%lu:",
186 : grp->gr_name,
187 : grp->gr_passwd,
188 832 : (unsigned long)grp->gr_gid);
189 :
190 832 : if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) {
191 702 : printf("\n");
192 702 : return;
193 : }
194 :
195 130 : for (i=0; grp->gr_mem[i+1]; i++) {
196 0 : printf("%s,", grp->gr_mem[i]);
197 : }
198 130 : printf("%s\n", grp->gr_mem[i]);
199 : }
200 :
201 124 : static bool test_getgrnam(struct torture_context *tctx,
202 : const char *name,
203 : struct group *grp_p)
204 : {
205 : struct group *grp;
206 : int ret;
207 :
208 124 : torture_comment(tctx, "Testing getgrnam: %s\n", name);
209 :
210 124 : errno = 0;
211 124 : grp = getgrnam(name);
212 124 : ret = errno;
213 124 : torture_assert(tctx, (grp != NULL), talloc_asprintf(tctx,
214 : "getgrnam(%s) failed - %d - %s",
215 : name, ret, strerror(ret)));
216 :
217 124 : print_group(grp);
218 :
219 124 : if (grp_p != NULL) {
220 124 : torture_assert(tctx, copy_group(tctx, grp, grp_p), __location__);
221 : }
222 :
223 124 : return true;
224 : }
225 :
226 116 : static bool test_getgrnam_r(struct torture_context *tctx,
227 : const char *name,
228 : struct group *grp_p)
229 : {
230 : struct group grp, *grpp;
231 : char buffer[4096];
232 : int ret;
233 :
234 116 : torture_comment(tctx, "Testing getgrnam_r: %s\n", name);
235 :
236 116 : ret = getgrnam_r(name, &grp, buffer, sizeof(buffer), &grpp);
237 116 : torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
238 : "getgrnam_r(%s) failed - %d - %s",
239 : name, ret, strerror(ret)));
240 :
241 116 : print_group(&grp);
242 :
243 116 : if (grp_p != NULL) {
244 116 : torture_assert(tctx, copy_group(tctx, &grp, grp_p), __location__);
245 : }
246 :
247 116 : return true;
248 : }
249 :
250 :
251 186 : static bool test_getgrgid(struct torture_context *tctx,
252 : gid_t gid,
253 : struct group *grp_p)
254 : {
255 : struct group *grp;
256 : int ret;
257 :
258 186 : torture_comment(tctx, "Testing getgrgid: %lu\n", (unsigned long)gid);
259 :
260 186 : errno = 0;
261 186 : grp = getgrgid(gid);
262 186 : ret = errno;
263 186 : torture_assert(tctx, (grp != NULL), talloc_asprintf(tctx,
264 : "getgrgid(%lu) failed - %d - %s",
265 : (unsigned long)gid, ret, strerror(ret)));
266 :
267 186 : print_group(grp);
268 :
269 186 : if (grp_p != NULL) {
270 116 : torture_assert(tctx, copy_group(tctx, grp, grp_p), __location__);
271 : }
272 :
273 186 : return true;
274 : }
275 :
276 116 : static bool test_getgrgid_r(struct torture_context *tctx,
277 : gid_t gid,
278 : struct group *grp_p)
279 : {
280 : struct group grp, *grpp;
281 : char buffer[4096];
282 : int ret;
283 :
284 116 : torture_comment(tctx, "Testing getgrgid_r: %lu\n", (unsigned long)gid);
285 :
286 116 : ret = getgrgid_r(gid, &grp, buffer, sizeof(buffer), &grpp);
287 116 : torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
288 : "getgrgid_r(%lu) failed - %d - %s",
289 : (unsigned long)gid, ret, strerror(ret)));
290 :
291 116 : print_group(&grp);
292 :
293 116 : if (grp_p != NULL) {
294 116 : torture_assert(tctx, copy_group(tctx, &grp, grp_p), __location__);
295 : }
296 :
297 116 : return true;
298 : }
299 :
300 6 : static bool test_enum_passwd(struct torture_context *tctx,
301 : struct passwd **pwd_array_p,
302 : size_t *num_pwd_p)
303 : {
304 : struct passwd *pwd;
305 6 : struct passwd *pwd_array = NULL;
306 6 : size_t num_pwd = 0;
307 :
308 6 : torture_comment(tctx, "Testing setpwent\n");
309 6 : setpwent();
310 :
311 195 : while ((pwd = getpwent()) != NULL) {
312 186 : torture_comment(tctx, "Testing getpwent\n");
313 :
314 186 : print_passwd(pwd);
315 186 : if (pwd_array_p && num_pwd_p) {
316 186 : pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1);
317 186 : torture_assert(tctx, pwd_array, "out of memory");
318 186 : copy_passwd(tctx, pwd, &pwd_array[num_pwd]);
319 186 : num_pwd++;
320 : }
321 : }
322 :
323 6 : torture_comment(tctx, "Testing endpwent\n");
324 6 : endpwent();
325 :
326 6 : if (pwd_array_p) {
327 6 : *pwd_array_p = pwd_array;
328 : }
329 6 : if (num_pwd_p) {
330 6 : *num_pwd_p = num_pwd;
331 : }
332 :
333 6 : return true;
334 : }
335 :
336 4 : static bool test_enum_r_passwd(struct torture_context *tctx,
337 : struct passwd **pwd_array_p,
338 : size_t *num_pwd_p)
339 : {
340 : struct passwd pwd, *pwdp;
341 4 : struct passwd *pwd_array = NULL;
342 4 : size_t num_pwd = 0;
343 : char buffer[4096];
344 : int ret;
345 :
346 4 : torture_comment(tctx, "Testing setpwent\n");
347 4 : setpwent();
348 :
349 : #ifdef HAVE_GETPWENT_R /* getpwent_r not supported on macOS */
350 : while (1) {
351 190 : torture_comment(tctx, "Testing getpwent_r\n");
352 :
353 : #ifdef SOLARIS_GETPWENT_R
354 : ret = getpwent_r(&pwd, buffer, sizeof(buffer));
355 : #else /* SOLARIS_GETPWENT_R */
356 128 : ret = getpwent_r(&pwd, buffer, sizeof(buffer), &pwdp);
357 : #endif /* SOLARIS_GETPWENT_R */
358 128 : if (ret != 0) {
359 4 : if (ret != ENOENT) {
360 0 : torture_comment(tctx, "got %d return code\n", ret);
361 : }
362 4 : break;
363 : }
364 124 : print_passwd(&pwd);
365 124 : if (pwd_array_p && num_pwd_p) {
366 124 : pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1);
367 124 : torture_assert(tctx, pwd_array, "out of memory");
368 124 : copy_passwd(tctx, &pwd, &pwd_array[num_pwd]);
369 124 : num_pwd++;
370 : }
371 : }
372 : #endif /* getpwent_r not supported on macOS */
373 :
374 4 : torture_comment(tctx, "Testing endpwent\n");
375 4 : endpwent();
376 :
377 4 : if (pwd_array_p) {
378 4 : *pwd_array_p = pwd_array;
379 : }
380 4 : if (num_pwd_p) {
381 4 : *num_pwd_p = num_pwd;
382 : }
383 :
384 4 : return true;
385 : }
386 :
387 744 : static bool torture_assert_passwd_equal(struct torture_context *tctx,
388 : const struct passwd *p1,
389 : const struct passwd *p2,
390 : const char *comment)
391 : {
392 744 : torture_assert_str_equal(tctx, p1->pw_name, p2->pw_name, comment);
393 744 : torture_assert_str_equal(tctx, p1->pw_passwd, p2->pw_passwd, comment);
394 744 : torture_assert_int_equal(tctx, p1->pw_uid, p2->pw_uid, comment);
395 744 : torture_assert_int_equal(tctx, p1->pw_gid, p2->pw_gid, comment);
396 744 : torture_assert_str_equal(tctx, p1->pw_gecos, p2->pw_gecos, comment);
397 744 : torture_assert_str_equal(tctx, p1->pw_dir, p2->pw_dir, comment);
398 744 : torture_assert_str_equal(tctx, p1->pw_shell, p2->pw_shell, comment);
399 :
400 744 : return true;
401 : }
402 :
403 2 : static bool test_passwd(struct torture_context *tctx)
404 : {
405 : int i;
406 : struct passwd *pwd, pwd1, pwd2;
407 : size_t num_pwd;
408 :
409 2 : torture_assert(tctx, test_enum_passwd(tctx, &pwd, &num_pwd),
410 : "failed to enumerate passwd");
411 :
412 64 : for (i=0; i < num_pwd; i++) {
413 62 : torture_assert(tctx, test_getpwnam(tctx, pwd[i].pw_name, &pwd1),
414 : "failed to call getpwnam for enumerated user");
415 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
416 : "getpwent and getpwnam gave different results"),
417 : __location__);
418 62 : torture_assert(tctx, test_getpwuid(tctx, pwd[i].pw_uid, &pwd2),
419 : "failed to call getpwuid for enumerated user");
420 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
421 : "getpwent and getpwuid gave different results"),
422 : __location__);
423 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
424 : "getpwnam and getpwuid gave different results"),
425 : __location__);
426 : }
427 :
428 2 : return true;
429 : }
430 :
431 2 : static bool test_passwd_r(struct torture_context *tctx)
432 : {
433 : int i;
434 : struct passwd *pwd, pwd1, pwd2;
435 : size_t num_pwd;
436 :
437 2 : torture_assert(tctx, test_enum_r_passwd(tctx, &pwd, &num_pwd),
438 : "failed to enumerate passwd");
439 :
440 64 : for (i=0; i < num_pwd; i++) {
441 62 : torture_assert(tctx, test_getpwnam_r(tctx, pwd[i].pw_name, &pwd1),
442 : "failed to call getpwnam_r for enumerated user");
443 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
444 : "getpwent_r and getpwnam_r gave different results"),
445 : __location__);
446 62 : torture_assert(tctx, test_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2),
447 : "failed to call getpwuid_r for enumerated user");
448 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
449 : "getpwent_r and getpwuid_r gave different results"),
450 : __location__);
451 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
452 : "getpwnam_r and getpwuid_r gave different results"),
453 : __location__);
454 : }
455 :
456 2 : return true;
457 : }
458 :
459 2 : static bool test_passwd_r_cross(struct torture_context *tctx)
460 : {
461 : int i;
462 : struct passwd *pwd, pwd1, pwd2, pwd3, pwd4;
463 : size_t num_pwd;
464 :
465 2 : torture_assert(tctx, test_enum_r_passwd(tctx, &pwd, &num_pwd),
466 : "failed to enumerate passwd");
467 :
468 64 : for (i=0; i < num_pwd; i++) {
469 62 : torture_assert(tctx, test_getpwnam_r(tctx, pwd[i].pw_name, &pwd1),
470 : "failed to call getpwnam_r for enumerated user");
471 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
472 : "getpwent_r and getpwnam_r gave different results"),
473 : __location__);
474 62 : torture_assert(tctx, test_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2),
475 : "failed to call getpwuid_r for enumerated user");
476 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
477 : "getpwent_r and getpwuid_r gave different results"),
478 : __location__);
479 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
480 : "getpwnam_r and getpwuid_r gave different results"),
481 : __location__);
482 62 : torture_assert(tctx, test_getpwnam(tctx, pwd[i].pw_name, &pwd3),
483 : "failed to call getpwnam for enumerated user");
484 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd3,
485 : "getpwent_r and getpwnam gave different results"),
486 : __location__);
487 62 : torture_assert(tctx, test_getpwuid(tctx, pwd[i].pw_uid, &pwd4),
488 : "failed to call getpwuid for enumerated user");
489 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd4,
490 : "getpwent_r and getpwuid gave different results"),
491 : __location__);
492 62 : torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd3, &pwd4,
493 : "getpwnam and getpwuid gave different results"),
494 : __location__);
495 : }
496 :
497 2 : return true;
498 : }
499 :
500 6 : static bool test_enum_group(struct torture_context *tctx,
501 : struct group **grp_array_p,
502 : size_t *num_grp_p)
503 : {
504 : struct group *grp;
505 6 : struct group *grp_array = NULL;
506 6 : size_t num_grp = 0;
507 :
508 6 : torture_comment(tctx, "Testing setgrent\n");
509 6 : setgrent();
510 :
511 183 : while ((grp = getgrent()) != NULL) {
512 174 : torture_comment(tctx, "Testing getgrent\n");
513 :
514 174 : print_group(grp);
515 174 : if (grp_array_p && num_grp_p) {
516 174 : grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1);
517 174 : torture_assert(tctx, grp_array, "out of memory");
518 174 : copy_group(tctx, grp, &grp_array[num_grp]);
519 174 : num_grp++;
520 : }
521 : }
522 :
523 6 : torture_comment(tctx, "Testing endgrent\n");
524 6 : endgrent();
525 :
526 6 : if (grp_array_p) {
527 6 : *grp_array_p = grp_array;
528 : }
529 6 : if (num_grp_p) {
530 6 : *num_grp_p = num_grp;
531 : }
532 :
533 6 : return true;
534 : }
535 :
536 4 : static bool test_enum_r_group(struct torture_context *tctx,
537 : struct group **grp_array_p,
538 : size_t *num_grp_p)
539 : {
540 : struct group grp, *grpp;
541 4 : struct group *grp_array = NULL;
542 4 : size_t num_grp = 0;
543 : char buffer[4096];
544 : int ret;
545 :
546 4 : torture_comment(tctx, "Testing setgrent\n");
547 4 : setgrent();
548 :
549 : #ifdef HAVE_GETGRENT_R /* getgrent_r not supported on macOS */
550 : while (1) {
551 178 : torture_comment(tctx, "Testing getgrent_r\n");
552 :
553 : #ifdef SOLARIS_GETGRENT_R
554 : ret = getgrent_r(&grp, buffer, sizeof(buffer));
555 : #else /* SOLARIS_GETGRENT_R */
556 120 : ret = getgrent_r(&grp, buffer, sizeof(buffer), &grpp);
557 : #endif /* SOLARIS_GETGRENT_R */
558 120 : if (ret != 0) {
559 4 : if (ret != ENOENT) {
560 0 : torture_comment(tctx, "got %d return code\n", ret);
561 : }
562 4 : break;
563 : }
564 116 : print_group(&grp);
565 116 : if (grp_array_p && num_grp_p) {
566 116 : grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1);
567 116 : torture_assert(tctx, grp_array, "out of memory");
568 116 : copy_group(tctx, &grp, &grp_array[num_grp]);
569 116 : num_grp++;
570 : }
571 : }
572 : #endif /* getgrent_r not supported on macOS */
573 :
574 4 : torture_comment(tctx, "Testing endgrent\n");
575 4 : endgrent();
576 :
577 4 : if (grp_array_p) {
578 4 : *grp_array_p = grp_array;
579 : }
580 4 : if (num_grp_p) {
581 4 : *num_grp_p = num_grp;
582 : }
583 :
584 4 : return true;
585 : }
586 :
587 696 : static bool torture_assert_group_equal(struct torture_context *tctx,
588 : const struct group *g1,
589 : const struct group *g2,
590 : const char *comment)
591 : {
592 : int i;
593 696 : torture_assert_str_equal(tctx, g1->gr_name, g2->gr_name, comment);
594 696 : torture_assert_str_equal(tctx, g1->gr_passwd, g2->gr_passwd, comment);
595 696 : torture_assert_int_equal(tctx, g1->gr_gid, g2->gr_gid, comment);
596 696 : torture_assert(tctx, !(g1->gr_mem && !g2->gr_mem), __location__);
597 696 : torture_assert(tctx, !(!g1->gr_mem && g2->gr_mem), __location__);
598 696 : if (!g1->gr_mem && !g2->gr_mem) {
599 600 : return true;
600 : }
601 192 : for (i=0; g1->gr_mem[i] && g2->gr_mem[i]; i++) {
602 96 : torture_assert_str_equal(tctx, g1->gr_mem[i], g2->gr_mem[i], comment);
603 : }
604 :
605 96 : return true;
606 : }
607 :
608 2 : static bool test_group(struct torture_context *tctx)
609 : {
610 : int i;
611 : struct group *grp, grp1, grp2;
612 : size_t num_grp;
613 :
614 2 : torture_assert(tctx, test_enum_group(tctx, &grp, &num_grp),
615 : "failed to enumerate group");
616 :
617 60 : for (i=0; i < num_grp; i++) {
618 58 : torture_assert(tctx, test_getgrnam(tctx, grp[i].gr_name, &grp1),
619 : "failed to call getgrnam for enumerated user");
620 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp1,
621 : "getgrent and getgrnam gave different results"),
622 : __location__);
623 58 : torture_assert(tctx, test_getgrgid(tctx, grp[i].gr_gid, &grp2),
624 : "failed to call getgrgid for enumerated user");
625 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp2,
626 : "getgrent and getgrgid gave different results"),
627 : __location__);
628 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp1, &grp2,
629 : "getgrnam and getgrgid gave different results"),
630 : __location__);
631 : }
632 :
633 2 : return true;
634 : }
635 :
636 2 : static bool test_group_r(struct torture_context *tctx)
637 : {
638 : int i;
639 : struct group *grp, grp1, grp2;
640 : size_t num_grp;
641 :
642 2 : torture_assert(tctx, test_enum_r_group(tctx, &grp, &num_grp),
643 : "failed to enumerate group");
644 :
645 60 : for (i=0; i < num_grp; i++) {
646 58 : torture_assert(tctx, test_getgrnam_r(tctx, grp[i].gr_name, &grp1),
647 : "failed to call getgrnam_r for enumerated user");
648 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp1,
649 : "getgrent_r and getgrnam_r gave different results"),
650 : __location__);
651 58 : torture_assert(tctx, test_getgrgid_r(tctx, grp[i].gr_gid, &grp2),
652 : "failed to call getgrgid_r for enumerated user");
653 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp2,
654 : "getgrent_r and getgrgid_r gave different results"),
655 : __location__);
656 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp1, &grp2,
657 : "getgrnam_r and getgrgid_r gave different results"),
658 : __location__);
659 : }
660 :
661 2 : return true;
662 : }
663 :
664 2 : static bool test_group_r_cross(struct torture_context *tctx)
665 : {
666 : int i;
667 : struct group *grp, grp1, grp2, grp3, grp4;
668 : size_t num_grp;
669 :
670 2 : torture_assert(tctx, test_enum_r_group(tctx, &grp, &num_grp),
671 : "failed to enumerate group");
672 :
673 60 : for (i=0; i < num_grp; i++) {
674 58 : torture_assert(tctx, test_getgrnam_r(tctx, grp[i].gr_name, &grp1),
675 : "failed to call getgrnam_r for enumerated user");
676 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp1,
677 : "getgrent_r and getgrnam_r gave different results"),
678 : __location__);
679 58 : torture_assert(tctx, test_getgrgid_r(tctx, grp[i].gr_gid, &grp2),
680 : "failed to call getgrgid_r for enumerated user");
681 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp2,
682 : "getgrent_r and getgrgid_r gave different results"),
683 : __location__);
684 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp1, &grp2,
685 : "getgrnam_r and getgrgid_r gave different results"),
686 : __location__);
687 58 : torture_assert(tctx, test_getgrnam(tctx, grp[i].gr_name, &grp3),
688 : "failed to call getgrnam for enumerated user");
689 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp3,
690 : "getgrent_r and getgrnam gave different results"),
691 : __location__);
692 58 : torture_assert(tctx, test_getgrgid(tctx, grp[i].gr_gid, &grp4),
693 : "failed to call getgrgid for enumerated user");
694 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp4,
695 : "getgrent_r and getgrgid gave different results"),
696 : __location__);
697 58 : torture_assert(tctx, torture_assert_group_equal(tctx, &grp3, &grp4,
698 : "getgrnam and getgrgid gave different results"),
699 : __location__);
700 : }
701 :
702 2 : return true;
703 : }
704 :
705 : #ifdef HAVE_GETGROUPLIST
706 62 : static bool test_getgrouplist(struct torture_context *tctx,
707 : const char *user,
708 : gid_t gid,
709 : gid_t **gids_p,
710 : int *num_gids_p)
711 : {
712 : int ret;
713 62 : int num_groups = 0;
714 62 : gid_t *groups = NULL;
715 :
716 62 : torture_comment(tctx, "Testing getgrouplist: %s\n", user);
717 :
718 62 : ret = getgrouplist(user, gid, NULL, &num_groups);
719 62 : if (ret == -1 || num_groups != 0) {
720 :
721 62 : groups = talloc_array(tctx, gid_t, num_groups);
722 62 : torture_assert(tctx, groups, "out of memory\n");
723 :
724 62 : ret = getgrouplist(user, gid, groups, &num_groups);
725 : }
726 :
727 62 : torture_assert(tctx, (ret != -1), "failed to call getgrouplist");
728 :
729 62 : torture_comment(tctx, "%s is member in %d groups\n", user, num_groups);
730 :
731 62 : if (gids_p) {
732 62 : *gids_p = groups;
733 : }
734 62 : if (num_gids_p) {
735 62 : *num_gids_p = num_groups;
736 : }
737 :
738 62 : return true;
739 : }
740 : #endif /* HAVE_GETGROUPLIST */
741 :
742 1798 : static bool test_user_in_group(struct torture_context *tctx,
743 : const struct passwd *pwd,
744 : const struct group *grp)
745 : {
746 : int i;
747 :
748 2038 : for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
749 248 : if (strequal(grp->gr_mem[i], pwd->pw_name)) {
750 8 : return true;
751 : }
752 : }
753 :
754 1790 : return false;
755 : }
756 :
757 62 : static bool test_membership_user(struct torture_context *tctx,
758 : const struct passwd *pwd,
759 : struct group *grp_array,
760 : size_t num_grp)
761 : {
762 62 : int num_user_groups = 0;
763 62 : int num_user_groups_from_enum = 0;
764 62 : gid_t *user_groups = NULL;
765 : int g, i;
766 62 : bool primary_group_had_user_member = false;
767 :
768 : #ifdef HAVE_GETGROUPLIST
769 62 : torture_assert(tctx, test_getgrouplist(tctx,
770 : pwd->pw_name,
771 : pwd->pw_gid,
772 : &user_groups,
773 : &num_user_groups),
774 : "failed to test getgrouplist");
775 : #endif /* HAVE_GETGROUPLIST */
776 :
777 132 : for (g=0; g < num_user_groups; g++) {
778 70 : torture_assert(tctx, test_getgrgid(tctx, user_groups[g], NULL),
779 : "failed to find the group the user is a member of");
780 : }
781 :
782 :
783 1860 : for (i=0; i < num_grp; i++) {
784 :
785 1798 : struct group grp = grp_array[i];
786 :
787 1798 : if (test_user_in_group(tctx, pwd, &grp)) {
788 :
789 : struct group current_grp;
790 8 : num_user_groups_from_enum++;
791 :
792 8 : torture_assert(tctx, test_getgrnam(tctx, grp.gr_name, ¤t_grp),
793 : "failed to find the group the user is a member of");
794 :
795 8 : if (current_grp.gr_gid == pwd->pw_gid) {
796 0 : torture_comment(tctx, "primary group %s of user %s lists user as member\n",
797 : current_grp.gr_name,
798 0 : pwd->pw_name);
799 0 : primary_group_had_user_member = true;
800 : }
801 :
802 8 : continue;
803 : }
804 : }
805 :
806 62 : if (!primary_group_had_user_member) {
807 62 : num_user_groups_from_enum++;
808 : }
809 :
810 62 : torture_assert_int_equal(tctx, num_user_groups, num_user_groups_from_enum,
811 : "getgrouplist and real inspection of grouplist gave different results\n");
812 :
813 62 : return true;
814 : }
815 :
816 2 : static bool test_membership(struct torture_context *tctx)
817 : {
818 2 : const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
819 2 : const char *old_group = getenv("NSS_WRAPPER_GROUP");
820 : struct passwd *pwd;
821 : size_t num_pwd;
822 : struct group *grp;
823 : size_t num_grp;
824 : int i;
825 :
826 2 : if (!old_pwd || !old_group) {
827 0 : torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
828 0 : torture_skip(tctx, "nothing to test\n");
829 : }
830 :
831 2 : torture_assert(tctx, test_enum_passwd(tctx, &pwd, &num_pwd),
832 : "failed to enumerate passwd");
833 2 : torture_assert(tctx, test_enum_group(tctx, &grp, &num_grp),
834 : "failed to enumerate group");
835 :
836 64 : for (i=0; i < num_pwd; i++) {
837 :
838 62 : torture_assert(tctx, test_membership_user(tctx, &pwd[i], grp, num_grp),
839 : "failed to test membership for user");
840 :
841 : }
842 :
843 2 : return true;
844 : }
845 :
846 2 : static bool test_enumeration(struct torture_context *tctx)
847 : {
848 2 : const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
849 2 : const char *old_group = getenv("NSS_WRAPPER_GROUP");
850 :
851 2 : if (!old_pwd || !old_group) {
852 0 : torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
853 0 : torture_skip(tctx, "nothing to test\n");
854 : }
855 :
856 2 : torture_assert(tctx, test_passwd(tctx),
857 : "failed to test users");
858 2 : torture_assert(tctx, test_group(tctx),
859 : "failed to test groups");
860 :
861 2 : return true;
862 : }
863 :
864 2 : static bool test_reentrant_enumeration(struct torture_context *tctx)
865 : {
866 2 : const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
867 2 : const char *old_group = getenv("NSS_WRAPPER_GROUP");
868 :
869 2 : if (!old_pwd || !old_group) {
870 0 : torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
871 0 : torture_skip(tctx, "nothing to test\n");
872 : }
873 :
874 2 : torture_comment(tctx, "Testing re-entrant calls\n");
875 :
876 2 : torture_assert(tctx, test_passwd_r(tctx),
877 : "failed to test users");
878 2 : torture_assert(tctx, test_group_r(tctx),
879 : "failed to test groups");
880 :
881 2 : return true;
882 : }
883 :
884 2 : static bool test_reentrant_enumeration_crosschecks(struct torture_context *tctx)
885 : {
886 2 : const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
887 2 : const char *old_group = getenv("NSS_WRAPPER_GROUP");
888 :
889 2 : if (!old_pwd || !old_group) {
890 0 : torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
891 0 : torture_skip(tctx, "nothing to test\n");
892 : }
893 :
894 2 : torture_comment(tctx, "Testing re-entrant calls with cross checks\n");
895 :
896 2 : torture_assert(tctx, test_passwd_r_cross(tctx),
897 : "failed to test users");
898 2 : torture_assert(tctx, test_group_r_cross(tctx),
899 : "failed to test groups");
900 :
901 2 : return true;
902 : }
903 :
904 2 : static bool test_passwd_duplicates(struct torture_context *tctx)
905 : {
906 : size_t i, d;
907 : struct passwd *pwd;
908 : size_t num_pwd;
909 2 : int duplicates = 0;
910 :
911 2 : torture_assert(tctx, test_enum_passwd(tctx, &pwd, &num_pwd),
912 : "failed to enumerate passwd");
913 :
914 64 : for (i=0; i < num_pwd; i++) {
915 62 : const char *current_name = pwd[i].pw_name;
916 1984 : for (d=0; d < num_pwd; d++) {
917 1922 : const char *dup_name = pwd[d].pw_name;
918 1922 : if (d == i) {
919 62 : continue;
920 : }
921 1860 : if (!strequal(current_name, dup_name)) {
922 1860 : continue;
923 : }
924 :
925 0 : torture_warning(tctx, "found duplicate names:");
926 0 : print_passwd(&pwd[d]);
927 0 : print_passwd(&pwd[i]);
928 0 : duplicates++;
929 : }
930 : }
931 :
932 2 : if (duplicates) {
933 0 : torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates));
934 : }
935 :
936 2 : return true;
937 : }
938 :
939 2 : static bool test_group_duplicates(struct torture_context *tctx)
940 : {
941 : size_t i, d;
942 : struct group *grp;
943 : size_t num_grp;
944 2 : int duplicates = 0;
945 :
946 2 : torture_assert(tctx, test_enum_group(tctx, &grp, &num_grp),
947 : "failed to enumerate group");
948 :
949 60 : for (i=0; i < num_grp; i++) {
950 58 : const char *current_name = grp[i].gr_name;
951 1740 : for (d=0; d < num_grp; d++) {
952 1682 : const char *dup_name = grp[d].gr_name;
953 1682 : if (d == i) {
954 58 : continue;
955 : }
956 1624 : if (!strequal(current_name, dup_name)) {
957 1624 : continue;
958 : }
959 :
960 0 : torture_warning(tctx, "found duplicate names:");
961 0 : print_group(&grp[d]);
962 0 : print_group(&grp[i]);
963 0 : duplicates++;
964 : }
965 : }
966 :
967 2 : if (duplicates) {
968 0 : torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates));
969 : }
970 :
971 2 : return true;
972 : }
973 :
974 :
975 2 : static bool test_duplicates(struct torture_context *tctx)
976 : {
977 2 : const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
978 2 : const char *old_group = getenv("NSS_WRAPPER_GROUP");
979 :
980 2 : if (!old_pwd || !old_group) {
981 0 : torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
982 0 : torture_skip(tctx, "nothing to test\n");
983 : }
984 :
985 2 : torture_assert(tctx, test_passwd_duplicates(tctx),
986 : "failed to test users");
987 2 : torture_assert(tctx, test_group_duplicates(tctx),
988 : "failed to test groups");
989 :
990 2 : return true;
991 : }
992 :
993 :
994 964 : struct torture_suite *torture_local_nss(TALLOC_CTX *mem_ctx)
995 : {
996 964 : struct torture_suite *suite = torture_suite_create(mem_ctx, "nss");
997 :
998 964 : torture_suite_add_simple_test(suite, "enumeration", test_enumeration);
999 964 : torture_suite_add_simple_test(suite, "reentrant enumeration", test_reentrant_enumeration);
1000 964 : torture_suite_add_simple_test(suite, "reentrant enumeration crosschecks", test_reentrant_enumeration_crosschecks);
1001 964 : torture_suite_add_simple_test(suite, "membership", test_membership);
1002 964 : torture_suite_add_simple_test(suite, "duplicates", test_duplicates);
1003 :
1004 964 : return suite;
1005 : }
|