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