bsm_user.c revision 185573
1185573Srwatson/*-
2185573Srwatson * Copyright (c) 2004 Apple 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.
14185573Srwatson * 3.  Neither the name of Apple 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 *
30185573Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#18 $
31155131Srwatson */
32155131Srwatson
33185573Srwatson#include <config/config.h>
34185573Srwatson
35155131Srwatson#include <bsm/libbsm.h>
36155131Srwatson
37155131Srwatson#include <string.h>
38155131Srwatson#include <pthread.h>
39155131Srwatson#include <stdio.h>
40155131Srwatson#include <stdlib.h>
41155131Srwatson
42185573Srwatson#ifndef HAVE_STRLCPY
43185573Srwatson#include <compat/strlcpy.h>
44185573Srwatson#endif
45185573Srwatson
46155131Srwatson/*
47155131Srwatson * Parse the contents of the audit_user file into au_user_ent structures.
48155131Srwatson */
49155131Srwatson
50155131Srwatsonstatic FILE		*fp = NULL;
51155131Srwatsonstatic char		 linestr[AU_LINE_MAX];
52155131Srwatsonstatic const char	*user_delim = ":";
53155131Srwatson
54155131Srwatsonstatic pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
55155131Srwatson
56155131Srwatson/*
57155131Srwatson * Parse one line from the audit_user file into the au_user_ent structure.
58155131Srwatson */
59155131Srwatsonstatic struct au_user_ent *
60155131Srwatsonuserfromstr(char *str, struct au_user_ent *u)
61155131Srwatson{
62155131Srwatson	char *username, *always, *never;
63155131Srwatson	char *last;
64155131Srwatson
65155131Srwatson	username = strtok_r(str, user_delim, &last);
66155131Srwatson	always = strtok_r(NULL, user_delim, &last);
67155131Srwatson	never = strtok_r(NULL, user_delim, &last);
68155131Srwatson
69155131Srwatson	if ((username == NULL) || (always == NULL) || (never == NULL))
70155131Srwatson		return (NULL);
71155131Srwatson
72155131Srwatson	if (strlen(username) >= AU_USER_NAME_MAX)
73155131Srwatson		return (NULL);
74155131Srwatson
75185573Srwatson	strlcpy(u->au_name, username, AU_USER_NAME_MAX);
76155131Srwatson	if (getauditflagsbin(always, &(u->au_always)) == -1)
77155131Srwatson		return (NULL);
78155131Srwatson
79155131Srwatson	if (getauditflagsbin(never, &(u->au_never)) == -1)
80155131Srwatson		return (NULL);
81155131Srwatson
82155131Srwatson	return (u);
83155131Srwatson}
84155131Srwatson
85155131Srwatson/*
86155131Srwatson * Rewind to beginning of the file
87155131Srwatson */
88155131Srwatsonstatic void
89155131Srwatsonsetauuser_locked(void)
90155131Srwatson{
91155131Srwatson
92155131Srwatson	if (fp != NULL)
93155131Srwatson		fseek(fp, 0, SEEK_SET);
94155131Srwatson}
95155131Srwatson
96155131Srwatsonvoid
97155131Srwatsonsetauuser(void)
98155131Srwatson{
99155131Srwatson
100155131Srwatson	pthread_mutex_lock(&mutex);
101155131Srwatson	setauuser_locked();
102155131Srwatson	pthread_mutex_unlock(&mutex);
103155131Srwatson}
104155131Srwatson
105155131Srwatson/*
106155131Srwatson * Close the file descriptor
107155131Srwatson */
108155131Srwatsonvoid
109155131Srwatsonendauuser(void)
110155131Srwatson{
111155131Srwatson
112155131Srwatson	pthread_mutex_lock(&mutex);
113155131Srwatson	if (fp != NULL) {
114155131Srwatson		fclose(fp);
115155131Srwatson		fp = NULL;
116155131Srwatson	}
117155131Srwatson	pthread_mutex_unlock(&mutex);
118155131Srwatson}
119155131Srwatson
120155131Srwatson/*
121155131Srwatson * Enumerate the au_user_ent structures from the file
122155131Srwatson */
123155131Srwatsonstatic struct au_user_ent *
124155131Srwatsongetauuserent_r_locked(struct au_user_ent *u)
125155131Srwatson{
126155131Srwatson	char *nl;
127155131Srwatson
128155131Srwatson	if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL))
129155131Srwatson		return (NULL);
130155131Srwatson
131155131Srwatson	while (1) {
132155131Srwatson		if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
133155131Srwatson			return (NULL);
134155131Srwatson
135155131Srwatson		/* Remove new lines. */
136155131Srwatson		if ((nl = strrchr(linestr, '\n')) != NULL)
137155131Srwatson			*nl = '\0';
138155131Srwatson
139155131Srwatson		/* Skip comments. */
140155131Srwatson		if (linestr[0] == '#')
141155131Srwatson			continue;
142155131Srwatson
143155131Srwatson		/* Get the next structure. */
144155131Srwatson		if (userfromstr(linestr, u) == NULL)
145155131Srwatson			return (NULL);
146155131Srwatson		break;
147155131Srwatson	}
148155131Srwatson
149155131Srwatson	return (u);
150155131Srwatson}
151155131Srwatson
152155131Srwatsonstruct au_user_ent *
153155131Srwatsongetauuserent_r(struct au_user_ent *u)
154155131Srwatson{
155155131Srwatson	struct au_user_ent *up;
156155131Srwatson
157155131Srwatson	pthread_mutex_lock(&mutex);
158155131Srwatson	up = getauuserent_r_locked(u);
159155131Srwatson	pthread_mutex_unlock(&mutex);
160155131Srwatson	return (up);
161155131Srwatson}
162155131Srwatson
163155131Srwatsonstruct au_user_ent *
164155131Srwatsongetauuserent(void)
165155131Srwatson{
166155131Srwatson	static char user_ent_name[AU_USER_NAME_MAX];
167155131Srwatson	static struct au_user_ent u;
168155131Srwatson
169155131Srwatson	bzero(&u, sizeof(u));
170155131Srwatson	bzero(user_ent_name, sizeof(user_ent_name));
171155131Srwatson	u.au_name = user_ent_name;
172155131Srwatson
173155131Srwatson	return (getauuserent_r(&u));
174155131Srwatson}
175155131Srwatson
176155131Srwatson/*
177155131Srwatson * Find a au_user_ent structure matching the given user name.
178155131Srwatson */
179155131Srwatsonstruct au_user_ent *
180155131Srwatsongetauusernam_r(struct au_user_ent *u, const char *name)
181155131Srwatson{
182155131Srwatson	struct au_user_ent *up;
183155131Srwatson
184155131Srwatson	if (name == NULL)
185155131Srwatson		return (NULL);
186155131Srwatson
187155131Srwatson	pthread_mutex_lock(&mutex);
188155131Srwatson
189155131Srwatson	setauuser_locked();
190155131Srwatson	while ((up = getauuserent_r_locked(u)) != NULL) {
191155131Srwatson		if (strcmp(name, u->au_name) == 0) {
192155131Srwatson			pthread_mutex_unlock(&mutex);
193155131Srwatson			return (u);
194155131Srwatson		}
195155131Srwatson	}
196155131Srwatson
197155131Srwatson	pthread_mutex_unlock(&mutex);
198155131Srwatson	return (NULL);
199155131Srwatson
200155131Srwatson}
201155131Srwatson
202155131Srwatsonstruct au_user_ent *
203155131Srwatsongetauusernam(const char *name)
204155131Srwatson{
205155131Srwatson	static char user_ent_name[AU_USER_NAME_MAX];
206155131Srwatson	static struct au_user_ent u;
207155131Srwatson
208155131Srwatson	bzero(&u, sizeof(u));
209155131Srwatson	bzero(user_ent_name, sizeof(user_ent_name));
210155131Srwatson	u.au_name = user_ent_name;
211155131Srwatson
212155131Srwatson	return (getauusernam_r(&u, name));
213155131Srwatson}
214155131Srwatson
215155131Srwatson/*
216155131Srwatson * Read the default system wide audit classes from audit_control, combine with
217155131Srwatson * the per-user audit class and update the binary preselection mask.
218155131Srwatson */
219155131Srwatsonint
220155131Srwatsonau_user_mask(char *username, au_mask_t *mask_p)
221155131Srwatson{
222155131Srwatson	char auditstring[MAX_AUDITSTRING_LEN + 1];
223155131Srwatson	char user_ent_name[AU_USER_NAME_MAX];
224155131Srwatson	struct au_user_ent u, *up;
225155131Srwatson
226155131Srwatson	bzero(&u, sizeof(u));
227155131Srwatson	bzero(user_ent_name, sizeof(user_ent_name));
228155131Srwatson	u.au_name = user_ent_name;
229155131Srwatson
230155131Srwatson	/* Get user mask. */
231155131Srwatson	if ((up = getauusernam_r(&u, username)) != NULL) {
232155131Srwatson		if (-1 == getfauditflags(&up->au_always, &up->au_never,
233155131Srwatson		    mask_p))
234155131Srwatson			return (-1);
235155131Srwatson		return (0);
236155131Srwatson	}
237155131Srwatson
238155131Srwatson	/* Read the default system mask. */
239155131Srwatson	if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
240155131Srwatson		if (-1 == getauditflagsbin(auditstring, mask_p))
241155131Srwatson			return (-1);
242155131Srwatson		return (0);
243155131Srwatson	}
244155131Srwatson
245155131Srwatson	/* No masks defined. */
246155131Srwatson	return (-1);
247155131Srwatson}
248155131Srwatson
249155131Srwatson/*
250155131Srwatson * Generate the process audit state by combining the audit masks passed as
251155131Srwatson * parameters with the system audit masks.
252155131Srwatson */
253155131Srwatsonint
254155131Srwatsongetfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask)
255155131Srwatson{
256155131Srwatson	char auditstring[MAX_AUDITSTRING_LEN + 1];
257155131Srwatson
258155131Srwatson	if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL))
259155131Srwatson		return (-1);
260155131Srwatson
261155131Srwatson	lastmask->am_success = 0;
262155131Srwatson	lastmask->am_failure = 0;
263155131Srwatson
264155131Srwatson	/* Get the system mask. */
265155131Srwatson	if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
266155131Srwatson		if (getauditflagsbin(auditstring, lastmask) != 0)
267155131Srwatson			return (-1);
268155131Srwatson	}
269155131Srwatson
270155131Srwatson	ADDMASK(lastmask, usremask);
271155131Srwatson	SUBMASK(lastmask, usrdmask);
272155131Srwatson
273155131Srwatson	return (0);
274155131Srwatson}
275