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.
31 #include <config/config.h>
33 #include <bsm/libbsm.h>
36 #ifdef HAVE_PTHREAD_MUTEX_LOCK
43 #include <compat/strlcpy.h>
47 * Parse the contents of the audit_user file into au_user_ent structures.
50 static FILE *fp = NULL;
51 static char linestr[AU_LINE_MAX];
52 static const char *user_delim = ":";
54 #ifdef HAVE_PTHREAD_MUTEX_LOCK
55 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
59 * Parse one line from the audit_user file into the au_user_ent structure.
61 static struct au_user_ent *
62 userfromstr(char *str, struct au_user_ent *u)
64 char *username, *always, *never;
67 username = strtok_r(str, user_delim, &last);
68 always = strtok_r(NULL, user_delim, &last);
69 never = strtok_r(NULL, user_delim, &last);
71 if ((username == NULL) || (always == NULL) || (never == NULL))
74 if (strlen(username) >= AU_USER_NAME_MAX)
77 strlcpy(u->au_name, username, AU_USER_NAME_MAX);
78 if (getauditflagsbin(always, &(u->au_always)) == -1)
81 if (getauditflagsbin(never, &(u->au_never)) == -1)
88 * Rewind to beginning of the file
91 setauuser_locked(void)
95 fseek(fp, 0, SEEK_SET);
102 #ifdef HAVE_PTHREAD_MUTEX_LOCK
103 pthread_mutex_lock(&mutex);
106 #ifdef HAVE_PTHREAD_MUTEX_LOCK
107 pthread_mutex_unlock(&mutex);
112 * Close the file descriptor
118 #ifdef HAVE_PTHREAD_MUTEX_LOCK
119 pthread_mutex_lock(&mutex);
125 #ifdef HAVE_PTHREAD_MUTEX_LOCK
126 pthread_mutex_unlock(&mutex);
131 * Enumerate the au_user_ent structures from the file
133 static struct au_user_ent *
134 getauuserent_r_locked(struct au_user_ent *u)
138 if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL))
142 if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
145 /* Remove new lines. */
146 if ((nl = strrchr(linestr, '\n')) != NULL)
150 if (linestr[0] == '#')
153 /* Get the next structure. */
154 if (userfromstr(linestr, u) == NULL)
163 getauuserent_r(struct au_user_ent *u)
165 struct au_user_ent *up;
167 #ifdef HAVE_PTHREAD_MUTEX_LOCK
168 pthread_mutex_lock(&mutex);
170 up = getauuserent_r_locked(u);
171 #ifdef HAVE_PTHREAD_MUTEX_LOCK
172 pthread_mutex_unlock(&mutex);
180 static char user_ent_name[AU_USER_NAME_MAX];
181 static struct au_user_ent u;
183 bzero(&u, sizeof(u));
184 bzero(user_ent_name, sizeof(user_ent_name));
185 u.au_name = user_ent_name;
187 return (getauuserent_r(&u));
191 * Find a au_user_ent structure matching the given user name.
194 getauusernam_r(struct au_user_ent *u, const char *name)
196 struct au_user_ent *up;
201 #ifdef HAVE_PTHREAD_MUTEX_LOCK
202 pthread_mutex_lock(&mutex);
206 while ((up = getauuserent_r_locked(u)) != NULL) {
207 if (strcmp(name, u->au_name) == 0) {
208 #ifdef HAVE_PTHREAD_MUTEX_LOCK
209 pthread_mutex_unlock(&mutex);
215 #ifdef HAVE_PTHREAD_MUTEX_LOCK
216 pthread_mutex_unlock(&mutex);
223 getauusernam(const char *name)
225 static char user_ent_name[AU_USER_NAME_MAX];
226 static struct au_user_ent u;
228 bzero(&u, sizeof(u));
229 bzero(user_ent_name, sizeof(user_ent_name));
230 u.au_name = user_ent_name;
232 return (getauusernam_r(&u, name));
236 * Read the default system wide audit classes from audit_control, combine with
237 * the per-user audit class and update the binary preselection mask.
240 au_user_mask(char *username, au_mask_t *mask_p)
242 char auditstring[MAX_AUDITSTRING_LEN + 1];
243 char user_ent_name[AU_USER_NAME_MAX];
244 struct au_user_ent u, *up;
246 bzero(&u, sizeof(u));
247 bzero(user_ent_name, sizeof(user_ent_name));
248 u.au_name = user_ent_name;
251 if ((up = getauusernam_r(&u, username)) != NULL) {
252 if (-1 == getfauditflags(&up->au_always, &up->au_never,
258 /* Read the default system mask. */
259 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
260 if (-1 == getauditflagsbin(auditstring, mask_p))
265 /* No masks defined. */
270 * Generate the process audit state by combining the audit masks passed as
271 * parameters with the system audit masks.
274 getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask)
276 char auditstring[MAX_AUDITSTRING_LEN + 1];
278 if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL))
281 lastmask->am_success = 0;
282 lastmask->am_failure = 0;
284 /* Get the system mask. */
285 if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
286 if (getauditflagsbin(auditstring, lastmask) != 0)
290 ADDMASK(lastmask, usremask);
291 SUBMASK(lastmask, usrdmask);