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