bsm_user.c revision 155131
1155131Srwatson/*
2155131Srwatson * Copyright (c) 2004 Apple Computer, Inc.
3155131Srwatson * Copyright (c) 2006 Robert N. M. Watson
4155131Srwatson * All rights reserved.
5155131Srwatson *
6155131Srwatson * Redistribution and use in source and binary forms, with or without
7155131Srwatson * modification, are permitted provided that the following conditions
8155131Srwatson * are met:
9155131Srwatson * 1.  Redistributions of source code must retain the above copyright
10155131Srwatson *     notice, this list of conditions and the following disclaimer.
11155131Srwatson * 2.  Redistributions in binary form must reproduce the above copyright
12155131Srwatson *     notice, this list of conditions and the following disclaimer in the
13155131Srwatson *     documentation and/or other materials provided with the distribution.
14155131Srwatson * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15155131Srwatson *     its contributors may be used to endorse or promote products derived
16155131Srwatson *     from this software without specific prior written permission.
17155131Srwatson *
18155131Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
19155131Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21155131Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22155131Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26155131Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27155131Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28155131Srwatson * POSSIBILITY OF SUCH DAMAGE.
29155131Srwatson *
30155131Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#14 $
31155131Srwatson */
32155131Srwatson
33155131Srwatson#include <bsm/libbsm.h>
34155131Srwatson
35155131Srwatson#include <string.h>
36155131Srwatson#include <pthread.h>
37155131Srwatson#include <stdio.h>
38155131Srwatson#include <stdlib.h>
39155131Srwatson
40155131Srwatson/*
41155131Srwatson * Parse the contents of the audit_user file into au_user_ent structures.
42155131Srwatson */
43155131Srwatson
44155131Srwatsonstatic FILE		*fp = NULL;
45155131Srwatsonstatic char		 linestr[AU_LINE_MAX];
46155131Srwatsonstatic const char	*user_delim = ":";
47155131Srwatson
48155131Srwatsonstatic pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
49155131Srwatson
50155131Srwatson/*
51155131Srwatson * Parse one line from the audit_user file into the au_user_ent structure.
52155131Srwatson */
53155131Srwatsonstatic struct au_user_ent *
54155131Srwatsonuserfromstr(char *str, struct au_user_ent *u)
55155131Srwatson{
56155131Srwatson	char *username, *always, *never;
57155131Srwatson	char *last;
58155131Srwatson
59155131Srwatson	username = strtok_r(str, user_delim, &last);
60155131Srwatson	always = strtok_r(NULL, user_delim, &last);
61155131Srwatson	never = strtok_r(NULL, user_delim, &last);
62155131Srwatson
63155131Srwatson	if ((username == NULL) || (always == NULL) || (never == NULL))
64155131Srwatson		return (NULL);
65155131Srwatson
66155131Srwatson	if (strlen(username) >= AU_USER_NAME_MAX)
67155131Srwatson		return (NULL);
68155131Srwatson
69155131Srwatson	strcpy(u->au_name, username);
70155131Srwatson	if (getauditflagsbin(always, &(u->au_always)) == -1)
71155131Srwatson		return (NULL);
72155131Srwatson
73155131Srwatson	if (getauditflagsbin(never, &(u->au_never)) == -1)
74155131Srwatson		return (NULL);
75155131Srwatson
76155131Srwatson	return (u);
77155131Srwatson}
78155131Srwatson
79155131Srwatson/*
80155131Srwatson * Rewind to beginning of the file
81155131Srwatson */
82155131Srwatsonstatic void
83155131Srwatsonsetauuser_locked(void)
84155131Srwatson{
85155131Srwatson
86155131Srwatson	if (fp != NULL)
87155131Srwatson		fseek(fp, 0, SEEK_SET);
88155131Srwatson}
89155131Srwatson
90155131Srwatsonvoid
91155131Srwatsonsetauuser(void)
92155131Srwatson{
93155131Srwatson
94155131Srwatson	pthread_mutex_lock(&mutex);
95155131Srwatson	setauuser_locked();
96155131Srwatson	pthread_mutex_unlock(&mutex);
97155131Srwatson}
98155131Srwatson
99155131Srwatson/*
100155131Srwatson * Close the file descriptor
101155131Srwatson */
102155131Srwatsonvoid
103155131Srwatsonendauuser(void)
104155131Srwatson{
105155131Srwatson
106155131Srwatson	pthread_mutex_lock(&mutex);
107155131Srwatson	if (fp != NULL) {
108155131Srwatson		fclose(fp);
109155131Srwatson		fp = NULL;
110155131Srwatson	}
111155131Srwatson	pthread_mutex_unlock(&mutex);
112155131Srwatson}
113155131Srwatson
114155131Srwatson/*
115155131Srwatson * Enumerate the au_user_ent structures from the file
116155131Srwatson */
117155131Srwatsonstatic struct au_user_ent *
118155131Srwatsongetauuserent_r_locked(struct au_user_ent *u)
119155131Srwatson{
120155131Srwatson	char *nl;
121155131Srwatson
122155131Srwatson	if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL))
123155131Srwatson		return (NULL);
124155131Srwatson
125155131Srwatson	while (1) {
126155131Srwatson		if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
127155131Srwatson			return (NULL);
128155131Srwatson
129155131Srwatson		/* Remove new lines. */
130155131Srwatson		if ((nl = strrchr(linestr, '\n')) != NULL)
131155131Srwatson			*nl = '\0';
132155131Srwatson
133155131Srwatson		/* Skip comments. */
134155131Srwatson		if (linestr[0] == '#')
135155131Srwatson			continue;
136155131Srwatson
137155131Srwatson		/* Get the next structure. */
138155131Srwatson		if (userfromstr(linestr, u) == NULL)
139155131Srwatson			return (NULL);
140155131Srwatson		break;
141155131Srwatson	}
142155131Srwatson
143155131Srwatson	return (u);
144155131Srwatson}
145155131Srwatson
146155131Srwatsonstruct au_user_ent *
147155131Srwatsongetauuserent_r(struct au_user_ent *u)
148155131Srwatson{
149155131Srwatson	struct au_user_ent *up;
150155131Srwatson
151155131Srwatson	pthread_mutex_lock(&mutex);
152155131Srwatson	up = getauuserent_r_locked(u);
153155131Srwatson	pthread_mutex_unlock(&mutex);
154155131Srwatson	return (up);
155155131Srwatson}
156155131Srwatson
157155131Srwatsonstruct au_user_ent *
158155131Srwatsongetauuserent(void)
159155131Srwatson{
160155131Srwatson	static char user_ent_name[AU_USER_NAME_MAX];
161155131Srwatson	static struct au_user_ent u;
162155131Srwatson
163155131Srwatson	bzero(&u, sizeof(u));
164155131Srwatson	bzero(user_ent_name, sizeof(user_ent_name));
165155131Srwatson	u.au_name = user_ent_name;
166155131Srwatson
167155131Srwatson	return (getauuserent_r(&u));
168155131Srwatson}
169155131Srwatson
170155131Srwatson/*
171155131Srwatson * Find a au_user_ent structure matching the given user name.
172155131Srwatson */
173155131Srwatsonstruct au_user_ent *
174155131Srwatsongetauusernam_r(struct au_user_ent *u, const char *name)
175155131Srwatson{
176155131Srwatson	struct au_user_ent *up;
177155131Srwatson
178155131Srwatson	if (name == NULL)
179155131Srwatson		return (NULL);
180155131Srwatson
181155131Srwatson	pthread_mutex_lock(&mutex);
182155131Srwatson
183155131Srwatson	setauuser_locked();
184155131Srwatson	while ((up = getauuserent_r_locked(u)) != NULL) {
185155131Srwatson		if (strcmp(name, u->au_name) == 0) {
186155131Srwatson			pthread_mutex_unlock(&mutex);
187155131Srwatson			return (u);
188155131Srwatson		}
189155131Srwatson	}
190155131Srwatson
191155131Srwatson	pthread_mutex_unlock(&mutex);
192155131Srwatson	return (NULL);
193155131Srwatson
194155131Srwatson}
195155131Srwatson
196155131Srwatsonstruct au_user_ent *
197155131Srwatsongetauusernam(const char *name)
198155131Srwatson{
199155131Srwatson	static char user_ent_name[AU_USER_NAME_MAX];
200155131Srwatson	static struct au_user_ent u;
201155131Srwatson
202155131Srwatson	bzero(&u, sizeof(u));
203155131Srwatson	bzero(user_ent_name, sizeof(user_ent_name));
204155131Srwatson	u.au_name = user_ent_name;
205155131Srwatson
206155131Srwatson	return (getauusernam_r(&u, name));
207155131Srwatson}
208155131Srwatson
209155131Srwatson/*
210155131Srwatson * Read the default system wide audit classes from audit_control, combine with
211155131Srwatson * the per-user audit class and update the binary preselection mask.
212155131Srwatson */
213155131Srwatsonint
214155131Srwatsonau_user_mask(char *username, au_mask_t *mask_p)
215155131Srwatson{
216155131Srwatson	char auditstring[MAX_AUDITSTRING_LEN + 1];
217155131Srwatson	char user_ent_name[AU_USER_NAME_MAX];
218155131Srwatson	struct au_user_ent u, *up;
219155131Srwatson
220155131Srwatson	bzero(&u, sizeof(u));
221155131Srwatson	bzero(user_ent_name, sizeof(user_ent_name));
222155131Srwatson	u.au_name = user_ent_name;
223155131Srwatson
224155131Srwatson	/* Get user mask. */
225155131Srwatson	if ((up = getauusernam_r(&u, username)) != NULL) {
226155131Srwatson		if (-1 == getfauditflags(&up->au_always, &up->au_never,
227155131Srwatson		    mask_p))
228155131Srwatson			return (-1);
229155131Srwatson		return (0);
230155131Srwatson	}
231155131Srwatson
232155131Srwatson	/* Read the default system mask. */
233155131Srwatson	if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
234155131Srwatson		if (-1 == getauditflagsbin(auditstring, mask_p))
235155131Srwatson			return (-1);
236155131Srwatson		return (0);
237155131Srwatson	}
238155131Srwatson
239155131Srwatson	/* No masks defined. */
240155131Srwatson	return (-1);
241155131Srwatson}
242155131Srwatson
243155131Srwatson/*
244155131Srwatson * Generate the process audit state by combining the audit masks passed as
245155131Srwatson * parameters with the system audit masks.
246155131Srwatson */
247155131Srwatsonint
248155131Srwatsongetfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask)
249155131Srwatson{
250155131Srwatson	char auditstring[MAX_AUDITSTRING_LEN + 1];
251155131Srwatson
252155131Srwatson	if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL))
253155131Srwatson		return (-1);
254155131Srwatson
255155131Srwatson	lastmask->am_success = 0;
256155131Srwatson	lastmask->am_failure = 0;
257155131Srwatson
258155131Srwatson	/* Get the system mask. */
259155131Srwatson	if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
260155131Srwatson		if (getauditflagsbin(auditstring, lastmask) != 0)
261155131Srwatson			return (-1);
262155131Srwatson	}
263155131Srwatson
264155131Srwatson	ADDMASK(lastmask, usremask);
265155131Srwatson	SUBMASK(lastmask, usrdmask);
266155131Srwatson
267155131Srwatson	return (0);
268155131Srwatson}
269