]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/openbsm/libbsm/bsm_control.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / openbsm / libbsm / bsm_control.c
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_control.c#16 $
31  */
32
33 #include <bsm/libbsm.h>
34
35 #include <errno.h>
36 #include <string.h>
37 #include <pthread.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #include <config/config.h>
42 #ifndef HAVE_STRLCAT
43 #include <compat/strlcat.h>
44 #endif
45
46 /*
47  * Parse the contents of the audit_control file to return the audit control
48  * parameters.  These static fields are protected by 'mutex'.
49  */
50 static FILE     *fp = NULL;
51 static char     linestr[AU_LINE_MAX];
52 static char     *delim = ":";
53
54 static char     inacdir = 0;
55 static char     ptrmoved = 0;
56
57 static pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
58
59 /*
60  * Returns the string value corresponding to the given label from the
61  * configuration file.
62  *
63  * Must be called with mutex held.
64  */
65 static int
66 getstrfromtype_locked(char *name, char **str)
67 {
68         char *type, *nl;
69         char *tokptr;
70         char *last;
71
72         *str = NULL;
73
74         if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
75                 return (-1); /* Error */
76
77         while (1) {
78                 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
79                         if (ferror(fp))
80                                 return (-1);
81                         return (0);     /* EOF */
82                 }
83
84                 if (linestr[0] == '#')
85                         continue;
86
87                 /* Remove trailing new line character. */
88                 if ((nl = strrchr(linestr, '\n')) != NULL)
89                         *nl = '\0';
90
91                 tokptr = linestr;
92                 if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
93                         if (strcmp(name, type) == 0) {
94                                 /* Found matching name. */
95                                 *str = strtok_r(NULL, delim, &last);
96                                 if (*str == NULL) {
97                                         errno = EINVAL;
98                                         return (-1); /* Parse error in file */
99                                 }
100                                 return (0); /* Success */
101                         }
102                 }
103         }
104 }
105
106 /*
107  * Convert a policy to a string.  Return -1 on failure, or >= 0 representing
108  * the actual size of the string placed in the buffer (excluding terminating
109  * nul).
110  */
111 ssize_t
112 au_poltostr(long policy, size_t maxsize, char *buf)
113 {
114         int first;
115
116         if (maxsize < 1)
117                 return (-1);
118         first = 1;
119         buf[0] = '\0';
120
121         if (policy & AUDIT_CNT) {
122                 if (strlcat(buf, "cnt", maxsize) >= maxsize)
123                         return (-1);
124                 first = 0;
125         }
126         if (policy & AUDIT_AHLT) {
127                 if (!first) {
128                         if (strlcat(buf, ",", maxsize) >= maxsize)
129                                 return (-1);
130                 }
131                 if (strlcat(buf, "ahlt", maxsize) >= maxsize)
132                         return (-1);
133                 first = 0;
134         }
135         if (policy & AUDIT_ARGV) {
136                 if (!first) {
137                         if (strlcat(buf, ",", maxsize) >= maxsize)
138                                 return (-1);
139                 }
140                 if (strlcat(buf, "argv", maxsize) >= maxsize)
141                         return (-1);
142                 first = 0;
143         }
144         if (policy & AUDIT_ARGE) {
145                 if (!first) {
146                         if (strlcat(buf, ",", maxsize) >= maxsize)
147                                 return (-1);
148                 }
149                 if (strlcat(buf, "arge", maxsize) >= maxsize)
150                         return (-1);
151                 first = 0;
152         }
153         if (policy & AUDIT_SEQ) {
154                 if (!first) {
155                         if (strlcat(buf, ",", maxsize) >= maxsize)
156                                 return (-1);
157                 }
158                 if (strlcat(buf, "seq", maxsize) >= maxsize)
159                         return (-1);
160                 first = 0;
161         }
162         if (policy & AUDIT_WINDATA) {
163                 if (!first) {
164                         if (strlcat(buf, ",", maxsize) >= maxsize)
165                                 return (-1);
166                 }
167                 if (strlcat(buf, "windata", maxsize) >= maxsize)
168                         return (-1);
169                 first = 0;
170         }
171         if (policy & AUDIT_USER) {
172                 if (!first) {
173                         if (strlcat(buf, ",", maxsize) >= maxsize)
174                                 return (-1);
175                 }
176                 if (strlcat(buf, "user", maxsize) >= maxsize)
177                         return (-1);
178                 first = 0;
179         }
180         if (policy & AUDIT_GROUP) {
181                 if (!first) {
182                         if (strlcat(buf, ",", maxsize) >= maxsize)
183                                 return (-1);
184                 }
185                 if (strlcat(buf, "group", maxsize) >= maxsize)
186                         return (-1);
187                 first = 0;
188         }
189         if (policy & AUDIT_TRAIL) {
190                 if (!first) {
191                         if (strlcat(buf, ",", maxsize) >= maxsize)
192                                 return (-1);
193                 }
194                 if (strlcat(buf, "trail", maxsize) >= maxsize)
195                         return (-1);
196                 first = 0;
197         }
198         if (policy & AUDIT_PATH) {
199                 if (!first) {
200                         if (strlcat(buf, ",", maxsize) >= maxsize)
201                                 return (-1);
202                 }
203                 if (strlcat(buf, "path", maxsize) >= maxsize)
204                         return (-1);
205                 first = 0;
206         }
207         if (policy & AUDIT_SCNT) {
208                 if (!first) {
209                         if (strlcat(buf, ",", maxsize) >= maxsize)
210                                 return (-1);
211                 }
212                 if (strlcat(buf, "scnt", maxsize) >= maxsize)
213                         return (-1);
214                 first = 0;
215         }
216         if (policy & AUDIT_PUBLIC) {
217                 if (!first) {
218                         if (strlcat(buf, ",", maxsize) >= maxsize)
219                                 return (-1);
220                 }
221                 if (strlcat(buf, "public", maxsize) >= maxsize)
222                         return (-1);
223                 first = 0;
224         }
225         if (policy & AUDIT_ZONENAME) {
226                 if (!first) {
227                         if (strlcat(buf, ",", maxsize) >= maxsize)
228                                 return (-1);
229                 }
230                 if (strlcat(buf, "zonename", maxsize) >= maxsize)
231                         return (-1);
232                 first = 0;
233         }
234         if (policy & AUDIT_PERZONE) {
235                 if (!first) {
236                         if (strlcat(buf, ",", maxsize) >= maxsize)
237                                 return (-1);
238                 }
239                 if (strlcat(buf, "perzone", maxsize) >= maxsize)
240                         return (-1);
241                 first = 0;
242         }
243         return (strlen(buf));
244 }
245
246 /*
247  * Convert a string to a policy.  Return -1 on failure (with errno EINVAL,
248  * ENOMEM) or 0 on success.
249  */
250 int
251 au_strtopol(const char *polstr, long *policy)
252 {
253         char *bufp, *string;
254         char *buffer;
255
256         *policy = 0;
257         buffer = strdup(polstr);
258         if (buffer == NULL)
259                 return (-1);
260
261         bufp = buffer;
262         while ((string = strsep(&bufp, ",")) != NULL) {
263                 if (strcmp(string, "cnt") == 0)
264                         *policy |= AUDIT_CNT;
265                 else if (strcmp(string, "ahlt") == 0)
266                         *policy |= AUDIT_AHLT;
267                 else if (strcmp(string, "argv") == 0)
268                         *policy |= AUDIT_ARGV;
269                 else if (strcmp(string, "arge") == 0)
270                         *policy |= AUDIT_ARGE;
271                 else if (strcmp(string, "seq") == 0)
272                         *policy |= AUDIT_SEQ;
273                 else if (strcmp(string, "winau_fstat") == 0)
274                         *policy |= AUDIT_WINDATA;
275                 else if (strcmp(string, "user") == 0)
276                         *policy |= AUDIT_USER;
277                 else if (strcmp(string, "group") == 0)
278                         *policy |= AUDIT_GROUP;
279                 else if (strcmp(string, "trail") == 0)
280                         *policy |= AUDIT_TRAIL;
281                 else if (strcmp(string, "path") == 0)
282                         *policy |= AUDIT_PATH;
283                 else if (strcmp(string, "scnt") == 0)
284                         *policy |= AUDIT_SCNT;
285                 else if (strcmp(string, "public") == 0)
286                         *policy |= AUDIT_PUBLIC;
287                 else if (strcmp(string, "zonename") == 0)
288                         *policy |= AUDIT_ZONENAME;
289                 else if (strcmp(string, "perzone") == 0)
290                         *policy |= AUDIT_PERZONE;
291                 else {
292                         free(buffer);
293                         errno = EINVAL;
294                         return (-1);
295                 }
296         }
297         free(buffer);
298         return (0);
299 }
300
301 /*
302  * Rewind the file pointer to beginning.
303  */
304 static void
305 setac_locked(void)
306 {
307
308         ptrmoved = 1;
309         if (fp != NULL)
310                 fseek(fp, 0, SEEK_SET);
311 }
312
313 void
314 setac(void)
315 {
316
317         pthread_mutex_lock(&mutex);
318         setac_locked();
319         pthread_mutex_unlock(&mutex);
320 }
321
322 /*
323  * Close the audit_control file.
324  */
325 void
326 endac(void)
327 {
328
329         pthread_mutex_lock(&mutex);
330         ptrmoved = 1;
331         if (fp != NULL) {
332                 fclose(fp);
333                 fp = NULL;
334         }
335         pthread_mutex_unlock(&mutex);
336 }
337
338 /*
339  * Return audit directory information from the audit control file.
340  */
341 int
342 getacdir(char *name, int len)
343 {
344         char *dir;
345         int ret = 0;
346
347         /*
348          * Check if another function was called between successive calls to
349          * getacdir.
350          */
351         pthread_mutex_lock(&mutex);
352         if (inacdir && ptrmoved) {
353                 ptrmoved = 0;
354                 if (fp != NULL)
355                         fseek(fp, 0, SEEK_SET);
356                 ret = 2;
357         }
358         if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
359                 pthread_mutex_unlock(&mutex);
360                 return (-2);
361         }
362         if (dir == NULL) {
363                 pthread_mutex_unlock(&mutex);
364                 return (-1);
365         }
366         if (strlen(dir) >= len) {
367                 pthread_mutex_unlock(&mutex);
368                 return (-3);
369         }
370         strcpy(name, dir);
371         pthread_mutex_unlock(&mutex);
372         return (ret);
373 }
374
375 /*
376  * Return the minimum free diskspace value from the audit control file.
377  */
378 int
379 getacmin(int *min_val)
380 {
381         char *min;
382
383         pthread_mutex_lock(&mutex);
384         setac_locked();
385         if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
386                 pthread_mutex_unlock(&mutex);
387                 return (-2);
388         }
389         if (min == NULL) {
390                 pthread_mutex_unlock(&mutex);
391                 return (1);
392         }
393         *min_val = atoi(min);
394         pthread_mutex_unlock(&mutex);
395         return (0);
396 }
397
398 /*
399  * Return the desired trail rotation size from the audit control file.
400  */
401 int
402 getacfilesz(size_t *filesz_val)
403 {
404         char *filesz, *dummy;
405         long long ll;
406
407         pthread_mutex_lock(&mutex);
408         setac_locked();
409         if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &filesz) < 0) {
410                 pthread_mutex_unlock(&mutex);
411                 return (-2);
412         }
413         if (filesz == NULL) {
414                 pthread_mutex_unlock(&mutex);
415                 errno = EINVAL;
416                 return (1);
417         }
418         ll = strtoll(filesz, &dummy, 10);
419         if (*dummy != '\0') {
420                 pthread_mutex_unlock(&mutex);
421                 errno = EINVAL;
422                 return (-1);
423         }
424         /*
425          * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE.  0
426          * indicates no rotation size.
427          */
428         if (ll < 0 || (ll > 0 && ll < MIN_AUDIT_FILE_SIZE)) {
429                 pthread_mutex_unlock(&mutex);
430                 errno = EINVAL;
431                 return (-1);
432         }
433         *filesz_val = ll;
434         pthread_mutex_unlock(&mutex);
435         return (0);
436 }
437
438 /*
439  * Return the system audit value from the audit contol file.
440  */
441 int
442 getacflg(char *auditstr, int len)
443 {
444         char *str;
445
446         pthread_mutex_lock(&mutex);
447         setac_locked();
448         if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) {
449                 pthread_mutex_unlock(&mutex);
450                 return (-2);
451         }
452         if (str == NULL) {
453                 pthread_mutex_unlock(&mutex);
454                 return (1);
455         }
456         if (strlen(str) >= len) {
457                 pthread_mutex_unlock(&mutex);
458                 return (-3);
459         }
460         strcpy(auditstr, str);
461         pthread_mutex_unlock(&mutex);
462         return (0);
463 }
464
465 /*
466  * Return the non attributable flags from the audit contol file.
467  */
468 int
469 getacna(char *auditstr, int len)
470 {
471         char *str;
472
473         pthread_mutex_lock(&mutex);
474         setac_locked();
475         if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) {
476                 pthread_mutex_unlock(&mutex);
477                 return (-2);
478         }
479         if (str == NULL) {
480                 pthread_mutex_unlock(&mutex);
481                 return (1);
482         }
483         if (strlen(str) >= len) {
484                 pthread_mutex_unlock(&mutex);
485                 return (-3);
486         }
487         strcpy(auditstr, str);
488         return (0);
489 }
490
491 /*
492  * Return the policy field from the audit control file.
493  */
494 int
495 getacpol(char *auditstr, size_t len)
496 {
497         char *str;
498
499         pthread_mutex_lock(&mutex);
500         setac_locked();
501         if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) {
502                 pthread_mutex_unlock(&mutex);
503                 return (-2);
504         }
505         if (str == NULL) {
506                 pthread_mutex_unlock(&mutex);
507                 return (-1);
508         }
509         if (strlen(str) >= len) {
510                 pthread_mutex_unlock(&mutex);
511                 return (-3);
512         }
513         strcpy(auditstr, str);
514         pthread_mutex_unlock(&mutex);
515         return (0);
516 }