]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libcasper/services/cap_grp/tests/grp_test.c
Merge ACPICA 20170831.
[FreeBSD/FreeBSD.git] / lib / libcasper / services / cap_grp / tests / grp_test.c
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 }