2 * Copyright (c) 2004 Apple Inc.
3 * Copyright (c) 2006 Robert N. M. Watson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#20 $
33 #include <config/config.h>
35 #include <bsm/libbsm.h>
38 #ifdef HAVE_PTHREAD_MUTEX_LOCK
45 #include <compat/strlcpy.h>
49 * Parse the contents of the audit_user file into au_user_ent structures.
52 static FILE *fp = NULL;
53 static char linestr[AU_LINE_MAX];
54 static const char *user_delim = ":";
56 #ifdef HAVE_PTHREAD_MUTEX_LOCK
57 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
61 * Parse one line from the audit_user file into the au_user_ent structure.
63 static struct au_user_ent *
64 userfromstr(char *str, struct au_user_ent *u)
66 char *username, *always, *never;
69 username = strtok_r(str, user_delim, &last);
70 always = strtok_r(NULL, user_delim, &last);
71 never = strtok_r(NULL, user_delim, &last);
73 if ((username == NULL) || (always == NULL) || (never == NULL))
76 if (strlen(username) >= AU_USER_NAME_MAX)
79 strlcpy(u->au_name, username, AU_USER_NAME_MAX);
80 if (getauditflagsbin(always, &(u->au_always)) == -1)
83 if (getauditflagsbin(never, &(u->au_never)) == -1)
90 * Rewind to beginning of the file
93 setauuser_locked(void)
97 fseek(fp, 0, SEEK_SET);
104 #ifdef HAVE_PTHREAD_MUTEX_LOCK
105 pthread_mutex_lock(&mutex);
108 #ifdef HAVE_PTHREAD_MUTEX_LOCK
109 pthread_mutex_unlock(&mutex);
114 * Close the file descriptor
120 #ifdef HAVE_PTHREAD_MUTEX_LOCK
121 pthread_mutex_lock(&mutex);
127 #ifdef HAVE_PTHREAD_MUTEX_LOCK
128 pthread_mutex_unlock(&mutex);
133 * Enumerate the au_user_ent structures from the file
135 static struct au_user_ent *
136 getauuserent_r_locked(struct au_user_ent *u)
140 if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL))
144 if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
147 /* Remove new lines. */
148 if ((nl = strrchr(linestr, '\n')) != NULL)
152 if (linestr[0] == '#')
155 /* Get the next structure. */
156 if (userfromstr(linestr, u) == NULL)
165 getauuserent_r(struct au_user_ent *u)
167 struct au_user_ent *up;
169 #ifdef HAVE_PTHREAD_MUTEX_LOCK
170 pthread_mutex_lock(&mutex);
172 up = getauuserent_r_locked(u);
173 #ifdef HAVE_PTHREAD_MUTEX_LOCK
174 pthread_mutex_unlock(&mutex);
182 static char user_ent_name[AU_USER_NAME_MAX];
183 static struct au_user_ent u;
185 bzero(&u, sizeof(u));
186 bzero(user_ent_name, sizeof(user_ent_name));
187 u.au_name = user_ent_name;
189 return (getauuserent_r(&u));
193 * Find a au_user_ent structure matching the given user name.
196 getauusernam_r(struct au_user_ent *u, const char *name)
198 struct au_user_ent *up;
203 #ifdef HAVE_PTHREAD_MUTEX_LOCK
204 pthread_mutex_lock(&mutex);
208 while ((up = getauuserent_r_locked(u)) != NULL) {
209 if (strcmp(name, u->au_name) == 0) {
210 #ifdef HAVE_PTHREAD_MUTEX_LOCK
211 pthread_mutex_unlock(&mutex);
217 #ifdef HAVE_PTHREAD_MUTEX_LOCK
218 pthread_mutex_unlock(&mutex);
225 getauusernam(const char *name)
227 static char user_ent_name[AU_USER_NAME_MAX];
228 static struct au_user_ent u;
230 bzero(&u, sizeof(u));
231 bzero(user_ent_name, sizeof(user_ent_name));
232 u.au_name = user_ent_name;
234 return (getauusernam_r(&u, name));
238 * Read the default system wide audit classes from audit_control, combine with
239 * the per-user audit class and update the binary preselection mask.
242 au_user_mask(char *username, au_mask_t *mask_p)
244 char auditstring[MAX_AUDITSTRING_LEN + 1];
245 char user_ent_name[AU_USER_NAME_MAX];
246 struct au_user_ent u, *up;
248 bzero(&u, sizeof(u));
249 bzero(user_ent_name, sizeof(user_ent_name));
250 u.au_name = user_ent_name;
253 if ((up = getauusernam_r(&u, username)) != NULL) {
254 if (-1 == getfauditflags(&up->au_always, &up->au_never,
260 /* Read the default system mask. */
261 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
262 if (-1 == getauditflagsbin(auditstring, mask_p))
267 /* No masks defined. */
272 * Generate the process audit state by combining the audit masks passed as
273 * parameters with the system audit masks.
276 getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask)
278 char auditstring[MAX_AUDITSTRING_LEN + 1];
280 if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL))
283 lastmask->am_success = 0;
284 lastmask->am_failure = 0;
286 /* Get the system mask. */
287 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
288 if (getauditflagsbin(auditstring, lastmask) != 0)
292 ADDMASK(lastmask, usremask);
293 SUBMASK(lastmask, usrdmask);