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 }
1295