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
91struct dir_ent {
92	char			*dirname;
93	uint8_t			 softlim;
94	uint8_t			 hardlim;
95	TAILQ_ENTRY(dir_ent)	 dirs;
96};
97
98static TAILQ_HEAD(, dir_ent)	dir_q;
99
100struct 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
108static int auditd_minval = -1;
109static int auditd_dist = 0;
110
111static char auditd_host[MAXHOSTNAMELEN];
112static int auditd_hostlen = -1;
113
114static 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 */
146const char *
147auditd_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 */
161static void
162free_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 */
180static char *
181affixdir(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 */
208static void
209insert_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 */
232int
233auditd_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 */
255int
256auditd_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 */
319int
320auditd_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 */
343static int
344trailname_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 */
412int
413auditd_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 */
600int
601auditd_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
670void
671auditd_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 */
690int
691auditd_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 */
751int
752auditd_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 */
776int
777auditd_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 */
802int
803auditd_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 */
828int
829auditd_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
850static void
851inject_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
863static int
864auditdist_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
877int
878auditd_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 */
898static int
899open_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 */
935int
936auditd_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__
997int
998auditd_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
1018int
1019auditd_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 */
1049int
1050auditd_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 */
1103int
1104auditd_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 */
1160int
1161audit_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
1224out:
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 */
1237int
1238audit_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}
1295