17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*f8804e7fSgww * Common Development and Distribution License (the "License"). 6*f8804e7fSgww * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*f8804e7fSgww * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 267c478bd9Sstevel@tonic-gate * get audit preselection mask values 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 29*f8804e7fSgww #include <ctype.h> 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <string.h> 32*f8804e7fSgww 33*f8804e7fSgww #include <sys/errno.h> 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <bsm/audit.h> 367c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h> 377c478bd9Sstevel@tonic-gate 38*f8804e7fSgww #include <adt_xlate.h> /* adt_write_syslog */ 397c478bd9Sstevel@tonic-gate 40*f8804e7fSgww #define SUCCESS 0x1 /* '+' success mask */ 41*f8804e7fSgww #define FAILURE 0x2 /* '-' failure mask */ 42*f8804e7fSgww #define INVERSE 0x4 /* '^' invert the mask */ 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static int 45*f8804e7fSgww match_class(char *s, char *prefix, uint_t m, int v) 467c478bd9Sstevel@tonic-gate { 477c478bd9Sstevel@tonic-gate au_class_ent_t *p_class; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate (void) strcat(s, prefix); 507c478bd9Sstevel@tonic-gate if (cacheauclass(&p_class, m) == 1) { 51*f8804e7fSgww if (v == 0) { 52*f8804e7fSgww (void) strncat(s, p_class->ac_name, AU_CLASS_NAME_MAX); 53*f8804e7fSgww } else { 54*f8804e7fSgww (void) strncat(s, p_class->ac_desc, AU_CLASS_DESC_MAX); 55*f8804e7fSgww } 567c478bd9Sstevel@tonic-gate (void) strcat(s, ","); 577c478bd9Sstevel@tonic-gate return (0); 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate return (-1); 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * getauditflagschar() - convert bit flag to character string 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * input: masks->am_success - audit on success 667c478bd9Sstevel@tonic-gate * masks->am_failure - audit on failure 677c478bd9Sstevel@tonic-gate * verbose - string format. 0 if short name; 1 if long name; 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * output: auditstring - resultant audit string 707c478bd9Sstevel@tonic-gate * 717c478bd9Sstevel@tonic-gate * returns: 0 - entry read ok 727c478bd9Sstevel@tonic-gate * -1 - error 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate int 76*f8804e7fSgww getauditflagschar(char *auditstring, au_mask_t *masks, int verbose) 777c478bd9Sstevel@tonic-gate { 787c478bd9Sstevel@tonic-gate char *prefix; /* +, -, or null */ 797c478bd9Sstevel@tonic-gate unsigned int m; /* for masking with masks */ 807c478bd9Sstevel@tonic-gate au_mask_t all; /* value for the string "all" */ 817c478bd9Sstevel@tonic-gate int plus_all = 0; /* true if +all */ 827c478bd9Sstevel@tonic-gate int minus_all = 0; /* true if -all */ 837c478bd9Sstevel@tonic-gate int l; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* initialize input buffer */ 867c478bd9Sstevel@tonic-gate *auditstring = '\0'; 877c478bd9Sstevel@tonic-gate /* no masks, no flags; we're outta here */ 887c478bd9Sstevel@tonic-gate if ((masks->am_success == 0) && (masks->am_failure == 0)) { 897c478bd9Sstevel@tonic-gate if (match_class(auditstring, "", 0, verbose) != 0) 907c478bd9Sstevel@tonic-gate return (-1); 917c478bd9Sstevel@tonic-gate /* kludge to get rid of trailing comma */ 927c478bd9Sstevel@tonic-gate l = strlen(auditstring) - 1; 93*f8804e7fSgww if (auditstring[l] == ',') 947c478bd9Sstevel@tonic-gate auditstring[l] = '\0'; 957c478bd9Sstevel@tonic-gate return (0); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate /* Get the mask value for the string "all" */ 987c478bd9Sstevel@tonic-gate all.am_success = 0; 997c478bd9Sstevel@tonic-gate all.am_failure = 0; 1007c478bd9Sstevel@tonic-gate if (getauditflagsbin("all", &all) != 0) 1017c478bd9Sstevel@tonic-gate return (-1); 1027c478bd9Sstevel@tonic-gate if (all.am_success == masks->am_success) { 1037c478bd9Sstevel@tonic-gate if (all.am_failure == masks->am_failure) { 1047c478bd9Sstevel@tonic-gate (void) strcat(auditstring, "all"); 1057c478bd9Sstevel@tonic-gate return (0); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate (void) strcat(auditstring, "+all,"); 1087c478bd9Sstevel@tonic-gate plus_all = 1; 1097c478bd9Sstevel@tonic-gate } else if (all.am_failure == masks->am_failure) { 1107c478bd9Sstevel@tonic-gate (void) strcat(auditstring, "-all,"); 1117c478bd9Sstevel@tonic-gate minus_all = 1; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate for (m = (unsigned)0x80000000; m != 0; m >>= 1) { 1147c478bd9Sstevel@tonic-gate if (m & masks->am_success & masks->am_failure) 1157c478bd9Sstevel@tonic-gate prefix = plus_all ? "-" : (minus_all ? "+" : ""); 1167c478bd9Sstevel@tonic-gate else if (m & masks->am_success) 1177c478bd9Sstevel@tonic-gate prefix = "+"; 1187c478bd9Sstevel@tonic-gate else if (m & masks->am_failure) 1197c478bd9Sstevel@tonic-gate prefix = "-"; 1207c478bd9Sstevel@tonic-gate else 1217c478bd9Sstevel@tonic-gate continue; 1227c478bd9Sstevel@tonic-gate if (match_class(auditstring, prefix, m, verbose) != 0) 1237c478bd9Sstevel@tonic-gate return (-1); 1247c478bd9Sstevel@tonic-gate } 125*f8804e7fSgww if (*(prefix = auditstring + strlen(auditstring) - 1) == ',') 1267c478bd9Sstevel@tonic-gate *prefix = '\0'; 1277c478bd9Sstevel@tonic-gate return (0); 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 132*f8804e7fSgww * Audit flags: 133*f8804e7fSgww * 134*f8804e7fSgww * [+ | - | ^ | ^+ | ^-]<classname>{,[+ | - | ^ | ^+ | ^-]<classname>}* 135*f8804e7fSgww * 136*f8804e7fSgww * <classname>, add class mask to success and failure mask. 137*f8804e7fSgww * +<classname>, add class mask only to success mask. 138*f8804e7fSgww * -<classname>, add class mask only to failure mask. 139*f8804e7fSgww * ^<classname>, remove class mask from success and failure mask. 140*f8804e7fSgww * ^+<classname>, remove class mask from success mask. 141*f8804e7fSgww * ^-<classname>, remove class mask from failure mask. 142*f8804e7fSgww */ 143*f8804e7fSgww 144*f8804e7fSgww /* 145*f8804e7fSgww * __chkflags - check if the audit flags are valid for this system 146*f8804e7fSgww * 147*f8804e7fSgww * Entry flags = audit flags string. 148*f8804e7fSgww * cont = B_TRUE, continue parsing even if error. 149*f8804e7fSgww * B_FALSE, return failure on error. 150*f8804e7fSgww * 151*f8804e7fSgww * Exit mask = audit mask as defined by flags. 152*f8804e7fSgww * 153*f8804e7fSgww * Return B_TRUE if no errors, or continue == B_TRUE. 154*f8804e7fSgww * B_FALSE and if error != NULL, flags in error. 155*f8804e7fSgww */ 156*f8804e7fSgww 157*f8804e7fSgww boolean_t 158*f8804e7fSgww __chkflags(char *flags, au_mask_t *mask, boolean_t cont, char **error) 159*f8804e7fSgww { 160*f8804e7fSgww uint32_t prefix; 161*f8804e7fSgww au_class_ent_t *class; 162*f8804e7fSgww char name[AU_CLASS_NAME_MAX+1]; 163*f8804e7fSgww int i; 164*f8804e7fSgww 165*f8804e7fSgww if (flags == NULL || mask == NULL) { 166*f8804e7fSgww return (B_FALSE); 167*f8804e7fSgww } 168*f8804e7fSgww 169*f8804e7fSgww mask->am_success = 0; 170*f8804e7fSgww mask->am_failure = 0; 171*f8804e7fSgww 172*f8804e7fSgww while (*flags != '\0') { 173*f8804e7fSgww prefix = (SUCCESS | FAILURE); 174*f8804e7fSgww 175*f8804e7fSgww /* skip white space */ 176*f8804e7fSgww while (isspace(*flags)) { 177*f8804e7fSgww flags++; 178*f8804e7fSgww } 179*f8804e7fSgww 180*f8804e7fSgww if (flags == '\0') { 181*f8804e7fSgww break; 182*f8804e7fSgww } 183*f8804e7fSgww if (error != NULL) { 184*f8804e7fSgww /* save error pointer */ 185*f8804e7fSgww *error = flags; 186*f8804e7fSgww } 187*f8804e7fSgww 188*f8804e7fSgww /* get the prefix */ 189*f8804e7fSgww if (*flags == '+') { 190*f8804e7fSgww flags++; 191*f8804e7fSgww prefix ^= FAILURE; 192*f8804e7fSgww } else if (*flags == '-') { 193*f8804e7fSgww flags++; 194*f8804e7fSgww prefix ^= SUCCESS; 195*f8804e7fSgww } else if (*flags == '^') { 196*f8804e7fSgww flags++; 197*f8804e7fSgww prefix |= INVERSE; 198*f8804e7fSgww if (*flags == '+') { 199*f8804e7fSgww flags++; 200*f8804e7fSgww prefix ^= FAILURE; 201*f8804e7fSgww } else if (*flags == '-') { 202*f8804e7fSgww flags++; 203*f8804e7fSgww prefix ^= SUCCESS; 204*f8804e7fSgww } 205*f8804e7fSgww } 206*f8804e7fSgww 207*f8804e7fSgww /* get class name */ 208*f8804e7fSgww 209*f8804e7fSgww for (i = 0; (i < sizeof (name) - 1) && 210*f8804e7fSgww !(*flags == '\0' || *flags == ','); i++) { 211*f8804e7fSgww name[i] = *flags++; 212*f8804e7fSgww } 213*f8804e7fSgww name[i++] = '\0'; 214*f8804e7fSgww if (*flags == ',') { 215*f8804e7fSgww /* skip comma (',') */ 216*f8804e7fSgww flags++; 217*f8804e7fSgww } 218*f8804e7fSgww if (cacheauclassnam(&class, name) != 1) { 219*f8804e7fSgww if (!cont) { 220*f8804e7fSgww return (B_FALSE); 221*f8804e7fSgww } else { 222*f8804e7fSgww char msg[512]; 223*f8804e7fSgww 224*f8804e7fSgww (void) snprintf(msg, sizeof (msg), "invalid " 225*f8804e7fSgww "audit flag %s", name); 226*f8804e7fSgww adt_write_syslog(msg, EINVAL); 227*f8804e7fSgww } 228*f8804e7fSgww } else { 229*f8804e7fSgww /* add class mask */ 230*f8804e7fSgww 231*f8804e7fSgww if ((prefix & (INVERSE | SUCCESS)) == SUCCESS) { 232*f8804e7fSgww mask->am_success |= class->ac_class; 233*f8804e7fSgww } else if ((prefix & (INVERSE | SUCCESS)) == 234*f8804e7fSgww (INVERSE | SUCCESS)) { 235*f8804e7fSgww mask->am_success &= ~(class->ac_class); 236*f8804e7fSgww } 237*f8804e7fSgww if ((prefix & (INVERSE | FAILURE)) == FAILURE) { 238*f8804e7fSgww mask->am_failure |= class->ac_class; 239*f8804e7fSgww } else if ((prefix & (INVERSE | FAILURE)) == 240*f8804e7fSgww (INVERSE | FAILURE)) { 241*f8804e7fSgww mask->am_failure &= ~(class->ac_class); 242*f8804e7fSgww } 243*f8804e7fSgww } 244*f8804e7fSgww } 245*f8804e7fSgww 246*f8804e7fSgww return (B_TRUE); 247*f8804e7fSgww } 248*f8804e7fSgww 249*f8804e7fSgww /* 2507c478bd9Sstevel@tonic-gate * getauditflagsbin() - converts character string to success and 2517c478bd9Sstevel@tonic-gate * failure bit masks 2527c478bd9Sstevel@tonic-gate * 2537c478bd9Sstevel@tonic-gate * input: auditstring - audit string 2547c478bd9Sstevel@tonic-gate * 2557c478bd9Sstevel@tonic-gate * output: masks->am_success - audit on success 2567c478bd9Sstevel@tonic-gate * masks->am_failure - audit on failure 2577c478bd9Sstevel@tonic-gate * 2587c478bd9Sstevel@tonic-gate * returns: 0 - ok 259*f8804e7fSgww * -1 - error - string or mask NULL. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate int 263*f8804e7fSgww getauditflagsbin(char *auditstring, au_mask_t *masks) 2647c478bd9Sstevel@tonic-gate { 265*f8804e7fSgww if (__chkflags(auditstring, masks, B_TRUE, NULL)) { 266*f8804e7fSgww return (0); 267*f8804e7fSgww } 2687c478bd9Sstevel@tonic-gate return (-1); 2697c478bd9Sstevel@tonic-gate } 270