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, &current_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(&current_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