1 /*-
2  * Copyright (c) 2008 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#2 $
30  */
31 
32 #include <sys/param.h>
33 
34 #include <config/config.h>
35 
36 #include <sys/dirent.h>
37 #include <sys/mount.h>
38 #include <sys/socket.h>
39 #ifdef HAVE_FULL_QUEUE_H
40 #include <sys/queue.h>
41 #else /* !HAVE_FULL_QUEUE_H */
42 #include <compat/queue.h>
43 #endif /* !HAVE_FULL_QUEUE_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 <err.h>
56 #include <errno.h>
57 #include <fcntl.h>
58 #include <stdio.h>
59 #include <string.h>
60 #include <stdlib.h>
61 #include <time.h>
62 #include <unistd.h>
63 #include <netdb.h>
64 
65 #ifdef __APPLE__
66 #include <notify.h>
67 #ifndef __BSM_INTERNAL_NOTIFY_KEY
68 #define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change"
69 #endif /* __BSM_INTERNAL_NOTIFY_KEY */
70 #endif /* __APPLE__ */
71 
72 /*
73  * XXX This is temporary until this is moved to <bsm/audit.h> and shared with
74  * the kernel.
75  */
76 #ifndef	AUDIT_HARD_LIMIT_FREE_BLOCKS
77 #define	AUDIT_HARD_LIMIT_FREE_BLOCKS	4
78 #endif
79 
80 struct dir_ent {
81 	char			*dirname;
82 	uint8_t			 softlim;
83 	uint8_t			 hardlim;
84 	TAILQ_ENTRY(dir_ent)	 dirs;
85 };
86 
87 static TAILQ_HEAD(, dir_ent)	dir_q;
88 static int minval = -1;
89 
90 static char *auditd_errmsg[] = {
91 	"no error",					/* ADE_NOERR 	( 0) */
92 	"could not parse audit_control(5) file",	/* ADE_PARSE 	( 1) */
93 	"auditon(2) failed",				/* ADE_AUDITON 	( 2) */
94 	"malloc(3) failed",				/* ADE_NOMEM 	( 3) */
95 	"all audit log directories over soft limit",	/* ADE_SOFTLIM  ( 4) */
96 	"all audit log directories over hard limit",	/* ADE_HARDLIM 	( 5) */
97 	"could not create file name string",		/* ADE_STRERR 	( 6) */
98 	"could not open audit record", 			/* ADE_AU_OPEN 	( 7) */
99 	"could not close audit record",			/* ADE_AU_CLOSE ( 8) */
100 	"could not set active audit session state",	/* ADE_SETAUDIT ( 9) */
101 	"auditctl(2) failed (trail still swapped)",	/* ADE_ACTL 	(10) */
102 	"auditctl(2) failed (trail not swapped)",	/* ADE_ACTLERR  (11) */
103 	"could not swap audit trail file",		/* ADE_SWAPERR 	(12) */
104 	"could not rename crash recovery file",		/* ADE_RENAME	(13) */
105 	"could not read 'current' link file",		/* ADE_READLINK	(14) */
106 	"could not create 'current' link file", 	/* ADE_SYMLINK  (15) */
107 	"invalid argument",				/* ADE_INVAL	(16) */
108 	"could not resolve hostname to address",	/* ADE_GETADDR	(17) */
109 	"address family not supported",			/* ADE_ADDRFAM	(18) */
110 };
111 
112 #define MAXERRCODE (sizeof(auditd_errmsg) / sizeof(auditd_errmsg[0]))
113 
114 #define NA_EVENT_STR_SIZE       25
115 #define POL_STR_SIZE            128
116 
117 
118 /*
119  * Look up and return the error string for the given audit error code.
120  */
121 const char *
122 auditd_strerror(int errcode)
123 {
124 	int idx = -errcode;
125 
126 	if (idx < 0 || idx > (int)MAXERRCODE)
127 		return ("Invalid auditd error code");
128 
129 	return (auditd_errmsg[idx]);
130 }
131 
132 
133 /*
134  * Free our local list of directory names and init list
135  */
136 static void
137 free_dir_q(void)
138 {
139 	struct dir_ent *d1, *d2;
140 
141 	d1 = TAILQ_FIRST(&dir_q);
142 	while (d1 != NULL) {
143 		d2 = TAILQ_NEXT(d1, dirs);
144 		free(d1->dirname);
145 		free(d1);
146 		d1 = d2;
147 	}
148 	TAILQ_INIT(&dir_q);
149 }
150 
151 /*
152  * Concat the directory name to the given file name.
153  * XXX We should affix the hostname also
154  */
155 static char *
156 affixdir(char *name, struct dir_ent *dirent)
157 {
158 	char *fn = NULL;
159 
160 	/*
161 	 * Sanity check on file name.
162 	 */
163 	if (strlen(name) != (FILENAME_LEN - 1)) {
164 		errno = EINVAL;
165                 return (NULL);
166 	}
167 
168 	asprintf(&fn, "%s/%s", dirent->dirname, name);
169 	return (fn);
170 }
171 
172 /*
173  * Insert the directory entry in the list by the way they are ordered in
174  * audit_control(5).  Move the entries that are over the soft and hard limits
175  * toward the tail.
176  */
177 static void
178 insert_orderly(struct dir_ent *denew)
179 {
180 	struct dir_ent *dep;
181 
182 	TAILQ_FOREACH(dep, &dir_q, dirs) {
183 		if (dep->softlim == 1 && denew->softlim == 0) {
184 			TAILQ_INSERT_BEFORE(dep, denew, dirs);
185 			return;
186 		}
187 		if (dep->hardlim == 1 && denew->hardlim == 0) {
188 			TAILQ_INSERT_BEFORE(dep, denew, dirs);
189 			return;
190 		}
191 	}
192 	TAILQ_INSERT_TAIL(&dir_q, denew, dirs);
193 }
194 
195 /*
196  * Get the host from audit_control(5) and set it in the audit kernel
197  * information.  Return:
198  *	ADE_NOERR	on success.
199  *	ADE_PARSE	error parsing audit_control(5).
200  *	ADE_AUDITON	error getting/setting auditon(2) value.
201  *	ADE_GETADDR 	error getting address info for host.
202  *	ADE_ADDRFAM	un-supported address family.
203  */
204 int
205 auditd_set_host(void)
206 {
207 	char hoststr[MAXHOSTNAMELEN];
208 	struct sockaddr_in6 *sin6;
209 	struct sockaddr_in *sin;
210 	struct addrinfo *res;
211 	struct auditinfo_addr aia;
212 	int error, ret = ADE_NOERR;
213 
214 	if (getachost(hoststr, MAXHOSTNAMELEN) != 0) {
215 
216 		ret = ADE_PARSE;
217 
218 		/*
219 		 * To maintain reverse compatability with older audit_control
220 		 * files, simply drop a warning if the host parameter has not
221 		 * been set.  However, we will explicitly disable the
222 		 * generation of extended audit header by passing in a zeroed
223 		 * termid structure.
224 		 */
225 		bzero(&aia, sizeof(aia));
226 		aia.ai_termid.at_type = AU_IPv4;
227 		error = auditon(A_SETKAUDIT, &aia, sizeof(aia));
228 		if (error < 0 && errno != ENOSYS)
229 			ret = ADE_AUDITON;
230 		return (ret);
231 	}
232 	error = getaddrinfo(hoststr, NULL, NULL, &res);
233 	if (error)
234 		return (ADE_GETADDR);
235 	switch (res->ai_family) {
236 	case PF_INET6:
237 		sin6 = (struct sockaddr_in6 *) res->ai_addr;
238 		bcopy(&sin6->sin6_addr.s6_addr,
239 		    &aia.ai_termid.at_addr[0], sizeof(struct in6_addr));
240 		aia.ai_termid.at_type = AU_IPv6;
241 		break;
242 
243 	case PF_INET:
244 		sin = (struct sockaddr_in *) res->ai_addr;
245 		bcopy(&sin->sin_addr.s_addr,
246 		    &aia.ai_termid.at_addr[0], sizeof(struct in_addr));
247 		aia.ai_termid.at_type = AU_IPv4;
248 		break;
249 
250 	default:
251 		/* Un-supported address family in host parameter. */
252 		errno = EAFNOSUPPORT;
253 		return (ADE_ADDRFAM);
254 	}
255 
256 	if (auditon(A_SETKAUDIT, &aia, sizeof(aia)) < 0)
257 		ret = ADE_AUDITON;
258 
259 	return (ret);
260 }
261 
262 /*
263  * Get the min percentage of free blocks from audit_control(5) and that
264  * value in the kernel.  Return:
265  *	ADE_NOERR	on success,
266  *	ADE_PARSE 	error parsing audit_control(5),
267  *	ADE_AUDITON	error getting/setting auditon(2) value.
268  */
269 int
270 auditd_set_minfree(void)
271 {
272 	au_qctrl_t qctrl;
273 
274 	if (getacmin(&minval) != 0)
275 		return (ADE_PARSE);
276 
277 	if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0)
278 		return (ADE_AUDITON);
279 
280 	if (qctrl.aq_minfree != minval) {
281 		qctrl.aq_minfree = minval;
282 		if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0)
283 			return (ADE_AUDITON);
284 	}
285 
286 	return (0);
287 }
288 
289 /*
290  * Parses the "dir" entry in audit_control(5) into an ordered list.  Also, will
291  * set the minfree value if not already set.  Arguments include function
292  * pointers to audit_warn functions for soft and hard limits. Returns:
293  *	ADE_NOERR	on success,
294  *	ADE_PARSE	error parsing audit_control(5),
295  *	ADE_AUDITON	error getting/setting auditon(2) value,
296  *	ADE_NOMEM	error allocating memory,
297  *	ADE_SOFTLIM	if all the directories are over the soft limit,
298  *	ADE_HARDLIM	if all the directories are over the hard limit,
299  */
300 int
301 auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *))
302 {
303 	char cur_dir[MAXNAMLEN];
304 	struct dir_ent *dirent;
305 	struct statfs sfs;
306 	int err;
307 	char soft, hard;
308 	int tcnt = 0;
309 	int scnt = 0;
310 	int hcnt = 0;
311 
312 	if (minval == -1 && (err = auditd_set_minfree()) != 0)
313 		return (err);
314 
315         /*
316          * Init directory q.  Force a re-read of the file the next time.
317          */
318 	free_dir_q();
319 	endac();
320 
321 	/*
322 	 * Read the list of directories into an ordered linked list
323 	 * admin's preference, then those over soft limit and, finally,
324 	 * those over the hard limit.
325 	 *
326          * XXX We should use the reentrant interfaces once they are
327          * available.
328          */
329 	while (getacdir(cur_dir, MAXNAMLEN) >= 0) {
330 		if (statfs(cur_dir, &sfs) < 0)
331 			continue;  /* XXX should warn */
332 		soft = (sfs.f_bfree < (sfs.f_blocks / (100 / minval))) ? 1 : 0;
333 		hard = (sfs.f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) ? 1 : 0;
334 		if (soft) {
335 			if (warn_soft)
336 				(*warn_soft)(cur_dir);
337 			scnt++;
338 		}
339 		if (hard) {
340 			if (warn_hard)
341 				(*warn_hard)(cur_dir);
342 			hcnt++;
343 		}
344 		dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent));
345 		if (dirent == NULL)
346 			return (ADE_NOMEM);
347 		dirent->softlim = soft;
348 		dirent->hardlim = hard;
349 		dirent->dirname = (char *) malloc(MAXNAMLEN);
350 		if (dirent->dirname == NULL) {
351 			free(dirent);
352 			return (ADE_NOMEM);
353 		}
354 		strlcpy(dirent->dirname, cur_dir, MAXNAMLEN);
355 		insert_orderly(dirent);
356 		tcnt++;
357 	}
358 
359 	if (hcnt == tcnt)
360 		return (ADE_HARDLIM);
361 	if (scnt == tcnt)
362 		return (ADE_SOFTLIM);
363 	return (0);
364 }
365 
366 void
367 auditd_close_dirs(void)
368 {
369 	free_dir_q();
370 	minval = -1;
371 }
372 
373 
374 /*
375  * Process the audit event file, obtaining a class mapping for each event, and
376  * set that mapping into the kernel. Return:
377  * 	 n	number of event mappings that were successfully processed,
378  *   ADE_NOMEM	if there was an error allocating memory.
379  */
380 int
381 auditd_set_evcmap(void)
382 {
383 	au_event_ent_t ev, *evp;
384 	au_evclass_map_t evc_map;
385 	int ctr = 0;
386 
387 
388 	/*
389 	 * XXX There's a risk here that the BSM library will return NULL
390 	 * for an event when it can't properly map it to a class. In that
391 	 * case, we will not process any events beyond the one that failed,
392 	 * but should. We need a way to get a count of the events.
393 	 */
394 	ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
395 	ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
396 	if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) {
397 		if (ev.ae_name != NULL)
398 			free(ev.ae_name);
399 		return (ADE_NOMEM);
400 	}
401 
402 	/*
403 	 * XXXRW: Currently we have no way to remove mappings from the kernel
404 	 * when they are removed from the file-based mappings.
405 	 */
406 	evp = &ev;
407 	setauevent();
408 	while ((evp = getauevent_r(evp)) != NULL) {
409 		evc_map.ec_number = evp->ae_number;
410 		evc_map.ec_class = evp->ae_class;
411 		if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t))
412 		    == 0)
413 			ctr++;
414 	}
415 	endauevent();
416 	free(ev.ae_name);
417 	free(ev.ae_desc);
418 
419 	return (ctr);
420 }
421 
422 /*
423  * Get the non-attributable event string and set the kernel mask.  Return:
424  *	ADE_NOERR 	on success,
425  *	ADE_PARSE	error parsing audit_control(5),
426  *	ADE_AUDITON	error setting the mask using auditon(2).
427  */
428 int
429 auditd_set_namask(void)
430 {
431 	au_mask_t aumask;
432 	char naeventstr[NA_EVENT_STR_SIZE];
433 
434 	if ((getacna(naeventstr, NA_EVENT_STR_SIZE) != 0) ||
435 	    (getauditflagsbin(naeventstr, &aumask) != 0))
436 		return (ADE_PARSE);
437 
438 	if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t)))
439 		return (ADE_AUDITON);
440 
441 	return (ADE_NOERR);
442 }
443 
444 /*
445  * Set the audit control policy if a policy is configured in audit_control(5),
446  * implement the policy. However, if one isn't defined or if there is an error
447  * parsing the control file, set AUDIT_CNT to avoid leaving the system in a
448  * fragile state.  Return:
449  *	ADE_NOERR 	on success,
450  *	ADE_PARSE	error parsing audit_control(5),
451  *	ADE_AUDITON	error setting policy using auditon(2).
452  */
453 int
454 auditd_set_policy(void)
455 {
456 	long policy;
457 	char polstr[POL_STR_SIZE];
458 
459 	if ((getacpol(polstr, POL_STR_SIZE) != 0) ||
460             (au_strtopol(polstr, &policy) != 0)) {
461 		policy = AUDIT_CNT;
462 		if (auditon(A_SETPOLICY, &policy, sizeof(policy)))
463 			return (ADE_AUDITON);
464 		return (ADE_PARSE);
465         }
466 
467 	if (auditon(A_SETPOLICY, &policy, sizeof(policy)))
468 		return (ADE_AUDITON);
469 
470 	return (ADE_NOERR);
471 }
472 
473 /*
474  * Set trail rotation size.  Return:
475  *	ADE_NOERR 	on success,
476  *	ADE_PARSE	error parsing audit_control(5),
477  *	ADE_AUDITON	error setting file size using auditon(2).
478  */
479 int
480 auditd_set_fsize(void)
481 {
482 	size_t filesz;
483 	au_fstat_t au_fstat;
484 
485 	/*
486 	 * Set trail rotation size.
487 	 */
488 	if (getacfilesz(&filesz) != 0)
489 		return (ADE_PARSE);
490 
491 	bzero(&au_fstat, sizeof(au_fstat));
492 	au_fstat.af_filesz = filesz;
493 	if (auditon(A_SETFSIZE, &au_fstat, sizeof(au_fstat)) < 0)
494 		return (ADE_AUDITON);
495 
496         return (ADE_NOERR);
497 }
498 
499 /*
500  * Create the new audit file with appropriate permissions and ownership.  Try
501  * to clean up if something goes wrong.
502  */
503 static int
504 open_trail(char *fname, gid_t gid)
505 {
506 	int error, fd;
507 
508 	fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
509 	if (fd < 0)
510 		return (-1);
511 	if (fchown(fd, -1, gid) < 0) {
512 		error = errno;
513 		close(fd);
514 		(void)unlink(fname);
515 		errno = error;
516 		return (-1);
517 	}
518 	return (fd);
519 }
520 
521 /*
522  * Create the new audit trail file, swap with existing audit file.  Arguments
523  * include timestamp for the filename, a pointer to a string for returning the
524  * new file name, GID for trail file, and audit_warn function pointer for
525  * 'getacdir()' errors.  Returns:
526  *  	ADE_NOERR	on success,
527  *  	ADE_STRERR	if the file name string could not be created,
528  *  	ADE_SWAPERR	if the audit trail file could not be swapped,
529  *	ADE_ACTL 	if the auditctl(2) call failed but file swap still
530  *			successful.
531  *	ADE_ACTLERR	if the auditctl(2) call failed and file swap failed.
532  *	ADE_SYMLINK	if symlink(2) failed updating the current link.
533  */
534 int
535 auditd_swap_trail(char *TS, char **newfile, gid_t gid,
536     int (*warn_getacdir)(char *))
537 {
538 	char timestr[FILENAME_LEN];
539 	char *fn;
540 	struct dir_ent *dirent;
541 	int fd;
542 	int error;
543 	int saverrno = 0;
544 
545 	if (strlen(TS) !=  (TIMESTAMP_LEN - 1) ||
546 	    snprintf(timestr, FILENAME_LEN, "%s.%s", TS, NOT_TERMINATED) < 0) {
547 		errno = EINVAL;
548 		return (ADE_STRERR);
549 	}
550 
551 	/* Try until we succeed. */
552 	while ((dirent = TAILQ_FIRST(&dir_q))) {
553 		if (dirent->hardlim)
554 			continue;
555 		if ((fn = affixdir(timestr, dirent)) == NULL)
556 			return (ADE_STRERR);
557 
558 		/*
559 		 * Create and open the file; then close and pass to the
560 		 * kernel if all went well.
561 		 */
562 		fd = open_trail(fn, gid);
563 		if (fd >= 0) {
564 			error = auditctl(fn);
565 			if (error) {
566 				/*
567 				 * auditctl failed setting log file.
568 				 * Try again.
569 				 */
570 				saverrno = errno;
571                                 close(fd);
572                         } else {
573                                 /* Success. */
574                                 *newfile = fn;
575                                 close(fd);
576 				if (error)
577 					return (error);
578 				if (saverrno) {
579 					/*
580 					 * auditctl() failed but still
581 					 * successful. Return errno and "soft"
582 					 * error.
583 					 */
584 					errno = saverrno;
585 					return (ADE_ACTL);
586 				}
587                                 return (ADE_NOERR);
588                         }
589                 }
590 
591 		/*
592 		 * Tell the administrator about lack of permissions for dir.
593 		 */
594 		if (warn_getacdir != NULL)
595 			(*warn_getacdir)(dirent->dirname);
596 	}
597 	if (saverrno) {
598 		errno = saverrno;
599 		return (ADE_ACTLERR);
600 	} else
601 		return (ADE_SWAPERR);
602 }
603 
604 /*
605  * Mask calling process from being audited. Returns:
606  *	ADE_NOERR	on success,
607  *	ADE_SETAUDIT	if setaudit(2) fails.
608  */
609 int
610 auditd_prevent_audit(void)
611 {
612 	auditinfo_t ai;
613 
614 	/*
615 	 * To prevent event feedback cycles and avoid audit becoming stalled if
616 	 * auditing is suspended we mask this processes events from being
617 	 * audited.  We allow the uid, tid, and mask fields to be implicitly
618 	 * set to zero, but do set the audit session ID to the PID.
619 	 *
620 	 * XXXRW: Is there more to it than this?
621 	 */
622 	bzero(&ai, sizeof(ai));
623 	ai.ai_asid = getpid();
624 	if (setaudit(&ai) != 0)
625 		return (ADE_SETAUDIT);
626 	return (ADE_NOERR);
627 }
628 
629 /*
630  * Generate and submit audit record for audit startup or shutdown.  The event
631  * argument can be AUE_audit_recovery, AUE_audit_startup or
632  * AUE_audit_shutdown. The path argument will add a path token, if not NULL.
633  * Returns:
634  *	AUE_NOERR	on success,
635  *	ADE_NOMEM	if memory allocation fails,
636  * 	ADE_AU_OPEN	if au_open(3) fails,
637  *	ADE_AU_CLOSE	if au_close(3) fails.
638  */
639 int
640 auditd_gen_record(int event, char *path)
641 {
642 	int aufd;
643 	uid_t uid;
644 	pid_t pid;
645 	char *autext = NULL;
646 	token_t *tok;
647 	struct auditinfo_addr aia;
648 
649 	if (event == AUE_audit_startup)
650 		asprintf(&autext, "%s::Audit startup", getprogname());
651 	else if (event == AUE_audit_shutdown)
652 		asprintf(&autext, "%s::Audit shutdown", getprogname());
653 	else if (event == AUE_audit_recovery)
654 		asprintf(&autext, "%s::Audit recovery", getprogname());
655 	else
656 		return (ADE_INVAL);
657 	if (autext == NULL)
658 		return (ADE_NOMEM);
659 
660 	if ((aufd = au_open()) == -1) {
661 		free(autext);
662 		return (ADE_AU_OPEN);
663 	}
664 	bzero(&aia, sizeof(aia));
665 	uid = getuid(); pid = getpid();
666 	if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, getgid(),
667 	     pid, pid, &aia.ai_termid)) != NULL)
668 		au_write(aufd, tok);
669 	if ((tok = au_to_text(autext)) != NULL)
670 		au_write(aufd, tok);
671 	free(autext);
672 	if (path != NULL && (tok = au_to_path(path)) != NULL)
673 		au_write(aufd, tok);
674 	if ((tok = au_to_return32(0, 0)) != NULL)
675 		au_write(aufd, tok);
676 	if (au_close(aufd, 1, event) == -1)
677 		return (ADE_AU_CLOSE);
678 
679 	return (ADE_NOERR);
680 }
681 
682 /*
683  * Check for a 'current' symlink and do crash recovery, if needed. Create a new
684  * 'current' symlink. The argument 'curfile' is the file the 'current' symlink
685  * should point to.  Returns:
686  *	ADE_NOERR	on success,
687  *  	ADE_AU_OPEN	if au_open(3) fails,
688  *  	ADE_AU_CLOSE	if au_close(3) fails.
689  *	ADE_RENAME	if error renaming audit trail file,
690  *	ADE_READLINK	if error reading the 'current' link,
691  *	ADE_SYMLINK	if error creating 'current' link.
692  */
693 int
694 auditd_new_curlink(char *curfile)
695 {
696 	int len, err;
697 	char *ptr;
698 	char *path = NULL;
699 	struct stat sb;
700 	char recoveredname[MAXPATHLEN];
701 	char newname[MAXPATHLEN];
702 
703 	/*
704 	 * Check to see if audit was shutdown properly.  If not, clean up,
705 	 * recover previous audit trail file, and generate audit record.
706 	 */
707 	len = readlink(AUDIT_CURRENT_LINK, recoveredname, MAXPATHLEN - 1);
708 	if (len > 0) {
709 		/* 'current' exist but is it pointing at a valid file?  */
710 		recoveredname[len++] = '\0';
711 		if (stat(recoveredname, &sb) == 0) {
712 			/* Yes, rename it to a crash recovery file. */
713 			strlcpy(newname, recoveredname, MAXPATHLEN);
714 
715 			if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
716 				strlcpy(ptr, CRASH_RECOVERY, TIMESTAMP_LEN);
717 				if (rename(recoveredname, newname) != 0)
718 					return (ADE_RENAME);
719 			} else
720 				return (ADE_STRERR);
721 
722 			path = newname;
723 		}
724 
725 		/* 'current' symlink is (now) invalid so remove it. */
726 		(void) unlink(AUDIT_CURRENT_LINK);
727 
728 		/* Note the crash recovery in current audit trail */
729 		err = auditd_gen_record(AUE_audit_recovery, path);
730 		if (err)
731 			return (err);
732 	}
733 
734 	if (len < 0 && errno != ENOENT)
735 		return (ADE_READLINK);
736 
737 	if (symlink(curfile, AUDIT_CURRENT_LINK) != 0)
738 		return (ADE_SYMLINK);
739 
740 	return (0);
741 }
742 
743 /*
744  * Do just what we need to quickly start auditing.  Assume no system logging or
745  * notify.  Return:
746  *   0	 on success,
747  *  -1   on failure.
748  */
749 int
750 audit_quick_start(void)
751 {
752 	int err;
753 	char *newfile;
754 	time_t tt;
755 	char TS[TIMESTAMP_LEN];
756 
757 	/*
758 	 * Mask auditing of this process.
759 	 */
760 	if (auditd_prevent_audit() != 0)
761 		return (-1);
762 
763 	/*
764 	 * Read audit_control and get log directories.
765 	 */
766         err = auditd_read_dirs(NULL, NULL);
767 	if (err != ADE_NOERR && err != ADE_SOFTLIM)
768 		return (-1);
769 
770 	/*
771 	 *  Create a new audit trail log.
772 	 */
773 	if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
774 		return (-1);
775 	err = auditd_swap_trail(TS, &newfile, getgid(), NULL);
776 	if (err != ADE_NOERR && err != ADE_ACTL)
777 		return (-1);
778 
779 	/*
780 	 * Add the current symlink and recover from crash, if needed.
781 	 */
782 	if (auditd_new_curlink(newfile) != 0)
783 		return(-1);
784 
785 	/*
786 	 * At this point auditing has started so generate audit start-up record.
787 	 */
788 	if (auditd_gen_record(AUE_audit_startup, NULL) != 0)
789 		return (-1);
790 
791 	/*
792 	 *  Configure the audit controls.
793 	 */
794 	(void) auditd_set_evcmap();
795 	(void) auditd_set_namask();
796 	(void) auditd_set_policy();
797 	(void) auditd_set_fsize();
798 	(void) auditd_set_minfree();
799 	(void) auditd_set_host();
800 
801 	return (0);
802 }
803 
804 /*
805  * Shut down auditing quickly.  Assumes that is only called on system shutdown.
806  * Returns:
807  *	 0	on success,
808  *	-1	on failure.
809  */
810 int
811 audit_quick_stop(void)
812 {
813 	int len;
814 	long cond;
815 	char *ptr;
816 	time_t tt;
817 	char oldname[MAXPATHLEN];
818 	char newname[MAXPATHLEN];
819 	char TS[TIMESTAMP_LEN];
820 
821 	/*
822 	 * Auditing already disabled?
823 	 */
824 	if (auditon(A_GETCOND, &cond, sizeof(cond)) < 0)
825 		return (-1);
826 	if (cond == AUC_NOAUDIT)
827 		return (0);
828 
829 	/*
830 	 *  Generate audit shutdown record.
831 	 */
832 	(void) auditd_gen_record(AUE_audit_shutdown, NULL);
833 
834 	/*
835 	 * Shutdown auditing in the kernel.
836 	 */
837 	cond = AUC_DISABLED;
838 	if (auditon(A_SETCOND, &cond, sizeof(cond)) != 0)
839 		return (-1);
840 #ifdef	__BSM_INTERNAL_NOTIFY_KEY
841 	notify_post(__BSM_INTERNAL_NOTIFY_KEY);
842 #endif
843 
844 	/*
845 	 * Rename last audit trail and remove 'current' link.
846 	 */
847 	len = readlink(AUDIT_CURRENT_LINK, oldname, MAXPATHLEN - 1);
848 	if (len < 0)
849 		return (-1);
850 	oldname[len++] = '\0';
851 
852 	if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
853 		return (-1);
854 
855 	strlcpy(newname, oldname, len);
856 
857 	if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
858 		strlcpy(ptr, TS, TIMESTAMP_LEN);
859 		if (rename(oldname, newname) != 0)
860 			return (-1);
861 	} else
862 		return (-1);
863 
864 	(void) unlink(AUDIT_CURRENT_LINK);
865 
866 	return (0);
867 }
868