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