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