]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/regression/capsicum/libcasper/grp.c
Add simple support for CloudABI processes to kdump(1).
[FreeBSD/FreeBSD.git] / tools / regression / capsicum / libcasper / grp.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         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
84 static bool
85 group_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
106 static bool
107 group_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
134 static unsigned int
135 runtest_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
223 static void
224 test_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
875 static unsigned int
876 group_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
897 static bool
898 runtest_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
933 static void
934 test_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
1202 static bool
1203 runtest_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
1276 static void
1277 test_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
1521 int
1522 main(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 }