bsm_user.c revision 292432
1169691Skan/*- 2169691Skan * Copyright (c) 2004 Apple Inc. 3169691Skan * Copyright (c) 2006 Robert N. M. Watson 4169691Skan * All rights reserved. 5169691Skan * 6169691Skan * Redistribution and use in source and binary forms, with or without 7169691Skan * modification, are permitted provided that the following conditions 8169691Skan * are met: 9169691Skan * 1. Redistributions of source code must retain the above copyright 10169691Skan * notice, this list of conditions and the following disclaimer. 11169691Skan * 2. Redistributions in binary form must reproduce the above copyright 12169691Skan * notice, this list of conditions and the following disclaimer in the 13169691Skan * documentation and/or other materials provided with the distribution. 14169691Skan * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15169691Skan * its contributors may be used to endorse or promote products derived 16169691Skan * from this software without specific prior written permission. 17169691Skan * 18169691Skan * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19169691Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20169691Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21169691Skan * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22169691Skan * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23169691Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24169691Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25169691Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26169691Skan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27169691Skan * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28169691Skan * POSSIBILITY OF SUCH DAMAGE. 29169691Skan */ 30169691Skan 31169691Skan#include <config/config.h> 32169691Skan 33169691Skan#include <bsm/libbsm.h> 34169691Skan 35169691Skan#include <string.h> 36169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 37169691Skan#include <pthread.h> 38169691Skan#endif 39169691Skan#include <stdio.h> 40169691Skan#include <stdlib.h> 41169691Skan 42169691Skan#ifndef HAVE_STRLCPY 43169691Skan#include <compat/strlcpy.h> 44169691Skan#endif 45169691Skan 46169691Skan/* 47169691Skan * Parse the contents of the audit_user file into au_user_ent structures. 48169691Skan */ 49169691Skan 50169691Skanstatic FILE *fp = NULL; 51169691Skanstatic char linestr[AU_LINE_MAX]; 52169691Skanstatic const char *user_delim = ":"; 53169691Skan 54169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 55169691Skanstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 56169691Skan#endif 57169691Skan 58169691Skan/* 59169691Skan * Parse one line from the audit_user file into the au_user_ent structure. 60169691Skan */ 61169691Skanstatic struct au_user_ent * 62169691Skanuserfromstr(char *str, struct au_user_ent *u) 63169691Skan{ 64169691Skan char *username, *always, *never; 65169691Skan char *last; 66169691Skan 67169691Skan username = strtok_r(str, user_delim, &last); 68169691Skan always = strtok_r(NULL, user_delim, &last); 69169691Skan never = strtok_r(NULL, user_delim, &last); 70169691Skan 71169691Skan if ((username == NULL) || (always == NULL) || (never == NULL)) 72169691Skan return (NULL); 73169691Skan 74169691Skan if (strlen(username) >= AU_USER_NAME_MAX) 75169691Skan return (NULL); 76169691Skan 77169691Skan strlcpy(u->au_name, username, AU_USER_NAME_MAX); 78169691Skan if (getauditflagsbin(always, &(u->au_always)) == -1) 79169691Skan return (NULL); 80169691Skan 81169691Skan if (getauditflagsbin(never, &(u->au_never)) == -1) 82169691Skan return (NULL); 83169691Skan 84169691Skan return (u); 85169691Skan} 86169691Skan 87169691Skan/* 88169691Skan * Rewind to beginning of the file 89169691Skan */ 90169691Skanstatic void 91169691Skansetauuser_locked(void) 92169691Skan{ 93169691Skan 94169691Skan if (fp != NULL) 95169691Skan fseek(fp, 0, SEEK_SET); 96169691Skan} 97169691Skan 98169691Skanvoid 99169691Skansetauuser(void) 100169691Skan{ 101169691Skan 102169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 103169691Skan pthread_mutex_lock(&mutex); 104169691Skan#endif 105169691Skan setauuser_locked(); 106169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 107169691Skan pthread_mutex_unlock(&mutex); 108169691Skan#endif 109169691Skan} 110169691Skan 111169691Skan/* 112169691Skan * Close the file descriptor 113169691Skan */ 114169691Skanvoid 115169691Skanendauuser(void) 116169691Skan{ 117169691Skan 118169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 119169691Skan pthread_mutex_lock(&mutex); 120169691Skan#endif 121169691Skan if (fp != NULL) { 122169691Skan fclose(fp); 123169691Skan fp = NULL; 124169691Skan } 125169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 126169691Skan pthread_mutex_unlock(&mutex); 127169691Skan#endif 128169691Skan} 129169691Skan 130169691Skan/* 131169691Skan * Enumerate the au_user_ent structures from the file 132169691Skan */ 133169691Skanstatic struct au_user_ent * 134169691Skangetauuserent_r_locked(struct au_user_ent *u) 135169691Skan{ 136169691Skan char *nl; 137169691Skan 138169691Skan if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL)) 139169691Skan return (NULL); 140169691Skan 141169691Skan while (1) { 142169691Skan if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 143169691Skan return (NULL); 144169691Skan 145169691Skan /* Remove new lines. */ 146169691Skan if ((nl = strrchr(linestr, '\n')) != NULL) 147169691Skan *nl = '\0'; 148169691Skan 149169691Skan /* Skip comments. */ 150169691Skan if (linestr[0] == '#') 151169691Skan continue; 152169691Skan 153169691Skan /* Get the next structure. */ 154169691Skan if (userfromstr(linestr, u) == NULL) 155169691Skan return (NULL); 156169691Skan break; 157169691Skan } 158169691Skan 159169691Skan return (u); 160169691Skan} 161169691Skan 162169691Skanstruct au_user_ent * 163169691Skangetauuserent_r(struct au_user_ent *u) 164169691Skan{ 165169691Skan struct au_user_ent *up; 166169691Skan 167169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 168169691Skan pthread_mutex_lock(&mutex); 169169691Skan#endif 170169691Skan up = getauuserent_r_locked(u); 171169691Skan#ifdef HAVE_PTHREAD_MUTEX_LOCK 172169691Skan pthread_mutex_unlock(&mutex); 173169691Skan#endif 174169691Skan return (up); 175169691Skan} 176169691Skan 177169691Skanstruct au_user_ent * 178169691Skangetauuserent(void) 179169691Skan{ 180 static char user_ent_name[AU_USER_NAME_MAX]; 181 static struct au_user_ent u; 182 183 bzero(&u, sizeof(u)); 184 bzero(user_ent_name, sizeof(user_ent_name)); 185 u.au_name = user_ent_name; 186 187 return (getauuserent_r(&u)); 188} 189 190/* 191 * Find a au_user_ent structure matching the given user name. 192 */ 193struct au_user_ent * 194getauusernam_r(struct au_user_ent *u, const char *name) 195{ 196 struct au_user_ent *up; 197 198 if (name == NULL) 199 return (NULL); 200 201#ifdef HAVE_PTHREAD_MUTEX_LOCK 202 pthread_mutex_lock(&mutex); 203#endif 204 205 setauuser_locked(); 206 while ((up = getauuserent_r_locked(u)) != NULL) { 207 if (strcmp(name, u->au_name) == 0) { 208#ifdef HAVE_PTHREAD_MUTEX_LOCK 209 pthread_mutex_unlock(&mutex); 210#endif 211 return (up); 212 } 213 } 214 215#ifdef HAVE_PTHREAD_MUTEX_LOCK 216 pthread_mutex_unlock(&mutex); 217#endif 218 return (NULL); 219 220} 221 222struct au_user_ent * 223getauusernam(const char *name) 224{ 225 static char user_ent_name[AU_USER_NAME_MAX]; 226 static struct au_user_ent u; 227 228 bzero(&u, sizeof(u)); 229 bzero(user_ent_name, sizeof(user_ent_name)); 230 u.au_name = user_ent_name; 231 232 return (getauusernam_r(&u, name)); 233} 234 235/* 236 * Read the default system wide audit classes from audit_control, combine with 237 * the per-user audit class and update the binary preselection mask. 238 */ 239int 240au_user_mask(char *username, au_mask_t *mask_p) 241{ 242 char auditstring[MAX_AUDITSTRING_LEN + 1]; 243 char user_ent_name[AU_USER_NAME_MAX]; 244 struct au_user_ent u, *up; 245 246 bzero(&u, sizeof(u)); 247 bzero(user_ent_name, sizeof(user_ent_name)); 248 u.au_name = user_ent_name; 249 250 /* Get user mask. */ 251 if ((up = getauusernam_r(&u, username)) != NULL) { 252 if (-1 == getfauditflags(&up->au_always, &up->au_never, 253 mask_p)) 254 return (-1); 255 return (0); 256 } 257 258 /* Read the default system mask. */ 259 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 260 if (-1 == getauditflagsbin(auditstring, mask_p)) 261 return (-1); 262 return (0); 263 } 264 265 /* No masks defined. */ 266 return (-1); 267} 268 269/* 270 * Generate the process audit state by combining the audit masks passed as 271 * parameters with the system audit masks. 272 */ 273int 274getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask) 275{ 276 char auditstring[MAX_AUDITSTRING_LEN + 1]; 277 278 if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL)) 279 return (-1); 280 281 lastmask->am_success = 0; 282 lastmask->am_failure = 0; 283 284 /* Get the system mask. */ 285 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 286 if (getauditflagsbin(auditstring, lastmask) != 0) 287 return (-1); 288 } 289 290 ADDMASK(lastmask, usremask); 291 SUBMASK(lastmask, usrdmask); 292 293 return (0); 294} 295