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 * 30243750Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#20 $ 31155131Srwatson */ 32155131Srwatson 33185573Srwatson#include <config/config.h> 34185573Srwatson 35155131Srwatson#include <bsm/libbsm.h> 36155131Srwatson 37155131Srwatson#include <string.h> 38186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 39155131Srwatson#include <pthread.h> 40186647Srwatson#endif 41155131Srwatson#include <stdio.h> 42155131Srwatson#include <stdlib.h> 43155131Srwatson 44185573Srwatson#ifndef HAVE_STRLCPY 45185573Srwatson#include <compat/strlcpy.h> 46185573Srwatson#endif 47185573Srwatson 48155131Srwatson/* 49155131Srwatson * Parse the contents of the audit_user file into au_user_ent structures. 50155131Srwatson */ 51155131Srwatson 52155131Srwatsonstatic FILE *fp = NULL; 53155131Srwatsonstatic char linestr[AU_LINE_MAX]; 54155131Srwatsonstatic const char *user_delim = ":"; 55155131Srwatson 56186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 57155131Srwatsonstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 58186647Srwatson#endif 59155131Srwatson 60155131Srwatson/* 61155131Srwatson * Parse one line from the audit_user file into the au_user_ent structure. 62155131Srwatson */ 63155131Srwatsonstatic struct au_user_ent * 64155131Srwatsonuserfromstr(char *str, struct au_user_ent *u) 65155131Srwatson{ 66155131Srwatson char *username, *always, *never; 67155131Srwatson char *last; 68155131Srwatson 69155131Srwatson username = strtok_r(str, user_delim, &last); 70155131Srwatson always = strtok_r(NULL, user_delim, &last); 71155131Srwatson never = strtok_r(NULL, user_delim, &last); 72155131Srwatson 73155131Srwatson if ((username == NULL) || (always == NULL) || (never == NULL)) 74155131Srwatson return (NULL); 75155131Srwatson 76155131Srwatson if (strlen(username) >= AU_USER_NAME_MAX) 77155131Srwatson return (NULL); 78155131Srwatson 79185573Srwatson strlcpy(u->au_name, username, AU_USER_NAME_MAX); 80155131Srwatson if (getauditflagsbin(always, &(u->au_always)) == -1) 81155131Srwatson return (NULL); 82155131Srwatson 83155131Srwatson if (getauditflagsbin(never, &(u->au_never)) == -1) 84155131Srwatson return (NULL); 85155131Srwatson 86155131Srwatson return (u); 87155131Srwatson} 88155131Srwatson 89155131Srwatson/* 90155131Srwatson * Rewind to beginning of the file 91155131Srwatson */ 92155131Srwatsonstatic void 93155131Srwatsonsetauuser_locked(void) 94155131Srwatson{ 95155131Srwatson 96155131Srwatson if (fp != NULL) 97155131Srwatson fseek(fp, 0, SEEK_SET); 98155131Srwatson} 99155131Srwatson 100155131Srwatsonvoid 101155131Srwatsonsetauuser(void) 102155131Srwatson{ 103155131Srwatson 104186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 105155131Srwatson pthread_mutex_lock(&mutex); 106186647Srwatson#endif 107155131Srwatson setauuser_locked(); 108186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 109155131Srwatson pthread_mutex_unlock(&mutex); 110186647Srwatson#endif 111155131Srwatson} 112155131Srwatson 113155131Srwatson/* 114155131Srwatson * Close the file descriptor 115155131Srwatson */ 116155131Srwatsonvoid 117155131Srwatsonendauuser(void) 118155131Srwatson{ 119155131Srwatson 120186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 121155131Srwatson pthread_mutex_lock(&mutex); 122186647Srwatson#endif 123155131Srwatson if (fp != NULL) { 124155131Srwatson fclose(fp); 125155131Srwatson fp = NULL; 126155131Srwatson } 127186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 128155131Srwatson pthread_mutex_unlock(&mutex); 129186647Srwatson#endif 130155131Srwatson} 131155131Srwatson 132155131Srwatson/* 133155131Srwatson * Enumerate the au_user_ent structures from the file 134155131Srwatson */ 135155131Srwatsonstatic struct au_user_ent * 136155131Srwatsongetauuserent_r_locked(struct au_user_ent *u) 137155131Srwatson{ 138155131Srwatson char *nl; 139155131Srwatson 140155131Srwatson if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL)) 141155131Srwatson return (NULL); 142155131Srwatson 143155131Srwatson while (1) { 144155131Srwatson if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 145155131Srwatson return (NULL); 146155131Srwatson 147155131Srwatson /* Remove new lines. */ 148155131Srwatson if ((nl = strrchr(linestr, '\n')) != NULL) 149155131Srwatson *nl = '\0'; 150155131Srwatson 151155131Srwatson /* Skip comments. */ 152155131Srwatson if (linestr[0] == '#') 153155131Srwatson continue; 154155131Srwatson 155155131Srwatson /* Get the next structure. */ 156155131Srwatson if (userfromstr(linestr, u) == NULL) 157155131Srwatson return (NULL); 158155131Srwatson break; 159155131Srwatson } 160155131Srwatson 161155131Srwatson return (u); 162155131Srwatson} 163155131Srwatson 164155131Srwatsonstruct au_user_ent * 165155131Srwatsongetauuserent_r(struct au_user_ent *u) 166155131Srwatson{ 167155131Srwatson struct au_user_ent *up; 168155131Srwatson 169186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 170155131Srwatson pthread_mutex_lock(&mutex); 171186647Srwatson#endif 172155131Srwatson up = getauuserent_r_locked(u); 173186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 174155131Srwatson pthread_mutex_unlock(&mutex); 175186647Srwatson#endif 176155131Srwatson return (up); 177155131Srwatson} 178155131Srwatson 179155131Srwatsonstruct au_user_ent * 180155131Srwatsongetauuserent(void) 181155131Srwatson{ 182155131Srwatson static char user_ent_name[AU_USER_NAME_MAX]; 183155131Srwatson static struct au_user_ent u; 184155131Srwatson 185155131Srwatson bzero(&u, sizeof(u)); 186155131Srwatson bzero(user_ent_name, sizeof(user_ent_name)); 187155131Srwatson u.au_name = user_ent_name; 188155131Srwatson 189155131Srwatson return (getauuserent_r(&u)); 190155131Srwatson} 191155131Srwatson 192155131Srwatson/* 193155131Srwatson * Find a au_user_ent structure matching the given user name. 194155131Srwatson */ 195155131Srwatsonstruct au_user_ent * 196155131Srwatsongetauusernam_r(struct au_user_ent *u, const char *name) 197155131Srwatson{ 198155131Srwatson struct au_user_ent *up; 199155131Srwatson 200155131Srwatson if (name == NULL) 201155131Srwatson return (NULL); 202155131Srwatson 203186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 204155131Srwatson pthread_mutex_lock(&mutex); 205186647Srwatson#endif 206155131Srwatson 207155131Srwatson setauuser_locked(); 208155131Srwatson while ((up = getauuserent_r_locked(u)) != NULL) { 209155131Srwatson if (strcmp(name, u->au_name) == 0) { 210186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 211155131Srwatson pthread_mutex_unlock(&mutex); 212186647Srwatson#endif 213243750Srwatson return (up); 214155131Srwatson } 215155131Srwatson } 216155131Srwatson 217186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK 218155131Srwatson pthread_mutex_unlock(&mutex); 219186647Srwatson#endif 220155131Srwatson return (NULL); 221155131Srwatson 222155131Srwatson} 223155131Srwatson 224155131Srwatsonstruct au_user_ent * 225155131Srwatsongetauusernam(const char *name) 226155131Srwatson{ 227155131Srwatson static char user_ent_name[AU_USER_NAME_MAX]; 228155131Srwatson static struct au_user_ent u; 229155131Srwatson 230155131Srwatson bzero(&u, sizeof(u)); 231155131Srwatson bzero(user_ent_name, sizeof(user_ent_name)); 232155131Srwatson u.au_name = user_ent_name; 233155131Srwatson 234155131Srwatson return (getauusernam_r(&u, name)); 235155131Srwatson} 236155131Srwatson 237155131Srwatson/* 238155131Srwatson * Read the default system wide audit classes from audit_control, combine with 239155131Srwatson * the per-user audit class and update the binary preselection mask. 240155131Srwatson */ 241155131Srwatsonint 242155131Srwatsonau_user_mask(char *username, au_mask_t *mask_p) 243155131Srwatson{ 244155131Srwatson char auditstring[MAX_AUDITSTRING_LEN + 1]; 245155131Srwatson char user_ent_name[AU_USER_NAME_MAX]; 246155131Srwatson struct au_user_ent u, *up; 247155131Srwatson 248155131Srwatson bzero(&u, sizeof(u)); 249155131Srwatson bzero(user_ent_name, sizeof(user_ent_name)); 250155131Srwatson u.au_name = user_ent_name; 251155131Srwatson 252155131Srwatson /* Get user mask. */ 253155131Srwatson if ((up = getauusernam_r(&u, username)) != NULL) { 254155131Srwatson if (-1 == getfauditflags(&up->au_always, &up->au_never, 255155131Srwatson mask_p)) 256155131Srwatson return (-1); 257155131Srwatson return (0); 258155131Srwatson } 259155131Srwatson 260155131Srwatson /* Read the default system mask. */ 261155131Srwatson if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 262155131Srwatson if (-1 == getauditflagsbin(auditstring, mask_p)) 263155131Srwatson return (-1); 264155131Srwatson return (0); 265155131Srwatson } 266155131Srwatson 267155131Srwatson /* No masks defined. */ 268155131Srwatson return (-1); 269155131Srwatson} 270155131Srwatson 271155131Srwatson/* 272155131Srwatson * Generate the process audit state by combining the audit masks passed as 273155131Srwatson * parameters with the system audit masks. 274155131Srwatson */ 275155131Srwatsonint 276155131Srwatsongetfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask) 277155131Srwatson{ 278155131Srwatson char auditstring[MAX_AUDITSTRING_LEN + 1]; 279155131Srwatson 280155131Srwatson if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL)) 281155131Srwatson return (-1); 282155131Srwatson 283155131Srwatson lastmask->am_success = 0; 284155131Srwatson lastmask->am_failure = 0; 285155131Srwatson 286155131Srwatson /* Get the system mask. */ 287155131Srwatson if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 288155131Srwatson if (getauditflagsbin(auditstring, lastmask) != 0) 289155131Srwatson return (-1); 290155131Srwatson } 291155131Srwatson 292155131Srwatson ADDMASK(lastmask, usremask); 293155131Srwatson SUBMASK(lastmask, usrdmask); 294155131Srwatson 295155131Srwatson return (0); 296155131Srwatson} 297