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)
774 if (statfs(spec, &buf) < 0) {
775 len = snprintf(errstr, buflen, "Unable to get id for %s: %s",
776 spec, strerror(errno));
786 bsde_parse_object(int argc, char *argv[],
787 struct mac_bsdextended_object *object, size_t buflen, char *errstr)
790 int current, neg, nextnot;
791 uid_t uid_min, uid_max;
792 gid_t gid_min, gid_max;
802 if (strcmp("not", argv[current]) == 0) {
808 while (current < argc) {
809 if (strcmp(argv[current], "uid") == 0) {
810 if (current + 2 > argc) {
811 len = snprintf(errstr, buflen, "uid short");
814 if (flags & MBO_UID_DEFINED) {
815 len = snprintf(errstr, buflen, "one uid only");
818 if (bsde_parse_uidrange(argv[current+1],
819 &uid_min, &uid_max, buflen, errstr) < 0)
821 flags |= MBO_UID_DEFINED;
823 neg ^= MBO_UID_DEFINED;
827 } else if (strcmp(argv[current], "gid") == 0) {
828 if (current + 2 > argc) {
829 len = snprintf(errstr, buflen, "gid short");
832 if (flags & MBO_GID_DEFINED) {
833 len = snprintf(errstr, buflen, "one gid only");
836 if (bsde_parse_gidrange(argv[current+1],
837 &gid_min, &gid_max, buflen, errstr) < 0)
839 flags |= MBO_GID_DEFINED;
841 neg ^= MBO_GID_DEFINED;
845 } else if (strcmp(argv[current], "filesys") == 0) {
846 if (current + 2 > argc) {
847 len = snprintf(errstr, buflen, "filesys short");
850 if (flags & MBO_FSID_DEFINED) {
851 len = snprintf(errstr, buflen, "one fsid only");
854 if (bsde_parse_fsid(argv[current+1], &fsid,
857 flags |= MBO_FSID_DEFINED;
859 neg ^= MBO_FSID_DEFINED;
863 } else if (strcmp(argv[current], "suid") == 0) {
870 } else if (strcmp(argv[current], "sgid") == 0) {
877 } else if (strcmp(argv[current], "uid_of_subject") == 0) {
878 flags |= MBO_UID_SUBJECT;
880 neg ^= MBO_UID_SUBJECT;
884 } else if (strcmp(argv[current], "gid_of_subject") == 0) {
885 flags |= MBO_GID_SUBJECT;
887 neg ^= MBO_GID_SUBJECT;
891 } else if (strcmp(argv[current], "type") == 0) {
892 if (current + 2 > argc) {
893 len = snprintf(errstr, buflen, "type short");
896 if (flags & MBO_TYPE_DEFINED) {
897 len = snprintf(errstr, buflen, "one type only");
900 if (bsde_parse_type(argv[current+1], &type,
903 flags |= MBO_TYPE_DEFINED;
905 neg ^= MBO_TYPE_DEFINED;
909 } else if (strcmp(argv[current], "!") == 0) {
911 len = snprintf(errstr, buflen,
918 len = snprintf(errstr, buflen, "'%s' not expected",
924 object->mbo_flags = flags;
926 object->mbo_neg = MBO_ALL_FLAGS ^ neg;
928 object->mbo_neg = neg;
929 if (flags & MBO_UID_DEFINED) {
930 object->mbo_uid_min = uid_min;
931 object->mbo_uid_max = uid_max;
933 if (flags & MBO_GID_DEFINED) {
934 object->mbo_gid_min = gid_min;
935 object->mbo_gid_max = gid_max;
937 if (flags & MBO_FSID_DEFINED)
938 object->mbo_fsid = fsid;
939 if (flags & MBO_TYPE_DEFINED)
940 object->mbo_type = type;
946 bsde_parse_mode(int argc, char *argv[], mode_t *mode, size_t buflen,
953 len = snprintf(errstr, buflen, "mode expects mode value");
958 len = snprintf(errstr, buflen, "'%s' unexpected", argv[1]);
963 for (i = 0; i < strlen(argv[0]); i++) {
964 switch (argv[0][i]) {
984 len = snprintf(errstr, buflen, "Unknown mode letter: %c",
994 bsde_parse_rule(int argc, char *argv[], struct mac_bsdextended_rule *rule,
995 size_t buflen, char *errstr)
997 int subject, subject_elements, subject_elements_length;
998 int object, object_elements, object_elements_length;
999 int mode, mode_elements, mode_elements_length;
1003 bzero(rule, sizeof(*rule));
1006 len = snprintf(errstr, buflen, "Rule must begin with subject");
1010 if (strcmp(argv[0], "subject") != 0) {
1011 len = snprintf(errstr, buflen, "Rule must begin with subject");
1015 subject_elements = 1;
1017 /* Search forward for object. */
1020 for (i = 1; i < argc; i++)
1021 if (strcmp(argv[i], "object") == 0)
1025 len = snprintf(errstr, buflen, "Rule must contain an object");
1029 /* Search forward for mode. */
1031 for (i = object; i < argc; i++)
1032 if (strcmp(argv[i], "mode") == 0)
1036 len = snprintf(errstr, buflen, "Rule must contain mode");
1040 subject_elements_length = object - subject - 1;
1041 object_elements = object + 1;
1042 object_elements_length = mode - object_elements;
1043 mode_elements = mode + 1;
1044 mode_elements_length = argc - mode_elements;
1046 error = bsde_parse_subject(subject_elements_length,
1047 argv + subject_elements, &rule->mbr_subject, buflen, errstr);
1051 error = bsde_parse_object(object_elements_length,
1052 argv + object_elements, &rule->mbr_object, buflen, errstr);
1056 error = bsde_parse_mode(mode_elements_length, argv + mode_elements,
1057 &rule->mbr_mode, buflen, errstr);
1065 bsde_parse_rule_string(const char *string, struct mac_bsdextended_rule *rule,
1066 size_t buflen, char *errstr)
1068 char *stringdup, *stringp, *argv[100], **ap;
1071 stringp = stringdup = strdup(string);
1072 while (*stringp == ' ' || *stringp == '\t')
1076 for (ap = argv; (*ap = strsep(&stringp, " \t")) != NULL;) {
1079 if (++ap >= &argv[100])
1083 error = bsde_parse_rule(argc, argv, rule, buflen, errstr);
1091 bsde_get_mib(const char *string, int *name, size_t *namelen)
1097 error = sysctlnametomib(string, name, &len);
1106 bsde_check_version(size_t buflen, char *errstr)
1112 len = sizeof(version);
1113 error = sysctlbyname(MIB ".rule_version", &version, &len, NULL, 0);
1115 len = snprintf(errstr, buflen, "version check failed: %s",
1119 if (version != MB_VERSION) {
1120 len = snprintf(errstr, buflen, "module v%d != library v%d",
1121 version, MB_VERSION);
1128 bsde_get_rule_count(size_t buflen, char *errstr)
1134 len = sizeof(rule_count);
1135 error = sysctlbyname(MIB ".rule_count", &rule_count, &len, NULL, 0);
1137 len = snprintf(errstr, buflen, "%s", strerror(errno));
1140 if (len != sizeof(rule_count)) {
1141 len = snprintf(errstr, buflen, "Data error in %s.rule_count",
1146 return (rule_count);
1150 bsde_get_rule_slots(size_t buflen, char *errstr)
1156 len = sizeof(rule_slots);
1157 error = sysctlbyname(MIB ".rule_slots", &rule_slots, &len, NULL, 0);
1159 len = snprintf(errstr, buflen, "%s", strerror(errno));
1162 if (len != sizeof(rule_slots)) {
1163 len = snprintf(errstr, buflen, "Data error in %s.rule_slots",
1168 return (rule_slots);
1172 * Returns 0 for success;
1173 * Returns -1 for failure;
1174 * Returns -2 for not present
1177 bsde_get_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t errlen,
1184 if (bsde_check_version(errlen, errstr) != 0)
1188 error = bsde_get_mib(MIB ".rules", name, &len);
1190 len = snprintf(errstr, errlen, "%s: %s", MIB ".rules",
1195 size = sizeof(*rule);
1196 name[len] = rulenum;
1198 error = sysctl(name, len, rule, &size, NULL, 0);
1199 if (error == -1 && errno == ENOENT)
1202 len = snprintf(errstr, errlen, "%s.%d: %s", MIB ".rules",
1203 rulenum, strerror(errno));
1205 } else if (size != sizeof(*rule)) {
1206 len = snprintf(errstr, errlen, "Data error in %s.%d: %s",
1207 MIB ".rules", rulenum, strerror(errno));
1215 bsde_delete_rule(int rulenum, size_t buflen, char *errstr)
1217 struct mac_bsdextended_rule rule;
1222 if (bsde_check_version(buflen, errstr) != 0)
1226 error = bsde_get_mib(MIB ".rules", name, &len);
1228 len = snprintf(errstr, buflen, "%s: %s", MIB ".rules",
1233 name[len] = rulenum;
1236 size = sizeof(rule);
1237 error = sysctl(name, len, NULL, NULL, &rule, 0);
1239 len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
1240 rulenum, strerror(errno));
1248 bsde_set_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t buflen,
1255 if (bsde_check_version(buflen, errstr) != 0)
1259 error = bsde_get_mib(MIB ".rules", name, &len);
1261 len = snprintf(errstr, buflen, "%s: %s", MIB ".rules",
1266 name[len] = rulenum;
1269 size = sizeof(*rule);
1270 error = sysctl(name, len, NULL, NULL, rule, size);
1272 len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
1273 rulenum, strerror(errno));
1281 bsde_add_rule(int *rulenum, struct mac_bsdextended_rule *rule, size_t buflen,
1284 char charstr[BUFSIZ];
1287 int error, rule_slots;
1289 if (bsde_check_version(buflen, errstr) != 0)
1293 error = bsde_get_mib(MIB ".rules", name, &len);
1295 len = snprintf(errstr, buflen, "%s: %s", MIB ".rules",
1300 rule_slots = bsde_get_rule_slots(BUFSIZ, charstr);
1301 if (rule_slots == -1) {
1302 len = snprintf(errstr, buflen, "unable to get rule slots: %s",
1307 name[len] = rule_slots;
1310 size = sizeof(*rule);
1311 error = sysctl(name, len, NULL, NULL, rule, size);
1313 len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
1314 rule_slots, strerror(errno));
1318 if (rulenum != NULL)
1319 *rulenum = rule_slots;