]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/openbsm/libauditd/auditd_lib.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / contrib / openbsm / libauditd / auditd_lib.c
1 /*-
2  * Copyright (c) 2008-2009 Apple Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <sys/param.h>
31
32 #include <config/config.h>
33
34 #include <sys/dirent.h>
35 #ifdef HAVE_FULL_QUEUE_H
36 #include <sys/queue.h>
37 #else /* !HAVE_FULL_QUEUE_H */
38 #include <compat/queue.h>
39 #endif /* !HAVE_FULL_QUEUE_H */
40 #include <sys/mount.h>
41 #include <sys/socket.h>
42
43 #include <sys/stat.h>
44 #include <sys/time.h>
45
46 #include <netinet/in.h>
47
48 #include <bsm/audit.h>
49 #include <bsm/audit_uevents.h>
50 #include <bsm/auditd_lib.h>
51 #include <bsm/libbsm.h>
52
53 #include <assert.h>
54 #include <dirent.h>
55 #include <err.h>
56 #include <errno.h>
57 #include <fcntl.h>
58 #include <stdio.h>
59 #include <string.h>
60 #include <stdlib.h>
61 #include <time.h>
62 #include <unistd.h>
63 #include <netdb.h>
64
65 #ifdef __APPLE__
66 #include <notify.h>
67 #ifndef __BSM_INTERNAL_NOTIFY_KEY
68 #define __BSM_INTERNAL_NOTIFY_KEY       "com.apple.audit.change"
69 #endif /* __BSM_INTERNAL_NOTIFY_KEY */
70 #endif /* __APPLE__ */
71
72 /*
73  * XXX This is temporary until this is moved to <bsm/audit.h> and shared with
74  * the kernel.
75  */
76 #ifndef AUDIT_HARD_LIMIT_FREE_BLOCKS
77 #define AUDIT_HARD_LIMIT_FREE_BLOCKS    4
78 #endif
79
80 /*
81  * Number of seconds to January 1, 2000
82  */
83 #define JAN_01_2000     946598400
84
85 struct dir_ent {
86         char                    *dirname;
87         uint8_t                  softlim;
88         uint8_t                  hardlim;
89         TAILQ_ENTRY(dir_ent)     dirs;
90 };
91
92 static TAILQ_HEAD(, dir_ent)    dir_q;
93
94 struct audit_trail {
95         time_t                   at_time;
96         char                    *at_path;
97         off_t                    at_size;
98
99         TAILQ_ENTRY(audit_trail) at_trls;
100 };
101
102 static int auditd_minval = -1;
103 static int auditd_dist = 0;
104
105 static char auditd_host[MAXHOSTNAMELEN];
106 static int auditd_hostlen = -1;
107
108 static char *auditd_errmsg[] = {
109         "no error",                                     /* ADE_NOERR    ( 0) */
110         "could not parse audit_control(5) file",        /* ADE_PARSE    ( 1) */
111         "auditon(2) failed",                            /* ADE_AUDITON  ( 2) */
112         "malloc(3) failed",                             /* ADE_NOMEM    ( 3) */
113         "all audit log directories over soft limit",    /* ADE_SOFTLIM  ( 4) */
114         "all audit log directories over hard limit",    /* ADE_HARDLIM  ( 5) */
115         "could not create file name string",            /* ADE_STRERR   ( 6) */
116         "could not open audit record",                  /* ADE_AU_OPEN  ( 7) */
117         "could not close audit record",                 /* ADE_AU_CLOSE ( 8) */
118         "could not set active audit session state",     /* ADE_SETAUDIT ( 9) */
119         "auditctl(2) failed (trail still swapped)",     /* ADE_ACTL     (10) */
120         "auditctl(2) failed (trail not swapped)",       /* ADE_ACTLERR  (11) */
121         "could not swap audit trail file",              /* ADE_SWAPERR  (12) */
122         "could not rename crash recovery file",         /* ADE_RENAME   (13) */
123         "could not read 'current' link file",           /* ADE_READLINK (14) */
124         "could not create 'current' link file",         /* ADE_SYMLINK  (15) */
125         "invalid argument",                             /* ADE_INVAL    (16) */
126         "could not resolve hostname to address",        /* ADE_GETADDR  (17) */
127         "address family not supported",                 /* ADE_ADDRFAM  (18) */
128         "error expiring audit trail files",             /* ADE_EXPIRE   (19) */
129 };
130
131 #define MAXERRCODE      (sizeof(auditd_errmsg) / sizeof(auditd_errmsg[0]))
132
133 #define NA_EVENT_STR_SIZE       128
134 #define POL_STR_SIZE            128
135
136
137 /*
138  * Look up and return the error string for the given audit error code.
139  */
140 const char *
141 auditd_strerror(int errcode)
142 {
143         int idx = -errcode;
144
145         if (idx < 0 || idx > (int)MAXERRCODE)
146                 return ("Invalid auditd error code");
147
148         return (auditd_errmsg[idx]);
149 }
150
151
152 /*
153  * Free our local list of directory names and init list.
154  */
155 static void
156 free_dir_q(void)
157 {
158         struct dir_ent *d1, *d2;
159
160         d1 = TAILQ_FIRST(&dir_q);
161         while (d1 != NULL) {
162                 d2 = TAILQ_NEXT(d1, dirs);
163                 free(d1->dirname);
164                 free(d1);
165                 d1 = d2;
166         }
167         TAILQ_INIT(&dir_q);
168 }
169
170 /*
171  * Concat the directory name to the given file name.
172  * XXX We should affix the hostname also
173  */
174 static char *
175 affixdir(char *name, struct dir_ent *dirent)
176 {
177         char *fn = NULL;
178
179         /*
180          * Sanity check on file name.
181          */
182         if (strlen(name) != FILENAME_LEN) {
183                 errno = EINVAL;
184                 return (NULL);
185         }
186
187         /*
188          * If the host is set then also add the hostname to the filename.
189          */
190         if (auditd_hostlen != -1)
191                 asprintf(&fn, "%s/%s.%s", dirent->dirname, name, auditd_host);
192         else
193                 asprintf(&fn, "%s/%s", dirent->dirname, name);
194         return (fn);
195 }
196
197 /*
198  * Insert the directory entry in the list by the way they are ordered in
199  * audit_control(5).  Move the entries that are over the soft and hard limits
200  * toward the tail.
201  */
202 static void
203 insert_orderly(struct dir_ent *denew)
204 {
205         struct dir_ent *dep;
206
207         TAILQ_FOREACH(dep, &dir_q, dirs) {
208                 if (dep->softlim == 1 && denew->softlim == 0) {
209                         TAILQ_INSERT_BEFORE(dep, denew, dirs);
210                         return;
211                 }
212                 if (dep->hardlim == 1 && denew->hardlim == 0) {
213                         TAILQ_INSERT_BEFORE(dep, denew, dirs);
214                         return;
215                 }
216         }
217         TAILQ_INSERT_TAIL(&dir_q, denew, dirs);
218 }
219
220 /*
221  * Get the min percentage of free blocks from audit_control(5) and that
222  * value in the kernel.  Return:
223  *      ADE_NOERR       on success,
224  *      ADE_PARSE       error parsing audit_control(5),
225  */
226 int
227 auditd_set_dist(void)
228 {
229         int ret;
230
231         ret = getacdist();
232         if (ret < 0)
233                 return (ADE_PARSE);
234
235         auditd_dist = ret;
236
237         return (ADE_NOERR);
238 }
239
240 /*
241  * Get the host from audit_control(5) and set it in the audit kernel
242  * information.  Return:
243  *      ADE_NOERR       on success.
244  *      ADE_PARSE       error parsing audit_control(5).
245  *      ADE_AUDITON     error getting/setting auditon(2) value.
246  *      ADE_GETADDR     error getting address info for host.
247  *      ADE_ADDRFAM     un-supported address family.
248  */
249 int
250 auditd_set_host(void)
251 {
252         struct sockaddr_in6 *sin6;
253         struct sockaddr_in *sin;
254         struct addrinfo *res;
255         struct auditinfo_addr aia;
256         int error, ret = ADE_NOERR;
257
258         if (getachost(auditd_host, sizeof(auditd_host)) != 0) {
259                 ret = ADE_PARSE;
260
261                 /*
262                  * To maintain reverse compatability with older audit_control
263                  * files, simply drop a warning if the host parameter has not
264                  * been set.  However, we will explicitly disable the
265                  * generation of extended audit header by passing in a zeroed
266                  * termid structure.
267                  */
268                 bzero(&aia, sizeof(aia));
269                 aia.ai_termid.at_type = AU_IPv4;
270                 error = audit_set_kaudit(&aia, sizeof(aia));
271                 if (error < 0 && errno != ENOSYS)
272                         ret = ADE_AUDITON;
273                 return (ret);
274         }
275         auditd_hostlen = strlen(auditd_host);
276         error = getaddrinfo(auditd_host, NULL, NULL, &res);
277         if (error)
278                 return (ADE_GETADDR);
279         switch (res->ai_family) {
280         case PF_INET6:
281                 sin6 = (struct sockaddr_in6 *) res->ai_addr;
282                 bcopy(&sin6->sin6_addr.s6_addr,
283                     &aia.ai_termid.at_addr[0], sizeof(struct in6_addr));
284                 aia.ai_termid.at_type = AU_IPv6;
285                 break;
286
287         case PF_INET:
288                 sin = (struct sockaddr_in *) res->ai_addr;
289                 bcopy(&sin->sin_addr.s_addr,
290                     &aia.ai_termid.at_addr[0], sizeof(struct in_addr));
291                 aia.ai_termid.at_type = AU_IPv4;
292                 break;
293
294         default:
295                 /* Un-supported address family in host parameter. */
296                 errno = EAFNOSUPPORT;
297                 return (ADE_ADDRFAM);
298         }
299
300         if (audit_set_kaudit(&aia, sizeof(aia)) < 0)
301                 ret = ADE_AUDITON;
302
303         return (ret);
304 }
305
306 /*
307  * Get the min percentage of free blocks from audit_control(5) and that
308  * value in the kernel.  Return:
309  *      ADE_NOERR       on success,
310  *      ADE_PARSE       error parsing audit_control(5),
311  *      ADE_AUDITON     error getting/setting auditon(2) value.
312  */
313 int
314 auditd_set_minfree(void)
315 {
316         au_qctrl_t qctrl;
317
318         if (getacmin(&auditd_minval) != 0)
319                 return (ADE_PARSE);
320
321         if (audit_get_qctrl(&qctrl, sizeof(qctrl)) != 0)
322                 return (ADE_AUDITON);
323
324         if (qctrl.aq_minfree != auditd_minval) {
325                 qctrl.aq_minfree = auditd_minval;
326                 if (audit_set_qctrl(&qctrl, sizeof(qctrl)) != 0)
327                         return (ADE_AUDITON);
328         }
329
330         return (0);
331 }
332
333 /*
334  * Convert a trailname into a timestamp (seconds).  Return 0 if the conversion
335  * was successful.
336  */
337 static int
338 trailname_to_tstamp(char *fn, time_t *tstamp)
339 {
340         struct tm tm;
341         char ts[TIMESTAMP_LEN + 1];
342         char *p;
343
344         *tstamp = 0;
345
346         /*
347          * Get the ending time stamp.
348          */
349         if ((p = strchr(fn, '.')) == NULL)
350                 return (1);
351         strlcpy(ts, ++p, sizeof(ts));
352         if (strlen(ts) != POSTFIX_LEN)
353                 return (1);
354
355         bzero(&tm, sizeof(tm));
356
357         /* seconds (0-60) */
358         p = ts + POSTFIX_LEN - 2;
359         tm.tm_sec = atol(p);
360         if (tm.tm_sec < 0 || tm.tm_sec > 60)
361                 return (1);
362
363         /* minutes (0-59) */
364         *p = '\0'; p -= 2;
365         tm.tm_min = atol(p);
366         if (tm.tm_min < 0 || tm.tm_min > 59)
367                 return (1);
368
369         /* hours (0 - 23) */
370         *p = '\0'; p -= 2;
371         tm.tm_hour = atol(p);
372         if (tm.tm_hour < 0 || tm.tm_hour > 23)
373                 return (1);
374
375         /* day of month (1-31) */
376         *p = '\0'; p -= 2;
377         tm.tm_mday = atol(p);
378         if (tm.tm_mday < 1 || tm.tm_mday > 31)
379                 return (1);
380
381         /* month (0 - 11) */
382         *p = '\0'; p -= 2;
383         tm.tm_mon = atol(p) - 1;
384         if (tm.tm_mon < 0 || tm.tm_mon > 11)
385                 return (1);
386
387         /* year (year - 1900) */
388         *p = '\0'; p -= 4;
389         tm.tm_year = atol(p) - 1900;
390         if (tm.tm_year < 0)
391                 return (1);
392
393         *tstamp = timegm(&tm);
394
395         return (0);
396 }
397
398 /*
399  * Remove audit trails files according to the expiration conditions.  Returns:
400  *      ADE_NOERR       on success or there is nothing to do.
401  *      ADE_PARSE       if error parsing audit_control(5).
402  *      ADE_NOMEM       if could not allocate memory.
403  *      ADE_READLINK    if could not read link file.
404  *      ADE_EXPIRE      if there was an unexpected error.
405  */
406 int
407 auditd_expire_trails(int (*warn_expired)(char *))
408 {
409         int andflg, len, ret = ADE_NOERR;
410         size_t expire_size, total_size = 0L;
411         time_t expire_age, oldest_time, current_time = time(NULL);
412         struct dir_ent *traildir;
413         struct audit_trail *at;
414         char *afnp, *pn;
415         TAILQ_HEAD(au_trls_head, audit_trail) head =
416             TAILQ_HEAD_INITIALIZER(head);
417         struct stat stbuf;
418         char activefn[MAXPATHLEN];
419
420         /*
421          * Read the expiration conditions.  If no conditions then return no
422          * error.
423          */
424         if (getacexpire(&andflg, &expire_age, &expire_size) < 0)
425                 return (ADE_PARSE);
426         if (!expire_age && !expire_size)
427                 return (ADE_NOERR);
428
429         /*
430          * Read the 'current' trail file name.  Trim off directory path.
431          */
432         activefn[0] = '\0';
433         len = readlink(AUDIT_CURRENT_LINK, activefn, MAXPATHLEN - 1);
434         if (len < 0)
435                 return (ADE_READLINK);
436         if ((afnp = strrchr(activefn, '/')) != NULL)
437                 afnp++;
438
439
440         /*
441          * Build tail queue of the trail files.
442          */
443         TAILQ_FOREACH(traildir, &dir_q, dirs) {
444                 DIR *dirp;
445                 struct dirent *dp;
446
447                 dirp = opendir(traildir->dirname);
448                 while ((dp = readdir(dirp)) != NULL) {
449                         time_t tstamp = 0;
450                         struct audit_trail *new;
451
452                         /*
453                          * Quickly filter non-trail files.
454                          */
455                         if (dp->d_namlen < FILENAME_LEN ||
456                             dp->d_name[POSTFIX_LEN] != '.')
457                                 continue;
458
459                         if (asprintf(&pn, "%s/%s", traildir->dirname,
460                             dp->d_name) < 0) {
461                                 ret = ADE_NOMEM;
462                                 break;
463                         }
464
465                         if (stat(pn, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {
466                                 free(pn);
467                                 continue;
468                         }
469
470                         total_size += stbuf.st_size;
471
472                         /*
473                          * If this is the 'current' audit trail then
474                          * don't add it to the tail queue.
475                          */
476                         if (NULL != afnp && strcmp(dp->d_name, afnp) == 0) {
477                                 free(pn);
478                                 continue;
479                         }
480
481                         /*
482                          * Get the ending time stamp encoded in the trail
483                          * name.  If we can't read it or if it is older
484                          * than Jan 1, 2000 then use the mtime.
485                          */
486                         if (trailname_to_tstamp(dp->d_name, &tstamp) != 0 ||
487                             tstamp < JAN_01_2000)
488                                 tstamp = stbuf.st_mtime;
489
490                         /*
491                          * If the time stamp is older than Jan 1, 2000 then
492                          * update the mtime of the trail file to the current
493                          * time. This is so we don't prematurely remove a trail
494                          * file that was created while the system clock reset
495                          * to the * "beginning of time" but later the system
496                          * clock is set to the correct current time.
497                          */
498                         if (current_time >= JAN_01_2000 &&
499                             tstamp < JAN_01_2000) {
500                                 struct timeval tv[2];
501
502                                 tstamp = stbuf.st_mtime = current_time;
503                                 TIMESPEC_TO_TIMEVAL(&tv[0],
504                                     &stbuf.st_atimespec);
505                                 TIMESPEC_TO_TIMEVAL(&tv[1],
506                                     &stbuf.st_mtimespec);
507                                 utimes(pn, tv);
508                         }
509
510                         /*
511                          * Allocate and populate the new entry.
512                          */
513                         new = malloc(sizeof(*new));
514                         if (NULL == new) {
515                                 free(pn);
516                                 ret = ADE_NOMEM;
517                                 break;
518                         }
519                         new->at_time = tstamp;
520                         new->at_size = stbuf.st_size;
521                         new->at_path = pn;
522
523                         /*
524                          * Check to see if we have a new head.  Otherwise,
525                          * walk the tailq from the tail first and do a simple
526                          * insertion sort.
527                          */
528                         if (TAILQ_EMPTY(&head) ||
529                             new->at_time <= TAILQ_FIRST(&head)->at_time) {
530                                 TAILQ_INSERT_HEAD(&head, new, at_trls);
531                                 continue;
532                         }
533
534                         TAILQ_FOREACH_REVERSE(at, &head, au_trls_head, at_trls)
535                                 if (new->at_time >= at->at_time) {
536                                         TAILQ_INSERT_AFTER(&head, at, new,
537                                             at_trls);
538                                         break;
539                                 }
540
541                 }
542                 closedir(dirp);
543         }
544
545         oldest_time = current_time - expire_age;
546
547         /*
548          * Expire trail files, oldest (mtime) first, if the given
549          * conditions are met.
550          */
551         at = TAILQ_FIRST(&head);
552         while (NULL != at) {
553                 struct audit_trail *at_next = TAILQ_NEXT(at, at_trls);
554
555                 if (andflg) {
556                         if ((expire_size && total_size > expire_size) &&
557                             (expire_age && at->at_time < oldest_time)) {
558                                 if (warn_expired)
559                                         (*warn_expired)(at->at_path);
560                                 if (unlink(at->at_path) < 0)
561                                         ret = ADE_EXPIRE;
562                                 total_size -= at->at_size;
563                         }
564                 } else {
565                         if ((expire_size && total_size > expire_size) ||
566                             (expire_age && at->at_time < oldest_time)) {
567                                 if (warn_expired)
568                                         (*warn_expired)(at->at_path);
569                                 if (unlink(at->at_path) < 0)
570                                         ret = ADE_EXPIRE;
571                                 total_size -= at->at_size;
572                         }
573                 }
574
575                 free(at->at_path);
576                 free(at);
577                 at = at_next;
578         }
579
580         return (ret);
581 }
582
583 /*
584  * Parses the "dir" entry in audit_control(5) into an ordered list.  Also, will
585  * set the minfree and host values if not already set.  Arguments include
586  * function pointers to audit_warn functions for soft and hard limits. Returns:
587  *      ADE_NOERR       on success,
588  *      ADE_PARSE       error parsing audit_control(5),
589  *      ADE_AUDITON     error getting/setting auditon(2) value,
590  *      ADE_NOMEM       error allocating memory,
591  *      ADE_SOFTLIM     if all the directories are over the soft limit,
592  *      ADE_HARDLIM     if all the directories are over the hard limit,
593  */
594 int
595 auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *))
596 {
597         char cur_dir[MAXNAMLEN];
598         struct dir_ent *dirent;
599         struct statfs sfs;
600         int err;
601         char soft, hard;
602         int tcnt = 0;
603         int scnt = 0;
604         int hcnt = 0;
605
606         if (auditd_minval == -1 && (err = auditd_set_minfree()) != 0)
607                 return (err);
608
609         if (auditd_hostlen == -1)
610                 auditd_set_host();
611
612         /*
613          * Init directory q.  Force a re-read of the file the next time.
614          */
615         free_dir_q();
616         endac();
617
618         /*
619          * Read the list of directories into an ordered linked list
620          * admin's preference, then those over soft limit and, finally,
621          * those over the hard limit.
622          *
623          * XXX We should use the reentrant interfaces once they are
624          * available.
625          */
626         while (getacdir(cur_dir, MAXNAMLEN) >= 0) {
627                 if (statfs(cur_dir, &sfs) < 0)
628                         continue;  /* XXX should warn */
629                 soft = (sfs.f_bfree < (sfs.f_blocks * auditd_minval / 100 )) ?
630                     1 : 0;
631                 hard = (sfs.f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) ? 1 : 0;
632                 if (soft) {
633                         if (warn_soft)
634                                 (*warn_soft)(cur_dir);
635                         scnt++;
636                 }
637                 if (hard) {
638                         if (warn_hard)
639                                 (*warn_hard)(cur_dir);
640                         hcnt++;
641                 }
642                 dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent));
643                 if (dirent == NULL)
644                         return (ADE_NOMEM);
645                 dirent->softlim = soft;
646                 dirent->hardlim = hard;
647                 dirent->dirname = (char *) malloc(MAXNAMLEN);
648                 if (dirent->dirname == NULL) {
649                         free(dirent);
650                         return (ADE_NOMEM);
651                 }
652                 strlcpy(dirent->dirname, cur_dir, MAXNAMLEN);
653                 insert_orderly(dirent);
654                 tcnt++;
655         }
656
657         if (hcnt == tcnt)
658                 return (ADE_HARDLIM);
659         if (scnt == tcnt)
660                 return (ADE_SOFTLIM);
661         return (0);
662 }
663
664 void
665 auditd_close_dirs(void)
666 {
667         free_dir_q();
668         auditd_minval = -1;
669         auditd_hostlen = -1;
670 }
671
672
673 /*
674  * Process the audit event file, obtaining a class mapping for each event, and
675  * set that mapping into the kernel. Return:
676  *       n      number of event mappings that were successfully processed,
677  *   ADE_NOMEM  if there was an error allocating memory.
678  */
679 int
680 auditd_set_evcmap(void)
681 {
682         au_event_ent_t ev, *evp;
683         au_evclass_map_t evc_map;
684         int ctr = 0;
685
686         /*
687          * XXX There's a risk here that the BSM library will return NULL
688          * for an event when it can't properly map it to a class. In that
689          * case, we will not process any events beyond the one that failed,
690          * but should. We need a way to get a count of the events.
691          */
692         ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
693         ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
694         if (ev.ae_name == NULL || ev.ae_desc == NULL) {
695                 if (ev.ae_name != NULL)
696                         free(ev.ae_name);
697                 return (ADE_NOMEM);
698         }
699
700         /*
701          * XXXRW: Currently we have no way to remove mappings from the kernel
702          * when they are removed from the file-based mappings.
703          */
704         evp = &ev;
705         setauevent();
706         while ((evp = getauevent_r(evp)) != NULL) {
707                 evc_map.ec_number = evp->ae_number;
708                 evc_map.ec_class = evp->ae_class;
709                 if (audit_set_class(&evc_map, sizeof(evc_map)) == 0)
710                         ctr++;
711         }
712         endauevent();
713         free(ev.ae_name);
714         free(ev.ae_desc);
715
716         return (ctr);
717 }
718
719 /*
720  * Get the non-attributable event string and set the kernel mask.  Return:
721  *      ADE_NOERR       on success,
722  *      ADE_PARSE       error parsing audit_control(5),
723  *      ADE_AUDITON     error setting the mask using auditon(2).
724  */
725 int
726 auditd_set_namask(void)
727 {
728         au_mask_t aumask;
729         char naeventstr[NA_EVENT_STR_SIZE];
730
731         if (getacna(naeventstr, NA_EVENT_STR_SIZE) != 0 ||
732             getauditflagsbin(naeventstr, &aumask) != 0)
733                 return (ADE_PARSE);
734
735         if (audit_set_kmask(&aumask, sizeof(aumask)) != 0)
736                 return (ADE_AUDITON);
737
738         return (ADE_NOERR);
739 }
740
741 /*
742  * Set the audit control policy if a policy is configured in audit_control(5),
743  * implement the policy. However, if one isn't defined or if there is an error
744  * parsing the control file, set AUDIT_CNT to avoid leaving the system in a
745  * fragile state.  Return:
746  *      ADE_NOERR       on success,
747  *      ADE_PARSE       error parsing audit_control(5),
748  *      ADE_AUDITON     error setting policy using auditon(2).
749  */
750 int
751 auditd_set_policy(void)
752 {
753         int policy;
754         char polstr[POL_STR_SIZE];
755
756         if (getacpol(polstr, POL_STR_SIZE) != 0 ||
757             au_strtopol(polstr, &policy) != 0) {
758                 policy = AUDIT_CNT;
759                 if (audit_set_policy(&policy) != 0)
760                         return (ADE_AUDITON);
761                 return (ADE_PARSE);
762         }
763
764         if (audit_set_policy(&policy) != 0)
765                 return (ADE_AUDITON);
766
767         return (ADE_NOERR);
768 }
769
770 /*
771  * Set trail rotation size.  Return:
772  *      ADE_NOERR       on success,
773  *      ADE_PARSE       error parsing audit_control(5),
774  *      ADE_AUDITON     error setting file size using auditon(2).
775  */
776 int
777 auditd_set_fsize(void)
778 {
779         size_t filesz;
780         au_fstat_t au_fstat;
781
782         /*
783          * Set trail rotation size.
784          */
785         if (getacfilesz(&filesz) != 0)
786                 return (ADE_PARSE);
787
788         bzero(&au_fstat, sizeof(au_fstat));
789         au_fstat.af_filesz = filesz;
790         if (audit_set_fsize(&au_fstat, sizeof(au_fstat)) != 0)
791                 return (ADE_AUDITON);
792
793         return (ADE_NOERR);
794 }
795
796 static void
797 inject_dist(const char *fromname, char *toname, size_t tonamesize)
798 {
799         char *ptr;
800
801         ptr = strrchr(fromname, '/');
802         assert(ptr != NULL);
803         assert(ptr - fromname < (ssize_t)tonamesize);
804         strlcpy(toname, fromname, ptr - fromname + 1);
805         strlcat(toname, "/dist/", tonamesize);
806         strlcat(toname, ptr + 1, tonamesize);
807 }
808
809 static int
810 auditdist_link(const char *filename)
811 {
812         char fname[MAXPATHLEN];
813
814         if (auditd_dist) {
815                 inject_dist(filename, fname, sizeof(fname));
816                 /* Ignore errors. */
817                 (void) link(filename, fname);
818         }
819
820         return (0);
821 }
822
823 int
824 auditd_rename(const char *fromname, const char *toname)
825 {
826         char fname[MAXPATHLEN], tname[MAXPATHLEN];
827
828         if (auditd_dist) {
829                 inject_dist(fromname, fname, sizeof(fname));
830                 inject_dist(toname, tname, sizeof(tname));
831                 /* Ignore errors. */
832                 (void) rename(fname, tname);
833         }
834
835         return (rename(fromname, toname));
836 }
837
838 /*
839  * Create the new audit file with appropriate permissions and ownership.
840  * Call auditctl(2) for this file.
841  * Try to clean up if something goes wrong.
842  * *errorp is modified only on auditctl(2) failure.
843  */
844 static int
845 open_trail(char *fname, gid_t gid, int *errorp)
846 {
847         int fd;
848
849         /* XXXPJD: What should we do if the file already exists? */
850         fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR);
851         if (fd < 0)
852                 return (-1);
853         if (fchown(fd, -1, gid) < 0 || fchmod(fd, S_IRUSR | S_IRGRP) < 0) {
854                 (void) close(fd);
855                 (void) unlink(fname);
856                 return (-1);
857         }
858         (void) close(fd);
859         if (auditctl(fname) < 0) {
860                 *errorp = errno;
861                 (void) unlink(fname);
862                 return (-1);
863         }
864         (void) auditdist_link(fname);
865         return (0);
866 }
867
868 /*
869  * Create the new audit trail file, swap with existing audit file.  Arguments
870  * include timestamp for the filename, a pointer to a string for returning the
871  * new file name, GID for trail file, and audit_warn function pointer for
872  * 'getacdir()' errors.  Returns:
873  *      ADE_NOERR       on success,
874  *      ADE_STRERR      if the file name string could not be created,
875  *      ADE_SWAPERR     if the audit trail file could not be swapped,
876  *      ADE_ACTL        if the auditctl(2) call failed but file swap still
877  *                      successful.
878  *      ADE_ACTLERR     if the auditctl(2) call failed and file swap failed.
879  *      ADE_SYMLINK     if symlink(2) failed updating the current link.
880  */
881 int
882 auditd_swap_trail(char *TS, char **newfile, gid_t gid,
883     int (*warn_getacdir)(char *))
884 {
885         char timestr[FILENAME_LEN + 1];
886         char *fn;
887         struct dir_ent *dirent;
888         int saverrno = 0;
889
890         if (strlen(TS) != TIMESTAMP_LEN ||
891             snprintf(timestr, sizeof(timestr), "%s.%s", TS,
892             NOT_TERMINATED) < 0) {
893                 errno = EINVAL;
894                 return (ADE_STRERR);
895         }
896
897         /* Try until we succeed. */
898         TAILQ_FOREACH(dirent, &dir_q, dirs) {
899                 if (dirent->hardlim)
900                         continue;
901                 if ((fn = affixdir(timestr, dirent)) == NULL)
902                         return (ADE_STRERR);
903
904                 /*
905                  * Create the file and pass to the kernel if all went well.
906                  */
907                 if (open_trail(fn, gid, &saverrno) == 0) {
908                         /* Success. */
909                         *newfile = fn;
910                         if (saverrno) {
911                                 /*
912                                  * auditctl() failed but still
913                                  * successful. Return errno and "soft"
914                                  * error.
915                                  */
916                                 errno = saverrno;
917                                 return (ADE_ACTL);
918                         }
919                         return (ADE_NOERR);
920                 }
921                 /*
922                  * auditctl failed setting log file. Try again.
923                  */
924                 /*
925                  * Tell the administrator about lack of permissions for dir.
926                  */
927                 if (warn_getacdir != NULL)
928                         (*warn_getacdir)(dirent->dirname);
929         }
930         if (saverrno) {
931                 errno = saverrno;
932                 return (ADE_ACTLERR);
933         } else
934                 return (ADE_SWAPERR);
935 }
936
937 /*
938  * Mask calling process from being audited. Returns:
939  *      ADE_NOERR       on success,
940  *      ADE_SETAUDIT    if setaudit(2) fails.
941  */
942 #ifdef __APPLE__
943 int
944 auditd_prevent_audit(void)
945 {
946         auditinfo_addr_t aia;
947
948         /*
949          * To prevent event feedback cycles and avoid audit becoming stalled if
950          * auditing is suspended we mask this processes events from being
951          * audited.  We allow the uid, tid, and mask fields to be implicitly
952          * set to zero, but do set the audit session ID to the PID.
953          *
954          * XXXRW: Is there more to it than this?
955          */
956         bzero(&aia, sizeof(aia));
957         aia.ai_asid = AU_ASSIGN_ASID;
958         aia.ai_termid.at_type = AU_IPv4;
959         if (setaudit_addr(&aia, sizeof(aia)) != 0)
960                 return (ADE_SETAUDIT);
961         return (ADE_NOERR);
962 }
963 #else
964 int
965 auditd_prevent_audit(void)
966 {
967         auditinfo_t ai;
968
969         /*
970          * To prevent event feedback cycles and avoid audit becoming stalled if
971          * auditing is suspended we mask this processes events from being
972          * audited.  We allow the uid, tid, and mask fields to be implicitly
973          * set to zero, but do set the audit session ID to the PID.
974          *
975          * XXXRW: Is there more to it than this?
976          */
977         bzero(&ai, sizeof(ai));
978         ai.ai_asid = getpid();
979         if (setaudit(&ai) != 0)
980                 return (ADE_SETAUDIT);
981         return (ADE_NOERR);
982 }
983 #endif /* !__APPLE__ */
984
985 /*
986  * Generate and submit audit record for audit startup or shutdown.  The event
987  * argument can be AUE_audit_recovery, AUE_audit_startup or
988  * AUE_audit_shutdown. The path argument will add a path token, if not NULL.
989  * Returns:
990  *      AUE_NOERR       on success,
991  *      ADE_NOMEM       if memory allocation fails,
992  *      ADE_AU_OPEN     if au_open(3) fails,
993  *      ADE_AU_CLOSE    if au_close(3) fails.
994  */
995 int
996 auditd_gen_record(int event, char *path)
997 {
998         int aufd;
999         uid_t uid;
1000         pid_t pid;
1001         char *autext = NULL;
1002         token_t *tok;
1003         struct auditinfo_addr aia;
1004
1005         if (event == AUE_audit_startup)
1006                 asprintf(&autext, "%s::Audit startup", getprogname());
1007         else if (event == AUE_audit_shutdown)
1008                 asprintf(&autext, "%s::Audit shutdown", getprogname());
1009         else if (event == AUE_audit_recovery)
1010                 asprintf(&autext, "%s::Audit recovery", getprogname());
1011         else
1012                 return (ADE_INVAL);
1013         if (autext == NULL)
1014                 return (ADE_NOMEM);
1015
1016         if ((aufd = au_open()) == -1) {
1017                 free(autext);
1018                 return (ADE_AU_OPEN);
1019         }
1020         bzero(&aia, sizeof(aia));
1021         uid = getuid(); pid = getpid();
1022         if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, getgid(),
1023             pid, pid, &aia.ai_termid)) != NULL)
1024                 au_write(aufd, tok);
1025         if ((tok = au_to_text(autext)) != NULL)
1026                 au_write(aufd, tok);
1027         free(autext);
1028         if (path != NULL && (tok = au_to_path(path)) != NULL)
1029                 au_write(aufd, tok);
1030         if ((tok = au_to_return32(0, 0)) != NULL)
1031                 au_write(aufd, tok);
1032         if (au_close(aufd, 1, event) == -1)
1033                 return (ADE_AU_CLOSE);
1034
1035         return (ADE_NOERR);
1036 }
1037
1038 /*
1039  * Check for a 'current' symlink and do crash recovery, if needed. Create a new
1040  * 'current' symlink. The argument 'curfile' is the file the 'current' symlink
1041  * should point to.  Returns:
1042  *      ADE_NOERR       on success,
1043  *      ADE_AU_OPEN     if au_open(3) fails,
1044  *      ADE_AU_CLOSE    if au_close(3) fails.
1045  *      ADE_RENAME      if error renaming audit trail file,
1046  *      ADE_READLINK    if error reading the 'current' link,
1047  *      ADE_SYMLINK     if error creating 'current' link.
1048  */
1049 int
1050 auditd_new_curlink(char *curfile)
1051 {
1052         int len, err;
1053         char *ptr;
1054         char *path = NULL;
1055         struct stat sb;
1056         char recoveredname[MAXPATHLEN];
1057         char newname[MAXPATHLEN];
1058
1059         /*
1060          * Check to see if audit was shutdown properly.  If not, clean up,
1061          * recover previous audit trail file, and generate audit record.
1062          */
1063         len = readlink(AUDIT_CURRENT_LINK, recoveredname,
1064             sizeof(recoveredname) - 1);
1065         if (len > 0) {
1066                 /* 'current' exist but is it pointing at a valid file?  */
1067                 recoveredname[len++] = '\0';
1068                 if (stat(recoveredname, &sb) == 0) {
1069                         /* Yes, rename it to a crash recovery file. */
1070                         strlcpy(newname, recoveredname, sizeof(newname));
1071
1072                         if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
1073                                 memcpy(ptr, CRASH_RECOVERY, POSTFIX_LEN);
1074                                 if (auditd_rename(recoveredname, newname) != 0)
1075                                         return (ADE_RENAME);
1076                         } else
1077                                 return (ADE_STRERR);
1078
1079                         path = newname;
1080                 }
1081
1082                 /* 'current' symlink is (now) invalid so remove it. */
1083                 (void) unlink(AUDIT_CURRENT_LINK);
1084
1085                 /* Note the crash recovery in current audit trail */
1086                 err = auditd_gen_record(AUE_audit_recovery, path);
1087                 if (err)
1088                         return (err);
1089         }
1090
1091         if (len < 0 && errno != ENOENT)
1092                 return (ADE_READLINK);
1093
1094         if (symlink(curfile, AUDIT_CURRENT_LINK) != 0)
1095                 return (ADE_SYMLINK);
1096
1097         return (0);
1098 }
1099
1100 /*
1101  * Do just what we need to quickly start auditing.  Assume no system logging or
1102  * notify.  Return:
1103  *   0   on success,
1104  *  -1   on failure.
1105  */
1106 int
1107 audit_quick_start(void)
1108 {
1109         int err;
1110         char *newfile = NULL;
1111         time_t tt;
1112         char TS[TIMESTAMP_LEN + 1];
1113         int ret = 0;
1114
1115         /*
1116          * Mask auditing of this process.
1117          */
1118         if (auditd_prevent_audit() != 0)
1119                 return (-1);
1120
1121         /*
1122          * Read audit_control and get log directories.
1123          */
1124         err = auditd_read_dirs(NULL, NULL);
1125         if (err != ADE_NOERR && err != ADE_SOFTLIM)
1126                 return (-1);
1127
1128         /*
1129          * Setup trail file distribution.
1130          */
1131         (void) auditd_set_dist();
1132
1133         /*
1134          *  Create a new audit trail log.
1135          */
1136         if (getTSstr(tt, TS, sizeof(TS)) != 0)
1137                 return (-1);
1138         err = auditd_swap_trail(TS, &newfile, getgid(), NULL);
1139         if (err != ADE_NOERR && err != ADE_ACTL) {
1140                 ret = -1;
1141                 goto out;
1142         }
1143
1144         /*
1145          * Add the current symlink and recover from crash, if needed.
1146          */
1147         if (auditd_new_curlink(newfile) != 0) {
1148                 ret = -1;
1149                 goto out;
1150         }
1151
1152         /*
1153          * At this point auditing has started so generate audit start-up record.
1154          */
1155         if (auditd_gen_record(AUE_audit_startup, NULL) != 0) {
1156                 ret = -1;
1157                 goto out;
1158         }
1159
1160         /*
1161          *  Configure the audit controls.
1162          */
1163         (void) auditd_set_evcmap();
1164         (void) auditd_set_namask();
1165         (void) auditd_set_policy();
1166         (void) auditd_set_fsize();
1167         (void) auditd_set_minfree();
1168         (void) auditd_set_host();
1169
1170 out:
1171         if (newfile != NULL)
1172                 free(newfile);
1173
1174         return (ret);
1175 }
1176
1177 /*
1178  * Shut down auditing quickly.  Assumes that is only called on system shutdown.
1179  * Returns:
1180  *       0      on success,
1181  *      -1      on failure.
1182  */
1183 int
1184 audit_quick_stop(void)
1185 {
1186         int len;
1187         int cond;
1188         char *ptr;
1189         time_t tt;
1190         char oldname[MAXPATHLEN];
1191         char newname[MAXPATHLEN];
1192         char TS[TIMESTAMP_LEN + 1];
1193
1194         /*
1195          * Auditing already disabled?
1196          */
1197         if (audit_get_cond(&cond) != 0)
1198                 return (-1);
1199         if (cond == AUC_NOAUDIT)
1200                 return (0);
1201
1202         /*
1203          *  Generate audit shutdown record.
1204          */
1205         (void) auditd_gen_record(AUE_audit_shutdown, NULL);
1206
1207         /*
1208          * Shutdown auditing in the kernel.
1209          */
1210         cond = AUC_DISABLED;
1211         if (audit_set_cond(&cond) != 0)
1212                 return (-1);
1213 #ifdef  __BSM_INTERNAL_NOTIFY_KEY
1214         notify_post(__BSM_INTERNAL_NOTIFY_KEY);
1215 #endif
1216
1217         /*
1218          * Rename last audit trail and remove 'current' link.
1219          */
1220         len = readlink(AUDIT_CURRENT_LINK, oldname, sizeof(oldname) - 1);
1221         if (len < 0)
1222                 return (-1);
1223         oldname[len++] = '\0';
1224
1225         if (getTSstr(tt, TS, sizeof(TS)) != 0)
1226                 return (-1);
1227
1228         strlcpy(newname, oldname, sizeof(newname));
1229
1230         if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
1231                 memcpy(ptr, TS, POSTFIX_LEN);
1232                 if (auditd_rename(oldname, newname) != 0)
1233                         return (-1);
1234         } else
1235                 return (-1);
1236
1237         (void) unlink(AUDIT_CURRENT_LINK);
1238
1239         return (0);
1240 }