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