2 * Copyright (c) 2002-2005 Networks Associates Technology, Inc.
5 * This software was developed for the FreeBSD Project by Network Associates
6 * Laboratories, the Security Research Division of Network Associates, Inc.
7 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
8 * DARPA CHATS research program.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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
33 #include <sys/param.h>
34 #include <sys/errno.h>
36 #include <sys/sysctl.h>
37 #include <sys/ucred.h>
38 #include <sys/mount.h>
40 #include <security/mac_bsdextended/mac_bsdextended.h>
51 * Text format for rules: rules contain subject and object elements, mode.
52 * The total form is "subject [s_element] object [o_element] mode [mode]".
53 * At least * one of a uid or gid entry must be present; both may also be
57 #define MIB "security.mac.bsdextended"
60 bsde_rule_to_string(struct mac_bsdextended_rule
*rule
, char *buf
, size_t buflen
)
64 struct statfs
*mntbuf
;
65 char *cur
, type
[sizeof(rule
->mbr_object
.mbo_type
) * CHAR_BIT
+ 1];
67 int anymode
, unknownmode
, truncated
, numfs
, i
, notdone
;
73 len
= snprintf(cur
, left
, "subject ");
74 if (len
< 0 || len
> left
)
78 if (rule
->mbr_subject
.mbs_flags
) {
79 if (rule
->mbr_subject
.mbs_neg
== MBS_ALL_FLAGS
) {
80 len
= snprintf(cur
, left
, "not ");
81 if (len
< 0 || len
> left
)
90 if (!notdone
&& (rule
->mbr_subject
.mbs_neg
& MBO_UID_DEFINED
)) {
91 len
= snprintf(cur
, left
, "! ");
92 if (len
< 0 || len
> left
)
97 if (rule
->mbr_subject
.mbs_flags
& MBO_UID_DEFINED
) {
98 pwd
= getpwuid(rule
->mbr_subject
.mbs_uid_min
);
100 len
= snprintf(cur
, left
, "uid %s",
102 if (len
< 0 || len
> left
)
107 len
= snprintf(cur
, left
, "uid %u",
108 rule
->mbr_subject
.mbs_uid_min
);
109 if (len
< 0 || len
> left
)
114 if (rule
->mbr_subject
.mbs_uid_min
!=
115 rule
->mbr_subject
.mbs_uid_max
) {
116 pwd
= getpwuid(rule
->mbr_subject
.mbs_uid_max
);
118 len
= snprintf(cur
, left
, ":%s ",
120 if (len
< 0 || len
> left
)
125 len
= snprintf(cur
, left
, ":%u ",
126 rule
->mbr_subject
.mbs_uid_max
);
127 if (len
< 0 || len
> left
)
133 len
= snprintf(cur
, left
, " ");
134 if (len
< 0 || len
> left
)
140 if (!notdone
&& (rule
->mbr_subject
.mbs_neg
& MBO_GID_DEFINED
)) {
141 len
= snprintf(cur
, left
, "! ");
142 if (len
< 0 || len
> left
)
147 if (rule
->mbr_subject
.mbs_flags
& MBO_GID_DEFINED
) {
148 grp
= getgrgid(rule
->mbr_subject
.mbs_gid_min
);
150 len
= snprintf(cur
, left
, "gid %s",
152 if (len
< 0 || len
> left
)
157 len
= snprintf(cur
, left
, "gid %u",
158 rule
->mbr_subject
.mbs_gid_min
);
159 if (len
< 0 || len
> left
)
164 if (rule
->mbr_subject
.mbs_gid_min
!=
165 rule
->mbr_subject
.mbs_gid_max
) {
166 grp
= getgrgid(rule
->mbr_subject
.mbs_gid_max
);
168 len
= snprintf(cur
, left
, ":%s ",
170 if (len
< 0 || len
> left
)
175 len
= snprintf(cur
, left
, ":%u ",
176 rule
->mbr_subject
.mbs_gid_max
);
177 if (len
< 0 || len
> left
)
183 len
= snprintf(cur
, left
, " ");
184 if (len
< 0 || len
> left
)
190 if (!notdone
&& (rule
->mbr_subject
.mbs_neg
& MBS_PRISON_DEFINED
)) {
191 len
= snprintf(cur
, left
, "! ");
192 if (len
< 0 || len
> left
)
197 if (rule
->mbr_subject
.mbs_flags
& MBS_PRISON_DEFINED
) {
198 len
= snprintf(cur
, left
, "jailid %d ",
199 rule
->mbr_subject
.mbs_prison
);
200 if (len
< 0 || len
> left
)
207 len
= snprintf(cur
, left
, "object ");
208 if (len
< 0 || len
> left
)
212 if (rule
->mbr_object
.mbo_flags
) {
213 if (rule
->mbr_object
.mbo_neg
== MBO_ALL_FLAGS
) {
214 len
= snprintf(cur
, left
, "not ");
215 if (len
< 0 || len
> left
)
224 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_UID_DEFINED
)) {
225 len
= snprintf(cur
, left
, "! ");
226 if (len
< 0 || len
> left
)
231 if (rule
->mbr_object
.mbo_flags
& MBO_UID_DEFINED
) {
232 pwd
= getpwuid(rule
->mbr_object
.mbo_uid_min
);
234 len
= snprintf(cur
, left
, "uid %s",
236 if (len
< 0 || len
> left
)
241 len
= snprintf(cur
, left
, "uid %u",
242 rule
->mbr_object
.mbo_uid_min
);
243 if (len
< 0 || len
> left
)
248 if (rule
->mbr_object
.mbo_uid_min
!=
249 rule
->mbr_object
.mbo_uid_max
) {
250 pwd
= getpwuid(rule
->mbr_object
.mbo_uid_max
);
252 len
= snprintf(cur
, left
, ":%s ",
254 if (len
< 0 || len
> left
)
259 len
= snprintf(cur
, left
, ":%u ",
260 rule
->mbr_object
.mbo_uid_max
);
261 if (len
< 0 || len
> left
)
267 len
= snprintf(cur
, left
, " ");
268 if (len
< 0 || len
> left
)
274 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_GID_DEFINED
)) {
275 len
= snprintf(cur
, left
, "! ");
276 if (len
< 0 || len
> left
)
281 if (rule
->mbr_object
.mbo_flags
& MBO_GID_DEFINED
) {
282 grp
= getgrgid(rule
->mbr_object
.mbo_gid_min
);
284 len
= snprintf(cur
, left
, "gid %s",
286 if (len
< 0 || len
> left
)
291 len
= snprintf(cur
, left
, "gid %u",
292 rule
->mbr_object
.mbo_gid_min
);
293 if (len
< 0 || len
> left
)
298 if (rule
->mbr_object
.mbo_gid_min
!=
299 rule
->mbr_object
.mbo_gid_max
) {
300 grp
= getgrgid(rule
->mbr_object
.mbo_gid_max
);
302 len
= snprintf(cur
, left
, ":%s ",
304 if (len
< 0 || len
> left
)
309 len
= snprintf(cur
, left
, ":%u ",
310 rule
->mbr_object
.mbo_gid_max
);
311 if (len
< 0 || len
> left
)
317 len
= snprintf(cur
, left
, " ");
318 if (len
< 0 || len
> left
)
324 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_FSID_DEFINED
)) {
325 len
= snprintf(cur
, left
, "! ");
326 if (len
< 0 || len
> left
)
331 if (rule
->mbr_object
.mbo_flags
& MBO_FSID_DEFINED
) {
332 numfs
= getmntinfo(&mntbuf
, MNT_NOWAIT
);
333 for (i
= 0; i
< numfs
; i
++)
334 if (memcmp(&(rule
->mbr_object
.mbo_fsid
),
336 sizeof(mntbuf
[i
].f_fsid
)) == 0)
338 len
= snprintf(cur
, left
, "filesys %s ",
339 i
== numfs
? "???" : mntbuf
[i
].f_mntonname
);
340 if (len
< 0 || len
> left
)
345 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_SUID
)) {
346 len
= snprintf(cur
, left
, "! ");
347 if (len
< 0 || len
> left
)
352 if (rule
->mbr_object
.mbo_flags
& MBO_SUID
) {
353 len
= snprintf(cur
, left
, "suid ");
354 if (len
< 0 || len
> left
)
359 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_SGID
)) {
360 len
= snprintf(cur
, left
, "! ");
361 if (len
< 0 || len
> left
)
366 if (rule
->mbr_object
.mbo_flags
& MBO_SGID
) {
367 len
= snprintf(cur
, left
, "sgid ");
368 if (len
< 0 || len
> left
)
373 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_UID_SUBJECT
)) {
374 len
= snprintf(cur
, left
, "! ");
375 if (len
< 0 || len
> left
)
380 if (rule
->mbr_object
.mbo_flags
& MBO_UID_SUBJECT
) {
381 len
= snprintf(cur
, left
, "uid_of_subject ");
382 if (len
< 0 || len
> left
)
387 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_GID_SUBJECT
)) {
388 len
= snprintf(cur
, left
, "! ");
389 if (len
< 0 || len
> left
)
394 if (rule
->mbr_object
.mbo_flags
& MBO_GID_SUBJECT
) {
395 len
= snprintf(cur
, left
, "gid_of_subject ");
396 if (len
< 0 || len
> left
)
401 if (!notdone
&& (rule
->mbr_object
.mbo_neg
& MBO_TYPE_DEFINED
)) {
402 len
= snprintf(cur
, left
, "! ");
403 if (len
< 0 || len
> left
)
408 if (rule
->mbr_object
.mbo_flags
& MBO_TYPE_DEFINED
) {
410 if (rule
->mbr_object
.mbo_type
& MBO_TYPE_REG
)
412 if (rule
->mbr_object
.mbo_type
& MBO_TYPE_DIR
)
414 if (rule
->mbr_object
.mbo_type
& MBO_TYPE_BLK
)
416 if (rule
->mbr_object
.mbo_type
& MBO_TYPE_CHR
)
418 if (rule
->mbr_object
.mbo_type
& MBO_TYPE_LNK
)
420 if (rule
->mbr_object
.mbo_type
& MBO_TYPE_SOCK
)
422 if (rule
->mbr_object
.mbo_type
& MBO_TYPE_FIFO
)
424 if (rule
->mbr_object
.mbo_type
== MBO_ALL_TYPE
) {
429 len
= snprintf(cur
, left
, "type %s ", type
);
430 if (len
< 0 || len
> left
)
437 len
= snprintf(cur
, left
, "mode ");
438 if (len
< 0 || len
> left
)
443 anymode
= (rule
->mbr_mode
& MBI_ALLPERM
);
444 unknownmode
= (rule
->mbr_mode
& ~MBI_ALLPERM
);
446 if (rule
->mbr_mode
& MBI_ADMIN
) {
447 len
= snprintf(cur
, left
, "a");
448 if (len
< 0 || len
> left
)
454 if (rule
->mbr_mode
& MBI_READ
) {
455 len
= snprintf(cur
, left
, "r");
456 if (len
< 0 || len
> left
)
462 if (rule
->mbr_mode
& MBI_STAT
) {
463 len
= snprintf(cur
, left
, "s");
464 if (len
< 0 || len
> left
)
470 if (rule
->mbr_mode
& MBI_WRITE
) {
471 len
= snprintf(cur
, left
, "w");
472 if (len
< 0 || len
> left
)
478 if (rule
->mbr_mode
& MBI_EXEC
) {
479 len
= snprintf(cur
, left
, "x");
480 if (len
< 0 || len
> left
)
487 len
= snprintf(cur
, left
, "n");
488 if (len
< 0 || len
> left
)
495 len
= snprintf(cur
, left
, "?");
496 if (len
< 0 || len
> left
)
510 bsde_parse_uidrange(char *spec
, uid_t
*min
, uid_t
*max
,
511 size_t buflen
, char *errstr
){
514 char *spec1
, *spec2
, *endp
;
519 spec1
= strsep(&spec2
, ":");
521 pwd
= getpwnam(spec1
);
525 value
= strtoul(spec1
, &endp
, 10);
527 len
= snprintf(errstr
, buflen
,
528 "invalid uid: '%s'", spec1
);
539 pwd
= getpwnam(spec2
);
543 value
= strtoul(spec2
, &endp
, 10);
545 len
= snprintf(errstr
, buflen
,
546 "invalid uid: '%s'", spec2
);
559 bsde_parse_gidrange(char *spec
, gid_t
*min
, gid_t
*max
,
560 size_t buflen
, char *errstr
){
563 char *spec1
, *spec2
, *endp
;
568 spec1
= strsep(&spec2
, ":");
570 grp
= getgrnam(spec1
);
574 value
= strtoul(spec1
, &endp
, 10);
576 len
= snprintf(errstr
, buflen
,
577 "invalid gid: '%s'", spec1
);
588 grp
= getgrnam(spec2
);
592 value
= strtoul(spec2
, &endp
, 10);
594 len
= snprintf(errstr
, buflen
,
595 "invalid gid: '%s'", spec2
);
608 bsde_parse_subject(int argc
, char *argv
[],
609 struct mac_bsdextended_subject
*subject
, size_t buflen
, char *errstr
)
612 int current
, neg
, nextnot
;
614 uid_t uid_min
, uid_max
;
615 gid_t gid_min
, gid_max
;
625 if (strcmp("not", argv
[current
]) == 0) {
631 while (current
< argc
) {
632 if (strcmp(argv
[current
], "uid") == 0) {
633 if (current
+ 2 > argc
) {
634 len
= snprintf(errstr
, buflen
, "uid short");
637 if (flags
& MBS_UID_DEFINED
) {
638 len
= snprintf(errstr
, buflen
, "one uid only");
641 if (bsde_parse_uidrange(argv
[current
+1],
642 &uid_min
, &uid_max
, buflen
, errstr
) < 0)
644 flags
|= MBS_UID_DEFINED
;
646 neg
^= MBS_UID_DEFINED
;
650 } else if (strcmp(argv
[current
], "gid") == 0) {
651 if (current
+ 2 > argc
) {
652 len
= snprintf(errstr
, buflen
, "gid short");
655 if (flags
& MBS_GID_DEFINED
) {
656 len
= snprintf(errstr
, buflen
, "one gid only");
659 if (bsde_parse_gidrange(argv
[current
+1],
660 &gid_min
, &gid_max
, buflen
, errstr
) < 0)
662 flags
|= MBS_GID_DEFINED
;
664 neg
^= MBS_GID_DEFINED
;
668 } else if (strcmp(argv
[current
], "jailid") == 0) {
669 if (current
+ 2 > argc
) {
670 len
= snprintf(errstr
, buflen
, "prison short");
673 if (flags
& MBS_PRISON_DEFINED
) {
674 len
= snprintf(errstr
, buflen
, "one jail only");
677 value
= strtol(argv
[current
+1], &endp
, 10);
679 len
= snprintf(errstr
, buflen
,
680 "invalid jid: '%s'", argv
[current
+1]);
684 flags
|= MBS_PRISON_DEFINED
;
686 neg
^= MBS_PRISON_DEFINED
;
690 } else if (strcmp(argv
[current
], "!") == 0) {
692 len
= snprintf(errstr
, buflen
,
699 len
= snprintf(errstr
, buflen
, "'%s' not expected",
705 subject
->mbs_flags
= flags
;
707 subject
->mbs_neg
= MBS_ALL_FLAGS
^ neg
;
709 subject
->mbs_neg
= neg
;
710 if (flags
& MBS_UID_DEFINED
) {
711 subject
->mbs_uid_min
= uid_min
;
712 subject
->mbs_uid_max
= uid_max
;
714 if (flags
& MBS_GID_DEFINED
) {
715 subject
->mbs_gid_min
= gid_min
;
716 subject
->mbs_gid_max
= gid_max
;
718 if (flags
& MBS_PRISON_DEFINED
)
719 subject
->mbs_prison
= jid
;
725 bsde_parse_type(char *spec
, int *type
, size_t buflen
, char *errstr
)
731 for (i
= 0; i
< strlen(spec
); i
++) {
735 *type
|= MBO_TYPE_REG
;
738 *type
|= MBO_TYPE_DIR
;
741 *type
|= MBO_TYPE_BLK
;
744 *type
|= MBO_TYPE_CHR
;
747 *type
|= MBO_TYPE_LNK
;
750 *type
|= MBO_TYPE_SOCK
;
753 *type
|= MBO_TYPE_FIFO
;
756 *type
|= MBO_ALL_TYPE
;
759 len
= snprintf(errstr
, buflen
, "Unknown type code: %c",
769 bsde_parse_fsid(char *spec
, struct fsid
*fsid
, size_t buflen
, char *errstr
)
775 if (statfs(spec
, &buf
) < 0) {
776 len
= snprintf(errstr
, buflen
, "Unable to get id for %s: %s",
777 spec
, strerror(errno
));
787 bsde_parse_object(int argc
, char *argv
[],
788 struct mac_bsdextended_object
*object
, size_t buflen
, char *errstr
)
791 int current
, neg
, nextnot
;
792 uid_t uid_min
, uid_max
;
793 gid_t gid_min
, gid_max
;
803 if (strcmp("not", argv
[current
]) == 0) {
809 while (current
< argc
) {
810 if (strcmp(argv
[current
], "uid") == 0) {
811 if (current
+ 2 > argc
) {
812 len
= snprintf(errstr
, buflen
, "uid short");
815 if (flags
& MBO_UID_DEFINED
) {
816 len
= snprintf(errstr
, buflen
, "one uid only");
819 if (bsde_parse_uidrange(argv
[current
+1],
820 &uid_min
, &uid_max
, buflen
, errstr
) < 0)
822 flags
|= MBO_UID_DEFINED
;
824 neg
^= MBO_UID_DEFINED
;
828 } else if (strcmp(argv
[current
], "gid") == 0) {
829 if (current
+ 2 > argc
) {
830 len
= snprintf(errstr
, buflen
, "gid short");
833 if (flags
& MBO_GID_DEFINED
) {
834 len
= snprintf(errstr
, buflen
, "one gid only");
837 if (bsde_parse_gidrange(argv
[current
+1],
838 &gid_min
, &gid_max
, buflen
, errstr
) < 0)
840 flags
|= MBO_GID_DEFINED
;
842 neg
^= MBO_GID_DEFINED
;
846 } else if (strcmp(argv
[current
], "filesys") == 0) {
847 if (current
+ 2 > argc
) {
848 len
= snprintf(errstr
, buflen
, "filesys short");
851 if (flags
& MBO_FSID_DEFINED
) {
852 len
= snprintf(errstr
, buflen
, "one fsid only");
855 if (bsde_parse_fsid(argv
[current
+1], &fsid
,
858 flags
|= MBO_FSID_DEFINED
;
860 neg
^= MBO_FSID_DEFINED
;
864 } else if (strcmp(argv
[current
], "suid") == 0) {
871 } else if (strcmp(argv
[current
], "sgid") == 0) {
878 } else if (strcmp(argv
[current
], "uid_of_subject") == 0) {
879 flags
|= MBO_UID_SUBJECT
;
881 neg
^= MBO_UID_SUBJECT
;
885 } else if (strcmp(argv
[current
], "gid_of_subject") == 0) {
886 flags
|= MBO_GID_SUBJECT
;
888 neg
^= MBO_GID_SUBJECT
;
892 } else if (strcmp(argv
[current
], "type") == 0) {
893 if (current
+ 2 > argc
) {
894 len
= snprintf(errstr
, buflen
, "type short");
897 if (flags
& MBO_TYPE_DEFINED
) {
898 len
= snprintf(errstr
, buflen
, "one type only");
901 if (bsde_parse_type(argv
[current
+1], &type
,
904 flags
|= MBO_TYPE_DEFINED
;
906 neg
^= MBO_TYPE_DEFINED
;
910 } else if (strcmp(argv
[current
], "!") == 0) {
912 len
= snprintf(errstr
, buflen
,
919 len
= snprintf(errstr
, buflen
, "'%s' not expected",
925 object
->mbo_flags
= flags
;
927 object
->mbo_neg
= MBO_ALL_FLAGS
^ neg
;
929 object
->mbo_neg
= neg
;
930 if (flags
& MBO_UID_DEFINED
) {
931 object
->mbo_uid_min
= uid_min
;
932 object
->mbo_uid_max
= uid_max
;
934 if (flags
& MBO_GID_DEFINED
) {
935 object
->mbo_gid_min
= gid_min
;
936 object
->mbo_gid_max
= gid_max
;
938 if (flags
& MBO_FSID_DEFINED
)
939 object
->mbo_fsid
= fsid
;
940 if (flags
& MBO_TYPE_DEFINED
)
941 object
->mbo_type
= type
;
947 bsde_parse_mode(int argc
, char *argv
[], mode_t
*mode
, size_t buflen
,
954 len
= snprintf(errstr
, buflen
, "mode expects mode value");
959 len
= snprintf(errstr
, buflen
, "'%s' unexpected", argv
[1]);
964 for (i
= 0; i
< strlen(argv
[0]); i
++) {
965 switch (argv
[0][i
]) {
985 len
= snprintf(errstr
, buflen
, "Unknown mode letter: %c",
995 bsde_parse_rule(int argc
, char *argv
[], struct mac_bsdextended_rule
*rule
,
996 size_t buflen
, char *errstr
)
998 int subject
, subject_elements
, subject_elements_length
;
999 int object
, object_elements
, object_elements_length
;
1000 int mode
, mode_elements
, mode_elements_length
;
1004 bzero(rule
, sizeof(*rule
));
1007 len
= snprintf(errstr
, buflen
, "Rule must begin with subject");
1011 if (strcmp(argv
[0], "subject") != 0) {
1012 len
= snprintf(errstr
, buflen
, "Rule must begin with subject");
1016 subject_elements
= 1;
1018 /* Search forward for object. */
1021 for (i
= 1; i
< argc
; i
++)
1022 if (strcmp(argv
[i
], "object") == 0)
1026 len
= snprintf(errstr
, buflen
, "Rule must contain an object");
1030 /* Search forward for mode. */
1032 for (i
= object
; i
< argc
; i
++)
1033 if (strcmp(argv
[i
], "mode") == 0)
1037 len
= snprintf(errstr
, buflen
, "Rule must contain mode");
1041 subject_elements_length
= object
- subject
- 1;
1042 object_elements
= object
+ 1;
1043 object_elements_length
= mode
- object_elements
;
1044 mode_elements
= mode
+ 1;
1045 mode_elements_length
= argc
- mode_elements
;
1047 error
= bsde_parse_subject(subject_elements_length
,
1048 argv
+ subject_elements
, &rule
->mbr_subject
, buflen
, errstr
);
1052 error
= bsde_parse_object(object_elements_length
,
1053 argv
+ object_elements
, &rule
->mbr_object
, buflen
, errstr
);
1057 error
= bsde_parse_mode(mode_elements_length
, argv
+ mode_elements
,
1058 &rule
->mbr_mode
, buflen
, errstr
);
1066 bsde_parse_rule_string(const char *string
, struct mac_bsdextended_rule
*rule
,
1067 size_t buflen
, char *errstr
)
1069 char *stringdup
, *stringp
, *argv
[100], **ap
;
1072 stringp
= stringdup
= strdup(string
);
1073 while (*stringp
== ' ' || *stringp
== '\t')
1077 for (ap
= argv
; (*ap
= strsep(&stringp
, " \t")) != NULL
;) {
1080 if (++ap
>= &argv
[100])
1084 error
= bsde_parse_rule(argc
, argv
, rule
, buflen
, errstr
);
1092 bsde_get_mib(const char *string
, int *name
, size_t *namelen
)
1098 error
= sysctlnametomib(string
, name
, &len
);
1107 bsde_check_version(size_t buflen
, char *errstr
)
1113 len
= sizeof(version
);
1114 error
= sysctlbyname(MIB
".rule_version", &version
, &len
, NULL
, 0);
1116 len
= snprintf(errstr
, buflen
, "version check failed: %s",
1120 if (version
!= MB_VERSION
) {
1121 len
= snprintf(errstr
, buflen
, "module v%d != library v%d",
1122 version
, MB_VERSION
);
1129 bsde_get_rule_count(size_t buflen
, char *errstr
)
1135 len
= sizeof(rule_count
);
1136 error
= sysctlbyname(MIB
".rule_count", &rule_count
, &len
, NULL
, 0);
1138 len
= snprintf(errstr
, buflen
, strerror(errno
));
1141 if (len
!= sizeof(rule_count
)) {
1142 len
= snprintf(errstr
, buflen
, "Data error in %s.rule_count",
1147 return (rule_count
);
1151 bsde_get_rule_slots(size_t buflen
, char *errstr
)
1157 len
= sizeof(rule_slots
);
1158 error
= sysctlbyname(MIB
".rule_slots", &rule_slots
, &len
, NULL
, 0);
1160 len
= snprintf(errstr
, buflen
, strerror(errno
));
1163 if (len
!= sizeof(rule_slots
)) {
1164 len
= snprintf(errstr
, buflen
, "Data error in %s.rule_slots",
1169 return (rule_slots
);
1173 * Returns 0 for success;
1174 * Returns -1 for failure;
1175 * Returns -2 for not present
1178 bsde_get_rule(int rulenum
, struct mac_bsdextended_rule
*rule
, size_t errlen
,
1185 if (bsde_check_version(errlen
, errstr
) != 0)
1189 error
= bsde_get_mib(MIB
".rules", name
, &len
);
1191 len
= snprintf(errstr
, errlen
, "%s: %s", MIB
".rules",
1196 size
= sizeof(*rule
);
1197 name
[len
] = rulenum
;
1199 error
= sysctl(name
, len
, rule
, &size
, NULL
, 0);
1200 if (error
== -1 && errno
== ENOENT
)
1203 len
= snprintf(errstr
, errlen
, "%s.%d: %s", MIB
".rules",
1204 rulenum
, strerror(errno
));
1206 } else if (size
!= sizeof(*rule
)) {
1207 len
= snprintf(errstr
, errlen
, "Data error in %s.%d: %s",
1208 MIB
".rules", rulenum
, strerror(errno
));
1216 bsde_delete_rule(int rulenum
, size_t buflen
, char *errstr
)
1218 struct mac_bsdextended_rule rule
;
1223 if (bsde_check_version(buflen
, errstr
) != 0)
1227 error
= bsde_get_mib(MIB
".rules", name
, &len
);
1229 len
= snprintf(errstr
, buflen
, "%s: %s", MIB
".rules",
1234 name
[len
] = rulenum
;
1237 size
= sizeof(rule
);
1238 error
= sysctl(name
, len
, NULL
, NULL
, &rule
, 0);
1240 len
= snprintf(errstr
, buflen
, "%s.%d: %s", MIB
".rules",
1241 rulenum
, strerror(errno
));
1249 bsde_set_rule(int rulenum
, struct mac_bsdextended_rule
*rule
, size_t buflen
,
1256 if (bsde_check_version(buflen
, errstr
) != 0)
1260 error
= bsde_get_mib(MIB
".rules", name
, &len
);
1262 len
= snprintf(errstr
, buflen
, "%s: %s", MIB
".rules",
1267 name
[len
] = rulenum
;
1270 size
= sizeof(*rule
);
1271 error
= sysctl(name
, len
, NULL
, NULL
, rule
, size
);
1273 len
= snprintf(errstr
, buflen
, "%s.%d: %s", MIB
".rules",
1274 rulenum
, strerror(errno
));
1282 bsde_add_rule(int *rulenum
, struct mac_bsdextended_rule
*rule
, size_t buflen
,
1285 char charstr
[BUFSIZ
];
1288 int error
, rule_slots
;
1290 if (bsde_check_version(buflen
, errstr
) != 0)
1294 error
= bsde_get_mib(MIB
".rules", name
, &len
);
1296 len
= snprintf(errstr
, buflen
, "%s: %s", MIB
".rules",
1301 rule_slots
= bsde_get_rule_slots(BUFSIZ
, charstr
);
1302 if (rule_slots
== -1) {
1303 len
= snprintf(errstr
, buflen
, "unable to get rule slots: %s",
1308 name
[len
] = rule_slots
;
1311 size
= sizeof(*rule
);
1312 error
= sysctl(name
, len
, NULL
, NULL
, rule
, size
);
1314 len
= snprintf(errstr
, buflen
, "%s.%d: %s", MIB
".rules",
1315 rule_slots
, strerror(errno
));
1319 if (rulenum
!= NULL
)
1320 *rulenum
= rule_slots
;