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_user.c#15 $ 31 */ 32 33 #include <bsm/libbsm.h> 34 35 #include <string.h> 36 #include <pthread.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 40 /* 41 * Parse the contents of the audit_user file into au_user_ent structures. 42 */ 43 44 static FILE *fp = NULL; 45 static char linestr[AU_LINE_MAX]; 46 static const char *user_delim = ":"; 47 48 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 49 50 /* 51 * Parse one line from the audit_user file into the au_user_ent structure. 52 */ 53 static struct au_user_ent * 54 userfromstr(char *str, struct au_user_ent *u) 55 { 56 char *username, *always, *never; 57 char *last; 58 59 username = strtok_r(str, user_delim, &last); 60 always = strtok_r(NULL, user_delim, &last); 61 never = strtok_r(NULL, user_delim, &last); 62 63 if ((username == NULL) || (always == NULL) || (never == NULL)) 64 return (NULL); 65 66 if (strlen(username) >= AU_USER_NAME_MAX) 67 return (NULL); 68 69 strcpy(u->au_name, username); 70 if (getauditflagsbin(always, &(u->au_always)) == -1) 71 return (NULL); 72 73 if (getauditflagsbin(never, &(u->au_never)) == -1) 74 return (NULL); 75 76 return (u); 77 } 78 79 /* 80 * Rewind to beginning of the file 81 */ 82 static void 83 setauuser_locked(void) 84 { 85 86 if (fp != NULL) 87 fseek(fp, 0, SEEK_SET); 88 } 89 90 void 91 setauuser(void) 92 { 93 94 pthread_mutex_lock(&mutex); 95 setauuser_locked(); 96 pthread_mutex_unlock(&mutex); 97 } 98 99 /* 100 * Close the file descriptor 101 */ 102 void 103 endauuser(void) 104 { 105 106 pthread_mutex_lock(&mutex); 107 if (fp != NULL) { 108 fclose(fp); 109 fp = NULL; 110 } 111 pthread_mutex_unlock(&mutex); 112 } 113 114 /* 115 * Enumerate the au_user_ent structures from the file 116 */ 117 static struct au_user_ent * 118 getauuserent_r_locked(struct au_user_ent *u) 119 { 120 char *nl; 121 122 if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL)) 123 return (NULL); 124 125 while (1) { 126 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 127 return (NULL); 128 129 /* Remove new lines. */ 130 if ((nl = strrchr(linestr, '\n')) != NULL) 131 *nl = '\0'; 132 133 /* Skip comments. */ 134 if (linestr[0] == '#') 135 continue; 136 137 /* Get the next structure. */ 138 if (userfromstr(linestr, u) == NULL) 139 return (NULL); 140 break; 141 } 142 143 return (u); 144 } 145 146 struct au_user_ent * 147 getauuserent_r(struct au_user_ent *u) 148 { 149 struct au_user_ent *up; 150 151 pthread_mutex_lock(&mutex); 152 up = getauuserent_r_locked(u); 153 pthread_mutex_unlock(&mutex); 154 return (up); 155 } 156 157 struct au_user_ent * 158 getauuserent(void) 159 { 160 static char user_ent_name[AU_USER_NAME_MAX]; 161 static struct au_user_ent u; 162 163 bzero(&u, sizeof(u)); 164 bzero(user_ent_name, sizeof(user_ent_name)); 165 u.au_name = user_ent_name; 166 167 return (getauuserent_r(&u)); 168 } 169 170 /* 171 * Find a au_user_ent structure matching the given user name. 172 */ 173 struct au_user_ent * 174 getauusernam_r(struct au_user_ent *u, const char *name) 175 { 176 struct au_user_ent *up; 177 178 if (name == NULL) 179 return (NULL); 180 181 pthread_mutex_lock(&mutex); 182 183 setauuser_locked(); 184 while ((up = getauuserent_r_locked(u)) != NULL) { 185 if (strcmp(name, u->au_name) == 0) { 186 pthread_mutex_unlock(&mutex); 187 return (u); 188 } 189 } 190 191 pthread_mutex_unlock(&mutex); 192 return (NULL); 193 194 } 195 196 struct au_user_ent * 197 getauusernam(const char *name) 198 { 199 static char user_ent_name[AU_USER_NAME_MAX]; 200 static struct au_user_ent u; 201 202 bzero(&u, sizeof(u)); 203 bzero(user_ent_name, sizeof(user_ent_name)); 204 u.au_name = user_ent_name; 205 206 return (getauusernam_r(&u, name)); 207 } 208 209 /* 210 * Read the default system wide audit classes from audit_control, combine with 211 * the per-user audit class and update the binary preselection mask. 212 */ 213 int 214 au_user_mask(char *username, au_mask_t *mask_p) 215 { 216 char auditstring[MAX_AUDITSTRING_LEN + 1]; 217 char user_ent_name[AU_USER_NAME_MAX]; 218 struct au_user_ent u, *up; 219 220 bzero(&u, sizeof(u)); 221 bzero(user_ent_name, sizeof(user_ent_name)); 222 u.au_name = user_ent_name; 223 224 /* Get user mask. */ 225 if ((up = getauusernam_r(&u, username)) != NULL) { 226 if (-1 == getfauditflags(&up->au_always, &up->au_never, 227 mask_p)) 228 return (-1); 229 return (0); 230 } 231 232 /* Read the default system mask. */ 233 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 234 if (-1 == getauditflagsbin(auditstring, mask_p)) 235 return (-1); 236 return (0); 237 } 238 239 /* No masks defined. */ 240 return (-1); 241 } 242 243 /* 244 * Generate the process audit state by combining the audit masks passed as 245 * parameters with the system audit masks. 246 */ 247 int 248 getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask) 249 { 250 char auditstring[MAX_AUDITSTRING_LEN + 1]; 251 252 if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL)) 253 return (-1); 254 255 lastmask->am_success = 0; 256 lastmask->am_failure = 0; 257 258 /* Get the system mask. */ 259 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 260 if (getauditflagsbin(auditstring, lastmask) != 0) 261 return (-1); 262 } 263 264 ADDMASK(lastmask, usremask); 265 SUBMASK(lastmask, usrdmask); 266 267 return (0); 268 } 269