xref: /freebsd/lib/libugidfw/ugidfw.c (revision bf417062733b558b4dba6b6ee6b65853e0b53779)
146d1a925SRobert Watson /*-
2a6c2bc8bSRobert Watson  * Copyright (c) 2002-2005 Networks Associates Technology, Inc.
346d1a925SRobert Watson  * All rights reserved.
446d1a925SRobert Watson  *
50285334bSRobert Watson  * This software was developed for the FreeBSD Project by Network Associates
60285334bSRobert Watson  * Laboratories, the Security Research Division of Network Associates, Inc.
70285334bSRobert Watson  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
80285334bSRobert Watson  * DARPA CHATS research program.
946d1a925SRobert Watson  *
1046d1a925SRobert Watson  * Redistribution and use in source and binary forms, with or without
1146d1a925SRobert Watson  * modification, are permitted provided that the following conditions
1246d1a925SRobert Watson  * are met:
1346d1a925SRobert Watson  * 1. Redistributions of source code must retain the above copyright
1446d1a925SRobert Watson  *    notice, this list of conditions and the following disclaimer.
1546d1a925SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
1646d1a925SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
1746d1a925SRobert Watson  *    documentation and/or other materials provided with the distribution.
1846d1a925SRobert Watson  *
1946d1a925SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2046d1a925SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2146d1a925SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2246d1a925SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2346d1a925SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2446d1a925SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2546d1a925SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2646d1a925SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2746d1a925SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2846d1a925SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2946d1a925SRobert Watson  * SUCH DAMAGE.
3046d1a925SRobert Watson  *
3146d1a925SRobert Watson  * $FreeBSD$
3246d1a925SRobert Watson  */
3346d1a925SRobert Watson #include <sys/param.h>
3446d1a925SRobert Watson #include <sys/errno.h>
3546d1a925SRobert Watson #include <sys/time.h>
3646d1a925SRobert Watson #include <sys/sysctl.h>
3789ddbd45SDavid Malone #include <sys/ucred.h>
3889ddbd45SDavid Malone #include <sys/mount.h>
3946d1a925SRobert Watson 
4046d1a925SRobert Watson #include <security/mac_bsdextended/mac_bsdextended.h>
4146d1a925SRobert Watson 
4246d1a925SRobert Watson #include <grp.h>
4346d1a925SRobert Watson #include <pwd.h>
4446d1a925SRobert Watson #include <stdio.h>
4546d1a925SRobert Watson #include <stdlib.h>
4646d1a925SRobert Watson #include <string.h>
4746d1a925SRobert Watson 
48912dd12aSRobert Watson #include "ugidfw.h"
4946d1a925SRobert Watson 
5046d1a925SRobert Watson /*
5146d1a925SRobert Watson  * Text format for rules: rules contain subject and object elements, mode.
5289ddbd45SDavid Malone  * The total form is "subject [s_element] object [o_element] mode [mode]".
5346d1a925SRobert Watson  * At least * one of a uid or gid entry must be present; both may also be
5446d1a925SRobert Watson  * present.
5546d1a925SRobert Watson  */
5646d1a925SRobert Watson 
5746d1a925SRobert Watson #define	MIB	"security.mac.bsdextended"
5846d1a925SRobert Watson 
5946d1a925SRobert Watson int
6046d1a925SRobert Watson bsde_rule_to_string(struct mac_bsdextended_rule *rule, char *buf, size_t buflen)
6146d1a925SRobert Watson {
6246d1a925SRobert Watson 	struct group *grp;
6346d1a925SRobert Watson 	struct passwd *pwd;
6489ddbd45SDavid Malone 	struct statfs *mntbuf;
6589ddbd45SDavid Malone 	char *cur, type[sizeof(rule->mbr_object.mbo_type) * CHAR_BIT + 1];
6646d1a925SRobert Watson 	size_t left, len;
67da1259f0SMarcelo Araujo 	int anymode, unknownmode, numfs, i, notdone;
6846d1a925SRobert Watson 
6946d1a925SRobert Watson 	cur = buf;
7046d1a925SRobert Watson 	left = buflen;
7146d1a925SRobert Watson 
7246d1a925SRobert Watson 	len = snprintf(cur, left, "subject ");
7346d1a925SRobert Watson 	if (len < 0 || len > left)
7446d1a925SRobert Watson 		goto truncated;
7546d1a925SRobert Watson 	left -= len;
7646d1a925SRobert Watson 	cur += len;
7789ddbd45SDavid Malone 	if (rule->mbr_subject.mbs_flags) {
7889ddbd45SDavid Malone 		if (rule->mbr_subject.mbs_neg == MBS_ALL_FLAGS) {
7946d1a925SRobert Watson 			len = snprintf(cur, left, "not ");
8046d1a925SRobert Watson 			if (len < 0 || len > left)
8146d1a925SRobert Watson 				goto truncated;
8246d1a925SRobert Watson 			left -= len;
8346d1a925SRobert Watson 			cur += len;
8489ddbd45SDavid Malone 			notdone = 1;
8589ddbd45SDavid Malone 		} else {
8689ddbd45SDavid Malone 			notdone = 0;
8746d1a925SRobert Watson 		}
8889ddbd45SDavid Malone 
8989ddbd45SDavid Malone 		if (!notdone && (rule->mbr_subject.mbs_neg & MBO_UID_DEFINED)) {
9089ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
9189ddbd45SDavid Malone 			if (len < 0 || len > left)
9289ddbd45SDavid Malone 				goto truncated;
9389ddbd45SDavid Malone 			left -= len;
9489ddbd45SDavid Malone 			cur += len;
9589ddbd45SDavid Malone 		}
9689ddbd45SDavid Malone 		if (rule->mbr_subject.mbs_flags & MBO_UID_DEFINED) {
9789ddbd45SDavid Malone 			pwd = getpwuid(rule->mbr_subject.mbs_uid_min);
9846d1a925SRobert Watson 			if (pwd != NULL) {
9946d1a925SRobert Watson 				len = snprintf(cur, left, "uid %s",
10046d1a925SRobert Watson 				    pwd->pw_name);
10146d1a925SRobert Watson 				if (len < 0 || len > left)
10246d1a925SRobert Watson 					goto truncated;
10346d1a925SRobert Watson 				left -= len;
10446d1a925SRobert Watson 				cur += len;
10546d1a925SRobert Watson 			} else {
10646d1a925SRobert Watson 				len = snprintf(cur, left, "uid %u",
10789ddbd45SDavid Malone 				    rule->mbr_subject.mbs_uid_min);
10889ddbd45SDavid Malone 				if (len < 0 || len > left)
10989ddbd45SDavid Malone 					goto truncated;
11089ddbd45SDavid Malone 				left -= len;
11189ddbd45SDavid Malone 				cur += len;
11289ddbd45SDavid Malone 			}
11389ddbd45SDavid Malone 			if (rule->mbr_subject.mbs_uid_min !=
11489ddbd45SDavid Malone 			    rule->mbr_subject.mbs_uid_max) {
11589ddbd45SDavid Malone 				pwd = getpwuid(rule->mbr_subject.mbs_uid_max);
11689ddbd45SDavid Malone 				if (pwd != NULL) {
11789ddbd45SDavid Malone 					len = snprintf(cur, left, ":%s ",
11889ddbd45SDavid Malone 					    pwd->pw_name);
11989ddbd45SDavid Malone 					if (len < 0 || len > left)
12089ddbd45SDavid Malone 						goto truncated;
12189ddbd45SDavid Malone 					left -= len;
12289ddbd45SDavid Malone 					cur += len;
12389ddbd45SDavid Malone 				} else {
12489ddbd45SDavid Malone 					len = snprintf(cur, left, ":%u ",
12589ddbd45SDavid Malone 					    rule->mbr_subject.mbs_uid_max);
12689ddbd45SDavid Malone 					if (len < 0 || len > left)
12789ddbd45SDavid Malone 						goto truncated;
12889ddbd45SDavid Malone 					left -= len;
12989ddbd45SDavid Malone 					cur += len;
13089ddbd45SDavid Malone 				}
13189ddbd45SDavid Malone 			} else {
13289ddbd45SDavid Malone 				len = snprintf(cur, left, " ");
13346d1a925SRobert Watson 				if (len < 0 || len > left)
13446d1a925SRobert Watson 					goto truncated;
13546d1a925SRobert Watson 				left -= len;
13646d1a925SRobert Watson 				cur += len;
13746d1a925SRobert Watson 			}
13846d1a925SRobert Watson 		}
13989ddbd45SDavid Malone 		if (!notdone && (rule->mbr_subject.mbs_neg & MBO_GID_DEFINED)) {
14089ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
14189ddbd45SDavid Malone 			if (len < 0 || len > left)
14289ddbd45SDavid Malone 				goto truncated;
14389ddbd45SDavid Malone 			left -= len;
14489ddbd45SDavid Malone 			cur += len;
14589ddbd45SDavid Malone 		}
14689ddbd45SDavid Malone 		if (rule->mbr_subject.mbs_flags & MBO_GID_DEFINED) {
14789ddbd45SDavid Malone 			grp = getgrgid(rule->mbr_subject.mbs_gid_min);
14846d1a925SRobert Watson 			if (grp != NULL) {
14946d1a925SRobert Watson 				len = snprintf(cur, left, "gid %s",
15046d1a925SRobert Watson 				    grp->gr_name);
15146d1a925SRobert Watson 				if (len < 0 || len > left)
15246d1a925SRobert Watson 					goto truncated;
15346d1a925SRobert Watson 				left -= len;
15446d1a925SRobert Watson 				cur += len;
15546d1a925SRobert Watson 			} else {
15646d1a925SRobert Watson 				len = snprintf(cur, left, "gid %u",
15789ddbd45SDavid Malone 				    rule->mbr_subject.mbs_gid_min);
15889ddbd45SDavid Malone 				if (len < 0 || len > left)
15989ddbd45SDavid Malone 					goto truncated;
16089ddbd45SDavid Malone 				left -= len;
16189ddbd45SDavid Malone 				cur += len;
16289ddbd45SDavid Malone 			}
16389ddbd45SDavid Malone 			if (rule->mbr_subject.mbs_gid_min !=
16489ddbd45SDavid Malone 			    rule->mbr_subject.mbs_gid_max) {
16589ddbd45SDavid Malone 				grp = getgrgid(rule->mbr_subject.mbs_gid_max);
16689ddbd45SDavid Malone 				if (grp != NULL) {
16789ddbd45SDavid Malone 					len = snprintf(cur, left, ":%s ",
16889ddbd45SDavid Malone 					    grp->gr_name);
16989ddbd45SDavid Malone 					if (len < 0 || len > left)
17089ddbd45SDavid Malone 						goto truncated;
17189ddbd45SDavid Malone 					left -= len;
17289ddbd45SDavid Malone 					cur += len;
17389ddbd45SDavid Malone 				} else {
17489ddbd45SDavid Malone 					len = snprintf(cur, left, ":%u ",
17589ddbd45SDavid Malone 					    rule->mbr_subject.mbs_gid_max);
17689ddbd45SDavid Malone 					if (len < 0 || len > left)
17789ddbd45SDavid Malone 						goto truncated;
17889ddbd45SDavid Malone 					left -= len;
17989ddbd45SDavid Malone 					cur += len;
18089ddbd45SDavid Malone 				}
18189ddbd45SDavid Malone 			} else {
18289ddbd45SDavid Malone 				len = snprintf(cur, left, " ");
18346d1a925SRobert Watson 				if (len < 0 || len > left)
18446d1a925SRobert Watson 					goto truncated;
18546d1a925SRobert Watson 				left -= len;
18646d1a925SRobert Watson 				cur += len;
18746d1a925SRobert Watson 			}
18846d1a925SRobert Watson 		}
18989ddbd45SDavid Malone 		if (!notdone && (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)) {
19089ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
19189ddbd45SDavid Malone 			if (len < 0 || len > left)
19289ddbd45SDavid Malone 				goto truncated;
19389ddbd45SDavid Malone 			left -= len;
19489ddbd45SDavid Malone 			cur += len;
19546d1a925SRobert Watson 		}
19689ddbd45SDavid Malone 		if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
19789ddbd45SDavid Malone 			len = snprintf(cur, left, "jailid %d ",
19889ddbd45SDavid Malone 			    rule->mbr_subject.mbs_prison);
19989ddbd45SDavid Malone 			if (len < 0 || len > left)
20089ddbd45SDavid Malone 				goto truncated;
20189ddbd45SDavid Malone 			left -= len;
20289ddbd45SDavid Malone 			cur += len;
20389ddbd45SDavid Malone 		}
20489ddbd45SDavid Malone 	}
20589ddbd45SDavid Malone 
20646d1a925SRobert Watson 	len = snprintf(cur, left, "object ");
20746d1a925SRobert Watson 	if (len < 0 || len > left)
20846d1a925SRobert Watson 		goto truncated;
20946d1a925SRobert Watson 	left -= len;
21046d1a925SRobert Watson 	cur += len;
21189ddbd45SDavid Malone 	if (rule->mbr_object.mbo_flags) {
21289ddbd45SDavid Malone 		if (rule->mbr_object.mbo_neg == MBO_ALL_FLAGS) {
21346d1a925SRobert Watson 			len = snprintf(cur, left, "not ");
21446d1a925SRobert Watson 			if (len < 0 || len > left)
21546d1a925SRobert Watson 				goto truncated;
21646d1a925SRobert Watson 			left -= len;
21746d1a925SRobert Watson 			cur += len;
21889ddbd45SDavid Malone 			notdone = 1;
21989ddbd45SDavid Malone 		} else {
22089ddbd45SDavid Malone 			notdone = 0;
22146d1a925SRobert Watson 		}
22289ddbd45SDavid Malone 
22389ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)) {
22489ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
22589ddbd45SDavid Malone 			if (len < 0 || len > left)
22689ddbd45SDavid Malone 				goto truncated;
22789ddbd45SDavid Malone 			left -= len;
22889ddbd45SDavid Malone 			cur += len;
22989ddbd45SDavid Malone 		}
23089ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
23189ddbd45SDavid Malone 			pwd = getpwuid(rule->mbr_object.mbo_uid_min);
23246d1a925SRobert Watson 			if (pwd != NULL) {
23346d1a925SRobert Watson 				len = snprintf(cur, left, "uid %s",
23446d1a925SRobert Watson 				    pwd->pw_name);
23546d1a925SRobert Watson 				if (len < 0 || len > left)
23646d1a925SRobert Watson 					goto truncated;
23746d1a925SRobert Watson 				left -= len;
23846d1a925SRobert Watson 				cur += len;
23946d1a925SRobert Watson 			} else {
24046d1a925SRobert Watson 				len = snprintf(cur, left, "uid %u",
24189ddbd45SDavid Malone 				    rule->mbr_object.mbo_uid_min);
24289ddbd45SDavid Malone 				if (len < 0 || len > left)
24389ddbd45SDavid Malone 					goto truncated;
24489ddbd45SDavid Malone 				left -= len;
24589ddbd45SDavid Malone 				cur += len;
24689ddbd45SDavid Malone 			}
24789ddbd45SDavid Malone 			if (rule->mbr_object.mbo_uid_min !=
24889ddbd45SDavid Malone 			    rule->mbr_object.mbo_uid_max) {
24989ddbd45SDavid Malone 				pwd = getpwuid(rule->mbr_object.mbo_uid_max);
25089ddbd45SDavid Malone 				if (pwd != NULL) {
25189ddbd45SDavid Malone 					len = snprintf(cur, left, ":%s ",
25289ddbd45SDavid Malone 					    pwd->pw_name);
25389ddbd45SDavid Malone 					if (len < 0 || len > left)
25489ddbd45SDavid Malone 						goto truncated;
25589ddbd45SDavid Malone 					left -= len;
25689ddbd45SDavid Malone 					cur += len;
25789ddbd45SDavid Malone 				} else {
25889ddbd45SDavid Malone 					len = snprintf(cur, left, ":%u ",
25989ddbd45SDavid Malone 					    rule->mbr_object.mbo_uid_max);
26089ddbd45SDavid Malone 					if (len < 0 || len > left)
26189ddbd45SDavid Malone 						goto truncated;
26289ddbd45SDavid Malone 					left -= len;
26389ddbd45SDavid Malone 					cur += len;
26489ddbd45SDavid Malone 				}
26589ddbd45SDavid Malone 			} else {
26689ddbd45SDavid Malone 				len = snprintf(cur, left, " ");
26789ddbd45SDavid Malone 				if (len < 0 || len > left)
26889ddbd45SDavid Malone 					goto truncated;
26946d1a925SRobert Watson 				left -= len;
27046d1a925SRobert Watson 				cur += len;
27146d1a925SRobert Watson 			}
27246d1a925SRobert Watson 		}
27389ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)) {
27489ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
27589ddbd45SDavid Malone 			if (len < 0 || len > left)
27689ddbd45SDavid Malone 				goto truncated;
27789ddbd45SDavid Malone 			left -= len;
27889ddbd45SDavid Malone 			cur += len;
27989ddbd45SDavid Malone 		}
28089ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
28189ddbd45SDavid Malone 			grp = getgrgid(rule->mbr_object.mbo_gid_min);
28246d1a925SRobert Watson 			if (grp != NULL) {
28346d1a925SRobert Watson 				len = snprintf(cur, left, "gid %s",
28446d1a925SRobert Watson 				    grp->gr_name);
28546d1a925SRobert Watson 				if (len < 0 || len > left)
28646d1a925SRobert Watson 					goto truncated;
28746d1a925SRobert Watson 				left -= len;
28846d1a925SRobert Watson 				cur += len;
28946d1a925SRobert Watson 			} else {
29046d1a925SRobert Watson 				len = snprintf(cur, left, "gid %u",
29189ddbd45SDavid Malone 				    rule->mbr_object.mbo_gid_min);
29246d1a925SRobert Watson 				if (len < 0 || len > left)
29346d1a925SRobert Watson 					goto truncated;
29446d1a925SRobert Watson 				left -= len;
29546d1a925SRobert Watson 				cur += len;
29646d1a925SRobert Watson 			}
29789ddbd45SDavid Malone 			if (rule->mbr_object.mbo_gid_min !=
29889ddbd45SDavid Malone 			    rule->mbr_object.mbo_gid_max) {
29989ddbd45SDavid Malone 				grp = getgrgid(rule->mbr_object.mbo_gid_max);
30089ddbd45SDavid Malone 				if (grp != NULL) {
30189ddbd45SDavid Malone 					len = snprintf(cur, left, ":%s ",
30289ddbd45SDavid Malone 					    grp->gr_name);
30389ddbd45SDavid Malone 					if (len < 0 || len > left)
30489ddbd45SDavid Malone 						goto truncated;
30589ddbd45SDavid Malone 					left -= len;
30689ddbd45SDavid Malone 					cur += len;
30789ddbd45SDavid Malone 				} else {
30889ddbd45SDavid Malone 					len = snprintf(cur, left, ":%u ",
30989ddbd45SDavid Malone 					    rule->mbr_object.mbo_gid_max);
31089ddbd45SDavid Malone 					if (len < 0 || len > left)
31189ddbd45SDavid Malone 						goto truncated;
31289ddbd45SDavid Malone 					left -= len;
31389ddbd45SDavid Malone 					cur += len;
31489ddbd45SDavid Malone 				}
31589ddbd45SDavid Malone 			} else {
31689ddbd45SDavid Malone 				len = snprintf(cur, left, " ");
31789ddbd45SDavid Malone 				if (len < 0 || len > left)
31889ddbd45SDavid Malone 					goto truncated;
31989ddbd45SDavid Malone 				left -= len;
32089ddbd45SDavid Malone 				cur += len;
32189ddbd45SDavid Malone 			}
32289ddbd45SDavid Malone 		}
32389ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)) {
32489ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
32589ddbd45SDavid Malone 			if (len < 0 || len > left)
32689ddbd45SDavid Malone 				goto truncated;
32789ddbd45SDavid Malone 			left -= len;
32889ddbd45SDavid Malone 			cur += len;
32989ddbd45SDavid Malone 		}
33089ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
33189ddbd45SDavid Malone 			numfs = getmntinfo(&mntbuf, MNT_NOWAIT);
33289ddbd45SDavid Malone 			for (i = 0; i < numfs; i++)
33389ddbd45SDavid Malone 				if (memcmp(&(rule->mbr_object.mbo_fsid),
33489ddbd45SDavid Malone 				    &(mntbuf[i].f_fsid),
33589ddbd45SDavid Malone 				    sizeof(mntbuf[i].f_fsid)) == 0)
33689ddbd45SDavid Malone 					break;
33789ddbd45SDavid Malone 			len = snprintf(cur, left, "filesys %s ",
33889ddbd45SDavid Malone 			    i == numfs ? "???" : mntbuf[i].f_mntonname);
33989ddbd45SDavid Malone 			if (len < 0 || len > left)
34089ddbd45SDavid Malone 				goto truncated;
34189ddbd45SDavid Malone 			left -= len;
34289ddbd45SDavid Malone 			cur += len;
34389ddbd45SDavid Malone 		}
34489ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_SUID)) {
34589ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
34689ddbd45SDavid Malone 			if (len < 0 || len > left)
34789ddbd45SDavid Malone 				goto truncated;
34889ddbd45SDavid Malone 			left -= len;
34989ddbd45SDavid Malone 			cur += len;
35089ddbd45SDavid Malone 		}
35189ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_SUID) {
35289ddbd45SDavid Malone 			len = snprintf(cur, left, "suid ");
35389ddbd45SDavid Malone 			if (len < 0 || len > left)
35489ddbd45SDavid Malone 				goto truncated;
35589ddbd45SDavid Malone 			left -= len;
35689ddbd45SDavid Malone 			cur += len;
35789ddbd45SDavid Malone 		}
35889ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_SGID)) {
35989ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
36089ddbd45SDavid Malone 			if (len < 0 || len > left)
36189ddbd45SDavid Malone 				goto truncated;
36289ddbd45SDavid Malone 			left -= len;
36389ddbd45SDavid Malone 			cur += len;
36489ddbd45SDavid Malone 		}
36589ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_SGID) {
36689ddbd45SDavid Malone 			len = snprintf(cur, left, "sgid ");
36789ddbd45SDavid Malone 			if (len < 0 || len > left)
36889ddbd45SDavid Malone 				goto truncated;
36989ddbd45SDavid Malone 			left -= len;
37089ddbd45SDavid Malone 			cur += len;
37189ddbd45SDavid Malone 		}
37289ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)) {
37389ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
37489ddbd45SDavid Malone 			if (len < 0 || len > left)
37589ddbd45SDavid Malone 				goto truncated;
37689ddbd45SDavid Malone 			left -= len;
37789ddbd45SDavid Malone 			cur += len;
37889ddbd45SDavid Malone 		}
37989ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
38089ddbd45SDavid Malone 			len = snprintf(cur, left, "uid_of_subject ");
38189ddbd45SDavid Malone 			if (len < 0 || len > left)
38289ddbd45SDavid Malone 				goto truncated;
38389ddbd45SDavid Malone 			left -= len;
38489ddbd45SDavid Malone 			cur += len;
38589ddbd45SDavid Malone 		}
38689ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)) {
38789ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
38889ddbd45SDavid Malone 			if (len < 0 || len > left)
38989ddbd45SDavid Malone 				goto truncated;
39089ddbd45SDavid Malone 			left -= len;
39189ddbd45SDavid Malone 			cur += len;
39289ddbd45SDavid Malone 		}
39389ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
39489ddbd45SDavid Malone 			len = snprintf(cur, left, "gid_of_subject ");
39589ddbd45SDavid Malone 			if (len < 0 || len > left)
39689ddbd45SDavid Malone 				goto truncated;
39789ddbd45SDavid Malone 			left -= len;
39889ddbd45SDavid Malone 			cur += len;
39989ddbd45SDavid Malone 		}
40089ddbd45SDavid Malone 		if (!notdone && (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)) {
40189ddbd45SDavid Malone 			len = snprintf(cur, left, "! ");
40289ddbd45SDavid Malone 			if (len < 0 || len > left)
40389ddbd45SDavid Malone 				goto truncated;
40489ddbd45SDavid Malone 			left -= len;
40589ddbd45SDavid Malone 			cur += len;
40689ddbd45SDavid Malone 		}
40789ddbd45SDavid Malone 		if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
40889ddbd45SDavid Malone 			i = 0;
40989ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type & MBO_TYPE_REG)
41089ddbd45SDavid Malone 				type[i++] = 'r';
41189ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type & MBO_TYPE_DIR)
41289ddbd45SDavid Malone 				type[i++] = 'd';
41389ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type & MBO_TYPE_BLK)
41489ddbd45SDavid Malone 				type[i++] = 'b';
41589ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type & MBO_TYPE_CHR)
41689ddbd45SDavid Malone 				type[i++] = 'c';
41789ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type & MBO_TYPE_LNK)
41889ddbd45SDavid Malone 				type[i++] = 'l';
41989ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type & MBO_TYPE_SOCK)
42089ddbd45SDavid Malone 				type[i++] = 's';
42189ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type & MBO_TYPE_FIFO)
42289ddbd45SDavid Malone 				type[i++] = 'p';
42389ddbd45SDavid Malone 			if (rule->mbr_object.mbo_type == MBO_ALL_TYPE) {
42489ddbd45SDavid Malone 				i = 0;
42589ddbd45SDavid Malone 				type[i++] = 'a';
42689ddbd45SDavid Malone 			}
42789ddbd45SDavid Malone 			type[i++] = '\0';
42889ddbd45SDavid Malone 			len = snprintf(cur, left, "type %s ", type);
42989ddbd45SDavid Malone 			if (len < 0 || len > left)
43089ddbd45SDavid Malone 				goto truncated;
43189ddbd45SDavid Malone 			left -= len;
43289ddbd45SDavid Malone 			cur += len;
43346d1a925SRobert Watson 		}
43446d1a925SRobert Watson 	}
43546d1a925SRobert Watson 
43646d1a925SRobert Watson 	len = snprintf(cur, left, "mode ");
43746d1a925SRobert Watson 	if (len < 0 || len > left)
43846d1a925SRobert Watson 		goto truncated;
43946d1a925SRobert Watson 	left -= len;
44046d1a925SRobert Watson 	cur += len;
44146d1a925SRobert Watson 
442f4194603SRobert Watson 	anymode = (rule->mbr_mode & MBI_ALLPERM);
443f4194603SRobert Watson 	unknownmode = (rule->mbr_mode & ~MBI_ALLPERM);
44446d1a925SRobert Watson 
445f4194603SRobert Watson 	if (rule->mbr_mode & MBI_ADMIN) {
44646d1a925SRobert Watson 		len = snprintf(cur, left, "a");
44746d1a925SRobert Watson 		if (len < 0 || len > left)
44846d1a925SRobert Watson 			goto truncated;
44946d1a925SRobert Watson 
45046d1a925SRobert Watson 		left -= len;
45146d1a925SRobert Watson 		cur += len;
45246d1a925SRobert Watson 	}
453f4194603SRobert Watson 	if (rule->mbr_mode & MBI_READ) {
45446d1a925SRobert Watson 		len = snprintf(cur, left, "r");
45546d1a925SRobert Watson 		if (len < 0 || len > left)
45646d1a925SRobert Watson 			goto truncated;
45746d1a925SRobert Watson 
45846d1a925SRobert Watson 		left -= len;
45946d1a925SRobert Watson 		cur += len;
46046d1a925SRobert Watson 	}
461f4194603SRobert Watson 	if (rule->mbr_mode & MBI_STAT) {
46246d1a925SRobert Watson 		len = snprintf(cur, left, "s");
46346d1a925SRobert Watson 		if (len < 0 || len > left)
46446d1a925SRobert Watson 			goto truncated;
46546d1a925SRobert Watson 
46646d1a925SRobert Watson 		left -= len;
46746d1a925SRobert Watson 		cur += len;
46846d1a925SRobert Watson 	}
469f4194603SRobert Watson 	if (rule->mbr_mode & MBI_WRITE) {
47046d1a925SRobert Watson 		len = snprintf(cur, left, "w");
47146d1a925SRobert Watson 		if (len < 0 || len > left)
47246d1a925SRobert Watson 			goto truncated;
47346d1a925SRobert Watson 
47446d1a925SRobert Watson 		left -= len;
47546d1a925SRobert Watson 		cur += len;
47646d1a925SRobert Watson 	}
477f4194603SRobert Watson 	if (rule->mbr_mode & MBI_EXEC) {
47846d1a925SRobert Watson 		len = snprintf(cur, left, "x");
47946d1a925SRobert Watson 		if (len < 0 || len > left)
48046d1a925SRobert Watson 			goto truncated;
48146d1a925SRobert Watson 
48246d1a925SRobert Watson 		left -= len;
48346d1a925SRobert Watson 		cur += len;
48446d1a925SRobert Watson 	}
48546d1a925SRobert Watson 	if (!anymode) {
48646d1a925SRobert Watson 		len = snprintf(cur, left, "n");
48746d1a925SRobert Watson 		if (len < 0 || len > left)
48846d1a925SRobert Watson 			goto truncated;
48946d1a925SRobert Watson 
49046d1a925SRobert Watson 		left -= len;
49146d1a925SRobert Watson 		cur += len;
49246d1a925SRobert Watson 	}
49346d1a925SRobert Watson 	if (unknownmode) {
49446d1a925SRobert Watson 		len = snprintf(cur, left, "?");
49546d1a925SRobert Watson 		if (len < 0 || len > left)
49646d1a925SRobert Watson 			goto truncated;
49746d1a925SRobert Watson 
49846d1a925SRobert Watson 		left -= len;
49946d1a925SRobert Watson 		cur += len;
50046d1a925SRobert Watson 	}
50146d1a925SRobert Watson 
50246d1a925SRobert Watson 	return (0);
50346d1a925SRobert Watson 
50446d1a925SRobert Watson truncated:
50546d1a925SRobert Watson 	return (-1);
50646d1a925SRobert Watson }
50746d1a925SRobert Watson 
508*bf417062SMarcelo Araujo static int
50989ddbd45SDavid Malone bsde_parse_uidrange(char *spec, uid_t *min, uid_t *max,
51089ddbd45SDavid Malone     size_t buflen, char *errstr){
51146d1a925SRobert Watson 	struct passwd *pwd;
51289ddbd45SDavid Malone 	uid_t uid1, uid2;
51389ddbd45SDavid Malone 	char *spec1, *spec2, *endp;
51489ddbd45SDavid Malone 	unsigned long value;
51546d1a925SRobert Watson 	size_t len;
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') {
52689ddbd45SDavid Malone 			len = snprintf(errstr, buflen,
52789ddbd45SDavid Malone 			    "invalid uid: '%s'", spec1);
52846d1a925SRobert Watson 			return (-1);
52946d1a925SRobert Watson 		}
53089ddbd45SDavid Malone 		uid1 = value;
53189ddbd45SDavid Malone 	}
53289ddbd45SDavid Malone 
53389ddbd45SDavid Malone 	if (spec2 == NULL) {
53489ddbd45SDavid Malone 		*max = *min = uid1;
53589ddbd45SDavid Malone 		return (0);
53689ddbd45SDavid Malone 	}
53789ddbd45SDavid Malone 
53889ddbd45SDavid Malone 	pwd = getpwnam(spec2);
53989ddbd45SDavid Malone 	if (pwd != NULL)
54089ddbd45SDavid Malone 		uid2 = pwd->pw_uid;
54189ddbd45SDavid Malone 	else {
54289ddbd45SDavid Malone 		value = strtoul(spec2, &endp, 10);
54389ddbd45SDavid Malone 		if (*endp != '\0') {
54489ddbd45SDavid Malone 			len = snprintf(errstr, buflen,
54589ddbd45SDavid Malone 			    "invalid uid: '%s'", spec2);
54689ddbd45SDavid Malone 			return (-1);
54789ddbd45SDavid Malone 		}
54889ddbd45SDavid Malone 		uid2 = value;
54989ddbd45SDavid Malone 	}
55089ddbd45SDavid Malone 
55189ddbd45SDavid Malone 	*min = uid1;
55289ddbd45SDavid Malone 	*max = uid2;
55389ddbd45SDavid Malone 
55489ddbd45SDavid Malone 	return (0);
55589ddbd45SDavid Malone }
55689ddbd45SDavid Malone 
557*bf417062SMarcelo Araujo static int
55889ddbd45SDavid Malone bsde_parse_gidrange(char *spec, gid_t *min, gid_t *max,
55989ddbd45SDavid Malone     size_t buflen, char *errstr){
56089ddbd45SDavid Malone 	struct group *grp;
56189ddbd45SDavid Malone 	gid_t gid1, gid2;
56289ddbd45SDavid Malone 	char *spec1, *spec2, *endp;
56389ddbd45SDavid Malone 	unsigned long value;
56489ddbd45SDavid Malone 	size_t len;
56589ddbd45SDavid Malone 
56689ddbd45SDavid Malone 	spec2 = spec;
56789ddbd45SDavid Malone 	spec1 = strsep(&spec2, ":");
56889ddbd45SDavid Malone 
56989ddbd45SDavid Malone 	grp = getgrnam(spec1);
57089ddbd45SDavid Malone 	if (grp != NULL)
57189ddbd45SDavid Malone 		gid1 = grp->gr_gid;
57289ddbd45SDavid Malone 	else {
57389ddbd45SDavid Malone 		value = strtoul(spec1, &endp, 10);
57489ddbd45SDavid Malone 		if (*endp != '\0') {
57589ddbd45SDavid Malone 			len = snprintf(errstr, buflen,
57689ddbd45SDavid Malone 			    "invalid gid: '%s'", spec1);
57789ddbd45SDavid Malone 			return (-1);
57889ddbd45SDavid Malone 		}
57989ddbd45SDavid Malone 		gid1 = value;
58089ddbd45SDavid Malone 	}
58189ddbd45SDavid Malone 
58289ddbd45SDavid Malone 	if (spec2 == NULL) {
58389ddbd45SDavid Malone 		*max = *min = gid1;
58489ddbd45SDavid Malone 		return (0);
58589ddbd45SDavid Malone 	}
58689ddbd45SDavid Malone 
58789ddbd45SDavid Malone 	grp = getgrnam(spec2);
58889ddbd45SDavid Malone 	if (grp != NULL)
58989ddbd45SDavid Malone 		gid2 = grp->gr_gid;
59089ddbd45SDavid Malone 	else {
59189ddbd45SDavid Malone 		value = strtoul(spec2, &endp, 10);
59289ddbd45SDavid Malone 		if (*endp != '\0') {
59389ddbd45SDavid Malone 			len = snprintf(errstr, buflen,
59489ddbd45SDavid Malone 			    "invalid gid: '%s'", spec2);
59589ddbd45SDavid Malone 			return (-1);
59689ddbd45SDavid Malone 		}
59789ddbd45SDavid Malone 		gid2 = value;
59889ddbd45SDavid Malone 	}
59989ddbd45SDavid Malone 
60089ddbd45SDavid Malone 	*min = gid1;
60189ddbd45SDavid Malone 	*max = gid2;
60289ddbd45SDavid Malone 
60389ddbd45SDavid Malone 	return (0);
60489ddbd45SDavid Malone }
60589ddbd45SDavid Malone 
606*bf417062SMarcelo Araujo static int
60789ddbd45SDavid Malone bsde_parse_subject(int argc, char *argv[],
60889ddbd45SDavid Malone     struct mac_bsdextended_subject *subject, size_t buflen, char *errstr)
60989ddbd45SDavid Malone {
61089ddbd45SDavid Malone 	int not_seen, flags;
61189ddbd45SDavid Malone 	int current, neg, nextnot;
61289ddbd45SDavid Malone 	char *endp;
61389ddbd45SDavid Malone 	uid_t uid_min, uid_max;
61489ddbd45SDavid Malone 	gid_t gid_min, gid_max;
615*bf417062SMarcelo Araujo 	int jid = 0;
61689ddbd45SDavid Malone 	size_t len;
61789ddbd45SDavid Malone 	long value;
61846d1a925SRobert Watson 
61946d1a925SRobert Watson 	current = 0;
62089ddbd45SDavid Malone 	flags = 0;
62189ddbd45SDavid Malone 	neg = 0;
62289ddbd45SDavid Malone 	nextnot = 0;
62346d1a925SRobert Watson 
62489ddbd45SDavid Malone 	if (strcmp("not", argv[current]) == 0) {
62546d1a925SRobert Watson 		not_seen = 1;
62646d1a925SRobert Watson 		current++;
62746d1a925SRobert Watson 	} else
62846d1a925SRobert Watson 		not_seen = 0;
62946d1a925SRobert Watson 
63089ddbd45SDavid Malone 	while (current < argc) {
63189ddbd45SDavid Malone 		if (strcmp(argv[current], "uid") == 0) {
63246d1a925SRobert Watson 			if (current + 2 > argc) {
63346d1a925SRobert Watson 				len = snprintf(errstr, buflen, "uid short");
63446d1a925SRobert Watson 				return (-1);
63546d1a925SRobert Watson 			}
63689ddbd45SDavid Malone 			if (flags & MBS_UID_DEFINED) {
63789ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "one uid only");
63846d1a925SRobert Watson 				return (-1);
63946d1a925SRobert Watson 			}
64089ddbd45SDavid Malone 			if (bsde_parse_uidrange(argv[current+1],
64189ddbd45SDavid Malone 			    &uid_min, &uid_max, buflen, errstr) < 0)
64289ddbd45SDavid Malone 				return (-1);
64389ddbd45SDavid Malone 			flags |= MBS_UID_DEFINED;
64489ddbd45SDavid Malone 			if (nextnot) {
64589ddbd45SDavid Malone 				neg ^= MBS_UID_DEFINED;
64689ddbd45SDavid Malone 				nextnot = 0;
64746d1a925SRobert Watson 			}
64846d1a925SRobert Watson 			current += 2;
64989ddbd45SDavid Malone 		} else if (strcmp(argv[current], "gid") == 0) {
65046d1a925SRobert Watson 			if (current + 2 > argc) {
65146d1a925SRobert Watson 				len = snprintf(errstr, buflen, "gid short");
65246d1a925SRobert Watson 				return (-1);
65346d1a925SRobert Watson 			}
65489ddbd45SDavid Malone 			if (flags & MBS_GID_DEFINED) {
65589ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "one gid only");
65646d1a925SRobert Watson 				return (-1);
65746d1a925SRobert Watson 			}
65889ddbd45SDavid Malone 			if (bsde_parse_gidrange(argv[current+1],
65989ddbd45SDavid Malone 			    &gid_min, &gid_max, buflen, errstr) < 0)
66089ddbd45SDavid Malone 				return (-1);
66189ddbd45SDavid Malone 			flags |= MBS_GID_DEFINED;
66289ddbd45SDavid Malone 			if (nextnot) {
66389ddbd45SDavid Malone 				neg ^= MBS_GID_DEFINED;
66489ddbd45SDavid Malone 				nextnot = 0;
66546d1a925SRobert Watson 			}
66646d1a925SRobert Watson 			current += 2;
66789ddbd45SDavid Malone 		} else if (strcmp(argv[current], "jailid") == 0) {
66846d1a925SRobert Watson 			if (current + 2 > argc) {
66989ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "prison short");
67046d1a925SRobert Watson 				return (-1);
67146d1a925SRobert Watson 			}
67289ddbd45SDavid Malone 			if (flags & MBS_PRISON_DEFINED) {
67389ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "one jail only");
67489ddbd45SDavid Malone 				return (-1);
67589ddbd45SDavid Malone 			}
67646d1a925SRobert Watson 			value = strtol(argv[current+1], &endp, 10);
67746d1a925SRobert Watson 			if (*endp != '\0') {
678a6c2bc8bSRobert Watson 				len = snprintf(errstr, buflen,
67989ddbd45SDavid Malone 				    "invalid jid: '%s'", argv[current+1]);
68046d1a925SRobert Watson 				return (-1);
68146d1a925SRobert Watson 			}
68289ddbd45SDavid Malone 			jid = value;
68389ddbd45SDavid Malone 			flags |= MBS_PRISON_DEFINED;
68489ddbd45SDavid Malone 			if (nextnot) {
68589ddbd45SDavid Malone 				neg ^= MBS_PRISON_DEFINED;
68689ddbd45SDavid Malone 				nextnot = 0;
687a6c2bc8bSRobert Watson 			}
68846d1a925SRobert Watson 			current += 2;
68989ddbd45SDavid Malone 		} else if (strcmp(argv[current], "!") == 0) {
69089ddbd45SDavid Malone 			if (nextnot) {
69146d1a925SRobert Watson 				len = snprintf(errstr, buflen,
69289ddbd45SDavid Malone 				    "double negative");
69346d1a925SRobert Watson 				return (-1);
69446d1a925SRobert Watson 			}
69589ddbd45SDavid Malone 			nextnot = 1;
69689ddbd45SDavid Malone 			current += 1;
69746d1a925SRobert Watson 		} else {
69846d1a925SRobert Watson 			len = snprintf(errstr, buflen, "'%s' not expected",
69946d1a925SRobert Watson 			    argv[current]);
70046d1a925SRobert Watson 			return (-1);
70146d1a925SRobert Watson 		}
70246d1a925SRobert Watson 	}
70346d1a925SRobert Watson 
70489ddbd45SDavid Malone 	subject->mbs_flags = flags;
70546d1a925SRobert Watson 	if (not_seen)
70689ddbd45SDavid Malone 		subject->mbs_neg = MBS_ALL_FLAGS ^ neg;
70789ddbd45SDavid Malone 	else
70889ddbd45SDavid Malone 		subject->mbs_neg = neg;
70989ddbd45SDavid Malone 	if (flags & MBS_UID_DEFINED) {
71089ddbd45SDavid Malone 		subject->mbs_uid_min = uid_min;
71189ddbd45SDavid Malone 		subject->mbs_uid_max = uid_max;
71289ddbd45SDavid Malone 	}
71389ddbd45SDavid Malone 	if (flags & MBS_GID_DEFINED) {
71489ddbd45SDavid Malone 		subject->mbs_gid_min = gid_min;
71589ddbd45SDavid Malone 		subject->mbs_gid_max = gid_max;
71689ddbd45SDavid Malone 	}
71789ddbd45SDavid Malone 	if (flags & MBS_PRISON_DEFINED)
71889ddbd45SDavid Malone 		subject->mbs_prison = jid;
71946d1a925SRobert Watson 
72089ddbd45SDavid Malone 	return (0);
72189ddbd45SDavid Malone }
72246d1a925SRobert Watson 
723*bf417062SMarcelo Araujo static int
72489ddbd45SDavid Malone bsde_parse_type(char *spec, int *type, size_t buflen, char *errstr)
72589ddbd45SDavid Malone {
72689ddbd45SDavid Malone 	size_t len;
72789ddbd45SDavid Malone 	int i;
72889ddbd45SDavid Malone 
72989ddbd45SDavid Malone 	*type = 0;
73089ddbd45SDavid Malone 	for (i = 0; i < strlen(spec); i++) {
73189ddbd45SDavid Malone 		switch (spec[i]) {
73289ddbd45SDavid Malone 		case 'r':
73389ddbd45SDavid Malone 		case '-':
73489ddbd45SDavid Malone 			*type |= MBO_TYPE_REG;
73589ddbd45SDavid Malone 			break;
73689ddbd45SDavid Malone 		case 'd':
73789ddbd45SDavid Malone 			*type |= MBO_TYPE_DIR;
73889ddbd45SDavid Malone 			break;
73989ddbd45SDavid Malone 		case 'b':
74089ddbd45SDavid Malone 			*type |= MBO_TYPE_BLK;
74189ddbd45SDavid Malone 			break;
74289ddbd45SDavid Malone 		case 'c':
74389ddbd45SDavid Malone 			*type |= MBO_TYPE_CHR;
74489ddbd45SDavid Malone 			break;
74589ddbd45SDavid Malone 		case 'l':
74689ddbd45SDavid Malone 			*type |= MBO_TYPE_LNK;
74789ddbd45SDavid Malone 			break;
74889ddbd45SDavid Malone 		case 's':
74989ddbd45SDavid Malone 			*type |= MBO_TYPE_SOCK;
75089ddbd45SDavid Malone 			break;
75189ddbd45SDavid Malone 		case 'p':
75289ddbd45SDavid Malone 			*type |= MBO_TYPE_FIFO;
75389ddbd45SDavid Malone 			break;
75489ddbd45SDavid Malone 		case 'a':
75589ddbd45SDavid Malone 			*type |= MBO_ALL_TYPE;
75689ddbd45SDavid Malone 			break;
75789ddbd45SDavid Malone 		default:
75889ddbd45SDavid Malone 			len = snprintf(errstr, buflen, "Unknown type code: %c",
75989ddbd45SDavid Malone 			    spec[i]);
76089ddbd45SDavid Malone 			return (-1);
76189ddbd45SDavid Malone 		}
76289ddbd45SDavid Malone 	}
76389ddbd45SDavid Malone 
76489ddbd45SDavid Malone 	return (0);
76589ddbd45SDavid Malone }
76689ddbd45SDavid Malone 
767*bf417062SMarcelo Araujo static int
76889ddbd45SDavid Malone bsde_parse_fsid(char *spec, struct fsid *fsid, size_t buflen, char *errstr)
76989ddbd45SDavid Malone {
77089ddbd45SDavid Malone 	size_t len;
77189ddbd45SDavid Malone 	struct statfs buf;
77289ddbd45SDavid Malone 
77389ddbd45SDavid Malone 	if (statfs(spec, &buf) < 0) {
77489ddbd45SDavid Malone 		len = snprintf(errstr, buflen, "Unable to get id for %s: %s",
77589ddbd45SDavid Malone 		    spec, strerror(errno));
77689ddbd45SDavid Malone 		return (-1);
77789ddbd45SDavid Malone 	}
77889ddbd45SDavid Malone 
77989ddbd45SDavid Malone 	*fsid = buf.f_fsid;
78089ddbd45SDavid Malone 
78189ddbd45SDavid Malone 	return (0);
78289ddbd45SDavid Malone }
78389ddbd45SDavid Malone 
784*bf417062SMarcelo Araujo static int
78589ddbd45SDavid Malone bsde_parse_object(int argc, char *argv[],
78689ddbd45SDavid Malone     struct mac_bsdextended_object *object, size_t buflen, char *errstr)
78789ddbd45SDavid Malone {
78889ddbd45SDavid Malone 	int not_seen, flags;
78989ddbd45SDavid Malone 	int current, neg, nextnot;
790*bf417062SMarcelo Araujo 	int type;
79189ddbd45SDavid Malone 	uid_t uid_min, uid_max;
79289ddbd45SDavid Malone 	gid_t gid_min, gid_max;
79389ddbd45SDavid Malone 	struct fsid fsid;
79489ddbd45SDavid Malone 	size_t len;
79589ddbd45SDavid Malone 
79689ddbd45SDavid Malone 	current = 0;
79789ddbd45SDavid Malone 	flags = 0;
79889ddbd45SDavid Malone 	neg = 0;
79989ddbd45SDavid Malone 	nextnot = 0;
800*bf417062SMarcelo Araujo 	type = 0;
80189ddbd45SDavid Malone 
80289ddbd45SDavid Malone 	if (strcmp("not", argv[current]) == 0) {
80389ddbd45SDavid Malone 		not_seen = 1;
80489ddbd45SDavid Malone 		current++;
80546d1a925SRobert Watson 	} else
80689ddbd45SDavid Malone 		not_seen = 0;
80789ddbd45SDavid Malone 
80889ddbd45SDavid Malone 	while (current < argc) {
80989ddbd45SDavid Malone 		if (strcmp(argv[current], "uid") == 0) {
81089ddbd45SDavid Malone 			if (current + 2 > argc) {
81189ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "uid short");
81289ddbd45SDavid Malone 				return (-1);
81389ddbd45SDavid Malone 			}
81489ddbd45SDavid Malone 			if (flags & MBO_UID_DEFINED) {
81589ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "one uid only");
81689ddbd45SDavid Malone 				return (-1);
81789ddbd45SDavid Malone 			}
81889ddbd45SDavid Malone 			if (bsde_parse_uidrange(argv[current+1],
81989ddbd45SDavid Malone 			    &uid_min, &uid_max, buflen, errstr) < 0)
82089ddbd45SDavid Malone 				return (-1);
82189ddbd45SDavid Malone 			flags |= MBO_UID_DEFINED;
82289ddbd45SDavid Malone 			if (nextnot) {
82389ddbd45SDavid Malone 				neg ^= MBO_UID_DEFINED;
82489ddbd45SDavid Malone 				nextnot = 0;
82589ddbd45SDavid Malone 			}
82689ddbd45SDavid Malone 			current += 2;
82789ddbd45SDavid Malone 		} else if (strcmp(argv[current], "gid") == 0) {
82889ddbd45SDavid Malone 			if (current + 2 > argc) {
82989ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "gid short");
83089ddbd45SDavid Malone 				return (-1);
83189ddbd45SDavid Malone 			}
83289ddbd45SDavid Malone 			if (flags & MBO_GID_DEFINED) {
83389ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "one gid only");
83489ddbd45SDavid Malone 				return (-1);
83589ddbd45SDavid Malone 			}
83689ddbd45SDavid Malone 			if (bsde_parse_gidrange(argv[current+1],
83789ddbd45SDavid Malone 			    &gid_min, &gid_max, buflen, errstr) < 0)
83889ddbd45SDavid Malone 				return (-1);
83989ddbd45SDavid Malone 			flags |= MBO_GID_DEFINED;
84089ddbd45SDavid Malone 			if (nextnot) {
84189ddbd45SDavid Malone 				neg ^= MBO_GID_DEFINED;
84289ddbd45SDavid Malone 				nextnot = 0;
84389ddbd45SDavid Malone 			}
84489ddbd45SDavid Malone 			current += 2;
84589ddbd45SDavid Malone 		} else if (strcmp(argv[current], "filesys") == 0) {
84689ddbd45SDavid Malone 			if (current + 2 > argc) {
84789ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "filesys short");
84889ddbd45SDavid Malone 				return (-1);
84989ddbd45SDavid Malone 			}
85089ddbd45SDavid Malone 			if (flags & MBO_FSID_DEFINED) {
85189ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "one fsid only");
85289ddbd45SDavid Malone 				return (-1);
85389ddbd45SDavid Malone 			}
85489ddbd45SDavid Malone 			if (bsde_parse_fsid(argv[current+1], &fsid,
85589ddbd45SDavid Malone 			    buflen, errstr) < 0)
85689ddbd45SDavid Malone 				return (-1);
85789ddbd45SDavid Malone 			flags |= MBO_FSID_DEFINED;
85889ddbd45SDavid Malone 			if (nextnot) {
85989ddbd45SDavid Malone 				neg ^= MBO_FSID_DEFINED;
86089ddbd45SDavid Malone 				nextnot = 0;
86189ddbd45SDavid Malone 			}
86289ddbd45SDavid Malone 			current += 2;
86389ddbd45SDavid Malone 		} else if (strcmp(argv[current], "suid") == 0) {
86489ddbd45SDavid Malone 			flags |= MBO_SUID;
86589ddbd45SDavid Malone 			if (nextnot) {
86689ddbd45SDavid Malone 				neg ^= MBO_SUID;
86789ddbd45SDavid Malone 				nextnot = 0;
86889ddbd45SDavid Malone 			}
86989ddbd45SDavid Malone 			current += 1;
87089ddbd45SDavid Malone 		} else if (strcmp(argv[current], "sgid") == 0) {
87189ddbd45SDavid Malone 			flags |= MBO_SGID;
87289ddbd45SDavid Malone 			if (nextnot) {
87389ddbd45SDavid Malone 				neg ^= MBO_SGID;
87489ddbd45SDavid Malone 				nextnot = 0;
87589ddbd45SDavid Malone 			}
87689ddbd45SDavid Malone 			current += 1;
87789ddbd45SDavid Malone 		} else if (strcmp(argv[current], "uid_of_subject") == 0) {
87889ddbd45SDavid Malone 			flags |= MBO_UID_SUBJECT;
87989ddbd45SDavid Malone 			if (nextnot) {
88089ddbd45SDavid Malone 				neg ^= MBO_UID_SUBJECT;
88189ddbd45SDavid Malone 				nextnot = 0;
88289ddbd45SDavid Malone 			}
88389ddbd45SDavid Malone 			current += 1;
88489ddbd45SDavid Malone 		} else if (strcmp(argv[current], "gid_of_subject") == 0) {
88589ddbd45SDavid Malone 			flags |= MBO_GID_SUBJECT;
88689ddbd45SDavid Malone 			if (nextnot) {
88789ddbd45SDavid Malone 				neg ^= MBO_GID_SUBJECT;
88889ddbd45SDavid Malone 				nextnot = 0;
88989ddbd45SDavid Malone 			}
89089ddbd45SDavid Malone 			current += 1;
89189ddbd45SDavid Malone 		} else if (strcmp(argv[current], "type") == 0) {
89289ddbd45SDavid Malone 			if (current + 2 > argc) {
89389ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "type short");
89489ddbd45SDavid Malone 				return (-1);
89589ddbd45SDavid Malone 			}
89689ddbd45SDavid Malone 			if (flags & MBO_TYPE_DEFINED) {
89789ddbd45SDavid Malone 				len = snprintf(errstr, buflen, "one type only");
89889ddbd45SDavid Malone 				return (-1);
89989ddbd45SDavid Malone 			}
90089ddbd45SDavid Malone 			if (bsde_parse_type(argv[current+1], &type,
90189ddbd45SDavid Malone 			    buflen, errstr) < 0)
90289ddbd45SDavid Malone 				return (-1);
90389ddbd45SDavid Malone 			flags |= MBO_TYPE_DEFINED;
90489ddbd45SDavid Malone 			if (nextnot) {
90589ddbd45SDavid Malone 				neg ^= MBO_TYPE_DEFINED;
90689ddbd45SDavid Malone 				nextnot = 0;
90789ddbd45SDavid Malone 			}
90889ddbd45SDavid Malone 			current += 2;
90989ddbd45SDavid Malone 		} else if (strcmp(argv[current], "!") == 0) {
91089ddbd45SDavid Malone 			if (nextnot) {
91189ddbd45SDavid Malone 				len = snprintf(errstr, buflen,
91289ddbd45SDavid Malone 				    "double negative'");
91389ddbd45SDavid Malone 				return (-1);
91489ddbd45SDavid Malone 			}
91589ddbd45SDavid Malone 			nextnot = 1;
91689ddbd45SDavid Malone 			current += 1;
91789ddbd45SDavid Malone 		} else {
91889ddbd45SDavid Malone 			len = snprintf(errstr, buflen, "'%s' not expected",
91989ddbd45SDavid Malone 			    argv[current]);
92089ddbd45SDavid Malone 			return (-1);
92189ddbd45SDavid Malone 		}
92289ddbd45SDavid Malone 	}
92389ddbd45SDavid Malone 
92489ddbd45SDavid Malone 	object->mbo_flags = flags;
92589ddbd45SDavid Malone 	if (not_seen)
92689ddbd45SDavid Malone 		object->mbo_neg = MBO_ALL_FLAGS ^ neg;
92789ddbd45SDavid Malone 	else
92889ddbd45SDavid Malone 		object->mbo_neg = neg;
92989ddbd45SDavid Malone 	if (flags & MBO_UID_DEFINED) {
93089ddbd45SDavid Malone 		object->mbo_uid_min = uid_min;
93189ddbd45SDavid Malone 		object->mbo_uid_max = uid_max;
93289ddbd45SDavid Malone 	}
93389ddbd45SDavid Malone 	if (flags & MBO_GID_DEFINED) {
93489ddbd45SDavid Malone 		object->mbo_gid_min = gid_min;
93589ddbd45SDavid Malone 		object->mbo_gid_max = gid_max;
93689ddbd45SDavid Malone 	}
93789ddbd45SDavid Malone 	if (flags & MBO_FSID_DEFINED)
93889ddbd45SDavid Malone 		object->mbo_fsid = fsid;
93989ddbd45SDavid Malone 	if (flags & MBO_TYPE_DEFINED)
94089ddbd45SDavid Malone 		object->mbo_type = type;
94146d1a925SRobert Watson 
94246d1a925SRobert Watson 	return (0);
94346d1a925SRobert Watson }
94446d1a925SRobert Watson 
94546d1a925SRobert Watson int
94646d1a925SRobert Watson bsde_parse_mode(int argc, char *argv[], mode_t *mode, size_t buflen,
94746d1a925SRobert Watson     char *errstr)
94846d1a925SRobert Watson {
94946d1a925SRobert Watson 	size_t len;
95046d1a925SRobert Watson 	int i;
95146d1a925SRobert Watson 
95246d1a925SRobert Watson 	if (argc == 0) {
95346d1a925SRobert Watson 		len = snprintf(errstr, buflen, "mode expects mode value");
95446d1a925SRobert Watson 		return (-1);
95546d1a925SRobert Watson 	}
95646d1a925SRobert Watson 
95746d1a925SRobert Watson 	if (argc != 1) {
95846d1a925SRobert Watson 		len = snprintf(errstr, buflen, "'%s' unexpected", argv[1]);
95946d1a925SRobert Watson 		return (-1);
96046d1a925SRobert Watson 	}
96146d1a925SRobert Watson 
96246d1a925SRobert Watson 	*mode = 0;
96346d1a925SRobert Watson 	for (i = 0; i < strlen(argv[0]); i++) {
96446d1a925SRobert Watson 		switch (argv[0][i]) {
96546d1a925SRobert Watson 		case 'a':
966f4194603SRobert Watson 			*mode |= MBI_ADMIN;
96746d1a925SRobert Watson 			break;
96846d1a925SRobert Watson 		case 'r':
969f4194603SRobert Watson 			*mode |= MBI_READ;
97046d1a925SRobert Watson 			break;
97146d1a925SRobert Watson 		case 's':
972f4194603SRobert Watson 			*mode |= MBI_STAT;
97346d1a925SRobert Watson 			break;
97446d1a925SRobert Watson 		case 'w':
975f4194603SRobert Watson 			*mode |= MBI_WRITE;
97646d1a925SRobert Watson 			break;
97746d1a925SRobert Watson 		case 'x':
978f4194603SRobert Watson 			*mode |= MBI_EXEC;
97946d1a925SRobert Watson 			break;
98046d1a925SRobert Watson 		case 'n':
98146d1a925SRobert Watson 			/* ignore */
98246d1a925SRobert Watson 			break;
98346d1a925SRobert Watson 		default:
98446d1a925SRobert Watson 			len = snprintf(errstr, buflen, "Unknown mode letter: %c",
98546d1a925SRobert Watson 			    argv[0][i]);
98646d1a925SRobert Watson 			return (-1);
98746d1a925SRobert Watson 		}
98846d1a925SRobert Watson 	}
98946d1a925SRobert Watson 
99046d1a925SRobert Watson 	return (0);
99146d1a925SRobert Watson }
99246d1a925SRobert Watson 
99346d1a925SRobert Watson int
99446d1a925SRobert Watson bsde_parse_rule(int argc, char *argv[], struct mac_bsdextended_rule *rule,
99546d1a925SRobert Watson     size_t buflen, char *errstr)
99646d1a925SRobert Watson {
99746d1a925SRobert Watson 	int subject, subject_elements, subject_elements_length;
99846d1a925SRobert Watson 	int object, object_elements, object_elements_length;
99946d1a925SRobert Watson 	int mode, mode_elements, mode_elements_length;
100046d1a925SRobert Watson 	int error, i;
100146d1a925SRobert Watson 	size_t len;
100246d1a925SRobert Watson 
100346d1a925SRobert Watson 	bzero(rule, sizeof(*rule));
100446d1a925SRobert Watson 
100546d1a925SRobert Watson 	if (argc < 1) {
100646d1a925SRobert Watson 		len = snprintf(errstr, buflen, "Rule must begin with subject");
100746d1a925SRobert Watson 		return (-1);
100846d1a925SRobert Watson 	}
100946d1a925SRobert Watson 
101046d1a925SRobert Watson 	if (strcmp(argv[0], "subject") != 0) {
101146d1a925SRobert Watson 		len = snprintf(errstr, buflen, "Rule must begin with subject");
101246d1a925SRobert Watson 		return (-1);
101346d1a925SRobert Watson 	}
101446d1a925SRobert Watson 	subject = 0;
101546d1a925SRobert Watson 	subject_elements = 1;
101646d1a925SRobert Watson 
101746d1a925SRobert Watson 	/* Search forward for object. */
101846d1a925SRobert Watson 
101946d1a925SRobert Watson 	object = -1;
102046d1a925SRobert Watson 	for (i = 1; i < argc; i++)
102146d1a925SRobert Watson 		if (strcmp(argv[i], "object") == 0)
102246d1a925SRobert Watson 			object = i;
102346d1a925SRobert Watson 
102446d1a925SRobert Watson 	if (object == -1) {
102546d1a925SRobert Watson 		len = snprintf(errstr, buflen, "Rule must contain an object");
102646d1a925SRobert Watson 		return (-1);
102746d1a925SRobert Watson 	}
102846d1a925SRobert Watson 
102946d1a925SRobert Watson 	/* Search forward for mode. */
103046d1a925SRobert Watson 	mode = -1;
103146d1a925SRobert Watson 	for (i = object; i < argc; i++)
103246d1a925SRobert Watson 		if (strcmp(argv[i], "mode") == 0)
103346d1a925SRobert Watson 			mode = i;
103446d1a925SRobert Watson 
103546d1a925SRobert Watson 	if (mode == -1) {
103646d1a925SRobert Watson 		len = snprintf(errstr, buflen, "Rule must contain mode");
103746d1a925SRobert Watson 		return (-1);
103846d1a925SRobert Watson 	}
103946d1a925SRobert Watson 
104046d1a925SRobert Watson 	subject_elements_length = object - subject - 1;
104146d1a925SRobert Watson 	object_elements = object + 1;
104246d1a925SRobert Watson 	object_elements_length = mode - object_elements;
104346d1a925SRobert Watson 	mode_elements = mode + 1;
104446d1a925SRobert Watson 	mode_elements_length = argc - mode_elements;
104546d1a925SRobert Watson 
104689ddbd45SDavid Malone 	error = bsde_parse_subject(subject_elements_length,
104746d1a925SRobert Watson 	    argv + subject_elements, &rule->mbr_subject, buflen, errstr);
104846d1a925SRobert Watson 	if (error)
104946d1a925SRobert Watson 		return (-1);
105046d1a925SRobert Watson 
105189ddbd45SDavid Malone 	error = bsde_parse_object(object_elements_length,
105246d1a925SRobert Watson 	    argv + object_elements, &rule->mbr_object, buflen, errstr);
105346d1a925SRobert Watson 	if (error)
105446d1a925SRobert Watson 		return (-1);
105546d1a925SRobert Watson 
105646d1a925SRobert Watson 	error = bsde_parse_mode(mode_elements_length, argv + mode_elements,
105746d1a925SRobert Watson 	    &rule->mbr_mode, buflen, errstr);
105846d1a925SRobert Watson 	if (error)
105946d1a925SRobert Watson 		return (-1);
106046d1a925SRobert Watson 
106146d1a925SRobert Watson 	return (0);
106246d1a925SRobert Watson }
106346d1a925SRobert Watson 
106446d1a925SRobert Watson int
106546d1a925SRobert Watson bsde_parse_rule_string(const char *string, struct mac_bsdextended_rule *rule,
106646d1a925SRobert Watson     size_t buflen, char *errstr)
106746d1a925SRobert Watson {
106889ddbd45SDavid Malone 	char *stringdup, *stringp, *argv[100], **ap;
106946d1a925SRobert Watson 	int argc, error;
107046d1a925SRobert Watson 
107146d1a925SRobert Watson 	stringp = stringdup = strdup(string);
107246d1a925SRobert Watson 	while (*stringp == ' ' || *stringp == '\t')
107346d1a925SRobert Watson 		stringp++;
107446d1a925SRobert Watson 
107546d1a925SRobert Watson 	argc = 0;
107646d1a925SRobert Watson 	for (ap = argv; (*ap = strsep(&stringp, " \t")) != NULL;) {
107746d1a925SRobert Watson 		argc++;
107846d1a925SRobert Watson 		if (**ap != '\0')
107989ddbd45SDavid Malone 			if (++ap >= &argv[100])
108046d1a925SRobert Watson 				break;
108146d1a925SRobert Watson 	}
108246d1a925SRobert Watson 
108346d1a925SRobert Watson 	error = bsde_parse_rule(argc, argv, rule, buflen, errstr);
108446d1a925SRobert Watson 
108546d1a925SRobert Watson 	free(stringdup);
108646d1a925SRobert Watson 
108746d1a925SRobert Watson 	return (error);
108846d1a925SRobert Watson }
108946d1a925SRobert Watson 
109046d1a925SRobert Watson int
1091da30581eSRobert Watson bsde_get_mib(const char *string, int *name, size_t *namelen)
109246d1a925SRobert Watson {
1093da30581eSRobert Watson 	size_t len;
1094da30581eSRobert Watson 	int error;
109546d1a925SRobert Watson 
109646d1a925SRobert Watson 	len = *namelen;
109746d1a925SRobert Watson 	error = sysctlnametomib(string, name, &len);
109846d1a925SRobert Watson 	if (error)
109946d1a925SRobert Watson 		return (error);
110046d1a925SRobert Watson 
110146d1a925SRobert Watson 	*namelen = len;
110246d1a925SRobert Watson 	return (0);
110346d1a925SRobert Watson }
110446d1a925SRobert Watson 
1105*bf417062SMarcelo Araujo static int
110689ddbd45SDavid Malone bsde_check_version(size_t buflen, char *errstr)
110789ddbd45SDavid Malone {
110889ddbd45SDavid Malone 	size_t len;
110989ddbd45SDavid Malone 	int error;
111089ddbd45SDavid Malone 	int version;
111189ddbd45SDavid Malone 
111289ddbd45SDavid Malone 	len = sizeof(version);
111389ddbd45SDavid Malone 	error = sysctlbyname(MIB ".rule_version", &version, &len, NULL, 0);
111489ddbd45SDavid Malone 	if (error) {
111589ddbd45SDavid Malone 		len = snprintf(errstr, buflen, "version check failed: %s",
111689ddbd45SDavid Malone 		    strerror(errno));
111789ddbd45SDavid Malone 		return (-1);
111889ddbd45SDavid Malone 	}
111989ddbd45SDavid Malone 	if (version != MB_VERSION) {
112089ddbd45SDavid Malone 		len = snprintf(errstr, buflen, "module v%d != library v%d",
112189ddbd45SDavid Malone 		    version, MB_VERSION);
112289ddbd45SDavid Malone 		return (-1);
112389ddbd45SDavid Malone 	}
112489ddbd45SDavid Malone 	return (0);
112589ddbd45SDavid Malone }
112689ddbd45SDavid Malone 
112789ddbd45SDavid Malone int
112846d1a925SRobert Watson bsde_get_rule_count(size_t buflen, char *errstr)
112946d1a925SRobert Watson {
113046d1a925SRobert Watson 	size_t len;
113146d1a925SRobert Watson 	int error;
113246d1a925SRobert Watson 	int rule_count;
113346d1a925SRobert Watson 
113446d1a925SRobert Watson 	len = sizeof(rule_count);
11350f9a2306SBruce Evans 	error = sysctlbyname(MIB ".rule_count", &rule_count, &len, NULL, 0);
113646d1a925SRobert Watson 	if (error) {
1137fa1f169dSEd Maste 		len = snprintf(errstr, buflen, "%s", strerror(errno));
113846d1a925SRobert Watson 		return (-1);
113946d1a925SRobert Watson 	}
114046d1a925SRobert Watson 	if (len != sizeof(rule_count)) {
114146d1a925SRobert Watson 		len = snprintf(errstr, buflen, "Data error in %s.rule_count",
114246d1a925SRobert Watson 		    MIB);
114346d1a925SRobert Watson 		return (-1);
114446d1a925SRobert Watson 	}
114546d1a925SRobert Watson 
114646d1a925SRobert Watson 	return (rule_count);
114746d1a925SRobert Watson }
114846d1a925SRobert Watson 
114946d1a925SRobert Watson int
115046d1a925SRobert Watson bsde_get_rule_slots(size_t buflen, char *errstr)
115146d1a925SRobert Watson {
115246d1a925SRobert Watson 	size_t len;
115346d1a925SRobert Watson 	int error;
115446d1a925SRobert Watson 	int rule_slots;
115546d1a925SRobert Watson 
115646d1a925SRobert Watson 	len = sizeof(rule_slots);
11570f9a2306SBruce Evans 	error = sysctlbyname(MIB ".rule_slots", &rule_slots, &len, NULL, 0);
115846d1a925SRobert Watson 	if (error) {
1159fa1f169dSEd Maste 		len = snprintf(errstr, buflen, "%s", strerror(errno));
116046d1a925SRobert Watson 		return (-1);
116146d1a925SRobert Watson 	}
116246d1a925SRobert Watson 	if (len != sizeof(rule_slots)) {
116346d1a925SRobert Watson 		len = snprintf(errstr, buflen, "Data error in %s.rule_slots",
116446d1a925SRobert Watson 		    MIB);
116546d1a925SRobert Watson 		return (-1);
116646d1a925SRobert Watson 	}
116746d1a925SRobert Watson 
116846d1a925SRobert Watson 	return (rule_slots);
116946d1a925SRobert Watson }
117046d1a925SRobert Watson 
117146d1a925SRobert Watson /*
117246d1a925SRobert Watson  * Returns 0 for success;
117346d1a925SRobert Watson  * Returns -1 for failure;
117446d1a925SRobert Watson  * Returns -2 for not present
117546d1a925SRobert Watson  */
117646d1a925SRobert Watson int
117746d1a925SRobert Watson bsde_get_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t errlen,
117846d1a925SRobert Watson     char *errstr)
117946d1a925SRobert Watson {
118046d1a925SRobert Watson 	int name[10];
118146d1a925SRobert Watson 	size_t len, size;
118246d1a925SRobert Watson 	int error;
118346d1a925SRobert Watson 
118489ddbd45SDavid Malone 	if (bsde_check_version(errlen, errstr) != 0)
118589ddbd45SDavid Malone 		return (-1);
118689ddbd45SDavid Malone 
118746d1a925SRobert Watson 	len = 10;
118846d1a925SRobert Watson 	error = bsde_get_mib(MIB ".rules", name, &len);
118946d1a925SRobert Watson 	if (error) {
119046d1a925SRobert Watson 		len = snprintf(errstr, errlen, "%s: %s", MIB ".rules",
119146d1a925SRobert Watson 		    strerror(errno));
119246d1a925SRobert Watson 		return (-1);
119346d1a925SRobert Watson 	}
119446d1a925SRobert Watson 
119546d1a925SRobert Watson 	size = sizeof(*rule);
119646d1a925SRobert Watson 	name[len] = rulenum;
119746d1a925SRobert Watson 	len++;
119846d1a925SRobert Watson 	error = sysctl(name, len, rule, &size, NULL, 0);
119946d1a925SRobert Watson 	if (error  == -1 && errno == ENOENT)
120046d1a925SRobert Watson 		return (-2);
120146d1a925SRobert Watson 	if (error) {
120246d1a925SRobert Watson 		len = snprintf(errstr, errlen, "%s.%d: %s", MIB ".rules",
120346d1a925SRobert Watson 		    rulenum, strerror(errno));
120446d1a925SRobert Watson 		return (-1);
120546d1a925SRobert Watson 	} else if (size != sizeof(*rule)) {
120646d1a925SRobert Watson 		len = snprintf(errstr, errlen, "Data error in %s.%d: %s",
120746d1a925SRobert Watson 		    MIB ".rules", rulenum, strerror(errno));
120846d1a925SRobert Watson 		return (-1);
120946d1a925SRobert Watson 	}
121046d1a925SRobert Watson 
121146d1a925SRobert Watson 	return (0);
121246d1a925SRobert Watson }
121346d1a925SRobert Watson 
121446d1a925SRobert Watson int
121546d1a925SRobert Watson bsde_delete_rule(int rulenum, size_t buflen, char *errstr)
121646d1a925SRobert Watson {
121746d1a925SRobert Watson 	struct mac_bsdextended_rule rule;
121846d1a925SRobert Watson 	int name[10];
1219da1259f0SMarcelo Araujo 	size_t len;
122046d1a925SRobert Watson 	int error;
122146d1a925SRobert Watson 
122289ddbd45SDavid Malone 	if (bsde_check_version(buflen, errstr) != 0)
122389ddbd45SDavid Malone 		return (-1);
122489ddbd45SDavid Malone 
122546d1a925SRobert Watson 	len = 10;
122646d1a925SRobert Watson 	error = bsde_get_mib(MIB ".rules", name, &len);
122746d1a925SRobert Watson 	if (error) {
122846d1a925SRobert Watson 		len = snprintf(errstr, buflen, "%s: %s", MIB ".rules",
122946d1a925SRobert Watson 		    strerror(errno));
123046d1a925SRobert Watson 		return (-1);
123146d1a925SRobert Watson 	}
123246d1a925SRobert Watson 
123346d1a925SRobert Watson 	name[len] = rulenum;
123446d1a925SRobert Watson 	len++;
123546d1a925SRobert Watson 
1236a7c4e991SMarcelo Araujo 	error = sysctl(name, len, NULL, NULL, &rule, sizeof(rule));
123746d1a925SRobert Watson 	if (error) {
123846d1a925SRobert Watson 		len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
123946d1a925SRobert Watson 		    rulenum, strerror(errno));
124046d1a925SRobert Watson 		return (-1);
124146d1a925SRobert Watson 	}
124246d1a925SRobert Watson 
124346d1a925SRobert Watson 	return (0);
124446d1a925SRobert Watson }
124546d1a925SRobert Watson 
124646d1a925SRobert Watson int
124746d1a925SRobert Watson bsde_set_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t buflen,
124846d1a925SRobert Watson     char *errstr)
124946d1a925SRobert Watson {
125046d1a925SRobert Watson 	int name[10];
1251a7c4e991SMarcelo Araujo 	size_t len;
125246d1a925SRobert Watson 	int error;
125346d1a925SRobert Watson 
125489ddbd45SDavid Malone 	if (bsde_check_version(buflen, errstr) != 0)
125589ddbd45SDavid Malone 		return (-1);
125689ddbd45SDavid Malone 
125746d1a925SRobert Watson 	len = 10;
125846d1a925SRobert Watson 	error = bsde_get_mib(MIB ".rules", name, &len);
125946d1a925SRobert Watson 	if (error) {
126046d1a925SRobert Watson 		len = snprintf(errstr, buflen, "%s: %s", MIB ".rules",
126146d1a925SRobert Watson 		    strerror(errno));
126246d1a925SRobert Watson 		return (-1);
126346d1a925SRobert Watson 	}
126446d1a925SRobert Watson 
126546d1a925SRobert Watson 	name[len] = rulenum;
126646d1a925SRobert Watson 	len++;
126746d1a925SRobert Watson 
1268a7c4e991SMarcelo Araujo 	error = sysctl(name, len, NULL, NULL, rule, sizeof(*rule));
126946d1a925SRobert Watson 	if (error) {
127046d1a925SRobert Watson 		len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
127146d1a925SRobert Watson 		    rulenum, strerror(errno));
127246d1a925SRobert Watson 		return (-1);
127346d1a925SRobert Watson 	}
127446d1a925SRobert Watson 
127546d1a925SRobert Watson 	return (0);
127646d1a925SRobert Watson }
127747ab23aaSRobert Watson 
127847ab23aaSRobert Watson int
127947ab23aaSRobert Watson bsde_add_rule(int *rulenum, struct mac_bsdextended_rule *rule, size_t buflen,
128047ab23aaSRobert Watson     char *errstr)
128147ab23aaSRobert Watson {
128247ab23aaSRobert Watson 	char charstr[BUFSIZ];
128347ab23aaSRobert Watson 	int name[10];
1284a7c4e991SMarcelo Araujo 	size_t len;
128547ab23aaSRobert Watson 	int error, rule_slots;
128647ab23aaSRobert Watson 
128789ddbd45SDavid Malone 	if (bsde_check_version(buflen, errstr) != 0)
128889ddbd45SDavid Malone 		return (-1);
128989ddbd45SDavid Malone 
129047ab23aaSRobert Watson 	len = 10;
129147ab23aaSRobert Watson 	error = bsde_get_mib(MIB ".rules", name, &len);
129247ab23aaSRobert Watson 	if (error) {
129347ab23aaSRobert Watson 		len = snprintf(errstr, buflen, "%s: %s", MIB ".rules",
129447ab23aaSRobert Watson 		    strerror(errno));
129547ab23aaSRobert Watson 		return (-1);
129647ab23aaSRobert Watson 	}
129747ab23aaSRobert Watson 
129847ab23aaSRobert Watson 	rule_slots = bsde_get_rule_slots(BUFSIZ, charstr);
129947ab23aaSRobert Watson 	if (rule_slots == -1) {
130047ab23aaSRobert Watson 		len = snprintf(errstr, buflen, "unable to get rule slots: %s",
130147ab23aaSRobert Watson 		    strerror(errno));
130247ab23aaSRobert Watson 		return (-1);
130347ab23aaSRobert Watson 	}
130447ab23aaSRobert Watson 
130547ab23aaSRobert Watson 	name[len] = rule_slots;
130647ab23aaSRobert Watson 	len++;
130747ab23aaSRobert Watson 
1308a7c4e991SMarcelo Araujo 	error = sysctl(name, len, NULL, NULL, rule, sizeof(*rule));
130947ab23aaSRobert Watson 	if (error) {
131047ab23aaSRobert Watson 		len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules",
131147ab23aaSRobert Watson 		    rule_slots, strerror(errno));
131247ab23aaSRobert Watson 		return (-1);
131347ab23aaSRobert Watson 	}
131447ab23aaSRobert Watson 
131547ab23aaSRobert Watson 	if (rulenum != NULL)
1316fbc822aeSPawel Jakub Dawidek 		*rulenum = rule_slots;
131747ab23aaSRobert Watson 
131847ab23aaSRobert Watson 	return (0);
131947ab23aaSRobert Watson }
1320