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