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