Home | History | Annotate | Download | only in auditd
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /* Audit daemon server */
     27 /*
     28  * These routines make up the audit daemon server.  This daemon, called
     29  * auditd, handles the user level parts of auditing.  It receives buffered
     30  * audit records (usually one or more per buffer, potentially less than
     31  * one) and passes them to one or more plugins for processing.
     32  *
     33  * The major interrupts are AU_SIG_READ_CONTROL (start over),
     34  * AU_SIG_DISABLE (start shutting down), SIGALRM (quit), and
     35  * AU_SIG_NEXT_DIR (start a new audit log file). SIGTERM (the implementation
     36  * value of AU_SIG_DISABLE) is also used for the child to tell the parent
     37  * that audit is ready.
     38  *
     39  * Configuration data comes from /etc/security/audit_control and the auditon
     40  * system call.
     41  *
     42  * The major errors are EBUSY (auditing is already in use) and EINTR
     43  * (one of the above signals was received).  File space errors are
     44  * handled by the audit_binfile plugin
     45  */
     46 
     47 /* #define	DEBUG    - define for debug messages to be generated */
     48 /* #define	MEM_TEST - define to generate core dump on exit */
     49 #define	DEBUG		0
     50 #define	MEM_TEST	0
     51 
     52 #include <assert.h>
     53 #include <bsm/adt.h>
     54 #include <bsm/audit.h>
     55 #include <bsm/audit_record.h>
     56 #include <bsm/libbsm.h>
     57 #include <fcntl.h>
     58 #include <libintl.h>
     59 #include <locale.h>
     60 #include <netdb.h>
     61 #include <pwd.h>
     62 #include <secdb.h>
     63 #include <signal.h>
     64 #include <stdio.h>
     65 #include <stdlib.h>
     66 #include <string.h>
     67 #include <syslog.h>
     68 #include <errno.h>
     69 #include <sys/file.h>
     70 #include <sys/param.h>
     71 #include <sys/stat.h>
     72 #include <sys/statvfs.h>
     73 #include <sys/time.h>
     74 #include <sys/types.h>
     75 #include <sys/wait.h>
     76 #include <termios.h>
     77 #include <unistd.h>
     78 #include "plugin.h"
     79 #include "audit_sig_infc.h"
     80 #include <audit_plugin.h>
     81 #include <audit_scf.h>
     82 
     83 #if !defined(TEXT_DOMAIN)
     84 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
     85 #endif
     86 /*
     87  * After we get a AU_SIG_DISABLE, we want to set a timer for 2 seconds
     88  * and let c2audit write as many records as it can until the timer
     89  * goes off(at which point it returns to auditd with SIGALRM).  If any
     90  * other signals are received during that time, we call
     91  * __audit_dowarn() to indicate that the queue may not have been fully
     92  * flushed.
     93  */
     94 #define	ALRM_TIME	2
     95 #define	SLEEP_TIME	20	/* # of seconds to sleep in all hard loop */
     96 
     97 static plugin_t	*binfile = NULL;
     98 
     99 static int	turn_audit_on  = AUC_AUDITING;
    100 static int	turn_audit_off = AUC_NOAUDIT;
    101 
    102 static int	running = 1;
    103 
    104 /*
    105  * GLOBALS:
    106  */
    107 plugin_t		*plugin_head = NULL;
    108 static thr_data_t	main_thr;	/* auditd thread (0) */
    109 pthread_mutex_t		plugin_mutex;	/* for plugin_t list */
    110 
    111 static int	caught_alrm = 0;	/* number of SIGALRMs pending */
    112 static int	caught_readc = 0;	/* number of AU_SIG_READ_CONTROLs */
    113 static int	caught_term = 0;	/* number of AU_SIG_DISABLEs pending */
    114 static int	caught_nextd = 0;	/* number of AU_SIG_NEXT_DIRs pending */
    115 
    116 static int	reset_list = 1;	/* 1 to re-read audit_control */
    117 static int	reset_file = 1; /* 1 to close/open binary log */
    118 
    119 static int	auditing_set = 0;	/* 1 if auditon(A_SETCOND, on... */
    120 
    121 static void	my_sleep();
    122 static void	signal_thread();
    123 static void	loadauditlist();
    124 static void	block_signals();
    125 static int	do_sethost();
    126 
    127 static void	conf_to_kernel();
    128 static void	aconf_to_kernel();
    129 static void	scf_to_kernel_qctrl();
    130 static void	scf_to_kernel_policy();
    131 
    132 /*
    133  * err_exit() - exit function after the unsuccessful call to auditon();
    134  * prints_out / saves_via_syslog the necessary error messages.
    135  */
    136 static void
    137 err_exit(int rc, char *msg)
    138 {
    139 	if (msg != NULL) {
    140 		DPRINT((dbfp, "%s\n", msg));
    141 		__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT,
    142 		    LOG_DAEMON, LOG_ALERT, msg);
    143 		free(msg);
    144 	} else {
    145 		DPRINT((dbfp, "the memory allocation failed\n"));
    146 		__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT,
    147 		    LOG_DAEMON, LOG_ALERT, gettext("no memory"));
    148 	}
    149 	auditd_thread_close();
    150 	auditd_exit(rc);
    151 }
    152 
    153 /* common exit function */
    154 void
    155 auditd_exit(int status)
    156 {
    157 #if MEM_TEST
    158 	sigset_t	set;
    159 
    160 	DPRINT((dbfp, "mem_test intentional abort (status=%d)\n",
    161 	    status));
    162 	abort();
    163 #endif
    164 	DPRINT((dbfp, "%ld exit status = %d auditing_set = %d\n",
    165 	    getpid(), status, auditing_set));
    166 
    167 	if (auditing_set)
    168 		(void) auditon(A_SETCOND, (caddr_t)&turn_audit_off,
    169 		    (int)sizeof (int));
    170 
    171 #if DEBUG
    172 	(void) fclose(dbfp);
    173 #endif
    174 
    175 	exit(status);
    176 }
    177 
    178 /* ARGSUSED */
    179 int
    180 main(int argc, char *argv[])
    181 {
    182 	auditinfo_addr_t	as_null;	/* audit state to set */
    183 	au_id_t			auid;
    184 	pthread_t		tid;
    185 	plugin_t		*p;
    186 	pid_t			pid;
    187 
    188 #if DEBUG
    189 	/* LINTED */
    190 	char			*envp;
    191 	if (dbfp == NULL) {
    192 		dbfp = __auditd_debug_file_open();
    193 	}
    194 #endif
    195 	(void) setsid();
    196 
    197 	/* Internationalization */
    198 	(void) setlocale(LC_ALL, "");
    199 	(void) textdomain(TEXT_DOMAIN);
    200 
    201 	/*
    202 	 * Set the audit host-id.
    203 	 */
    204 	if (do_sethost() != 0) {
    205 		__audit_dowarn("nostart", "", 0);
    206 		auditd_exit(1);
    207 	}
    208 
    209 	/*
    210 	 * Turn off all auditing for this process.
    211 	 */
    212 	if (getaudit_addr(&as_null, sizeof (as_null)) == -1) {
    213 		__audit_dowarn("nostart", "", 0);
    214 		auditd_exit(2);
    215 	}
    216 	as_null.ai_mask.as_success = 0;
    217 	as_null.ai_mask.as_failure = 0;
    218 	(void) setaudit_addr(&as_null, sizeof (as_null));
    219 	auid = AU_NOAUDITID;
    220 	(void) setauid(&auid);
    221 	/*
    222 	 * Set the audit state flag to AUDITING.
    223 	 */
    224 	if (auditon(A_SETCOND, (caddr_t)&turn_audit_on, (int)sizeof (int)) !=
    225 	    0) {
    226 		DPRINT((dbfp, "auditon(A_SETCOND...) failed (exit)\n"));
    227 		__audit_dowarn("nostart", "", 0);
    228 		auditd_exit(7);
    229 	}
    230 
    231 	block_signals();
    232 
    233 	/*
    234 	 * wait for "ready" signal before exit -- for greenline
    235 	 */
    236 	if (fork()) {
    237 		sigset_t	set;
    238 		int		signal_caught = 0;
    239 
    240 		(void) sigemptyset(&set);
    241 		(void) sigaddset(&set, AU_SIG_DISABLE);
    242 
    243 		while (signal_caught != AU_SIG_DISABLE)
    244 			signal_caught = sigwait(&set);
    245 
    246 		DPRINT((dbfp, "init complete:  parent can now exit\n"));
    247 
    248 		auditd_exit(0);
    249 	}
    250 	pid = getppid();
    251 
    252 	auditing_set = 1;
    253 
    254 #if DEBUG && MEM_TEST
    255 	envp = getenv("UMEM_DEBUG");
    256 	if (envp != NULL)
    257 		DPRINT((dbfp, "UMEM_DEBUG=%s\n", envp));
    258 	envp = getenv("UMEM_LOGGING");
    259 	if (envp != NULL)
    260 		DPRINT((dbfp, "UMEM_LOGGING=%s\n", envp));
    261 #endif
    262 	DPRINT((dbfp, "auditd pid=%ld\n", getpid()));
    263 
    264 	/* thread 0 sync */
    265 	(void) pthread_mutex_init(&(main_thr.thd_mutex), NULL);
    266 	(void) pthread_cond_init(&(main_thr.thd_cv), NULL);
    267 	(void) pthread_mutex_init(&plugin_mutex, NULL);
    268 	/*
    269 	 * Set up a separate thread for signal handling.
    270 	 */
    271 	if (pthread_create(&tid, NULL, (void *(*)(void *))signal_thread,
    272 	    NULL)) {
    273 		(void) fprintf(stderr, gettext(
    274 		    "auditd can't create a thread\n"));
    275 		auditd_exit(3);
    276 	}
    277 	/*
    278 	 * Set the umask so that only audit or other users in the audit group
    279 	 * can get to the files created by auditd.
    280 	 */
    281 	(void) umask(007);
    282 
    283 	if (__logpost("")) {	/* Open the audit_data file. */
    284 		DPRINT((dbfp, "logpost failed\n"));
    285 		auditd_exit(4);
    286 	}
    287 	/*
    288 	 * Here is the main body of the audit daemon.  running == 0 means that
    289 	 * after flushing out the audit queue, it is time to exit in response to
    290 	 * AU_SIG_DISABLE
    291 	 */
    292 	while (running) {
    293 		/*
    294 		 * Read audit_control and create plugin lists.
    295 		 *
    296 		 * loadauditlist() and auditd_thread_init() are called
    297 		 * while under the plugin_mutex lock to avoid a race
    298 		 * with unload_plugin().
    299 		 */
    300 		if (reset_list || reset_file) {
    301 			if (reset_list) {
    302 				conf_to_kernel();
    303 				aconf_to_kernel();
    304 				scf_to_kernel_qctrl();
    305 				scf_to_kernel_policy();
    306 				(void) pthread_mutex_lock(&plugin_mutex);
    307 				loadauditlist();
    308 			} else {
    309 				(void) pthread_mutex_lock(&plugin_mutex);
    310 			}
    311 
    312 			if (auditd_thread_init()) {
    313 				auditd_thread_close();
    314 				/* continue; wait for audit -s */
    315 			}
    316 			(void) pthread_mutex_unlock(&plugin_mutex);
    317 			reset_list = 0;
    318 
    319 			if (reset_list && reset_file) {
    320 				(void) printf(gettext("auditd started\n"));
    321 			} else {
    322 				(void) printf(gettext("auditd refreshed\n"));
    323 			}
    324 		}
    325 		/*
    326 		 * tell parent I'm running whether or not the initialization
    327 		 * actually worked.  The failure case is to wait for an
    328 		 * audit -n or audit -s to fix the problem.
    329 		 */
    330 		if (pid != 0) {
    331 			(void) kill(pid, AU_SIG_DISABLE);
    332 			pid = 0;
    333 		}
    334 		/*
    335 		 * thread_signal() signals main (this thread) when
    336 		 * it has received a signal.
    337 		 */
    338 		DPRINT((dbfp, "main thread is waiting\n"));
    339 		(void) pthread_mutex_lock(&(main_thr.thd_mutex));
    340 
    341 		if (!(caught_readc || caught_term || caught_alrm ||
    342 		    caught_nextd))
    343 			(void) pthread_cond_wait(&(main_thr.thd_cv),
    344 			    &(main_thr.thd_mutex));
    345 		(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
    346 		/*
    347 		 * Got here because a signal came in.
    348 		 * Since we may have gotten more than one, we assume a
    349 		 * priority scheme with SIGALRM being the most
    350 		 * significant.
    351 		 */
    352 		if (caught_alrm) {
    353 			/*
    354 			 * We have returned from our timed wait for
    355 			 * c2audit to calm down.  We need to really shut
    356 			 * down here.
    357 			 */
    358 			caught_alrm = 0;
    359 			running = 0;	/* shut down now */
    360 		} else if (caught_term) {
    361 			/*
    362 			 * we are going to shut down, but need to
    363 			 * allow time for the audit queues in
    364 			 * c2audit and for the threads to empty.
    365 			 */
    366 
    367 			p = plugin_head;
    368 			while (p != NULL) {
    369 				DPRINT((dbfp, "signalling thread %d\n",
    370 				    p->plg_tid));
    371 				(void) pthread_mutex_lock(&(p->plg_mutex));
    372 				p->plg_removed = 1;
    373 
    374 				if (p->plg_initialized)
    375 					(void) pthread_cond_signal(
    376 					    &(p->plg_cv));
    377 
    378 				(void) pthread_mutex_unlock(&(p->plg_mutex));
    379 				p = p->plg_next;
    380 			}
    381 
    382 			caught_alrm = 0;
    383 			caught_readc  = 0;
    384 			caught_term = 0;
    385 			caught_nextd = 0;
    386 
    387 			DPRINT((dbfp,
    388 			    "main thread is pausing before exit.\n"));
    389 			(void) pthread_mutex_lock(&(main_thr.thd_mutex));
    390 			caught_alrm = 0;
    391 			(void) alarm(ALRM_TIME);
    392 			while (!caught_alrm)
    393 				(void) pthread_cond_wait(&(main_thr.thd_cv),
    394 				    &(main_thr.thd_mutex));
    395 
    396 			(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
    397 
    398 			running = 0;	/* Close down auditing and exit */
    399 		} else if (caught_readc) {
    400 			/*
    401 			 * if both hup and usr1 are caught, the logic in
    402 			 * loadauditlist() results in hup winning.  The
    403 			 * result will be that the audit file is not rolled
    404 			 * over unless audit_control actually changed.
    405 			 *
    406 			 * They want to reread the audit_control file.
    407 			 * Set reset_list which will return us to the
    408 			 * main while loop in the main routine.
    409 			 */
    410 			caught_readc = 0;
    411 			reset_list = 1;
    412 		} else if (caught_nextd) {
    413 			/*
    414 			 * This is a special case for the binfile
    415 			 * plugin. (audit -n)  NULL out kvlist
    416 			 * so binfile won't re-read audit_control
    417 			 */
    418 			caught_nextd = 0;
    419 			reset_file = 1;
    420 			if (binfile != NULL) {
    421 				_kva_free(binfile->plg_kvlist);
    422 				binfile->plg_kvlist = NULL;
    423 				binfile->plg_reopen = 1;
    424 			}
    425 		}
    426 	}	/* end while (running) */
    427 	auditd_thread_close();
    428 
    429 	auditd_exit(0);
    430 	return (0);
    431 }
    432 
    433 /*
    434  * my_sleep - sleep for SLEEP_TIME seconds but only accept the signals
    435  *	that we want to accept.  (Premature termination just means the
    436  *	caller retries more often, not a big deal.)
    437  */
    438 
    439 static void
    440 my_sleep()
    441 {
    442 	DPRINT((dbfp, "auditd: sleeping for 20 seconds\n"));
    443 	/*
    444 	 * Set timer to "sleep"
    445 	 */
    446 	(void) alarm(SLEEP_TIME);
    447 
    448 	DPRINT((dbfp, "main thread is waiting for SIGALRM before exit.\n"));
    449 	(void) pthread_mutex_lock(&(main_thr.thd_mutex));
    450 	(void) pthread_cond_wait(&(main_thr.thd_cv), &(main_thr.thd_mutex));
    451 	(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
    452 
    453 	if (caught_term) {
    454 		DPRINT((dbfp, "normal AU_SIG_DISABLE exit\n"));
    455 		/*
    456 		 * Exit, as requested.
    457 		 */
    458 		auditd_thread_close();
    459 	}
    460 	if (caught_readc)
    461 		reset_list = 1;		/* Reread the audit_control file */
    462 
    463 	caught_readc = 0;
    464 	caught_nextd = 0;
    465 }
    466 
    467 /*
    468  * search for $ISA/ in path and replace it with "" if auditd
    469  * is 32 bit, else "sparcv9/"  The plugin $ISA must match however
    470  * auditd was compiled.
    471  */
    472 
    473 static void
    474 isa_ified(char *path, char **newpath)
    475 {
    476 	char	*p, *q;
    477 
    478 	if (((p = strchr(path, '$')) != NULL) &&
    479 	    (strncmp("$ISA/", p, 5) == 0)) {
    480 		(void) memcpy(*newpath, path, p - path);
    481 		q = *newpath + (p - path);
    482 #ifdef __sparcv9
    483 		q += strlcpy(q, "sparcv9/", avail_length);
    484 #endif
    485 		(void) strcpy(q, p + 5);
    486 	} else
    487 		*newpath = path;
    488 }
    489 
    490 /*
    491  * init_plugin first searches the existing plugin list to see
    492  * if the plugin already has been defined; if not, it creates it
    493  * and links it into the list.  It returns a pointer to the found
    494  * or created struct.  A change of path in audit_control for a
    495  * given plugin will cause a miss.
    496  */
    497 /*
    498  * for 64 bits, the path name can grow 3 bytes (minus 5 for the
    499  * removed "$ISA" and plus 8 for the added "sparcv9/"
    500  */
    501 
    502 #define	ISA_GROW	8 - 5
    503 
    504 static plugin_t *
    505 init_plugin(char *name, kva_t *list, int cnt_flag)
    506 {
    507 	plugin_t	*p, *q;
    508 	char		filepath[MAXPATHLEN + 1 + ISA_GROW];
    509 	char		*path = filepath;
    510 
    511 	if (*name != '/') {
    512 #ifdef  __sparcv9
    513 		(void) strcpy(filepath, "/usr/lib/security/sparcv9/");
    514 #else
    515 		(void) strcpy(filepath, "/usr/lib/security/");
    516 #endif
    517 		if (strlcat(filepath, name, MAXPATHLEN) >= MAXPATHLEN)
    518 			return (NULL);
    519 	} else {
    520 		if (strlen(name) > MAXPATHLEN + ISA_GROW)
    521 			return (NULL);
    522 		isa_ified(name, &path);
    523 	}
    524 	p = plugin_head;
    525 	q = plugin_head;
    526 	while (p != NULL) {
    527 		if (p->plg_path != NULL) {
    528 			if (strcmp(p->plg_path, path) == 0) {
    529 				p->plg_removed = 0;
    530 				p->plg_to_be_removed = 0;
    531 				p->plg_cnt = cnt_flag;
    532 
    533 				_kva_free(p->plg_kvlist);
    534 				p->plg_kvlist = list;
    535 				p->plg_reopen = 1;
    536 				DPRINT((dbfp, "reusing %s\n", p->plg_path));
    537 				return (p);
    538 			}
    539 		}
    540 		q = p;
    541 		p = p->plg_next;
    542 	}
    543 	DPRINT((dbfp, "creating new plugin structure for %s\n", path));
    544 
    545 	p = malloc(sizeof (plugin_t));
    546 
    547 	if (p == NULL) {
    548 		perror("auditd");
    549 		return (NULL);
    550 	}
    551 	if (q == NULL)
    552 		plugin_head = p;
    553 	else
    554 		q->plg_next = p;
    555 
    556 	p->plg_next = NULL;
    557 	p->plg_initialized = 0;
    558 	p->plg_reopen = 1;
    559 	p->plg_tid = 0;
    560 	p->plg_removed = 0;
    561 	p->plg_to_be_removed = 0;
    562 	p->plg_tossed = 0;
    563 	p->plg_queued = 0;
    564 	p->plg_output = 0;
    565 	p->plg_sequence = 1;
    566 	p->plg_last_seq_out = 0;
    567 	p->plg_path = strdup(path);
    568 	p->plg_kvlist = list;
    569 	p->plg_cnt = cnt_flag;
    570 	p->plg_retry_time = SLEEP_TIME;
    571 	p->plg_qmax = 0;
    572 	p->plg_save_q_copy = NULL;
    573 
    574 	DPRINT((dbfp, "created plugin:  %s\n", path));
    575 	return (p);
    576 }
    577 
    578 /*
    579  * loadauditlist - read the directory list from the audit_control file.
    580  *		   to determine if a binary file is to be written.
    581  *		 - read the plugin entries from the audit_control file
    582  *
    583  * globals -
    584  *
    585  *	plugin queues
    586  *
    587  * success is when at least one plug in is defined.
    588  *
    589  * set cnt policy here based on auditconfig setting.  future could
    590  * have a policy = {+|-}cnt entry per plugin with auditconfig providing the
    591  * default.
    592  */
    593 
    594 static void
    595 loadauditlist()
    596 {
    597 	char		buf[MAXPATHLEN];
    598 	char		*value;
    599 	plugin_t	*p;
    600 	int		acresult;
    601 	int		wait_count = 0;
    602 	kva_t		*kvlist;
    603 	long		policy;
    604 	int		cnt_flag;
    605 	struct au_qctrl	kqmax;
    606 	au_acinfo_t	*ach = NULL;
    607 	int		got_dir = 0;
    608 	int		have_plugin = 0;
    609 	char		*endptr;
    610 
    611 	if (auditon(A_GETPOLICY, (char *)&policy, 0) == -1) {
    612 		DPRINT((dbfp, "auditon(A_GETPOLICY...) failed (exit)\n"));
    613 		__audit_dowarn("auditoff", "", 0);
    614 		auditd_thread_close();
    615 		auditd_exit(5);
    616 	}
    617 	cnt_flag = ((policy & AUDIT_CNT) != 0) ? 1 : 0;
    618 	DPRINT((dbfp, "loadauditlist:  policy is to %s\n", (cnt_flag == 1) ?
    619 	    "continue" : "block"));
    620 
    621 #if DEBUG
    622 	if (auditon(A_GETCOND, (caddr_t)&acresult, (int)sizeof (int)) != 0)
    623 		DPRINT((dbfp, "auditon(A_GETCOND...) failed (exit)\n"));
    624 
    625 	DPRINT((dbfp, "audit cond = %d (1 is on)\n", acresult));
    626 #endif
    627 
    628 
    629 	if (auditon(A_GETQCTRL, (char *)&kqmax, sizeof (struct au_qctrl)) !=
    630 	    0) {
    631 		DPRINT((dbfp, "auditon(A_GETQCTRL...) failed (exit)\n"));
    632 		__audit_dowarn("auditoff", "", 0);
    633 		auditd_thread_close();
    634 		auditd_exit(6);
    635 	}
    636 	kqmax.aq_hiwater *= 5;		/* RAM is cheaper in userspace */
    637 	DPRINT((dbfp, "auditd: reading audit_control\n"));
    638 
    639 	p = plugin_head;
    640 	/*
    641 	 * two-step on setting p->plg_removed because the input thread
    642 	 * in doorway.c uses p->plg_removed to decide if the plugin is
    643 	 * active.
    644 	 */
    645 	while (p != NULL) {
    646 		DPRINT((dbfp, "loadauditlist:  %p, %s previously created\n",
    647 		    (void *)p, p->plg_path));
    648 		p->plg_to_be_removed = 1;	/* tentative removal */
    649 		p = p->plg_next;
    650 	}
    651 	/*
    652 	 * have_plugin may over count by one if both a "dir" entry
    653 	 * and a "plugin" entry for binfile are found.  All that
    654 	 * matters is that it be zero if no plugin or dir entries
    655 	 * are found.
    656 	 */
    657 	have_plugin = 0;
    658 	for (;;) {
    659 		/* NULL == use standard path for audit_control */
    660 		ach = _openac(NULL);
    661 		/*
    662 		 * loop until a directory entry is found (0) or eof (-1)
    663 		 */
    664 		while (((acresult = _getacdir(ach, buf, sizeof (buf))) != 0) &&
    665 		    acresult != -1) {
    666 		}
    667 		if (acresult == 0) {
    668 			DPRINT((dbfp,
    669 			    "loadauditlist: "
    670 			    "got binfile via old config syntax\n"));
    671 			/*
    672 			 * A directory entry was found.
    673 			 */
    674 			got_dir = 1;
    675 			kvlist = _str2kva("name=audit_binfile.so.1",
    676 			    "=", ";");
    677 
    678 			p = init_plugin("audit_binfile.so.1", kvlist, cnt_flag);
    679 
    680 			if (p != NULL) {
    681 				binfile = p;
    682 				p->plg_qmax = kqmax.aq_hiwater;
    683 				have_plugin++;
    684 			}
    685 		}
    686 		/*
    687 		 * collect plugin entries.  If there is an entry for
    688 		 * binfile.so.1, the parameters from the plugin line
    689 		 * override those set above.  For binfile, p_dir is
    690 		 * required only if dir wasn't specified elsewhere in
    691 		 * audit_control
    692 		 */
    693 		_rewindac(ach);
    694 		while ((acresult = _getacplug(ach, &kvlist)) == 0) {
    695 			value = kva_match(kvlist, "name");
    696 			if (value == NULL)
    697 				break;
    698 			DPRINT((dbfp, "loadauditlist: have an entry for %s\n",
    699 			    value));
    700 			p = init_plugin(value, kvlist, cnt_flag);
    701 			if (p == NULL)
    702 				continue;
    703 
    704 			if (strstr(value, "/audit_binfile.so") != NULL) {
    705 				binfile = p;
    706 				if (!got_dir &&
    707 				    (kva_match(kvlist, "p_dir") ==
    708 				    NULL)) {
    709 					__audit_dowarn("getacdir", "",
    710 					    wait_count);
    711 				}
    712 			}
    713 			p->plg_qmax = kqmax.aq_hiwater; /* default */
    714 			value = kva_match(kvlist, "qsize");
    715 			if (value != NULL) {
    716 				long	tmp;
    717 
    718 				tmp = strtol(value, &endptr, 10);
    719 				if (*endptr == '\0')
    720 					p->plg_qmax = tmp;
    721 			}
    722 			DPRINT((dbfp, "%s queue max = %d\n", p->plg_path,
    723 			    p->plg_qmax));
    724 
    725 			have_plugin++;
    726 		}
    727 		_endac(ach);
    728 		if (have_plugin != 0)
    729 			break;
    730 		/*
    731 		 * there was a problem getting the directory
    732 		 * list or remote host info from the audit_control file
    733 		 */
    734 		wait_count++;
    735 #if DEBUG
    736 		if (wait_count < 2)
    737 			DPRINT((dbfp,
    738 			    "auditd: problem getting directory "
    739 			    "/ or plugin list from audit_control.\n"));
    740 #endif	/* DEBUG */
    741 		__audit_dowarn("getacdir", "", wait_count);
    742 		/*
    743 		 * sleep for SLEEP_TIME seconds.
    744 		 */
    745 		my_sleep();
    746 	}    /* end for(;;) */
    747 
    748 	p = plugin_head;
    749 	while (p != NULL) {
    750 		DPRINT((dbfp, "loadauditlist: %s remove flag=%d; cnt=%d\n",
    751 		    p->plg_path, p->plg_to_be_removed, p->plg_cnt));
    752 		p->plg_removed = p->plg_to_be_removed;
    753 		p = p->plg_next;
    754 	}
    755 }
    756 
    757 /*
    758  * block signals -- thread-specific blocking of the signals expected
    759  * by the main thread.
    760  */
    761 
    762 static void
    763 block_signals()
    764 {
    765 	sigset_t	set;
    766 
    767 	(void) sigfillset(&set);
    768 	(void) pthread_sigmask(SIG_BLOCK, &set, NULL);
    769 }
    770 
    771 /*
    772  * signal_thread is the designated signal catcher.  It wakes up the
    773  * main thread whenever it receives a signal and then goes back to
    774  * sleep; it does not exit.  The global variables caught_* let
    775  * the main thread which signal was received.
    776  *
    777  * The thread is created with all signals blocked.
    778  */
    779 
    780 static void
    781 signal_thread()
    782 {
    783 	sigset_t	set;
    784 	int		signal_caught;
    785 
    786 	DPRINT((dbfp, "the signal thread is thread %d\n",
    787 	    pthread_self()));
    788 
    789 	(void) sigemptyset(&set);
    790 	(void) sigaddset(&set, SIGALRM);
    791 	(void) sigaddset(&set, AU_SIG_DISABLE);
    792 	(void) sigaddset(&set, AU_SIG_READ_CONTROL);
    793 	(void) sigaddset(&set, AU_SIG_NEXT_DIR);
    794 
    795 	for (;;) {
    796 		signal_caught = sigwait(&set);
    797 		switch (signal_caught) {
    798 		case SIGALRM:
    799 			caught_alrm++;
    800 			DPRINT((dbfp, "caught SIGALRM\n"));
    801 			break;
    802 		case AU_SIG_DISABLE:
    803 			caught_term++;
    804 			DPRINT((dbfp, "caught AU_SIG_DISABLE\n"));
    805 			break;
    806 		case AU_SIG_READ_CONTROL:
    807 			caught_readc++;
    808 			DPRINT((dbfp, "caught AU_SIG_READ_CONTROL\n"));
    809 			break;
    810 		case AU_SIG_NEXT_DIR:
    811 			caught_nextd++;
    812 			DPRINT((dbfp, "caught AU_SIG_NEXT_DIR\n"));
    813 			break;
    814 		default:
    815 			DPRINT((dbfp, "caught unexpected signal:  %d\n",
    816 			    signal_caught));
    817 			break;
    818 		}
    819 		(void) pthread_cond_signal(&(main_thr.thd_cv));
    820 	}
    821 }
    822 
    823 /*
    824  * do_sethost - do auditon(2) to set the audit host-id.
    825  *		Returns 0 if success or -1 otherwise.
    826  */
    827 static int
    828 do_sethost(void)
    829 {
    830 	au_tid_addr_t	*termid;
    831 	auditinfo_addr_t	audit_info;
    832 	char	msg[512];
    833 
    834 	if (adt_load_hostname(NULL, (adt_termid_t **)&termid) < 0) {
    835 		(void) snprintf(msg, sizeof (msg), "unable to get local "
    836 		    "IP address: %s", strerror(errno));
    837 		goto fail;
    838 	}
    839 	/* Get current kernel audit info, and fill in the IP address */
    840 	if (auditon(A_GETKAUDIT, (caddr_t)&audit_info,
    841 	    sizeof (audit_info)) < 0) {
    842 		(void) snprintf(msg, sizeof (msg), "unable to get kernel "
    843 		    "audit info: %s", strerror(errno));
    844 		goto fail;
    845 	}
    846 
    847 	audit_info.ai_termid = *termid;
    848 
    849 	/* Update the kernel audit info with new IP address */
    850 	if (auditon(A_SETKAUDIT, (caddr_t)&audit_info,
    851 	    sizeof (audit_info)) < 0) {
    852 		(void) snprintf(msg, sizeof (msg), "unable to set kernel "
    853 		    "audit info: %s", strerror(errno));
    854 		goto fail;
    855 	}
    856 
    857 	free(termid);
    858 	return (0);
    859 
    860 fail:
    861 	free(termid);
    862 	__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_DAEMON,
    863 	    LOG_ALERT, msg);
    864 	return (-1);
    865 }
    866 
    867 /*
    868  * conf_to_kernel() - configure the event to class mapping; see also
    869  * auditconfig(1M) -conf option.
    870  */
    871 static void
    872 conf_to_kernel(void)
    873 {
    874 	register au_event_ent_t *evp;
    875 	register int 		i;
    876 	char			*msg;
    877 	au_evclass_map_t 	ec;
    878 	au_stat_t 		as;
    879 
    880 	if (auditon(A_GETSTAT, (caddr_t)&as, 0) != 0) {
    881 		(void) asprintf(&msg, gettext("Audit module does not appear "
    882 		    "to be loaded."));
    883 		err_exit(1, msg);
    884 	}
    885 
    886 	i = 0;
    887 	setauevent();
    888 	while ((evp = getauevent()) != NULL) {
    889 		if (evp->ae_number <= as.as_numevent) {
    890 			++i;
    891 			ec.ec_number = evp->ae_number;
    892 			ec.ec_class = evp->ae_class;
    893 
    894 			if (auditon(A_SETCLASS, (caddr_t)&ec,
    895 			    (int)sizeof (ec)) != 0) {
    896 				(void) asprintf(&msg,
    897 				    gettext("Could not configure kernel audit "
    898 				    "event to class mappings."));
    899 				err_exit(1, msg);
    900 			}
    901 		}
    902 	}
    903 	endauevent();
    904 
    905 	DPRINT((dbfp, "configured %d kernel events.\n", i));
    906 }
    907 
    908 /*
    909  * aconf_to_kernel() - set the non-attributable audit mask from the
    910  * audit_control(4); see also auditconfig(1M) -aconf option.
    911  */
    912 static void
    913 aconf_to_kernel(void)
    914 {
    915 	char		*msg;
    916 	char		buf[2048];
    917 	au_mask_t	pmask;
    918 
    919 	if (getacna(buf, sizeof (buf)) < 0) {
    920 		(void) asprintf(&msg,
    921 		    gettext("bad non-attributable flags in audit_control(4)"));
    922 		err_exit(1, msg);
    923 	}
    924 
    925 	if (getauditflagsbin(buf, &pmask) < 0) {
    926 		(void) asprintf(&msg,
    927 		    gettext("bad audit flag value encountered"));
    928 		err_exit(1, msg);
    929 	}
    930 
    931 	if (auditon(A_SETKMASK, (caddr_t)&pmask, (int)sizeof (pmask)) != 0) {
    932 		(void) asprintf(&msg,
    933 		    gettext("Could not configure non-attributable events."));
    934 		err_exit(1, msg);
    935 	}
    936 
    937 	DPRINT((dbfp, "configured non-attributable events.\n"));
    938 }
    939 
    940 /*
    941  * scf_to_kernel_qctrl() - update the kernel queue control parameters
    942  */
    943 static void
    944 scf_to_kernel_qctrl(void)
    945 {
    946 	struct au_qctrl	act_qctrl;
    947 	struct au_qctrl	cfg_qctrl;
    948 	char		*msg;
    949 
    950 	if (!do_getqctrl_scf(&cfg_qctrl)) {
    951 		(void) asprintf(&msg, gettext("Unable to gather audit queue "
    952 		    "control parameters from the SMF repository."));
    953 		err_exit(1, msg);
    954 	}
    955 
    956 	DPRINT((dbfp, "will check and set qctrl parameters:\n"));
    957 	DPRINT((dbfp, "\thiwater: %d\n", cfg_qctrl.aq_hiwater));
    958 	DPRINT((dbfp, "\tlowater: %d\n", cfg_qctrl.aq_lowater));
    959 	DPRINT((dbfp, "\tbufsz: %d\n", cfg_qctrl.aq_bufsz));
    960 	DPRINT((dbfp, "\tdelay: %ld\n", cfg_qctrl.aq_delay));
    961 
    962 	if (auditon(A_GETQCTRL, (caddr_t)&act_qctrl, 0) != 0) {
    963 		(void) asprintf(&msg, gettext("Could not retrieve "
    964 		    "audit queue controls from kernel."));
    965 		err_exit(1, msg);
    966 	}
    967 
    968 	/* overwrite the default (zeros) from the qctrl configuration */
    969 	if (cfg_qctrl.aq_hiwater == 0) {
    970 		cfg_qctrl.aq_hiwater = act_qctrl.aq_hiwater;
    971 		DPRINT((dbfp, "hiwater changed to active value: %u\n",
    972 		    cfg_qctrl.aq_hiwater));
    973 	}
    974 	if (cfg_qctrl.aq_lowater == 0) {
    975 		cfg_qctrl.aq_lowater = act_qctrl.aq_lowater;
    976 		DPRINT((dbfp, "lowater changed to active value: %u\n",
    977 		    cfg_qctrl.aq_lowater));
    978 	}
    979 	if (cfg_qctrl.aq_bufsz == 0) {
    980 		cfg_qctrl.aq_bufsz = act_qctrl.aq_bufsz;
    981 		DPRINT((dbfp, "bufsz changed to active value: %u\n",
    982 		    cfg_qctrl.aq_bufsz));
    983 	}
    984 	if (cfg_qctrl.aq_delay == 0) {
    985 		cfg_qctrl.aq_delay = act_qctrl.aq_delay;
    986 		DPRINT((dbfp, "delay changed to active value: %ld\n",
    987 		    cfg_qctrl.aq_delay));
    988 	}
    989 
    990 	if (auditon(A_SETQCTRL, (caddr_t)&cfg_qctrl, 0) != 0) {
    991 		(void) asprintf(&msg,
    992 		    gettext("Could not configure audit queue controls."));
    993 		err_exit(1, msg);
    994 	}
    995 
    996 	DPRINT((dbfp, "qctrl parameters set\n"));
    997 }
    998 
    999 /*
   1000  * scf_to_kernel_policy() - update the audit service policies
   1001  */
   1002 static void
   1003 scf_to_kernel_policy(void)
   1004 {
   1005 	uint32_t	policy;
   1006 	char		*msg;
   1007 
   1008 	if (!do_getpolicy_scf(&policy)) {
   1009 		(void) asprintf(&msg, gettext("Unable to get audit policy "
   1010 		    "configuration from the SMF repository."));
   1011 		err_exit(1, msg);
   1012 	}
   1013 
   1014 	if (auditon(A_SETPOLICY, (caddr_t)&policy, 0) != 0) {
   1015 		(void) asprintf(&msg,
   1016 		    gettext("Could not update active policy settings."));
   1017 		err_exit(1, msg);
   1018 	}
   1019 
   1020 	DPRINT((dbfp, "kernel policy settings updated\n"));
   1021 }
   1022