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 <grp.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_grp.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	GID_WHEEL	0
73 #define	GID_OPERATOR	5
74 
75 #define	GETGRENT0	0x0001
76 #define	GETGRENT1	0x0002
77 #define	GETGRENT2	0x0004
78 #define	GETGRENT	(GETGRENT0 | GETGRENT1 | GETGRENT2)
79 #define	GETGRENT_R0	0x0008
80 #define	GETGRENT_R1	0x0010
81 #define	GETGRENT_R2	0x0020
82 #define	GETGRENT_R	(GETGRENT_R0 | GETGRENT_R1 | GETGRENT_R2)
83 #define	GETGRNAM	0x0040
84 #define	GETGRNAM_R	0x0080
85 #define	GETGRGID	0x0100
86 #define	GETGRGID_R	0x0200
87 #define	SETGRENT	0x0400
88 
89 static bool
90 group_mem_compare(char **mem0, char **mem1)
91 {
92 	int i0, i1;
93 
94 	if (mem0 == NULL && mem1 == NULL)
95 		return (true);
96 	if (mem0 == NULL || mem1 == NULL)
97 		return (false);
98 
99 	for (i0 = 0; mem0[i0] != NULL; i0++) {
100 		for (i1 = 0; mem1[i1] != NULL; i1++) {
101 			if (strcmp(mem0[i0], mem1[i1]) == 0)
102 				break;
103 		}
104 		if (mem1[i1] == NULL)
105 			return (false);
106 	}
107 
108 	return (true);
109 }
110 
111 static bool
112 group_compare(const struct group *grp0, const struct group *grp1)
113 {
114 
115 	if (grp0 == NULL && grp1 == NULL)
116 		return (true);
117 	if (grp0 == NULL || grp1 == NULL)
118 		return (false);
119 
120 	if (strcmp(grp0->gr_name, grp1->gr_name) != 0)
121 		return (false);
122 
123 	if (grp0->gr_passwd != NULL || grp1->gr_passwd != NULL) {
124 		if (grp0->gr_passwd == NULL || grp1->gr_passwd == NULL)
125 			return (false);
126 		if (strcmp(grp0->gr_passwd, grp1->gr_passwd) != 0)
127 			return (false);
128 	}
129 
130 	if (grp0->gr_gid != grp1->gr_gid)
131 		return (false);
132 
133 	if (!group_mem_compare(grp0->gr_mem, grp1->gr_mem))
134 		return (false);
135 
136 	return (true);
137 }
138 
139 static unsigned int
140 runtest_cmds(cap_channel_t *capgrp)
141 {
142 	char bufs[1024], bufc[1024];
143 	unsigned int result;
144 	struct group *grps, *grpc;
145 	struct group sts, stc;
146 
147 	result = 0;
148 
149 	(void)setgrent();
150 	if (cap_setgrent(capgrp) == 1)
151 		result |= SETGRENT;
152 
153 	grps = getgrent();
154 	grpc = cap_getgrent(capgrp);
155 	if (group_compare(grps, grpc)) {
156 		result |= GETGRENT0;
157 		grps = getgrent();
158 		grpc = cap_getgrent(capgrp);
159 		if (group_compare(grps, grpc))
160 			result |= GETGRENT1;
161 	}
162 
163 	getgrent_r(&sts, bufs, sizeof(bufs), &grps);
164 	cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc);
165 	if (group_compare(grps, grpc)) {
166 		result |= GETGRENT_R0;
167 		getgrent_r(&sts, bufs, sizeof(bufs), &grps);
168 		cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc);
169 		if (group_compare(grps, grpc))
170 			result |= GETGRENT_R1;
171 	}
172 
173 	(void)setgrent();
174 	if (cap_setgrent(capgrp) == 1)
175 		result |= SETGRENT;
176 
177 	getgrent_r(&sts, bufs, sizeof(bufs), &grps);
178 	cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc);
179 	if (group_compare(grps, grpc))
180 		result |= GETGRENT_R2;
181 
182 	grps = getgrent();
183 	grpc = cap_getgrent(capgrp);
184 	if (group_compare(grps, grpc))
185 		result |= GETGRENT2;
186 
187 	grps = getgrnam("wheel");
188 	grpc = cap_getgrnam(capgrp, "wheel");
189 	if (group_compare(grps, grpc)) {
190 		grps = getgrnam("operator");
191 		grpc = cap_getgrnam(capgrp, "operator");
192 		if (group_compare(grps, grpc))
193 			result |= GETGRNAM;
194 	}
195 
196 	getgrnam_r("wheel", &sts, bufs, sizeof(bufs), &grps);
197 	cap_getgrnam_r(capgrp, "wheel", &stc, bufc, sizeof(bufc), &grpc);
198 	if (group_compare(grps, grpc)) {
199 		getgrnam_r("operator", &sts, bufs, sizeof(bufs), &grps);
200 		cap_getgrnam_r(capgrp, "operator", &stc, bufc, sizeof(bufc),
201 		    &grpc);
202 		if (group_compare(grps, grpc))
203 			result |= GETGRNAM_R;
204 	}
205 
206 	grps = getgrgid(GID_WHEEL);
207 	grpc = cap_getgrgid(capgrp, GID_WHEEL);
208 	if (group_compare(grps, grpc)) {
209 		grps = getgrgid(GID_OPERATOR);
210 		grpc = cap_getgrgid(capgrp, GID_OPERATOR);
211 		if (group_compare(grps, grpc))
212 			result |= GETGRGID;
213 	}
214 
215 	getgrgid_r(GID_WHEEL, &sts, bufs, sizeof(bufs), &grps);
216 	cap_getgrgid_r(capgrp, GID_WHEEL, &stc, bufc, sizeof(bufc), &grpc);
217 	if (group_compare(grps, grpc)) {
218 		getgrgid_r(GID_OPERATOR, &sts, bufs, sizeof(bufs), &grps);
219 		cap_getgrgid_r(capgrp, GID_OPERATOR, &stc, bufc, sizeof(bufc),
220 		    &grpc);
221 		if (group_compare(grps, grpc))
222 			result |= GETGRGID_R;
223 	}
224 
225 	return (result);
226 }
227 
228 static void
229 test_cmds(cap_channel_t *origcapgrp)
230 {
231 	cap_channel_t *capgrp;
232 	const char *cmds[7], *fields[4], *names[5];
233 	gid_t gids[5];
234 
235 	fields[0] = "gr_name";
236 	fields[1] = "gr_passwd";
237 	fields[2] = "gr_gid";
238 	fields[3] = "gr_mem";
239 
240 	names[0] = "wheel";
241 	names[1] = "daemon";
242 	names[2] = "kmem";
243 	names[3] = "sys";
244 	names[4] = "operator";
245 
246 	gids[0] = 0;
247 	gids[1] = 1;
248 	gids[2] = 2;
249 	gids[3] = 3;
250 	gids[4] = 5;
251 
252 	/*
253 	 * Allow:
254 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
255 	 *       getgrgid, getgrgid_r
256 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
257 	 * groups:
258 	 *     names: wheel, daemon, kmem, sys, operator
259 	 *     gids:
260 	 */
261 	capgrp = cap_clone(origcapgrp);
262 	CHECK(capgrp != NULL);
263 
264 	cmds[0] = "setgrent";
265 	cmds[1] = "getgrent";
266 	cmds[2] = "getgrent_r";
267 	cmds[3] = "getgrnam";
268 	cmds[4] = "getgrnam_r";
269 	cmds[5] = "getgrgid";
270 	cmds[6] = "getgrgid_r";
271 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0);
272 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
273 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
274 
275 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
276 	    GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
277 
278 	cap_close(capgrp);
279 
280 	/*
281 	 * Allow:
282 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
283 	 *       getgrgid, getgrgid_r
284 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
285 	 * groups:
286 	 *     names:
287 	 *     gids: 0, 1, 2, 3, 5
288 	 */
289 	capgrp = cap_clone(origcapgrp);
290 	CHECK(capgrp != NULL);
291 
292 	cmds[0] = "setgrent";
293 	cmds[1] = "getgrent";
294 	cmds[2] = "getgrent_r";
295 	cmds[3] = "getgrnam";
296 	cmds[4] = "getgrnam_r";
297 	cmds[5] = "getgrgid";
298 	cmds[6] = "getgrgid_r";
299 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0);
300 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
301 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
302 
303 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
304 	    GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
305 
306 	cap_close(capgrp);
307 
308 	/*
309 	 * Allow:
310 	 * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r,
311 	 *       getgrgid, getgrgid_r
312 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
313 	 * groups:
314 	 *     names: wheel, daemon, kmem, sys, operator
315 	 *     gids:
316 	 * Disallow:
317 	 * cmds: setgrent
318 	 * fields:
319 	 * groups:
320 	 */
321 	capgrp = cap_clone(origcapgrp);
322 	CHECK(capgrp != NULL);
323 
324 	cmds[0] = "getgrent";
325 	cmds[1] = "getgrent_r";
326 	cmds[2] = "getgrnam";
327 	cmds[3] = "getgrnam_r";
328 	cmds[4] = "getgrgid";
329 	cmds[5] = "getgrgid_r";
330 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
331 	cmds[0] = "setgrent";
332 	cmds[1] = "getgrent";
333 	cmds[2] = "getgrent_r";
334 	cmds[3] = "getgrnam";
335 	cmds[4] = "getgrnam_r";
336 	cmds[5] = "getgrgid";
337 	cmds[6] = "getgrgid_r";
338 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
339 	cmds[0] = "setgrent";
340 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
341 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
342 
343 	CHECK(runtest_cmds(capgrp) == (GETGRENT0 | GETGRENT1 | GETGRENT_R0 |
344 	    GETGRENT_R1 | GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
345 
346 	cap_close(capgrp);
347 
348 	/*
349 	 * Allow:
350 	 * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r,
351 	 *       getgrgid, getgrgid_r
352 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
353 	 * groups:
354 	 *     names:
355 	 *     gids: 0, 1, 2, 3, 5
356 	 * Disallow:
357 	 * cmds: setgrent
358 	 * fields:
359 	 * groups:
360 	 */
361 	capgrp = cap_clone(origcapgrp);
362 	CHECK(capgrp != NULL);
363 
364 	cmds[0] = "getgrent";
365 	cmds[1] = "getgrent_r";
366 	cmds[2] = "getgrnam";
367 	cmds[3] = "getgrnam_r";
368 	cmds[4] = "getgrgid";
369 	cmds[5] = "getgrgid_r";
370 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
371 	cmds[0] = "setgrent";
372 	cmds[1] = "getgrent";
373 	cmds[2] = "getgrent_r";
374 	cmds[3] = "getgrnam";
375 	cmds[4] = "getgrnam_r";
376 	cmds[5] = "getgrgid";
377 	cmds[6] = "getgrgid_r";
378 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
379 	cmds[0] = "setgrent";
380 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
381 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
382 
383 	CHECK(runtest_cmds(capgrp) == (GETGRENT0 | GETGRENT1 | GETGRENT_R0 |
384 	    GETGRENT_R1 | GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
385 
386 	cap_close(capgrp);
387 
388 	/*
389 	 * Allow:
390 	 * cmds: setgrent, getgrent_r, getgrnam, getgrnam_r,
391 	 *       getgrgid, getgrgid_r
392 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
393 	 * groups:
394 	 *     names: wheel, daemon, kmem, sys, operator
395 	 *     gids:
396 	 * Disallow:
397 	 * cmds: getgrent
398 	 * fields:
399 	 * groups:
400 	 */
401 	capgrp = cap_clone(origcapgrp);
402 	CHECK(capgrp != NULL);
403 
404 	cmds[0] = "setgrent";
405 	cmds[1] = "getgrent_r";
406 	cmds[2] = "getgrnam";
407 	cmds[3] = "getgrnam_r";
408 	cmds[4] = "getgrgid";
409 	cmds[5] = "getgrgid_r";
410 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
411 	cmds[0] = "setgrent";
412 	cmds[1] = "getgrent";
413 	cmds[2] = "getgrent_r";
414 	cmds[3] = "getgrnam";
415 	cmds[4] = "getgrnam_r";
416 	cmds[5] = "getgrgid";
417 	cmds[6] = "getgrgid_r";
418 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
419 	cmds[0] = "getgrent";
420 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
421 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
422 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
423 
424 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT_R2 |
425 	    GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
426 
427 	cap_close(capgrp);
428 
429 	/*
430 	 * Allow:
431 	 * cmds: setgrent, getgrent_r, getgrnam, getgrnam_r,
432 	 *       getgrgid, getgrgid_r
433 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
434 	 * groups:
435 	 *     names:
436 	 *     gids: 0, 1, 2, 3, 5
437 	 * Disallow:
438 	 * cmds: getgrent
439 	 * fields:
440 	 * groups:
441 	 */
442 	capgrp = cap_clone(origcapgrp);
443 	CHECK(capgrp != NULL);
444 
445 	cmds[0] = "setgrent";
446 	cmds[1] = "getgrent_r";
447 	cmds[2] = "getgrnam";
448 	cmds[3] = "getgrnam_r";
449 	cmds[4] = "getgrgid";
450 	cmds[5] = "getgrgid_r";
451 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
452 	cmds[0] = "setgrent";
453 	cmds[1] = "getgrent";
454 	cmds[2] = "getgrent_r";
455 	cmds[3] = "getgrnam";
456 	cmds[4] = "getgrnam_r";
457 	cmds[5] = "getgrgid";
458 	cmds[6] = "getgrgid_r";
459 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
460 	cmds[0] = "getgrent";
461 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
462 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
463 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
464 
465 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT_R2 |
466 	    GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
467 
468 	cap_close(capgrp);
469 
470 	/*
471 	 * Allow:
472 	 * cmds: setgrent, getgrent, getgrnam, getgrnam_r,
473 	 *       getgrgid, getgrgid_r
474 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
475 	 * groups:
476 	 *     names: wheel, daemon, kmem, sys, operator
477 	 *     gids:
478 	 * Disallow:
479 	 * cmds: getgrent_r
480 	 * fields:
481 	 * groups:
482 	 */
483 	capgrp = cap_clone(origcapgrp);
484 	CHECK(capgrp != NULL);
485 
486 	cmds[0] = "setgrent";
487 	cmds[1] = "getgrent";
488 	cmds[2] = "getgrnam";
489 	cmds[3] = "getgrnam_r";
490 	cmds[4] = "getgrgid";
491 	cmds[5] = "getgrgid_r";
492 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
493 	cmds[0] = "setgrent";
494 	cmds[1] = "getgrent";
495 	cmds[2] = "getgrent_r";
496 	cmds[3] = "getgrnam";
497 	cmds[4] = "getgrnam_r";
498 	cmds[5] = "getgrgid";
499 	cmds[6] = "getgrgid_r";
500 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
501 	cmds[0] = "getgrent_r";
502 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
503 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
504 
505 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT0 | GETGRENT1 |
506 	    GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
507 
508 	cap_close(capgrp);
509 
510 	/*
511 	 * Allow:
512 	 * cmds: setgrent, getgrent, getgrnam, getgrnam_r,
513 	 *       getgrgid, getgrgid_r
514 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
515 	 * groups:
516 	 *     names:
517 	 *     gids: 0, 1, 2, 3, 5
518 	 * Disallow:
519 	 * cmds: getgrent_r
520 	 * fields:
521 	 * groups:
522 	 */
523 	capgrp = cap_clone(origcapgrp);
524 	CHECK(capgrp != NULL);
525 
526 	cmds[0] = "setgrent";
527 	cmds[1] = "getgrent";
528 	cmds[2] = "getgrnam";
529 	cmds[3] = "getgrnam_r";
530 	cmds[4] = "getgrgid";
531 	cmds[5] = "getgrgid_r";
532 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
533 	cmds[0] = "setgrent";
534 	cmds[1] = "getgrent";
535 	cmds[2] = "getgrent_r";
536 	cmds[3] = "getgrnam";
537 	cmds[4] = "getgrnam_r";
538 	cmds[5] = "getgrgid";
539 	cmds[6] = "getgrgid_r";
540 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
541 	cmds[0] = "getgrent_r";
542 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
543 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
544 
545 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT0 | GETGRENT1 |
546 	    GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
547 
548 	cap_close(capgrp);
549 
550 	/*
551 	 * Allow:
552 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam_r,
553 	 *       getgrgid, getgrgid_r
554 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
555 	 * groups:
556 	 *     names: wheel, daemon, kmem, sys, operator
557 	 *     gids:
558 	 * Disallow:
559 	 * cmds: getgrnam
560 	 * fields:
561 	 * groups:
562 	 */
563 	capgrp = cap_clone(origcapgrp);
564 	CHECK(capgrp != NULL);
565 
566 	cmds[0] = "setgrent";
567 	cmds[1] = "getgrent";
568 	cmds[2] = "getgrent_r";
569 	cmds[3] = "getgrnam_r";
570 	cmds[4] = "getgrgid";
571 	cmds[5] = "getgrgid_r";
572 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
573 	cmds[0] = "setgrent";
574 	cmds[1] = "getgrent";
575 	cmds[2] = "getgrent_r";
576 	cmds[3] = "getgrnam";
577 	cmds[4] = "getgrnam_r";
578 	cmds[5] = "getgrgid";
579 	cmds[6] = "getgrgid_r";
580 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
581 	cmds[0] = "getgrnam";
582 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
583 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
584 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
585 
586 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
587 	    GETGRNAM_R | GETGRGID | GETGRGID_R));
588 
589 	cap_close(capgrp);
590 
591 	/*
592 	 * Allow:
593 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam_r,
594 	 *       getgrgid, getgrgid_r
595 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
596 	 * groups:
597 	 *     names:
598 	 *     gids: 0, 1, 2, 3, 5
599 	 * Disallow:
600 	 * cmds: getgrnam
601 	 * fields:
602 	 * groups:
603 	 */
604 	capgrp = cap_clone(origcapgrp);
605 	CHECK(capgrp != NULL);
606 
607 	cmds[0] = "setgrent";
608 	cmds[1] = "getgrent";
609 	cmds[2] = "getgrent_r";
610 	cmds[3] = "getgrnam_r";
611 	cmds[4] = "getgrgid";
612 	cmds[5] = "getgrgid_r";
613 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
614 	cmds[0] = "setgrent";
615 	cmds[1] = "getgrent";
616 	cmds[2] = "getgrent_r";
617 	cmds[3] = "getgrnam";
618 	cmds[4] = "getgrnam_r";
619 	cmds[5] = "getgrgid";
620 	cmds[6] = "getgrgid_r";
621 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
622 	cmds[0] = "getgrnam";
623 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
624 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
625 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
626 
627 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
628 	    GETGRNAM_R | GETGRGID | GETGRGID_R));
629 
630 	cap_close(capgrp);
631 
632 	/*
633 	 * Allow:
634 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam,
635 	 *       getgrgid, getgrgid_r
636 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
637 	 * groups:
638 	 *     names: wheel, daemon, kmem, sys, operator
639 	 *     gids:
640 	 * Disallow:
641 	 * cmds: getgrnam_r
642 	 * fields:
643 	 * groups:
644 	 */
645 	capgrp = cap_clone(origcapgrp);
646 	CHECK(capgrp != NULL);
647 
648 	cmds[0] = "setgrent";
649 	cmds[1] = "getgrent";
650 	cmds[2] = "getgrent_r";
651 	cmds[3] = "getgrnam";
652 	cmds[4] = "getgrgid";
653 	cmds[5] = "getgrgid_r";
654 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
655 	cmds[0] = "setgrent";
656 	cmds[1] = "getgrent";
657 	cmds[2] = "getgrent_r";
658 	cmds[3] = "getgrnam";
659 	cmds[4] = "getgrnam_r";
660 	cmds[5] = "getgrgid";
661 	cmds[6] = "getgrgid_r";
662 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
663 	cmds[0] = "getgrnam_r";
664 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
665 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
666 
667 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
668 	    GETGRNAM | GETGRGID | GETGRGID_R));
669 
670 	cap_close(capgrp);
671 
672 	/*
673 	 * Allow:
674 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam,
675 	 *       getgrgid, getgrgid_r
676 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
677 	 * groups:
678 	 *     names:
679 	 *     gids: 0, 1, 2, 3, 5
680 	 * Disallow:
681 	 * cmds: getgrnam_r
682 	 * fields:
683 	 * groups:
684 	 */
685 	capgrp = cap_clone(origcapgrp);
686 	CHECK(capgrp != NULL);
687 
688 	cmds[0] = "setgrent";
689 	cmds[1] = "getgrent";
690 	cmds[2] = "getgrent_r";
691 	cmds[3] = "getgrnam";
692 	cmds[4] = "getgrgid";
693 	cmds[5] = "getgrgid_r";
694 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
695 	cmds[0] = "setgrent";
696 	cmds[1] = "getgrent";
697 	cmds[2] = "getgrent_r";
698 	cmds[3] = "getgrnam";
699 	cmds[4] = "getgrnam_r";
700 	cmds[5] = "getgrgid";
701 	cmds[6] = "getgrgid_r";
702 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
703 	cmds[0] = "getgrnam_r";
704 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
705 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
706 
707 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
708 	    GETGRNAM | GETGRGID | GETGRGID_R));
709 
710 	cap_close(capgrp);
711 
712 	/*
713 	 * Allow:
714 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
715 	 *       getgrgid_r
716 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
717 	 * groups:
718 	 *     names: wheel, daemon, kmem, sys, operator
719 	 *     gids:
720 	 * Disallow:
721 	 * cmds: getgrgid
722 	 * fields:
723 	 * groups:
724 	 */
725 	capgrp = cap_clone(origcapgrp);
726 	CHECK(capgrp != NULL);
727 
728 	cmds[0] = "setgrent";
729 	cmds[1] = "getgrent";
730 	cmds[2] = "getgrent_r";
731 	cmds[3] = "getgrnam";
732 	cmds[4] = "getgrnam_r";
733 	cmds[5] = "getgrgid_r";
734 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
735 	cmds[0] = "setgrent";
736 	cmds[1] = "getgrent";
737 	cmds[2] = "getgrent_r";
738 	cmds[3] = "getgrnam";
739 	cmds[4] = "getgrnam_r";
740 	cmds[5] = "getgrgid";
741 	cmds[6] = "getgrgid_r";
742 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
743 	cmds[0] = "getgrgid";
744 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
745 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
746 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
747 
748 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
749 	    GETGRNAM | GETGRNAM_R | GETGRGID_R));
750 
751 	cap_close(capgrp);
752 
753 	/*
754 	 * Allow:
755 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
756 	 *       getgrgid_r
757 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
758 	 * groups:
759 	 *     names:
760 	 *     gids: 0, 1, 2, 3, 5
761 	 * Disallow:
762 	 * cmds: getgrgid
763 	 * fields:
764 	 * groups:
765 	 */
766 	capgrp = cap_clone(origcapgrp);
767 	CHECK(capgrp != NULL);
768 
769 	cmds[0] = "setgrent";
770 	cmds[1] = "getgrent";
771 	cmds[2] = "getgrent_r";
772 	cmds[3] = "getgrnam";
773 	cmds[4] = "getgrnam_r";
774 	cmds[5] = "getgrgid_r";
775 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
776 	cmds[0] = "setgrent";
777 	cmds[1] = "getgrent";
778 	cmds[2] = "getgrent_r";
779 	cmds[3] = "getgrnam";
780 	cmds[4] = "getgrnam_r";
781 	cmds[5] = "getgrgid";
782 	cmds[6] = "getgrgid_r";
783 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
784 	cmds[0] = "getgrgid";
785 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
786 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
787 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
788 
789 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
790 	    GETGRNAM | GETGRNAM_R | GETGRGID_R));
791 
792 	cap_close(capgrp);
793 
794 	/*
795 	 * Allow:
796 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
797 	 *       getgrgid
798 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
799 	 * groups:
800 	 *     names: wheel, daemon, kmem, sys, operator
801 	 *     gids:
802 	 * Disallow:
803 	 * cmds: getgrgid_r
804 	 * fields:
805 	 * groups:
806 	 */
807 	capgrp = cap_clone(origcapgrp);
808 	CHECK(capgrp != NULL);
809 
810 	cmds[0] = "setgrent";
811 	cmds[1] = "getgrent";
812 	cmds[2] = "getgrent_r";
813 	cmds[3] = "getgrnam";
814 	cmds[4] = "getgrnam_r";
815 	cmds[5] = "getgrgid";
816 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
817 	cmds[0] = "setgrent";
818 	cmds[1] = "getgrent";
819 	cmds[2] = "getgrent_r";
820 	cmds[3] = "getgrnam";
821 	cmds[4] = "getgrnam_r";
822 	cmds[5] = "getgrgid";
823 	cmds[6] = "getgrgid_r";
824 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
825 	cmds[0] = "getgrgid_r";
826 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
827 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
828 
829 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
830 	    GETGRNAM | GETGRNAM_R | GETGRGID));
831 
832 	cap_close(capgrp);
833 
834 	/*
835 	 * Allow:
836 	 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
837 	 *       getgrgid
838 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
839 	 * groups:
840 	 *     names:
841 	 *     gids: 0, 1, 2, 3, 5
842 	 * Disallow:
843 	 * cmds: getgrgid_r
844 	 * fields:
845 	 * groups:
846 	 */
847 	capgrp = cap_clone(origcapgrp);
848 	CHECK(capgrp != NULL);
849 
850 	cmds[0] = "setgrent";
851 	cmds[1] = "getgrent";
852 	cmds[2] = "getgrent_r";
853 	cmds[3] = "getgrnam";
854 	cmds[4] = "getgrnam_r";
855 	cmds[5] = "getgrgid";
856 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
857 	cmds[0] = "setgrent";
858 	cmds[1] = "getgrent";
859 	cmds[2] = "getgrent_r";
860 	cmds[3] = "getgrnam";
861 	cmds[4] = "getgrnam_r";
862 	cmds[5] = "getgrgid";
863 	cmds[6] = "getgrgid_r";
864 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
865 	cmds[0] = "getgrgid_r";
866 	CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
867 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
868 
869 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
870 	    GETGRNAM | GETGRNAM_R | GETGRGID));
871 
872 	cap_close(capgrp);
873 }
874 
875 #define	GR_NAME		0x01
876 #define	GR_PASSWD	0x02
877 #define	GR_GID		0x04
878 #define	GR_MEM		0x08
879 
880 static unsigned int
881 group_fields(const struct group *grp)
882 {
883 	unsigned int result;
884 
885 	result = 0;
886 
887 	if (grp->gr_name != NULL && grp->gr_name[0] != '\0')
888 		result |= GR_NAME;
889 
890 	if (grp->gr_passwd != NULL && grp->gr_passwd[0] != '\0')
891 		result |= GR_PASSWD;
892 
893 	if (grp->gr_gid != (gid_t)-1)
894 		result |= GR_GID;
895 
896 	if (grp->gr_mem != NULL && grp->gr_mem[0] != NULL)
897 		result |= GR_MEM;
898 
899 	return (result);
900 }
901 
902 static bool
903 runtest_fields(cap_channel_t *capgrp, unsigned int expected)
904 {
905 	char buf[1024];
906 	struct group *grp;
907 	struct group st;
908 
909 	(void)cap_setgrent(capgrp);
910 	grp = cap_getgrent(capgrp);
911 	if (group_fields(grp) != expected)
912 		return (false);
913 
914 	(void)cap_setgrent(capgrp);
915 	cap_getgrent_r(capgrp, &st, buf, sizeof(buf), &grp);
916 	if (group_fields(grp) != expected)
917 		return (false);
918 
919 	grp = cap_getgrnam(capgrp, "wheel");
920 	if (group_fields(grp) != expected)
921 		return (false);
922 
923 	cap_getgrnam_r(capgrp, "wheel", &st, buf, sizeof(buf), &grp);
924 	if (group_fields(grp) != expected)
925 		return (false);
926 
927 	grp = cap_getgrgid(capgrp, GID_WHEEL);
928 	if (group_fields(grp) != expected)
929 		return (false);
930 
931 	cap_getgrgid_r(capgrp, GID_WHEEL, &st, buf, sizeof(buf), &grp);
932 	if (group_fields(grp) != expected)
933 		return (false);
934 
935 	return (true);
936 }
937 
938 static void
939 test_fields(cap_channel_t *origcapgrp)
940 {
941 	cap_channel_t *capgrp;
942 	const char *fields[4];
943 
944 	/* No limits. */
945 
946 	CHECK(runtest_fields(origcapgrp, GR_NAME | GR_PASSWD | GR_GID | GR_MEM));
947 
948 	/*
949 	 * Allow:
950 	 * fields: gr_name, gr_passwd, gr_gid, gr_mem
951 	 */
952 	capgrp = cap_clone(origcapgrp);
953 	CHECK(capgrp != NULL);
954 
955 	fields[0] = "gr_name";
956 	fields[1] = "gr_passwd";
957 	fields[2] = "gr_gid";
958 	fields[3] = "gr_mem";
959 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
960 
961 	CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_GID | GR_MEM));
962 
963 	cap_close(capgrp);
964 
965 	/*
966 	 * Allow:
967 	 * fields: gr_passwd, gr_gid, gr_mem
968 	 */
969 	capgrp = cap_clone(origcapgrp);
970 	CHECK(capgrp != NULL);
971 
972 	fields[0] = "gr_passwd";
973 	fields[1] = "gr_gid";
974 	fields[2] = "gr_mem";
975 	CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0);
976 	fields[0] = "gr_name";
977 	fields[1] = "gr_passwd";
978 	fields[2] = "gr_gid";
979 	fields[3] = "gr_mem";
980 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
981 	    errno == ENOTCAPABLE);
982 
983 	CHECK(runtest_fields(capgrp, GR_PASSWD | GR_GID | GR_MEM));
984 
985 	cap_close(capgrp);
986 
987 	/*
988 	 * Allow:
989 	 * fields: gr_name, gr_gid, gr_mem
990 	 */
991 	capgrp = cap_clone(origcapgrp);
992 	CHECK(capgrp != NULL);
993 
994 	fields[0] = "gr_name";
995 	fields[1] = "gr_gid";
996 	fields[2] = "gr_mem";
997 	CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0);
998 	fields[0] = "gr_name";
999 	fields[1] = "gr_passwd";
1000 	fields[2] = "gr_gid";
1001 	fields[3] = "gr_mem";
1002 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1003 	    errno == ENOTCAPABLE);
1004 	fields[0] = "gr_passwd";
1005 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1006 	    errno == ENOTCAPABLE);
1007 
1008 	CHECK(runtest_fields(capgrp, GR_NAME | GR_GID | GR_MEM));
1009 
1010 	cap_close(capgrp);
1011 
1012 	/*
1013 	 * Allow:
1014 	 * fields: gr_name, gr_passwd, gr_mem
1015 	 */
1016 	capgrp = cap_clone(origcapgrp);
1017 	CHECK(capgrp != NULL);
1018 
1019 	fields[0] = "gr_name";
1020 	fields[1] = "gr_passwd";
1021 	fields[2] = "gr_mem";
1022 	CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0);
1023 	fields[0] = "gr_name";
1024 	fields[1] = "gr_passwd";
1025 	fields[2] = "gr_gid";
1026 	fields[3] = "gr_mem";
1027 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1028 	    errno == ENOTCAPABLE);
1029 	fields[0] = "gr_gid";
1030 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1031 	    errno == ENOTCAPABLE);
1032 
1033 	CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_MEM));
1034 
1035 	cap_close(capgrp);
1036 
1037 	/*
1038 	 * Allow:
1039 	 * fields: gr_name, gr_passwd, gr_gid
1040 	 */
1041 	capgrp = cap_clone(origcapgrp);
1042 	CHECK(capgrp != NULL);
1043 
1044 	fields[0] = "gr_name";
1045 	fields[1] = "gr_passwd";
1046 	fields[2] = "gr_gid";
1047 	CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0);
1048 	fields[0] = "gr_name";
1049 	fields[1] = "gr_passwd";
1050 	fields[2] = "gr_gid";
1051 	fields[3] = "gr_mem";
1052 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1053 	    errno == ENOTCAPABLE);
1054 	fields[0] = "gr_mem";
1055 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1056 	    errno == ENOTCAPABLE);
1057 
1058 	CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_GID));
1059 
1060 	cap_close(capgrp);
1061 
1062 	/*
1063 	 * Allow:
1064 	 * fields: gr_name, gr_passwd
1065 	 */
1066 	capgrp = cap_clone(origcapgrp);
1067 	CHECK(capgrp != NULL);
1068 
1069 	fields[0] = "gr_name";
1070 	fields[1] = "gr_passwd";
1071 	CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0);
1072 	fields[0] = "gr_name";
1073 	fields[1] = "gr_passwd";
1074 	fields[2] = "gr_gid";
1075 	fields[3] = "gr_mem";
1076 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1077 	    errno == ENOTCAPABLE);
1078 	fields[0] = "gr_gid";
1079 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1080 	    errno == ENOTCAPABLE);
1081 
1082 	CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD));
1083 
1084 	cap_close(capgrp);
1085 
1086 	/*
1087 	 * Allow:
1088 	 * fields: gr_name, gr_gid
1089 	 */
1090 	capgrp = cap_clone(origcapgrp);
1091 	CHECK(capgrp != NULL);
1092 
1093 	fields[0] = "gr_name";
1094 	fields[1] = "gr_gid";
1095 	CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0);
1096 	fields[0] = "gr_name";
1097 	fields[1] = "gr_passwd";
1098 	fields[2] = "gr_gid";
1099 	fields[3] = "gr_mem";
1100 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1101 	    errno == ENOTCAPABLE);
1102 	fields[0] = "gr_mem";
1103 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1104 	    errno == ENOTCAPABLE);
1105 
1106 	CHECK(runtest_fields(capgrp, GR_NAME | GR_GID));
1107 
1108 	cap_close(capgrp);
1109 
1110 	/*
1111 	 * Allow:
1112 	 * fields: gr_name, gr_mem
1113 	 */
1114 	capgrp = cap_clone(origcapgrp);
1115 	CHECK(capgrp != NULL);
1116 
1117 	fields[0] = "gr_name";
1118 	fields[1] = "gr_mem";
1119 	CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0);
1120 	fields[0] = "gr_name";
1121 	fields[1] = "gr_passwd";
1122 	fields[2] = "gr_gid";
1123 	fields[3] = "gr_mem";
1124 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1125 	    errno == ENOTCAPABLE);
1126 	fields[0] = "gr_passwd";
1127 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1128 	    errno == ENOTCAPABLE);
1129 
1130 	CHECK(runtest_fields(capgrp, GR_NAME | GR_MEM));
1131 
1132 	cap_close(capgrp);
1133 
1134 	/*
1135 	 * Allow:
1136 	 * fields: gr_passwd, gr_gid
1137 	 */
1138 	capgrp = cap_clone(origcapgrp);
1139 	CHECK(capgrp != NULL);
1140 
1141 	fields[0] = "gr_passwd";
1142 	fields[1] = "gr_gid";
1143 	CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0);
1144 	fields[0] = "gr_name";
1145 	fields[1] = "gr_passwd";
1146 	fields[2] = "gr_gid";
1147 	fields[3] = "gr_mem";
1148 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1149 	    errno == ENOTCAPABLE);
1150 	fields[0] = "gr_mem";
1151 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1152 	    errno == ENOTCAPABLE);
1153 
1154 	CHECK(runtest_fields(capgrp, GR_PASSWD | GR_GID));
1155 
1156 	cap_close(capgrp);
1157 
1158 	/*
1159 	 * Allow:
1160 	 * fields: gr_passwd, gr_mem
1161 	 */
1162 	capgrp = cap_clone(origcapgrp);
1163 	CHECK(capgrp != NULL);
1164 
1165 	fields[0] = "gr_passwd";
1166 	fields[1] = "gr_mem";
1167 	CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0);
1168 	fields[0] = "gr_name";
1169 	fields[1] = "gr_passwd";
1170 	fields[2] = "gr_gid";
1171 	fields[3] = "gr_mem";
1172 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1173 	    errno == ENOTCAPABLE);
1174 	fields[0] = "gr_gid";
1175 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1176 	    errno == ENOTCAPABLE);
1177 
1178 	CHECK(runtest_fields(capgrp, GR_PASSWD | GR_MEM));
1179 
1180 	cap_close(capgrp);
1181 
1182 	/*
1183 	 * Allow:
1184 	 * fields: gr_gid, gr_mem
1185 	 */
1186 	capgrp = cap_clone(origcapgrp);
1187 	CHECK(capgrp != NULL);
1188 
1189 	fields[0] = "gr_gid";
1190 	fields[1] = "gr_mem";
1191 	CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0);
1192 	fields[0] = "gr_name";
1193 	fields[1] = "gr_passwd";
1194 	fields[2] = "gr_gid";
1195 	fields[3] = "gr_mem";
1196 	CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 &&
1197 	    errno == ENOTCAPABLE);
1198 	fields[0] = "gr_passwd";
1199 	CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 &&
1200 	    errno == ENOTCAPABLE);
1201 
1202 	CHECK(runtest_fields(capgrp, GR_GID | GR_MEM));
1203 
1204 	cap_close(capgrp);
1205 }
1206 
1207 static bool
1208 runtest_groups(cap_channel_t *capgrp, const char **names, const gid_t *gids,
1209     size_t ngroups)
1210 {
1211 	char buf[1024];
1212 	struct group *grp;
1213 	struct group st;
1214 	unsigned int i, got;
1215 
1216 	(void)cap_setgrent(capgrp);
1217 	got = 0;
1218 	for (;;) {
1219 		grp = cap_getgrent(capgrp);
1220 		if (grp == NULL)
1221 			break;
1222 		got++;
1223 		for (i = 0; i < ngroups; i++) {
1224 			if (strcmp(names[i], grp->gr_name) == 0 &&
1225 			    gids[i] == grp->gr_gid) {
1226 				break;
1227 			}
1228 		}
1229 		if (i == ngroups)
1230 			return (false);
1231 	}
1232 	if (got != ngroups)
1233 		return (false);
1234 
1235 	(void)cap_setgrent(capgrp);
1236 	got = 0;
1237 	for (;;) {
1238 		cap_getgrent_r(capgrp, &st, buf, sizeof(buf), &grp);
1239 		if (grp == NULL)
1240 			break;
1241 		got++;
1242 		for (i = 0; i < ngroups; i++) {
1243 			if (strcmp(names[i], grp->gr_name) == 0 &&
1244 			    gids[i] == grp->gr_gid) {
1245 				break;
1246 			}
1247 		}
1248 		if (i == ngroups)
1249 			return (false);
1250 	}
1251 	if (got != ngroups)
1252 		return (false);
1253 
1254 	for (i = 0; i < ngroups; i++) {
1255 		grp = cap_getgrnam(capgrp, names[i]);
1256 		if (grp == NULL)
1257 			return (false);
1258 	}
1259 
1260 	for (i = 0; i < ngroups; i++) {
1261 		cap_getgrnam_r(capgrp, names[i], &st, buf, sizeof(buf), &grp);
1262 		if (grp == NULL)
1263 			return (false);
1264 	}
1265 
1266 	for (i = 0; i < ngroups; i++) {
1267 		grp = cap_getgrgid(capgrp, gids[i]);
1268 		if (grp == NULL)
1269 			return (false);
1270 	}
1271 
1272 	for (i = 0; i < ngroups; i++) {
1273 		cap_getgrgid_r(capgrp, gids[i], &st, buf, sizeof(buf), &grp);
1274 		if (grp == NULL)
1275 			return (false);
1276 	}
1277 
1278 	return (true);
1279 }
1280 
1281 static void
1282 test_groups(cap_channel_t *origcapgrp)
1283 {
1284 	cap_channel_t *capgrp;
1285 	const char *names[5];
1286 	gid_t gids[5];
1287 
1288 	/*
1289 	 * Allow:
1290 	 * groups:
1291 	 *     names: wheel, daemon, kmem, sys, tty
1292 	 *     gids:
1293 	 */
1294 	capgrp = cap_clone(origcapgrp);
1295 	CHECK(capgrp != NULL);
1296 
1297 	names[0] = "wheel";
1298 	names[1] = "daemon";
1299 	names[2] = "kmem";
1300 	names[3] = "sys";
1301 	names[4] = "tty";
1302 	CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
1303 	gids[0] = 0;
1304 	gids[1] = 1;
1305 	gids[2] = 2;
1306 	gids[3] = 3;
1307 	gids[4] = 4;
1308 
1309 	CHECK(runtest_groups(capgrp, names, gids, 5));
1310 
1311 	cap_close(capgrp);
1312 
1313 	/*
1314 	 * Allow:
1315 	 * groups:
1316 	 *     names: kmem, sys, tty
1317 	 *     gids:
1318 	 */
1319 	capgrp = cap_clone(origcapgrp);
1320 	CHECK(capgrp != NULL);
1321 
1322 	names[0] = "kmem";
1323 	names[1] = "sys";
1324 	names[2] = "tty";
1325 	CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == 0);
1326 	names[3] = "daemon";
1327 	CHECK(cap_grp_limit_groups(capgrp, names, 4, NULL, 0) == -1 &&
1328 	    errno == ENOTCAPABLE);
1329 	names[0] = "daemon";
1330 	CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 &&
1331 	    errno == ENOTCAPABLE);
1332 	names[0] = "kmem";
1333 	gids[0] = 2;
1334 	gids[1] = 3;
1335 	gids[2] = 4;
1336 
1337 	CHECK(runtest_groups(capgrp, names, gids, 3));
1338 
1339 	cap_close(capgrp);
1340 
1341 	/*
1342 	 * Allow:
1343 	 * groups:
1344 	 *     names: wheel, kmem, tty
1345 	 *     gids:
1346 	 */
1347 	capgrp = cap_clone(origcapgrp);
1348 	CHECK(capgrp != NULL);
1349 
1350 	names[0] = "wheel";
1351 	names[1] = "kmem";
1352 	names[2] = "tty";
1353 	CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == 0);
1354 	names[3] = "daemon";
1355 	CHECK(cap_grp_limit_groups(capgrp, names, 4, NULL, 0) == -1 &&
1356 	    errno == ENOTCAPABLE);
1357 	names[0] = "daemon";
1358 	CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 &&
1359 	    errno == ENOTCAPABLE);
1360 	names[0] = "wheel";
1361 	gids[0] = 0;
1362 	gids[1] = 2;
1363 	gids[2] = 4;
1364 
1365 	CHECK(runtest_groups(capgrp, names, gids, 3));
1366 
1367 	cap_close(capgrp);
1368 
1369 	/*
1370 	 * Allow:
1371 	 * groups:
1372 	 *     names:
1373 	 *     gids: 2, 3, 4
1374 	 */
1375 	capgrp = cap_clone(origcapgrp);
1376 	CHECK(capgrp != NULL);
1377 
1378 	names[0] = "kmem";
1379 	names[1] = "sys";
1380 	names[2] = "tty";
1381 	gids[0] = 2;
1382 	gids[1] = 3;
1383 	gids[2] = 4;
1384 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == 0);
1385 	gids[3] = 0;
1386 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 4) == -1 &&
1387 	    errno == ENOTCAPABLE);
1388 	gids[0] = 0;
1389 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 &&
1390 	    errno == ENOTCAPABLE);
1391 	gids[0] = 2;
1392 
1393 	CHECK(runtest_groups(capgrp, names, gids, 3));
1394 
1395 	cap_close(capgrp);
1396 
1397 	/*
1398 	 * Allow:
1399 	 * groups:
1400 	 *     names:
1401 	 *     gids: 0, 2, 4
1402 	 */
1403 	capgrp = cap_clone(origcapgrp);
1404 	CHECK(capgrp != NULL);
1405 
1406 	names[0] = "wheel";
1407 	names[1] = "kmem";
1408 	names[2] = "tty";
1409 	gids[0] = 0;
1410 	gids[1] = 2;
1411 	gids[2] = 4;
1412 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == 0);
1413 	gids[3] = 1;
1414 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 4) == -1 &&
1415 	    errno == ENOTCAPABLE);
1416 	gids[0] = 1;
1417 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 &&
1418 	    errno == ENOTCAPABLE);
1419 	gids[0] = 0;
1420 
1421 	CHECK(runtest_groups(capgrp, names, gids, 3));
1422 
1423 	cap_close(capgrp);
1424 
1425 	/*
1426 	 * Allow:
1427 	 * groups:
1428 	 *     names: kmem
1429 	 *     gids:
1430 	 */
1431 	capgrp = cap_clone(origcapgrp);
1432 	CHECK(capgrp != NULL);
1433 
1434 	names[0] = "kmem";
1435 	CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == 0);
1436 	names[1] = "daemon";
1437 	CHECK(cap_grp_limit_groups(capgrp, names, 2, NULL, 0) == -1 &&
1438 	    errno == ENOTCAPABLE);
1439 	names[0] = "daemon";
1440 	CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 &&
1441 	    errno == ENOTCAPABLE);
1442 	names[0] = "kmem";
1443 	gids[0] = 2;
1444 
1445 	CHECK(runtest_groups(capgrp, names, gids, 1));
1446 
1447 	cap_close(capgrp);
1448 
1449 	/*
1450 	 * Allow:
1451 	 * groups:
1452 	 *     names: wheel, tty
1453 	 *     gids:
1454 	 */
1455 	capgrp = cap_clone(origcapgrp);
1456 	CHECK(capgrp != NULL);
1457 
1458 	names[0] = "wheel";
1459 	names[1] = "tty";
1460 	CHECK(cap_grp_limit_groups(capgrp, names, 2, NULL, 0) == 0);
1461 	names[2] = "daemon";
1462 	CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == -1 &&
1463 	    errno == ENOTCAPABLE);
1464 	names[0] = "daemon";
1465 	CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 &&
1466 	    errno == ENOTCAPABLE);
1467 	names[0] = "wheel";
1468 	gids[0] = 0;
1469 	gids[1] = 4;
1470 
1471 	CHECK(runtest_groups(capgrp, names, gids, 2));
1472 
1473 	cap_close(capgrp);
1474 
1475 	/*
1476 	 * Allow:
1477 	 * groups:
1478 	 *     names:
1479 	 *     gids: 2
1480 	 */
1481 	capgrp = cap_clone(origcapgrp);
1482 	CHECK(capgrp != NULL);
1483 
1484 	names[0] = "kmem";
1485 	gids[0] = 2;
1486 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == 0);
1487 	gids[1] = 1;
1488 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 2) == -1 &&
1489 	    errno == ENOTCAPABLE);
1490 	gids[0] = 1;
1491 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 &&
1492 	    errno == ENOTCAPABLE);
1493 	gids[0] = 2;
1494 
1495 	CHECK(runtest_groups(capgrp, names, gids, 1));
1496 
1497 	cap_close(capgrp);
1498 
1499 	/*
1500 	 * Allow:
1501 	 * groups:
1502 	 *     names:
1503 	 *     gids: 0, 4
1504 	 */
1505 	capgrp = cap_clone(origcapgrp);
1506 	CHECK(capgrp != NULL);
1507 
1508 	names[0] = "wheel";
1509 	names[1] = "tty";
1510 	gids[0] = 0;
1511 	gids[1] = 4;
1512 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 2) == 0);
1513 	gids[2] = 1;
1514 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == -1 &&
1515 	    errno == ENOTCAPABLE);
1516 	gids[0] = 1;
1517 	CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 &&
1518 	    errno == ENOTCAPABLE);
1519 	gids[0] = 0;
1520 
1521 	CHECK(runtest_groups(capgrp, names, gids, 2));
1522 
1523 	cap_close(capgrp);
1524 }
1525 
1526 int
1527 main(void)
1528 {
1529 	cap_channel_t *capcas, *capgrp;
1530 
1531 	printf("1..199\n");
1532 	fflush(stdout);
1533 
1534 	capcas = cap_init();
1535 	CHECKX(capcas != NULL);
1536 
1537 	capgrp = cap_service_open(capcas, "system.grp");
1538 	CHECKX(capgrp != NULL);
1539 
1540 	cap_close(capcas);
1541 
1542 	/* No limits. */
1543 
1544 	CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
1545 	    GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
1546 
1547 	test_cmds(capgrp);
1548 
1549 	test_fields(capgrp);
1550 
1551 	test_groups(capgrp);
1552 
1553 	cap_close(capgrp);
1554 
1555 	exit(0);
1556 }
1557