1 /*- 2 * Copyright (c) 2004 Apple 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 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#16 $ 31 */ 32 33 #include <config/config.h> 34 35 #include <bsm/libbsm.h> 36 37 #include <errno.h> 38 #include <stdio.h> 39 #include <string.h> 40 41 #ifndef HAVE_STRLCPY 42 #include <compat/strlcpy.h> 43 #endif 44 45 static const char *flagdelim = ","; 46 47 /* 48 * Convert the character representation of audit values into the au_mask_t 49 * field. 50 */ 51 int 52 getauditflagsbin(char *auditstr, au_mask_t *masks) 53 { 54 char class_ent_name[AU_CLASS_NAME_MAX]; 55 char class_ent_desc[AU_CLASS_DESC_MAX]; 56 struct au_class_ent c; 57 char *tok; 58 char sel, sub; 59 char *last; 60 61 bzero(&c, sizeof(c)); 62 bzero(class_ent_name, sizeof(class_ent_name)); 63 bzero(class_ent_desc, sizeof(class_ent_desc)); 64 c.ac_name = class_ent_name; 65 c.ac_desc = class_ent_desc; 66 67 masks->am_success = 0; 68 masks->am_failure = 0; 69 70 tok = strtok_r(auditstr, flagdelim, &last); 71 while (tok != NULL) { 72 /* Check for the events that should not be audited. */ 73 if (tok[0] == '^') { 74 sub = 1; 75 tok++; 76 } else 77 sub = 0; 78 79 /* Check for the events to be audited for success. */ 80 if (tok[0] == '+') { 81 sel = AU_PRS_SUCCESS; 82 tok++; 83 } else if (tok[0] == '-') { 84 sel = AU_PRS_FAILURE; 85 tok++; 86 } else 87 sel = AU_PRS_BOTH; 88 89 if ((getauclassnam_r(&c, tok)) != NULL) { 90 if (sub) 91 SUB_FROM_MASK(masks, c.ac_class, sel); 92 else 93 ADD_TO_MASK(masks, c.ac_class, sel); 94 } else { 95 errno = EINVAL; 96 return (-1); 97 } 98 99 /* Get the next class. */ 100 tok = strtok_r(NULL, flagdelim, &last); 101 } 102 return (0); 103 } 104 105 /* 106 * Convert the au_mask_t fields into a string value. If verbose is non-zero 107 * the long flag names are used else the short (2-character)flag names are 108 * used. 109 * 110 * XXXRW: If bits are specified that are not matched by any class, they are 111 * omitted rather than rejected with EINVAL. 112 * 113 * XXXRW: This is not thread-safe as it relies on atomicity between 114 * setauclass() and sequential calls to getauclassent(). This could be 115 * fixed by iterating through the bitmask fields rather than iterating 116 * through the classes. 117 */ 118 int 119 getauditflagschar(char *auditstr, au_mask_t *masks, int verbose) 120 { 121 char class_ent_name[AU_CLASS_NAME_MAX]; 122 char class_ent_desc[AU_CLASS_DESC_MAX]; 123 struct au_class_ent c; 124 char *strptr = auditstr; 125 u_char sel; 126 127 bzero(&c, sizeof(c)); 128 bzero(class_ent_name, sizeof(class_ent_name)); 129 bzero(class_ent_desc, sizeof(class_ent_desc)); 130 c.ac_name = class_ent_name; 131 c.ac_desc = class_ent_desc; 132 133 /* 134 * Enumerate the class entries, check if each is selected in either 135 * the success or failure masks. 136 */ 137 setauclass(); 138 while ((getauclassent_r(&c)) != NULL) { 139 sel = 0; 140 141 /* Dont do anything for class = no. */ 142 if (c.ac_class == 0) 143 continue; 144 145 sel |= ((c.ac_class & masks->am_success) == c.ac_class) ? 146 AU_PRS_SUCCESS : 0; 147 sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ? 148 AU_PRS_FAILURE : 0; 149 150 /* 151 * No prefix should be attached if both success and failure 152 * are selected. 153 */ 154 if ((sel & AU_PRS_BOTH) == 0) { 155 if ((sel & AU_PRS_SUCCESS) != 0) { 156 *strptr = '+'; 157 strptr = strptr + 1; 158 } else if ((sel & AU_PRS_FAILURE) != 0) { 159 *strptr = '-'; 160 strptr = strptr + 1; 161 } 162 } 163 164 if (sel != 0) { 165 if (verbose) { 166 strlcpy(strptr, c.ac_desc, AU_CLASS_DESC_MAX); 167 strptr += strlen(c.ac_desc); 168 } else { 169 strlcpy(strptr, c.ac_name, AU_CLASS_NAME_MAX); 170 strptr += strlen(c.ac_name); 171 } 172 *strptr = ','; /* delimiter */ 173 strptr = strptr + 1; 174 } 175 } 176 177 /* Overwrite the last delimiter with the string terminator. */ 178 if (strptr != auditstr) 179 *(strptr-1) = '\0'; 180 181 return (0); 182 } 183