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