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