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