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: stable/11/lib/libcasper/services/cap_grp/tests/grp_test.c 322715 2017-08-20 06:07:40Z ngie $");
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
48static 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
86static bool
87group_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
108static bool
109group_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
136static unsigned int
137runtest_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
225static void
226test_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
877static unsigned int
878group_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
899static bool
900runtest_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
935static void
936test_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
1204static bool
1205runtest_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
1278static void
1279test_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
1523int
1524main(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