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