xref: /freebsd/lib/libcasper/services/cap_pwd/tests/pwd_test.c (revision dd41de95a84d979615a2ef11df6850622bf6184e)
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 
51 static 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 
88 static bool
89 passwd_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 
153 static unsigned int
154 runtest_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 
240 static void
241 test_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 
887 static unsigned int
888 passwd_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 
954 if (false && pwd->pw_fields != (int)result) {
955 printf("fields=0x%x != result=0x%x\n", (const unsigned int)pwd->pw_fields, result);
956 printf("           fields result\n");
957 printf("PW_NAME    %d      %d\n", (pwd->pw_fields & PW_NAME) != 0, (result & PW_NAME) != 0);
958 printf("PW_PASSWD  %d      %d\n", (pwd->pw_fields & PW_PASSWD) != 0, (result & PW_PASSWD) != 0);
959 printf("PW_UID     %d      %d\n", (pwd->pw_fields & PW_UID) != 0, (result & PW_UID) != 0);
960 printf("PW_GID     %d      %d\n", (pwd->pw_fields & PW_GID) != 0, (result & PW_GID) != 0);
961 printf("PW_CHANGE  %d      %d\n", (pwd->pw_fields & PW_CHANGE) != 0, (result & PW_CHANGE) != 0);
962 printf("PW_CLASS   %d      %d\n", (pwd->pw_fields & PW_CLASS) != 0, (result & PW_CLASS) != 0);
963 printf("PW_GECOS   %d      %d\n", (pwd->pw_fields & PW_GECOS) != 0, (result & PW_GECOS) != 0);
964 printf("PW_DIR     %d      %d\n", (pwd->pw_fields & PW_DIR) != 0, (result & PW_DIR) != 0);
965 printf("PW_SHELL   %d      %d\n", (pwd->pw_fields & PW_SHELL) != 0, (result & PW_SHELL) != 0);
966 printf("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 
973 static bool
974 runtest_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 
1010 static void
1011 test_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 
1191 static bool
1192 runtest_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 
1265 static void
1266 test_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 
1512 int
1513 main(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