1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * get audit preselection mask values 27 */ 28 29 #include <ctype.h> 30 #include <stdio.h> 31 #include <string.h> 32 33 #include <sys/errno.h> 34 #include <sys/types.h> 35 #include <bsm/audit.h> 36 #include <bsm/libbsm.h> 37 38 #include <adt_xlate.h> /* adt_write_syslog */ 39 40 #define SUCCESS 0x1 /* '+' success mask */ 41 #define FAILURE 0x2 /* '-' failure mask */ 42 #define INVERSE 0x4 /* '^' invert the mask */ 43 44 static int 45 match_class(char *s, char *prefix, uint_t m, int v) 46 { 47 au_class_ent_t *p_class; 48 49 (void) strcat(s, prefix); 50 if (cacheauclass(&p_class, m) == 1) { 51 if (v == 0) { 52 (void) strncat(s, p_class->ac_name, AU_CLASS_NAME_MAX); 53 } else { 54 (void) strncat(s, p_class->ac_desc, AU_CLASS_DESC_MAX); 55 } 56 (void) strcat(s, ","); 57 return (0); 58 } 59 return (-1); 60 } 61 62 /* 63 * getauditflagschar() - convert bit flag to character string 64 * 65 * input: masks->am_success - audit on success 66 * masks->am_failure - audit on failure 67 * verbose - string format. 0 if short name; 1 if long name; 68 * 69 * output: auditstring - resultant audit string 70 * 71 * returns: 0 - entry read ok 72 * -1 - error 73 */ 74 75 int 76 getauditflagschar(char *auditstring, au_mask_t *masks, int verbose) 77 { 78 char *prefix; /* +, -, or null */ 79 unsigned int m; /* for masking with masks */ 80 au_mask_t all; /* value for the string "all" */ 81 int plus_all = 0; /* true if +all */ 82 int minus_all = 0; /* true if -all */ 83 int l; 84 85 /* initialize input buffer */ 86 *auditstring = '\0'; 87 /* no masks, no flags; we're outta here */ 88 if ((masks->am_success == 0) && (masks->am_failure == 0)) { 89 if (match_class(auditstring, "", 0, verbose) != 0) 90 return (-1); 91 /* kludge to get rid of trailing comma */ 92 l = strlen(auditstring) - 1; 93 if (auditstring[l] == ',') 94 auditstring[l] = '\0'; 95 return (0); 96 } 97 /* Get the mask value for the string "all" */ 98 all.am_success = 0; 99 all.am_failure = 0; 100 if (getauditflagsbin("all", &all) != 0) 101 return (-1); 102 if (all.am_success == masks->am_success) { 103 if (all.am_failure == masks->am_failure) { 104 (void) strcat(auditstring, "all"); 105 return (0); 106 } 107 (void) strcat(auditstring, "+all,"); 108 plus_all = 1; 109 } else if (all.am_failure == masks->am_failure) { 110 (void) strcat(auditstring, "-all,"); 111 minus_all = 1; 112 } 113 for (m = (unsigned)0x80000000; m != 0; m >>= 1) { 114 if (m & masks->am_success & masks->am_failure) 115 prefix = plus_all ? "-" : (minus_all ? "+" : ""); 116 else if (m & masks->am_success) 117 prefix = "+"; 118 else if (m & masks->am_failure) 119 prefix = "-"; 120 else 121 continue; 122 if (match_class(auditstring, prefix, m, verbose) != 0) 123 return (-1); 124 } 125 if (*(prefix = auditstring + strlen(auditstring) - 1) == ',') 126 *prefix = '\0'; 127 return (0); 128 129 } 130 131 /* 132 * Audit flags: 133 * 134 * [+ | - | ^ | ^+ | ^-]<classname>{,[+ | - | ^ | ^+ | ^-]<classname>}* 135 * 136 * <classname>, add class mask to success and failure mask. 137 * +<classname>, add class mask only to success mask. 138 * -<classname>, add class mask only to failure mask. 139 * ^<classname>, remove class mask from success and failure mask. 140 * ^+<classname>, remove class mask from success mask. 141 * ^-<classname>, remove class mask from failure mask. 142 */ 143 144 /* 145 * __chkflags - check if the audit flags are valid for this system 146 * 147 * Entry flags = audit flags string. 148 * cont = B_TRUE, continue parsing even if error. 149 * B_FALSE, return failure on error. 150 * 151 * Exit mask = audit mask as defined by flags. 152 * 153 * Return B_TRUE if no errors, or continue == B_TRUE. 154 * B_FALSE and if error != NULL, flags in error. 155 */ 156 157 boolean_t 158 __chkflags(char *flags, au_mask_t *mask, boolean_t cont, char **error) 159 { 160 uint32_t prefix; 161 au_class_ent_t *class; 162 char name[AU_CLASS_NAME_MAX+1]; 163 int i; 164 165 if (flags == NULL || mask == NULL) { 166 return (B_FALSE); 167 } 168 169 mask->am_success = 0; 170 mask->am_failure = 0; 171 172 while (*flags != '\0') { 173 prefix = (SUCCESS | FAILURE); 174 175 /* skip white space */ 176 while (isspace(*flags)) { 177 flags++; 178 } 179 180 if (flags == '\0') { 181 break; 182 } 183 if (error != NULL) { 184 /* save error pointer */ 185 *error = flags; 186 } 187 188 /* get the prefix */ 189 if (*flags == '+') { 190 flags++; 191 prefix ^= FAILURE; 192 } else if (*flags == '-') { 193 flags++; 194 prefix ^= SUCCESS; 195 } else if (*flags == '^') { 196 flags++; 197 prefix |= INVERSE; 198 if (*flags == '+') { 199 flags++; 200 prefix ^= FAILURE; 201 } else if (*flags == '-') { 202 flags++; 203 prefix ^= SUCCESS; 204 } 205 } 206 207 /* get class name */ 208 209 for (i = 0; (i < sizeof (name) - 1) && 210 !(*flags == '\0' || *flags == ','); i++) { 211 name[i] = *flags++; 212 } 213 name[i++] = '\0'; 214 if (*flags == ',') { 215 /* skip comma (',') */ 216 flags++; 217 } 218 if (cacheauclassnam(&class, name) != 1) { 219 if (!cont) { 220 return (B_FALSE); 221 } else { 222 char msg[512]; 223 224 (void) snprintf(msg, sizeof (msg), "invalid " 225 "audit flag %s", name); 226 adt_write_syslog(msg, EINVAL); 227 } 228 } else { 229 /* add class mask */ 230 231 if ((prefix & (INVERSE | SUCCESS)) == SUCCESS) { 232 mask->am_success |= class->ac_class; 233 } else if ((prefix & (INVERSE | SUCCESS)) == 234 (INVERSE | SUCCESS)) { 235 mask->am_success &= ~(class->ac_class); 236 } 237 if ((prefix & (INVERSE | FAILURE)) == FAILURE) { 238 mask->am_failure |= class->ac_class; 239 } else if ((prefix & (INVERSE | FAILURE)) == 240 (INVERSE | FAILURE)) { 241 mask->am_failure &= ~(class->ac_class); 242 } 243 } 244 } 245 246 return (B_TRUE); 247 } 248 249 /* 250 * getauditflagsbin() - converts character string to success and 251 * failure bit masks 252 * 253 * input: auditstring - audit string 254 * 255 * output: masks->am_success - audit on success 256 * masks->am_failure - audit on failure 257 * 258 * returns: 0 - ok 259 * -1 - error - string or mask NULL. 260 */ 261 262 int 263 getauditflagsbin(char *auditstring, au_mask_t *masks) 264 { 265 if (__chkflags(auditstring, masks, B_TRUE, NULL)) { 266 return (0); 267 } 268 return (-1); 269 } 270