1ca0716f5SRobert Watson /* 2ca0716f5SRobert Watson * Copyright (c) 2004 Apple Computer, Inc. 3ca0716f5SRobert Watson * Copyright (c) 2006 Robert N. M. Watson 4ca0716f5SRobert Watson * All rights reserved. 5ca0716f5SRobert Watson * 6ca0716f5SRobert Watson * Redistribution and use in source and binary forms, with or without 7ca0716f5SRobert Watson * modification, are permitted provided that the following conditions 8ca0716f5SRobert Watson * are met: 9ca0716f5SRobert Watson * 1. Redistributions of source code must retain the above copyright 10ca0716f5SRobert Watson * notice, this list of conditions and the following disclaimer. 11ca0716f5SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 12ca0716f5SRobert Watson * notice, this list of conditions and the following disclaimer in the 13ca0716f5SRobert Watson * documentation and/or other materials provided with the distribution. 14ca0716f5SRobert Watson * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15ca0716f5SRobert Watson * its contributors may be used to endorse or promote products derived 16ca0716f5SRobert Watson * from this software without specific prior written permission. 17ca0716f5SRobert Watson * 18ca0716f5SRobert Watson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19ca0716f5SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20ca0716f5SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21ca0716f5SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22ca0716f5SRobert Watson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23ca0716f5SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24ca0716f5SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25ca0716f5SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26ca0716f5SRobert Watson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27ca0716f5SRobert Watson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28ca0716f5SRobert Watson * POSSIBILITY OF SUCH DAMAGE. 29ca0716f5SRobert Watson * 30ca0716f5SRobert Watson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#14 $ 31ca0716f5SRobert Watson */ 32ca0716f5SRobert Watson 33ca0716f5SRobert Watson #include <bsm/libbsm.h> 34ca0716f5SRobert Watson 35ca0716f5SRobert Watson #include <string.h> 36ca0716f5SRobert Watson #include <pthread.h> 37ca0716f5SRobert Watson #include <stdio.h> 38ca0716f5SRobert Watson #include <stdlib.h> 39ca0716f5SRobert Watson 40ca0716f5SRobert Watson /* 41ca0716f5SRobert Watson * Parse the contents of the audit_user file into au_user_ent structures. 42ca0716f5SRobert Watson */ 43ca0716f5SRobert Watson 44ca0716f5SRobert Watson static FILE *fp = NULL; 45ca0716f5SRobert Watson static char linestr[AU_LINE_MAX]; 46ca0716f5SRobert Watson static const char *user_delim = ":"; 47ca0716f5SRobert Watson 48ca0716f5SRobert Watson static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 49ca0716f5SRobert Watson 50ca0716f5SRobert Watson /* 51ca0716f5SRobert Watson * Parse one line from the audit_user file into the au_user_ent structure. 52ca0716f5SRobert Watson */ 53ca0716f5SRobert Watson static struct au_user_ent * 54ca0716f5SRobert Watson userfromstr(char *str, struct au_user_ent *u) 55ca0716f5SRobert Watson { 56ca0716f5SRobert Watson char *username, *always, *never; 57ca0716f5SRobert Watson char *last; 58ca0716f5SRobert Watson 59ca0716f5SRobert Watson username = strtok_r(str, user_delim, &last); 60ca0716f5SRobert Watson always = strtok_r(NULL, user_delim, &last); 61ca0716f5SRobert Watson never = strtok_r(NULL, user_delim, &last); 62ca0716f5SRobert Watson 63ca0716f5SRobert Watson if ((username == NULL) || (always == NULL) || (never == NULL)) 64ca0716f5SRobert Watson return (NULL); 65ca0716f5SRobert Watson 66ca0716f5SRobert Watson if (strlen(username) >= AU_USER_NAME_MAX) 67ca0716f5SRobert Watson return (NULL); 68ca0716f5SRobert Watson 69ca0716f5SRobert Watson strcpy(u->au_name, username); 70ca0716f5SRobert Watson if (getauditflagsbin(always, &(u->au_always)) == -1) 71ca0716f5SRobert Watson return (NULL); 72ca0716f5SRobert Watson 73ca0716f5SRobert Watson if (getauditflagsbin(never, &(u->au_never)) == -1) 74ca0716f5SRobert Watson return (NULL); 75ca0716f5SRobert Watson 76ca0716f5SRobert Watson return (u); 77ca0716f5SRobert Watson } 78ca0716f5SRobert Watson 79ca0716f5SRobert Watson /* 80ca0716f5SRobert Watson * Rewind to beginning of the file 81ca0716f5SRobert Watson */ 82ca0716f5SRobert Watson static void 83ca0716f5SRobert Watson setauuser_locked(void) 84ca0716f5SRobert Watson { 85ca0716f5SRobert Watson 86ca0716f5SRobert Watson if (fp != NULL) 87ca0716f5SRobert Watson fseek(fp, 0, SEEK_SET); 88ca0716f5SRobert Watson } 89ca0716f5SRobert Watson 90ca0716f5SRobert Watson void 91ca0716f5SRobert Watson setauuser(void) 92ca0716f5SRobert Watson { 93ca0716f5SRobert Watson 94ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 95ca0716f5SRobert Watson setauuser_locked(); 96ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 97ca0716f5SRobert Watson } 98ca0716f5SRobert Watson 99ca0716f5SRobert Watson /* 100ca0716f5SRobert Watson * Close the file descriptor 101ca0716f5SRobert Watson */ 102ca0716f5SRobert Watson void 103ca0716f5SRobert Watson endauuser(void) 104ca0716f5SRobert Watson { 105ca0716f5SRobert Watson 106ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 107ca0716f5SRobert Watson if (fp != NULL) { 108ca0716f5SRobert Watson fclose(fp); 109ca0716f5SRobert Watson fp = NULL; 110ca0716f5SRobert Watson } 111ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 112ca0716f5SRobert Watson } 113ca0716f5SRobert Watson 114ca0716f5SRobert Watson /* 115ca0716f5SRobert Watson * Enumerate the au_user_ent structures from the file 116ca0716f5SRobert Watson */ 117ca0716f5SRobert Watson static struct au_user_ent * 118ca0716f5SRobert Watson getauuserent_r_locked(struct au_user_ent *u) 119ca0716f5SRobert Watson { 120ca0716f5SRobert Watson char *nl; 121ca0716f5SRobert Watson 122ca0716f5SRobert Watson if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL)) 123ca0716f5SRobert Watson return (NULL); 124ca0716f5SRobert Watson 125ca0716f5SRobert Watson while (1) { 126ca0716f5SRobert Watson if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 127ca0716f5SRobert Watson return (NULL); 128ca0716f5SRobert Watson 129ca0716f5SRobert Watson /* Remove new lines. */ 130ca0716f5SRobert Watson if ((nl = strrchr(linestr, '\n')) != NULL) 131ca0716f5SRobert Watson *nl = '\0'; 132ca0716f5SRobert Watson 133ca0716f5SRobert Watson /* Skip comments. */ 134ca0716f5SRobert Watson if (linestr[0] == '#') 135ca0716f5SRobert Watson continue; 136ca0716f5SRobert Watson 137ca0716f5SRobert Watson /* Get the next structure. */ 138ca0716f5SRobert Watson if (userfromstr(linestr, u) == NULL) 139ca0716f5SRobert Watson return (NULL); 140ca0716f5SRobert Watson break; 141ca0716f5SRobert Watson } 142ca0716f5SRobert Watson 143ca0716f5SRobert Watson return (u); 144ca0716f5SRobert Watson } 145ca0716f5SRobert Watson 146ca0716f5SRobert Watson struct au_user_ent * 147ca0716f5SRobert Watson getauuserent_r(struct au_user_ent *u) 148ca0716f5SRobert Watson { 149ca0716f5SRobert Watson struct au_user_ent *up; 150ca0716f5SRobert Watson 151ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 152ca0716f5SRobert Watson up = getauuserent_r_locked(u); 153ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 154ca0716f5SRobert Watson return (up); 155ca0716f5SRobert Watson } 156ca0716f5SRobert Watson 157ca0716f5SRobert Watson struct au_user_ent * 158ca0716f5SRobert Watson getauuserent(void) 159ca0716f5SRobert Watson { 160ca0716f5SRobert Watson static char user_ent_name[AU_USER_NAME_MAX]; 161ca0716f5SRobert Watson static struct au_user_ent u; 162ca0716f5SRobert Watson 163ca0716f5SRobert Watson bzero(&u, sizeof(u)); 164ca0716f5SRobert Watson bzero(user_ent_name, sizeof(user_ent_name)); 165ca0716f5SRobert Watson u.au_name = user_ent_name; 166ca0716f5SRobert Watson 167ca0716f5SRobert Watson return (getauuserent_r(&u)); 168ca0716f5SRobert Watson } 169ca0716f5SRobert Watson 170ca0716f5SRobert Watson /* 171ca0716f5SRobert Watson * Find a au_user_ent structure matching the given user name. 172ca0716f5SRobert Watson */ 173ca0716f5SRobert Watson struct au_user_ent * 174ca0716f5SRobert Watson getauusernam_r(struct au_user_ent *u, const char *name) 175ca0716f5SRobert Watson { 176ca0716f5SRobert Watson struct au_user_ent *up; 177ca0716f5SRobert Watson 178ca0716f5SRobert Watson if (name == NULL) 179ca0716f5SRobert Watson return (NULL); 180ca0716f5SRobert Watson 181ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 182ca0716f5SRobert Watson 183ca0716f5SRobert Watson setauuser_locked(); 184ca0716f5SRobert Watson while ((up = getauuserent_r_locked(u)) != NULL) { 185ca0716f5SRobert Watson if (strcmp(name, u->au_name) == 0) { 186ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 187ca0716f5SRobert Watson return (u); 188ca0716f5SRobert Watson } 189ca0716f5SRobert Watson } 190ca0716f5SRobert Watson 191ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 192ca0716f5SRobert Watson return (NULL); 193ca0716f5SRobert Watson 194ca0716f5SRobert Watson } 195ca0716f5SRobert Watson 196ca0716f5SRobert Watson struct au_user_ent * 197ca0716f5SRobert Watson getauusernam(const char *name) 198ca0716f5SRobert Watson { 199ca0716f5SRobert Watson static char user_ent_name[AU_USER_NAME_MAX]; 200ca0716f5SRobert Watson static struct au_user_ent u; 201ca0716f5SRobert Watson 202ca0716f5SRobert Watson bzero(&u, sizeof(u)); 203ca0716f5SRobert Watson bzero(user_ent_name, sizeof(user_ent_name)); 204ca0716f5SRobert Watson u.au_name = user_ent_name; 205ca0716f5SRobert Watson 206ca0716f5SRobert Watson return (getauusernam_r(&u, name)); 207ca0716f5SRobert Watson } 208ca0716f5SRobert Watson 209ca0716f5SRobert Watson /* 210ca0716f5SRobert Watson * Read the default system wide audit classes from audit_control, combine with 211ca0716f5SRobert Watson * the per-user audit class and update the binary preselection mask. 212ca0716f5SRobert Watson */ 213ca0716f5SRobert Watson int 214ca0716f5SRobert Watson au_user_mask(char *username, au_mask_t *mask_p) 215ca0716f5SRobert Watson { 216ca0716f5SRobert Watson char auditstring[MAX_AUDITSTRING_LEN + 1]; 217ca0716f5SRobert Watson char user_ent_name[AU_USER_NAME_MAX]; 218ca0716f5SRobert Watson struct au_user_ent u, *up; 219ca0716f5SRobert Watson 220ca0716f5SRobert Watson bzero(&u, sizeof(u)); 221ca0716f5SRobert Watson bzero(user_ent_name, sizeof(user_ent_name)); 222ca0716f5SRobert Watson u.au_name = user_ent_name; 223ca0716f5SRobert Watson 224ca0716f5SRobert Watson /* Get user mask. */ 225ca0716f5SRobert Watson if ((up = getauusernam_r(&u, username)) != NULL) { 226ca0716f5SRobert Watson if (-1 == getfauditflags(&up->au_always, &up->au_never, 227ca0716f5SRobert Watson mask_p)) 228ca0716f5SRobert Watson return (-1); 229ca0716f5SRobert Watson return (0); 230ca0716f5SRobert Watson } 231ca0716f5SRobert Watson 232ca0716f5SRobert Watson /* Read the default system mask. */ 233ca0716f5SRobert Watson if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 234ca0716f5SRobert Watson if (-1 == getauditflagsbin(auditstring, mask_p)) 235ca0716f5SRobert Watson return (-1); 236ca0716f5SRobert Watson return (0); 237ca0716f5SRobert Watson } 238ca0716f5SRobert Watson 239ca0716f5SRobert Watson /* No masks defined. */ 240ca0716f5SRobert Watson return (-1); 241ca0716f5SRobert Watson } 242ca0716f5SRobert Watson 243ca0716f5SRobert Watson /* 244ca0716f5SRobert Watson * Generate the process audit state by combining the audit masks passed as 245ca0716f5SRobert Watson * parameters with the system audit masks. 246ca0716f5SRobert Watson */ 247ca0716f5SRobert Watson int 248ca0716f5SRobert Watson getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask) 249ca0716f5SRobert Watson { 250ca0716f5SRobert Watson char auditstring[MAX_AUDITSTRING_LEN + 1]; 251ca0716f5SRobert Watson 252ca0716f5SRobert Watson if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL)) 253ca0716f5SRobert Watson return (-1); 254ca0716f5SRobert Watson 255ca0716f5SRobert Watson lastmask->am_success = 0; 256ca0716f5SRobert Watson lastmask->am_failure = 0; 257ca0716f5SRobert Watson 258ca0716f5SRobert Watson /* Get the system mask. */ 259ca0716f5SRobert Watson if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { 260ca0716f5SRobert Watson if (getauditflagsbin(auditstring, lastmask) != 0) 261ca0716f5SRobert Watson return (-1); 262ca0716f5SRobert Watson } 263ca0716f5SRobert Watson 264ca0716f5SRobert Watson ADDMASK(lastmask, usremask); 265ca0716f5SRobert Watson SUBMASK(lastmask, usrdmask); 266ca0716f5SRobert Watson 267ca0716f5SRobert Watson return (0); 268ca0716f5SRobert Watson } 269