xref: /freebsd/contrib/openbsm/libauditd/auditd_lib.c (revision aca5021d5f7dcab1e11692923266373e35322d9a)
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 
87 struct dir_ent {
88 	char			*dirname;
89 	uint8_t			 softlim;
90 	uint8_t			 hardlim;
91 	TAILQ_ENTRY(dir_ent)	 dirs;
92 };
93 
94 static TAILQ_HEAD(, dir_ent)	dir_q;
95 
96 struct 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 
104 static int auditd_minval = -1;
105 static int auditd_dist = 0;
106 
107 static char auditd_host[MAXHOSTNAMELEN];
108 static int auditd_hostlen = -1;
109 
110 static 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  */
142 const char *
143 auditd_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  */
157 static void
158 free_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  */
176 static char *
177 affixdir(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  */
204 static void
205 insert_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  */
228 int
229 auditd_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  */
251 int
252 auditd_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  */
315 int
316 auditd_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  */
339 static int
340 trailname_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  */
407 int
408 auditd_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  */
593 int
594 auditd_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 
663 void
664 auditd_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  */
678 int
679 auditd_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  */
724 int
725 auditd_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  */
749 int
750 auditd_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  */
775 int
776 auditd_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 
795 static void
796 inject_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 
808 static int
809 auditdist_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 
822 int
823 auditd_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  */
843 static int
844 open_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  */
880 int
881 auditd_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__
942 int
943 auditd_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
963 int
964 auditd_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  */
994 int
995 auditd_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  */
1048 int
1049 auditd_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  */
1105 int
1106 audit_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 
1169 out:
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  */
1182 int
1183 audit_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