146d1a925SRobert Watson /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni *
4a6c2bc8bSRobert Watson * Copyright (c) 2002-2005 Networks Associates Technology, Inc.
546d1a925SRobert Watson * All rights reserved.
646d1a925SRobert Watson *
70285334bSRobert Watson * This software was developed for the FreeBSD Project by Network Associates
80285334bSRobert Watson * Laboratories, the Security Research Division of Network Associates, Inc.
90285334bSRobert Watson * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
100285334bSRobert Watson * DARPA CHATS research program.
1146d1a925SRobert Watson *
1246d1a925SRobert Watson * Redistribution and use in source and binary forms, with or without
1346d1a925SRobert Watson * modification, are permitted provided that the following conditions
1446d1a925SRobert Watson * are met:
1546d1a925SRobert Watson * 1. Redistributions of source code must retain the above copyright
1646d1a925SRobert Watson * notice, this list of conditions and the following disclaimer.
1746d1a925SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
1846d1a925SRobert Watson * notice, this list of conditions and the following disclaimer in the
1946d1a925SRobert Watson * documentation and/or other materials provided with the distribution.
2046d1a925SRobert Watson *
2146d1a925SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2246d1a925SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2346d1a925SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2446d1a925SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2546d1a925SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2646d1a925SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2746d1a925SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2846d1a925SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2946d1a925SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3046d1a925SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3146d1a925SRobert Watson * SUCH DAMAGE.
3246d1a925SRobert Watson */
3346d1a925SRobert Watson #include <sys/param.h>
3446d1a925SRobert Watson #include <sys/errno.h>
35de68a320SJamie Gritton #include <sys/jail.h>
3646d1a925SRobert Watson #include <sys/time.h>
3746d1a925SRobert Watson #include <sys/sysctl.h>
3889ddbd45SDavid Malone #include <sys/ucred.h>
39de68a320SJamie Gritton #include <sys/uio.h>
4089ddbd45SDavid Malone #include <sys/mount.h>
4146d1a925SRobert Watson
4246d1a925SRobert Watson #include <security/mac_bsdextended/mac_bsdextended.h>
4346d1a925SRobert Watson
4446d1a925SRobert Watson #include <grp.h>
4546d1a925SRobert Watson #include <pwd.h>
4646d1a925SRobert Watson #include <stdio.h>
4746d1a925SRobert Watson #include <stdlib.h>
4846d1a925SRobert Watson #include <string.h>
4946d1a925SRobert Watson
50912dd12aSRobert Watson #include "ugidfw.h"
5146d1a925SRobert Watson
5246d1a925SRobert Watson /*
5346d1a925SRobert Watson * Text format for rules: rules contain subject and object elements, mode.
5489ddbd45SDavid Malone * The total form is "subject [s_element] object [o_element] mode [mode]".
5546d1a925SRobert Watson * At least * one of a uid or gid entry must be present; both may also be
5646d1a925SRobert Watson * present.
5746d1a925SRobert Watson */
5846d1a925SRobert Watson
5946d1a925SRobert Watson #define MIB "security.mac.bsdextended"
6046d1a925SRobert Watson
6146d1a925SRobert Watson int
bsde_rule_to_string(struct mac_bsdextended_rule * rule,char * buf,size_t buflen)6246d1a925SRobert Watson bsde_rule_to_string(struct mac_bsdextended_rule *rule, char *buf, size_t buflen)
6346d1a925SRobert Watson {
6446d1a925SRobert Watson struct group *grp;
6546d1a925SRobert Watson struct passwd *pwd;
6689ddbd45SDavid Malone struct statfs *mntbuf;
6789ddbd45SDavid Malone char *cur, type[sizeof(rule->mbr_object.mbo_type) * CHAR_BIT + 1];
6846d1a925SRobert Watson size_t left, len;
69da1259f0SMarcelo Araujo int anymode, unknownmode, numfs, i, notdone;
7046d1a925SRobert Watson
7146d1a925SRobert Watson cur = buf;
7246d1a925SRobert Watson left = buflen;
7346d1a925SRobert Watson
7446d1a925SRobert Watson len = snprintf(cur, left, "subject ");
7546d1a925SRobert Watson if (len < 0 || len > left)
7646d1a925SRobert Watson goto truncated;
7746d1a925SRobert Watson left -= len;
7846d1a925SRobert Watson cur += len;
7989ddbd45SDavid Malone if (rule->mbr_subject.mbs_flags) {
8089ddbd45SDavid Malone if (rule->mbr_subject.mbs_neg == MBS_ALL_FLAGS) {
8146d1a925SRobert Watson len = snprintf(cur, left, "not ");
8246d1a925SRobert Watson if (len < 0 || len > left)
8346d1a925SRobert Watson goto truncated;
8446d1a925SRobert Watson left -= len;
8546d1a925SRobert Watson cur += len;
8689ddbd45SDavid Malone notdone = 1;
8789ddbd45SDavid Malone } else {
8889ddbd45SDavid Malone notdone = 0;
8946d1a925SRobert Watson }
9089ddbd45SDavid Malone
9189ddbd45SDavid Malone if (!notdone && (rule->mbr_subject.mbs_neg & MBO_UID_DEFINED)) {
9289ddbd45SDavid Malone len = snprintf(cur, left, "! ");
9389ddbd45SDavid Malone if (len < 0 || len > left)
9489ddbd45SDavid Malone goto truncated;
9589ddbd45SDavid Malone left -= len;
9689ddbd45SDavid Malone cur += len;
9789ddbd45SDavid Malone }
9889ddbd45SDavid Malone if (rule->mbr_subject.mbs_flags & MBO_UID_DEFINED) {
9989ddbd45SDavid Malone pwd = getpwuid(rule->mbr_subject.mbs_uid_min);
10046d1a925SRobert Watson if (pwd != NULL) {
10146d1a925SRobert Watson len = snprintf(cur, left, "uid %s",
10246d1a925SRobert Watson pwd->pw_name);
10346d1a925SRobert Watson if (len < 0 || len > left)
10446d1a925SRobert Watson goto truncated;
10546d1a925SRobert Watson left -= len;
10646d1a925SRobert Watson cur += len;
10746d1a925SRobert Watson } else {
10846d1a925SRobert Watson len = snprintf(cur, left, "uid %u",
10989ddbd45SDavid Malone rule->mbr_subject.mbs_uid_min);
11089ddbd45SDavid Malone if (len < 0 || len > left)
11189ddbd45SDavid Malone goto truncated;
11289ddbd45SDavid Malone left -= len;
11389ddbd45SDavid Malone cur += len;
11489ddbd45SDavid Malone }
11589ddbd45SDavid Malone if (rule->mbr_subject.mbs_uid_min !=
11689ddbd45SDavid Malone rule->mbr_subject.mbs_uid_max) {
11789ddbd45SDavid Malone pwd = getpwuid(rule->mbr_subject.mbs_uid_max);
11889ddbd45SDavid Malone if (pwd != NULL) {
11989ddbd45SDavid Malone len = snprintf(cur, left, ":%s ",
12089ddbd45SDavid Malone pwd->pw_name);
12189ddbd45SDavid Malone if (len < 0 || len > left)
12289ddbd45SDavid Malone goto truncated;
12389ddbd45SDavid Malone left -= len;
12489ddbd45SDavid Malone cur += len;
12589ddbd45SDavid Malone } else {
12689ddbd45SDavid Malone len = snprintf(cur, left, ":%u ",
12789ddbd45SDavid Malone rule->mbr_subject.mbs_uid_max);
12889ddbd45SDavid Malone if (len < 0 || len > left)
12989ddbd45SDavid Malone goto truncated;
13089ddbd45SDavid Malone left -= len;
13189ddbd45SDavid Malone cur += len;
13289ddbd45SDavid Malone }
13389ddbd45SDavid Malone } else {
13489ddbd45SDavid Malone len = snprintf(cur, left, " ");
13546d1a925SRobert Watson if (len < 0 || len > left)
13646d1a925SRobert Watson goto truncated;
13746d1a925SRobert Watson left -= len;
13846d1a925SRobert Watson cur += len;
13946d1a925SRobert Watson }
14046d1a925SRobert Watson }
14189ddbd45SDavid Malone if (!notdone && (rule->mbr_subject.mbs_neg & MBO_GID_DEFINED)) {
14289ddbd45SDavid Malone len = snprintf(cur, left, "! ");
14389ddbd45SDavid Malone if (len < 0 || len > left)
14489ddbd45SDavid Malone goto truncated;
14589ddbd45SDavid Malone left -= len;
14689ddbd45SDavid Malone cur += len;
14789ddbd45SDavid Malone }
14889ddbd45SDavid Malone if (rule->mbr_subject.mbs_flags & MBO_GID_DEFINED) {
14989ddbd45SDavid Malone grp = getgrgid(rule->mbr_subject.mbs_gid_min);
15046d1a925SRobert Watson if (grp != NULL) {
15146d1a925SRobert Watson len = snprintf(cur, left, "gid %s",
15246d1a925SRobert Watson grp->gr_name);
15346d1a925SRobert Watson if (len < 0 || len > left)
15446d1a925SRobert Watson goto truncated;
15546d1a925SRobert Watson left -= len;
15646d1a925SRobert Watson cur += len;
15746d1a925SRobert Watson } else {
15846d1a925SRobert Watson len = snprintf(cur, left, "gid %u",
15989ddbd45SDavid Malone rule->mbr_subject.mbs_gid_min);
16089ddbd45SDavid Malone if (len < 0 || len > left)
16189ddbd45SDavid Malone goto truncated;
16289ddbd45SDavid Malone left -= len;
16389ddbd45SDavid Malone cur += len;
16489ddbd45SDavid Malone }
16589ddbd45SDavid Malone if (rule->mbr_subject.mbs_gid_min !=
16689ddbd45SDavid Malone rule->mbr_subject.mbs_gid_max) {
16789ddbd45SDavid Malone grp = getgrgid(rule->mbr_subject.mbs_gid_max);
16889ddbd45SDavid Malone if (grp != NULL) {
16989ddbd45SDavid Malone len = snprintf(cur, left, ":%s ",
17089ddbd45SDavid Malone grp->gr_name);
17189ddbd45SDavid Malone if (len < 0 || len > left)
17289ddbd45SDavid Malone goto truncated;
17389ddbd45SDavid Malone left -= len;
17489ddbd45SDavid Malone cur += len;
17589ddbd45SDavid Malone } else {
17689ddbd45SDavid Malone len = snprintf(cur, left, ":%u ",
17789ddbd45SDavid Malone rule->mbr_subject.mbs_gid_max);
17889ddbd45SDavid Malone if (len < 0 || len > left)
17989ddbd45SDavid Malone goto truncated;
18089ddbd45SDavid Malone left -= len;
18189ddbd45SDavid Malone cur += len;
18289ddbd45SDavid Malone }
18389ddbd45SDavid Malone } else {
18489ddbd45SDavid Malone len = snprintf(cur, left, " ");
18546d1a925SRobert Watson if (len < 0 || len > left)
18646d1a925SRobert Watson goto truncated;
18746d1a925SRobert Watson left -= len;
18846d1a925SRobert Watson cur += len;
18946d1a925SRobert Watson }
19046d1a925SRobert Watson }
19189ddbd45SDavid Malone if (!notdone && (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)) {
19289ddbd45SDavid Malone len = snprintf(cur, left, "! ");
19389ddbd45SDavid Malone if (len < 0 || len > left)
19489ddbd45SDavid Malone goto truncated;
19589ddbd45SDavid Malone left -= len;
19689ddbd45SDavid Malone cur += len;
19746d1a925SRobert Watson }
19889ddbd45SDavid Malone if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
19989ddbd45SDavid Malone len = snprintf(cur, left, "jailid %d ",
20089ddbd45SDavid Malone rule->mbr_subject.mbs_prison);
20189ddbd45SDavid Malone if (len < 0 || len > left)
20289ddbd45SDavid Malone goto truncated;
20389ddbd45SDavid Malone left -= len;
20489ddbd45SDavid Malone cur += len;
20589ddbd45SDavid Malone }
20689ddbd45SDavid Malone }
20789ddbd45SDavid Malone
20846d1a925SRobert Watson len = snprintf(cur, left, "object ");
20946d1a925SRobert Watson if (len < 0 || len > left)
21046d1a925SRobert Watson goto truncated;
21146d1a925SRobert Watson left -= len;
21246d1a925SRobert Watson cur += len;
21389ddbd45SDavid Malone if (rule->mbr_object.mbo_flags) {
21489ddbd45SDavid Malone if (rule->mbr_object.mbo_neg == MBO_ALL_FLAGS) {
21546d1a925SRobert Watson len = snprintf(cur, left, "not ");
21646d1a925SRobert Watson if (len < 0 || len > left)
21746d1a925SRobert Watson goto truncated;
21846d1a925SRobert Watson left -= len;
21946d1a925SRobert Watson cur += len;
22089ddbd45SDavid Malone notdone = 1;
22189ddbd45SDavid Malone } else {
22289ddbd45SDavid Malone notdone = 0;
22346d1a925SRobert Watson }
22489ddbd45SDavid Malone
22589ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)) {
22689ddbd45SDavid Malone len = snprintf(cur, left, "! ");
22789ddbd45SDavid Malone if (len < 0 || len > left)
22889ddbd45SDavid Malone goto truncated;
22989ddbd45SDavid Malone left -= len;
23089ddbd45SDavid Malone cur += len;
23189ddbd45SDavid Malone }
23289ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
23389ddbd45SDavid Malone pwd = getpwuid(rule->mbr_object.mbo_uid_min);
23446d1a925SRobert Watson if (pwd != NULL) {
23546d1a925SRobert Watson len = snprintf(cur, left, "uid %s",
23646d1a925SRobert Watson pwd->pw_name);
23746d1a925SRobert Watson if (len < 0 || len > left)
23846d1a925SRobert Watson goto truncated;
23946d1a925SRobert Watson left -= len;
24046d1a925SRobert Watson cur += len;
24146d1a925SRobert Watson } else {
24246d1a925SRobert Watson len = snprintf(cur, left, "uid %u",
24389ddbd45SDavid Malone rule->mbr_object.mbo_uid_min);
24489ddbd45SDavid Malone if (len < 0 || len > left)
24589ddbd45SDavid Malone goto truncated;
24689ddbd45SDavid Malone left -= len;
24789ddbd45SDavid Malone cur += len;
24889ddbd45SDavid Malone }
24989ddbd45SDavid Malone if (rule->mbr_object.mbo_uid_min !=
25089ddbd45SDavid Malone rule->mbr_object.mbo_uid_max) {
25189ddbd45SDavid Malone pwd = getpwuid(rule->mbr_object.mbo_uid_max);
25289ddbd45SDavid Malone if (pwd != NULL) {
25389ddbd45SDavid Malone len = snprintf(cur, left, ":%s ",
25489ddbd45SDavid Malone pwd->pw_name);
25589ddbd45SDavid Malone if (len < 0 || len > left)
25689ddbd45SDavid Malone goto truncated;
25789ddbd45SDavid Malone left -= len;
25889ddbd45SDavid Malone cur += len;
25989ddbd45SDavid Malone } else {
26089ddbd45SDavid Malone len = snprintf(cur, left, ":%u ",
26189ddbd45SDavid Malone rule->mbr_object.mbo_uid_max);
26289ddbd45SDavid Malone if (len < 0 || len > left)
26389ddbd45SDavid Malone goto truncated;
26489ddbd45SDavid Malone left -= len;
26589ddbd45SDavid Malone cur += len;
26689ddbd45SDavid Malone }
26789ddbd45SDavid Malone } else {
26889ddbd45SDavid Malone len = snprintf(cur, left, " ");
26989ddbd45SDavid Malone if (len < 0 || len > left)
27089ddbd45SDavid Malone goto truncated;
27146d1a925SRobert Watson left -= len;
27246d1a925SRobert Watson cur += len;
27346d1a925SRobert Watson }
27446d1a925SRobert Watson }
27589ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)) {
27689ddbd45SDavid Malone len = snprintf(cur, left, "! ");
27789ddbd45SDavid Malone if (len < 0 || len > left)
27889ddbd45SDavid Malone goto truncated;
27989ddbd45SDavid Malone left -= len;
28089ddbd45SDavid Malone cur += len;
28189ddbd45SDavid Malone }
28289ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
28389ddbd45SDavid Malone grp = getgrgid(rule->mbr_object.mbo_gid_min);
28446d1a925SRobert Watson if (grp != NULL) {
28546d1a925SRobert Watson len = snprintf(cur, left, "gid %s",
28646d1a925SRobert Watson grp->gr_name);
28746d1a925SRobert Watson if (len < 0 || len > left)
28846d1a925SRobert Watson goto truncated;
28946d1a925SRobert Watson left -= len;
29046d1a925SRobert Watson cur += len;
29146d1a925SRobert Watson } else {
29246d1a925SRobert Watson len = snprintf(cur, left, "gid %u",
29389ddbd45SDavid Malone rule->mbr_object.mbo_gid_min);
29446d1a925SRobert Watson if (len < 0 || len > left)
29546d1a925SRobert Watson goto truncated;
29646d1a925SRobert Watson left -= len;
29746d1a925SRobert Watson cur += len;
29846d1a925SRobert Watson }
29989ddbd45SDavid Malone if (rule->mbr_object.mbo_gid_min !=
30089ddbd45SDavid Malone rule->mbr_object.mbo_gid_max) {
30189ddbd45SDavid Malone grp = getgrgid(rule->mbr_object.mbo_gid_max);
30289ddbd45SDavid Malone if (grp != NULL) {
30389ddbd45SDavid Malone len = snprintf(cur, left, ":%s ",
30489ddbd45SDavid Malone grp->gr_name);
30589ddbd45SDavid Malone if (len < 0 || len > left)
30689ddbd45SDavid Malone goto truncated;
30789ddbd45SDavid Malone left -= len;
30889ddbd45SDavid Malone cur += len;
30989ddbd45SDavid Malone } else {
31089ddbd45SDavid Malone len = snprintf(cur, left, ":%u ",
31189ddbd45SDavid Malone rule->mbr_object.mbo_gid_max);
31289ddbd45SDavid Malone if (len < 0 || len > left)
31389ddbd45SDavid Malone goto truncated;
31489ddbd45SDavid Malone left -= len;
31589ddbd45SDavid Malone cur += len;
31689ddbd45SDavid Malone }
31789ddbd45SDavid Malone } else {
31889ddbd45SDavid Malone len = snprintf(cur, left, " ");
31989ddbd45SDavid Malone if (len < 0 || len > left)
32089ddbd45SDavid Malone goto truncated;
32189ddbd45SDavid Malone left -= len;
32289ddbd45SDavid Malone cur += len;
32389ddbd45SDavid Malone }
32489ddbd45SDavid Malone }
32589ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)) {
32689ddbd45SDavid Malone len = snprintf(cur, left, "! ");
32789ddbd45SDavid Malone if (len < 0 || len > left)
32889ddbd45SDavid Malone goto truncated;
32989ddbd45SDavid Malone left -= len;
33089ddbd45SDavid Malone cur += len;
33189ddbd45SDavid Malone }
33289ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
33389ddbd45SDavid Malone numfs = getmntinfo(&mntbuf, MNT_NOWAIT);
33489ddbd45SDavid Malone for (i = 0; i < numfs; i++)
335245bfd34SRyan Moeller if (fsidcmp(&rule->mbr_object.mbo_fsid,
336245bfd34SRyan Moeller &mntbuf[i].f_fsid) == 0)
33789ddbd45SDavid Malone break;
33889ddbd45SDavid Malone len = snprintf(cur, left, "filesys %s ",
33989ddbd45SDavid Malone i == numfs ? "???" : mntbuf[i].f_mntonname);
34089ddbd45SDavid Malone if (len < 0 || len > left)
34189ddbd45SDavid Malone goto truncated;
34289ddbd45SDavid Malone left -= len;
34389ddbd45SDavid Malone cur += len;
34489ddbd45SDavid Malone }
34589ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_SUID)) {
34689ddbd45SDavid Malone len = snprintf(cur, left, "! ");
34789ddbd45SDavid Malone if (len < 0 || len > left)
34889ddbd45SDavid Malone goto truncated;
34989ddbd45SDavid Malone left -= len;
35089ddbd45SDavid Malone cur += len;
35189ddbd45SDavid Malone }
35289ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_SUID) {
35389ddbd45SDavid Malone len = snprintf(cur, left, "suid ");
35489ddbd45SDavid Malone if (len < 0 || len > left)
35589ddbd45SDavid Malone goto truncated;
35689ddbd45SDavid Malone left -= len;
35789ddbd45SDavid Malone cur += len;
35889ddbd45SDavid Malone }
35989ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_SGID)) {
36089ddbd45SDavid Malone len = snprintf(cur, left, "! ");
36189ddbd45SDavid Malone if (len < 0 || len > left)
36289ddbd45SDavid Malone goto truncated;
36389ddbd45SDavid Malone left -= len;
36489ddbd45SDavid Malone cur += len;
36589ddbd45SDavid Malone }
36689ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_SGID) {
36789ddbd45SDavid Malone len = snprintf(cur, left, "sgid ");
36889ddbd45SDavid Malone if (len < 0 || len > left)
36989ddbd45SDavid Malone goto truncated;
37089ddbd45SDavid Malone left -= len;
37189ddbd45SDavid Malone cur += len;
37289ddbd45SDavid Malone }
37389ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)) {
37489ddbd45SDavid Malone len = snprintf(cur, left, "! ");
37589ddbd45SDavid Malone if (len < 0 || len > left)
37689ddbd45SDavid Malone goto truncated;
37789ddbd45SDavid Malone left -= len;
37889ddbd45SDavid Malone cur += len;
37989ddbd45SDavid Malone }
38089ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
38189ddbd45SDavid Malone len = snprintf(cur, left, "uid_of_subject ");
38289ddbd45SDavid Malone if (len < 0 || len > left)
38389ddbd45SDavid Malone goto truncated;
38489ddbd45SDavid Malone left -= len;
38589ddbd45SDavid Malone cur += len;
38689ddbd45SDavid Malone }
38789ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)) {
38889ddbd45SDavid Malone len = snprintf(cur, left, "! ");
38989ddbd45SDavid Malone if (len < 0 || len > left)
39089ddbd45SDavid Malone goto truncated;
39189ddbd45SDavid Malone left -= len;
39289ddbd45SDavid Malone cur += len;
39389ddbd45SDavid Malone }
39489ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
39589ddbd45SDavid Malone len = snprintf(cur, left, "gid_of_subject ");
39689ddbd45SDavid Malone if (len < 0 || len > left)
39789ddbd45SDavid Malone goto truncated;
39889ddbd45SDavid Malone left -= len;
39989ddbd45SDavid Malone cur += len;
40089ddbd45SDavid Malone }
40189ddbd45SDavid Malone if (!notdone && (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)) {
40289ddbd45SDavid Malone len = snprintf(cur, left, "! ");
40389ddbd45SDavid Malone if (len < 0 || len > left)
40489ddbd45SDavid Malone goto truncated;
40589ddbd45SDavid Malone left -= len;
40689ddbd45SDavid Malone cur += len;
40789ddbd45SDavid Malone }
40889ddbd45SDavid Malone if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
40989ddbd45SDavid Malone i = 0;
41089ddbd45SDavid Malone if (rule->mbr_object.mbo_type & MBO_TYPE_REG)
41189ddbd45SDavid Malone type[i++] = 'r';
41289ddbd45SDavid Malone if (rule->mbr_object.mbo_type & MBO_TYPE_DIR)
41389ddbd45SDavid Malone type[i++] = 'd';
41489ddbd45SDavid Malone if (rule->mbr_object.mbo_type & MBO_TYPE_BLK)
41589ddbd45SDavid Malone type[i++] = 'b';
41689ddbd45SDavid Malone if (rule->mbr_object.mbo_type & MBO_TYPE_CHR)
41789ddbd45SDavid Malone type[i++] = 'c';
41889ddbd45SDavid Malone if (rule->mbr_object.mbo_type & MBO_TYPE_LNK)
41989ddbd45SDavid Malone type[i++] = 'l';
42089ddbd45SDavid Malone if (rule->mbr_object.mbo_type & MBO_TYPE_SOCK)
42189ddbd45SDavid Malone type[i++] = 's';
42289ddbd45SDavid Malone if (rule->mbr_object.mbo_type & MBO_TYPE_FIFO)
42389ddbd45SDavid Malone type[i++] = 'p';
42489ddbd45SDavid Malone if (rule->mbr_object.mbo_type == MBO_ALL_TYPE) {
42589ddbd45SDavid Malone i = 0;
42689ddbd45SDavid Malone type[i++] = 'a';
42789ddbd45SDavid Malone }
42889ddbd45SDavid Malone type[i++] = '\0';
42989ddbd45SDavid Malone len = snprintf(cur, left, "type %s ", type);
43089ddbd45SDavid Malone if (len < 0 || len > left)
43189ddbd45SDavid Malone goto truncated;
43289ddbd45SDavid Malone left -= len;
43389ddbd45SDavid Malone cur += len;
43446d1a925SRobert Watson }
43546d1a925SRobert Watson }
43646d1a925SRobert Watson
43746d1a925SRobert Watson len = snprintf(cur, left, "mode ");
43846d1a925SRobert Watson if (len < 0 || len > left)
43946d1a925SRobert Watson goto truncated;
44046d1a925SRobert Watson left -= len;
44146d1a925SRobert Watson cur += len;
44246d1a925SRobert Watson
443f4194603SRobert Watson anymode = (rule->mbr_mode & MBI_ALLPERM);
444f4194603SRobert Watson unknownmode = (rule->mbr_mode & ~MBI_ALLPERM);
44546d1a925SRobert Watson
446f4194603SRobert Watson if (rule->mbr_mode & MBI_ADMIN) {
44746d1a925SRobert Watson len = snprintf(cur, left, "a");
44846d1a925SRobert Watson if (len < 0 || len > left)
44946d1a925SRobert Watson goto truncated;
45046d1a925SRobert Watson
45146d1a925SRobert Watson left -= len;
45246d1a925SRobert Watson cur += len;
45346d1a925SRobert Watson }
454f4194603SRobert Watson if (rule->mbr_mode & MBI_READ) {
45546d1a925SRobert Watson len = snprintf(cur, left, "r");
45646d1a925SRobert Watson if (len < 0 || len > left)
45746d1a925SRobert Watson goto truncated;
45846d1a925SRobert Watson
45946d1a925SRobert Watson left -= len;
46046d1a925SRobert Watson cur += len;
46146d1a925SRobert Watson }
462f4194603SRobert Watson if (rule->mbr_mode & MBI_STAT) {
46346d1a925SRobert Watson len = snprintf(cur, left, "s");
46446d1a925SRobert Watson if (len < 0 || len > left)
46546d1a925SRobert Watson goto truncated;
46646d1a925SRobert Watson
46746d1a925SRobert Watson left -= len;
46846d1a925SRobert Watson cur += len;
46946d1a925SRobert Watson }
470f4194603SRobert Watson if (rule->mbr_mode & MBI_WRITE) {
47146d1a925SRobert Watson len = snprintf(cur, left, "w");
47246d1a925SRobert Watson if (len < 0 || len > left)
47346d1a925SRobert Watson goto truncated;
47446d1a925SRobert Watson
47546d1a925SRobert Watson left -= len;
47646d1a925SRobert Watson cur += len;
47746d1a925SRobert Watson }
478f4194603SRobert Watson if (rule->mbr_mode & MBI_EXEC) {
47946d1a925SRobert Watson len = snprintf(cur, left, "x");
48046d1a925SRobert Watson if (len < 0 || len > left)
48146d1a925SRobert Watson goto truncated;
48246d1a925SRobert Watson
48346d1a925SRobert Watson left -= len;
48446d1a925SRobert Watson cur += len;
48546d1a925SRobert Watson }
48646d1a925SRobert Watson if (!anymode) {
48746d1a925SRobert Watson len = snprintf(cur, left, "n");
48846d1a925SRobert Watson if (len < 0 || len > left)
48946d1a925SRobert Watson goto truncated;
49046d1a925SRobert Watson
49146d1a925SRobert Watson left -= len;
49246d1a925SRobert Watson cur += len;
49346d1a925SRobert Watson }
49446d1a925SRobert Watson if (unknownmode) {
49546d1a925SRobert Watson len = snprintf(cur, left, "?");
49646d1a925SRobert Watson if (len < 0 || len > left)
49746d1a925SRobert Watson goto truncated;
49846d1a925SRobert Watson
49946d1a925SRobert Watson left -= len;
50046d1a925SRobert Watson cur += len;
50146d1a925SRobert Watson }
50246d1a925SRobert Watson
50346d1a925SRobert Watson return (0);
50446d1a925SRobert Watson
50546d1a925SRobert Watson truncated:
50646d1a925SRobert Watson return (-1);
50746d1a925SRobert Watson }
50846d1a925SRobert Watson
509bf417062SMarcelo Araujo static int
bsde_parse_uidrange(char * spec,uid_t * min,uid_t * max,size_t buflen,char * errstr)51089ddbd45SDavid Malone bsde_parse_uidrange(char *spec, uid_t *min, uid_t *max,
51189ddbd45SDavid Malone size_t buflen, char *errstr){
51246d1a925SRobert Watson struct passwd *pwd;
51389ddbd45SDavid Malone uid_t uid1, uid2;
51489ddbd45SDavid Malone char *spec1, *spec2, *endp;
51589ddbd45SDavid Malone unsigned long value;
51646d1a925SRobert Watson
51789ddbd45SDavid Malone spec2 = spec;
51889ddbd45SDavid Malone spec1 = strsep(&spec2, ":");
51989ddbd45SDavid Malone
52089ddbd45SDavid Malone pwd = getpwnam(spec1);
52189ddbd45SDavid Malone if (pwd != NULL)
52289ddbd45SDavid Malone uid1 = pwd->pw_uid;
52389ddbd45SDavid Malone else {
52489ddbd45SDavid Malone value = strtoul(spec1, &endp, 10);
52589ddbd45SDavid Malone if (*endp != '\0') {
526df6a67d6SEnji Cooper snprintf(errstr, buflen, "invalid uid: '%s'", spec1);
52746d1a925SRobert Watson return (-1);
52846d1a925SRobert Watson }
52989ddbd45SDavid Malone uid1 = value;
53089ddbd45SDavid Malone }
53189ddbd45SDavid Malone
53289ddbd45SDavid Malone if (spec2 == NULL) {
53389ddbd45SDavid Malone *max = *min = uid1;
53489ddbd45SDavid Malone return (0);
53589ddbd45SDavid Malone }
53689ddbd45SDavid Malone
53789ddbd45SDavid Malone pwd = getpwnam(spec2);
53889ddbd45SDavid Malone if (pwd != NULL)
53989ddbd45SDavid Malone uid2 = pwd->pw_uid;
54089ddbd45SDavid Malone else {
54189ddbd45SDavid Malone value = strtoul(spec2, &endp, 10);
54289ddbd45SDavid Malone if (*endp != '\0') {
543df6a67d6SEnji Cooper snprintf(errstr, buflen, "invalid uid: '%s'", spec2);
54489ddbd45SDavid Malone return (-1);
54589ddbd45SDavid Malone }
54689ddbd45SDavid Malone uid2 = value;
54789ddbd45SDavid Malone }
54889ddbd45SDavid Malone
54989ddbd45SDavid Malone *min = uid1;
55089ddbd45SDavid Malone *max = uid2;
55189ddbd45SDavid Malone
55289ddbd45SDavid Malone return (0);
55389ddbd45SDavid Malone }
55489ddbd45SDavid Malone
555bf417062SMarcelo Araujo static int
bsde_parse_gidrange(char * spec,gid_t * min,gid_t * max,size_t buflen,char * errstr)55689ddbd45SDavid Malone bsde_parse_gidrange(char *spec, gid_t *min, gid_t *max,
55789ddbd45SDavid Malone size_t buflen, char *errstr){
55889ddbd45SDavid Malone struct group *grp;
55989ddbd45SDavid Malone gid_t gid1, gid2;
56089ddbd45SDavid Malone char *spec1, *spec2, *endp;
56189ddbd45SDavid Malone unsigned long value;
56289ddbd45SDavid Malone
56389ddbd45SDavid Malone spec2 = spec;
56489ddbd45SDavid Malone spec1 = strsep(&spec2, ":");
56589ddbd45SDavid Malone
56689ddbd45SDavid Malone grp = getgrnam(spec1);
56789ddbd45SDavid Malone if (grp != NULL)
56889ddbd45SDavid Malone gid1 = grp->gr_gid;
56989ddbd45SDavid Malone else {
57089ddbd45SDavid Malone value = strtoul(spec1, &endp, 10);
57189ddbd45SDavid Malone if (*endp != '\0') {
572df6a67d6SEnji Cooper snprintf(errstr, buflen, "invalid gid: '%s'", spec1);
57389ddbd45SDavid Malone return (-1);
57489ddbd45SDavid Malone }
57589ddbd45SDavid Malone gid1 = value;
57689ddbd45SDavid Malone }
57789ddbd45SDavid Malone
57889ddbd45SDavid Malone if (spec2 == NULL) {
57989ddbd45SDavid Malone *max = *min = gid1;
58089ddbd45SDavid Malone return (0);
58189ddbd45SDavid Malone }
58289ddbd45SDavid Malone
58389ddbd45SDavid Malone grp = getgrnam(spec2);
58489ddbd45SDavid Malone if (grp != NULL)
58589ddbd45SDavid Malone gid2 = grp->gr_gid;
58689ddbd45SDavid Malone else {
58789ddbd45SDavid Malone value = strtoul(spec2, &endp, 10);
58889ddbd45SDavid Malone if (*endp != '\0') {
589df6a67d6SEnji Cooper snprintf(errstr, buflen, "invalid gid: '%s'", spec2);
59089ddbd45SDavid Malone return (-1);
59189ddbd45SDavid Malone }
59289ddbd45SDavid Malone gid2 = value;
59389ddbd45SDavid Malone }
59489ddbd45SDavid Malone
59589ddbd45SDavid Malone *min = gid1;
59689ddbd45SDavid Malone *max = gid2;
59789ddbd45SDavid Malone
59889ddbd45SDavid Malone return (0);
59989ddbd45SDavid Malone }
60089ddbd45SDavid Malone
601bf417062SMarcelo Araujo static int
bsde_get_jailid(const char * name,size_t buflen,char * errstr)602de68a320SJamie Gritton bsde_get_jailid(const char *name, size_t buflen, char *errstr)
603de68a320SJamie Gritton {
604de68a320SJamie Gritton char *ep;
605de68a320SJamie Gritton int jid;
606de68a320SJamie Gritton struct iovec jiov[4];
607de68a320SJamie Gritton
608de68a320SJamie Gritton /* Copy jail_getid(3) instead of messing with library dependancies */
609de68a320SJamie Gritton jid = strtoul(name, &ep, 10);
610de68a320SJamie Gritton if (*name && !*ep)
611de68a320SJamie Gritton return jid;
612de68a320SJamie Gritton jiov[0].iov_base = __DECONST(char *, "name");
613de68a320SJamie Gritton jiov[0].iov_len = sizeof("name");
614de68a320SJamie Gritton jiov[1].iov_len = strlen(name) + 1;
615de68a320SJamie Gritton jiov[1].iov_base = alloca(jiov[1].iov_len);
616de68a320SJamie Gritton strcpy(jiov[1].iov_base, name);
617de68a320SJamie Gritton if (errstr && buflen) {
618de68a320SJamie Gritton jiov[2].iov_base = __DECONST(char *, "errmsg");
619de68a320SJamie Gritton jiov[2].iov_len = sizeof("errmsg");
620de68a320SJamie Gritton jiov[3].iov_base = errstr;
621de68a320SJamie Gritton jiov[3].iov_len = buflen;
622de68a320SJamie Gritton errstr[0] = 0;
623de68a320SJamie Gritton jid = jail_get(jiov, 4, 0);
624de68a320SJamie Gritton if (jid < 0 && !errstr[0])
625de68a320SJamie Gritton snprintf(errstr, buflen, "jail_get: %s",
626de68a320SJamie Gritton strerror(errno));
627de68a320SJamie Gritton } else
628de68a320SJamie Gritton jid = jail_get(jiov, 2, 0);
629de68a320SJamie Gritton return jid;
630de68a320SJamie Gritton }
631de68a320SJamie Gritton
632de68a320SJamie Gritton static int
bsde_parse_subject(int argc,char * argv[],struct mac_bsdextended_subject * subject,size_t buflen,char * errstr)63389ddbd45SDavid Malone bsde_parse_subject(int argc, char *argv[],
63489ddbd45SDavid Malone struct mac_bsdextended_subject *subject, size_t buflen, char *errstr)
63589ddbd45SDavid Malone {
63689ddbd45SDavid Malone int not_seen, flags;
63789ddbd45SDavid Malone int current, neg, nextnot;
63889ddbd45SDavid Malone uid_t uid_min, uid_max;
63989ddbd45SDavid Malone gid_t gid_min, gid_max;
640bf417062SMarcelo Araujo int jid = 0;
64146d1a925SRobert Watson
64246d1a925SRobert Watson current = 0;
64389ddbd45SDavid Malone flags = 0;
64489ddbd45SDavid Malone neg = 0;
64589ddbd45SDavid Malone nextnot = 0;
64646d1a925SRobert Watson
64789ddbd45SDavid Malone if (strcmp("not", argv[current]) == 0) {
64846d1a925SRobert Watson not_seen = 1;
64946d1a925SRobert Watson current++;
65046d1a925SRobert Watson } else
65146d1a925SRobert Watson not_seen = 0;
65246d1a925SRobert Watson
65389ddbd45SDavid Malone while (current < argc) {
65489ddbd45SDavid Malone if (strcmp(argv[current], "uid") == 0) {
65546d1a925SRobert Watson if (current + 2 > argc) {
656df6a67d6SEnji Cooper snprintf(errstr, buflen, "uid short");
65746d1a925SRobert Watson return (-1);
65846d1a925SRobert Watson }
65989ddbd45SDavid Malone if (flags & MBS_UID_DEFINED) {
660df6a67d6SEnji Cooper snprintf(errstr, buflen, "one uid only");
66146d1a925SRobert Watson return (-1);
66246d1a925SRobert Watson }
66389ddbd45SDavid Malone if (bsde_parse_uidrange(argv[current+1],
66489ddbd45SDavid Malone &uid_min, &uid_max, buflen, errstr) < 0)
66589ddbd45SDavid Malone return (-1);
66689ddbd45SDavid Malone flags |= MBS_UID_DEFINED;
66789ddbd45SDavid Malone if (nextnot) {
66889ddbd45SDavid Malone neg ^= MBS_UID_DEFINED;
66989ddbd45SDavid Malone nextnot = 0;
67046d1a925SRobert Watson }
67146d1a925SRobert Watson current += 2;
67289ddbd45SDavid Malone } else if (strcmp(argv[current], "gid") == 0) {
67346d1a925SRobert Watson if (current + 2 > argc) {
674df6a67d6SEnji Cooper snprintf(errstr, buflen, "gid short");
67546d1a925SRobert Watson return (-1);
67646d1a925SRobert Watson }
67789ddbd45SDavid Malone if (flags & MBS_GID_DEFINED) {
678df6a67d6SEnji Cooper snprintf(errstr, buflen, "one gid only");
67946d1a925SRobert Watson return (-1);
68046d1a925SRobert Watson }
68189ddbd45SDavid Malone if (bsde_parse_gidrange(argv[current+1],
68289ddbd45SDavid Malone &gid_min, &gid_max, buflen, errstr) < 0)
68389ddbd45SDavid Malone return (-1);
68489ddbd45SDavid Malone flags |= MBS_GID_DEFINED;
68589ddbd45SDavid Malone if (nextnot) {
68689ddbd45SDavid Malone neg ^= MBS_GID_DEFINED;
68789ddbd45SDavid Malone nextnot = 0;
68846d1a925SRobert Watson }
68946d1a925SRobert Watson current += 2;
69089ddbd45SDavid Malone } else if (strcmp(argv[current], "jailid") == 0) {
69146d1a925SRobert Watson if (current + 2 > argc) {
692df6a67d6SEnji Cooper snprintf(errstr, buflen, "prison short");
69346d1a925SRobert Watson return (-1);
69446d1a925SRobert Watson }
69589ddbd45SDavid Malone if (flags & MBS_PRISON_DEFINED) {
696df6a67d6SEnji Cooper snprintf(errstr, buflen, "one jail only");
69789ddbd45SDavid Malone return (-1);
69889ddbd45SDavid Malone }
699de68a320SJamie Gritton jid = bsde_get_jailid(argv[current+1], buflen, errstr);
700de68a320SJamie Gritton if (jid < 0)
70146d1a925SRobert Watson return (-1);
70289ddbd45SDavid Malone flags |= MBS_PRISON_DEFINED;
70389ddbd45SDavid Malone if (nextnot) {
70489ddbd45SDavid Malone neg ^= MBS_PRISON_DEFINED;
70589ddbd45SDavid Malone nextnot = 0;
706a6c2bc8bSRobert Watson }
70746d1a925SRobert Watson current += 2;
70889ddbd45SDavid Malone } else if (strcmp(argv[current], "!") == 0) {
70989ddbd45SDavid Malone if (nextnot) {
710df6a67d6SEnji Cooper snprintf(errstr, buflen, "double negative");
71146d1a925SRobert Watson return (-1);
71246d1a925SRobert Watson }
71389ddbd45SDavid Malone nextnot = 1;
71489ddbd45SDavid Malone current += 1;
71546d1a925SRobert Watson } else {
716df6a67d6SEnji Cooper snprintf(errstr, buflen, "'%s' not expected",
71746d1a925SRobert Watson argv[current]);
71846d1a925SRobert Watson return (-1);
71946d1a925SRobert Watson }
72046d1a925SRobert Watson }
72146d1a925SRobert Watson
72289ddbd45SDavid Malone subject->mbs_flags = flags;
72346d1a925SRobert Watson if (not_seen)
72489ddbd45SDavid Malone subject->mbs_neg = MBS_ALL_FLAGS ^ neg;
72589ddbd45SDavid Malone else
72689ddbd45SDavid Malone subject->mbs_neg = neg;
72789ddbd45SDavid Malone if (flags & MBS_UID_DEFINED) {
72889ddbd45SDavid Malone subject->mbs_uid_min = uid_min;
72989ddbd45SDavid Malone subject->mbs_uid_max = uid_max;
73089ddbd45SDavid Malone }
73189ddbd45SDavid Malone if (flags & MBS_GID_DEFINED) {
73289ddbd45SDavid Malone subject->mbs_gid_min = gid_min;
73389ddbd45SDavid Malone subject->mbs_gid_max = gid_max;
73489ddbd45SDavid Malone }
73589ddbd45SDavid Malone if (flags & MBS_PRISON_DEFINED)
73689ddbd45SDavid Malone subject->mbs_prison = jid;
73746d1a925SRobert Watson
73889ddbd45SDavid Malone return (0);
73989ddbd45SDavid Malone }
74046d1a925SRobert Watson
741bf417062SMarcelo Araujo static int
bsde_parse_type(char * spec,int * type,size_t buflen,char * errstr)74289ddbd45SDavid Malone bsde_parse_type(char *spec, int *type, size_t buflen, char *errstr)
74389ddbd45SDavid Malone {
74489ddbd45SDavid Malone int i;
74589ddbd45SDavid Malone
74689ddbd45SDavid Malone *type = 0;
74789ddbd45SDavid Malone for (i = 0; i < strlen(spec); i++) {
74889ddbd45SDavid Malone switch (spec[i]) {
74989ddbd45SDavid Malone case 'r':
75089ddbd45SDavid Malone case '-':
75189ddbd45SDavid Malone *type |= MBO_TYPE_REG;
75289ddbd45SDavid Malone break;
75389ddbd45SDavid Malone case 'd':
75489ddbd45SDavid Malone *type |= MBO_TYPE_DIR;
75589ddbd45SDavid Malone break;
75689ddbd45SDavid Malone case 'b':
75789ddbd45SDavid Malone *type |= MBO_TYPE_BLK;
75889ddbd45SDavid Malone break;
75989ddbd45SDavid Malone case 'c':
76089ddbd45SDavid Malone *type |= MBO_TYPE_CHR;
76189ddbd45SDavid Malone break;
76289ddbd45SDavid Malone case 'l':
76389ddbd45SDavid Malone *type |= MBO_TYPE_LNK;
76489ddbd45SDavid Malone break;
76589ddbd45SDavid Malone case 's':
76689ddbd45SDavid Malone *type |= MBO_TYPE_SOCK;
76789ddbd45SDavid Malone break;
76889ddbd45SDavid Malone case 'p':
76989ddbd45SDavid Malone *type |= MBO_TYPE_FIFO;
77089ddbd45SDavid Malone break;
77189ddbd45SDavid Malone case 'a':
77289ddbd45SDavid Malone *type |= MBO_ALL_TYPE;
77389ddbd45SDavid Malone break;
77489ddbd45SDavid Malone default:
775df6a67d6SEnji Cooper snprintf(errstr, buflen, "Unknown type code: %c",
77689ddbd45SDavid Malone spec[i]);
77789ddbd45SDavid Malone return (-1);
77889ddbd45SDavid Malone }
77989ddbd45SDavid Malone }
78089ddbd45SDavid Malone
78189ddbd45SDavid Malone return (0);
78289ddbd45SDavid Malone }
78389ddbd45SDavid Malone
784bf417062SMarcelo Araujo static int
bsde_parse_fsid(char * spec,struct fsid * fsid,size_t buflen,char * errstr)78589ddbd45SDavid Malone bsde_parse_fsid(char *spec, struct fsid *fsid, size_t buflen, char *errstr)
78689ddbd45SDavid Malone {
78789ddbd45SDavid Malone struct statfs buf;
78889ddbd45SDavid Malone
78989ddbd45SDavid Malone if (statfs(spec, &buf) < 0) {
790df6a67d6SEnji Cooper snprintf(errstr, buflen, "Unable to get id for %s: %s",
79189ddbd45SDavid Malone spec, strerror(errno));
79289ddbd45SDavid Malone return (-1);
79389ddbd45SDavid Malone }
79489ddbd45SDavid Malone
79589ddbd45SDavid Malone *fsid = buf.f_fsid;
79689ddbd45SDavid Malone
79789ddbd45SDavid Malone return (0);
79889ddbd45SDavid Malone }
79989ddbd45SDavid Malone
800bf417062SMarcelo Araujo static int
bsde_parse_object(int argc,char * argv[],struct mac_bsdextended_object * object,size_t buflen,char * errstr)80189ddbd45SDavid Malone bsde_parse_object(int argc, char *argv[],
80289ddbd45SDavid Malone struct mac_bsdextended_object *object, size_t buflen, char *errstr)
80389ddbd45SDavid Malone {
80489ddbd45SDavid Malone int not_seen, flags;
80589ddbd45SDavid Malone int current, neg, nextnot;
806bf417062SMarcelo Araujo int type;
80789ddbd45SDavid Malone uid_t uid_min, uid_max;
80889ddbd45SDavid Malone gid_t gid_min, gid_max;
80989ddbd45SDavid Malone struct fsid fsid;
81089ddbd45SDavid Malone
81189ddbd45SDavid Malone current = 0;
81289ddbd45SDavid Malone flags = 0;
81389ddbd45SDavid Malone neg = 0;
81489ddbd45SDavid Malone nextnot = 0;
815bf417062SMarcelo Araujo type = 0;
81689ddbd45SDavid Malone
81789ddbd45SDavid Malone if (strcmp("not", argv[current]) == 0) {
81889ddbd45SDavid Malone not_seen = 1;
81989ddbd45SDavid Malone current++;
82046d1a925SRobert Watson } else
82189ddbd45SDavid Malone not_seen = 0;
82289ddbd45SDavid Malone
82389ddbd45SDavid Malone while (current < argc) {
82489ddbd45SDavid Malone if (strcmp(argv[current], "uid") == 0) {
82589ddbd45SDavid Malone if (current + 2 > argc) {
826df6a67d6SEnji Cooper snprintf(errstr, buflen, "uid short");
82789ddbd45SDavid Malone return (-1);
82889ddbd45SDavid Malone }
82989ddbd45SDavid Malone if (flags & MBO_UID_DEFINED) {
830df6a67d6SEnji Cooper snprintf(errstr, buflen, "one uid only");
83189ddbd45SDavid Malone return (-1);
83289ddbd45SDavid Malone }
83389ddbd45SDavid Malone if (bsde_parse_uidrange(argv[current+1],
83489ddbd45SDavid Malone &uid_min, &uid_max, buflen, errstr) < 0)
83589ddbd45SDavid Malone return (-1);
83689ddbd45SDavid Malone flags |= MBO_UID_DEFINED;
83789ddbd45SDavid Malone if (nextnot) {
83889ddbd45SDavid Malone neg ^= MBO_UID_DEFINED;
83989ddbd45SDavid Malone nextnot = 0;
84089ddbd45SDavid Malone }
84189ddbd45SDavid Malone current += 2;
84289ddbd45SDavid Malone } else if (strcmp(argv[current], "gid") == 0) {
84389ddbd45SDavid Malone if (current + 2 > argc) {
844df6a67d6SEnji Cooper snprintf(errstr, buflen, "gid short");
84589ddbd45SDavid Malone return (-1);
84689ddbd45SDavid Malone }
84789ddbd45SDavid Malone if (flags & MBO_GID_DEFINED) {
848df6a67d6SEnji Cooper snprintf(errstr, buflen, "one gid only");
84989ddbd45SDavid Malone return (-1);
85089ddbd45SDavid Malone }
85189ddbd45SDavid Malone if (bsde_parse_gidrange(argv[current+1],
85289ddbd45SDavid Malone &gid_min, &gid_max, buflen, errstr) < 0)
85389ddbd45SDavid Malone return (-1);
85489ddbd45SDavid Malone flags |= MBO_GID_DEFINED;
85589ddbd45SDavid Malone if (nextnot) {
85689ddbd45SDavid Malone neg ^= MBO_GID_DEFINED;
85789ddbd45SDavid Malone nextnot = 0;
85889ddbd45SDavid Malone }
85989ddbd45SDavid Malone current += 2;
86089ddbd45SDavid Malone } else if (strcmp(argv[current], "filesys") == 0) {
86189ddbd45SDavid Malone if (current + 2 > argc) {
862df6a67d6SEnji Cooper snprintf(errstr, buflen, "filesys short");
86389ddbd45SDavid Malone return (-1);
86489ddbd45SDavid Malone }
86589ddbd45SDavid Malone if (flags & MBO_FSID_DEFINED) {
866df6a67d6SEnji Cooper snprintf(errstr, buflen, "one fsid only");
86789ddbd45SDavid Malone return (-1);
86889ddbd45SDavid Malone }
86989ddbd45SDavid Malone if (bsde_parse_fsid(argv[current+1], &fsid,
87089ddbd45SDavid Malone buflen, errstr) < 0)
87189ddbd45SDavid Malone return (-1);
87289ddbd45SDavid Malone flags |= MBO_FSID_DEFINED;
87389ddbd45SDavid Malone if (nextnot) {
87489ddbd45SDavid Malone neg ^= MBO_FSID_DEFINED;
87589ddbd45SDavid Malone nextnot = 0;
87689ddbd45SDavid Malone }
87789ddbd45SDavid Malone current += 2;
87889ddbd45SDavid Malone } else if (strcmp(argv[current], "suid") == 0) {
87989ddbd45SDavid Malone flags |= MBO_SUID;
88089ddbd45SDavid Malone if (nextnot) {
88189ddbd45SDavid Malone neg ^= MBO_SUID;
88289ddbd45SDavid Malone nextnot = 0;
88389ddbd45SDavid Malone }
88489ddbd45SDavid Malone current += 1;
88589ddbd45SDavid Malone } else if (strcmp(argv[current], "sgid") == 0) {
88689ddbd45SDavid Malone flags |= MBO_SGID;
88789ddbd45SDavid Malone if (nextnot) {
88889ddbd45SDavid Malone neg ^= MBO_SGID;
88989ddbd45SDavid Malone nextnot = 0;
89089ddbd45SDavid Malone }
89189ddbd45SDavid Malone current += 1;
89289ddbd45SDavid Malone } else if (strcmp(argv[current], "uid_of_subject") == 0) {
89389ddbd45SDavid Malone flags |= MBO_UID_SUBJECT;
89489ddbd45SDavid Malone if (nextnot) {
89589ddbd45SDavid Malone neg ^= MBO_UID_SUBJECT;
89689ddbd45SDavid Malone nextnot = 0;
89789ddbd45SDavid Malone }
89889ddbd45SDavid Malone current += 1;
89989ddbd45SDavid Malone } else if (strcmp(argv[current], "gid_of_subject") == 0) {
90089ddbd45SDavid Malone flags |= MBO_GID_SUBJECT;
90189ddbd45SDavid Malone if (nextnot) {
90289ddbd45SDavid Malone neg ^= MBO_GID_SUBJECT;
90389ddbd45SDavid Malone nextnot = 0;
90489ddbd45SDavid Malone }
90589ddbd45SDavid Malone current += 1;
90689ddbd45SDavid Malone } else if (strcmp(argv[current], "type") == 0) {
90789ddbd45SDavid Malone if (current + 2 > argc) {
908df6a67d6SEnji Cooper snprintf(errstr, buflen, "type short");
90989ddbd45SDavid Malone return (-1);
91089ddbd45SDavid Malone }
91189ddbd45SDavid Malone if (flags & MBO_TYPE_DEFINED) {
912df6a67d6SEnji Cooper snprintf(errstr, buflen, "one type only");
91389ddbd45SDavid Malone return (-1);
91489ddbd45SDavid Malone }
91589ddbd45SDavid Malone if (bsde_parse_type(argv[current+1], &type,
91689ddbd45SDavid Malone buflen, errstr) < 0)
91789ddbd45SDavid Malone return (-1);
91889ddbd45SDavid Malone flags |= MBO_TYPE_DEFINED;
91989ddbd45SDavid Malone if (nextnot) {
92089ddbd45SDavid Malone neg ^= MBO_TYPE_DEFINED;
92189ddbd45SDavid Malone nextnot = 0;
92289ddbd45SDavid Malone }
92389ddbd45SDavid Malone current += 2;
92489ddbd45SDavid Malone } else if (strcmp(argv[current], "!") == 0) {
92589ddbd45SDavid Malone if (nextnot) {
926df6a67d6SEnji Cooper snprintf(errstr, buflen,
92789ddbd45SDavid Malone "double negative'");
92889ddbd45SDavid Malone return (-1);
92989ddbd45SDavid Malone }
93089ddbd45SDavid Malone nextnot = 1;
93189ddbd45SDavid Malone current += 1;
93289ddbd45SDavid Malone } else {
933df6a67d6SEnji Cooper snprintf(errstr, buflen, "'%s' not expected",
93489ddbd45SDavid Malone argv[current]);
93589ddbd45SDavid Malone return (-1);
93689ddbd45SDavid Malone }
93789ddbd45SDavid Malone }
93889ddbd45SDavid Malone
93989ddbd45SDavid Malone object->mbo_flags = flags;
94089ddbd45SDavid Malone if (not_seen)
94189ddbd45SDavid Malone object->mbo_neg = MBO_ALL_FLAGS ^ neg;
94289ddbd45SDavid Malone else
94389ddbd45SDavid Malone object->mbo_neg = neg;
94489ddbd45SDavid Malone if (flags & MBO_UID_DEFINED) {
94589ddbd45SDavid Malone object->mbo_uid_min = uid_min;
94689ddbd45SDavid Malone object->mbo_uid_max = uid_max;
94789ddbd45SDavid Malone }
94889ddbd45SDavid Malone if (flags & MBO_GID_DEFINED) {
94989ddbd45SDavid Malone object->mbo_gid_min = gid_min;
95089ddbd45SDavid Malone object->mbo_gid_max = gid_max;
95189ddbd45SDavid Malone }
95289ddbd45SDavid Malone if (flags & MBO_FSID_DEFINED)
95389ddbd45SDavid Malone object->mbo_fsid = fsid;
95489ddbd45SDavid Malone if (flags & MBO_TYPE_DEFINED)
95589ddbd45SDavid Malone object->mbo_type = type;
95646d1a925SRobert Watson
95746d1a925SRobert Watson return (0);
95846d1a925SRobert Watson }
95946d1a925SRobert Watson
96046d1a925SRobert Watson int
bsde_parse_mode(int argc,char * argv[],mode_t * mode,size_t buflen,char * errstr)96146d1a925SRobert Watson bsde_parse_mode(int argc, char *argv[], mode_t *mode, size_t buflen,
96246d1a925SRobert Watson char *errstr)
96346d1a925SRobert Watson {
96446d1a925SRobert Watson int i;
96546d1a925SRobert Watson
96646d1a925SRobert Watson if (argc == 0) {
967df6a67d6SEnji Cooper snprintf(errstr, buflen, "mode expects mode value");
96846d1a925SRobert Watson return (-1);
96946d1a925SRobert Watson }
97046d1a925SRobert Watson
97146d1a925SRobert Watson if (argc != 1) {
972df6a67d6SEnji Cooper snprintf(errstr, buflen, "'%s' unexpected", argv[1]);
97346d1a925SRobert Watson return (-1);
97446d1a925SRobert Watson }
97546d1a925SRobert Watson
97646d1a925SRobert Watson *mode = 0;
97746d1a925SRobert Watson for (i = 0; i < strlen(argv[0]); i++) {
97846d1a925SRobert Watson switch (argv[0][i]) {
97946d1a925SRobert Watson case 'a':
980f4194603SRobert Watson *mode |= MBI_ADMIN;
98146d1a925SRobert Watson break;
98246d1a925SRobert Watson case 'r':
983f4194603SRobert Watson *mode |= MBI_READ;
98446d1a925SRobert Watson break;
98546d1a925SRobert Watson case 's':
986f4194603SRobert Watson *mode |= MBI_STAT;
98746d1a925SRobert Watson break;
98846d1a925SRobert Watson case 'w':
989f4194603SRobert Watson *mode |= MBI_WRITE;
99046d1a925SRobert Watson break;
99146d1a925SRobert Watson case 'x':
992f4194603SRobert Watson *mode |= MBI_EXEC;
99346d1a925SRobert Watson break;
99446d1a925SRobert Watson case 'n':
99546d1a925SRobert Watson /* ignore */
99646d1a925SRobert Watson break;
99746d1a925SRobert Watson default:
998df6a67d6SEnji Cooper snprintf(errstr, buflen, "Unknown mode letter: %c",
99946d1a925SRobert Watson argv[0][i]);
100046d1a925SRobert Watson return (-1);
100146d1a925SRobert Watson }
100246d1a925SRobert Watson }
100346d1a925SRobert Watson
100446d1a925SRobert Watson return (0);
100546d1a925SRobert Watson }
100646d1a925SRobert Watson
100746d1a925SRobert Watson int
bsde_parse_rule(int argc,char * argv[],struct mac_bsdextended_rule * rule,size_t buflen,char * errstr)100846d1a925SRobert Watson bsde_parse_rule(int argc, char *argv[], struct mac_bsdextended_rule *rule,
100946d1a925SRobert Watson size_t buflen, char *errstr)
101046d1a925SRobert Watson {
101146d1a925SRobert Watson int subject, subject_elements, subject_elements_length;
101246d1a925SRobert Watson int object, object_elements, object_elements_length;
101346d1a925SRobert Watson int mode, mode_elements, mode_elements_length;
101446d1a925SRobert Watson int error, i;
101546d1a925SRobert Watson
101646d1a925SRobert Watson bzero(rule, sizeof(*rule));
101746d1a925SRobert Watson
101846d1a925SRobert Watson if (argc < 1) {
1019df6a67d6SEnji Cooper snprintf(errstr, buflen, "Rule must begin with subject");
102046d1a925SRobert Watson return (-1);
102146d1a925SRobert Watson }
102246d1a925SRobert Watson
102346d1a925SRobert Watson if (strcmp(argv[0], "subject") != 0) {
1024df6a67d6SEnji Cooper snprintf(errstr, buflen, "Rule must begin with subject");
102546d1a925SRobert Watson return (-1);
102646d1a925SRobert Watson }
102746d1a925SRobert Watson subject = 0;
102846d1a925SRobert Watson subject_elements = 1;
102946d1a925SRobert Watson
103046d1a925SRobert Watson /* Search forward for object. */
103146d1a925SRobert Watson
103246d1a925SRobert Watson object = -1;
103346d1a925SRobert Watson for (i = 1; i < argc; i++)
103446d1a925SRobert Watson if (strcmp(argv[i], "object") == 0)
103546d1a925SRobert Watson object = i;
103646d1a925SRobert Watson
103746d1a925SRobert Watson if (object == -1) {
1038df6a67d6SEnji Cooper snprintf(errstr, buflen, "Rule must contain an object");
103946d1a925SRobert Watson return (-1);
104046d1a925SRobert Watson }
104146d1a925SRobert Watson
104246d1a925SRobert Watson /* Search forward for mode. */
104346d1a925SRobert Watson mode = -1;
104446d1a925SRobert Watson for (i = object; i < argc; i++)
104546d1a925SRobert Watson if (strcmp(argv[i], "mode") == 0)
104646d1a925SRobert Watson mode = i;
104746d1a925SRobert Watson
104846d1a925SRobert Watson if (mode == -1) {
1049df6a67d6SEnji Cooper snprintf(errstr, buflen, "Rule must contain mode");
105046d1a925SRobert Watson return (-1);
105146d1a925SRobert Watson }
105246d1a925SRobert Watson
105346d1a925SRobert Watson subject_elements_length = object - subject - 1;
105446d1a925SRobert Watson object_elements = object + 1;
105546d1a925SRobert Watson object_elements_length = mode - object_elements;
105646d1a925SRobert Watson mode_elements = mode + 1;
105746d1a925SRobert Watson mode_elements_length = argc - mode_elements;
105846d1a925SRobert Watson
105989ddbd45SDavid Malone error = bsde_parse_subject(subject_elements_length,
106046d1a925SRobert Watson argv + subject_elements, &rule->mbr_subject, buflen, errstr);
106146d1a925SRobert Watson if (error)
106246d1a925SRobert Watson return (-1);
106346d1a925SRobert Watson
106489ddbd45SDavid Malone error = bsde_parse_object(object_elements_length,
106546d1a925SRobert Watson argv + object_elements, &rule->mbr_object, buflen, errstr);
106646d1a925SRobert Watson if (error)
106746d1a925SRobert Watson return (-1);
106846d1a925SRobert Watson
106946d1a925SRobert Watson error = bsde_parse_mode(mode_elements_length, argv + mode_elements,
107046d1a925SRobert Watson &rule->mbr_mode, buflen, errstr);
107146d1a925SRobert Watson if (error)
107246d1a925SRobert Watson return (-1);
107346d1a925SRobert Watson
107446d1a925SRobert Watson return (0);
107546d1a925SRobert Watson }
107646d1a925SRobert Watson
107746d1a925SRobert Watson int
bsde_parse_rule_string(const char * string,struct mac_bsdextended_rule * rule,size_t buflen,char * errstr)107846d1a925SRobert Watson bsde_parse_rule_string(const char *string, struct mac_bsdextended_rule *rule,
107946d1a925SRobert Watson size_t buflen, char *errstr)
108046d1a925SRobert Watson {
108189ddbd45SDavid Malone char *stringdup, *stringp, *argv[100], **ap;
108246d1a925SRobert Watson int argc, error;
108346d1a925SRobert Watson
108446d1a925SRobert Watson stringp = stringdup = strdup(string);
108546d1a925SRobert Watson while (*stringp == ' ' || *stringp == '\t')
108646d1a925SRobert Watson stringp++;
108746d1a925SRobert Watson
108846d1a925SRobert Watson argc = 0;
108946d1a925SRobert Watson for (ap = argv; (*ap = strsep(&stringp, " \t")) != NULL;) {
109046d1a925SRobert Watson argc++;
109146d1a925SRobert Watson if (**ap != '\0')
109289ddbd45SDavid Malone if (++ap >= &argv[100])
109346d1a925SRobert Watson break;
109446d1a925SRobert Watson }
109546d1a925SRobert Watson
109646d1a925SRobert Watson error = bsde_parse_rule(argc, argv, rule, buflen, errstr);
109746d1a925SRobert Watson
109846d1a925SRobert Watson free(stringdup);
109946d1a925SRobert Watson
110046d1a925SRobert Watson return (error);
110146d1a925SRobert Watson }
110246d1a925SRobert Watson
110346d1a925SRobert Watson int
bsde_get_mib(const char * string,int * name,size_t * namelen)1104da30581eSRobert Watson bsde_get_mib(const char *string, int *name, size_t *namelen)
110546d1a925SRobert Watson {
1106da30581eSRobert Watson size_t len;
1107da30581eSRobert Watson int error;
110846d1a925SRobert Watson
110946d1a925SRobert Watson len = *namelen;
111046d1a925SRobert Watson error = sysctlnametomib(string, name, &len);
111146d1a925SRobert Watson if (error)
111246d1a925SRobert Watson return (error);
111346d1a925SRobert Watson
111446d1a925SRobert Watson *namelen = len;
111546d1a925SRobert Watson return (0);
111646d1a925SRobert Watson }
111746d1a925SRobert Watson
1118bf417062SMarcelo Araujo static int
bsde_check_version(size_t buflen,char * errstr)111989ddbd45SDavid Malone bsde_check_version(size_t buflen, char *errstr)
112089ddbd45SDavid Malone {
112189ddbd45SDavid Malone size_t len;
112289ddbd45SDavid Malone int error;
112389ddbd45SDavid Malone int version;
112489ddbd45SDavid Malone
112589ddbd45SDavid Malone len = sizeof(version);
112689ddbd45SDavid Malone error = sysctlbyname(MIB ".rule_version", &version, &len, NULL, 0);
112789ddbd45SDavid Malone if (error) {
1128df6a67d6SEnji Cooper snprintf(errstr, buflen, "version check failed: %s",
112989ddbd45SDavid Malone strerror(errno));
113089ddbd45SDavid Malone return (-1);
113189ddbd45SDavid Malone }
113289ddbd45SDavid Malone if (version != MB_VERSION) {
1133df6a67d6SEnji Cooper snprintf(errstr, buflen, "module v%d != library v%d",
113489ddbd45SDavid Malone version, MB_VERSION);
113589ddbd45SDavid Malone return (-1);
113689ddbd45SDavid Malone }
113789ddbd45SDavid Malone return (0);
113889ddbd45SDavid Malone }
113989ddbd45SDavid Malone
114089ddbd45SDavid Malone int
bsde_get_rule_count(size_t buflen,char * errstr)114146d1a925SRobert Watson bsde_get_rule_count(size_t buflen, char *errstr)
114246d1a925SRobert Watson {
114346d1a925SRobert Watson size_t len;
114446d1a925SRobert Watson int error;
114546d1a925SRobert Watson int rule_count;
114646d1a925SRobert Watson
114746d1a925SRobert Watson len = sizeof(rule_count);
11480f9a2306SBruce Evans error = sysctlbyname(MIB ".rule_count", &rule_count, &len, NULL, 0);
114946d1a925SRobert Watson if (error) {
1150df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s", strerror(errno));
115146d1a925SRobert Watson return (-1);
115246d1a925SRobert Watson }
115346d1a925SRobert Watson if (len != sizeof(rule_count)) {
1154df6a67d6SEnji Cooper snprintf(errstr, buflen, "Data error in %s.rule_count",
115546d1a925SRobert Watson MIB);
115646d1a925SRobert Watson return (-1);
115746d1a925SRobert Watson }
115846d1a925SRobert Watson
115946d1a925SRobert Watson return (rule_count);
116046d1a925SRobert Watson }
116146d1a925SRobert Watson
116246d1a925SRobert Watson int
bsde_get_rule_slots(size_t buflen,char * errstr)116346d1a925SRobert Watson bsde_get_rule_slots(size_t buflen, char *errstr)
116446d1a925SRobert Watson {
116546d1a925SRobert Watson size_t len;
116646d1a925SRobert Watson int error;
116746d1a925SRobert Watson int rule_slots;
116846d1a925SRobert Watson
116946d1a925SRobert Watson len = sizeof(rule_slots);
11700f9a2306SBruce Evans error = sysctlbyname(MIB ".rule_slots", &rule_slots, &len, NULL, 0);
117146d1a925SRobert Watson if (error) {
1172df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s", strerror(errno));
117346d1a925SRobert Watson return (-1);
117446d1a925SRobert Watson }
117546d1a925SRobert Watson if (len != sizeof(rule_slots)) {
1176df6a67d6SEnji Cooper snprintf(errstr, buflen, "Data error in %s.rule_slots", MIB);
117746d1a925SRobert Watson return (-1);
117846d1a925SRobert Watson }
117946d1a925SRobert Watson
118046d1a925SRobert Watson return (rule_slots);
118146d1a925SRobert Watson }
118246d1a925SRobert Watson
118346d1a925SRobert Watson /*
118446d1a925SRobert Watson * Returns 0 for success;
118546d1a925SRobert Watson * Returns -1 for failure;
118646d1a925SRobert Watson * Returns -2 for not present
118746d1a925SRobert Watson */
118846d1a925SRobert Watson int
bsde_get_rule(int rulenum,struct mac_bsdextended_rule * rule,size_t errlen,char * errstr)118946d1a925SRobert Watson bsde_get_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t errlen,
119046d1a925SRobert Watson char *errstr)
119146d1a925SRobert Watson {
119246d1a925SRobert Watson int name[10];
119346d1a925SRobert Watson size_t len, size;
119446d1a925SRobert Watson int error;
119546d1a925SRobert Watson
119689ddbd45SDavid Malone if (bsde_check_version(errlen, errstr) != 0)
119789ddbd45SDavid Malone return (-1);
119889ddbd45SDavid Malone
119946d1a925SRobert Watson len = 10;
120046d1a925SRobert Watson error = bsde_get_mib(MIB ".rules", name, &len);
120146d1a925SRobert Watson if (error) {
1202df6a67d6SEnji Cooper snprintf(errstr, errlen, "%s: %s", MIB ".rules",
120346d1a925SRobert Watson strerror(errno));
120446d1a925SRobert Watson return (-1);
120546d1a925SRobert Watson }
120646d1a925SRobert Watson
120746d1a925SRobert Watson size = sizeof(*rule);
120846d1a925SRobert Watson name[len] = rulenum;
120946d1a925SRobert Watson len++;
121046d1a925SRobert Watson error = sysctl(name, len, rule, &size, NULL, 0);
121146d1a925SRobert Watson if (error == -1 && errno == ENOENT)
121246d1a925SRobert Watson return (-2);
121346d1a925SRobert Watson if (error) {
1214df6a67d6SEnji Cooper snprintf(errstr, errlen, "%s.%d: %s", MIB ".rules",
121546d1a925SRobert Watson rulenum, strerror(errno));
121646d1a925SRobert Watson return (-1);
121746d1a925SRobert Watson } else if (size != sizeof(*rule)) {
1218df6a67d6SEnji Cooper snprintf(errstr, errlen, "Data error in %s.%d: %s",
121946d1a925SRobert Watson MIB ".rules", rulenum, strerror(errno));
122046d1a925SRobert Watson return (-1);
122146d1a925SRobert Watson }
122246d1a925SRobert Watson
122346d1a925SRobert Watson return (0);
122446d1a925SRobert Watson }
122546d1a925SRobert Watson
122646d1a925SRobert Watson int
bsde_delete_rule(int rulenum,size_t buflen,char * errstr)122746d1a925SRobert Watson bsde_delete_rule(int rulenum, size_t buflen, char *errstr)
122846d1a925SRobert Watson {
122946d1a925SRobert Watson struct mac_bsdextended_rule rule;
123046d1a925SRobert Watson int name[10];
1231da1259f0SMarcelo Araujo size_t len;
123246d1a925SRobert Watson int error;
123346d1a925SRobert Watson
123489ddbd45SDavid Malone if (bsde_check_version(buflen, errstr) != 0)
123589ddbd45SDavid Malone return (-1);
123689ddbd45SDavid Malone
123746d1a925SRobert Watson len = 10;
123846d1a925SRobert Watson error = bsde_get_mib(MIB ".rules", name, &len);
123946d1a925SRobert Watson if (error) {
1240df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s: %s", MIB ".rules",
124146d1a925SRobert Watson strerror(errno));
124246d1a925SRobert Watson return (-1);
124346d1a925SRobert Watson }
124446d1a925SRobert Watson
124546d1a925SRobert Watson name[len] = rulenum;
124646d1a925SRobert Watson len++;
124746d1a925SRobert Watson
124866157b38SBryan Drewery error = sysctl(name, len, NULL, NULL, &rule, 0);
124946d1a925SRobert Watson if (error) {
1250df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
125146d1a925SRobert Watson rulenum, strerror(errno));
125246d1a925SRobert Watson return (-1);
125346d1a925SRobert Watson }
125446d1a925SRobert Watson
125546d1a925SRobert Watson return (0);
125646d1a925SRobert Watson }
125746d1a925SRobert Watson
125846d1a925SRobert Watson int
bsde_set_rule(int rulenum,struct mac_bsdextended_rule * rule,size_t buflen,char * errstr)125946d1a925SRobert Watson bsde_set_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t buflen,
126046d1a925SRobert Watson char *errstr)
126146d1a925SRobert Watson {
126246d1a925SRobert Watson int name[10];
1263a7c4e991SMarcelo Araujo size_t len;
126446d1a925SRobert Watson int error;
126546d1a925SRobert Watson
126689ddbd45SDavid Malone if (bsde_check_version(buflen, errstr) != 0)
126789ddbd45SDavid Malone return (-1);
126889ddbd45SDavid Malone
126946d1a925SRobert Watson len = 10;
127046d1a925SRobert Watson error = bsde_get_mib(MIB ".rules", name, &len);
127146d1a925SRobert Watson if (error) {
1272df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s: %s", MIB ".rules",
127346d1a925SRobert Watson strerror(errno));
127446d1a925SRobert Watson return (-1);
127546d1a925SRobert Watson }
127646d1a925SRobert Watson
127746d1a925SRobert Watson name[len] = rulenum;
127846d1a925SRobert Watson len++;
127946d1a925SRobert Watson
1280a7c4e991SMarcelo Araujo error = sysctl(name, len, NULL, NULL, rule, sizeof(*rule));
128146d1a925SRobert Watson if (error) {
1282df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
128346d1a925SRobert Watson rulenum, strerror(errno));
128446d1a925SRobert Watson return (-1);
128546d1a925SRobert Watson }
128646d1a925SRobert Watson
128746d1a925SRobert Watson return (0);
128846d1a925SRobert Watson }
128947ab23aaSRobert Watson
129047ab23aaSRobert Watson int
bsde_add_rule(int * rulenum,struct mac_bsdextended_rule * rule,size_t buflen,char * errstr)129147ab23aaSRobert Watson bsde_add_rule(int *rulenum, struct mac_bsdextended_rule *rule, size_t buflen,
129247ab23aaSRobert Watson char *errstr)
129347ab23aaSRobert Watson {
129447ab23aaSRobert Watson char charstr[BUFSIZ];
129547ab23aaSRobert Watson int name[10];
1296a7c4e991SMarcelo Araujo size_t len;
129747ab23aaSRobert Watson int error, rule_slots;
129847ab23aaSRobert Watson
129989ddbd45SDavid Malone if (bsde_check_version(buflen, errstr) != 0)
130089ddbd45SDavid Malone return (-1);
130189ddbd45SDavid Malone
130247ab23aaSRobert Watson len = 10;
130347ab23aaSRobert Watson error = bsde_get_mib(MIB ".rules", name, &len);
130447ab23aaSRobert Watson if (error) {
1305df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s: %s", MIB ".rules",
130647ab23aaSRobert Watson strerror(errno));
130747ab23aaSRobert Watson return (-1);
130847ab23aaSRobert Watson }
130947ab23aaSRobert Watson
131047ab23aaSRobert Watson rule_slots = bsde_get_rule_slots(BUFSIZ, charstr);
131147ab23aaSRobert Watson if (rule_slots == -1) {
1312df6a67d6SEnji Cooper snprintf(errstr, buflen, "unable to get rule slots: %s",
131347ab23aaSRobert Watson strerror(errno));
131447ab23aaSRobert Watson return (-1);
131547ab23aaSRobert Watson }
131647ab23aaSRobert Watson
131747ab23aaSRobert Watson name[len] = rule_slots;
131847ab23aaSRobert Watson len++;
131947ab23aaSRobert Watson
1320a7c4e991SMarcelo Araujo error = sysctl(name, len, NULL, NULL, rule, sizeof(*rule));
132147ab23aaSRobert Watson if (error) {
1322df6a67d6SEnji Cooper snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
132347ab23aaSRobert Watson rule_slots, strerror(errno));
132447ab23aaSRobert Watson return (-1);
132547ab23aaSRobert Watson }
132647ab23aaSRobert Watson
132747ab23aaSRobert Watson if (rulenum != NULL)
1328fbc822aeSPawel Jakub Dawidek *rulenum = rule_slots;
132947ab23aaSRobert Watson
133047ab23aaSRobert Watson return (0);
133147ab23aaSRobert Watson }
1332