auditd_lib.c revision 191273
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#10 $
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
86struct dir_ent {
87	char			*dirname;
88	uint8_t			 softlim;
89	uint8_t			 hardlim;
90	TAILQ_ENTRY(dir_ent)	 dirs;
91};
92
93static TAILQ_HEAD(, dir_ent)	dir_q;
94
95struct 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
103static int auditd_minval = -1;
104
105static char auditd_host[MAXHOSTNAMELEN];
106static int auditd_hostlen = -1;
107
108static 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       25
134#define POL_STR_SIZE            128
135
136
137/*
138 * Look up and return the error string for the given audit error code.
139 */
140const char *
141auditd_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 */
155static void
156free_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 */
174static char *
175affixdir(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 */
202static void
203insert_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 */
229int
230auditd_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 */
293int
294auditd_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 */
317static int
318trailname_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 */
385int
386auditd_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	}
524
525	oldest_time = current_time - expire_age;
526
527	/*
528	 * Expire trail files, oldest (mtime) first, if the given
529	 * conditions are met.
530	 */
531	at = TAILQ_FIRST(&head);
532	while (NULL != at) {
533		struct audit_trail *at_next = TAILQ_NEXT(at, at_trls);
534
535		if (andflg) {
536			if ((expire_size && total_size > expire_size) &&
537			    (expire_age && at->at_time < oldest_time)) {
538				if (warn_expired)
539				    (*warn_expired)(at->at_path);
540				if (unlink(at->at_path) < 0)
541					ret = ADE_EXPIRE;
542				total_size -= at->at_size;
543			}
544		} else {
545			if ((expire_size && total_size > expire_size) ||
546			    (expire_age && at->at_time < oldest_time)) {
547				if (warn_expired)
548				    (*warn_expired)(at->at_path);
549				if (unlink(at->at_path) < 0)
550					ret = ADE_EXPIRE;
551				total_size -= at->at_size;
552			}
553		}
554
555		free(at->at_path);
556		free(at);
557		at = at_next;
558	}
559
560	return (ret);
561}
562
563/*
564 * Parses the "dir" entry in audit_control(5) into an ordered list.  Also, will
565 * set the minfree and host values if not already set.  Arguments include
566 * function pointers to audit_warn functions for soft and hard limits. Returns:
567 *	ADE_NOERR	on success,
568 *	ADE_PARSE	error parsing audit_control(5),
569 *	ADE_AUDITON	error getting/setting auditon(2) value,
570 *	ADE_NOMEM	error allocating memory,
571 *	ADE_SOFTLIM	if all the directories are over the soft limit,
572 *	ADE_HARDLIM	if all the directories are over the hard limit,
573 */
574int
575auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *))
576{
577	char cur_dir[MAXNAMLEN];
578	struct dir_ent *dirent;
579	struct statfs sfs;
580	int err;
581	char soft, hard;
582	int tcnt = 0;
583	int scnt = 0;
584	int hcnt = 0;
585
586	if (auditd_minval == -1 && (err = auditd_set_minfree()) != 0)
587		return (err);
588
589	if (auditd_hostlen == -1)
590		auditd_set_host();
591
592        /*
593         * Init directory q.  Force a re-read of the file the next time.
594         */
595	free_dir_q();
596	endac();
597
598	/*
599	 * Read the list of directories into an ordered linked list
600	 * admin's preference, then those over soft limit and, finally,
601	 * those over the hard limit.
602	 *
603         * XXX We should use the reentrant interfaces once they are
604         * available.
605         */
606	while (getacdir(cur_dir, MAXNAMLEN) >= 0) {
607		if (statfs(cur_dir, &sfs) < 0)
608			continue;  /* XXX should warn */
609		soft = (sfs.f_bfree < (sfs.f_blocks / (100 / auditd_minval))) ?
610		    1 : 0;
611		hard = (sfs.f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) ? 1 : 0;
612		if (soft) {
613			if (warn_soft)
614				(*warn_soft)(cur_dir);
615			scnt++;
616		}
617		if (hard) {
618			if (warn_hard)
619				(*warn_hard)(cur_dir);
620			hcnt++;
621		}
622		dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent));
623		if (dirent == NULL)
624			return (ADE_NOMEM);
625		dirent->softlim = soft;
626		dirent->hardlim = hard;
627		dirent->dirname = (char *) malloc(MAXNAMLEN);
628		if (dirent->dirname == NULL) {
629			free(dirent);
630			return (ADE_NOMEM);
631		}
632		strlcpy(dirent->dirname, cur_dir, MAXNAMLEN);
633		insert_orderly(dirent);
634		tcnt++;
635	}
636
637	if (hcnt == tcnt)
638		return (ADE_HARDLIM);
639	if (scnt == tcnt)
640		return (ADE_SOFTLIM);
641	return (0);
642}
643
644void
645auditd_close_dirs(void)
646{
647	free_dir_q();
648	auditd_minval = -1;
649	auditd_hostlen = -1;
650}
651
652
653/*
654 * Process the audit event file, obtaining a class mapping for each event, and
655 * set that mapping into the kernel. Return:
656 * 	 n	number of event mappings that were successfully processed,
657 *   ADE_NOMEM	if there was an error allocating memory.
658 */
659int
660auditd_set_evcmap(void)
661{
662	au_event_ent_t ev, *evp;
663	au_evclass_map_t evc_map;
664	int ctr = 0;
665
666
667	/*
668	 * XXX There's a risk here that the BSM library will return NULL
669	 * for an event when it can't properly map it to a class. In that
670	 * case, we will not process any events beyond the one that failed,
671	 * but should. We need a way to get a count of the events.
672	 */
673	ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
674	ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
675	if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) {
676		if (ev.ae_name != NULL)
677			free(ev.ae_name);
678		return (ADE_NOMEM);
679	}
680
681	/*
682	 * XXXRW: Currently we have no way to remove mappings from the kernel
683	 * when they are removed from the file-based mappings.
684	 */
685	evp = &ev;
686	setauevent();
687	while ((evp = getauevent_r(evp)) != NULL) {
688		evc_map.ec_number = evp->ae_number;
689		evc_map.ec_class = evp->ae_class;
690		if (audit_set_class(&evc_map, sizeof(evc_map)) == 0)
691			ctr++;
692	}
693	endauevent();
694	free(ev.ae_name);
695	free(ev.ae_desc);
696
697	return (ctr);
698}
699
700/*
701 * Get the non-attributable event string and set the kernel mask.  Return:
702 *	ADE_NOERR 	on success,
703 *	ADE_PARSE	error parsing audit_control(5),
704 *	ADE_AUDITON	error setting the mask using auditon(2).
705 */
706int
707auditd_set_namask(void)
708{
709	au_mask_t aumask;
710	char naeventstr[NA_EVENT_STR_SIZE];
711
712	if ((getacna(naeventstr, NA_EVENT_STR_SIZE) != 0) ||
713	    (getauditflagsbin(naeventstr, &aumask) != 0))
714		return (ADE_PARSE);
715
716	if (audit_set_kmask(&aumask, sizeof(aumask)) != 0)
717		return (ADE_AUDITON);
718
719	return (ADE_NOERR);
720}
721
722/*
723 * Set the audit control policy if a policy is configured in audit_control(5),
724 * implement the policy. However, if one isn't defined or if there is an error
725 * parsing the control file, set AUDIT_CNT to avoid leaving the system in a
726 * fragile state.  Return:
727 *	ADE_NOERR 	on success,
728 *	ADE_PARSE	error parsing audit_control(5),
729 *	ADE_AUDITON	error setting policy using auditon(2).
730 */
731int
732auditd_set_policy(void)
733{
734	int policy;
735	char polstr[POL_STR_SIZE];
736
737	if ((getacpol(polstr, POL_STR_SIZE) != 0) ||
738            (au_strtopol(polstr, &policy) != 0)) {
739		policy = AUDIT_CNT;
740		if (audit_set_policy(&policy) != 0)
741			return (ADE_AUDITON);
742		return (ADE_PARSE);
743        }
744
745	if (audit_set_policy(&policy) != 0)
746		return (ADE_AUDITON);
747
748	return (ADE_NOERR);
749}
750
751/*
752 * Set trail rotation size.  Return:
753 *	ADE_NOERR 	on success,
754 *	ADE_PARSE	error parsing audit_control(5),
755 *	ADE_AUDITON	error setting file size using auditon(2).
756 */
757int
758auditd_set_fsize(void)
759{
760	size_t filesz;
761	au_fstat_t au_fstat;
762
763	/*
764	 * Set trail rotation size.
765	 */
766	if (getacfilesz(&filesz) != 0)
767		return (ADE_PARSE);
768
769	bzero(&au_fstat, sizeof(au_fstat));
770	au_fstat.af_filesz = filesz;
771	if (audit_set_fsize(&au_fstat, sizeof(au_fstat)) != 0)
772		return (ADE_AUDITON);
773
774        return (ADE_NOERR);
775}
776
777/*
778 * Create the new audit file with appropriate permissions and ownership.  Try
779 * to clean up if something goes wrong.
780 */
781static int
782open_trail(char *fname, gid_t gid)
783{
784	int error, fd;
785
786	fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
787	if (fd < 0)
788		return (-1);
789	if (fchown(fd, -1, gid) < 0) {
790		error = errno;
791		close(fd);
792		(void)unlink(fname);
793		errno = error;
794		return (-1);
795	}
796	return (fd);
797}
798
799/*
800 * Create the new audit trail file, swap with existing audit file.  Arguments
801 * include timestamp for the filename, a pointer to a string for returning the
802 * new file name, GID for trail file, and audit_warn function pointer for
803 * 'getacdir()' errors.  Returns:
804 *  	ADE_NOERR	on success,
805 *  	ADE_STRERR	if the file name string could not be created,
806 *  	ADE_SWAPERR	if the audit trail file could not be swapped,
807 *	ADE_ACTL 	if the auditctl(2) call failed but file swap still
808 *			successful.
809 *	ADE_ACTLERR	if the auditctl(2) call failed and file swap failed.
810 *	ADE_SYMLINK	if symlink(2) failed updating the current link.
811 */
812int
813auditd_swap_trail(char *TS, char **newfile, gid_t gid,
814    int (*warn_getacdir)(char *))
815{
816	char timestr[FILENAME_LEN];
817	char *fn;
818	struct dir_ent *dirent;
819	int fd;
820	int error;
821	int saverrno = 0;
822
823	if (strlen(TS) !=  (TIMESTAMP_LEN - 1) ||
824	    snprintf(timestr, FILENAME_LEN, "%s.%s", TS, NOT_TERMINATED) < 0) {
825		errno = EINVAL;
826		return (ADE_STRERR);
827	}
828
829	/* Try until we succeed. */
830	TAILQ_FOREACH(dirent, &dir_q, dirs) {
831		if (dirent->hardlim)
832			continue;
833		if ((fn = affixdir(timestr, dirent)) == NULL)
834			return (ADE_STRERR);
835
836		/*
837		 * Create and open the file; then close and pass to the
838		 * kernel if all went well.
839		 */
840		fd = open_trail(fn, gid);
841		if (fd >= 0) {
842			error = auditctl(fn);
843			if (error) {
844				/*
845				 * auditctl failed setting log file.
846				 * Try again.
847				 */
848				saverrno = errno;
849                                close(fd);
850                        } else {
851                                /* Success. */
852                                *newfile = fn;
853                                close(fd);
854				if (error)
855					return (error);
856				if (saverrno) {
857					/*
858					 * auditctl() failed but still
859					 * successful. Return errno and "soft"
860					 * error.
861					 */
862					errno = saverrno;
863					return (ADE_ACTL);
864				}
865                                return (ADE_NOERR);
866                        }
867                }
868
869		/*
870		 * Tell the administrator about lack of permissions for dir.
871		 */
872		if (warn_getacdir != NULL)
873			(*warn_getacdir)(dirent->dirname);
874	}
875	if (saverrno) {
876		errno = saverrno;
877		return (ADE_ACTLERR);
878	} else
879		return (ADE_SWAPERR);
880}
881
882/*
883 * Mask calling process from being audited. Returns:
884 *	ADE_NOERR	on success,
885 *	ADE_SETAUDIT	if setaudit(2) fails.
886 */
887#ifdef __APPLE__
888int
889auditd_prevent_audit(void)
890{
891	auditinfo_addr_t aia;
892
893	/*
894	 * To prevent event feedback cycles and avoid audit becoming stalled if
895	 * auditing is suspended we mask this processes events from being
896	 * audited.  We allow the uid, tid, and mask fields to be implicitly
897	 * set to zero, but do set the audit session ID to the PID.
898	 *
899	 * XXXRW: Is there more to it than this?
900	 */
901	bzero(&aia, sizeof(aia));
902	aia.ai_asid = AU_ASSIGN_ASID;
903	aia.ai_termid.at_type = AU_IPv4;
904	if (setaudit_addr(&aia, sizeof(aia)) != 0)
905		return (ADE_SETAUDIT);
906	return (ADE_NOERR);
907}
908#else
909int
910auditd_prevent_audit(void)
911{
912	auditinfo_t ai;
913
914	/*
915	 * To prevent event feedback cycles and avoid audit becoming stalled if
916	 * auditing is suspended we mask this processes events from being
917	 * audited.  We allow the uid, tid, and mask fields to be implicitly
918	 * set to zero, but do set the audit session ID to the PID.
919	 *
920	 * XXXRW: Is there more to it than this?
921	 */
922	bzero(&ai, sizeof(ai));
923	ai.ai_asid = getpid();
924	if (setaudit(&ai) != 0)
925		return (ADE_SETAUDIT);
926	return (ADE_NOERR);
927}
928#endif /* __APPLE__ */
929
930/*
931 * Generate and submit audit record for audit startup or shutdown.  The event
932 * argument can be AUE_audit_recovery, AUE_audit_startup or
933 * AUE_audit_shutdown. The path argument will add a path token, if not NULL.
934 * Returns:
935 *	AUE_NOERR	on success,
936 *	ADE_NOMEM	if memory allocation fails,
937 * 	ADE_AU_OPEN	if au_open(3) fails,
938 *	ADE_AU_CLOSE	if au_close(3) fails.
939 */
940int
941auditd_gen_record(int event, char *path)
942{
943	int aufd;
944	uid_t uid;
945	pid_t pid;
946	char *autext = NULL;
947	token_t *tok;
948	struct auditinfo_addr aia;
949
950	if (event == AUE_audit_startup)
951		asprintf(&autext, "%s::Audit startup", getprogname());
952	else if (event == AUE_audit_shutdown)
953		asprintf(&autext, "%s::Audit shutdown", getprogname());
954	else if (event == AUE_audit_recovery)
955		asprintf(&autext, "%s::Audit recovery", getprogname());
956	else
957		return (ADE_INVAL);
958	if (autext == NULL)
959		return (ADE_NOMEM);
960
961	if ((aufd = au_open()) == -1) {
962		free(autext);
963		return (ADE_AU_OPEN);
964	}
965	bzero(&aia, sizeof(aia));
966	uid = getuid(); pid = getpid();
967	if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, getgid(),
968	     pid, pid, &aia.ai_termid)) != NULL)
969		au_write(aufd, tok);
970	if ((tok = au_to_text(autext)) != NULL)
971		au_write(aufd, tok);
972	free(autext);
973	if (path != NULL && (tok = au_to_path(path)) != NULL)
974		au_write(aufd, tok);
975	if ((tok = au_to_return32(0, 0)) != NULL)
976		au_write(aufd, tok);
977	if (au_close(aufd, 1, event) == -1)
978		return (ADE_AU_CLOSE);
979
980	return (ADE_NOERR);
981}
982
983/*
984 * Check for a 'current' symlink and do crash recovery, if needed. Create a new
985 * 'current' symlink. The argument 'curfile' is the file the 'current' symlink
986 * should point to.  Returns:
987 *	ADE_NOERR	on success,
988 *  	ADE_AU_OPEN	if au_open(3) fails,
989 *  	ADE_AU_CLOSE	if au_close(3) fails.
990 *	ADE_RENAME	if error renaming audit trail file,
991 *	ADE_READLINK	if error reading the 'current' link,
992 *	ADE_SYMLINK	if error creating 'current' link.
993 */
994int
995auditd_new_curlink(char *curfile)
996{
997	int len, err;
998	char *ptr;
999	char *path = NULL;
1000	struct stat sb;
1001	char recoveredname[MAXPATHLEN];
1002	char newname[MAXPATHLEN];
1003
1004	/*
1005	 * Check to see if audit was shutdown properly.  If not, clean up,
1006	 * recover previous audit trail file, and generate audit record.
1007	 */
1008	len = readlink(AUDIT_CURRENT_LINK, recoveredname, MAXPATHLEN - 1);
1009	if (len > 0) {
1010		/* 'current' exist but is it pointing at a valid file?  */
1011		recoveredname[len++] = '\0';
1012		if (stat(recoveredname, &sb) == 0) {
1013			/* Yes, rename it to a crash recovery file. */
1014			strlcpy(newname, recoveredname, MAXPATHLEN);
1015
1016			if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
1017				memcpy(ptr, CRASH_RECOVERY, POSTFIX_LEN);
1018				if (rename(recoveredname, newname) != 0)
1019					return (ADE_RENAME);
1020			} else
1021				return (ADE_STRERR);
1022
1023			path = newname;
1024		}
1025
1026		/* 'current' symlink is (now) invalid so remove it. */
1027		(void) unlink(AUDIT_CURRENT_LINK);
1028
1029		/* Note the crash recovery in current audit trail */
1030		err = auditd_gen_record(AUE_audit_recovery, path);
1031		if (err)
1032			return (err);
1033	}
1034
1035	if (len < 0 && errno != ENOENT)
1036		return (ADE_READLINK);
1037
1038	if (symlink(curfile, AUDIT_CURRENT_LINK) != 0)
1039		return (ADE_SYMLINK);
1040
1041	return (0);
1042}
1043
1044/*
1045 * Do just what we need to quickly start auditing.  Assume no system logging or
1046 * notify.  Return:
1047 *   0	 on success,
1048 *  -1   on failure.
1049 */
1050int
1051audit_quick_start(void)
1052{
1053	int err;
1054	char *newfile = NULL;
1055	time_t tt;
1056	char TS[TIMESTAMP_LEN];
1057	int ret = 0;
1058
1059	/*
1060	 * Mask auditing of this process.
1061	 */
1062	if (auditd_prevent_audit() != 0)
1063		return (-1);
1064
1065	/*
1066	 * Read audit_control and get log directories.
1067	 */
1068        err = auditd_read_dirs(NULL, NULL);
1069	if (err != ADE_NOERR && err != ADE_SOFTLIM)
1070		return (-1);
1071
1072	/*
1073	 *  Create a new audit trail log.
1074	 */
1075	if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
1076		return (-1);
1077	err = auditd_swap_trail(TS, &newfile, getgid(), NULL);
1078	if (err != ADE_NOERR && err != ADE_ACTL) {
1079		ret = -1;
1080		goto out;
1081	}
1082
1083	/*
1084	 * Add the current symlink and recover from crash, if needed.
1085	 */
1086	if (auditd_new_curlink(newfile) != 0) {
1087		ret = -1;
1088		goto out;
1089	}
1090
1091	/*
1092	 * At this point auditing has started so generate audit start-up record.
1093	 */
1094	if (auditd_gen_record(AUE_audit_startup, NULL) != 0) {
1095		ret = -1;
1096		goto out;
1097	}
1098
1099	/*
1100	 *  Configure the audit controls.
1101	 */
1102	(void) auditd_set_evcmap();
1103	(void) auditd_set_namask();
1104	(void) auditd_set_policy();
1105	(void) auditd_set_fsize();
1106	(void) auditd_set_minfree();
1107	(void) auditd_set_host();
1108
1109out:
1110	if (newfile != NULL)
1111		free(newfile);
1112
1113	return (ret);
1114}
1115
1116/*
1117 * Shut down auditing quickly.  Assumes that is only called on system shutdown.
1118 * Returns:
1119 *	 0	on success,
1120 *	-1	on failure.
1121 */
1122int
1123audit_quick_stop(void)
1124{
1125	int len;
1126	int cond;
1127	char *ptr;
1128	time_t tt;
1129	char oldname[MAXPATHLEN];
1130	char newname[MAXPATHLEN];
1131	char TS[TIMESTAMP_LEN];
1132
1133	/*
1134	 * Auditing already disabled?
1135	 */
1136	if (audit_get_cond(&cond) != 0)
1137		return (-1);
1138	if (cond == AUC_NOAUDIT)
1139		return (0);
1140
1141	/*
1142	 *  Generate audit shutdown record.
1143	 */
1144	(void) auditd_gen_record(AUE_audit_shutdown, NULL);
1145
1146	/*
1147	 * Shutdown auditing in the kernel.
1148	 */
1149	cond = AUC_DISABLED;
1150	if (audit_set_cond(&cond) != 0)
1151		return (-1);
1152#ifdef	__BSM_INTERNAL_NOTIFY_KEY
1153	notify_post(__BSM_INTERNAL_NOTIFY_KEY);
1154#endif
1155
1156	/*
1157	 * Rename last audit trail and remove 'current' link.
1158	 */
1159	len = readlink(AUDIT_CURRENT_LINK, oldname, MAXPATHLEN - 1);
1160	if (len < 0)
1161		return (-1);
1162	oldname[len++] = '\0';
1163
1164	if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
1165		return (-1);
1166
1167	strlcpy(newname, oldname, len);
1168
1169	if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
1170		memcpy(ptr, TS, POSTFIX_LEN);
1171		if (rename(oldname, newname) != 0)
1172			return (-1);
1173	} else
1174		return (-1);
1175
1176	(void) unlink(AUDIT_CURRENT_LINK);
1177
1178	return (0);
1179}
1180