1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2013 The FreeBSD Foundation
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/capsicum.h>
32 #include <sys/nv.h>
33
34 #include <assert.h>
35 #include <err.h>
36 #include <errno.h>
37 #include <grp.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42
43 #include <libcasper.h>
44
45 #include <casper/cap_grp.h>
46
47 static int ntest = 1;
48
49 #define CHECK(expr) do { \
50 if ((expr)) \
51 printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \
52 else \
53 printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \
54 fflush(stdout); \
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 fflush(stdout); \
65 ntest++; \
66 } while (0)
67
68 #define GID_WHEEL 0
69 #define GID_OPERATOR 5
70
71 #define GETGRENT0 0x0001
72 #define GETGRENT1 0x0002
73 #define GETGRENT2 0x0004
74 #define GETGRENT (GETGRENT0 | GETGRENT1 | GETGRENT2)
75 #define GETGRENT_R0 0x0008
76 #define GETGRENT_R1 0x0010
77 #define GETGRENT_R2 0x0020
78 #define GETGRENT_R (GETGRENT_R0 | GETGRENT_R1 | GETGRENT_R2)
79 #define GETGRNAM 0x0040
80 #define GETGRNAM_R 0x0080
81 #define GETGRGID 0x0100
82 #define GETGRGID_R 0x0200
83 #define SETGRENT 0x0400
84
85 static bool
group_mem_compare(char ** mem0,char ** mem1)86 group_mem_compare(char **mem0, char **mem1)
87 {
88 int i0, i1;
89
90 if (mem0 == NULL && mem1 == NULL)
91 return (true);
92 if (mem0 == NULL || mem1 == NULL)
93 return (false);
94
95 for (i0 = 0; mem0[i0] != NULL; i0++) {
96 for (i1 = 0; mem1[i1] != NULL; i1++) {
97 if (strcmp(mem0[i0], mem1[i1]) == 0)
98 break;
99 }
100 if (mem1[i1] == NULL)
101 return (false);
102 }
103
104 return (true);
105 }
106
107 static bool
group_compare(const struct group * grp0,const struct group * grp1)108 group_compare(const struct group *grp0, const struct group *grp1)
109 {
110
111 if (grp0 == NULL && grp1 == NULL)
112 return (true);
113 if (grp0 == NULL || grp1 == NULL)
114 return (false);
115
116 if (strcmp(grp0->gr_name, grp1->gr_name) != 0)
117 return (false);
118
119 if (grp0->gr_passwd != NULL || grp1->gr_passwd != NULL) {
120 if (grp0->gr_passwd == NULL || grp1->gr_passwd == NULL)
121 return (false);
122 if (strcmp(grp0->gr_passwd, grp1->gr_passwd) != 0)
123 return (false);
124 }
125
126 if (grp0->gr_gid != grp1->gr_gid)
127 return (false);
128
129 if (!group_mem_compare(grp0->gr_mem, grp1->gr_mem))
130 return (false);
131
132 return (true);
133 }
134
135 static unsigned int
runtest_cmds(cap_channel_t * capgrp)136 runtest_cmds(cap_channel_t *capgrp)
137 {
138 char bufs[1024], bufc[1024];
139 unsigned int result;
140 struct group *grps, *grpc;
141 struct group sts, stc;
142
143 result = 0;
144
145 (void)setgrent();
146 if (cap_setgrent(capgrp) == 1)
147 result |= SETGRENT;
148
149 grps = getgrent();
150 grpc = cap_getgrent(capgrp);
151 if (group_compare(grps, grpc)) {
152 result |= GETGRENT0;
153 grps = getgrent();
154 grpc = cap_getgrent(capgrp);
155 if (group_compare(grps, grpc))
156 result |= GETGRENT1;
157 }
158
159 getgrent_r(&sts, bufs, sizeof(bufs), &grps);
160 cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc);
161 if (group_compare(grps, grpc)) {
162 result |= GETGRENT_R0;
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_R1;
167 }
168
169 (void)setgrent();
170 if (cap_setgrent(capgrp) == 1)
171 result |= SETGRENT;
172
173 getgrent_r(&sts, bufs, sizeof(bufs), &grps);
174 cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc);
175 if (group_compare(grps, grpc))
176 result |= GETGRENT_R2;
177
178 grps = getgrent();
179 grpc = cap_getgrent(capgrp);
180 if (group_compare(grps, grpc))
181 result |= GETGRENT2;
182
183 grps = getgrnam("wheel");
184 grpc = cap_getgrnam(capgrp, "wheel");
185 if (group_compare(grps, grpc)) {
186 grps = getgrnam("operator");
187 grpc = cap_getgrnam(capgrp, "operator");
188 if (group_compare(grps, grpc))
189 result |= GETGRNAM;
190 }
191
192 getgrnam_r("wheel", &sts, bufs, sizeof(bufs), &grps);
193 cap_getgrnam_r(capgrp, "wheel", &stc, bufc, sizeof(bufc), &grpc);
194 if (group_compare(grps, grpc)) {
195 getgrnam_r("operator", &sts, bufs, sizeof(bufs), &grps);
196 cap_getgrnam_r(capgrp, "operator", &stc, bufc, sizeof(bufc),
197 &grpc);
198 if (group_compare(grps, grpc))
199 result |= GETGRNAM_R;
200 }
201
202 grps = getgrgid(GID_WHEEL);
203 grpc = cap_getgrgid(capgrp, GID_WHEEL);
204 if (group_compare(grps, grpc)) {
205 grps = getgrgid(GID_OPERATOR);
206 grpc = cap_getgrgid(capgrp, GID_OPERATOR);
207 if (group_compare(grps, grpc))
208 result |= GETGRGID;
209 }
210
211 getgrgid_r(GID_WHEEL, &sts, bufs, sizeof(bufs), &grps);
212 cap_getgrgid_r(capgrp, GID_WHEEL, &stc, bufc, sizeof(bufc), &grpc);
213 if (group_compare(grps, grpc)) {
214 getgrgid_r(GID_OPERATOR, &sts, bufs, sizeof(bufs), &grps);
215 cap_getgrgid_r(capgrp, GID_OPERATOR, &stc, bufc, sizeof(bufc),
216 &grpc);
217 if (group_compare(grps, grpc))
218 result |= GETGRGID_R;
219 }
220
221 return (result);
222 }
223
224 static void
test_cmds(cap_channel_t * origcapgrp)225 test_cmds(cap_channel_t *origcapgrp)
226 {
227 cap_channel_t *capgrp;
228 const char *cmds[7], *fields[4], *names[5];
229 gid_t gids[5];
230
231 fields[0] = "gr_name";
232 fields[1] = "gr_passwd";
233 fields[2] = "gr_gid";
234 fields[3] = "gr_mem";
235
236 names[0] = "wheel";
237 names[1] = "daemon";
238 names[2] = "kmem";
239 names[3] = "sys";
240 names[4] = "operator";
241
242 gids[0] = 0;
243 gids[1] = 1;
244 gids[2] = 2;
245 gids[3] = 3;
246 gids[4] = 5;
247
248 /*
249 * Allow:
250 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
251 * getgrgid, getgrgid_r
252 * fields: gr_name, gr_passwd, gr_gid, gr_mem
253 * groups:
254 * names: wheel, daemon, kmem, sys, operator
255 * gids:
256 */
257 capgrp = cap_clone(origcapgrp);
258 CHECK(capgrp != NULL);
259
260 cmds[0] = "setgrent";
261 cmds[1] = "getgrent";
262 cmds[2] = "getgrent_r";
263 cmds[3] = "getgrnam";
264 cmds[4] = "getgrnam_r";
265 cmds[5] = "getgrgid";
266 cmds[6] = "getgrgid_r";
267 CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0);
268 CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
269 CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
270
271 CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
272 GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
273
274 cap_close(capgrp);
275
276 /*
277 * Allow:
278 * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r,
279 * getgrgid, getgrgid_r
280 * fields: gr_name, gr_passwd, gr_gid, gr_mem
281 * groups:
282 * names:
283 * gids: 0, 1, 2, 3, 5
284 */
285 capgrp = cap_clone(origcapgrp);
286 CHECK(capgrp != NULL);
287
288 cmds[0] = "setgrent";
289 cmds[1] = "getgrent";
290 cmds[2] = "getgrent_r";
291 cmds[3] = "getgrnam";
292 cmds[4] = "getgrnam_r";
293 cmds[5] = "getgrgid";
294 cmds[6] = "getgrgid_r";
295 CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0);
296 CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0);
297 CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0);
298
299 CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R |
300 GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
301
302 cap_close(capgrp);
303
304 /*
305 * Allow:
306 * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r,
307 * getgrgid, getgrgid_r
308 * fields: gr_name, gr_passwd, gr_gid, gr_mem
309 * groups:
310 * names: wheel, daemon, kmem, sys, operator
311 * gids:
312 * Disallow:
313 * cmds: setgrent
314 * fields:
315 * groups:
316 */
317 capgrp = cap_clone(origcapgrp);
318 CHECK(capgrp != NULL);
319
320 cap_setgrent(capgrp);
321
322 cmds[0] = "getgrent";
323 cmds[1] = "getgrent_r";
324 cmds[2] = "getgrnam";
325 cmds[3] = "getgrnam_r";
326 cmds[4] = "getgrgid";
327 cmds[5] = "getgrgid_r";
328 CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0);
329 cmds[0] = "setgrent";
330 cmds[1] = "getgrent";
331 cmds[2] = "getgrent_r";
332 cmds[3] = "getgrnam";
333 cmds[4] = "getgrnam_r";
334 cmds[5] = "getgrgid";
335 cmds[6] = "getgrgid_r";
336 CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE);
337 cmds[0] = "setgrent";
338 CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE);
339 CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0);
340
341 CHECK(runtest_cmds(capgrp) == (GETGRENT0 | GETGRENT1 | GETGRENT_R0 |
342 GETGRENT_R1 | GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R));
343
344 cap_close(capgrp);
345
346 /*
347 * Allow:
348 * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r,
349 * getgrgid, getgrgid_r
350 * fields: gr_name, gr_passwd, gr_gid, gr_mem
351 * groups:
352 * names:
353 * gids: 0, 1, 2, 3, 5
354 * Disallow:
355 * cmds: setgrent
356 * fields:
357 * groups:
358 */
359 capgrp = cap_clone(origcapgrp);
360 CHECK(capgrp != NULL);
361
362 cap_setgrent(capgrp);
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
group_fields(const struct group * grp)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
runtest_fields(cap_channel_t * capgrp,unsigned int expected)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
test_fields(cap_channel_t * origcapgrp)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
runtest_groups(cap_channel_t * capgrp,const char ** names,const gid_t * gids,size_t ngroups)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
test_groups(cap_channel_t * origcapgrp)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
main(void)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 }
1557