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