xref: /freebsd-src/lib/libc/tests/nss/getpw_test.c (revision d11904b350214943dedb64c7121d4602799d7afd)
108ca345cSEnji Cooper /*-
208ca345cSEnji Cooper  * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
308ca345cSEnji Cooper  * All rights reserved.
408ca345cSEnji Cooper  *
508ca345cSEnji Cooper  * Redistribution and use in source and binary forms, with or without
608ca345cSEnji Cooper  * modification, are permitted provided that the following conditions
708ca345cSEnji Cooper  * are met:
808ca345cSEnji Cooper  * 1. Redistributions of source code must retain the above copyright
908ca345cSEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1008ca345cSEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1108ca345cSEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1208ca345cSEnji Cooper  *    documentation and/or other materials provided with the distribution.
1308ca345cSEnji Cooper  *
1408ca345cSEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1508ca345cSEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1608ca345cSEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1708ca345cSEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1808ca345cSEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1908ca345cSEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2008ca345cSEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2108ca345cSEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2208ca345cSEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2308ca345cSEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2408ca345cSEnji Cooper  * SUCH DAMAGE.
2508ca345cSEnji Cooper  *
2608ca345cSEnji Cooper  */
2708ca345cSEnji Cooper 
2808ca345cSEnji Cooper #include <errno.h>
2908ca345cSEnji Cooper #include <pwd.h>
3008ca345cSEnji Cooper #include <stdio.h>
3108ca345cSEnji Cooper #include <stdlib.h>
3208ca345cSEnji Cooper #include <string.h>
3308ca345cSEnji Cooper #include <unistd.h>
3408ca345cSEnji Cooper 
3508ca345cSEnji Cooper #include <atf-c.h>
3608ca345cSEnji Cooper 
3708ca345cSEnji Cooper #include "testutil.h"
3808ca345cSEnji Cooper 
3908ca345cSEnji Cooper enum test_methods {
4008ca345cSEnji Cooper 	TEST_GETPWENT,
416e411d8bSMark Johnston 	TEST_GETPWENT_INTERLEAVED_GETPWNAM,
426e411d8bSMark Johnston 	TEST_GETPWENT_INTERLEAVED_GETPWUID,
4308ca345cSEnji Cooper 	TEST_GETPWNAM,
4408ca345cSEnji Cooper 	TEST_GETPWUID,
4508ca345cSEnji Cooper 	TEST_GETPWENT_2PASS,
4608ca345cSEnji Cooper 	TEST_BUILD_SNAPSHOT
4708ca345cSEnji Cooper };
4808ca345cSEnji Cooper 
4908ca345cSEnji Cooper DECLARE_TEST_DATA(passwd)
5008ca345cSEnji Cooper DECLARE_TEST_FILE_SNAPSHOT(passwd)
5108ca345cSEnji Cooper DECLARE_1PASS_TEST(passwd)
5208ca345cSEnji Cooper DECLARE_2PASS_TEST(passwd)
5308ca345cSEnji Cooper 
5408ca345cSEnji Cooper static void clone_passwd(struct passwd *, struct passwd const *);
5508ca345cSEnji Cooper static int compare_passwd(struct passwd *, struct passwd *, void *);
5608ca345cSEnji Cooper static void free_passwd(struct passwd *);
5708ca345cSEnji Cooper 
5808ca345cSEnji Cooper static void sdump_passwd(struct passwd *, char *, size_t);
5987a9deedSEnji Cooper #ifdef DEBUG
6008ca345cSEnji Cooper static void dump_passwd(struct passwd *);
6187a9deedSEnji Cooper #endif
6208ca345cSEnji Cooper 
6308ca345cSEnji Cooper static int passwd_read_snapshot_func(struct passwd *, char *);
6408ca345cSEnji Cooper 
6508ca345cSEnji Cooper static int passwd_check_ambiguity(struct passwd_test_data *, struct passwd *);
666e411d8bSMark Johnston static int passwd_fill_test_data(struct passwd_test_data *,
676e411d8bSMark Johnston     int (*cb)(struct passwd *, void *));
6808ca345cSEnji Cooper static int passwd_test_correctness(struct passwd *, void *);
6908ca345cSEnji Cooper static int passwd_test_getpwnam(struct passwd *, void *);
7008ca345cSEnji Cooper static int passwd_test_getpwuid(struct passwd *, void *);
7108ca345cSEnji Cooper static int passwd_test_getpwent(struct passwd *, void *);
7208ca345cSEnji Cooper 
7308ca345cSEnji Cooper IMPLEMENT_TEST_DATA(passwd)
7408ca345cSEnji Cooper IMPLEMENT_TEST_FILE_SNAPSHOT(passwd)
7508ca345cSEnji Cooper IMPLEMENT_1PASS_TEST(passwd)
7608ca345cSEnji Cooper IMPLEMENT_2PASS_TEST(passwd)
7708ca345cSEnji Cooper 
7808ca345cSEnji Cooper static void
7908ca345cSEnji Cooper clone_passwd(struct passwd *dest, struct passwd const *src)
8008ca345cSEnji Cooper {
8108ca345cSEnji Cooper 	ATF_REQUIRE(dest != NULL);
8208ca345cSEnji Cooper 	ATF_REQUIRE(src != NULL);
8308ca345cSEnji Cooper 
8408ca345cSEnji Cooper 	memcpy(dest, src, sizeof(struct passwd));
8508ca345cSEnji Cooper 	if (src->pw_name != NULL)
8608ca345cSEnji Cooper 		dest->pw_name = strdup(src->pw_name);
8708ca345cSEnji Cooper 	if (src->pw_passwd != NULL)
8808ca345cSEnji Cooper 		dest->pw_passwd = strdup(src->pw_passwd);
8908ca345cSEnji Cooper 	if (src->pw_class != NULL)
9008ca345cSEnji Cooper 		dest->pw_class = strdup(src->pw_class);
9108ca345cSEnji Cooper 	if (src->pw_gecos != NULL)
9208ca345cSEnji Cooper 		dest->pw_gecos = strdup(src->pw_gecos);
9308ca345cSEnji Cooper 	if (src->pw_dir != NULL)
9408ca345cSEnji Cooper 		dest->pw_dir = strdup(src->pw_dir);
9508ca345cSEnji Cooper 	if (src->pw_shell != NULL)
9608ca345cSEnji Cooper 		dest->pw_shell = strdup(dest->pw_shell);
9708ca345cSEnji Cooper }
9808ca345cSEnji Cooper 
9908ca345cSEnji Cooper static int
10087a9deedSEnji Cooper compare_passwd(struct passwd *pwd1, struct passwd *pwd2, void *mdata __unused)
10108ca345cSEnji Cooper {
10208ca345cSEnji Cooper 	ATF_REQUIRE(pwd1 != NULL);
10308ca345cSEnji Cooper 	ATF_REQUIRE(pwd2 != NULL);
10408ca345cSEnji Cooper 
10508ca345cSEnji Cooper 	if (pwd1 == pwd2)
10608ca345cSEnji Cooper 		return (0);
10708ca345cSEnji Cooper 
10808ca345cSEnji Cooper 	if (pwd1->pw_uid != pwd2->pw_uid ||
10908ca345cSEnji Cooper 	    pwd1->pw_gid != pwd2->pw_gid ||
11008ca345cSEnji Cooper 	    pwd1->pw_change != pwd2->pw_change ||
11108ca345cSEnji Cooper 	    pwd1->pw_expire != pwd2->pw_expire ||
11208ca345cSEnji Cooper 	    pwd1->pw_fields != pwd2->pw_fields ||
11308ca345cSEnji Cooper 	    strcmp(pwd1->pw_name, pwd2->pw_name) != 0 ||
11408ca345cSEnji Cooper 	    strcmp(pwd1->pw_passwd, pwd2->pw_passwd) != 0 ||
11508ca345cSEnji Cooper 	    strcmp(pwd1->pw_class, pwd2->pw_class) != 0 ||
11608ca345cSEnji Cooper 	    strcmp(pwd1->pw_gecos, pwd2->pw_gecos) != 0 ||
11708ca345cSEnji Cooper 	    strcmp(pwd1->pw_dir, pwd2->pw_dir) != 0 ||
11808ca345cSEnji Cooper 	    strcmp(pwd1->pw_shell, pwd2->pw_shell) != 0)
11908ca345cSEnji Cooper 		return (-1);
12008ca345cSEnji Cooper 	else
12108ca345cSEnji Cooper 		return (0);
12208ca345cSEnji Cooper }
12308ca345cSEnji Cooper 
12408ca345cSEnji Cooper static void
12508ca345cSEnji Cooper free_passwd(struct passwd *pwd)
12608ca345cSEnji Cooper {
12708ca345cSEnji Cooper 	free(pwd->pw_name);
12808ca345cSEnji Cooper 	free(pwd->pw_passwd);
12908ca345cSEnji Cooper 	free(pwd->pw_class);
13008ca345cSEnji Cooper 	free(pwd->pw_gecos);
13108ca345cSEnji Cooper 	free(pwd->pw_dir);
13208ca345cSEnji Cooper 	free(pwd->pw_shell);
13308ca345cSEnji Cooper }
13408ca345cSEnji Cooper 
13508ca345cSEnji Cooper static void
13608ca345cSEnji Cooper sdump_passwd(struct passwd *pwd, char *buffer, size_t buflen)
13708ca345cSEnji Cooper {
13808ca345cSEnji Cooper 	snprintf(buffer, buflen, "%s:%s:%d:%d:%jd:%s:%s:%s:%s:%jd:%d",
13908ca345cSEnji Cooper 	    pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid,
14008ca345cSEnji Cooper 	    (uintmax_t)pwd->pw_change, pwd->pw_class, pwd->pw_gecos,
14108ca345cSEnji Cooper 	    pwd->pw_dir, pwd->pw_shell, (uintmax_t)pwd->pw_expire,
14208ca345cSEnji Cooper 	    pwd->pw_fields);
14308ca345cSEnji Cooper }
14408ca345cSEnji Cooper 
14587a9deedSEnji Cooper #ifdef DEBUG
14608ca345cSEnji Cooper static void
14708ca345cSEnji Cooper dump_passwd(struct passwd *pwd)
14808ca345cSEnji Cooper {
14908ca345cSEnji Cooper 	if (pwd != NULL) {
15008ca345cSEnji Cooper 		char buffer[2048];
15108ca345cSEnji Cooper 		sdump_passwd(pwd, buffer, sizeof(buffer));
15208ca345cSEnji Cooper 		printf("%s\n", buffer);
15308ca345cSEnji Cooper 	} else
15408ca345cSEnji Cooper 		printf("(null)\n");
15508ca345cSEnji Cooper }
15687a9deedSEnji Cooper #endif
15708ca345cSEnji Cooper 
15808ca345cSEnji Cooper static int
15908ca345cSEnji Cooper passwd_read_snapshot_func(struct passwd *pwd, char *line)
16008ca345cSEnji Cooper {
16108ca345cSEnji Cooper 	char *s, *ps, *ts;
16208ca345cSEnji Cooper 	int i;
16308ca345cSEnji Cooper 
16408ca345cSEnji Cooper #ifdef DEBUG
16508ca345cSEnji Cooper 	printf("1 line read from snapshot:\n%s\n", line);
16608ca345cSEnji Cooper #endif
16708ca345cSEnji Cooper 
16808ca345cSEnji Cooper 	i = 0;
16908ca345cSEnji Cooper 	ps = line;
17008ca345cSEnji Cooper 	memset(pwd, 0, sizeof(struct passwd));
17108ca345cSEnji Cooper 	while ((s = strsep(&ps, ":")) != NULL) {
17208ca345cSEnji Cooper 		switch (i) {
17308ca345cSEnji Cooper 		case 0:
17408ca345cSEnji Cooper 			pwd->pw_name = strdup(s);
17508ca345cSEnji Cooper 			ATF_REQUIRE(pwd->pw_name != NULL);
17608ca345cSEnji Cooper 			break;
17708ca345cSEnji Cooper 		case 1:
17808ca345cSEnji Cooper 			pwd->pw_passwd = strdup(s);
17908ca345cSEnji Cooper 			ATF_REQUIRE(pwd->pw_passwd != NULL);
18008ca345cSEnji Cooper 			break;
18108ca345cSEnji Cooper 		case 2:
18208ca345cSEnji Cooper 			pwd->pw_uid = (uid_t)strtol(s, &ts, 10);
18308ca345cSEnji Cooper 			if (*ts != '\0')
18408ca345cSEnji Cooper 				goto fin;
18508ca345cSEnji Cooper 			break;
18608ca345cSEnji Cooper 		case 3:
18708ca345cSEnji Cooper 			pwd->pw_gid = (gid_t)strtol(s, &ts, 10);
18808ca345cSEnji Cooper 			if (*ts != '\0')
18908ca345cSEnji Cooper 				goto fin;
19008ca345cSEnji Cooper 			break;
19108ca345cSEnji Cooper 		case 4:
19208ca345cSEnji Cooper 			pwd->pw_change = (time_t)strtol(s, &ts, 10);
19308ca345cSEnji Cooper 			if (*ts != '\0')
19408ca345cSEnji Cooper 				goto fin;
19508ca345cSEnji Cooper 			break;
19608ca345cSEnji Cooper 		case 5:
19708ca345cSEnji Cooper 			pwd->pw_class = strdup(s);
19808ca345cSEnji Cooper 			ATF_REQUIRE(pwd->pw_class != NULL);
19908ca345cSEnji Cooper 			break;
20008ca345cSEnji Cooper 		case 6:
20108ca345cSEnji Cooper 			pwd->pw_gecos = strdup(s);
20208ca345cSEnji Cooper 			ATF_REQUIRE(pwd->pw_gecos != NULL);
20308ca345cSEnji Cooper 			break;
20408ca345cSEnji Cooper 		case 7:
20508ca345cSEnji Cooper 			pwd->pw_dir = strdup(s);
20608ca345cSEnji Cooper 			ATF_REQUIRE(pwd->pw_dir != NULL);
20708ca345cSEnji Cooper 			break;
20808ca345cSEnji Cooper 		case 8:
20908ca345cSEnji Cooper 			pwd->pw_shell = strdup(s);
21008ca345cSEnji Cooper 			ATF_REQUIRE(pwd->pw_shell != NULL);
21108ca345cSEnji Cooper 			break;
21208ca345cSEnji Cooper 		case 9:
21308ca345cSEnji Cooper 			pwd->pw_expire = (time_t)strtol(s, &ts, 10);
21408ca345cSEnji Cooper 			if (*ts != '\0')
21508ca345cSEnji Cooper 				goto fin;
21608ca345cSEnji Cooper 			break;
21708ca345cSEnji Cooper 		case 10:
21808ca345cSEnji Cooper 			pwd->pw_fields = (int)strtol(s, &ts, 10);
21908ca345cSEnji Cooper 			if (*ts != '\0')
22008ca345cSEnji Cooper 				goto fin;
22108ca345cSEnji Cooper 			break;
22208ca345cSEnji Cooper 		default:
22308ca345cSEnji Cooper 			break;
22408ca345cSEnji Cooper 		}
22508ca345cSEnji Cooper 		++i;
22608ca345cSEnji Cooper 	}
22708ca345cSEnji Cooper 
22808ca345cSEnji Cooper fin:
22908ca345cSEnji Cooper 	if (i != 11) {
23008ca345cSEnji Cooper 		free_passwd(pwd);
23108ca345cSEnji Cooper 		memset(pwd, 0, sizeof(struct passwd));
23208ca345cSEnji Cooper 		return (-1);
23308ca345cSEnji Cooper 	}
23408ca345cSEnji Cooper 
23508ca345cSEnji Cooper 	return (0);
23608ca345cSEnji Cooper }
23708ca345cSEnji Cooper 
23808ca345cSEnji Cooper static int
2396e411d8bSMark Johnston passwd_fill_test_data(struct passwd_test_data *td,
2406e411d8bSMark Johnston     int (*cb)(struct passwd *, void *))
24108ca345cSEnji Cooper {
24208ca345cSEnji Cooper 	struct passwd *pwd;
243*d11904b3SAlan Somers 	const int limit = 1024;
244*d11904b3SAlan Somers 	int count = 0;
24508ca345cSEnji Cooper 
24608ca345cSEnji Cooper 	setpassent(1);
24708ca345cSEnji Cooper 	while ((pwd = getpwent()) != NULL) {
2486e411d8bSMark Johnston 		if (passwd_test_correctness(pwd, NULL) == 0) {
24908ca345cSEnji Cooper 			TEST_DATA_APPEND(passwd, td, pwd);
2506e411d8bSMark Johnston 			if (cb != NULL && cb(pwd, td) != 0)
25108ca345cSEnji Cooper 				return (-1);
2526e411d8bSMark Johnston 		} else {
2536e411d8bSMark Johnston 			return (-1);
2546e411d8bSMark Johnston 		}
255*d11904b3SAlan Somers 		if (++count >= limit)
256*d11904b3SAlan Somers 			break;
25708ca345cSEnji Cooper 	}
25808ca345cSEnji Cooper 	endpwent();
25908ca345cSEnji Cooper 
26008ca345cSEnji Cooper 	return (0);
26108ca345cSEnji Cooper }
26208ca345cSEnji Cooper 
26308ca345cSEnji Cooper static int
26487a9deedSEnji Cooper passwd_test_correctness(struct passwd *pwd, void *mdata __unused)
26508ca345cSEnji Cooper {
26608ca345cSEnji Cooper 
26708ca345cSEnji Cooper #ifdef DEBUG
26808ca345cSEnji Cooper 	printf("testing correctness with the following data:\n");
26908ca345cSEnji Cooper 	dump_passwd(pwd);
27008ca345cSEnji Cooper #endif
27108ca345cSEnji Cooper 
27208ca345cSEnji Cooper 	if (pwd == NULL)
27308ca345cSEnji Cooper 		return (-1);
27408ca345cSEnji Cooper 
27508ca345cSEnji Cooper 	if (pwd->pw_name == NULL)
27608ca345cSEnji Cooper 		goto errfin;
27708ca345cSEnji Cooper 
27808ca345cSEnji Cooper 	if (pwd->pw_passwd == NULL)
27908ca345cSEnji Cooper 		goto errfin;
28008ca345cSEnji Cooper 
28108ca345cSEnji Cooper 	if (pwd->pw_class == NULL)
28208ca345cSEnji Cooper 		goto errfin;
28308ca345cSEnji Cooper 
28408ca345cSEnji Cooper 	if (pwd->pw_gecos == NULL)
28508ca345cSEnji Cooper 		goto errfin;
28608ca345cSEnji Cooper 
28708ca345cSEnji Cooper 	if (pwd->pw_dir == NULL)
28808ca345cSEnji Cooper 		goto errfin;
28908ca345cSEnji Cooper 
29008ca345cSEnji Cooper 	if (pwd->pw_shell == NULL)
29108ca345cSEnji Cooper 		goto errfin;
29208ca345cSEnji Cooper 
29308ca345cSEnji Cooper #ifdef DEBUG
29408ca345cSEnji Cooper 	printf("correct\n");
29508ca345cSEnji Cooper #endif
29608ca345cSEnji Cooper 
29708ca345cSEnji Cooper 	return (0);
29808ca345cSEnji Cooper errfin:
29908ca345cSEnji Cooper #ifdef DEBUG
30008ca345cSEnji Cooper 	printf("incorrect\n");
30108ca345cSEnji Cooper #endif
30208ca345cSEnji Cooper 
30308ca345cSEnji Cooper 	return (-1);
30408ca345cSEnji Cooper }
30508ca345cSEnji Cooper 
30608ca345cSEnji Cooper /* passwd_check_ambiguity() is needed here because when doing the getpwent()
30708ca345cSEnji Cooper  * calls sequence, records from different nsswitch sources can be different,
30808ca345cSEnji Cooper  * though having the same pw_name/pw_uid */
30908ca345cSEnji Cooper static int
31008ca345cSEnji Cooper passwd_check_ambiguity(struct passwd_test_data *td, struct passwd *pwd)
31108ca345cSEnji Cooper {
31208ca345cSEnji Cooper 
313ed14c69dSMark Johnston 	return (TEST_DATA_FIND(passwd, td, pwd, compare_passwd, NULL) !=
314ed14c69dSMark Johnston 	    NULL ? 0 : -1);
31508ca345cSEnji Cooper }
31608ca345cSEnji Cooper 
31708ca345cSEnji Cooper static int
31808ca345cSEnji Cooper passwd_test_getpwnam(struct passwd *pwd_model, void *mdata)
31908ca345cSEnji Cooper {
32008ca345cSEnji Cooper 	struct passwd *pwd;
32108ca345cSEnji Cooper 
32208ca345cSEnji Cooper #ifdef DEBUG
32308ca345cSEnji Cooper 	printf("testing getpwnam() with the following data:\n");
32408ca345cSEnji Cooper 	dump_passwd(pwd_model);
32508ca345cSEnji Cooper #endif
32608ca345cSEnji Cooper 
32708ca345cSEnji Cooper 	pwd = getpwnam(pwd_model->pw_name);
32808ca345cSEnji Cooper 	if (passwd_test_correctness(pwd, NULL) != 0)
32908ca345cSEnji Cooper 		goto errfin;
33008ca345cSEnji Cooper 
331ed14c69dSMark Johnston 	if (compare_passwd(pwd, pwd_model, NULL) != 0 &&
332ed14c69dSMark Johnston 	    passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd) != 0)
33308ca345cSEnji Cooper 		goto errfin;
33408ca345cSEnji Cooper 
33508ca345cSEnji Cooper #ifdef DEBUG
33608ca345cSEnji Cooper 	printf("ok\n");
33708ca345cSEnji Cooper #endif
33808ca345cSEnji Cooper 	return (0);
33908ca345cSEnji Cooper 
34008ca345cSEnji Cooper errfin:
34108ca345cSEnji Cooper #ifdef DEBUG
34208ca345cSEnji Cooper 	printf("not ok\n");
34308ca345cSEnji Cooper #endif
34408ca345cSEnji Cooper 	return (-1);
34508ca345cSEnji Cooper }
34608ca345cSEnji Cooper 
34708ca345cSEnji Cooper static int
34808ca345cSEnji Cooper passwd_test_getpwuid(struct passwd *pwd_model, void *mdata)
34908ca345cSEnji Cooper {
35008ca345cSEnji Cooper 	struct passwd *pwd;
35108ca345cSEnji Cooper 
35208ca345cSEnji Cooper #ifdef DEBUG
35308ca345cSEnji Cooper 	printf("testing getpwuid() with the following data...\n");
35408ca345cSEnji Cooper 	dump_passwd(pwd_model);
35508ca345cSEnji Cooper #endif
35608ca345cSEnji Cooper 
35708ca345cSEnji Cooper 	pwd = getpwuid(pwd_model->pw_uid);
358ed14c69dSMark Johnston 	if (passwd_test_correctness(pwd, NULL) != 0 ||
359ed14c69dSMark Johnston 	    (compare_passwd(pwd, pwd_model, NULL) != 0 &&
360ed14c69dSMark Johnston 	    passwd_check_ambiguity((struct passwd_test_data *)mdata,
361ed14c69dSMark Johnston 	    pwd) != 0)) {
36208ca345cSEnji Cooper #ifdef DEBUG
36308ca345cSEnji Cooper 		printf("not ok\n");
36408ca345cSEnji Cooper #endif
36508ca345cSEnji Cooper 		return (-1);
36608ca345cSEnji Cooper 	} else {
36708ca345cSEnji Cooper #ifdef DEBUG
36808ca345cSEnji Cooper 		printf("ok\n");
36908ca345cSEnji Cooper #endif
37008ca345cSEnji Cooper 		return (0);
37108ca345cSEnji Cooper 	}
37208ca345cSEnji Cooper }
37308ca345cSEnji Cooper 
37408ca345cSEnji Cooper static int
37587a9deedSEnji Cooper passwd_test_getpwent(struct passwd *pwd, void *mdata __unused)
37608ca345cSEnji Cooper {
377ed14c69dSMark Johnston 	/*
378ed14c69dSMark Johnston 	 * Only correctness can be checked when doing 1-pass test for
379ed14c69dSMark Johnston 	 * getpwent().
380ed14c69dSMark Johnston 	 */
38108ca345cSEnji Cooper 	return (passwd_test_correctness(pwd, NULL));
38208ca345cSEnji Cooper }
38308ca345cSEnji Cooper 
38408ca345cSEnji Cooper static int
38508ca345cSEnji Cooper run_tests(const char *snapshot_file, enum test_methods method)
38608ca345cSEnji Cooper {
3876e411d8bSMark Johnston 	struct passwd_test_data td, td_snap, td_2pass, td_interleaved;
38808ca345cSEnji Cooper 	int rv;
38908ca345cSEnji Cooper 
39008ca345cSEnji Cooper 	TEST_DATA_INIT(passwd, &td, clone_passwd, free_passwd);
39108ca345cSEnji Cooper 	TEST_DATA_INIT(passwd, &td_snap, clone_passwd, free_passwd);
39208ca345cSEnji Cooper 	if (snapshot_file != NULL) {
39308ca345cSEnji Cooper 		if (access(snapshot_file, W_OK | R_OK) != 0) {
39408ca345cSEnji Cooper 			if (errno == ENOENT)
39508ca345cSEnji Cooper 				method = TEST_BUILD_SNAPSHOT;
39608ca345cSEnji Cooper 			else {
39708ca345cSEnji Cooper 				printf("can't access the file %s\n",
39808ca345cSEnji Cooper 				    snapshot_file);
39908ca345cSEnji Cooper 				rv = -1;
40008ca345cSEnji Cooper 				goto fin;
40108ca345cSEnji Cooper 			}
40208ca345cSEnji Cooper 		} else {
40308ca345cSEnji Cooper 			if (method == TEST_BUILD_SNAPSHOT) {
40408ca345cSEnji Cooper 				rv = 0;
40508ca345cSEnji Cooper 				goto fin;
40608ca345cSEnji Cooper 			}
40708ca345cSEnji Cooper 
40808ca345cSEnji Cooper 			TEST_SNAPSHOT_FILE_READ(passwd, snapshot_file,
40908ca345cSEnji Cooper 			    &td_snap, passwd_read_snapshot_func);
41008ca345cSEnji Cooper 		}
41108ca345cSEnji Cooper 	}
41208ca345cSEnji Cooper 
4136e411d8bSMark Johnston 	rv = passwd_fill_test_data(&td, NULL);
41408ca345cSEnji Cooper 	if (rv == -1)
41508ca345cSEnji Cooper 		return (-1);
41608ca345cSEnji Cooper 
41708ca345cSEnji Cooper 	switch (method) {
41808ca345cSEnji Cooper 	case TEST_GETPWNAM:
41908ca345cSEnji Cooper 		if (snapshot_file == NULL)
42008ca345cSEnji Cooper 			rv = DO_1PASS_TEST(passwd, &td,
42108ca345cSEnji Cooper 			    passwd_test_getpwnam, (void *)&td);
42208ca345cSEnji Cooper 		else
42308ca345cSEnji Cooper 			rv = DO_1PASS_TEST(passwd, &td_snap,
42408ca345cSEnji Cooper 			    passwd_test_getpwnam, (void *)&td_snap);
42508ca345cSEnji Cooper 		break;
42608ca345cSEnji Cooper 	case TEST_GETPWUID:
42708ca345cSEnji Cooper 		if (snapshot_file == NULL)
42808ca345cSEnji Cooper 			rv = DO_1PASS_TEST(passwd, &td,
42908ca345cSEnji Cooper 			    passwd_test_getpwuid, (void *)&td);
43008ca345cSEnji Cooper 		else
43108ca345cSEnji Cooper 			rv = DO_1PASS_TEST(passwd, &td_snap,
43208ca345cSEnji Cooper 			    passwd_test_getpwuid, (void *)&td_snap);
43308ca345cSEnji Cooper 		break;
43408ca345cSEnji Cooper 	case TEST_GETPWENT:
43508ca345cSEnji Cooper 		if (snapshot_file == NULL)
43608ca345cSEnji Cooper 			rv = DO_1PASS_TEST(passwd, &td, passwd_test_getpwent,
43708ca345cSEnji Cooper 			    (void *)&td);
43808ca345cSEnji Cooper 		else
43908ca345cSEnji Cooper 			rv = DO_2PASS_TEST(passwd, &td, &td_snap,
44008ca345cSEnji Cooper 			    compare_passwd, NULL);
44108ca345cSEnji Cooper 		break;
44208ca345cSEnji Cooper 	case TEST_GETPWENT_2PASS:
44308ca345cSEnji Cooper 		TEST_DATA_INIT(passwd, &td_2pass, clone_passwd, free_passwd);
4446e411d8bSMark Johnston 		rv = passwd_fill_test_data(&td_2pass, NULL);
44508ca345cSEnji Cooper 		if (rv != -1)
44608ca345cSEnji Cooper 			rv = DO_2PASS_TEST(passwd, &td, &td_2pass,
44708ca345cSEnji Cooper 			    compare_passwd, NULL);
44808ca345cSEnji Cooper 		TEST_DATA_DESTROY(passwd, &td_2pass);
44908ca345cSEnji Cooper 		break;
4506e411d8bSMark Johnston 	case TEST_GETPWENT_INTERLEAVED_GETPWNAM:
4516e411d8bSMark Johnston 		TEST_DATA_INIT(passwd, &td_interleaved, clone_passwd, free_passwd);
4526e411d8bSMark Johnston 		rv = passwd_fill_test_data(&td_interleaved, passwd_test_getpwnam);
4536e411d8bSMark Johnston 		if (rv != -1)
4546e411d8bSMark Johnston 			rv = DO_2PASS_TEST(passwd, &td, &td_interleaved,
4556e411d8bSMark Johnston 			    compare_passwd, NULL);
4566e411d8bSMark Johnston 		TEST_DATA_DESTROY(passwd, &td_interleaved);
4576e411d8bSMark Johnston 		break;
4586e411d8bSMark Johnston 	case TEST_GETPWENT_INTERLEAVED_GETPWUID:
4596e411d8bSMark Johnston 		TEST_DATA_INIT(passwd, &td_interleaved, clone_passwd, free_passwd);
4606e411d8bSMark Johnston 		rv = passwd_fill_test_data(&td_interleaved, passwd_test_getpwuid);
4616e411d8bSMark Johnston 		if (rv != -1)
4626e411d8bSMark Johnston 			rv = DO_2PASS_TEST(passwd, &td, &td_interleaved,
4636e411d8bSMark Johnston 			    compare_passwd, NULL);
4646e411d8bSMark Johnston 		TEST_DATA_DESTROY(passwd, &td_interleaved);
4656e411d8bSMark Johnston 		break;
46608ca345cSEnji Cooper 	case TEST_BUILD_SNAPSHOT:
46708ca345cSEnji Cooper 		if (snapshot_file != NULL)
46808ca345cSEnji Cooper 			rv = TEST_SNAPSHOT_FILE_WRITE(passwd, snapshot_file,
46908ca345cSEnji Cooper 			    &td, sdump_passwd);
47008ca345cSEnji Cooper 		break;
47108ca345cSEnji Cooper 	default:
47208ca345cSEnji Cooper 		rv = 0;
47308ca345cSEnji Cooper 		break;
47408ca345cSEnji Cooper 	}
47508ca345cSEnji Cooper 
47608ca345cSEnji Cooper fin:
47708ca345cSEnji Cooper 	TEST_DATA_DESTROY(passwd, &td_snap);
47808ca345cSEnji Cooper 	TEST_DATA_DESTROY(passwd, &td);
47908ca345cSEnji Cooper 
48008ca345cSEnji Cooper 	return (rv);
48108ca345cSEnji Cooper }
48208ca345cSEnji Cooper 
48308ca345cSEnji Cooper #define	SNAPSHOT_FILE	"snapshot_pwd"
48408ca345cSEnji Cooper 
48508ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getpwent);
48608ca345cSEnji Cooper ATF_TC_BODY(getpwent, tc)
48708ca345cSEnji Cooper {
4887abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETPWENT) == 0);
48908ca345cSEnji Cooper }
49008ca345cSEnji Cooper 
49108ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getpwent_with_snapshot);
49208ca345cSEnji Cooper ATF_TC_BODY(getpwent_with_snapshot, tc)
49308ca345cSEnji Cooper {
49408ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
49508ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT) == 0);
49608ca345cSEnji Cooper }
49708ca345cSEnji Cooper 
49808ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getpwent_with_two_pass);
49908ca345cSEnji Cooper ATF_TC_BODY(getpwent_with_two_pass, tc)
50008ca345cSEnji Cooper {
5017abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETPWENT_2PASS) == 0);
50208ca345cSEnji Cooper }
50308ca345cSEnji Cooper 
50408ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getpwnam);
50508ca345cSEnji Cooper ATF_TC_BODY(getpwnam, tc)
50608ca345cSEnji Cooper {
5077abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETPWNAM) == 0);
50808ca345cSEnji Cooper }
50908ca345cSEnji Cooper 
51008ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getpwnam_with_snapshot);
51108ca345cSEnji Cooper ATF_TC_BODY(getpwnam_with_snapshot, tc)
51208ca345cSEnji Cooper {
51308ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
51408ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWNAM) == 0);
51508ca345cSEnji Cooper }
51608ca345cSEnji Cooper 
51708ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getpwuid);
51808ca345cSEnji Cooper ATF_TC_BODY(getpwuid, tc)
51908ca345cSEnji Cooper {
5207abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETPWUID) == 0);
52108ca345cSEnji Cooper }
52208ca345cSEnji Cooper 
52308ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getpwuid_with_snapshot);
52408ca345cSEnji Cooper ATF_TC_BODY(getpwuid_with_snapshot, tc)
52508ca345cSEnji Cooper {
52608ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
52708ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWUID) == 0);
52808ca345cSEnji Cooper }
52908ca345cSEnji Cooper 
5306e411d8bSMark Johnston ATF_TC_WITHOUT_HEAD(getpwent_interleaved_getpwnam);
5316e411d8bSMark Johnston ATF_TC_BODY(getpwent_interleaved_getpwnam, tc)
5326e411d8bSMark Johnston {
5336e411d8bSMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETPWENT_INTERLEAVED_GETPWNAM) == 0);
5346e411d8bSMark Johnston }
5356e411d8bSMark Johnston 
5366e411d8bSMark Johnston ATF_TC_WITHOUT_HEAD(getpwent_interleaved_getpwuid);
5376e411d8bSMark Johnston ATF_TC_BODY(getpwent_interleaved_getpwuid, tc)
5386e411d8bSMark Johnston {
5396e411d8bSMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETPWENT_INTERLEAVED_GETPWUID) == 0);
5406e411d8bSMark Johnston }
5416e411d8bSMark Johnston 
54208ca345cSEnji Cooper ATF_TP_ADD_TCS(tp)
54308ca345cSEnji Cooper {
54408ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getpwent);
54508ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getpwent_with_snapshot);
54608ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getpwent_with_two_pass);
54708ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getpwnam);
54808ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getpwnam_with_snapshot);
54908ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getpwuid);
55008ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getpwuid_with_snapshot);
5516e411d8bSMark Johnston 	ATF_TP_ADD_TC(tp, getpwent_interleaved_getpwnam);
5526e411d8bSMark Johnston 	ATF_TP_ADD_TC(tp, getpwent_interleaved_getpwuid);
55308ca345cSEnji Cooper 
55408ca345cSEnji Cooper 	return (atf_no_error());
55508ca345cSEnji Cooper }
556