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