1 /* 2 * Copyright (c) 2004 Apple Computer, Inc. 3 * Copyright (c) 2006 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_flags.c#13 $ 31 */ 32 33 #include <bsm/libbsm.h> 34 35 #include <errno.h> 36 #include <stdio.h> 37 #include <string.h> 38 39 static const char *flagdelim = ","; 40 41 /* 42 * Convert the character representation of audit values into the au_mask_t 43 * field. 44 */ 45 int 46 getauditflagsbin(char *auditstr, au_mask_t *masks) 47 { 48 char class_ent_name[AU_CLASS_NAME_MAX]; 49 char class_ent_desc[AU_CLASS_DESC_MAX]; 50 struct au_class_ent c; 51 char *tok; 52 char sel, sub; 53 char *last; 54 55 bzero(&c, sizeof(c)); 56 bzero(class_ent_name, sizeof(class_ent_name)); 57 bzero(class_ent_desc, sizeof(class_ent_desc)); 58 c.ac_name = class_ent_name; 59 c.ac_desc = class_ent_desc; 60 61 masks->am_success = 0; 62 masks->am_failure = 0; 63 64 tok = strtok_r(auditstr, flagdelim, &last); 65 while (tok != NULL) { 66 /* Check for the events that should not be audited. */ 67 if (tok[0] == '^') { 68 sub = 1; 69 tok++; 70 } else 71 sub = 0; 72 73 /* Check for the events to be audited for success. */ 74 if (tok[0] == '+') { 75 sel = AU_PRS_SUCCESS; 76 tok++; 77 } else if (tok[0] == '-') { 78 sel = AU_PRS_FAILURE; 79 tok++; 80 } else 81 sel = AU_PRS_BOTH; 82 83 if ((getauclassnam_r(&c, tok)) != NULL) { 84 if (sub) 85 SUB_FROM_MASK(masks, c.ac_class, sel); 86 else 87 ADD_TO_MASK(masks, c.ac_class, sel); 88 } else { 89 errno = EINVAL; 90 return (-1); 91 } 92 93 /* Get the next class. */ 94 tok = strtok_r(NULL, flagdelim, &last); 95 } 96 return (0); 97 } 98 99 /* 100 * Convert the au_mask_t fields into a string value. If verbose is non-zero 101 * the long flag names are used else the short (2-character)flag names are 102 * used. 103 * 104 * XXXRW: If bits are specified that are not matched by any class, they are 105 * omitted rather than rejected with EINVAL. 106 * 107 * XXXRW: This is not thread-safe as it relies on atomicity between 108 * setauclass() and sequential calls to getauclassent(). This could be 109 * fixed by iterating through the bitmask fields rather than iterating 110 * through the classes. 111 */ 112 int 113 getauditflagschar(char *auditstr, au_mask_t *masks, int verbose) 114 { 115 char class_ent_name[AU_CLASS_NAME_MAX]; 116 char class_ent_desc[AU_CLASS_DESC_MAX]; 117 struct au_class_ent c; 118 char *strptr = auditstr; 119 u_char sel; 120 121 bzero(&c, sizeof(c)); 122 bzero(class_ent_name, sizeof(class_ent_name)); 123 bzero(class_ent_desc, sizeof(class_ent_desc)); 124 c.ac_name = class_ent_name; 125 c.ac_desc = class_ent_desc; 126 127 /* 128 * Enumerate the class entries, check if each is selected in either 129 * the success or failure masks. 130 */ 131 setauclass(); 132 while ((getauclassent_r(&c)) != NULL) { 133 sel = 0; 134 135 /* Dont do anything for class = no. */ 136 if (c.ac_class == 0) 137 continue; 138 139 sel |= ((c.ac_class & masks->am_success) == c.ac_class) ? 140 AU_PRS_SUCCESS : 0; 141 sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ? 142 AU_PRS_FAILURE : 0; 143 144 /* 145 * No prefix should be attached if both success and failure 146 * are selected. 147 */ 148 if ((sel & AU_PRS_BOTH) == 0) { 149 if ((sel & AU_PRS_SUCCESS) != 0) { 150 *strptr = '+'; 151 strptr = strptr + 1; 152 } else if ((sel & AU_PRS_FAILURE) != 0) { 153 *strptr = '-'; 154 strptr = strptr + 1; 155 } 156 } 157 158 if (sel != 0) { 159 if (verbose) { 160 strcpy(strptr, c.ac_desc); 161 strptr += strlen(c.ac_desc); 162 } else { 163 strcpy(strptr, c.ac_name); 164 strptr += strlen(c.ac_name); 165 } 166 *strptr = ','; /* delimiter */ 167 strptr = strptr + 1; 168 } 169 } 170 171 /* Overwrite the last delimiter with the string terminator. */ 172 if (strptr != auditstr) 173 *(strptr-1) = '\0'; 174 175 return (0); 176 } 177