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 <libcapsicum.h>
45 #include <libcapsicum_grp.h>
46 #include <libcapsicum_service.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
group_mem_compare(char ** mem0,char ** mem1)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
group_compare(const struct group * grp0,const struct group * grp1)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
runtest_cmds(cap_channel_t * capgrp)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
test_cmds(cap_channel_t * origcapgrp)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
group_fields(const struct group * grp)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
runtest_fields(cap_channel_t * capgrp,unsigned int expected)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
test_fields(cap_channel_t * origcapgrp)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
runtest_groups(cap_channel_t * capgrp,const char ** names,const gid_t * gids,size_t ngroups)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
test_groups(cap_channel_t * origcapgrp)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
main(void)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 }
1551