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