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