xref: /illumos-gate/usr/src/cmd/auditd/auditd.c (revision bbf215553c7233fbab8a0afdf1fac74c44781867)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
59697ae98Sgww  * Common Development and Distribution License (the "License").
69697ae98Sgww  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22f8994074SJan Friedel  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /* Audit daemon server */
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * These routines make up the audit daemon server.  This daemon, called
287c478bd9Sstevel@tonic-gate  * auditd, handles the user level parts of auditing.  It receives buffered
297c478bd9Sstevel@tonic-gate  * audit records (usually one or more per buffer, potentially less than
307c478bd9Sstevel@tonic-gate  * one) and passes them to one or more plugins for processing.
317c478bd9Sstevel@tonic-gate  *
32f8994074SJan Friedel  * The major interrupts are SIGHUP (start over), SIGTERM (start shutting down),
33f8994074SJan Friedel  * SIGALRM (quit), and SIGUSR1 (start a new audit log file). SIGTERM is also
34f8994074SJan Friedel  * used for the child to tell the parent that audit is ready.
357c478bd9Sstevel@tonic-gate  *
36f8994074SJan Friedel  * Configuration data comes from audit service configuration
37*bbf21555SRichard Lowe  * (AUDITD_FMRI/smf(7)) and the auditon system call.
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  * The major errors are EBUSY (auditing is already in use) and EINTR
407c478bd9Sstevel@tonic-gate  * (one of the above signals was received).  File space errors are
417c478bd9Sstevel@tonic-gate  * handled by the audit_binfile plugin
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate 
448523fda3SJan Friedel /* #define	DEBUG    - define for debug messages to be generated */
458523fda3SJan Friedel /* #define	MEM_TEST - define to generate core dump on exit */
467c478bd9Sstevel@tonic-gate #define	DEBUG		0
478523fda3SJan Friedel #define	MEM_TEST	0
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #include <assert.h>
509697ae98Sgww #include <bsm/adt.h>
517c478bd9Sstevel@tonic-gate #include <bsm/audit.h>
527c478bd9Sstevel@tonic-gate #include <bsm/audit_record.h>
537c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
547c478bd9Sstevel@tonic-gate #include <fcntl.h>
557c478bd9Sstevel@tonic-gate #include <libintl.h>
567c478bd9Sstevel@tonic-gate #include <locale.h>
577c478bd9Sstevel@tonic-gate #include <netdb.h>
587c478bd9Sstevel@tonic-gate #include <pwd.h>
597c478bd9Sstevel@tonic-gate #include <secdb.h>
607c478bd9Sstevel@tonic-gate #include <signal.h>
617c478bd9Sstevel@tonic-gate #include <stdio.h>
627c478bd9Sstevel@tonic-gate #include <stdlib.h>
637c478bd9Sstevel@tonic-gate #include <string.h>
649697ae98Sgww #include <syslog.h>
657c478bd9Sstevel@tonic-gate #include <errno.h>
667c478bd9Sstevel@tonic-gate #include <sys/file.h>
677c478bd9Sstevel@tonic-gate #include <sys/param.h>
687c478bd9Sstevel@tonic-gate #include <sys/stat.h>
697c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
707c478bd9Sstevel@tonic-gate #include <sys/time.h>
717c478bd9Sstevel@tonic-gate #include <sys/types.h>
727c478bd9Sstevel@tonic-gate #include <sys/wait.h>
737c478bd9Sstevel@tonic-gate #include <termios.h>
747c478bd9Sstevel@tonic-gate #include <unistd.h>
757c478bd9Sstevel@tonic-gate #include "plugin.h"
767c478bd9Sstevel@tonic-gate #include <audit_plugin.h>
778523fda3SJan Friedel #include <audit_scf.h>
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
807c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
817c478bd9Sstevel@tonic-gate #endif
827c478bd9Sstevel@tonic-gate /*
83f8994074SJan Friedel  * After we get a SIGTERM, we want to set a timer for 2 seconds
847c478bd9Sstevel@tonic-gate  * and let c2audit write as many records as it can until the timer
85f8994074SJan Friedel  * goes off (at which point it returns to auditd with SIGALRM).
86f8994074SJan Friedel  * If any other signals are received during that time, we call
877c478bd9Sstevel@tonic-gate  * __audit_dowarn() to indicate that the queue may not have been fully
887c478bd9Sstevel@tonic-gate  * flushed.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate #define	ALRM_TIME	2
917c478bd9Sstevel@tonic-gate #define	SLEEP_TIME	20	/* # of seconds to sleep in all hard loop */
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate static plugin_t	*binfile = NULL;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate static int	turn_audit_on  = AUC_AUDITING;
967c478bd9Sstevel@tonic-gate static int	turn_audit_off = AUC_NOAUDIT;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate static int	running = 1;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * GLOBALS:
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate plugin_t		*plugin_head = NULL;
1047c478bd9Sstevel@tonic-gate static thr_data_t	main_thr;	/* auditd thread (0) */
1057c478bd9Sstevel@tonic-gate pthread_mutex_t		plugin_mutex;	/* for plugin_t list */
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate static int	caught_alrm = 0;	/* number of SIGALRMs pending */
108f8994074SJan Friedel static int	caught_readc = 0;	/* number of SIGHUPs pending */
109f8994074SJan Friedel static int	caught_term = 0;	/* number of SIGTERMs pending */
110f8994074SJan Friedel static int	caught_nextd = 0;	/* number of SIGUSR1s pending */
1117c478bd9Sstevel@tonic-gate 
112f8994074SJan Friedel static int	reset_list = 1;	/* 1 to re-read audit configuration */
1137c478bd9Sstevel@tonic-gate static int	reset_file = 1; /* 1 to close/open binary log */
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate static int	auditing_set = 0;	/* 1 if auditon(A_SETCOND, on... */
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate static void	my_sleep();
118d6beba26SToomas Soome static void	*signal_thread(void *);
1197c478bd9Sstevel@tonic-gate static void	loadauditlist();
1207c478bd9Sstevel@tonic-gate static void	block_signals();
1217c478bd9Sstevel@tonic-gate static int	do_sethost();
1227c478bd9Sstevel@tonic-gate 
1238523fda3SJan Friedel static void	conf_to_kernel();
1248523fda3SJan Friedel static void	scf_to_kernel_qctrl();
1258523fda3SJan Friedel static void	scf_to_kernel_policy();
1268523fda3SJan Friedel 
1278523fda3SJan Friedel /*
1288523fda3SJan Friedel  * err_exit() - exit function after the unsuccessful call to auditon();
1298523fda3SJan Friedel  * prints_out / saves_via_syslog the necessary error messages.
1308523fda3SJan Friedel  */
1318523fda3SJan Friedel static void
err_exit(char * msg)13217b6b380SJan Friedel err_exit(char *msg)
1338523fda3SJan Friedel {
1348523fda3SJan Friedel 	if (msg != NULL) {
1358523fda3SJan Friedel 		DPRINT((dbfp, "%s\n", msg));
1368523fda3SJan Friedel 		__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT,
1378523fda3SJan Friedel 		    LOG_DAEMON, LOG_ALERT, msg);
1388523fda3SJan Friedel 		free(msg);
1398523fda3SJan Friedel 	} else {
1408523fda3SJan Friedel 		DPRINT((dbfp, "the memory allocation failed\n"));
1418523fda3SJan Friedel 		__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT,
1428523fda3SJan Friedel 		    LOG_DAEMON, LOG_ALERT, gettext("no memory"));
1438523fda3SJan Friedel 	}
1448523fda3SJan Friedel 	auditd_thread_close();
14517b6b380SJan Friedel 	auditd_exit(1);
1468523fda3SJan Friedel }
1478523fda3SJan Friedel 
1487c478bd9Sstevel@tonic-gate /* common exit function */
1497c478bd9Sstevel@tonic-gate void
auditd_exit(int status)1507c478bd9Sstevel@tonic-gate auditd_exit(int status)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate #if MEM_TEST
1537c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "mem_test intentional abort (status=%d)\n",
1547c478bd9Sstevel@tonic-gate 	    status));
1557c478bd9Sstevel@tonic-gate 	abort();
1567c478bd9Sstevel@tonic-gate #endif
1577c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "%ld exit status = %d auditing_set = %d\n",
1587c478bd9Sstevel@tonic-gate 	    getpid(), status, auditing_set));
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	if (auditing_set)
1617c478bd9Sstevel@tonic-gate 		(void) auditon(A_SETCOND, (caddr_t)&turn_audit_off,
162f8994074SJan Friedel 		    sizeof (int));
1637c478bd9Sstevel@tonic-gate 
1648523fda3SJan Friedel #if DEBUG
1658523fda3SJan Friedel 	(void) fclose(dbfp);
1668523fda3SJan Friedel #endif
1678523fda3SJan Friedel 
1687c478bd9Sstevel@tonic-gate 	exit(status);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /* ARGSUSED */
1727883e825Spaulson int
main(int argc,char * argv[])1737c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	auditinfo_addr_t	as_null;	/* audit state to set */
1767c478bd9Sstevel@tonic-gate 	au_id_t			auid;
1777c478bd9Sstevel@tonic-gate 	pthread_t		tid;
1787c478bd9Sstevel@tonic-gate 	plugin_t		*p;
1797c478bd9Sstevel@tonic-gate 	pid_t			pid;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate #if DEBUG
182dfc7be02SJan Friedel #if MEM_TEST
1837c478bd9Sstevel@tonic-gate 	char	*envp;
184dfc7be02SJan Friedel #endif
1858523fda3SJan Friedel 	if (dbfp == NULL) {
1867c478bd9Sstevel@tonic-gate 		dbfp = __auditd_debug_file_open();
1878523fda3SJan Friedel 	}
1887c478bd9Sstevel@tonic-gate #endif
1897c478bd9Sstevel@tonic-gate 	(void) setsid();
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/* Internationalization */
1927c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1937c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	/*
1967c478bd9Sstevel@tonic-gate 	 * Set the audit host-id.
1977c478bd9Sstevel@tonic-gate 	 */
1987c478bd9Sstevel@tonic-gate 	if (do_sethost() != 0) {
1997c478bd9Sstevel@tonic-gate 		__audit_dowarn("nostart", "", 0);
2007c478bd9Sstevel@tonic-gate 		auditd_exit(1);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/*
2047c478bd9Sstevel@tonic-gate 	 * Turn off all auditing for this process.
2057c478bd9Sstevel@tonic-gate 	 */
2067c478bd9Sstevel@tonic-gate 	if (getaudit_addr(&as_null, sizeof (as_null)) == -1) {
2077c478bd9Sstevel@tonic-gate 		__audit_dowarn("nostart", "", 0);
20817b6b380SJan Friedel 		auditd_exit(1);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 	as_null.ai_mask.as_success = 0;
2117c478bd9Sstevel@tonic-gate 	as_null.ai_mask.as_failure = 0;
2127c478bd9Sstevel@tonic-gate 	(void) setaudit_addr(&as_null, sizeof (as_null));
2137c478bd9Sstevel@tonic-gate 	auid = AU_NOAUDITID;
2147c478bd9Sstevel@tonic-gate 	(void) setauid(&auid);
2157c478bd9Sstevel@tonic-gate 	/*
2167c478bd9Sstevel@tonic-gate 	 * Set the audit state flag to AUDITING.
2177c478bd9Sstevel@tonic-gate 	 */
218f8994074SJan Friedel 	if (auditon(A_SETCOND, (caddr_t)&turn_audit_on, sizeof (int)) !=
2197c478bd9Sstevel@tonic-gate 	    0) {
2207c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "auditon(A_SETCOND...) failed (exit)\n"));
2217c478bd9Sstevel@tonic-gate 		__audit_dowarn("nostart", "", 0);
22217b6b380SJan Friedel 		auditd_exit(1);
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	block_signals();
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/*
2287c478bd9Sstevel@tonic-gate 	 * wait for "ready" signal before exit -- for greenline
2297c478bd9Sstevel@tonic-gate 	 */
2307c478bd9Sstevel@tonic-gate 	if (fork()) {
2317c478bd9Sstevel@tonic-gate 		sigset_t	set;
2327c478bd9Sstevel@tonic-gate 		int		signal_caught = 0;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&set);
235f8994074SJan Friedel 		(void) sigaddset(&set, SIGTERM);
2367c478bd9Sstevel@tonic-gate 
237f8994074SJan Friedel 		while (signal_caught != SIGTERM)
2387c478bd9Sstevel@tonic-gate 			signal_caught = sigwait(&set);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "init complete:  parent can now exit\n"));
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		auditd_exit(0);
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 	pid = getppid();
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	auditing_set = 1;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate #if DEBUG && MEM_TEST
2497c478bd9Sstevel@tonic-gate 	envp = getenv("UMEM_DEBUG");
2507c478bd9Sstevel@tonic-gate 	if (envp != NULL)
2517c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "UMEM_DEBUG=%s\n", envp));
2527c478bd9Sstevel@tonic-gate 	envp = getenv("UMEM_LOGGING");
2537c478bd9Sstevel@tonic-gate 	if (envp != NULL)
2547c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "UMEM_LOGGING=%s\n", envp));
2557c478bd9Sstevel@tonic-gate #endif
2567c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "auditd pid=%ld\n", getpid()));
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/* thread 0 sync */
2597c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&(main_thr.thd_mutex), NULL);
2607c478bd9Sstevel@tonic-gate 	(void) pthread_cond_init(&(main_thr.thd_cv), NULL);
2617c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&plugin_mutex, NULL);
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	 * Set up a separate thread for signal handling.
2647c478bd9Sstevel@tonic-gate 	 */
265d6beba26SToomas Soome 	if (pthread_create(&tid, NULL, signal_thread, NULL)) {
2667c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
2677c478bd9Sstevel@tonic-gate 		    "auditd can't create a thread\n"));
26817b6b380SJan Friedel 		auditd_exit(1);
2697c478bd9Sstevel@tonic-gate 	}
2707c478bd9Sstevel@tonic-gate 	/*
2717c478bd9Sstevel@tonic-gate 	 * Set the umask so that only audit or other users in the audit group
2727c478bd9Sstevel@tonic-gate 	 * can get to the files created by auditd.
2737c478bd9Sstevel@tonic-gate 	 */
2747c478bd9Sstevel@tonic-gate 	(void) umask(007);
2757c478bd9Sstevel@tonic-gate 
276*bbf21555SRichard Lowe 	if (__logpost("")) {	/* Cannot unlink pointer to audit.log(5) file */
2777c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "logpost failed\n"));
27817b6b380SJan Friedel 		auditd_exit(1);
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 	/*
2817c478bd9Sstevel@tonic-gate 	 * Here is the main body of the audit daemon. running == 0 means that
282f8994074SJan Friedel 	 * after flushing out the audit queue, it is time to exit in response
283f8994074SJan Friedel 	 * to SIGTERM.
2847c478bd9Sstevel@tonic-gate 	 */
2857c478bd9Sstevel@tonic-gate 	while (running) {
2867c478bd9Sstevel@tonic-gate 		/*
287f8994074SJan Friedel 		 * Read auditd / auditd plugins related configuration from
288*bbf21555SRichard Lowe 		 * smf(7) repository and create plugin lists.
2897c478bd9Sstevel@tonic-gate 		 *
2907c478bd9Sstevel@tonic-gate 		 * loadauditlist() and auditd_thread_init() are called
2917c478bd9Sstevel@tonic-gate 		 * while under the plugin_mutex lock to avoid a race
2927c478bd9Sstevel@tonic-gate 		 * with unload_plugin().
2937c478bd9Sstevel@tonic-gate 		 */
2947c478bd9Sstevel@tonic-gate 		if (reset_list || reset_file) {
2958523fda3SJan Friedel 			if (reset_list) {
2968523fda3SJan Friedel 				conf_to_kernel();
2978523fda3SJan Friedel 				scf_to_kernel_qctrl();
2988523fda3SJan Friedel 				scf_to_kernel_policy();
2997c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_lock(&plugin_mutex);
3007c478bd9Sstevel@tonic-gate 				loadauditlist();
3018523fda3SJan Friedel 			} else {
3028523fda3SJan Friedel 				(void) pthread_mutex_lock(&plugin_mutex);
3038523fda3SJan Friedel 			}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 			if (auditd_thread_init()) {
3067c478bd9Sstevel@tonic-gate 				auditd_thread_close();
3077c478bd9Sstevel@tonic-gate 				/* continue; wait for audit -s */
3087c478bd9Sstevel@tonic-gate 			}
3097c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&plugin_mutex);
3108523fda3SJan Friedel 
3118523fda3SJan Friedel 			if (reset_list && reset_file) {
3128523fda3SJan Friedel 				(void) printf(gettext("auditd started\n"));
3138523fda3SJan Friedel 			} else {
3148523fda3SJan Friedel 				(void) printf(gettext("auditd refreshed\n"));
3158523fda3SJan Friedel 			}
316f8994074SJan Friedel 
317f8994074SJan Friedel 			reset_list = 0;
318f8994074SJan Friedel 			reset_file = 0;
3197c478bd9Sstevel@tonic-gate 		}
3207c478bd9Sstevel@tonic-gate 		/*
3217c478bd9Sstevel@tonic-gate 		 * tell parent I'm running whether or not the initialization
3227c478bd9Sstevel@tonic-gate 		 * actually worked.  The failure case is to wait for an
3237c478bd9Sstevel@tonic-gate 		 * audit -n or audit -s to fix the problem.
3247c478bd9Sstevel@tonic-gate 		 */
3257c478bd9Sstevel@tonic-gate 		if (pid != 0) {
326f8994074SJan Friedel 			(void) kill(pid, SIGTERM);
3277c478bd9Sstevel@tonic-gate 			pid = 0;
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 		/*
3307c478bd9Sstevel@tonic-gate 		 * thread_signal() signals main (this thread) when
3317c478bd9Sstevel@tonic-gate 		 * it has received a signal.
3327c478bd9Sstevel@tonic-gate 		 */
333f8994074SJan Friedel 		DPRINT((dbfp, "main thread is waiting for signal\n"));
3347c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&(main_thr.thd_mutex));
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		if (!(caught_readc || caught_term || caught_alrm ||
3377c478bd9Sstevel@tonic-gate 		    caught_nextd))
3387c478bd9Sstevel@tonic-gate 			(void) pthread_cond_wait(&(main_thr.thd_cv),
3397c478bd9Sstevel@tonic-gate 			    &(main_thr.thd_mutex));
3407c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
3417c478bd9Sstevel@tonic-gate 		/*
3427c478bd9Sstevel@tonic-gate 		 * Got here because a signal came in.
3437c478bd9Sstevel@tonic-gate 		 * Since we may have gotten more than one, we assume a
3447c478bd9Sstevel@tonic-gate 		 * priority scheme with SIGALRM being the most
3457c478bd9Sstevel@tonic-gate 		 * significant.
3467c478bd9Sstevel@tonic-gate 		 */
3477c478bd9Sstevel@tonic-gate 		if (caught_alrm) {
3487c478bd9Sstevel@tonic-gate 			/*
3497c478bd9Sstevel@tonic-gate 			 * We have returned from our timed wait for
3507c478bd9Sstevel@tonic-gate 			 * c2audit to calm down.  We need to really shut
3517c478bd9Sstevel@tonic-gate 			 * down here.
3527c478bd9Sstevel@tonic-gate 			 */
3537c478bd9Sstevel@tonic-gate 			caught_alrm = 0;
3547c478bd9Sstevel@tonic-gate 			running = 0;	/* shut down now */
3557c478bd9Sstevel@tonic-gate 		} else if (caught_term) {
3567c478bd9Sstevel@tonic-gate 			/*
3577c478bd9Sstevel@tonic-gate 			 * we are going to shut down, but need to
3587c478bd9Sstevel@tonic-gate 			 * allow time for the audit queues in
3597c478bd9Sstevel@tonic-gate 			 * c2audit and for the threads to empty.
3607c478bd9Sstevel@tonic-gate 			 */
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 			p = plugin_head;
3637c478bd9Sstevel@tonic-gate 			while (p != NULL) {
3647c478bd9Sstevel@tonic-gate 				DPRINT((dbfp, "signalling thread %d\n",
3657c478bd9Sstevel@tonic-gate 				    p->plg_tid));
3667c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_lock(&(p->plg_mutex));
3677c478bd9Sstevel@tonic-gate 				p->plg_removed = 1;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 				if (p->plg_initialized)
3707c478bd9Sstevel@tonic-gate 					(void) pthread_cond_signal(
3717c478bd9Sstevel@tonic-gate 					    &(p->plg_cv));
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock(&(p->plg_mutex));
3747c478bd9Sstevel@tonic-gate 				p = p->plg_next;
3757c478bd9Sstevel@tonic-gate 			}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 			caught_alrm = 0;
3787c478bd9Sstevel@tonic-gate 			caught_readc  = 0;
3797c478bd9Sstevel@tonic-gate 			caught_term = 0;
3807c478bd9Sstevel@tonic-gate 			caught_nextd = 0;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 			DPRINT((dbfp,
3837c478bd9Sstevel@tonic-gate 			    "main thread is pausing before exit.\n"));
3847c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&(main_thr.thd_mutex));
3857c478bd9Sstevel@tonic-gate 			caught_alrm = 0;
3867c478bd9Sstevel@tonic-gate 			(void) alarm(ALRM_TIME);
3877c478bd9Sstevel@tonic-gate 			while (!caught_alrm)
3887c478bd9Sstevel@tonic-gate 				(void) pthread_cond_wait(&(main_thr.thd_cv),
3897c478bd9Sstevel@tonic-gate 				    &(main_thr.thd_mutex));
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 			running = 0;	/* Close down auditing and exit */
3947c478bd9Sstevel@tonic-gate 		} else if (caught_readc) {
3957c478bd9Sstevel@tonic-gate 			/*
3967c478bd9Sstevel@tonic-gate 			 * if both hup and usr1 are caught, the logic in
3977c478bd9Sstevel@tonic-gate 			 * loadauditlist() results in hup winning.  The
3987c478bd9Sstevel@tonic-gate 			 * result will be that the audit file is not rolled
399f8994074SJan Friedel 			 * over unless audit configuration actually changed.
4007c478bd9Sstevel@tonic-gate 			 *
401f8994074SJan Friedel 			 * They want to reread the audit configuration from
402*bbf21555SRichard Lowe 			 * smf(7) repository (AUDITD_FMRI). Set reset_list
403f8994074SJan Friedel 			 * which will return us to the main while loop in the
404f8994074SJan Friedel 			 * main routine.
4057c478bd9Sstevel@tonic-gate 			 */
4067c478bd9Sstevel@tonic-gate 			caught_readc = 0;
4077c478bd9Sstevel@tonic-gate 			reset_list = 1;
4087c478bd9Sstevel@tonic-gate 		} else if (caught_nextd) {
4097c478bd9Sstevel@tonic-gate 			/*
410f8994074SJan Friedel 			 * This is a special case for the binfile plugin.
411f8994074SJan Friedel 			 * (audit -n)  NULL out kvlist so binfile won't
412f8994074SJan Friedel 			 * re-read audit configuration.
4137c478bd9Sstevel@tonic-gate 			 */
4147c478bd9Sstevel@tonic-gate 			caught_nextd = 0;
4157c478bd9Sstevel@tonic-gate 			reset_file = 1;
4167c478bd9Sstevel@tonic-gate 			if (binfile != NULL) {
4177c478bd9Sstevel@tonic-gate 				_kva_free(binfile->plg_kvlist);
4187c478bd9Sstevel@tonic-gate 				binfile->plg_kvlist = NULL;
4197c478bd9Sstevel@tonic-gate 				binfile->plg_reopen = 1;
4207c478bd9Sstevel@tonic-gate 			}
4217c478bd9Sstevel@tonic-gate 		}
4227c478bd9Sstevel@tonic-gate 	}	/* end while (running) */
4237c478bd9Sstevel@tonic-gate 	auditd_thread_close();
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	auditd_exit(0);
4267c478bd9Sstevel@tonic-gate 	return (0);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate  * my_sleep - sleep for SLEEP_TIME seconds but only accept the signals
4317c478bd9Sstevel@tonic-gate  *	that we want to accept.  (Premature termination just means the
4327c478bd9Sstevel@tonic-gate  *	caller retries more often, not a big deal.)
4337c478bd9Sstevel@tonic-gate  */
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate static void
my_sleep()4367c478bd9Sstevel@tonic-gate my_sleep()
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "auditd: sleeping for 20 seconds\n"));
4397c478bd9Sstevel@tonic-gate 	/*
4407c478bd9Sstevel@tonic-gate 	 * Set timer to "sleep"
4417c478bd9Sstevel@tonic-gate 	 */
4427c478bd9Sstevel@tonic-gate 	(void) alarm(SLEEP_TIME);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "main thread is waiting for SIGALRM before exit.\n"));
4457c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&(main_thr.thd_mutex));
4467c478bd9Sstevel@tonic-gate 	(void) pthread_cond_wait(&(main_thr.thd_cv), &(main_thr.thd_mutex));
4477c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	if (caught_term) {
450f8994074SJan Friedel 		DPRINT((dbfp, "normal SIGTERM exit\n"));
4517c478bd9Sstevel@tonic-gate 		/*
4527c478bd9Sstevel@tonic-gate 		 * Exit, as requested.
4537c478bd9Sstevel@tonic-gate 		 */
4547c478bd9Sstevel@tonic-gate 		auditd_thread_close();
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate 	if (caught_readc)
457f8994074SJan Friedel 		reset_list = 1;		/* Reread the audit configuration */
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	caught_readc = 0;
4607c478bd9Sstevel@tonic-gate 	caught_nextd = 0;
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate  * search for $ISA/ in path and replace it with "" if auditd
4657c478bd9Sstevel@tonic-gate  * is 32 bit, else "sparcv9/"  The plugin $ISA must match however
4667c478bd9Sstevel@tonic-gate  * auditd was compiled.
4677c478bd9Sstevel@tonic-gate  */
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate static void
isa_ified(char * path,char ** newpath)4707c478bd9Sstevel@tonic-gate isa_ified(char *path, char **newpath)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	char	*p, *q;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	if (((p = strchr(path, '$')) != NULL) &&
4757c478bd9Sstevel@tonic-gate 	    (strncmp("$ISA/", p, 5) == 0)) {
4767c478bd9Sstevel@tonic-gate 		(void) memcpy(*newpath, path, p - path);
4777c478bd9Sstevel@tonic-gate 		q = *newpath + (p - path);
4787c478bd9Sstevel@tonic-gate #ifdef __sparcv9
4797c478bd9Sstevel@tonic-gate 		q += strlcpy(q, "sparcv9/", avail_length);
4807c478bd9Sstevel@tonic-gate #endif
4817c478bd9Sstevel@tonic-gate 		(void) strcpy(q, p + 5);
4827c478bd9Sstevel@tonic-gate 	} else
4837c478bd9Sstevel@tonic-gate 		*newpath = path;
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate /*
487f8994074SJan Friedel  * init_plugin first searches the existing plugin list to see if the plugin
488f8994074SJan Friedel  * already has been defined; if not, it creates it and links it into the list.
489f8994074SJan Friedel  * It returns a pointer to the found or created struct. Note, that
490f8994074SJan Friedel  * (manual/unsupported) change of path property in audit service configuration
491f8994074SJan Friedel  * for given plugin will cause a miss.
4927c478bd9Sstevel@tonic-gate  */
4937c478bd9Sstevel@tonic-gate /*
4947c478bd9Sstevel@tonic-gate  * for 64 bits, the path name can grow 3 bytes (minus 5 for the
4957c478bd9Sstevel@tonic-gate  * removed "$ISA" and plus 8 for the added "sparcv9/"
4967c478bd9Sstevel@tonic-gate  */
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate #define	ISA_GROW	8 - 5
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate static plugin_t *
init_plugin(char * name,kva_t * list,int cnt_flag)5017c478bd9Sstevel@tonic-gate init_plugin(char *name, kva_t *list, int cnt_flag)
5027c478bd9Sstevel@tonic-gate {
5037c478bd9Sstevel@tonic-gate 	plugin_t	*p, *q;
5047c478bd9Sstevel@tonic-gate 	char		filepath[MAXPATHLEN + 1 + ISA_GROW];
5057c478bd9Sstevel@tonic-gate 	char		*path = filepath;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	if (*name != '/') {
5087c478bd9Sstevel@tonic-gate #ifdef  __sparcv9
5097c478bd9Sstevel@tonic-gate 		(void) strcpy(filepath, "/usr/lib/security/sparcv9/");
5107c478bd9Sstevel@tonic-gate #else
5117c478bd9Sstevel@tonic-gate 		(void) strcpy(filepath, "/usr/lib/security/");
5127c478bd9Sstevel@tonic-gate #endif
5137c478bd9Sstevel@tonic-gate 		if (strlcat(filepath, name, MAXPATHLEN) >= MAXPATHLEN)
5147c478bd9Sstevel@tonic-gate 			return (NULL);
5157c478bd9Sstevel@tonic-gate 	} else {
5167c478bd9Sstevel@tonic-gate 		if (strlen(name) > MAXPATHLEN + ISA_GROW)
5177c478bd9Sstevel@tonic-gate 			return (NULL);
5187c478bd9Sstevel@tonic-gate 		isa_ified(name, &path);
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 	p = plugin_head;
5217c478bd9Sstevel@tonic-gate 	q = plugin_head;
5227c478bd9Sstevel@tonic-gate 	while (p != NULL) {
5237c478bd9Sstevel@tonic-gate 		if (p->plg_path != NULL) {
5247c478bd9Sstevel@tonic-gate 			if (strcmp(p->plg_path, path) == 0) {
5257c478bd9Sstevel@tonic-gate 				p->plg_removed = 0;
5267c478bd9Sstevel@tonic-gate 				p->plg_to_be_removed = 0;
5277c478bd9Sstevel@tonic-gate 				p->plg_cnt = cnt_flag;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 				_kva_free(p->plg_kvlist);
530f8994074SJan Friedel 				p->plg_kvlist = _kva_dup(list);
531f8994074SJan Friedel 				if (list != NULL && p->plg_kvlist == NULL) {
532f8994074SJan Friedel 					err_exit(NULL);
533f8994074SJan Friedel 				}
5347c478bd9Sstevel@tonic-gate 				p->plg_reopen = 1;
5357c478bd9Sstevel@tonic-gate 				DPRINT((dbfp, "reusing %s\n", p->plg_path));
5367c478bd9Sstevel@tonic-gate 				return (p);
5377c478bd9Sstevel@tonic-gate 			}
5387c478bd9Sstevel@tonic-gate 		}
5397c478bd9Sstevel@tonic-gate 		q = p;
5407c478bd9Sstevel@tonic-gate 		p = p->plg_next;
5417c478bd9Sstevel@tonic-gate 	}
5427c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "creating new plugin structure for %s\n", path));
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	p = malloc(sizeof (plugin_t));
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	if (p == NULL) {
5477c478bd9Sstevel@tonic-gate 		perror("auditd");
5487c478bd9Sstevel@tonic-gate 		return (NULL);
5497c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 	if (q == NULL)
5517c478bd9Sstevel@tonic-gate 		plugin_head = p;
5527c478bd9Sstevel@tonic-gate 	else
5537c478bd9Sstevel@tonic-gate 		q->plg_next = p;
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	p->plg_next = NULL;
5567c478bd9Sstevel@tonic-gate 	p->plg_initialized = 0;
5577c478bd9Sstevel@tonic-gate 	p->plg_reopen = 1;
5587c478bd9Sstevel@tonic-gate 	p->plg_tid = 0;
5597c478bd9Sstevel@tonic-gate 	p->plg_removed = 0;
5607c478bd9Sstevel@tonic-gate 	p->plg_to_be_removed = 0;
5617c478bd9Sstevel@tonic-gate 	p->plg_tossed = 0;
5627c478bd9Sstevel@tonic-gate 	p->plg_queued = 0;
5637c478bd9Sstevel@tonic-gate 	p->plg_output = 0;
5647c478bd9Sstevel@tonic-gate 	p->plg_sequence = 1;
5657c478bd9Sstevel@tonic-gate 	p->plg_last_seq_out = 0;
5667c478bd9Sstevel@tonic-gate 	p->plg_path = strdup(path);
567f8994074SJan Friedel 	p->plg_kvlist = _kva_dup(list);
5687c478bd9Sstevel@tonic-gate 	p->plg_cnt = cnt_flag;
5697c478bd9Sstevel@tonic-gate 	p->plg_retry_time = SLEEP_TIME;
5707c478bd9Sstevel@tonic-gate 	p->plg_qmax = 0;
5717c478bd9Sstevel@tonic-gate 	p->plg_save_q_copy = NULL;
5727c478bd9Sstevel@tonic-gate 
573f8994074SJan Friedel 	if (list != NULL && p->plg_kvlist == NULL || p->plg_path == NULL) {
574f8994074SJan Friedel 		err_exit(NULL);
575f8994074SJan Friedel 	}
576f8994074SJan Friedel 
5777c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "created plugin:  %s\n", path));
5787c478bd9Sstevel@tonic-gate 	return (p);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate /*
582*bbf21555SRichard Lowe  * loadauditlist() - read the auditd plugin configuration from smf(7) and
583f8994074SJan Friedel  * prepare appropriate plugin related structures (plugin_t). Set cnt policy here
584f8994074SJan Friedel  * based on currently active policy settings. (future could have a policy =
585f8994074SJan Friedel  * {+|-}cnt entry per plugin with auditconfig providing the default)
5867c478bd9Sstevel@tonic-gate  */
5877c478bd9Sstevel@tonic-gate static void
loadauditlist()5887c478bd9Sstevel@tonic-gate loadauditlist()
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate 	char			*value;
591f8994074SJan Friedel 	char			*endptr;
5927c478bd9Sstevel@tonic-gate 	plugin_t		*p;
59396093503SMarek Pospisil 	uint32_t		policy;
5947c478bd9Sstevel@tonic-gate 	int			cnt_flag;
5957c478bd9Sstevel@tonic-gate 	struct au_qctrl		kqmax;
596f8994074SJan Friedel 	scf_plugin_kva_node_t	*plugin_kva_ll;
597f8994074SJan Friedel 	scf_plugin_kva_node_t	*plugin_kva_ll_head;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	if (auditon(A_GETPOLICY, (char *)&policy, 0) == -1) {
6007c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "auditon(A_GETPOLICY...) failed (exit)\n"));
6017c478bd9Sstevel@tonic-gate 		__audit_dowarn("auditoff", "", 0);
6027c478bd9Sstevel@tonic-gate 		auditd_thread_close();
60317b6b380SJan Friedel 		auditd_exit(1);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 	cnt_flag = ((policy & AUDIT_CNT) != 0) ? 1 : 0;
6067c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "loadauditlist: policy is to %s\n", (cnt_flag == 1) ?
6077c478bd9Sstevel@tonic-gate 	    "continue" : "block"));
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate #if DEBUG
610f8994074SJan Friedel 	{
611f8994074SJan Friedel 		int	acresult;
612f8994074SJan Friedel 		if (auditon(A_GETCOND, (caddr_t)&acresult, sizeof (int)) != 0) {
6137c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "auditon(A_GETCOND...) failed (exit)\n"));
614f8994074SJan Friedel 		}
6157c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "audit cond = %d (1 is on)\n", acresult));
616f8994074SJan Friedel 	}
6178523fda3SJan Friedel #endif
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	if (auditon(A_GETQCTRL, (char *)&kqmax, sizeof (struct au_qctrl)) !=
6217c478bd9Sstevel@tonic-gate 	    0) {
6227c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "auditon(A_GETQCTRL...) failed (exit)\n"));
6237c478bd9Sstevel@tonic-gate 		__audit_dowarn("auditoff", "", 0);
6247c478bd9Sstevel@tonic-gate 		auditd_thread_close();
62517b6b380SJan Friedel 		auditd_exit(1);
6267c478bd9Sstevel@tonic-gate 	}
6277c478bd9Sstevel@tonic-gate 	kqmax.aq_hiwater *= 5;		/* RAM is cheaper in userspace */
628f8994074SJan Friedel 	DPRINT((dbfp, "auditd: reading audit configuration\n"));
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	p = plugin_head;
6317c478bd9Sstevel@tonic-gate 	/*
6327c478bd9Sstevel@tonic-gate 	 * two-step on setting p->plg_removed because the input thread
6337c478bd9Sstevel@tonic-gate 	 * in doorway.c uses p->plg_removed to decide if the plugin is
6347c478bd9Sstevel@tonic-gate 	 * active.
6357c478bd9Sstevel@tonic-gate 	 */
6367c478bd9Sstevel@tonic-gate 	while (p != NULL) {
6378523fda3SJan Friedel 		DPRINT((dbfp, "loadauditlist: %p, %s previously created\n",
6388523fda3SJan Friedel 		    (void *)p, p->plg_path));
6397c478bd9Sstevel@tonic-gate 		p->plg_to_be_removed = 1;	/* tentative removal */
6407c478bd9Sstevel@tonic-gate 		p = p->plg_next;
6417c478bd9Sstevel@tonic-gate 	}
6427c478bd9Sstevel@tonic-gate 
643f8994074SJan Friedel 	if (!do_getpluginconfig_scf(NULL, &plugin_kva_ll)) {
644f8994074SJan Friedel 		DPRINT((dbfp, "Could not get plugin configuration.\n"));
645f8994074SJan Friedel 		auditd_thread_close();
646f8994074SJan Friedel 		auditd_exit(1);
647f8994074SJan Friedel 	}
648f8994074SJan Friedel 	plugin_kva_ll_head = plugin_kva_ll;
6497c478bd9Sstevel@tonic-gate 
650f8994074SJan Friedel 	while (plugin_kva_ll != NULL) {
651f8994074SJan Friedel 		DPRINT((dbfp, "loadauditlist: starting with %s",
652f8994074SJan Friedel 		    plugin_kva_ll->plugin_name));
653f8994074SJan Friedel 
654f8994074SJan Friedel 		/* skip inactive plugins */
655f8994074SJan Friedel 		value = kva_match(plugin_kva_ll->plugin_kva, PLUGIN_ACTIVE);
656f8994074SJan Friedel 		if (strcmp(value, "1") != 0) {
657f8994074SJan Friedel 			DPRINT((dbfp, " (inactive:%s) skipping..\n", value));
658f8994074SJan Friedel 			plugin_kva_ll = plugin_kva_ll->next;
6597c478bd9Sstevel@tonic-gate 			continue;
660f8994074SJan Friedel 		}
661f8994074SJan Friedel 		DPRINT((dbfp, " (active)\n"));
6627c478bd9Sstevel@tonic-gate 
663f8994074SJan Friedel 		value = kva_match(plugin_kva_ll->plugin_kva, PLUGIN_PATH);
664f8994074SJan Friedel 		DPRINT((dbfp, "loadauditlist: have an entry for %s (%s)\n",
665f8994074SJan Friedel 		    plugin_kva_ll->plugin_name, value));
666f8994074SJan Friedel 
667f8994074SJan Friedel 		p = init_plugin(value, plugin_kva_ll->plugin_kva, cnt_flag);
668f8994074SJan Friedel 		if (p == NULL) {
669f8994074SJan Friedel 			DPRINT((dbfp, "Unsuccessful plugin_t "
670f8994074SJan Friedel 			    "initialization.\n"));
671f8994074SJan Friedel 			my_sleep();
672f8994074SJan Friedel 			continue;
673f8994074SJan Friedel 		}
674f8994074SJan Friedel 
675f8994074SJan Friedel 		if (strcmp(plugin_kva_ll->plugin_name, "audit_binfile") == 0) {
6767c478bd9Sstevel@tonic-gate 			binfile = p;
6777c478bd9Sstevel@tonic-gate 		}
678f8994074SJan Friedel 
6797c478bd9Sstevel@tonic-gate 		p->plg_qmax = kqmax.aq_hiwater; /* default */
680f8994074SJan Friedel 		value = kva_match(plugin_kva_ll->plugin_kva, PLUGIN_QSIZE);
6817c478bd9Sstevel@tonic-gate 		if (value != NULL) {
6827c478bd9Sstevel@tonic-gate 			long	tmp;
6837c478bd9Sstevel@tonic-gate 			tmp = strtol(value, &endptr, 10);
684f8994074SJan Friedel 			if (*endptr == '\0' && tmp != 0) {
6857c478bd9Sstevel@tonic-gate 				p->plg_qmax = tmp;
6867c478bd9Sstevel@tonic-gate 			}
6877c478bd9Sstevel@tonic-gate 		}
688f8994074SJan Friedel 		DPRINT((dbfp, "%s queue max = %d\n", p->plg_path, p->plg_qmax));
689f8994074SJan Friedel 
690f8994074SJan Friedel 		plugin_kva_ll = plugin_kva_ll->next;
691f8994074SJan Friedel 	}
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	p = plugin_head;
6947c478bd9Sstevel@tonic-gate 	while (p != NULL) {
6957c478bd9Sstevel@tonic-gate 		DPRINT((dbfp, "loadauditlist: %s remove flag=%d; cnt=%d\n",
6967c478bd9Sstevel@tonic-gate 		    p->plg_path, p->plg_to_be_removed, p->plg_cnt));
6977c478bd9Sstevel@tonic-gate 		p->plg_removed = p->plg_to_be_removed;
6987c478bd9Sstevel@tonic-gate 		p = p->plg_next;
6997c478bd9Sstevel@tonic-gate 	}
700f8994074SJan Friedel 
701f8994074SJan Friedel 	plugin_kva_ll_free(plugin_kva_ll_head);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate /*
7057c478bd9Sstevel@tonic-gate  * block signals -- thread-specific blocking of the signals expected
7067c478bd9Sstevel@tonic-gate  * by the main thread.
7077c478bd9Sstevel@tonic-gate  */
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate static void
block_signals()7107c478bd9Sstevel@tonic-gate block_signals()
7117c478bd9Sstevel@tonic-gate {
7127c478bd9Sstevel@tonic-gate 	sigset_t	set;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	(void) sigfillset(&set);
7157c478bd9Sstevel@tonic-gate 	(void) pthread_sigmask(SIG_BLOCK, &set, NULL);
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate /*
7197c478bd9Sstevel@tonic-gate  * signal_thread is the designated signal catcher.  It wakes up the
7207c478bd9Sstevel@tonic-gate  * main thread whenever it receives a signal and then goes back to
7217c478bd9Sstevel@tonic-gate  * sleep; it does not exit.  The global variables caught_* let
7227c478bd9Sstevel@tonic-gate  * the main thread which signal was received.
7237c478bd9Sstevel@tonic-gate  *
7247c478bd9Sstevel@tonic-gate  * The thread is created with all signals blocked.
7257c478bd9Sstevel@tonic-gate  */
7267c478bd9Sstevel@tonic-gate 
727d6beba26SToomas Soome static void *
signal_thread(void * arg __unused)728d6beba26SToomas Soome signal_thread(void *arg __unused)
7297c478bd9Sstevel@tonic-gate {
7307c478bd9Sstevel@tonic-gate 	sigset_t	set;
7317c478bd9Sstevel@tonic-gate 	int		signal_caught;
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	DPRINT((dbfp, "the signal thread is thread %d\n",
7347c478bd9Sstevel@tonic-gate 	    pthread_self()));
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&set);
7377c478bd9Sstevel@tonic-gate 	(void) sigaddset(&set, SIGALRM);
738f8994074SJan Friedel 	(void) sigaddset(&set, SIGTERM);
739f8994074SJan Friedel 	(void) sigaddset(&set, SIGHUP);
740f8994074SJan Friedel 	(void) sigaddset(&set, SIGUSR1);
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	for (;;) {
7437c478bd9Sstevel@tonic-gate 		signal_caught = sigwait(&set);
7447c478bd9Sstevel@tonic-gate 		switch (signal_caught) {
7457c478bd9Sstevel@tonic-gate 		case SIGALRM:
7467c478bd9Sstevel@tonic-gate 			caught_alrm++;
7477c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "caught SIGALRM\n"));
7487c478bd9Sstevel@tonic-gate 			break;
749f8994074SJan Friedel 		case SIGTERM:
7507c478bd9Sstevel@tonic-gate 			caught_term++;
751f8994074SJan Friedel 			DPRINT((dbfp, "caught SIGTERM\n"));
7527c478bd9Sstevel@tonic-gate 			break;
753f8994074SJan Friedel 		case SIGHUP:
7547c478bd9Sstevel@tonic-gate 			caught_readc++;
755f8994074SJan Friedel 			DPRINT((dbfp, "caught SIGHUP\n"));
7567c478bd9Sstevel@tonic-gate 			break;
757f8994074SJan Friedel 		case SIGUSR1:
7587c478bd9Sstevel@tonic-gate 			caught_nextd++;
759f8994074SJan Friedel 			DPRINT((dbfp, "caught SIGUSR1\n"));
7607c478bd9Sstevel@tonic-gate 			break;
7617c478bd9Sstevel@tonic-gate 		default:
7627c478bd9Sstevel@tonic-gate 			DPRINT((dbfp, "caught unexpected signal:  %d\n",
7637c478bd9Sstevel@tonic-gate 			    signal_caught));
7647c478bd9Sstevel@tonic-gate 			break;
7657c478bd9Sstevel@tonic-gate 		}
7667c478bd9Sstevel@tonic-gate 		(void) pthread_cond_signal(&(main_thr.thd_cv));
7677c478bd9Sstevel@tonic-gate 	}
768d6beba26SToomas Soome 	return (NULL);
7697c478bd9Sstevel@tonic-gate }
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate /*
7727c478bd9Sstevel@tonic-gate  * do_sethost - do auditon(2) to set the audit host-id.
7739697ae98Sgww  *		Returns 0 if success or -1 otherwise.
7747c478bd9Sstevel@tonic-gate  */
7757c478bd9Sstevel@tonic-gate static int
do_sethost(void)7767c478bd9Sstevel@tonic-gate do_sethost(void)
7777c478bd9Sstevel@tonic-gate {
7789697ae98Sgww 	au_tid_addr_t	*termid;
7797c478bd9Sstevel@tonic-gate 	auditinfo_addr_t	audit_info;
7809697ae98Sgww 	char	msg[512];
7817c478bd9Sstevel@tonic-gate 
7829697ae98Sgww 	if (adt_load_hostname(NULL, (adt_termid_t **)&termid) < 0) {
7839697ae98Sgww 		(void) snprintf(msg, sizeof (msg), "unable to get local "
7849697ae98Sgww 		    "IP address: %s", strerror(errno));
7859697ae98Sgww 		goto fail;
7867c478bd9Sstevel@tonic-gate 	}
7877c478bd9Sstevel@tonic-gate 	/* Get current kernel audit info, and fill in the IP address */
7889697ae98Sgww 	if (auditon(A_GETKAUDIT, (caddr_t)&audit_info,
7899697ae98Sgww 	    sizeof (audit_info)) < 0) {
7909697ae98Sgww 		(void) snprintf(msg, sizeof (msg), "unable to get kernel "
7919697ae98Sgww 		    "audit info: %s", strerror(errno));
7929697ae98Sgww 		goto fail;
7937c478bd9Sstevel@tonic-gate 	}
7947c478bd9Sstevel@tonic-gate 
7959697ae98Sgww 	audit_info.ai_termid = *termid;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	/* Update the kernel audit info with new IP address */
7989697ae98Sgww 	if (auditon(A_SETKAUDIT, (caddr_t)&audit_info,
7999697ae98Sgww 	    sizeof (audit_info)) < 0) {
8009697ae98Sgww 		(void) snprintf(msg, sizeof (msg), "unable to set kernel "
8019697ae98Sgww 		    "audit info: %s", strerror(errno));
8029697ae98Sgww 		goto fail;
8037c478bd9Sstevel@tonic-gate 	}
8047c478bd9Sstevel@tonic-gate 
8059697ae98Sgww 	free(termid);
8067c478bd9Sstevel@tonic-gate 	return (0);
8079697ae98Sgww 
8089697ae98Sgww fail:
8099697ae98Sgww 	free(termid);
8109697ae98Sgww 	__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_DAEMON,
8119697ae98Sgww 	    LOG_ALERT, msg);
8129697ae98Sgww 	return (-1);
8137c478bd9Sstevel@tonic-gate }
8148523fda3SJan Friedel 
8158523fda3SJan Friedel /*
8168523fda3SJan Friedel  * conf_to_kernel() - configure the event to class mapping; see also
817*bbf21555SRichard Lowe  * auditconfig(8) -conf option.
8188523fda3SJan Friedel  */
8198523fda3SJan Friedel static void
conf_to_kernel(void)8208523fda3SJan Friedel conf_to_kernel(void)
8218523fda3SJan Friedel {
822d6beba26SToomas Soome 	au_event_ent_t		*evp;
823d6beba26SToomas Soome 	int			i;
8248523fda3SJan Friedel 	char			*msg;
8258523fda3SJan Friedel 	au_evclass_map_t	ec;
8268523fda3SJan Friedel 	au_stat_t		as;
8278523fda3SJan Friedel 
8288523fda3SJan Friedel 	if (auditon(A_GETSTAT, (caddr_t)&as, 0) != 0) {
8298523fda3SJan Friedel 		(void) asprintf(&msg, gettext("Audit module does not appear "
8308523fda3SJan Friedel 		    "to be loaded."));
83117b6b380SJan Friedel 		err_exit(msg);
8328523fda3SJan Friedel 	}
8338523fda3SJan Friedel 
8348523fda3SJan Friedel 	i = 0;
8358523fda3SJan Friedel 	setauevent();
8368523fda3SJan Friedel 	while ((evp = getauevent()) != NULL) {
8378523fda3SJan Friedel 		if (evp->ae_number <= as.as_numevent) {
8388523fda3SJan Friedel 			++i;
8398523fda3SJan Friedel 			ec.ec_number = evp->ae_number;
8408523fda3SJan Friedel 			ec.ec_class = evp->ae_class;
8418523fda3SJan Friedel 
8428523fda3SJan Friedel 			if (auditon(A_SETCLASS, (caddr_t)&ec,
843f8994074SJan Friedel 			    sizeof (ec)) != 0) {
8448523fda3SJan Friedel 				(void) asprintf(&msg,
8458523fda3SJan Friedel 				    gettext("Could not configure kernel audit "
8468523fda3SJan Friedel 				    "event to class mappings."));
84717b6b380SJan Friedel 				err_exit(msg);
8488523fda3SJan Friedel 			}
8498523fda3SJan Friedel 		}
8508523fda3SJan Friedel 	}
8518523fda3SJan Friedel 	endauevent();
8528523fda3SJan Friedel 
8538523fda3SJan Friedel 	DPRINT((dbfp, "configured %d kernel events.\n", i));
8548523fda3SJan Friedel }
8558523fda3SJan Friedel 
8568523fda3SJan Friedel /*
8578523fda3SJan Friedel  * scf_to_kernel_qctrl() - update the kernel queue control parameters
8588523fda3SJan Friedel  */
8598523fda3SJan Friedel static void
scf_to_kernel_qctrl(void)8608523fda3SJan Friedel scf_to_kernel_qctrl(void)
8618523fda3SJan Friedel {
8628523fda3SJan Friedel 	struct au_qctrl	act_qctrl;
8638523fda3SJan Friedel 	struct au_qctrl	cfg_qctrl;
8648523fda3SJan Friedel 	char		*msg;
8658523fda3SJan Friedel 
8668523fda3SJan Friedel 	if (!do_getqctrl_scf(&cfg_qctrl)) {
8678523fda3SJan Friedel 		(void) asprintf(&msg, gettext("Unable to gather audit queue "
8688523fda3SJan Friedel 		    "control parameters from the SMF repository."));
86917b6b380SJan Friedel 		err_exit(msg);
8708523fda3SJan Friedel 	}
8718523fda3SJan Friedel 
8728523fda3SJan Friedel 	DPRINT((dbfp, "will check and set qctrl parameters:\n"));
8738523fda3SJan Friedel 	DPRINT((dbfp, "\thiwater: %d\n", cfg_qctrl.aq_hiwater));
8748523fda3SJan Friedel 	DPRINT((dbfp, "\tlowater: %d\n", cfg_qctrl.aq_lowater));
8758523fda3SJan Friedel 	DPRINT((dbfp, "\tbufsz: %d\n", cfg_qctrl.aq_bufsz));
8768523fda3SJan Friedel 	DPRINT((dbfp, "\tdelay: %ld\n", cfg_qctrl.aq_delay));
8778523fda3SJan Friedel 
8788523fda3SJan Friedel 	if (auditon(A_GETQCTRL, (caddr_t)&act_qctrl, 0) != 0) {
8798523fda3SJan Friedel 		(void) asprintf(&msg, gettext("Could not retrieve "
8808523fda3SJan Friedel 		    "audit queue controls from kernel."));
88117b6b380SJan Friedel 		err_exit(msg);
8828523fda3SJan Friedel 	}
8838523fda3SJan Friedel 
8848523fda3SJan Friedel 	/* overwrite the default (zeros) from the qctrl configuration */
8858523fda3SJan Friedel 	if (cfg_qctrl.aq_hiwater == 0) {
8868523fda3SJan Friedel 		cfg_qctrl.aq_hiwater = act_qctrl.aq_hiwater;
8878523fda3SJan Friedel 		DPRINT((dbfp, "hiwater changed to active value: %u\n",
8888523fda3SJan Friedel 		    cfg_qctrl.aq_hiwater));
8898523fda3SJan Friedel 	}
8908523fda3SJan Friedel 	if (cfg_qctrl.aq_lowater == 0) {
8918523fda3SJan Friedel 		cfg_qctrl.aq_lowater = act_qctrl.aq_lowater;
8928523fda3SJan Friedel 		DPRINT((dbfp, "lowater changed to active value: %u\n",
8938523fda3SJan Friedel 		    cfg_qctrl.aq_lowater));
8948523fda3SJan Friedel 	}
8958523fda3SJan Friedel 	if (cfg_qctrl.aq_bufsz == 0) {
8968523fda3SJan Friedel 		cfg_qctrl.aq_bufsz = act_qctrl.aq_bufsz;
8978523fda3SJan Friedel 		DPRINT((dbfp, "bufsz changed to active value: %u\n",
8988523fda3SJan Friedel 		    cfg_qctrl.aq_bufsz));
8998523fda3SJan Friedel 	}
9008523fda3SJan Friedel 	if (cfg_qctrl.aq_delay == 0) {
9018523fda3SJan Friedel 		cfg_qctrl.aq_delay = act_qctrl.aq_delay;
9028523fda3SJan Friedel 		DPRINT((dbfp, "delay changed to active value: %ld\n",
9038523fda3SJan Friedel 		    cfg_qctrl.aq_delay));
9048523fda3SJan Friedel 	}
9058523fda3SJan Friedel 
9068523fda3SJan Friedel 	if (auditon(A_SETQCTRL, (caddr_t)&cfg_qctrl, 0) != 0) {
9078523fda3SJan Friedel 		(void) asprintf(&msg,
9088523fda3SJan Friedel 		    gettext("Could not configure audit queue controls."));
90917b6b380SJan Friedel 		err_exit(msg);
9108523fda3SJan Friedel 	}
9118523fda3SJan Friedel 
9128523fda3SJan Friedel 	DPRINT((dbfp, "qctrl parameters set\n"));
9138523fda3SJan Friedel }
9148523fda3SJan Friedel 
9158523fda3SJan Friedel /*
9168523fda3SJan Friedel  * scf_to_kernel_policy() - update the audit service policies
9178523fda3SJan Friedel  */
9188523fda3SJan Friedel static void
scf_to_kernel_policy(void)9198523fda3SJan Friedel scf_to_kernel_policy(void)
9208523fda3SJan Friedel {
9218523fda3SJan Friedel 	uint32_t	policy;
9228523fda3SJan Friedel 	char		*msg;
9238523fda3SJan Friedel 
9248523fda3SJan Friedel 	if (!do_getpolicy_scf(&policy)) {
9258523fda3SJan Friedel 		(void) asprintf(&msg, gettext("Unable to get audit policy "
9268523fda3SJan Friedel 		    "configuration from the SMF repository."));
92717b6b380SJan Friedel 		err_exit(msg);
9288523fda3SJan Friedel 	}
9298523fda3SJan Friedel 
9308523fda3SJan Friedel 	if (auditon(A_SETPOLICY, (caddr_t)&policy, 0) != 0) {
9318523fda3SJan Friedel 		(void) asprintf(&msg,
9328523fda3SJan Friedel 		    gettext("Could not update active policy settings."));
93317b6b380SJan Friedel 		err_exit(msg);
9348523fda3SJan Friedel 	}
9358523fda3SJan Friedel 
9368523fda3SJan Friedel 	DPRINT((dbfp, "kernel policy settings updated\n"));
9378523fda3SJan Friedel }
938