1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2013 The FreeBSD Foundation
5 * All rights reserved.
6 *
7 * This software was developed by Pawel Jakub Dawidek under sponsorship from
8 * the FreeBSD Foundation.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include <sys/capsicum.h>
36#include <sys/nv.h>
37
38#include <assert.h>
39#include <err.h>
40#include <errno.h>
41#include <pwd.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <unistd.h>
46
47#include <libcasper.h>
48
49#include <casper/cap_pwd.h>
50
51static int ntest = 1;
52
53#define CHECK(expr)     do {						\
54	if ((expr))							\
55		printf("ok %d # %s:%u\n", ntest, __FILE__, __LINE__);	\
56	else								\
57		printf("not ok %d # %s:%u\n", ntest, __FILE__, __LINE__); \
58	fflush(stdout);							\
59	ntest++;							\
60} while (0)
61#define CHECKX(expr)     do {						\
62	if ((expr)) {							\
63		printf("ok %d # %s:%u\n", ntest, __FILE__, __LINE__);	\
64	} else {							\
65		printf("not ok %d # %s:%u\n", ntest, __FILE__, __LINE__); \
66		exit(1);						\
67	}								\
68	fflush(stdout);							\
69	ntest++;							\
70} while (0)
71
72#define	UID_ROOT	0
73#define	UID_OPERATOR	2
74
75#define	GETPWENT0	0x0001
76#define	GETPWENT1	0x0002
77#define	GETPWENT2	0x0004
78#define	GETPWENT	(GETPWENT0 | GETPWENT1 | GETPWENT2)
79#define	GETPWENT_R0	0x0008
80#define	GETPWENT_R1	0x0010
81#define	GETPWENT_R2	0x0020
82#define	GETPWENT_R	(GETPWENT_R0 | GETPWENT_R1 | GETPWENT_R2)
83#define	GETPWNAM	0x0040
84#define	GETPWNAM_R	0x0080
85#define	GETPWUID	0x0100
86#define	GETPWUID_R	0x0200
87
88static bool
89passwd_compare(const struct passwd *pwd0, const struct passwd *pwd1)
90{
91
92	if (pwd0 == NULL && pwd1 == NULL)
93		return (true);
94	if (pwd0 == NULL || pwd1 == NULL)
95		return (false);
96
97	if (strcmp(pwd0->pw_name, pwd1->pw_name) != 0)
98		return (false);
99
100	if (pwd0->pw_passwd != NULL || pwd1->pw_passwd != NULL) {
101		if (pwd0->pw_passwd == NULL || pwd1->pw_passwd == NULL)
102			return (false);
103		if (strcmp(pwd0->pw_passwd, pwd1->pw_passwd) != 0)
104			return (false);
105	}
106
107	if (pwd0->pw_uid != pwd1->pw_uid)
108		return (false);
109
110	if (pwd0->pw_gid != pwd1->pw_gid)
111		return (false);
112
113	if (pwd0->pw_change != pwd1->pw_change)
114		return (false);
115
116	if (pwd0->pw_class != NULL || pwd1->pw_class != NULL) {
117		if (pwd0->pw_class == NULL || pwd1->pw_class == NULL)
118			return (false);
119		if (strcmp(pwd0->pw_class, pwd1->pw_class) != 0)
120			return (false);
121	}
122
123	if (pwd0->pw_gecos != NULL || pwd1->pw_gecos != NULL) {
124		if (pwd0->pw_gecos == NULL || pwd1->pw_gecos == NULL)
125			return (false);
126		if (strcmp(pwd0->pw_gecos, pwd1->pw_gecos) != 0)
127			return (false);
128	}
129
130	if (pwd0->pw_dir != NULL || pwd1->pw_dir != NULL) {
131		if (pwd0->pw_dir == NULL || pwd1->pw_dir == NULL)
132			return (false);
133		if (strcmp(pwd0->pw_dir, pwd1->pw_dir) != 0)
134			return (false);
135	}
136
137	if (pwd0->pw_shell != NULL || pwd1->pw_shell != NULL) {
138		if (pwd0->pw_shell == NULL || pwd1->pw_shell == NULL)
139			return (false);
140		if (strcmp(pwd0->pw_shell, pwd1->pw_shell) != 0)
141			return (false);
142	}
143
144	if (pwd0->pw_expire != pwd1->pw_expire)
145		return (false);
146
147	if (pwd0->pw_fields != pwd1->pw_fields)
148		return (false);
149
150	return (true);
151}
152
153static unsigned int
154runtest_cmds(cap_channel_t *cappwd)
155{
156	char bufs[1024], bufc[1024];
157	unsigned int result;
158	struct passwd *pwds, *pwdc;
159	struct passwd sts, stc;
160
161	result = 0;
162
163	setpwent();
164	cap_setpwent(cappwd);
165
166	pwds = getpwent();
167	pwdc = cap_getpwent(cappwd);
168	if (passwd_compare(pwds, pwdc)) {
169		result |= GETPWENT0;
170		pwds = getpwent();
171		pwdc = cap_getpwent(cappwd);
172		if (passwd_compare(pwds, pwdc))
173			result |= GETPWENT1;
174	}
175
176	getpwent_r(&sts, bufs, sizeof(bufs), &pwds);
177	cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc);
178	if (passwd_compare(pwds, pwdc)) {
179		result |= GETPWENT_R0;
180		getpwent_r(&sts, bufs, sizeof(bufs), &pwds);
181		cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc);
182		if (passwd_compare(pwds, pwdc))
183			result |= GETPWENT_R1;
184	}
185
186	setpwent();
187	cap_setpwent(cappwd);
188
189	getpwent_r(&sts, bufs, sizeof(bufs), &pwds);
190	cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc);
191	if (passwd_compare(pwds, pwdc))
192		result |= GETPWENT_R2;
193
194	pwds = getpwent();
195	pwdc = cap_getpwent(cappwd);
196	if (passwd_compare(pwds, pwdc))
197		result |= GETPWENT2;
198
199	pwds = getpwnam("root");
200	pwdc = cap_getpwnam(cappwd, "root");
201	if (passwd_compare(pwds, pwdc)) {
202		pwds = getpwnam("operator");
203		pwdc = cap_getpwnam(cappwd, "operator");
204		if (passwd_compare(pwds, pwdc))
205			result |= GETPWNAM;
206	}
207
208	getpwnam_r("root", &sts, bufs, sizeof(bufs), &pwds);
209	cap_getpwnam_r(cappwd, "root", &stc, bufc, sizeof(bufc), &pwdc);
210	if (passwd_compare(pwds, pwdc)) {
211		getpwnam_r("operator", &sts, bufs, sizeof(bufs), &pwds);
212		cap_getpwnam_r(cappwd, "operator", &stc, bufc, sizeof(bufc),
213		    &pwdc);
214		if (passwd_compare(pwds, pwdc))
215			result |= GETPWNAM_R;
216	}
217
218	pwds = getpwuid(UID_ROOT);
219	pwdc = cap_getpwuid(cappwd, UID_ROOT);
220	if (passwd_compare(pwds, pwdc)) {
221		pwds = getpwuid(UID_OPERATOR);
222		pwdc = cap_getpwuid(cappwd, UID_OPERATOR);
223		if (passwd_compare(pwds, pwdc))
224			result |= GETPWUID;
225	}
226
227	getpwuid_r(UID_ROOT, &sts, bufs, sizeof(bufs), &pwds);
228	cap_getpwuid_r(cappwd, UID_ROOT, &stc, bufc, sizeof(bufc), &pwdc);
229	if (passwd_compare(pwds, pwdc)) {
230		getpwuid_r(UID_OPERATOR, &sts, bufs, sizeof(bufs), &pwds);
231		cap_getpwuid_r(cappwd, UID_OPERATOR, &stc, bufc, sizeof(bufc),
232		    &pwdc);
233		if (passwd_compare(pwds, pwdc))
234			result |= GETPWUID_R;
235	}
236
237	return (result);
238}
239
240static void
241test_cmds(cap_channel_t *origcappwd)
242{
243	cap_channel_t *cappwd;
244	const char *cmds[7], *fields[10], *names[6];
245	uid_t uids[5];
246
247	fields[0] = "pw_name";
248	fields[1] = "pw_passwd";
249	fields[2] = "pw_uid";
250	fields[3] = "pw_gid";
251	fields[4] = "pw_change";
252	fields[5] = "pw_class";
253	fields[6] = "pw_gecos";
254	fields[7] = "pw_dir";
255	fields[8] = "pw_shell";
256	fields[9] = "pw_expire";
257
258	names[0] = "root";
259	names[1] = "toor";
260	names[2] = "daemon";
261	names[3] = "operator";
262	names[4] = "bin";
263	names[5] = "kmem";
264
265	uids[0] = 0;
266	uids[1] = 1;
267	uids[2] = 2;
268	uids[3] = 3;
269	uids[4] = 5;
270
271	/*
272	 * Allow:
273	 * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r,
274	 *       getpwuid, getpwuid_r
275	 * users:
276	 *     names: root, toor, daemon, operator, bin, kmem
277	 *     uids:
278	 */
279	cappwd = cap_clone(origcappwd);
280	CHECK(cappwd != NULL);
281
282	cmds[0] = "setpwent";
283	cmds[1] = "getpwent";
284	cmds[2] = "getpwent_r";
285	cmds[3] = "getpwnam";
286	cmds[4] = "getpwnam_r";
287	cmds[5] = "getpwuid";
288	cmds[6] = "getpwuid_r";
289	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == 0);
290	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
291	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
292
293	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
294	    GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
295
296	cap_close(cappwd);
297
298	/*
299	 * Allow:
300	 * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r,
301	 *       getpwuid, getpwuid_r
302	 * users:
303	 *     names:
304	 *     uids: 0, 1, 2, 3, 5
305	 */
306	cappwd = cap_clone(origcappwd);
307	CHECK(cappwd != NULL);
308
309	cmds[0] = "setpwent";
310	cmds[1] = "getpwent";
311	cmds[2] = "getpwent_r";
312	cmds[3] = "getpwnam";
313	cmds[4] = "getpwnam_r";
314	cmds[5] = "getpwuid";
315	cmds[6] = "getpwuid_r";
316	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == 0);
317	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
318	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
319
320	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
321	    GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
322
323	cap_close(cappwd);
324
325	/*
326	 * Allow:
327	 * cmds: getpwent, getpwent_r, getpwnam, getpwnam_r,
328	 *       getpwuid, getpwuid_r
329	 * users:
330	 *     names: root, toor, daemon, operator, bin, kmem
331	 *     uids:
332	 * Disallow:
333	 * cmds: setpwent
334	 * users:
335	 */
336	cappwd = cap_clone(origcappwd);
337	CHECK(cappwd != NULL);
338
339	cap_setpwent(cappwd);
340
341	cmds[0] = "getpwent";
342	cmds[1] = "getpwent_r";
343	cmds[2] = "getpwnam";
344	cmds[3] = "getpwnam_r";
345	cmds[4] = "getpwuid";
346	cmds[5] = "getpwuid_r";
347	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
348	cmds[0] = "setpwent";
349	cmds[1] = "getpwent";
350	cmds[2] = "getpwent_r";
351	cmds[3] = "getpwnam";
352	cmds[4] = "getpwnam_r";
353	cmds[5] = "getpwuid";
354	cmds[6] = "getpwuid_r";
355	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
356	cmds[0] = "setpwent";
357	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
358	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
359	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
360
361	CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | GETPWENT_R0 |
362	    GETPWENT_R1 | GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
363
364	cap_close(cappwd);
365
366	/*
367	 * Allow:
368	 * cmds: getpwent, getpwent_r, getpwnam, getpwnam_r,
369	 *       getpwuid, getpwuid_r
370	 * users:
371	 *     names:
372	 *     uids: 0, 1, 2, 3, 5
373	 * Disallow:
374	 * cmds: setpwent
375	 * users:
376	 */
377	cappwd = cap_clone(origcappwd);
378	CHECK(cappwd != NULL);
379
380	cap_setpwent(cappwd);
381
382	cmds[0] = "getpwent";
383	cmds[1] = "getpwent_r";
384	cmds[2] = "getpwnam";
385	cmds[3] = "getpwnam_r";
386	cmds[4] = "getpwuid";
387	cmds[5] = "getpwuid_r";
388	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
389	cmds[0] = "setpwent";
390	cmds[1] = "getpwent";
391	cmds[2] = "getpwent_r";
392	cmds[3] = "getpwnam";
393	cmds[4] = "getpwnam_r";
394	cmds[5] = "getpwuid";
395	cmds[6] = "getpwuid_r";
396	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
397	cmds[0] = "setpwent";
398	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
399	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
400	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
401
402	CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | GETPWENT_R0 |
403	    GETPWENT_R1 | GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
404
405	cap_close(cappwd);
406
407	/*
408	 * Allow:
409	 * cmds: setpwent, getpwent_r, getpwnam, getpwnam_r,
410	 *       getpwuid, getpwuid_r
411	 * users:
412	 *     names: root, toor, daemon, operator, bin, kmem
413	 *     uids:
414	 * Disallow:
415	 * cmds: getpwent
416	 * users:
417	 */
418	cappwd = cap_clone(origcappwd);
419	CHECK(cappwd != NULL);
420
421	cmds[0] = "setpwent";
422	cmds[1] = "getpwent_r";
423	cmds[2] = "getpwnam";
424	cmds[3] = "getpwnam_r";
425	cmds[4] = "getpwuid";
426	cmds[5] = "getpwuid_r";
427	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
428	cmds[0] = "setpwent";
429	cmds[1] = "getpwent";
430	cmds[2] = "getpwent_r";
431	cmds[3] = "getpwnam";
432	cmds[4] = "getpwnam_r";
433	cmds[5] = "getpwuid";
434	cmds[6] = "getpwuid_r";
435	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
436	cmds[0] = "getpwent";
437	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
438	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
439	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
440
441	CHECK(runtest_cmds(cappwd) == (GETPWENT_R2 |
442	    GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
443
444	cap_close(cappwd);
445
446	/*
447	 * Allow:
448	 * cmds: setpwent, getpwent_r, getpwnam, getpwnam_r,
449	 *       getpwuid, getpwuid_r
450	 * users:
451	 *     names:
452	 *     uids: 0, 1, 2, 3, 5
453	 * Disallow:
454	 * cmds: getpwent
455	 * users:
456	 */
457	cappwd = cap_clone(origcappwd);
458	CHECK(cappwd != NULL);
459
460	cmds[0] = "setpwent";
461	cmds[1] = "getpwent_r";
462	cmds[2] = "getpwnam";
463	cmds[3] = "getpwnam_r";
464	cmds[4] = "getpwuid";
465	cmds[5] = "getpwuid_r";
466	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
467	cmds[0] = "setpwent";
468	cmds[1] = "getpwent";
469	cmds[2] = "getpwent_r";
470	cmds[3] = "getpwnam";
471	cmds[4] = "getpwnam_r";
472	cmds[5] = "getpwuid";
473	cmds[6] = "getpwuid_r";
474	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
475	cmds[0] = "getpwent";
476	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
477	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
478	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
479
480	CHECK(runtest_cmds(cappwd) == (GETPWENT_R2 |
481	    GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
482
483	cap_close(cappwd);
484
485	/*
486	 * Allow:
487	 * cmds: setpwent, getpwent, getpwnam, getpwnam_r,
488	 *       getpwuid, getpwuid_r
489	 * users:
490	 *     names: root, toor, daemon, operator, bin, kmem
491	 *     uids:
492	 * Disallow:
493	 * cmds: getpwent_r
494	 * users:
495	 */
496	cappwd = cap_clone(origcappwd);
497	CHECK(cappwd != NULL);
498
499	cmds[0] = "setpwent";
500	cmds[1] = "getpwent";
501	cmds[2] = "getpwnam";
502	cmds[3] = "getpwnam_r";
503	cmds[4] = "getpwuid";
504	cmds[5] = "getpwuid_r";
505	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
506	cmds[0] = "setpwent";
507	cmds[1] = "getpwent";
508	cmds[2] = "getpwent_r";
509	cmds[3] = "getpwnam";
510	cmds[4] = "getpwnam_r";
511	cmds[5] = "getpwuid";
512	cmds[6] = "getpwuid_r";
513	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
514	cmds[0] = "getpwent_r";
515	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
516	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
517	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
518
519	CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 |
520	    GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
521
522	cap_close(cappwd);
523
524	/*
525	 * Allow:
526	 * cmds: setpwent, getpwent, getpwnam, getpwnam_r,
527	 *       getpwuid, getpwuid_r
528	 * users:
529	 *     names:
530	 *     uids: 0, 1, 2, 3, 5
531	 * Disallow:
532	 * cmds: getpwent_r
533	 * users:
534	 */
535	cappwd = cap_clone(origcappwd);
536	CHECK(cappwd != NULL);
537
538	cmds[0] = "setpwent";
539	cmds[1] = "getpwent";
540	cmds[2] = "getpwnam";
541	cmds[3] = "getpwnam_r";
542	cmds[4] = "getpwuid";
543	cmds[5] = "getpwuid_r";
544	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
545	cmds[0] = "setpwent";
546	cmds[1] = "getpwent";
547	cmds[2] = "getpwent_r";
548	cmds[3] = "getpwnam";
549	cmds[4] = "getpwnam_r";
550	cmds[5] = "getpwuid";
551	cmds[6] = "getpwuid_r";
552	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
553	cmds[0] = "getpwent_r";
554	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
555	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
556	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
557
558	CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 |
559	    GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R));
560
561	cap_close(cappwd);
562
563	/*
564	 * Allow:
565	 * cmds: setpwent, getpwent, getpwent_r, getpwnam_r,
566	 *       getpwuid, getpwuid_r
567	 * users:
568	 *     names: root, toor, daemon, operator, bin, kmem
569	 *     uids:
570	 * Disallow:
571	 * cmds: getpwnam
572	 * users:
573	 */
574	cappwd = cap_clone(origcappwd);
575	CHECK(cappwd != NULL);
576
577	cmds[0] = "setpwent";
578	cmds[1] = "getpwent";
579	cmds[2] = "getpwent_r";
580	cmds[3] = "getpwnam_r";
581	cmds[4] = "getpwuid";
582	cmds[5] = "getpwuid_r";
583	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
584	cmds[0] = "setpwent";
585	cmds[1] = "getpwent";
586	cmds[2] = "getpwent_r";
587	cmds[3] = "getpwnam";
588	cmds[4] = "getpwnam_r";
589	cmds[5] = "getpwuid";
590	cmds[6] = "getpwuid_r";
591	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
592	cmds[0] = "getpwnam";
593	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
594	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
595	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
596
597	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
598	    GETPWNAM_R | GETPWUID | GETPWUID_R));
599
600	cap_close(cappwd);
601
602	/*
603	 * Allow:
604	 * cmds: setpwent, getpwent, getpwent_r, getpwnam_r,
605	 *       getpwuid, getpwuid_r
606	 * users:
607	 *     names:
608	 *     uids: 0, 1, 2, 3, 5
609	 * Disallow:
610	 * cmds: getpwnam
611	 * users:
612	 */
613	cappwd = cap_clone(origcappwd);
614	CHECK(cappwd != NULL);
615
616	cmds[0] = "setpwent";
617	cmds[1] = "getpwent";
618	cmds[2] = "getpwent_r";
619	cmds[3] = "getpwnam_r";
620	cmds[4] = "getpwuid";
621	cmds[5] = "getpwuid_r";
622	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
623	cmds[0] = "setpwent";
624	cmds[1] = "getpwent";
625	cmds[2] = "getpwent_r";
626	cmds[3] = "getpwnam";
627	cmds[4] = "getpwnam_r";
628	cmds[5] = "getpwuid";
629	cmds[6] = "getpwuid_r";
630	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
631	cmds[0] = "getpwnam";
632	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
633	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
634	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
635
636	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
637	    GETPWNAM_R | GETPWUID | GETPWUID_R));
638
639	cap_close(cappwd);
640
641	/*
642	 * Allow:
643	 * cmds: setpwent, getpwent, getpwent_r, getpwnam,
644	 *       getpwuid, getpwuid_r
645	 * users:
646	 *     names: root, toor, daemon, operator, bin, kmem
647	 *     uids:
648	 * Disallow:
649	 * cmds: getpwnam_r
650	 * users:
651	 */
652	cappwd = cap_clone(origcappwd);
653	CHECK(cappwd != NULL);
654
655	cmds[0] = "setpwent";
656	cmds[1] = "getpwent";
657	cmds[2] = "getpwent_r";
658	cmds[3] = "getpwnam";
659	cmds[4] = "getpwuid";
660	cmds[5] = "getpwuid_r";
661	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
662	cmds[0] = "setpwent";
663	cmds[1] = "getpwent";
664	cmds[2] = "getpwent_r";
665	cmds[3] = "getpwnam";
666	cmds[4] = "getpwnam_r";
667	cmds[5] = "getpwuid";
668	cmds[6] = "getpwuid_r";
669	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
670	cmds[0] = "getpwnam_r";
671	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
672	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
673	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
674
675	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
676	    GETPWNAM | GETPWUID | GETPWUID_R));
677
678	cap_close(cappwd);
679
680	/*
681	 * Allow:
682	 * cmds: setpwent, getpwent, getpwent_r, getpwnam,
683	 *       getpwuid, getpwuid_r
684	 * users:
685	 *     names:
686	 *     uids: 0, 1, 2, 3, 5
687	 * Disallow:
688	 * cmds: getpwnam_r
689	 * users:
690	 */
691	cappwd = cap_clone(origcappwd);
692	CHECK(cappwd != NULL);
693
694	cmds[0] = "setpwent";
695	cmds[1] = "getpwent";
696	cmds[2] = "getpwent_r";
697	cmds[3] = "getpwnam";
698	cmds[4] = "getpwuid";
699	cmds[5] = "getpwuid_r";
700	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
701	cmds[0] = "setpwent";
702	cmds[1] = "getpwent";
703	cmds[2] = "getpwent_r";
704	cmds[3] = "getpwnam";
705	cmds[4] = "getpwnam_r";
706	cmds[5] = "getpwuid";
707	cmds[6] = "getpwuid_r";
708	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
709	cmds[0] = "getpwnam_r";
710	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
711	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
712	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
713
714	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
715	    GETPWNAM | GETPWUID | GETPWUID_R));
716
717	cap_close(cappwd);
718
719	/*
720	 * Allow:
721	 * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r,
722	 *       getpwuid_r
723	 * users:
724	 *     names: root, toor, daemon, operator, bin, kmem
725	 *     uids:
726	 * Disallow:
727	 * cmds: getpwuid
728	 * users:
729	 */
730	cappwd = cap_clone(origcappwd);
731	CHECK(cappwd != NULL);
732
733	cmds[0] = "setpwent";
734	cmds[1] = "getpwent";
735	cmds[2] = "getpwent_r";
736	cmds[3] = "getpwnam";
737	cmds[4] = "getpwnam_r";
738	cmds[5] = "getpwuid_r";
739	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
740	cmds[0] = "setpwent";
741	cmds[1] = "getpwent";
742	cmds[2] = "getpwent_r";
743	cmds[3] = "getpwnam";
744	cmds[4] = "getpwnam_r";
745	cmds[5] = "getpwuid";
746	cmds[6] = "getpwuid_r";
747	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
748	cmds[0] = "getpwuid";
749	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
750	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
751	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
752
753	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
754	    GETPWNAM | GETPWNAM_R | GETPWUID_R));
755
756	cap_close(cappwd);
757
758	/*
759	 * Allow:
760	 * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r,
761	 *       getpwuid_r
762	 * users:
763	 *     names:
764	 *     uids: 0, 1, 2, 3, 5
765	 * Disallow:
766	 * cmds: getpwuid
767	 * users:
768	 */
769	cappwd = cap_clone(origcappwd);
770	CHECK(cappwd != NULL);
771
772	cmds[0] = "setpwent";
773	cmds[1] = "getpwent";
774	cmds[2] = "getpwent_r";
775	cmds[3] = "getpwnam";
776	cmds[4] = "getpwnam_r";
777	cmds[5] = "getpwuid_r";
778	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
779	cmds[0] = "setpwent";
780	cmds[1] = "getpwent";
781	cmds[2] = "getpwent_r";
782	cmds[3] = "getpwnam";
783	cmds[4] = "getpwnam_r";
784	cmds[5] = "getpwuid";
785	cmds[6] = "getpwuid_r";
786	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
787	cmds[0] = "getpwuid";
788	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
789	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
790	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
791
792	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
793	    GETPWNAM | GETPWNAM_R | GETPWUID_R));
794
795	cap_close(cappwd);
796
797	/*
798	 * Allow:
799	 * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r,
800	 *       getpwuid
801	 * users:
802	 *     names: root, toor, daemon, operator, bin, kmem
803	 *     uids:
804	 * Disallow:
805	 * cmds: getpwuid_r
806	 * users:
807	 */
808	cappwd = cap_clone(origcappwd);
809	CHECK(cappwd != NULL);
810
811	cmds[0] = "setpwent";
812	cmds[1] = "getpwent";
813	cmds[2] = "getpwent_r";
814	cmds[3] = "getpwnam";
815	cmds[4] = "getpwnam_r";
816	cmds[5] = "getpwuid";
817	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
818	cmds[0] = "setpwent";
819	cmds[1] = "getpwent";
820	cmds[2] = "getpwent_r";
821	cmds[3] = "getpwnam";
822	cmds[4] = "getpwnam_r";
823	cmds[5] = "getpwuid";
824	cmds[6] = "getpwuid_r";
825	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
826	cmds[0] = "getpwuid_r";
827	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
828	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
829	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
830
831	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
832	    GETPWNAM | GETPWNAM_R | GETPWUID));
833
834	cap_close(cappwd);
835
836	/*
837	 * Allow:
838	 * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r,
839	 *       getpwuid
840	 * users:
841	 *     names:
842	 *     uids: 0, 1, 2, 3, 5
843	 * Disallow:
844	 * cmds: getpwuid_r
845	 * users:
846	 */
847	cappwd = cap_clone(origcappwd);
848	CHECK(cappwd != NULL);
849
850	cmds[0] = "setpwent";
851	cmds[1] = "getpwent";
852	cmds[2] = "getpwent_r";
853	cmds[3] = "getpwnam";
854	cmds[4] = "getpwnam_r";
855	cmds[5] = "getpwuid";
856	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0);
857	cmds[0] = "setpwent";
858	cmds[1] = "getpwent";
859	cmds[2] = "getpwent_r";
860	cmds[3] = "getpwnam";
861	cmds[4] = "getpwnam_r";
862	cmds[5] = "getpwuid";
863	cmds[6] = "getpwuid_r";
864	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE);
865	cmds[0] = "getpwuid_r";
866	CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE);
867	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
868	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0);
869
870	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R |
871	    GETPWNAM | GETPWNAM_R | GETPWUID));
872
873	cap_close(cappwd);
874}
875
876#define	PW_NAME		_PWF_NAME
877#define	PW_PASSWD	_PWF_PASSWD
878#define	PW_UID		_PWF_UID
879#define	PW_GID		_PWF_GID
880#define	PW_CHANGE	_PWF_CHANGE
881#define	PW_CLASS	_PWF_CLASS
882#define	PW_GECOS	_PWF_GECOS
883#define	PW_DIR		_PWF_DIR
884#define	PW_SHELL	_PWF_SHELL
885#define	PW_EXPIRE	_PWF_EXPIRE
886
887static unsigned int
888passwd_fields(const struct passwd *pwd)
889{
890	unsigned int result;
891
892	result = 0;
893
894	if (pwd->pw_name != NULL && pwd->pw_name[0] != '\0')
895		result |= PW_NAME;
896//	else
897//		printf("No pw_name\n");
898
899	if (pwd->pw_passwd != NULL && pwd->pw_passwd[0] != '\0')
900		result |= PW_PASSWD;
901	else if ((pwd->pw_fields & _PWF_PASSWD) != 0)
902		result |= PW_PASSWD;
903//	else
904//		printf("No pw_passwd\n");
905
906	if (pwd->pw_uid != (uid_t)-1)
907		result |= PW_UID;
908//	else
909//		printf("No pw_uid\n");
910
911	if (pwd->pw_gid != (gid_t)-1)
912		result |= PW_GID;
913//	else
914//		printf("No pw_gid\n");
915
916	if (pwd->pw_change != 0 || (pwd->pw_fields & _PWF_CHANGE) != 0)
917		result |= PW_CHANGE;
918//	else
919//		printf("No pw_change\n");
920
921	if (pwd->pw_class != NULL && pwd->pw_class[0] != '\0')
922		result |= PW_CLASS;
923	else if ((pwd->pw_fields & _PWF_CLASS) != 0)
924		result |= PW_CLASS;
925//	else
926//		printf("No pw_class\n");
927
928	if (pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0')
929		result |= PW_GECOS;
930	else if ((pwd->pw_fields & _PWF_GECOS) != 0)
931		result |= PW_GECOS;
932//	else
933//		printf("No pw_gecos\n");
934
935	if (pwd->pw_dir != NULL && pwd->pw_dir[0] != '\0')
936		result |= PW_DIR;
937	else if ((pwd->pw_fields & _PWF_DIR) != 0)
938		result |= PW_DIR;
939//	else
940//		printf("No pw_dir\n");
941
942	if (pwd->pw_shell != NULL && pwd->pw_shell[0] != '\0')
943		result |= PW_SHELL;
944	else if ((pwd->pw_fields & _PWF_SHELL) != 0)
945		result |= PW_SHELL;
946//	else
947//		printf("No pw_shell\n");
948
949	if (pwd->pw_expire != 0 || (pwd->pw_fields & _PWF_EXPIRE) != 0)
950		result |= PW_EXPIRE;
951//	else
952//		printf("No pw_expire\n");
953
954if (false && pwd->pw_fields != (int)result) {
955printf("fields=0x%x != result=0x%x\n", (const unsigned int)pwd->pw_fields, result);
956printf("           fields result\n");
957printf("PW_NAME    %d      %d\n", (pwd->pw_fields & PW_NAME) != 0, (result & PW_NAME) != 0);
958printf("PW_PASSWD  %d      %d\n", (pwd->pw_fields & PW_PASSWD) != 0, (result & PW_PASSWD) != 0);
959printf("PW_UID     %d      %d\n", (pwd->pw_fields & PW_UID) != 0, (result & PW_UID) != 0);
960printf("PW_GID     %d      %d\n", (pwd->pw_fields & PW_GID) != 0, (result & PW_GID) != 0);
961printf("PW_CHANGE  %d      %d\n", (pwd->pw_fields & PW_CHANGE) != 0, (result & PW_CHANGE) != 0);
962printf("PW_CLASS   %d      %d\n", (pwd->pw_fields & PW_CLASS) != 0, (result & PW_CLASS) != 0);
963printf("PW_GECOS   %d      %d\n", (pwd->pw_fields & PW_GECOS) != 0, (result & PW_GECOS) != 0);
964printf("PW_DIR     %d      %d\n", (pwd->pw_fields & PW_DIR) != 0, (result & PW_DIR) != 0);
965printf("PW_SHELL   %d      %d\n", (pwd->pw_fields & PW_SHELL) != 0, (result & PW_SHELL) != 0);
966printf("PW_EXPIRE  %d      %d\n", (pwd->pw_fields & PW_EXPIRE) != 0, (result & PW_EXPIRE) != 0);
967}
968
969//printf("result=0x%x\n", result);
970	return (result);
971}
972
973static bool
974runtest_fields(cap_channel_t *cappwd, unsigned int expected)
975{
976	char buf[1024];
977	struct passwd *pwd;
978	struct passwd st;
979
980//printf("expected=0x%x\n", expected);
981	cap_setpwent(cappwd);
982	pwd = cap_getpwent(cappwd);
983	if ((passwd_fields(pwd) & ~expected) != 0)
984		return (false);
985
986	cap_setpwent(cappwd);
987	cap_getpwent_r(cappwd, &st, buf, sizeof(buf), &pwd);
988	if ((passwd_fields(pwd) & ~expected) != 0)
989		return (false);
990
991	pwd = cap_getpwnam(cappwd, "root");
992	if ((passwd_fields(pwd) & ~expected) != 0)
993		return (false);
994
995	cap_getpwnam_r(cappwd, "root", &st, buf, sizeof(buf), &pwd);
996	if ((passwd_fields(pwd) & ~expected) != 0)
997		return (false);
998
999	pwd = cap_getpwuid(cappwd, UID_ROOT);
1000	if ((passwd_fields(pwd) & ~expected) != 0)
1001		return (false);
1002
1003	cap_getpwuid_r(cappwd, UID_ROOT, &st, buf, sizeof(buf), &pwd);
1004	if ((passwd_fields(pwd) & ~expected) != 0)
1005		return (false);
1006
1007	return (true);
1008}
1009
1010static void
1011test_fields(cap_channel_t *origcappwd)
1012{
1013	cap_channel_t *cappwd;
1014	const char *fields[10];
1015
1016	/* No limits. */
1017
1018	CHECK(runtest_fields(origcappwd, PW_NAME | PW_PASSWD | PW_UID |
1019	    PW_GID | PW_CHANGE | PW_CLASS | PW_GECOS | PW_DIR | PW_SHELL |
1020	    PW_EXPIRE));
1021
1022	/*
1023	 * Allow:
1024	 * fields: pw_name, pw_passwd, pw_uid, pw_gid, pw_change, pw_class,
1025	 *         pw_gecos, pw_dir, pw_shell, pw_expire
1026	 */
1027	cappwd = cap_clone(origcappwd);
1028	CHECK(cappwd != NULL);
1029
1030	fields[0] = "pw_name";
1031	fields[1] = "pw_passwd";
1032	fields[2] = "pw_uid";
1033	fields[3] = "pw_gid";
1034	fields[4] = "pw_change";
1035	fields[5] = "pw_class";
1036	fields[6] = "pw_gecos";
1037	fields[7] = "pw_dir";
1038	fields[8] = "pw_shell";
1039	fields[9] = "pw_expire";
1040	CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0);
1041
1042	CHECK(runtest_fields(origcappwd, PW_NAME | PW_PASSWD | PW_UID |
1043	    PW_GID | PW_CHANGE | PW_CLASS | PW_GECOS | PW_DIR | PW_SHELL |
1044	    PW_EXPIRE));
1045
1046	cap_close(cappwd);
1047
1048	/*
1049	 * Allow:
1050	 * fields: pw_name, pw_passwd, pw_uid, pw_gid, pw_change
1051	 */
1052	cappwd = cap_clone(origcappwd);
1053	CHECK(cappwd != NULL);
1054
1055	fields[0] = "pw_name";
1056	fields[1] = "pw_passwd";
1057	fields[2] = "pw_uid";
1058	fields[3] = "pw_gid";
1059	fields[4] = "pw_change";
1060	CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0);
1061	fields[5] = "pw_class";
1062	CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 &&
1063	    errno == ENOTCAPABLE);
1064	fields[0] = "pw_class";
1065	CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 &&
1066	    errno == ENOTCAPABLE);
1067
1068	CHECK(runtest_fields(cappwd, PW_NAME | PW_PASSWD | PW_UID |
1069	    PW_GID | PW_CHANGE));
1070
1071	cap_close(cappwd);
1072
1073	/*
1074	 * Allow:
1075	 * fields: pw_class, pw_gecos, pw_dir, pw_shell, pw_expire
1076	 */
1077	cappwd = cap_clone(origcappwd);
1078	CHECK(cappwd != NULL);
1079
1080	fields[0] = "pw_class";
1081	fields[1] = "pw_gecos";
1082	fields[2] = "pw_dir";
1083	fields[3] = "pw_shell";
1084	fields[4] = "pw_expire";
1085	CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0);
1086	fields[5] = "pw_uid";
1087	CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 &&
1088	    errno == ENOTCAPABLE);
1089	fields[0] = "pw_uid";
1090	CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 &&
1091	    errno == ENOTCAPABLE);
1092
1093	CHECK(runtest_fields(cappwd, PW_CLASS | PW_GECOS | PW_DIR |
1094	    PW_SHELL | PW_EXPIRE));
1095
1096	cap_close(cappwd);
1097
1098	/*
1099	 * Allow:
1100	 * fields: pw_name, pw_uid, pw_change, pw_gecos, pw_shell
1101	 */
1102	cappwd = cap_clone(origcappwd);
1103	CHECK(cappwd != NULL);
1104
1105	fields[0] = "pw_name";
1106	fields[1] = "pw_uid";
1107	fields[2] = "pw_change";
1108	fields[3] = "pw_gecos";
1109	fields[4] = "pw_shell";
1110	CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0);
1111	fields[5] = "pw_class";
1112	CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 &&
1113	    errno == ENOTCAPABLE);
1114	fields[0] = "pw_class";
1115	CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 &&
1116	    errno == ENOTCAPABLE);
1117
1118	CHECK(runtest_fields(cappwd, PW_NAME | PW_UID | PW_CHANGE |
1119	    PW_GECOS | PW_SHELL));
1120
1121	cap_close(cappwd);
1122
1123	/*
1124	 * Allow:
1125	 * fields: pw_passwd, pw_gid, pw_class, pw_dir, pw_expire
1126	 */
1127	cappwd = cap_clone(origcappwd);
1128	CHECK(cappwd != NULL);
1129
1130	fields[0] = "pw_passwd";
1131	fields[1] = "pw_gid";
1132	fields[2] = "pw_class";
1133	fields[3] = "pw_dir";
1134	fields[4] = "pw_expire";
1135	CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0);
1136	fields[5] = "pw_uid";
1137	CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 &&
1138	    errno == ENOTCAPABLE);
1139	fields[0] = "pw_uid";
1140	CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 &&
1141	    errno == ENOTCAPABLE);
1142
1143	CHECK(runtest_fields(cappwd, PW_PASSWD | PW_GID | PW_CLASS |
1144	    PW_DIR | PW_EXPIRE));
1145
1146	cap_close(cappwd);
1147
1148	/*
1149	 * Allow:
1150	 * fields: pw_uid, pw_class, pw_shell
1151	 */
1152	cappwd = cap_clone(origcappwd);
1153	CHECK(cappwd != NULL);
1154
1155	fields[0] = "pw_uid";
1156	fields[1] = "pw_class";
1157	fields[2] = "pw_shell";
1158	CHECK(cap_pwd_limit_fields(cappwd, fields, 3) == 0);
1159	fields[3] = "pw_change";
1160	CHECK(cap_pwd_limit_fields(cappwd, fields, 4) == -1 &&
1161	    errno == ENOTCAPABLE);
1162	fields[0] = "pw_change";
1163	CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 &&
1164	    errno == ENOTCAPABLE);
1165
1166	CHECK(runtest_fields(cappwd, PW_UID | PW_CLASS | PW_SHELL));
1167
1168	cap_close(cappwd);
1169
1170	/*
1171	 * Allow:
1172	 * fields: pw_change
1173	 */
1174	cappwd = cap_clone(origcappwd);
1175	CHECK(cappwd != NULL);
1176
1177	fields[0] = "pw_change";
1178	CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == 0);
1179	fields[1] = "pw_uid";
1180	CHECK(cap_pwd_limit_fields(cappwd, fields, 2) == -1 &&
1181	    errno == ENOTCAPABLE);
1182	fields[0] = "pw_uid";
1183	CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 &&
1184	    errno == ENOTCAPABLE);
1185
1186	CHECK(runtest_fields(cappwd, PW_CHANGE));
1187
1188	cap_close(cappwd);
1189}
1190
1191static bool
1192runtest_users(cap_channel_t *cappwd, const char **names, const uid_t *uids,
1193    size_t nusers)
1194{
1195	char buf[1024];
1196	struct passwd *pwd;
1197	struct passwd st;
1198	unsigned int i, got;
1199
1200	cap_setpwent(cappwd);
1201	got = 0;
1202	for (;;) {
1203		pwd = cap_getpwent(cappwd);
1204		if (pwd == NULL)
1205			break;
1206		got++;
1207		for (i = 0; i < nusers; i++) {
1208			if (strcmp(names[i], pwd->pw_name) == 0 &&
1209			    uids[i] == pwd->pw_uid) {
1210				break;
1211			}
1212		}
1213		if (i == nusers)
1214			return (false);
1215	}
1216	if (got != nusers)
1217		return (false);
1218
1219	cap_setpwent(cappwd);
1220	got = 0;
1221	for (;;) {
1222		cap_getpwent_r(cappwd, &st, buf, sizeof(buf), &pwd);
1223		if (pwd == NULL)
1224			break;
1225		got++;
1226		for (i = 0; i < nusers; i++) {
1227			if (strcmp(names[i], pwd->pw_name) == 0 &&
1228			    uids[i] == pwd->pw_uid) {
1229				break;
1230			}
1231		}
1232		if (i == nusers)
1233			return (false);
1234	}
1235	if (got != nusers)
1236		return (false);
1237
1238	for (i = 0; i < nusers; i++) {
1239		pwd = cap_getpwnam(cappwd, names[i]);
1240		if (pwd == NULL)
1241			return (false);
1242	}
1243
1244	for (i = 0; i < nusers; i++) {
1245		cap_getpwnam_r(cappwd, names[i], &st, buf, sizeof(buf), &pwd);
1246		if (pwd == NULL)
1247			return (false);
1248	}
1249
1250	for (i = 0; i < nusers; i++) {
1251		pwd = cap_getpwuid(cappwd, uids[i]);
1252		if (pwd == NULL)
1253			return (false);
1254	}
1255
1256	for (i = 0; i < nusers; i++) {
1257		cap_getpwuid_r(cappwd, uids[i], &st, buf, sizeof(buf), &pwd);
1258		if (pwd == NULL)
1259			return (false);
1260	}
1261
1262	return (true);
1263}
1264
1265static void
1266test_users(cap_channel_t *origcappwd)
1267{
1268	cap_channel_t *cappwd;
1269	const char *names[6];
1270	uid_t uids[6];
1271
1272	/*
1273	 * Allow:
1274	 * users:
1275	 *     names: root, toor, daemon, operator, bin, tty
1276	 *     uids:
1277	 */
1278	cappwd = cap_clone(origcappwd);
1279	CHECK(cappwd != NULL);
1280
1281	names[0] = "root";
1282	names[1] = "toor";
1283	names[2] = "daemon";
1284	names[3] = "operator";
1285	names[4] = "bin";
1286	names[5] = "tty";
1287	CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0);
1288	uids[0] = 0;
1289	uids[1] = 0;
1290	uids[2] = 1;
1291	uids[3] = 2;
1292	uids[4] = 3;
1293	uids[5] = 4;
1294
1295	CHECK(runtest_users(cappwd, names, uids, 6));
1296
1297	cap_close(cappwd);
1298
1299	/*
1300	 * Allow:
1301	 * users:
1302	 *     names: daemon, operator, bin
1303	 *     uids:
1304	 */
1305	cappwd = cap_clone(origcappwd);
1306	CHECK(cappwd != NULL);
1307
1308	names[0] = "daemon";
1309	names[1] = "operator";
1310	names[2] = "bin";
1311	CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == 0);
1312	names[3] = "tty";
1313	CHECK(cap_pwd_limit_users(cappwd, names, 4, NULL, 0) == -1 &&
1314	    errno == ENOTCAPABLE);
1315	names[0] = "tty";
1316	CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 &&
1317	    errno == ENOTCAPABLE);
1318	names[0] = "daemon";
1319	uids[0] = 1;
1320	uids[1] = 2;
1321	uids[2] = 3;
1322
1323	CHECK(runtest_users(cappwd, names, uids, 3));
1324
1325	cap_close(cappwd);
1326
1327	/*
1328	 * Allow:
1329	 * users:
1330	 *     names: daemon, bin, tty
1331	 *     uids:
1332	 */
1333	cappwd = cap_clone(origcappwd);
1334	CHECK(cappwd != NULL);
1335
1336	names[0] = "daemon";
1337	names[1] = "bin";
1338	names[2] = "tty";
1339	CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == 0);
1340	names[3] = "operator";
1341	CHECK(cap_pwd_limit_users(cappwd, names, 4, NULL, 0) == -1 &&
1342	    errno == ENOTCAPABLE);
1343	names[0] = "operator";
1344	CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 &&
1345	    errno == ENOTCAPABLE);
1346	names[0] = "daemon";
1347	uids[0] = 1;
1348	uids[1] = 3;
1349	uids[2] = 4;
1350
1351	CHECK(runtest_users(cappwd, names, uids, 3));
1352
1353	cap_close(cappwd);
1354
1355	/*
1356	 * Allow:
1357	 * users:
1358	 *     names:
1359	 *     uids: 1, 2, 3
1360	 */
1361	cappwd = cap_clone(origcappwd);
1362	CHECK(cappwd != NULL);
1363
1364	names[0] = "daemon";
1365	names[1] = "operator";
1366	names[2] = "bin";
1367	uids[0] = 1;
1368	uids[1] = 2;
1369	uids[2] = 3;
1370	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == 0);
1371	uids[3] = 4;
1372	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 4) == -1 &&
1373	    errno == ENOTCAPABLE);
1374	uids[0] = 4;
1375	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 &&
1376	    errno == ENOTCAPABLE);
1377	uids[0] = 1;
1378
1379	CHECK(runtest_users(cappwd, names, uids, 3));
1380
1381	cap_close(cappwd);
1382
1383	/*
1384	 * Allow:
1385	 * users:
1386	 *     names:
1387	 *     uids: 1, 3, 4
1388	 */
1389	cappwd = cap_clone(origcappwd);
1390	CHECK(cappwd != NULL);
1391
1392	names[0] = "daemon";
1393	names[1] = "bin";
1394	names[2] = "tty";
1395	uids[0] = 1;
1396	uids[1] = 3;
1397	uids[2] = 4;
1398	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == 0);
1399	uids[3] = 5;
1400	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 4) == -1 &&
1401	    errno == ENOTCAPABLE);
1402	uids[0] = 5;
1403	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 &&
1404	    errno == ENOTCAPABLE);
1405	uids[0] = 1;
1406
1407	CHECK(runtest_users(cappwd, names, uids, 3));
1408
1409	cap_close(cappwd);
1410
1411	/*
1412	 * Allow:
1413	 * users:
1414	 *     names: bin
1415	 *     uids:
1416	 */
1417	cappwd = cap_clone(origcappwd);
1418	CHECK(cappwd != NULL);
1419
1420	names[0] = "bin";
1421	CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == 0);
1422	names[1] = "operator";
1423	CHECK(cap_pwd_limit_users(cappwd, names, 2, NULL, 0) == -1 &&
1424	    errno == ENOTCAPABLE);
1425	names[0] = "operator";
1426	CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 &&
1427	    errno == ENOTCAPABLE);
1428	names[0] = "bin";
1429	uids[0] = 3;
1430
1431	CHECK(runtest_users(cappwd, names, uids, 1));
1432
1433	cap_close(cappwd);
1434
1435	/*
1436	 * Allow:
1437	 * users:
1438	 *     names: daemon, tty
1439	 *     uids:
1440	 */
1441	cappwd = cap_clone(origcappwd);
1442	CHECK(cappwd != NULL);
1443
1444	names[0] = "daemon";
1445	names[1] = "tty";
1446	CHECK(cap_pwd_limit_users(cappwd, names, 2, NULL, 0) == 0);
1447	names[2] = "operator";
1448	CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == -1 &&
1449	    errno == ENOTCAPABLE);
1450	names[0] = "operator";
1451	CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 &&
1452	    errno == ENOTCAPABLE);
1453	names[0] = "daemon";
1454	uids[0] = 1;
1455	uids[1] = 4;
1456
1457	CHECK(runtest_users(cappwd, names, uids, 2));
1458
1459	cap_close(cappwd);
1460
1461	/*
1462	 * Allow:
1463	 * users:
1464	 *     names:
1465	 *     uids: 3
1466	 */
1467	cappwd = cap_clone(origcappwd);
1468	CHECK(cappwd != NULL);
1469
1470	names[0] = "bin";
1471	uids[0] = 3;
1472	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == 0);
1473	uids[1] = 4;
1474	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 2) == -1 &&
1475	    errno == ENOTCAPABLE);
1476	uids[0] = 4;
1477	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 &&
1478	    errno == ENOTCAPABLE);
1479	uids[0] = 3;
1480
1481	CHECK(runtest_users(cappwd, names, uids, 1));
1482
1483	cap_close(cappwd);
1484
1485	/*
1486	 * Allow:
1487	 * users:
1488	 *     names:
1489	 *     uids: 1, 4
1490	 */
1491	cappwd = cap_clone(origcappwd);
1492	CHECK(cappwd != NULL);
1493
1494	names[0] = "daemon";
1495	names[1] = "tty";
1496	uids[0] = 1;
1497	uids[1] = 4;
1498	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 2) == 0);
1499	uids[2] = 3;
1500	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == -1 &&
1501	    errno == ENOTCAPABLE);
1502	uids[0] = 3;
1503	CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 &&
1504	    errno == ENOTCAPABLE);
1505	uids[0] = 1;
1506
1507	CHECK(runtest_users(cappwd, names, uids, 2));
1508
1509	cap_close(cappwd);
1510}
1511
1512int
1513main(void)
1514{
1515	cap_channel_t *capcas, *cappwd;
1516
1517	printf("1..188\n");
1518	fflush(stdout);
1519
1520	capcas = cap_init();
1521	CHECKX(capcas != NULL);
1522
1523	cappwd = cap_service_open(capcas, "system.pwd");
1524	CHECKX(cappwd != NULL);
1525
1526	cap_close(capcas);
1527
1528	/* No limits. */
1529
1530	CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | GETPWNAM |
1531	    GETPWNAM_R | GETPWUID | GETPWUID_R));
1532
1533	test_cmds(cappwd);
1534
1535	test_fields(cappwd);
1536
1537	test_users(cappwd);
1538
1539	cap_close(cappwd);
1540
1541	exit(0);
1542}
1543