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