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