1185573Srwatson/*- 2185573Srwatson * Copyright (c) 2004 Apple Inc. 3155131Srwatson * Copyright (c) 2006 Robert N. M. Watson 4155131Srwatson * All rights reserved. 5155131Srwatson * 6155131Srwatson * Redistribution and use in source and binary forms, with or without 7155131Srwatson * modification, are permitted provided that the following conditions 8155131Srwatson * are met: 9155131Srwatson * 1. Redistributions of source code must retain the above copyright 10155131Srwatson * notice, this list of conditions and the following disclaimer. 11155131Srwatson * 2. Redistributions in binary form must reproduce the above copyright 12155131Srwatson * notice, this list of conditions and the following disclaimer in the 13155131Srwatson * documentation and/or other materials provided with the distribution. 14185573Srwatson * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15155131Srwatson * its contributors may be used to endorse or promote products derived 16155131Srwatson * from this software without specific prior written permission. 17155131Srwatson * 18155131Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19155131Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21155131Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22155131Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26155131Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27155131Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28155131Srwatson * POSSIBILITY OF SUCH DAMAGE. 29155131Srwatson */ 30155131Srwatson 31185573Srwatson#include <config/config.h> 32185573Srwatson 33155131Srwatson#include <bsm/libbsm.h> 34155131Srwatson 35155131Srwatson#include <string.h> 36186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 37155131Srwatson#include <pthread.h> 38186647Srwatson#endif 39155131Srwatson#include <stdio.h> 40155131Srwatson#include <stdlib.h> 41155131Srwatson 42185573Srwatson#ifndef HAVE_STRLCPY 43185573Srwatson#include <compat/strlcpy.h> 44185573Srwatson#endif 45185573Srwatson 46155131Srwatson/* 47155131Srwatson * Parse the contents of the audit_user file into au_user_ent structures. 48155131Srwatson */ 49155131Srwatson 50155131Srwatsonstatic FILE *fp = NULL; 51155131Srwatsonstatic char linestr[AU_LINE_MAX]; 52155131Srwatsonstatic const char *user_delim = ":"; 53155131Srwatson 54186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 55155131Srwatsonstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 56186647Srwatson#endif 57155131Srwatson 58155131Srwatson/* 59155131Srwatson * Parse one line from the audit_user file into the au_user_ent structure. 60155131Srwatson */ 61155131Srwatsonstatic struct au_user_ent * 62155131Srwatsonuserfromstr(char *str, struct au_user_ent *u) 63155131Srwatson{ 64155131Srwatson char *username, *always, *never; 65155131Srwatson char *last; 66155131Srwatson 67155131Srwatson username = strtok_r(str, user_delim, &last); 68155131Srwatson always = strtok_r(NULL, user_delim, &last); 69155131Srwatson never = strtok_r(NULL, user_delim, &last); 70155131Srwatson 71155131Srwatson if ((username == NULL) || (always == NULL) || (never == NULL)) 72155131Srwatson return (NULL); 73155131Srwatson 74155131Srwatson if (strlen(username) >= AU_USER_NAME_MAX) 75155131Srwatson return (NULL); 76155131Srwatson 77185573Srwatson strlcpy(u->au_name, username, AU_USER_NAME_MAX); 78155131Srwatson if (getauditflagsbin(always, &(u->au_always)) == -1) 79155131Srwatson return (NULL); 80155131Srwatson 81155131Srwatson if (getauditflagsbin(never, &(u->au_never)) == -1) 82155131Srwatson return (NULL); 83155131Srwatson 84155131Srwatson return (u); 85155131Srwatson} 86155131Srwatson 87155131Srwatson/* 88155131Srwatson * Rewind to beginning of the file 89155131Srwatson */ 90155131Srwatsonstatic void 91155131Srwatsonsetauuser_locked(void) 92155131Srwatson{ 93155131Srwatson 94155131Srwatson if (fp != NULL) 95155131Srwatson fseek(fp, 0, SEEK_SET); 96155131Srwatson} 97155131Srwatson 98155131Srwatsonvoid 99155131Srwatsonsetauuser(void) 100155131Srwatson{ 101155131Srwatson 102186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 103155131Srwatson pthread_mutex_lock(&mutex); 104186647Srwatson#endif 105155131Srwatson setauuser_locked(); 106186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 107155131Srwatson pthread_mutex_unlock(&mutex); 108186647Srwatson#endif 109155131Srwatson} 110155131Srwatson 111155131Srwatson/* 112155131Srwatson * Close the file descriptor 113155131Srwatson */ 114155131Srwatsonvoid 115155131Srwatsonendauuser(void) 116155131Srwatson{ 117155131Srwatson 118186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 119155131Srwatson pthread_mutex_lock(&mutex); 120186647Srwatson#endif 121155131Srwatson if (fp != NULL) { 122155131Srwatson fclose(fp); 123155131Srwatson fp = NULL; 124155131Srwatson } 125186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 126155131Srwatson pthread_mutex_unlock(&mutex); 127186647Srwatson#endif 128155131Srwatson} 129155131Srwatson 130155131Srwatson/* 131155131Srwatson * Enumerate the au_user_ent structures from the file 132155131Srwatson */ 133155131Srwatsonstatic struct au_user_ent * 134155131Srwatsongetauuserent_r_locked(struct au_user_ent *u) 135155131Srwatson{ 136155131Srwatson char *nl; 137155131Srwatson 138155131Srwatson if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL)) 139155131Srwatson return (NULL); 140155131Srwatson 141155131Srwatson while (1) { 142155131Srwatson if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 143155131Srwatson return (NULL); 144155131Srwatson 145155131Srwatson /* Remove new lines. */ 146155131Srwatson if ((nl = strrchr(linestr, '\n')) != NULL) 147155131Srwatson *nl = '\0'; 148155131Srwatson 149155131Srwatson /* Skip comments. */ 150155131Srwatson if (linestr[0] == '#') 151155131Srwatson continue; 152155131Srwatson 153155131Srwatson /* Get the next structure. */ 154155131Srwatson if (userfromstr(linestr, u) == NULL) 155155131Srwatson return (NULL); 156155131Srwatson break; 157155131Srwatson } 158155131Srwatson 159155131Srwatson return (u); 160155131Srwatson} 161155131Srwatson 162155131Srwatsonstruct au_user_ent * 163155131Srwatsongetauuserent_r(struct au_user_ent *u) 164155131Srwatson{ 165155131Srwatson struct au_user_ent *up; 166155131Srwatson 167186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 168155131Srwatson pthread_mutex_lock(&mutex); 169186647Srwatson#endif 170155131Srwatson up = getauuserent_r_locked(u); 171186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 172155131Srwatson pthread_mutex_unlock(&mutex); 173186647Srwatson#endif 174155131Srwatson return (up); 175155131Srwatson} 176155131Srwatson 177155131Srwatsonstruct au_user_ent * 178155131Srwatsongetauuserent(void) 179155131Srwatson{ 180155131Srwatson static char user_ent_name[AU_USER_NAME_MAX]; 181155131Srwatson static struct au_user_ent u; 182155131Srwatson 183155131Srwatson bzero(&u, sizeof(u)); 184155131Srwatson bzero(user_ent_name, sizeof(user_ent_name)); 185155131Srwatson u.au_name = user_ent_name; 186155131Srwatson 187155131Srwatson return (getauuserent_r(&u)); 188155131Srwatson} 189155131Srwatson 190155131Srwatson/* 191155131Srwatson * Find a au_user_ent structure matching the given user name. 192155131Srwatson */ 193155131Srwatsonstruct au_user_ent * 194155131Srwatsongetauusernam_r(struct au_user_ent *u, const char *name) 195155131Srwatson{ 196155131Srwatson struct au_user_ent *up; 197155131Srwatson 198155131Srwatson if (name == NULL) 199155131Srwatson return (NULL); 200155131Srwatson 201186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 202155131Srwatson pthread_mutex_lock(&mutex); 203186647Srwatson#endif 204155131Srwatson 205155131Srwatson setauuser_locked(); 206155131Srwatson while ((up = getauuserent_r_locked(u)) != NULL) { 207155131Srwatson if (strcmp(name, u->au_name) == 0) { 208186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 209155131Srwatson pthread_mutex_unlock(&mutex); 210186647Srwatson#endif 211243750Srwatson return (up); 212155131Srwatson } 213155131Srwatson } 214155131Srwatson 215186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 216155131Srwatson pthread_mutex_unlock(&mutex); 217186647Srwatson#endif 218155131Srwatson return (NULL); 219155131Srwatson 220155131Srwatson} 221155131Srwatson 222155131Srwatsonstruct au_user_ent * 223155131Srwatsongetauusernam(const char *name) 224155131Srwatson{ 225155131Srwatson static char user_ent_name[AU_USER_NAME_MAX]; 226155131Srwatson static struct au_user_ent u; 227155131Srwatson 228155131Srwatson bzero(&u, sizeof(u)); 229155131Srwatson bzero(user_ent_name, sizeof(user_ent_name)); 230155131Srwatson u.au_name = user_ent_name; 231155131Srwatson 232155131Srwatson return (getauusernam_r(&u, name)); 233155131Srwatson} 234155131Srwatson 235155131Srwatson/* 236155131Srwatson * Read the default system wide audit classes from audit_control, combine with 237155131Srwatson * the per-user audit class and update the binary preselection mask. 238155131Srwatson */ 239155131Srwatsonint 240155131Srwatsonau_user_mask(char *username, au_mask_t *mask_p) 241155131Srwatson{ 242155131Srwatson char auditstring[MAX_AUDITSTRING_LEN + 1]; 243155131Srwatson char user_ent_name[AU_USER_NAME_MAX]; 244155131Srwatson struct au_user_ent u, *up; 245155131Srwatson 246155131Srwatson bzero(&u, sizeof(u)); 247155131Srwatson bzero(user_ent_name, sizeof(user_ent_name)); 248155131Srwatson u.au_name = user_ent_name; 249155131Srwatson 250155131Srwatson /* Get user mask. */ 251155131Srwatson if ((up = getauusernam_r(&u, username)) != NULL) { 252155131Srwatson if (-1 == getfauditflags(&up->au_always, &up->au_never, 253155131Srwatson mask_p)) 254155131Srwatson return (-1); 255155131Srwatson return (0); 256155131Srwatson } 257155131Srwatson 258155131Srwatson /* Read the default system mask. */ 259155131Srwatson if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 260155131Srwatson if (-1 == getauditflagsbin(auditstring, mask_p)) 261155131Srwatson return (-1); 262155131Srwatson return (0); 263155131Srwatson } 264155131Srwatson 265155131Srwatson /* No masks defined. */ 266155131Srwatson return (-1); 267155131Srwatson} 268155131Srwatson 269155131Srwatson/* 270155131Srwatson * Generate the process audit state by combining the audit masks passed as 271155131Srwatson * parameters with the system audit masks. 272155131Srwatson */ 273155131Srwatsonint 274155131Srwatsongetfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask) 275155131Srwatson{ 276155131Srwatson char auditstring[MAX_AUDITSTRING_LEN + 1]; 277155131Srwatson 278155131Srwatson if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL)) 279155131Srwatson return (-1); 280155131Srwatson 281155131Srwatson lastmask->am_success = 0; 282155131Srwatson lastmask->am_failure = 0; 283155131Srwatson 284155131Srwatson /* Get the system mask. */ 285155131Srwatson if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 286155131Srwatson if (getauditflagsbin(auditstring, lastmask) != 0) 287155131Srwatson return (-1); 288155131Srwatson } 289155131Srwatson 290155131Srwatson ADDMASK(lastmask, usremask); 291155131Srwatson SUBMASK(lastmask, usrdmask); 292155131Srwatson 293155131Srwatson return (0); 294155131Srwatson} 295