Deleted Added
full compact
bsm_user.c (155131) bsm_user.c (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 *
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#14 $
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}
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}