1101206Srwatson/*- 2145140Srwatson * Copyright (c) 2002-2005 Networks Associates Technology, Inc. 3101206Srwatson * All rights reserved. 4101206Srwatson * 5106573Srwatson * This software was developed for the FreeBSD Project by Network Associates 6106573Srwatson * Laboratories, the Security Research Division of Network Associates, Inc. 7106573Srwatson * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 8106573Srwatson * DARPA CHATS research program. 9101206Srwatson * 10101206Srwatson * Redistribution and use in source and binary forms, with or without 11101206Srwatson * modification, are permitted provided that the following conditions 12101206Srwatson * are met: 13101206Srwatson * 1. Redistributions of source code must retain the above copyright 14101206Srwatson * notice, this list of conditions and the following disclaimer. 15101206Srwatson * 2. Redistributions in binary form must reproduce the above copyright 16101206Srwatson * notice, this list of conditions and the following disclaimer in the 17101206Srwatson * documentation and/or other materials provided with the distribution. 18101206Srwatson * 19101206Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20101206Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21101206Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22101206Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23101206Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24101206Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25101206Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26101206Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27101206Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28101206Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29101206Srwatson * SUCH DAMAGE. 30101206Srwatson * 31101206Srwatson * $FreeBSD$ 32101206Srwatson */ 33101206Srwatson#include <sys/param.h> 34101206Srwatson#include <sys/errno.h> 35101206Srwatson#include <sys/time.h> 36101206Srwatson#include <sys/sysctl.h> 37157986Sdwmalone#include <sys/ucred.h> 38157986Sdwmalone#include <sys/mount.h> 39101206Srwatson 40101206Srwatson#include <security/mac_bsdextended/mac_bsdextended.h> 41101206Srwatson 42101206Srwatson#include <grp.h> 43101206Srwatson#include <pwd.h> 44101206Srwatson#include <stdio.h> 45101206Srwatson#include <stdlib.h> 46101206Srwatson#include <string.h> 47101206Srwatson 48101885Srwatson#include "ugidfw.h" 49101206Srwatson 50101206Srwatson/* 51145432Strhodes * Text format for rules: rules contain subject and object elements, mode. 52157986Sdwmalone * The total form is "subject [s_element] object [o_element] mode [mode]". 53101206Srwatson * At least * one of a uid or gid entry must be present; both may also be 54101206Srwatson * present. 55101206Srwatson */ 56101206Srwatson 57101206Srwatson#define MIB "security.mac.bsdextended" 58101206Srwatson 59101206Srwatsonint 60101206Srwatsonbsde_rule_to_string(struct mac_bsdextended_rule *rule, char *buf, size_t buflen) 61101206Srwatson{ 62101206Srwatson struct group *grp; 63101206Srwatson struct passwd *pwd; 64157986Sdwmalone struct statfs *mntbuf; 65157986Sdwmalone char *cur, type[sizeof(rule->mbr_object.mbo_type) * CHAR_BIT + 1]; 66101206Srwatson size_t left, len; 67157986Sdwmalone int anymode, unknownmode, truncated, numfs, i, notdone; 68101206Srwatson 69101206Srwatson cur = buf; 70101206Srwatson left = buflen; 71101206Srwatson truncated = 0; 72101206Srwatson 73157986Sdwmalone len = snprintf(cur, left, "subject "); 74157986Sdwmalone if (len < 0 || len > left) 75157986Sdwmalone goto truncated; 76157986Sdwmalone left -= len; 77157986Sdwmalone cur += len; 78157986Sdwmalone if (rule->mbr_subject.mbs_flags) { 79157986Sdwmalone if (rule->mbr_subject.mbs_neg == MBS_ALL_FLAGS) { 80101206Srwatson len = snprintf(cur, left, "not "); 81101206Srwatson if (len < 0 || len > left) 82101206Srwatson goto truncated; 83101206Srwatson left -= len; 84101206Srwatson cur += len; 85157986Sdwmalone notdone = 1; 86157986Sdwmalone } else { 87157986Sdwmalone notdone = 0; 88101206Srwatson } 89157986Sdwmalone 90157986Sdwmalone if (!notdone && (rule->mbr_subject.mbs_neg & MBO_UID_DEFINED)) { 91157986Sdwmalone len = snprintf(cur, left, "! "); 92157986Sdwmalone if (len < 0 || len > left) 93157986Sdwmalone goto truncated; 94157986Sdwmalone left -= len; 95157986Sdwmalone cur += len; 96157986Sdwmalone } 97157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBO_UID_DEFINED) { 98157986Sdwmalone pwd = getpwuid(rule->mbr_subject.mbs_uid_min); 99101206Srwatson if (pwd != NULL) { 100157986Sdwmalone len = snprintf(cur, left, "uid %s", 101101206Srwatson pwd->pw_name); 102101206Srwatson if (len < 0 || len > left) 103101206Srwatson goto truncated; 104101206Srwatson left -= len; 105101206Srwatson cur += len; 106101206Srwatson } else { 107157986Sdwmalone len = snprintf(cur, left, "uid %u", 108157986Sdwmalone rule->mbr_subject.mbs_uid_min); 109101206Srwatson if (len < 0 || len > left) 110101206Srwatson goto truncated; 111101206Srwatson left -= len; 112101206Srwatson cur += len; 113101206Srwatson } 114157986Sdwmalone if (rule->mbr_subject.mbs_uid_min != 115157986Sdwmalone rule->mbr_subject.mbs_uid_max) { 116157986Sdwmalone pwd = getpwuid(rule->mbr_subject.mbs_uid_max); 117157986Sdwmalone if (pwd != NULL) { 118157986Sdwmalone len = snprintf(cur, left, ":%s ", 119157986Sdwmalone pwd->pw_name); 120157986Sdwmalone if (len < 0 || len > left) 121157986Sdwmalone goto truncated; 122157986Sdwmalone left -= len; 123157986Sdwmalone cur += len; 124157986Sdwmalone } else { 125157986Sdwmalone len = snprintf(cur, left, ":%u ", 126157986Sdwmalone rule->mbr_subject.mbs_uid_max); 127157986Sdwmalone if (len < 0 || len > left) 128157986Sdwmalone goto truncated; 129157986Sdwmalone left -= len; 130157986Sdwmalone cur += len; 131157986Sdwmalone } 132157986Sdwmalone } else { 133157986Sdwmalone len = snprintf(cur, left, " "); 134157986Sdwmalone if (len < 0 || len > left) 135157986Sdwmalone goto truncated; 136157986Sdwmalone left -= len; 137157986Sdwmalone cur += len; 138157986Sdwmalone } 139101206Srwatson } 140157986Sdwmalone if (!notdone && (rule->mbr_subject.mbs_neg & MBO_GID_DEFINED)) { 141157986Sdwmalone len = snprintf(cur, left, "! "); 142157986Sdwmalone if (len < 0 || len > left) 143157986Sdwmalone goto truncated; 144157986Sdwmalone left -= len; 145157986Sdwmalone cur += len; 146157986Sdwmalone } 147157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBO_GID_DEFINED) { 148157986Sdwmalone grp = getgrgid(rule->mbr_subject.mbs_gid_min); 149101206Srwatson if (grp != NULL) { 150157986Sdwmalone len = snprintf(cur, left, "gid %s", 151101206Srwatson grp->gr_name); 152101206Srwatson if (len < 0 || len > left) 153101206Srwatson goto truncated; 154101206Srwatson left -= len; 155101206Srwatson cur += len; 156101206Srwatson } else { 157157986Sdwmalone len = snprintf(cur, left, "gid %u", 158157986Sdwmalone rule->mbr_subject.mbs_gid_min); 159101206Srwatson if (len < 0 || len > left) 160101206Srwatson goto truncated; 161101206Srwatson left -= len; 162101206Srwatson cur += len; 163101206Srwatson } 164157986Sdwmalone if (rule->mbr_subject.mbs_gid_min != 165157986Sdwmalone rule->mbr_subject.mbs_gid_max) { 166157986Sdwmalone grp = getgrgid(rule->mbr_subject.mbs_gid_max); 167157986Sdwmalone if (grp != NULL) { 168157986Sdwmalone len = snprintf(cur, left, ":%s ", 169157986Sdwmalone grp->gr_name); 170157986Sdwmalone if (len < 0 || len > left) 171157986Sdwmalone goto truncated; 172157986Sdwmalone left -= len; 173157986Sdwmalone cur += len; 174157986Sdwmalone } else { 175157986Sdwmalone len = snprintf(cur, left, ":%u ", 176157986Sdwmalone rule->mbr_subject.mbs_gid_max); 177157986Sdwmalone if (len < 0 || len > left) 178157986Sdwmalone goto truncated; 179157986Sdwmalone left -= len; 180157986Sdwmalone cur += len; 181157986Sdwmalone } 182157986Sdwmalone } else { 183157986Sdwmalone len = snprintf(cur, left, " "); 184157986Sdwmalone if (len < 0 || len > left) 185157986Sdwmalone goto truncated; 186157986Sdwmalone left -= len; 187157986Sdwmalone cur += len; 188157986Sdwmalone } 189101206Srwatson } 190157986Sdwmalone if (!notdone && (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)) { 191157986Sdwmalone len = snprintf(cur, left, "! "); 192157986Sdwmalone if (len < 0 || len > left) 193157986Sdwmalone goto truncated; 194157986Sdwmalone left -= len; 195157986Sdwmalone cur += len; 196157986Sdwmalone } 197157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) { 198157986Sdwmalone len = snprintf(cur, left, "jailid %d ", 199157986Sdwmalone rule->mbr_subject.mbs_prison); 200157986Sdwmalone if (len < 0 || len > left) 201157986Sdwmalone goto truncated; 202157986Sdwmalone left -= len; 203157986Sdwmalone cur += len; 204157986Sdwmalone } 205101206Srwatson } 206101206Srwatson 207157986Sdwmalone len = snprintf(cur, left, "object "); 208157986Sdwmalone if (len < 0 || len > left) 209157986Sdwmalone goto truncated; 210157986Sdwmalone left -= len; 211157986Sdwmalone cur += len; 212157986Sdwmalone if (rule->mbr_object.mbo_flags) { 213157986Sdwmalone if (rule->mbr_object.mbo_neg == MBO_ALL_FLAGS) { 214101206Srwatson len = snprintf(cur, left, "not "); 215101206Srwatson if (len < 0 || len > left) 216101206Srwatson goto truncated; 217101206Srwatson left -= len; 218101206Srwatson cur += len; 219157986Sdwmalone notdone = 1; 220157986Sdwmalone } else { 221157986Sdwmalone notdone = 0; 222101206Srwatson } 223157986Sdwmalone 224157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)) { 225157986Sdwmalone len = snprintf(cur, left, "! "); 226157986Sdwmalone if (len < 0 || len > left) 227157986Sdwmalone goto truncated; 228157986Sdwmalone left -= len; 229157986Sdwmalone cur += len; 230157986Sdwmalone } 231157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) { 232157986Sdwmalone pwd = getpwuid(rule->mbr_object.mbo_uid_min); 233101206Srwatson if (pwd != NULL) { 234157986Sdwmalone len = snprintf(cur, left, "uid %s", 235101206Srwatson pwd->pw_name); 236101206Srwatson if (len < 0 || len > left) 237101206Srwatson goto truncated; 238101206Srwatson left -= len; 239101206Srwatson cur += len; 240101206Srwatson } else { 241157986Sdwmalone len = snprintf(cur, left, "uid %u", 242157986Sdwmalone rule->mbr_object.mbo_uid_min); 243157986Sdwmalone if (len < 0 || len > left) 244157986Sdwmalone goto truncated; 245101206Srwatson left -= len; 246101206Srwatson cur += len; 247101206Srwatson } 248157986Sdwmalone if (rule->mbr_object.mbo_uid_min != 249157986Sdwmalone rule->mbr_object.mbo_uid_max) { 250157986Sdwmalone pwd = getpwuid(rule->mbr_object.mbo_uid_max); 251157986Sdwmalone if (pwd != NULL) { 252157986Sdwmalone len = snprintf(cur, left, ":%s ", 253157986Sdwmalone pwd->pw_name); 254157986Sdwmalone if (len < 0 || len > left) 255157986Sdwmalone goto truncated; 256157986Sdwmalone left -= len; 257157986Sdwmalone cur += len; 258157986Sdwmalone } else { 259157986Sdwmalone len = snprintf(cur, left, ":%u ", 260157986Sdwmalone rule->mbr_object.mbo_uid_max); 261157986Sdwmalone if (len < 0 || len > left) 262157986Sdwmalone goto truncated; 263157986Sdwmalone left -= len; 264157986Sdwmalone cur += len; 265157986Sdwmalone } 266157986Sdwmalone } else { 267157986Sdwmalone len = snprintf(cur, left, " "); 268157986Sdwmalone if (len < 0 || len > left) 269157986Sdwmalone goto truncated; 270157986Sdwmalone left -= len; 271157986Sdwmalone cur += len; 272157986Sdwmalone } 273101206Srwatson } 274157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)) { 275157986Sdwmalone len = snprintf(cur, left, "! "); 276157986Sdwmalone if (len < 0 || len > left) 277157986Sdwmalone goto truncated; 278157986Sdwmalone left -= len; 279157986Sdwmalone cur += len; 280157986Sdwmalone } 281157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) { 282157986Sdwmalone grp = getgrgid(rule->mbr_object.mbo_gid_min); 283101206Srwatson if (grp != NULL) { 284157986Sdwmalone len = snprintf(cur, left, "gid %s", 285101206Srwatson grp->gr_name); 286101206Srwatson if (len < 0 || len > left) 287101206Srwatson goto truncated; 288101206Srwatson left -= len; 289101206Srwatson cur += len; 290101206Srwatson } else { 291157986Sdwmalone len = snprintf(cur, left, "gid %u", 292157986Sdwmalone rule->mbr_object.mbo_gid_min); 293101206Srwatson if (len < 0 || len > left) 294101206Srwatson goto truncated; 295101206Srwatson left -= len; 296101206Srwatson cur += len; 297101206Srwatson } 298157986Sdwmalone if (rule->mbr_object.mbo_gid_min != 299157986Sdwmalone rule->mbr_object.mbo_gid_max) { 300157986Sdwmalone grp = getgrgid(rule->mbr_object.mbo_gid_max); 301157986Sdwmalone if (grp != NULL) { 302157986Sdwmalone len = snprintf(cur, left, ":%s ", 303157986Sdwmalone grp->gr_name); 304157986Sdwmalone if (len < 0 || len > left) 305157986Sdwmalone goto truncated; 306157986Sdwmalone left -= len; 307157986Sdwmalone cur += len; 308157986Sdwmalone } else { 309157986Sdwmalone len = snprintf(cur, left, ":%u ", 310157986Sdwmalone rule->mbr_object.mbo_gid_max); 311157986Sdwmalone if (len < 0 || len > left) 312157986Sdwmalone goto truncated; 313157986Sdwmalone left -= len; 314157986Sdwmalone cur += len; 315157986Sdwmalone } 316157986Sdwmalone } else { 317157986Sdwmalone len = snprintf(cur, left, " "); 318157986Sdwmalone if (len < 0 || len > left) 319157986Sdwmalone goto truncated; 320157986Sdwmalone left -= len; 321157986Sdwmalone cur += len; 322157986Sdwmalone } 323101206Srwatson } 324157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)) { 325157986Sdwmalone len = snprintf(cur, left, "! "); 326157986Sdwmalone if (len < 0 || len > left) 327157986Sdwmalone goto truncated; 328157986Sdwmalone left -= len; 329157986Sdwmalone cur += len; 330157986Sdwmalone } 331157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { 332157986Sdwmalone numfs = getmntinfo(&mntbuf, MNT_NOWAIT); 333157986Sdwmalone for (i = 0; i < numfs; i++) 334157986Sdwmalone if (memcmp(&(rule->mbr_object.mbo_fsid), 335157986Sdwmalone &(mntbuf[i].f_fsid), 336157986Sdwmalone sizeof(mntbuf[i].f_fsid)) == 0) 337157986Sdwmalone break; 338157986Sdwmalone len = snprintf(cur, left, "filesys %s ", 339157986Sdwmalone i == numfs ? "???" : mntbuf[i].f_mntonname); 340157986Sdwmalone if (len < 0 || len > left) 341157986Sdwmalone goto truncated; 342157986Sdwmalone left -= len; 343157986Sdwmalone cur += len; 344157986Sdwmalone } 345157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_SUID)) { 346157986Sdwmalone len = snprintf(cur, left, "! "); 347157986Sdwmalone if (len < 0 || len > left) 348157986Sdwmalone goto truncated; 349157986Sdwmalone left -= len; 350157986Sdwmalone cur += len; 351157986Sdwmalone } 352157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_SUID) { 353157986Sdwmalone len = snprintf(cur, left, "suid "); 354157986Sdwmalone if (len < 0 || len > left) 355157986Sdwmalone goto truncated; 356157986Sdwmalone left -= len; 357157986Sdwmalone cur += len; 358157986Sdwmalone } 359157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_SGID)) { 360157986Sdwmalone len = snprintf(cur, left, "! "); 361157986Sdwmalone if (len < 0 || len > left) 362157986Sdwmalone goto truncated; 363157986Sdwmalone left -= len; 364157986Sdwmalone cur += len; 365157986Sdwmalone } 366157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_SGID) { 367157986Sdwmalone len = snprintf(cur, left, "sgid "); 368157986Sdwmalone if (len < 0 || len > left) 369157986Sdwmalone goto truncated; 370157986Sdwmalone left -= len; 371157986Sdwmalone cur += len; 372157986Sdwmalone } 373157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)) { 374157986Sdwmalone len = snprintf(cur, left, "! "); 375157986Sdwmalone if (len < 0 || len > left) 376157986Sdwmalone goto truncated; 377157986Sdwmalone left -= len; 378157986Sdwmalone cur += len; 379157986Sdwmalone } 380157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) { 381157986Sdwmalone len = snprintf(cur, left, "uid_of_subject "); 382157986Sdwmalone if (len < 0 || len > left) 383157986Sdwmalone goto truncated; 384157986Sdwmalone left -= len; 385157986Sdwmalone cur += len; 386157986Sdwmalone } 387157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)) { 388157986Sdwmalone len = snprintf(cur, left, "! "); 389157986Sdwmalone if (len < 0 || len > left) 390157986Sdwmalone goto truncated; 391157986Sdwmalone left -= len; 392157986Sdwmalone cur += len; 393157986Sdwmalone } 394157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) { 395157986Sdwmalone len = snprintf(cur, left, "gid_of_subject "); 396157986Sdwmalone if (len < 0 || len > left) 397157986Sdwmalone goto truncated; 398157986Sdwmalone left -= len; 399157986Sdwmalone cur += len; 400157986Sdwmalone } 401157986Sdwmalone if (!notdone && (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)) { 402157986Sdwmalone len = snprintf(cur, left, "! "); 403157986Sdwmalone if (len < 0 || len > left) 404157986Sdwmalone goto truncated; 405157986Sdwmalone left -= len; 406157986Sdwmalone cur += len; 407157986Sdwmalone } 408157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) { 409157986Sdwmalone i = 0; 410157986Sdwmalone if (rule->mbr_object.mbo_type & MBO_TYPE_REG) 411157986Sdwmalone type[i++] = 'r'; 412157986Sdwmalone if (rule->mbr_object.mbo_type & MBO_TYPE_DIR) 413157986Sdwmalone type[i++] = 'd'; 414157986Sdwmalone if (rule->mbr_object.mbo_type & MBO_TYPE_BLK) 415157986Sdwmalone type[i++] = 'b'; 416157986Sdwmalone if (rule->mbr_object.mbo_type & MBO_TYPE_CHR) 417157986Sdwmalone type[i++] = 'c'; 418157986Sdwmalone if (rule->mbr_object.mbo_type & MBO_TYPE_LNK) 419157986Sdwmalone type[i++] = 'l'; 420157986Sdwmalone if (rule->mbr_object.mbo_type & MBO_TYPE_SOCK) 421157986Sdwmalone type[i++] = 's'; 422157986Sdwmalone if (rule->mbr_object.mbo_type & MBO_TYPE_FIFO) 423157986Sdwmalone type[i++] = 'p'; 424157986Sdwmalone if (rule->mbr_object.mbo_type == MBO_ALL_TYPE) { 425157986Sdwmalone i = 0; 426157986Sdwmalone type[i++] = 'a'; 427157986Sdwmalone } 428157986Sdwmalone type[i++] = '\0'; 429157986Sdwmalone len = snprintf(cur, left, "type %s ", type); 430157986Sdwmalone if (len < 0 || len > left) 431157986Sdwmalone goto truncated; 432157986Sdwmalone left -= len; 433157986Sdwmalone cur += len; 434157986Sdwmalone } 435101206Srwatson } 436101206Srwatson 437101206Srwatson len = snprintf(cur, left, "mode "); 438101206Srwatson if (len < 0 || len > left) 439101206Srwatson goto truncated; 440101206Srwatson left -= len; 441101206Srwatson cur += len; 442101206Srwatson 443136740Srwatson anymode = (rule->mbr_mode & MBI_ALLPERM); 444136740Srwatson unknownmode = (rule->mbr_mode & ~MBI_ALLPERM); 445101206Srwatson 446136740Srwatson if (rule->mbr_mode & MBI_ADMIN) { 447101206Srwatson len = snprintf(cur, left, "a"); 448101206Srwatson if (len < 0 || len > left) 449101206Srwatson goto truncated; 450101206Srwatson 451101206Srwatson left -= len; 452101206Srwatson cur += len; 453101206Srwatson } 454136740Srwatson if (rule->mbr_mode & MBI_READ) { 455101206Srwatson len = snprintf(cur, left, "r"); 456101206Srwatson if (len < 0 || len > left) 457101206Srwatson goto truncated; 458101206Srwatson 459101206Srwatson left -= len; 460101206Srwatson cur += len; 461101206Srwatson } 462136740Srwatson if (rule->mbr_mode & MBI_STAT) { 463101206Srwatson len = snprintf(cur, left, "s"); 464101206Srwatson if (len < 0 || len > left) 465101206Srwatson goto truncated; 466101206Srwatson 467101206Srwatson left -= len; 468101206Srwatson cur += len; 469101206Srwatson } 470136740Srwatson if (rule->mbr_mode & MBI_WRITE) { 471101206Srwatson len = snprintf(cur, left, "w"); 472101206Srwatson if (len < 0 || len > left) 473101206Srwatson goto truncated; 474101206Srwatson 475101206Srwatson left -= len; 476101206Srwatson cur += len; 477101206Srwatson } 478136740Srwatson if (rule->mbr_mode & MBI_EXEC) { 479101206Srwatson len = snprintf(cur, left, "x"); 480101206Srwatson if (len < 0 || len > left) 481101206Srwatson goto truncated; 482101206Srwatson 483101206Srwatson left -= len; 484101206Srwatson cur += len; 485101206Srwatson } 486101206Srwatson if (!anymode) { 487101206Srwatson len = snprintf(cur, left, "n"); 488101206Srwatson if (len < 0 || len > left) 489101206Srwatson goto truncated; 490101206Srwatson 491101206Srwatson left -= len; 492101206Srwatson cur += len; 493101206Srwatson } 494101206Srwatson if (unknownmode) { 495101206Srwatson len = snprintf(cur, left, "?"); 496101206Srwatson if (len < 0 || len > left) 497101206Srwatson goto truncated; 498101206Srwatson 499101206Srwatson left -= len; 500101206Srwatson cur += len; 501101206Srwatson } 502101206Srwatson 503101206Srwatson return (0); 504101206Srwatson 505101206Srwatsontruncated: 506101206Srwatson return (-1); 507101206Srwatson} 508101206Srwatson 509101206Srwatsonint 510157986Sdwmalonebsde_parse_uidrange(char *spec, uid_t *min, uid_t *max, 511157986Sdwmalone size_t buflen, char *errstr){ 512101206Srwatson struct passwd *pwd; 513157986Sdwmalone uid_t uid1, uid2; 514157986Sdwmalone char *spec1, *spec2, *endp; 515157986Sdwmalone unsigned long value; 516101206Srwatson size_t len; 517101206Srwatson 518157986Sdwmalone spec2 = spec; 519157986Sdwmalone spec1 = strsep(&spec2, ":"); 520157986Sdwmalone 521157986Sdwmalone pwd = getpwnam(spec1); 522157986Sdwmalone if (pwd != NULL) 523157986Sdwmalone uid1 = pwd->pw_uid; 524157986Sdwmalone else { 525157986Sdwmalone value = strtoul(spec1, &endp, 10); 526157986Sdwmalone if (*endp != '\0') { 527157986Sdwmalone len = snprintf(errstr, buflen, 528157986Sdwmalone "invalid uid: '%s'", spec1); 529157986Sdwmalone return (-1); 530157986Sdwmalone } 531157986Sdwmalone uid1 = value; 532101206Srwatson } 533101206Srwatson 534157986Sdwmalone if (spec2 == NULL) { 535157986Sdwmalone *max = *min = uid1; 536157986Sdwmalone return (0); 537157986Sdwmalone } 538157986Sdwmalone 539157986Sdwmalone pwd = getpwnam(spec2); 540157986Sdwmalone if (pwd != NULL) 541157986Sdwmalone uid2 = pwd->pw_uid; 542157986Sdwmalone else { 543157986Sdwmalone value = strtoul(spec2, &endp, 10); 544157986Sdwmalone if (*endp != '\0') { 545157986Sdwmalone len = snprintf(errstr, buflen, 546157986Sdwmalone "invalid uid: '%s'", spec2); 547157986Sdwmalone return (-1); 548157986Sdwmalone } 549157986Sdwmalone uid2 = value; 550157986Sdwmalone } 551157986Sdwmalone 552157986Sdwmalone *min = uid1; 553157986Sdwmalone *max = uid2; 554157986Sdwmalone 555157986Sdwmalone return (0); 556157986Sdwmalone} 557157986Sdwmalone 558157986Sdwmaloneint 559157986Sdwmalonebsde_parse_gidrange(char *spec, gid_t *min, gid_t *max, 560157986Sdwmalone size_t buflen, char *errstr){ 561157986Sdwmalone struct group *grp; 562157986Sdwmalone gid_t gid1, gid2; 563157986Sdwmalone char *spec1, *spec2, *endp; 564157986Sdwmalone unsigned long value; 565157986Sdwmalone size_t len; 566157986Sdwmalone 567157986Sdwmalone spec2 = spec; 568157986Sdwmalone spec1 = strsep(&spec2, ":"); 569157986Sdwmalone 570157986Sdwmalone grp = getgrnam(spec1); 571157986Sdwmalone if (grp != NULL) 572157986Sdwmalone gid1 = grp->gr_gid; 573157986Sdwmalone else { 574157986Sdwmalone value = strtoul(spec1, &endp, 10); 575157986Sdwmalone if (*endp != '\0') { 576157986Sdwmalone len = snprintf(errstr, buflen, 577157986Sdwmalone "invalid gid: '%s'", spec1); 578157986Sdwmalone return (-1); 579157986Sdwmalone } 580157986Sdwmalone gid1 = value; 581157986Sdwmalone } 582157986Sdwmalone 583157986Sdwmalone if (spec2 == NULL) { 584157986Sdwmalone *max = *min = gid1; 585157986Sdwmalone return (0); 586157986Sdwmalone } 587157986Sdwmalone 588157986Sdwmalone grp = getgrnam(spec2); 589157986Sdwmalone if (grp != NULL) 590157986Sdwmalone gid2 = grp->gr_gid; 591157986Sdwmalone else { 592157986Sdwmalone value = strtoul(spec2, &endp, 10); 593157986Sdwmalone if (*endp != '\0') { 594157986Sdwmalone len = snprintf(errstr, buflen, 595157986Sdwmalone "invalid gid: '%s'", spec2); 596157986Sdwmalone return (-1); 597157986Sdwmalone } 598157986Sdwmalone gid2 = value; 599157986Sdwmalone } 600157986Sdwmalone 601157986Sdwmalone *min = gid1; 602157986Sdwmalone *max = gid2; 603157986Sdwmalone 604157986Sdwmalone return (0); 605157986Sdwmalone} 606157986Sdwmalone 607157986Sdwmaloneint 608157986Sdwmalonebsde_parse_subject(int argc, char *argv[], 609157986Sdwmalone struct mac_bsdextended_subject *subject, size_t buflen, char *errstr) 610157986Sdwmalone{ 611157986Sdwmalone int not_seen, flags; 612157986Sdwmalone int current, neg, nextnot; 613157986Sdwmalone char *endp; 614157986Sdwmalone uid_t uid_min, uid_max; 615157986Sdwmalone gid_t gid_min, gid_max; 616157986Sdwmalone int jid; 617157986Sdwmalone size_t len; 618157986Sdwmalone long value; 619157986Sdwmalone 620101206Srwatson current = 0; 621157986Sdwmalone flags = 0; 622157986Sdwmalone neg = 0; 623157986Sdwmalone nextnot = 0; 624101206Srwatson 625157986Sdwmalone if (strcmp("not", argv[current]) == 0) { 626101206Srwatson not_seen = 1; 627101206Srwatson current++; 628101206Srwatson } else 629101206Srwatson not_seen = 0; 630101206Srwatson 631157986Sdwmalone while (current < argc) { 632157986Sdwmalone if (strcmp(argv[current], "uid") == 0) { 633157986Sdwmalone if (current + 2 > argc) { 634157986Sdwmalone len = snprintf(errstr, buflen, "uid short"); 635157986Sdwmalone return (-1); 636157986Sdwmalone } 637157986Sdwmalone if (flags & MBS_UID_DEFINED) { 638157986Sdwmalone len = snprintf(errstr, buflen, "one uid only"); 639157986Sdwmalone return (-1); 640157986Sdwmalone } 641157986Sdwmalone if (bsde_parse_uidrange(argv[current+1], 642157986Sdwmalone &uid_min, &uid_max, buflen, errstr) < 0) 643157986Sdwmalone return (-1); 644157986Sdwmalone flags |= MBS_UID_DEFINED; 645157986Sdwmalone if (nextnot) { 646157986Sdwmalone neg ^= MBS_UID_DEFINED; 647157986Sdwmalone nextnot = 0; 648157986Sdwmalone } 649157986Sdwmalone current += 2; 650157986Sdwmalone } else if (strcmp(argv[current], "gid") == 0) { 651157986Sdwmalone if (current + 2 > argc) { 652157986Sdwmalone len = snprintf(errstr, buflen, "gid short"); 653157986Sdwmalone return (-1); 654157986Sdwmalone } 655157986Sdwmalone if (flags & MBS_GID_DEFINED) { 656157986Sdwmalone len = snprintf(errstr, buflen, "one gid only"); 657157986Sdwmalone return (-1); 658157986Sdwmalone } 659157986Sdwmalone if (bsde_parse_gidrange(argv[current+1], 660157986Sdwmalone &gid_min, &gid_max, buflen, errstr) < 0) 661157986Sdwmalone return (-1); 662157986Sdwmalone flags |= MBS_GID_DEFINED; 663157986Sdwmalone if (nextnot) { 664157986Sdwmalone neg ^= MBS_GID_DEFINED; 665157986Sdwmalone nextnot = 0; 666157986Sdwmalone } 667157986Sdwmalone current += 2; 668157986Sdwmalone } else if (strcmp(argv[current], "jailid") == 0) { 669157986Sdwmalone if (current + 2 > argc) { 670157986Sdwmalone len = snprintf(errstr, buflen, "prison short"); 671157986Sdwmalone return (-1); 672157986Sdwmalone } 673157986Sdwmalone if (flags & MBS_PRISON_DEFINED) { 674157986Sdwmalone len = snprintf(errstr, buflen, "one jail only"); 675157986Sdwmalone return (-1); 676157986Sdwmalone } 677101206Srwatson value = strtol(argv[current+1], &endp, 10); 678101206Srwatson if (*endp != '\0') { 679101206Srwatson len = snprintf(errstr, buflen, 680157986Sdwmalone "invalid jid: '%s'", argv[current+1]); 681101206Srwatson return (-1); 682101206Srwatson } 683157986Sdwmalone jid = value; 684157986Sdwmalone flags |= MBS_PRISON_DEFINED; 685157986Sdwmalone if (nextnot) { 686157986Sdwmalone neg ^= MBS_PRISON_DEFINED; 687157986Sdwmalone nextnot = 0; 688157986Sdwmalone } 689157986Sdwmalone current += 2; 690157986Sdwmalone } else if (strcmp(argv[current], "!") == 0) { 691157986Sdwmalone if (nextnot) { 692101206Srwatson len = snprintf(errstr, buflen, 693157986Sdwmalone "double negative"); 694101206Srwatson return (-1); 695101206Srwatson } 696157986Sdwmalone nextnot = 1; 697157986Sdwmalone current += 1; 698157986Sdwmalone } else { 699157986Sdwmalone len = snprintf(errstr, buflen, "'%s' not expected", 700157986Sdwmalone argv[current]); 701157986Sdwmalone return (-1); 702101206Srwatson } 703157986Sdwmalone } 704157986Sdwmalone 705157986Sdwmalone subject->mbs_flags = flags; 706157986Sdwmalone if (not_seen) 707157986Sdwmalone subject->mbs_neg = MBS_ALL_FLAGS ^ neg; 708157986Sdwmalone else 709157986Sdwmalone subject->mbs_neg = neg; 710157986Sdwmalone if (flags & MBS_UID_DEFINED) { 711157986Sdwmalone subject->mbs_uid_min = uid_min; 712157986Sdwmalone subject->mbs_uid_max = uid_max; 713157986Sdwmalone } 714157986Sdwmalone if (flags & MBS_GID_DEFINED) { 715157986Sdwmalone subject->mbs_gid_min = gid_min; 716157986Sdwmalone subject->mbs_gid_max = gid_max; 717157986Sdwmalone } 718157986Sdwmalone if (flags & MBS_PRISON_DEFINED) 719157986Sdwmalone subject->mbs_prison = jid; 720157986Sdwmalone 721157986Sdwmalone return (0); 722157986Sdwmalone} 723157986Sdwmalone 724157986Sdwmaloneint 725157986Sdwmalonebsde_parse_type(char *spec, int *type, size_t buflen, char *errstr) 726157986Sdwmalone{ 727157986Sdwmalone size_t len; 728157986Sdwmalone int i; 729157986Sdwmalone 730157986Sdwmalone *type = 0; 731157986Sdwmalone for (i = 0; i < strlen(spec); i++) { 732157986Sdwmalone switch (spec[i]) { 733157986Sdwmalone case 'r': 734157986Sdwmalone case '-': 735157986Sdwmalone *type |= MBO_TYPE_REG; 736157986Sdwmalone break; 737157986Sdwmalone case 'd': 738157986Sdwmalone *type |= MBO_TYPE_DIR; 739157986Sdwmalone break; 740157986Sdwmalone case 'b': 741157986Sdwmalone *type |= MBO_TYPE_BLK; 742157986Sdwmalone break; 743157986Sdwmalone case 'c': 744157986Sdwmalone *type |= MBO_TYPE_CHR; 745157986Sdwmalone break; 746157986Sdwmalone case 'l': 747157986Sdwmalone *type |= MBO_TYPE_LNK; 748157986Sdwmalone break; 749157986Sdwmalone case 's': 750157986Sdwmalone *type |= MBO_TYPE_SOCK; 751157986Sdwmalone break; 752157986Sdwmalone case 'p': 753157986Sdwmalone *type |= MBO_TYPE_FIFO; 754157986Sdwmalone break; 755157986Sdwmalone case 'a': 756157986Sdwmalone *type |= MBO_ALL_TYPE; 757157986Sdwmalone break; 758157986Sdwmalone default: 759157986Sdwmalone len = snprintf(errstr, buflen, "Unknown type code: %c", 760157986Sdwmalone spec[i]); 761157986Sdwmalone return (-1); 762157986Sdwmalone } 763157986Sdwmalone } 764157986Sdwmalone 765157986Sdwmalone return (0); 766157986Sdwmalone} 767157986Sdwmalone 768157986Sdwmaloneint 769157986Sdwmalonebsde_parse_fsid(char *spec, struct fsid *fsid, size_t buflen, char *errstr) 770157986Sdwmalone{ 771157986Sdwmalone size_t len; 772157986Sdwmalone struct statfs buf; 773157986Sdwmalone 774157986Sdwmalone if (statfs(spec, &buf) < 0) { 775157986Sdwmalone len = snprintf(errstr, buflen, "Unable to get id for %s: %s", 776157986Sdwmalone spec, strerror(errno)); 777101206Srwatson return (-1); 778101206Srwatson } 779101206Srwatson 780157986Sdwmalone *fsid = buf.f_fsid; 781157986Sdwmalone 782157986Sdwmalone return (0); 783157986Sdwmalone} 784157986Sdwmalone 785157986Sdwmaloneint 786157986Sdwmalonebsde_parse_object(int argc, char *argv[], 787157986Sdwmalone struct mac_bsdextended_object *object, size_t buflen, char *errstr) 788157986Sdwmalone{ 789157986Sdwmalone int not_seen, flags; 790157986Sdwmalone int current, neg, nextnot; 791157986Sdwmalone uid_t uid_min, uid_max; 792157986Sdwmalone gid_t gid_min, gid_max; 793157986Sdwmalone int type; 794157986Sdwmalone struct fsid fsid; 795157986Sdwmalone size_t len; 796157986Sdwmalone 797157986Sdwmalone current = 0; 798157986Sdwmalone flags = 0; 799157986Sdwmalone neg = 0; 800157986Sdwmalone nextnot = 0; 801157986Sdwmalone 802157986Sdwmalone if (strcmp("not", argv[current]) == 0) { 803157986Sdwmalone not_seen = 1; 804157986Sdwmalone current++; 805157986Sdwmalone } else 806157986Sdwmalone not_seen = 0; 807157986Sdwmalone 808157986Sdwmalone while (current < argc) { 809157986Sdwmalone if (strcmp(argv[current], "uid") == 0) { 810157986Sdwmalone if (current + 2 > argc) { 811157986Sdwmalone len = snprintf(errstr, buflen, "uid short"); 812101206Srwatson return (-1); 813101206Srwatson } 814157986Sdwmalone if (flags & MBO_UID_DEFINED) { 815157986Sdwmalone len = snprintf(errstr, buflen, "one uid only"); 816157986Sdwmalone return (-1); 817157986Sdwmalone } 818157986Sdwmalone if (bsde_parse_uidrange(argv[current+1], 819157986Sdwmalone &uid_min, &uid_max, buflen, errstr) < 0) 820157986Sdwmalone return (-1); 821157986Sdwmalone flags |= MBO_UID_DEFINED; 822157986Sdwmalone if (nextnot) { 823157986Sdwmalone neg ^= MBO_UID_DEFINED; 824157986Sdwmalone nextnot = 0; 825157986Sdwmalone } 826157986Sdwmalone current += 2; 827157986Sdwmalone } else if (strcmp(argv[current], "gid") == 0) { 828101206Srwatson if (current + 2 > argc) { 829157986Sdwmalone len = snprintf(errstr, buflen, "gid short"); 830101206Srwatson return (-1); 831101206Srwatson } 832157986Sdwmalone if (flags & MBO_GID_DEFINED) { 833157986Sdwmalone len = snprintf(errstr, buflen, "one gid only"); 834157986Sdwmalone return (-1); 835101206Srwatson } 836157986Sdwmalone if (bsde_parse_gidrange(argv[current+1], 837157986Sdwmalone &gid_min, &gid_max, buflen, errstr) < 0) 838157986Sdwmalone return (-1); 839157986Sdwmalone flags |= MBO_GID_DEFINED; 840157986Sdwmalone if (nextnot) { 841157986Sdwmalone neg ^= MBO_GID_DEFINED; 842157986Sdwmalone nextnot = 0; 843157986Sdwmalone } 844101206Srwatson current += 2; 845157986Sdwmalone } else if (strcmp(argv[current], "filesys") == 0) { 846157986Sdwmalone if (current + 2 > argc) { 847157986Sdwmalone len = snprintf(errstr, buflen, "filesys short"); 848101206Srwatson return (-1); 849101206Srwatson } 850157986Sdwmalone if (flags & MBO_FSID_DEFINED) { 851157986Sdwmalone len = snprintf(errstr, buflen, "one fsid only"); 852157986Sdwmalone return (-1); 853157986Sdwmalone } 854157986Sdwmalone if (bsde_parse_fsid(argv[current+1], &fsid, 855157986Sdwmalone buflen, errstr) < 0) 856157986Sdwmalone return (-1); 857157986Sdwmalone flags |= MBO_FSID_DEFINED; 858157986Sdwmalone if (nextnot) { 859157986Sdwmalone neg ^= MBO_FSID_DEFINED; 860157986Sdwmalone nextnot = 0; 861157986Sdwmalone } 862157986Sdwmalone current += 2; 863157986Sdwmalone } else if (strcmp(argv[current], "suid") == 0) { 864157986Sdwmalone flags |= MBO_SUID; 865157986Sdwmalone if (nextnot) { 866157986Sdwmalone neg ^= MBO_SUID; 867157986Sdwmalone nextnot = 0; 868157986Sdwmalone } 869157986Sdwmalone current += 1; 870157986Sdwmalone } else if (strcmp(argv[current], "sgid") == 0) { 871157986Sdwmalone flags |= MBO_SGID; 872157986Sdwmalone if (nextnot) { 873157986Sdwmalone neg ^= MBO_SGID; 874157986Sdwmalone nextnot = 0; 875157986Sdwmalone } 876157986Sdwmalone current += 1; 877157986Sdwmalone } else if (strcmp(argv[current], "uid_of_subject") == 0) { 878157986Sdwmalone flags |= MBO_UID_SUBJECT; 879157986Sdwmalone if (nextnot) { 880157986Sdwmalone neg ^= MBO_UID_SUBJECT; 881157986Sdwmalone nextnot = 0; 882157986Sdwmalone } 883157986Sdwmalone current += 1; 884157986Sdwmalone } else if (strcmp(argv[current], "gid_of_subject") == 0) { 885157986Sdwmalone flags |= MBO_GID_SUBJECT; 886157986Sdwmalone if (nextnot) { 887157986Sdwmalone neg ^= MBO_GID_SUBJECT; 888157986Sdwmalone nextnot = 0; 889157986Sdwmalone } 890157986Sdwmalone current += 1; 891157986Sdwmalone } else if (strcmp(argv[current], "type") == 0) { 892101206Srwatson if (current + 2 > argc) { 893157986Sdwmalone len = snprintf(errstr, buflen, "type short"); 894101206Srwatson return (-1); 895101206Srwatson } 896157986Sdwmalone if (flags & MBO_TYPE_DEFINED) { 897157986Sdwmalone len = snprintf(errstr, buflen, "one type only"); 898157986Sdwmalone return (-1); 899101206Srwatson } 900157986Sdwmalone if (bsde_parse_type(argv[current+1], &type, 901157986Sdwmalone buflen, errstr) < 0) 902157986Sdwmalone return (-1); 903157986Sdwmalone flags |= MBO_TYPE_DEFINED; 904157986Sdwmalone if (nextnot) { 905157986Sdwmalone neg ^= MBO_TYPE_DEFINED; 906157986Sdwmalone nextnot = 0; 907157986Sdwmalone } 908101206Srwatson current += 2; 909157986Sdwmalone } else if (strcmp(argv[current], "!") == 0) { 910157986Sdwmalone if (nextnot) { 911157986Sdwmalone len = snprintf(errstr, buflen, 912157986Sdwmalone "double negative'"); 913157986Sdwmalone return (-1); 914157986Sdwmalone } 915157986Sdwmalone nextnot = 1; 916157986Sdwmalone current += 1; 917101206Srwatson } else { 918101206Srwatson len = snprintf(errstr, buflen, "'%s' not expected", 919101206Srwatson argv[current]); 920101206Srwatson return (-1); 921157986Sdwmalone } 922101206Srwatson } 923101206Srwatson 924157986Sdwmalone object->mbo_flags = flags; 925157986Sdwmalone if (not_seen) 926157986Sdwmalone object->mbo_neg = MBO_ALL_FLAGS ^ neg; 927157986Sdwmalone else 928157986Sdwmalone object->mbo_neg = neg; 929157986Sdwmalone if (flags & MBO_UID_DEFINED) { 930157986Sdwmalone object->mbo_uid_min = uid_min; 931157986Sdwmalone object->mbo_uid_max = uid_max; 932101206Srwatson } 933157986Sdwmalone if (flags & MBO_GID_DEFINED) { 934157986Sdwmalone object->mbo_gid_min = gid_min; 935157986Sdwmalone object->mbo_gid_max = gid_max; 936157986Sdwmalone } 937157986Sdwmalone if (flags & MBO_FSID_DEFINED) 938157986Sdwmalone object->mbo_fsid = fsid; 939157986Sdwmalone if (flags & MBO_TYPE_DEFINED) 940157986Sdwmalone object->mbo_type = type; 941101206Srwatson 942101206Srwatson return (0); 943101206Srwatson} 944101206Srwatson 945101206Srwatsonint 946101206Srwatsonbsde_parse_mode(int argc, char *argv[], mode_t *mode, size_t buflen, 947101206Srwatson char *errstr) 948101206Srwatson{ 949101206Srwatson size_t len; 950101206Srwatson int i; 951101206Srwatson 952101206Srwatson if (argc == 0) { 953101206Srwatson len = snprintf(errstr, buflen, "mode expects mode value"); 954101206Srwatson return (-1); 955101206Srwatson } 956101206Srwatson 957101206Srwatson if (argc != 1) { 958101206Srwatson len = snprintf(errstr, buflen, "'%s' unexpected", argv[1]); 959101206Srwatson return (-1); 960101206Srwatson } 961101206Srwatson 962101206Srwatson *mode = 0; 963101206Srwatson for (i = 0; i < strlen(argv[0]); i++) { 964101206Srwatson switch (argv[0][i]) { 965101206Srwatson case 'a': 966136740Srwatson *mode |= MBI_ADMIN; 967101206Srwatson break; 968101206Srwatson case 'r': 969136740Srwatson *mode |= MBI_READ; 970101206Srwatson break; 971101206Srwatson case 's': 972136740Srwatson *mode |= MBI_STAT; 973101206Srwatson break; 974101206Srwatson case 'w': 975136740Srwatson *mode |= MBI_WRITE; 976101206Srwatson break; 977101206Srwatson case 'x': 978136740Srwatson *mode |= MBI_EXEC; 979101206Srwatson break; 980101206Srwatson case 'n': 981101206Srwatson /* ignore */ 982101206Srwatson break; 983101206Srwatson default: 984101206Srwatson len = snprintf(errstr, buflen, "Unknown mode letter: %c", 985101206Srwatson argv[0][i]); 986101206Srwatson return (-1); 987101206Srwatson } 988101206Srwatson } 989101206Srwatson 990101206Srwatson return (0); 991101206Srwatson} 992101206Srwatson 993101206Srwatsonint 994101206Srwatsonbsde_parse_rule(int argc, char *argv[], struct mac_bsdextended_rule *rule, 995101206Srwatson size_t buflen, char *errstr) 996101206Srwatson{ 997101206Srwatson int subject, subject_elements, subject_elements_length; 998101206Srwatson int object, object_elements, object_elements_length; 999101206Srwatson int mode, mode_elements, mode_elements_length; 1000101206Srwatson int error, i; 1001101206Srwatson size_t len; 1002101206Srwatson 1003101206Srwatson bzero(rule, sizeof(*rule)); 1004101206Srwatson 1005101206Srwatson if (argc < 1) { 1006101206Srwatson len = snprintf(errstr, buflen, "Rule must begin with subject"); 1007101206Srwatson return (-1); 1008101206Srwatson } 1009101206Srwatson 1010101206Srwatson if (strcmp(argv[0], "subject") != 0) { 1011101206Srwatson len = snprintf(errstr, buflen, "Rule must begin with subject"); 1012101206Srwatson return (-1); 1013101206Srwatson } 1014101206Srwatson subject = 0; 1015101206Srwatson subject_elements = 1; 1016101206Srwatson 1017101206Srwatson /* Search forward for object. */ 1018101206Srwatson 1019101206Srwatson object = -1; 1020101206Srwatson for (i = 1; i < argc; i++) 1021101206Srwatson if (strcmp(argv[i], "object") == 0) 1022101206Srwatson object = i; 1023101206Srwatson 1024101206Srwatson if (object == -1) { 1025101206Srwatson len = snprintf(errstr, buflen, "Rule must contain an object"); 1026101206Srwatson return (-1); 1027101206Srwatson } 1028101206Srwatson 1029101206Srwatson /* Search forward for mode. */ 1030101206Srwatson mode = -1; 1031101206Srwatson for (i = object; i < argc; i++) 1032101206Srwatson if (strcmp(argv[i], "mode") == 0) 1033101206Srwatson mode = i; 1034101206Srwatson 1035101206Srwatson if (mode == -1) { 1036101206Srwatson len = snprintf(errstr, buflen, "Rule must contain mode"); 1037101206Srwatson return (-1); 1038101206Srwatson } 1039101206Srwatson 1040101206Srwatson subject_elements_length = object - subject - 1; 1041101206Srwatson object_elements = object + 1; 1042101206Srwatson object_elements_length = mode - object_elements; 1043101206Srwatson mode_elements = mode + 1; 1044101206Srwatson mode_elements_length = argc - mode_elements; 1045101206Srwatson 1046157986Sdwmalone error = bsde_parse_subject(subject_elements_length, 1047101206Srwatson argv + subject_elements, &rule->mbr_subject, buflen, errstr); 1048101206Srwatson if (error) 1049101206Srwatson return (-1); 1050101206Srwatson 1051157986Sdwmalone error = bsde_parse_object(object_elements_length, 1052101206Srwatson argv + object_elements, &rule->mbr_object, buflen, errstr); 1053101206Srwatson if (error) 1054101206Srwatson return (-1); 1055101206Srwatson 1056101206Srwatson error = bsde_parse_mode(mode_elements_length, argv + mode_elements, 1057101206Srwatson &rule->mbr_mode, buflen, errstr); 1058101206Srwatson if (error) 1059101206Srwatson return (-1); 1060101206Srwatson 1061101206Srwatson return (0); 1062101206Srwatson} 1063101206Srwatson 1064101206Srwatsonint 1065101206Srwatsonbsde_parse_rule_string(const char *string, struct mac_bsdextended_rule *rule, 1066101206Srwatson size_t buflen, char *errstr) 1067101206Srwatson{ 1068157986Sdwmalone char *stringdup, *stringp, *argv[100], **ap; 1069101206Srwatson int argc, error; 1070101206Srwatson 1071101206Srwatson stringp = stringdup = strdup(string); 1072101206Srwatson while (*stringp == ' ' || *stringp == '\t') 1073101206Srwatson stringp++; 1074101206Srwatson 1075101206Srwatson argc = 0; 1076101206Srwatson for (ap = argv; (*ap = strsep(&stringp, " \t")) != NULL;) { 1077101206Srwatson argc++; 1078101206Srwatson if (**ap != '\0') 1079157986Sdwmalone if (++ap >= &argv[100]) 1080101206Srwatson break; 1081101206Srwatson } 1082101206Srwatson 1083101206Srwatson error = bsde_parse_rule(argc, argv, rule, buflen, errstr); 1084101206Srwatson 1085101206Srwatson free(stringdup); 1086101206Srwatson 1087101206Srwatson return (error); 1088101206Srwatson} 1089101206Srwatson 1090101206Srwatsonint 1091104038Srwatsonbsde_get_mib(const char *string, int *name, size_t *namelen) 1092101206Srwatson{ 1093104038Srwatson size_t len; 1094104038Srwatson int error; 1095101206Srwatson 1096101206Srwatson len = *namelen; 1097101206Srwatson error = sysctlnametomib(string, name, &len); 1098101206Srwatson if (error) 1099101206Srwatson return (error); 1100101206Srwatson 1101101206Srwatson *namelen = len; 1102101206Srwatson return (0); 1103101206Srwatson} 1104101206Srwatson 1105101206Srwatsonint 1106157986Sdwmalonebsde_check_version(size_t buflen, char *errstr) 1107157986Sdwmalone{ 1108157986Sdwmalone size_t len; 1109157986Sdwmalone int error; 1110157986Sdwmalone int version; 1111157986Sdwmalone 1112157986Sdwmalone len = sizeof(version); 1113157986Sdwmalone error = sysctlbyname(MIB ".rule_version", &version, &len, NULL, 0); 1114157986Sdwmalone if (error) { 1115157986Sdwmalone len = snprintf(errstr, buflen, "version check failed: %s", 1116157986Sdwmalone strerror(errno)); 1117157986Sdwmalone return (-1); 1118157986Sdwmalone } 1119157986Sdwmalone if (version != MB_VERSION) { 1120157986Sdwmalone len = snprintf(errstr, buflen, "module v%d != library v%d", 1121157986Sdwmalone version, MB_VERSION); 1122157986Sdwmalone return (-1); 1123157986Sdwmalone } 1124157986Sdwmalone return (0); 1125157986Sdwmalone} 1126157986Sdwmalone 1127157986Sdwmaloneint 1128101206Srwatsonbsde_get_rule_count(size_t buflen, char *errstr) 1129101206Srwatson{ 1130101206Srwatson size_t len; 1131101206Srwatson int error; 1132101206Srwatson int rule_count; 1133101206Srwatson 1134101206Srwatson len = sizeof(rule_count); 1135126835Sbde error = sysctlbyname(MIB ".rule_count", &rule_count, &len, NULL, 0); 1136101206Srwatson if (error) { 1137216953Semaste len = snprintf(errstr, buflen, "%s", strerror(errno)); 1138101206Srwatson return (-1); 1139101206Srwatson } 1140101206Srwatson if (len != sizeof(rule_count)) { 1141101206Srwatson len = snprintf(errstr, buflen, "Data error in %s.rule_count", 1142101206Srwatson MIB); 1143101206Srwatson return (-1); 1144101206Srwatson } 1145101206Srwatson 1146101206Srwatson return (rule_count); 1147101206Srwatson} 1148101206Srwatson 1149101206Srwatsonint 1150101206Srwatsonbsde_get_rule_slots(size_t buflen, char *errstr) 1151101206Srwatson{ 1152101206Srwatson size_t len; 1153101206Srwatson int error; 1154101206Srwatson int rule_slots; 1155101206Srwatson 1156101206Srwatson len = sizeof(rule_slots); 1157126835Sbde error = sysctlbyname(MIB ".rule_slots", &rule_slots, &len, NULL, 0); 1158101206Srwatson if (error) { 1159216953Semaste len = snprintf(errstr, buflen, "%s", strerror(errno)); 1160101206Srwatson return (-1); 1161101206Srwatson } 1162101206Srwatson if (len != sizeof(rule_slots)) { 1163101206Srwatson len = snprintf(errstr, buflen, "Data error in %s.rule_slots", 1164101206Srwatson MIB); 1165101206Srwatson return (-1); 1166101206Srwatson } 1167101206Srwatson 1168101206Srwatson return (rule_slots); 1169101206Srwatson} 1170101206Srwatson 1171101206Srwatson/* 1172101206Srwatson * Returns 0 for success; 1173101206Srwatson * Returns -1 for failure; 1174101206Srwatson * Returns -2 for not present 1175101206Srwatson */ 1176101206Srwatsonint 1177101206Srwatsonbsde_get_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t errlen, 1178101206Srwatson char *errstr) 1179101206Srwatson{ 1180101206Srwatson int name[10]; 1181101206Srwatson size_t len, size; 1182101206Srwatson int error; 1183101206Srwatson 1184157986Sdwmalone if (bsde_check_version(errlen, errstr) != 0) 1185157986Sdwmalone return (-1); 1186157986Sdwmalone 1187101206Srwatson len = 10; 1188101206Srwatson error = bsde_get_mib(MIB ".rules", name, &len); 1189101206Srwatson if (error) { 1190101206Srwatson len = snprintf(errstr, errlen, "%s: %s", MIB ".rules", 1191101206Srwatson strerror(errno)); 1192101206Srwatson return (-1); 1193101206Srwatson } 1194101206Srwatson 1195101206Srwatson size = sizeof(*rule); 1196101206Srwatson name[len] = rulenum; 1197101206Srwatson len++; 1198101206Srwatson error = sysctl(name, len, rule, &size, NULL, 0); 1199101206Srwatson if (error == -1 && errno == ENOENT) 1200101206Srwatson return (-2); 1201101206Srwatson if (error) { 1202101206Srwatson len = snprintf(errstr, errlen, "%s.%d: %s", MIB ".rules", 1203101206Srwatson rulenum, strerror(errno)); 1204101206Srwatson return (-1); 1205101206Srwatson } else if (size != sizeof(*rule)) { 1206101206Srwatson len = snprintf(errstr, errlen, "Data error in %s.%d: %s", 1207101206Srwatson MIB ".rules", rulenum, strerror(errno)); 1208101206Srwatson return (-1); 1209101206Srwatson } 1210101206Srwatson 1211101206Srwatson return (0); 1212101206Srwatson} 1213101206Srwatson 1214101206Srwatsonint 1215101206Srwatsonbsde_delete_rule(int rulenum, size_t buflen, char *errstr) 1216101206Srwatson{ 1217101206Srwatson struct mac_bsdextended_rule rule; 1218101206Srwatson int name[10]; 1219101206Srwatson size_t len, size; 1220101206Srwatson int error; 1221101206Srwatson 1222157986Sdwmalone if (bsde_check_version(buflen, errstr) != 0) 1223157986Sdwmalone return (-1); 1224157986Sdwmalone 1225101206Srwatson len = 10; 1226101206Srwatson error = bsde_get_mib(MIB ".rules", name, &len); 1227101206Srwatson if (error) { 1228101206Srwatson len = snprintf(errstr, buflen, "%s: %s", MIB ".rules", 1229101206Srwatson strerror(errno)); 1230101206Srwatson return (-1); 1231101206Srwatson } 1232101206Srwatson 1233101206Srwatson name[len] = rulenum; 1234101206Srwatson len++; 1235101206Srwatson 1236101206Srwatson size = sizeof(rule); 1237101206Srwatson error = sysctl(name, len, NULL, NULL, &rule, 0); 1238101206Srwatson if (error) { 1239101206Srwatson len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules", 1240101206Srwatson rulenum, strerror(errno)); 1241101206Srwatson return (-1); 1242101206Srwatson } 1243101206Srwatson 1244101206Srwatson return (0); 1245101206Srwatson} 1246101206Srwatson 1247101206Srwatsonint 1248101206Srwatsonbsde_set_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t buflen, 1249101206Srwatson char *errstr) 1250101206Srwatson{ 1251101206Srwatson int name[10]; 1252101206Srwatson size_t len, size; 1253101206Srwatson int error; 1254101206Srwatson 1255157986Sdwmalone if (bsde_check_version(buflen, errstr) != 0) 1256157986Sdwmalone return (-1); 1257157986Sdwmalone 1258101206Srwatson len = 10; 1259101206Srwatson error = bsde_get_mib(MIB ".rules", name, &len); 1260101206Srwatson if (error) { 1261101206Srwatson len = snprintf(errstr, buflen, "%s: %s", MIB ".rules", 1262101206Srwatson strerror(errno)); 1263101206Srwatson return (-1); 1264101206Srwatson } 1265101206Srwatson 1266101206Srwatson name[len] = rulenum; 1267101206Srwatson len++; 1268101206Srwatson 1269101206Srwatson size = sizeof(*rule); 1270101206Srwatson error = sysctl(name, len, NULL, NULL, rule, size); 1271101206Srwatson if (error) { 1272101206Srwatson len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules", 1273101206Srwatson rulenum, strerror(errno)); 1274101206Srwatson return (-1); 1275101206Srwatson } 1276101206Srwatson 1277101206Srwatson return (0); 1278101206Srwatson} 1279126217Srwatson 1280126217Srwatsonint 1281126217Srwatsonbsde_add_rule(int *rulenum, struct mac_bsdextended_rule *rule, size_t buflen, 1282126217Srwatson char *errstr) 1283126217Srwatson{ 1284126217Srwatson char charstr[BUFSIZ]; 1285126217Srwatson int name[10]; 1286126217Srwatson size_t len, size; 1287126217Srwatson int error, rule_slots; 1288126217Srwatson 1289157986Sdwmalone if (bsde_check_version(buflen, errstr) != 0) 1290157986Sdwmalone return (-1); 1291157986Sdwmalone 1292126217Srwatson len = 10; 1293126217Srwatson error = bsde_get_mib(MIB ".rules", name, &len); 1294126217Srwatson if (error) { 1295126217Srwatson len = snprintf(errstr, buflen, "%s: %s", MIB ".rules", 1296126217Srwatson strerror(errno)); 1297126217Srwatson return (-1); 1298126217Srwatson } 1299126217Srwatson 1300126217Srwatson rule_slots = bsde_get_rule_slots(BUFSIZ, charstr); 1301126217Srwatson if (rule_slots == -1) { 1302126217Srwatson len = snprintf(errstr, buflen, "unable to get rule slots: %s", 1303126217Srwatson strerror(errno)); 1304126217Srwatson return (-1); 1305126217Srwatson } 1306126217Srwatson 1307126217Srwatson name[len] = rule_slots; 1308126217Srwatson len++; 1309126217Srwatson 1310126217Srwatson size = sizeof(*rule); 1311126217Srwatson error = sysctl(name, len, NULL, NULL, rule, size); 1312126217Srwatson if (error) { 1313126217Srwatson len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules", 1314126217Srwatson rule_slots, strerror(errno)); 1315126217Srwatson return (-1); 1316126217Srwatson } 1317126217Srwatson 1318126217Srwatson if (rulenum != NULL) 1319144210Spjd *rulenum = rule_slots; 1320126217Srwatson 1321126217Srwatson return (0); 1322126217Srwatson} 1323