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