ugidfw.c revision 101885
1101206Srwatson/*- 2101206Srwatson * Copyright (c) 2002 Networks Associates Technology, Inc. 3101206Srwatson * All rights reserved. 4101206Srwatson * 5101206Srwatson * This software was developed for the FreeBSD Project by NAI Labs, the 6101206Srwatson * Security Research Division of Network Associates, Inc. under 7101206Srwatson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 8101206Srwatson * 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 * 3. The names of the authors may not be used to endorse or promote 19101206Srwatson * products derived from this software without specific prior written 20101206Srwatson * permission. 21101206Srwatson * 22101206Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23101206Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24101206Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25101206Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26101206Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27101206Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28101206Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29101206Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30101206Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31101206Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32101206Srwatson * SUCH DAMAGE. 33101206Srwatson * 34101206Srwatson * $FreeBSD: head/lib/libugidfw/ugidfw.c 101885 2002-08-14 22:30:07Z rwatson $ 35101206Srwatson */ 36101206Srwatson#include <sys/param.h> 37101206Srwatson#include <sys/errno.h> 38101206Srwatson#include <sys/time.h> 39101206Srwatson#include <sys/sysctl.h> 40101206Srwatson#include <sys/vnode.h> 41101206Srwatson 42101206Srwatson#include <security/mac_bsdextended/mac_bsdextended.h> 43101206Srwatson 44101206Srwatson#include <grp.h> 45101206Srwatson#include <pwd.h> 46101206Srwatson#include <stdio.h> 47101206Srwatson#include <stdlib.h> 48101206Srwatson#include <string.h> 49101206Srwatson 50101885Srwatson#include "ugidfw.h" 51101206Srwatson 52101206Srwatson/* 53101206Srwatson * Text format for rules: rules contain subjectand object elements, mode. 54101206Srwatson * Each element takes the form "[not] [uid number] [gid number]". 55101206Srwatson * The total form is "subject [element] object [element] mode [mode]". 56101206Srwatson * At least * one of a uid or gid entry must be present; both may also be 57101206Srwatson * present. 58101206Srwatson */ 59101206Srwatson 60101206Srwatson#define MIB "security.mac.bsdextended" 61101206Srwatson 62101206Srwatsonint 63101206Srwatsonbsde_rule_to_string(struct mac_bsdextended_rule *rule, char *buf, size_t buflen) 64101206Srwatson{ 65101206Srwatson struct group *grp; 66101206Srwatson struct passwd *pwd; 67101206Srwatson char *cur; 68101206Srwatson size_t left, len; 69101206Srwatson int anymode, unknownmode, truncated; 70101206Srwatson 71101206Srwatson cur = buf; 72101206Srwatson left = buflen; 73101206Srwatson truncated = 0; 74101206Srwatson 75101206Srwatson if (rule->mbr_subject.mbi_flags & (MBI_UID_DEFINED | 76101206Srwatson MBI_GID_DEFINED)) { 77101206Srwatson len = snprintf(cur, left, "subject "); 78101206Srwatson if (len < 0 || len > left) 79101206Srwatson goto truncated; 80101206Srwatson left -= len; 81101206Srwatson cur += len; 82101206Srwatson 83101206Srwatson if (rule->mbr_subject.mbi_flags & MBI_NEGATED) { 84101206Srwatson len = snprintf(cur, left, "not "); 85101206Srwatson if (len < 0 || len > left) 86101206Srwatson goto truncated; 87101206Srwatson left -= len; 88101206Srwatson cur += len; 89101206Srwatson } 90101206Srwatson if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) { 91101206Srwatson pwd = getpwuid(rule->mbr_subject.mbi_uid); 92101206Srwatson if (pwd != NULL) { 93101206Srwatson len = snprintf(cur, left, "uid %s ", 94101206Srwatson pwd->pw_name); 95101206Srwatson if (len < 0 || len > left) 96101206Srwatson goto truncated; 97101206Srwatson left -= len; 98101206Srwatson cur += len; 99101206Srwatson } else { 100101206Srwatson len = snprintf(cur, left, "uid %u ", 101101206Srwatson rule->mbr_subject.mbi_uid); 102101206Srwatson if (len < 0 || len > left) 103101206Srwatson goto truncated; 104101206Srwatson left -= len; 105101206Srwatson cur += len; 106101206Srwatson } 107101206Srwatson } 108101206Srwatson if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) { 109101206Srwatson grp = getgrgid(rule->mbr_subject.mbi_gid); 110101206Srwatson if (grp != NULL) { 111101206Srwatson len = snprintf(cur, left, "gid %s ", 112101206Srwatson grp->gr_name); 113101206Srwatson if (len < 0 || len > left) 114101206Srwatson goto truncated; 115101206Srwatson left -= len; 116101206Srwatson cur += len; 117101206Srwatson } else { 118101206Srwatson len = snprintf(cur, left, "gid %u ", 119101206Srwatson rule->mbr_subject.mbi_gid); 120101206Srwatson if (len < 0 || len > left) 121101206Srwatson goto truncated; 122101206Srwatson left -= len; 123101206Srwatson cur += len; 124101206Srwatson } 125101206Srwatson } 126101206Srwatson } 127101206Srwatson if (rule->mbr_object.mbi_flags & (MBI_UID_DEFINED | 128101206Srwatson MBI_GID_DEFINED)) { 129101206Srwatson len = snprintf(cur, left, "object "); 130101206Srwatson if (len < 0 || len > left) 131101206Srwatson goto truncated; 132101206Srwatson left -= len; 133101206Srwatson cur += len; 134101206Srwatson 135101206Srwatson if (rule->mbr_object.mbi_flags & MBI_NEGATED) { 136101206Srwatson len = snprintf(cur, left, "not "); 137101206Srwatson if (len < 0 || len > left) 138101206Srwatson goto truncated; 139101206Srwatson left -= len; 140101206Srwatson cur += len; 141101206Srwatson } 142101206Srwatson if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) { 143101206Srwatson pwd = getpwuid(rule->mbr_object.mbi_uid); 144101206Srwatson if (pwd != NULL) { 145101206Srwatson len = snprintf(cur, left, "uid %s ", 146101206Srwatson pwd->pw_name); 147101206Srwatson if (len < 0 || len > left) 148101206Srwatson goto truncated; 149101206Srwatson left -= len; 150101206Srwatson cur += len; 151101206Srwatson } else { 152101206Srwatson len = snprintf(cur, left, "uid %u ", 153101206Srwatson rule->mbr_object.mbi_uid); 154101206Srwatson left -= len; 155101206Srwatson cur += len; 156101206Srwatson } 157101206Srwatson } 158101206Srwatson if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) { 159101206Srwatson grp = getgrgid(rule->mbr_object.mbi_gid); 160101206Srwatson if (grp != NULL) { 161101206Srwatson len = snprintf(cur, left, "gid %s ", 162101206Srwatson grp->gr_name); 163101206Srwatson if (len < 0 || len > left) 164101206Srwatson goto truncated; 165101206Srwatson left -= len; 166101206Srwatson cur += len; 167101206Srwatson } else { 168101206Srwatson len = snprintf(cur, left, "gid %u ", 169101206Srwatson rule->mbr_object.mbi_gid); 170101206Srwatson if (len < 0 || len > left) 171101206Srwatson goto truncated; 172101206Srwatson left -= len; 173101206Srwatson cur += len; 174101206Srwatson } 175101206Srwatson } 176101206Srwatson } 177101206Srwatson 178101206Srwatson len = snprintf(cur, left, "mode "); 179101206Srwatson if (len < 0 || len > left) 180101206Srwatson goto truncated; 181101206Srwatson left -= len; 182101206Srwatson cur += len; 183101206Srwatson 184101206Srwatson anymode = (rule->mbr_mode & VALLPERM); 185101206Srwatson unknownmode = (rule->mbr_mode & ~VALLPERM); 186101206Srwatson 187101206Srwatson if (rule->mbr_mode & VADMIN) { 188101206Srwatson len = snprintf(cur, left, "a"); 189101206Srwatson if (len < 0 || len > left) 190101206Srwatson goto truncated; 191101206Srwatson 192101206Srwatson left -= len; 193101206Srwatson cur += len; 194101206Srwatson } 195101206Srwatson if (rule->mbr_mode & VREAD) { 196101206Srwatson len = snprintf(cur, left, "r"); 197101206Srwatson if (len < 0 || len > left) 198101206Srwatson goto truncated; 199101206Srwatson 200101206Srwatson left -= len; 201101206Srwatson cur += len; 202101206Srwatson } 203101206Srwatson if (rule->mbr_mode & VSTAT) { 204101206Srwatson len = snprintf(cur, left, "s"); 205101206Srwatson if (len < 0 || len > left) 206101206Srwatson goto truncated; 207101206Srwatson 208101206Srwatson left -= len; 209101206Srwatson cur += len; 210101206Srwatson } 211101206Srwatson if (rule->mbr_mode & VWRITE) { 212101206Srwatson len = snprintf(cur, left, "w"); 213101206Srwatson if (len < 0 || len > left) 214101206Srwatson goto truncated; 215101206Srwatson 216101206Srwatson left -= len; 217101206Srwatson cur += len; 218101206Srwatson } 219101206Srwatson if (rule->mbr_mode & VEXEC) { 220101206Srwatson len = snprintf(cur, left, "x"); 221101206Srwatson if (len < 0 || len > left) 222101206Srwatson goto truncated; 223101206Srwatson 224101206Srwatson left -= len; 225101206Srwatson cur += len; 226101206Srwatson } 227101206Srwatson if (!anymode) { 228101206Srwatson len = snprintf(cur, left, "n"); 229101206Srwatson if (len < 0 || len > left) 230101206Srwatson goto truncated; 231101206Srwatson 232101206Srwatson left -= len; 233101206Srwatson cur += len; 234101206Srwatson } 235101206Srwatson if (unknownmode) { 236101206Srwatson len = snprintf(cur, left, "?"); 237101206Srwatson if (len < 0 || len > left) 238101206Srwatson goto truncated; 239101206Srwatson 240101206Srwatson left -= len; 241101206Srwatson cur += len; 242101206Srwatson } 243101206Srwatson 244101206Srwatson return (0); 245101206Srwatson 246101206Srwatsontruncated: 247101206Srwatson return (-1); 248101206Srwatson} 249101206Srwatson 250101206Srwatsonint 251101206Srwatsonbsde_parse_identity(int argc, char *argv[], 252101206Srwatson struct mac_bsdextended_identity *identity, size_t buflen, char *errstr) 253101206Srwatson{ 254101206Srwatson struct group *grp; 255101206Srwatson struct passwd *pwd; 256101206Srwatson int uid_seen, gid_seen, not_seen; 257101206Srwatson int current; 258101206Srwatson char *endp; 259101206Srwatson long value; 260101206Srwatson uid_t uid; 261101206Srwatson gid_t gid; 262101206Srwatson size_t len; 263101206Srwatson 264101206Srwatson if (argc == 0) { 265101206Srwatson len = snprintf(errstr, buflen, "Identity must not be empty"); 266101206Srwatson return (-1); 267101206Srwatson } 268101206Srwatson 269101206Srwatson current = 0; 270101206Srwatson 271101206Srwatson /* First element might be "not". */ 272101206Srwatson if (strcmp("not", argv[0]) == 0) { 273101206Srwatson not_seen = 1; 274101206Srwatson current++; 275101206Srwatson } else 276101206Srwatson not_seen = 0; 277101206Srwatson 278101206Srwatson if (current >= argc) { 279101206Srwatson len = snprintf(errstr, buflen, "Identity short"); 280101206Srwatson return (-1); 281101206Srwatson } 282101206Srwatson 283101206Srwatson uid_seen = 0; 284101206Srwatson uid = 0; 285101206Srwatson gid_seen = 0; 286101206Srwatson gid = 0; 287101206Srwatson 288101206Srwatson /* First phrase: uid [uid] or gid[gid]. */ 289101206Srwatson if (strcmp("uid", argv[current]) == 0) { 290101206Srwatson if (current + 2 > argc) { 291101206Srwatson len = snprintf(errstr, buflen, "uid short"); 292101206Srwatson return (-1); 293101206Srwatson } 294101206Srwatson pwd = getpwnam(argv[current+1]); 295101206Srwatson if (pwd != NULL) 296101206Srwatson uid = pwd->pw_uid; 297101206Srwatson else { 298101206Srwatson value = strtol(argv[current+1], &endp, 10); 299101206Srwatson if (*endp != '\0') { 300101206Srwatson len = snprintf(errstr, buflen, 301101206Srwatson "invalid uid: '%s'", 302101206Srwatson argv[current+1]); 303101206Srwatson return (-1); 304101206Srwatson } 305101206Srwatson uid = value; 306101206Srwatson } 307101206Srwatson uid_seen = 1; 308101206Srwatson current += 2; 309101206Srwatson } else if (strcmp("gid", argv[current]) == 0) { 310101206Srwatson if (current + 2 > argc) { 311101206Srwatson len = snprintf(errstr, buflen, "gid short"); 312101206Srwatson return (-1); 313101206Srwatson } 314101206Srwatson grp = getgrnam(argv[current+1]); 315101206Srwatson if (grp != NULL) 316101206Srwatson gid = grp->gr_gid; 317101206Srwatson else { 318101206Srwatson value = strtol(argv[current+1], &endp, 10); 319101206Srwatson if (*endp != '\0') { 320101206Srwatson len = snprintf(errstr, buflen, 321101206Srwatson "invalid gid: '%s'", 322101206Srwatson argv[current+1]); 323101206Srwatson return (-1); 324101206Srwatson } 325101206Srwatson gid = value; 326101206Srwatson } 327101206Srwatson gid_seen = 1; 328101206Srwatson current += 2; 329101206Srwatson } else { 330101206Srwatson len = snprintf(errstr, buflen, "'%s' not expected", 331101206Srwatson argv[current]); 332101206Srwatson return (-1); 333101206Srwatson } 334101206Srwatson 335101206Srwatson /* Onto optional second phrase. */ 336101206Srwatson if (current + 1 < argc) { 337101206Srwatson /* Second phrase: uid [uid] or gid [gid], but not a repeat. */ 338101206Srwatson if (strcmp("uid", argv[current]) == 0) { 339101206Srwatson if (uid_seen) { 340101206Srwatson len = snprintf(errstr, buflen, 341101206Srwatson "Only one uid permitted per identity clause"); 342101206Srwatson return (-1); 343101206Srwatson } 344101206Srwatson if (current + 2 > argc) { 345101206Srwatson len = snprintf(errstr, buflen, "uid short"); 346101206Srwatson return (-1); 347101206Srwatson } 348101206Srwatson value = strtol(argv[current+1], &endp, 10); 349101206Srwatson if (*endp != '\0') { 350101206Srwatson len = snprintf(errstr, buflen, "invalid uid: '%s'", 351101206Srwatson argv[current+1]); 352101206Srwatson return (-1); 353101206Srwatson } 354101206Srwatson uid = value; 355101206Srwatson uid_seen = 1; 356101206Srwatson current += 2; 357101206Srwatson } else if (strcmp("gid", argv[current]) == 0) { 358101206Srwatson if (gid_seen) { 359101206Srwatson len = snprintf(errstr, buflen, 360101206Srwatson "Only one gid permitted per identity clause"); 361101206Srwatson return (-1); 362101206Srwatson } 363101206Srwatson if (current + 2 > argc) { 364101206Srwatson len = snprintf(errstr, buflen, "gid short"); 365101206Srwatson return (-1); 366101206Srwatson } 367101206Srwatson value = strtol(argv[current+1], &endp, 10); 368101206Srwatson if (*endp != '\0') { 369101206Srwatson len = snprintf(errstr, buflen, "invalid gid: '%s'", 370101206Srwatson argv[current+1]); 371101206Srwatson return (-1); 372101206Srwatson } 373101206Srwatson gid = value; 374101206Srwatson gid_seen = 1; 375101206Srwatson current += 2; 376101206Srwatson } else { 377101206Srwatson len = snprintf(errstr, buflen, "'%s' not expected", 378101206Srwatson argv[current]); 379101206Srwatson return (-1); 380101206Srwatson } 381101206Srwatson } 382101206Srwatson 383101206Srwatson if (current +1 < argc) { 384101206Srwatson len = snprintf(errstr, buflen, "'%s' not expected", 385101206Srwatson argv[current]); 386101206Srwatson return (-1); 387101206Srwatson } 388101206Srwatson 389101206Srwatson /* Fill out the identity. */ 390101206Srwatson identity->mbi_flags = 0; 391101206Srwatson 392101206Srwatson if (not_seen) 393101206Srwatson identity->mbi_flags |= MBI_NEGATED; 394101206Srwatson 395101206Srwatson if (uid_seen) { 396101206Srwatson identity->mbi_flags |= MBI_UID_DEFINED; 397101206Srwatson identity->mbi_uid = uid; 398101206Srwatson } else 399101206Srwatson identity->mbi_uid = 0; 400101206Srwatson 401101206Srwatson if (gid_seen) { 402101206Srwatson identity->mbi_flags |= MBI_GID_DEFINED; 403101206Srwatson identity->mbi_gid = gid; 404101206Srwatson } else 405101206Srwatson identity->mbi_gid = 0; 406101206Srwatson 407101206Srwatson return (0); 408101206Srwatson} 409101206Srwatson 410101206Srwatsonint 411101206Srwatsonbsde_parse_mode(int argc, char *argv[], mode_t *mode, size_t buflen, 412101206Srwatson char *errstr) 413101206Srwatson{ 414101206Srwatson size_t len; 415101206Srwatson int i; 416101206Srwatson 417101206Srwatson if (argc == 0) { 418101206Srwatson len = snprintf(errstr, buflen, "mode expects mode value"); 419101206Srwatson return (-1); 420101206Srwatson } 421101206Srwatson 422101206Srwatson if (argc != 1) { 423101206Srwatson len = snprintf(errstr, buflen, "'%s' unexpected", argv[1]); 424101206Srwatson return (-1); 425101206Srwatson } 426101206Srwatson 427101206Srwatson *mode = 0; 428101206Srwatson for (i = 0; i < strlen(argv[0]); i++) { 429101206Srwatson switch (argv[0][i]) { 430101206Srwatson case 'a': 431101206Srwatson *mode |= VADMIN; 432101206Srwatson break; 433101206Srwatson case 'r': 434101206Srwatson *mode |= VREAD; 435101206Srwatson break; 436101206Srwatson case 's': 437101206Srwatson *mode |= VSTAT; 438101206Srwatson break; 439101206Srwatson case 'w': 440101206Srwatson *mode |= VWRITE; 441101206Srwatson break; 442101206Srwatson case 'x': 443101206Srwatson *mode |= VEXEC; 444101206Srwatson break; 445101206Srwatson case 'n': 446101206Srwatson /* ignore */ 447101206Srwatson break; 448101206Srwatson default: 449101206Srwatson len = snprintf(errstr, buflen, "Unknown mode letter: %c", 450101206Srwatson argv[0][i]); 451101206Srwatson return (-1); 452101206Srwatson } 453101206Srwatson } 454101206Srwatson 455101206Srwatson return (0); 456101206Srwatson} 457101206Srwatson 458101206Srwatsonint 459101206Srwatsonbsde_parse_rule(int argc, char *argv[], struct mac_bsdextended_rule *rule, 460101206Srwatson size_t buflen, char *errstr) 461101206Srwatson{ 462101206Srwatson int subject, subject_elements, subject_elements_length; 463101206Srwatson int object, object_elements, object_elements_length; 464101206Srwatson int mode, mode_elements, mode_elements_length; 465101206Srwatson int error, i; 466101206Srwatson size_t len; 467101206Srwatson 468101206Srwatson bzero(rule, sizeof(*rule)); 469101206Srwatson 470101206Srwatson if (argc < 1) { 471101206Srwatson len = snprintf(errstr, buflen, "Rule must begin with subject"); 472101206Srwatson return (-1); 473101206Srwatson } 474101206Srwatson 475101206Srwatson if (strcmp(argv[0], "subject") != 0) { 476101206Srwatson len = snprintf(errstr, buflen, "Rule must begin with subject"); 477101206Srwatson return (-1); 478101206Srwatson } 479101206Srwatson subject = 0; 480101206Srwatson subject_elements = 1; 481101206Srwatson 482101206Srwatson /* Search forward for object. */ 483101206Srwatson 484101206Srwatson object = -1; 485101206Srwatson for (i = 1; i < argc; i++) 486101206Srwatson if (strcmp(argv[i], "object") == 0) 487101206Srwatson object = i; 488101206Srwatson 489101206Srwatson if (object == -1) { 490101206Srwatson len = snprintf(errstr, buflen, "Rule must contain an object"); 491101206Srwatson return (-1); 492101206Srwatson } 493101206Srwatson 494101206Srwatson /* Search forward for mode. */ 495101206Srwatson mode = -1; 496101206Srwatson for (i = object; i < argc; i++) 497101206Srwatson if (strcmp(argv[i], "mode") == 0) 498101206Srwatson mode = i; 499101206Srwatson 500101206Srwatson if (mode == -1) { 501101206Srwatson len = snprintf(errstr, buflen, "Rule must contain mode"); 502101206Srwatson return (-1); 503101206Srwatson } 504101206Srwatson 505101206Srwatson subject_elements_length = object - subject - 1; 506101206Srwatson object_elements = object + 1; 507101206Srwatson object_elements_length = mode - object_elements; 508101206Srwatson mode_elements = mode + 1; 509101206Srwatson mode_elements_length = argc - mode_elements; 510101206Srwatson 511101206Srwatson error = bsde_parse_identity(subject_elements_length, 512101206Srwatson argv + subject_elements, &rule->mbr_subject, buflen, errstr); 513101206Srwatson if (error) 514101206Srwatson return (-1); 515101206Srwatson 516101206Srwatson error = bsde_parse_identity(object_elements_length, 517101206Srwatson argv + object_elements, &rule->mbr_object, buflen, errstr); 518101206Srwatson if (error) 519101206Srwatson return (-1); 520101206Srwatson 521101206Srwatson error = bsde_parse_mode(mode_elements_length, argv + mode_elements, 522101206Srwatson &rule->mbr_mode, buflen, errstr); 523101206Srwatson if (error) 524101206Srwatson return (-1); 525101206Srwatson 526101206Srwatson return (0); 527101206Srwatson} 528101206Srwatson 529101206Srwatsonint 530101206Srwatsonbsde_parse_rule_string(const char *string, struct mac_bsdextended_rule *rule, 531101206Srwatson size_t buflen, char *errstr) 532101206Srwatson{ 533101206Srwatson char *stringdup, *stringp, *argv[20], **ap; 534101206Srwatson int argc, error; 535101206Srwatson 536101206Srwatson stringp = stringdup = strdup(string); 537101206Srwatson while (*stringp == ' ' || *stringp == '\t') 538101206Srwatson stringp++; 539101206Srwatson 540101206Srwatson argc = 0; 541101206Srwatson for (ap = argv; (*ap = strsep(&stringp, " \t")) != NULL;) { 542101206Srwatson argc++; 543101206Srwatson if (**ap != '\0') 544101206Srwatson if (++ap >= &argv[20]) 545101206Srwatson break; 546101206Srwatson } 547101206Srwatson 548101206Srwatson error = bsde_parse_rule(argc, argv, rule, buflen, errstr); 549101206Srwatson 550101206Srwatson free(stringdup); 551101206Srwatson 552101206Srwatson return (error); 553101206Srwatson} 554101206Srwatson 555101206Srwatsonint 556101206Srwatsonbsde_get_mib(const char *string, int *name, int *namelen) 557101206Srwatson{ 558101206Srwatson int error, len; 559101206Srwatson 560101206Srwatson len = *namelen; 561101206Srwatson error = sysctlnametomib(string, name, &len); 562101206Srwatson if (error) 563101206Srwatson return (error); 564101206Srwatson 565101206Srwatson *namelen = len; 566101206Srwatson return (0); 567101206Srwatson} 568101206Srwatson 569101206Srwatsonint 570101206Srwatsonbsde_get_rule_count(size_t buflen, char *errstr) 571101206Srwatson{ 572101206Srwatson size_t len; 573101206Srwatson int error; 574101206Srwatson int rule_count; 575101206Srwatson 576101206Srwatson len = sizeof(rule_count); 577101206Srwatson error = sysctlbyname(MIB ".rule_count", &rule_count, &len, NULL, NULL); 578101206Srwatson if (error) { 579101206Srwatson len = snprintf(errstr, buflen, strerror(errno)); 580101206Srwatson return (-1); 581101206Srwatson } 582101206Srwatson if (len != sizeof(rule_count)) { 583101206Srwatson len = snprintf(errstr, buflen, "Data error in %s.rule_count", 584101206Srwatson MIB); 585101206Srwatson return (-1); 586101206Srwatson } 587101206Srwatson 588101206Srwatson return (rule_count); 589101206Srwatson} 590101206Srwatson 591101206Srwatsonint 592101206Srwatsonbsde_get_rule_slots(size_t buflen, char *errstr) 593101206Srwatson{ 594101206Srwatson size_t len; 595101206Srwatson int error; 596101206Srwatson int rule_slots; 597101206Srwatson 598101206Srwatson len = sizeof(rule_slots); 599101206Srwatson error = sysctlbyname(MIB ".rule_slots", &rule_slots, &len, NULL, 600101206Srwatson NULL); 601101206Srwatson if (error) { 602101206Srwatson len = snprintf(errstr, buflen, strerror(errno)); 603101206Srwatson return (-1); 604101206Srwatson } 605101206Srwatson if (len != sizeof(rule_slots)) { 606101206Srwatson len = snprintf(errstr, buflen, "Data error in %s.rule_slots", 607101206Srwatson MIB); 608101206Srwatson return (-1); 609101206Srwatson } 610101206Srwatson 611101206Srwatson return (rule_slots); 612101206Srwatson} 613101206Srwatson 614101206Srwatson/* 615101206Srwatson * Returns 0 for success; 616101206Srwatson * Returns -1 for failure; 617101206Srwatson * Returns -2 for not present 618101206Srwatson */ 619101206Srwatsonint 620101206Srwatsonbsde_get_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t errlen, 621101206Srwatson char *errstr) 622101206Srwatson{ 623101206Srwatson int name[10]; 624101206Srwatson size_t len, size; 625101206Srwatson int error; 626101206Srwatson 627101206Srwatson len = 10; 628101206Srwatson error = bsde_get_mib(MIB ".rules", name, &len); 629101206Srwatson if (error) { 630101206Srwatson len = snprintf(errstr, errlen, "%s: %s", MIB ".rules", 631101206Srwatson strerror(errno)); 632101206Srwatson return (-1); 633101206Srwatson } 634101206Srwatson 635101206Srwatson size = sizeof(*rule); 636101206Srwatson name[len] = rulenum; 637101206Srwatson len++; 638101206Srwatson error = sysctl(name, len, rule, &size, NULL, 0); 639101206Srwatson if (error == -1 && errno == ENOENT) 640101206Srwatson return (-2); 641101206Srwatson if (error) { 642101206Srwatson len = snprintf(errstr, errlen, "%s.%d: %s", MIB ".rules", 643101206Srwatson rulenum, strerror(errno)); 644101206Srwatson return (-1); 645101206Srwatson } else if (size != sizeof(*rule)) { 646101206Srwatson len = snprintf(errstr, errlen, "Data error in %s.%d: %s", 647101206Srwatson MIB ".rules", rulenum, strerror(errno)); 648101206Srwatson return (-1); 649101206Srwatson } 650101206Srwatson 651101206Srwatson return (0); 652101206Srwatson} 653101206Srwatson 654101206Srwatsonint 655101206Srwatsonbsde_delete_rule(int rulenum, size_t buflen, char *errstr) 656101206Srwatson{ 657101206Srwatson struct mac_bsdextended_rule rule; 658101206Srwatson int name[10]; 659101206Srwatson size_t len, size; 660101206Srwatson int error; 661101206Srwatson 662101206Srwatson len = 10; 663101206Srwatson error = bsde_get_mib(MIB ".rules", name, &len); 664101206Srwatson if (error) { 665101206Srwatson len = snprintf(errstr, buflen, "%s: %s", MIB ".rules", 666101206Srwatson strerror(errno)); 667101206Srwatson return (-1); 668101206Srwatson } 669101206Srwatson 670101206Srwatson name[len] = rulenum; 671101206Srwatson len++; 672101206Srwatson 673101206Srwatson size = sizeof(rule); 674101206Srwatson error = sysctl(name, len, NULL, NULL, &rule, 0); 675101206Srwatson if (error) { 676101206Srwatson len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules", 677101206Srwatson rulenum, strerror(errno)); 678101206Srwatson return (-1); 679101206Srwatson } 680101206Srwatson 681101206Srwatson return (0); 682101206Srwatson} 683101206Srwatson 684101206Srwatsonint 685101206Srwatsonbsde_set_rule(int rulenum, struct mac_bsdextended_rule *rule, size_t buflen, 686101206Srwatson char *errstr) 687101206Srwatson{ 688101206Srwatson int name[10]; 689101206Srwatson size_t len, size; 690101206Srwatson int error; 691101206Srwatson 692101206Srwatson len = 10; 693101206Srwatson error = bsde_get_mib(MIB ".rules", name, &len); 694101206Srwatson if (error) { 695101206Srwatson len = snprintf(errstr, buflen, "%s: %s", MIB ".rules", 696101206Srwatson strerror(errno)); 697101206Srwatson return (-1); 698101206Srwatson } 699101206Srwatson 700101206Srwatson name[len] = rulenum; 701101206Srwatson len++; 702101206Srwatson 703101206Srwatson size = sizeof(*rule); 704101206Srwatson error = sysctl(name, len, NULL, NULL, rule, size); 705101206Srwatson if (error) { 706101206Srwatson len = snprintf(errstr, buflen, "%s.%d: %s", MIB ".rules", 707101206Srwatson rulenum, strerror(errno)); 708101206Srwatson return (-1); 709101206Srwatson } 710101206Srwatson 711101206Srwatson return (0); 712101206Srwatson} 713