xref: /titanic_41/usr/src/cmd/auditd/auditd.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /* Audit daemon server */
30 /*
31  * These routines make up the audit daemon server.  This daemon, called
32  * auditd, handles the user level parts of auditing.  It receives buffered
33  * audit records (usually one or more per buffer, potentially less than
34  * one) and passes them to one or more plugins for processing.
35  *
36  * The major interrupts are AU_SIG_READ_CONTROL (start over),
37  * AU_SIG_DISABLE (start shutting down), SIGALRM (quit), and
38  * AU_SIG_NEXT_DIR (start a new audit log file). SIGTERM (the implementation
39  * value of AU_SIG_DISABLE) is also used for the child to tell the parent
40  * that audit is ready.
41  *
42  * Configuration data comes from /etc/security/audit_control and the auditon
43  * system call.
44  *
45  * The major errors are EBUSY (auditing is already in use) and EINTR
46  * (one of the above signals was received).  File space errors are
47  * handled by the audit_binfile plugin
48  */
49 
50 #define	DEBUG 		0
51 #define	MEM_TEST	0	/* set to one to generate core dump on exit */
52 
53 #include <assert.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 <errno.h>
68 #include <sys/file.h>
69 #include <sys/param.h>
70 #include <sys/stat.h>
71 #include <sys/statvfs.h>
72 #include <sys/time.h>
73 #include <sys/types.h>
74 #include <sys/wait.h>
75 #include <termios.h>
76 #include <unistd.h>
77 #include "plugin.h"
78 #include "audit_sig_infc.h"
79 #include <audit_plugin.h>
80 
81 #if !defined(TEXT_DOMAIN)
82 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
83 #endif
84 /*
85  * After we get a AU_SIG_DISABLE, we want to set a timer for 2 seconds
86  * and let c2audit write as many records as it can until the timer
87  * goes off(at which point it returns to auditd with SIGALRM).  If any
88  * other signals are received during that time, we call
89  * __audit_dowarn() to indicate that the queue may not have been fully
90  * flushed.
91  */
92 #define	ALRM_TIME	2
93 #define	SLEEP_TIME	20	/* # of seconds to sleep in all hard loop */
94 
95 #if DEBUG
96 #define	DPRINT(x) {(void) fprintf x; }
97 static FILE	*dbfp;	/* debug file */
98 #else
99 #define	DPRINT(x)
100 #endif /* DEBUG */
101 
102 static plugin_t	*binfile = NULL;
103 
104 static int	turn_audit_on  = AUC_AUDITING;
105 static int	turn_audit_off = AUC_NOAUDIT;
106 
107 static int	running = 1;
108 
109 /*
110  * GLOBALS:
111  */
112 plugin_t		*plugin_head = NULL;
113 static thr_data_t	main_thr;	/* auditd thread (0) */
114 pthread_mutex_t		plugin_mutex;	/* for plugin_t list */
115 
116 static int	caught_alrm = 0;	/* number of SIGALRMs pending */
117 static int	caught_readc = 0;	/* number of AU_SIG_READ_CONTROLs */
118 static int	caught_term = 0;	/* number of AU_SIG_DISABLEs pending */
119 static int	caught_nextd = 0;	/* number of AU_SIG_NEXT_DIRs pending */
120 
121 static int	reset_list = 1;	/* 1 to re-read audit_control */
122 static int	reset_file = 1; /* 1 to close/open binary log */
123 
124 static int	auditing_set = 0;	/* 1 if auditon(A_SETCOND, on... */
125 
126 static void	my_sleep();
127 static void	signal_thread();
128 static void	loadauditlist();
129 static void	block_signals();
130 static int	do_sethost();
131 
132 /* common exit function */
133 void
134 auditd_exit(int status)
135 {
136 #if MEM_TEST
137 	sigset_t	set;
138 
139 	DPRINT((dbfp, "mem_test intentional abort (status=%d)\n",
140 	    status));
141 	abort();
142 #endif
143 	DPRINT((dbfp, "%ld exit status = %d auditing_set = %d\n",
144 	    getpid(), status, auditing_set));
145 
146 	if (auditing_set)
147 		(void) auditon(A_SETCOND, (caddr_t)&turn_audit_off,
148 		    (int)sizeof (int));
149 
150 	exit(status);
151 }
152 
153 /* ARGSUSED */
154 main(int argc, char *argv[])
155 {
156 	auditinfo_addr_t	as_null;	/* audit state to set */
157 	au_id_t			auid;
158 	pthread_t		tid;
159 	plugin_t		*p;
160 	pid_t			pid;
161 
162 #if DEBUG
163 	/* LINTED */
164 	char			*envp;
165 	dbfp = __auditd_debug_file_open();
166 #endif
167 	(void) setsid();
168 
169 	/* Internationalization */
170 	(void) setlocale(LC_ALL, "");
171 	(void) textdomain(TEXT_DOMAIN);
172 
173 	/*
174 	 * Set the audit host-id.
175 	 */
176 	if (do_sethost() != 0) {
177 		__audit_dowarn("nostart", "", 0);
178 		auditd_exit(1);
179 	}
180 
181 	/*
182 	 * Turn off all auditing for this process.
183 	 */
184 	if (getaudit_addr(&as_null, sizeof (as_null)) == -1) {
185 		__audit_dowarn("nostart", "", 0);
186 		auditd_exit(2);
187 	}
188 	as_null.ai_mask.as_success = 0;
189 	as_null.ai_mask.as_failure = 0;
190 	(void) setaudit_addr(&as_null, sizeof (as_null));
191 	auid = AU_NOAUDITID;
192 	(void) setauid(&auid);
193 	/*
194 	 * Set the audit state flag to AUDITING.
195 	 */
196 	if (auditon(A_SETCOND, (caddr_t)&turn_audit_on, (int)sizeof (int)) !=
197 	    0) {
198 		DPRINT((dbfp, "auditon(A_SETCOND...) failed (exit)\n"));
199 		__audit_dowarn("nostart", "", 0);
200 		auditd_exit(7);
201 	}
202 
203 	block_signals();
204 
205 #if DEBUG
206 	/* output to dbfp shouldn't be duplicated by parent and child */
207 	(void) fflush(dbfp);
208 #endif
209 	/*
210 	 * wait for "ready" signal before exit -- for greenline
211 	 */
212 	if (fork()) {
213 		sigset_t	set;
214 		int		signal_caught = 0;
215 
216 		(void) sigemptyset(&set);
217 		(void) sigaddset(&set, AU_SIG_DISABLE);
218 
219 		while (signal_caught != AU_SIG_DISABLE)
220 			signal_caught = sigwait(&set);
221 
222 		DPRINT((dbfp, "init complete:  parent can now exit\n"));
223 
224 		auditd_exit(0);
225 	}
226 	pid = getppid();
227 
228 	auditing_set = 1;
229 
230 #if DEBUG && MEM_TEST
231 	envp = getenv("UMEM_DEBUG");
232 	if (envp != NULL)
233 		DPRINT((dbfp, "UMEM_DEBUG=%s\n", envp));
234 	envp = getenv("UMEM_LOGGING");
235 	if (envp != NULL)
236 		DPRINT((dbfp, "UMEM_LOGGING=%s\n", envp));
237 #endif
238 	DPRINT((dbfp, "auditd pid=%ld\n", getpid()));
239 
240 	/* thread 0 sync */
241 	(void) pthread_mutex_init(&(main_thr.thd_mutex), NULL);
242 	(void) pthread_cond_init(&(main_thr.thd_cv), NULL);
243 	(void) pthread_mutex_init(&plugin_mutex, NULL);
244 	/*
245 	 * Set up a separate thread for signal handling.
246 	 */
247 	if (pthread_create(&tid, NULL, (void *(*)(void *))signal_thread,
248 	    NULL)) {
249 		(void) fprintf(stderr, gettext(
250 		    "auditd can't create a thread\n"));
251 		auditd_exit(3);
252 	}
253 	/*
254 	 * Set the umask so that only audit or other users in the audit group
255 	 * can get to the files created by auditd.
256 	 */
257 	(void) umask(007);
258 
259 	if (__logpost("")) {	/* Open the audit_data file. */
260 		DPRINT((dbfp, "logpost failed\n"));
261 		auditd_exit(4);
262 	}
263 	/*
264 	 * Here is the main body of the audit daemon.  running == 0 means that
265 	 * after flushing out the audit queue, it is time to exit in response to
266 	 * AU_SIG_DISABLE
267 	 */
268 	while (running) {
269 		/*
270 		 * Read audit_control and create plugin lists.
271 		 *
272 		 * loadauditlist() and auditd_thread_init() are called
273 		 * while under the plugin_mutex lock to avoid a race
274 		 * with unload_plugin().
275 		 */
276 		if (reset_list || reset_file) {
277 			(void) pthread_mutex_lock(&plugin_mutex);
278 			if (reset_list)
279 				loadauditlist();
280 
281 			if (auditd_thread_init()) {
282 				auditd_thread_close();
283 				/* continue; wait for audit -s */
284 			}
285 			(void) pthread_mutex_unlock(&plugin_mutex);
286 			reset_list = 0;
287 		}
288 		/*
289 		 * tell parent I'm running whether or not the initialization
290 		 * actually worked.  The failure case is to wait for an
291 		 * audit -n or audit -s to fix the problem.
292 		 */
293 		if (pid != 0) {
294 			(void) kill(pid, AU_SIG_DISABLE);
295 			pid = 0;
296 		}
297 		/*
298 		 * thread_signal() signals main (this thread) when
299 		 * it has received a signal.
300 		 */
301 		DPRINT((dbfp, "main thread is waiting\n"));
302 		(void) pthread_mutex_lock(&(main_thr.thd_mutex));
303 
304 		if (!(caught_readc || caught_term || caught_alrm ||
305 		    caught_nextd))
306 			(void) pthread_cond_wait(&(main_thr.thd_cv),
307 			    &(main_thr.thd_mutex));
308 		(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
309 		/*
310 		 * Got here because a signal came in.
311 		 * Since we may have gotten more than one, we assume a
312 		 * priority scheme with SIGALRM being the most
313 		 * significant.
314 		 */
315 		if (caught_alrm) {
316 			/*
317 			 * We have returned from our timed wait for
318 			 * c2audit to calm down.  We need to really shut
319 			 * down here.
320 			 */
321 			caught_alrm = 0;
322 			running = 0;	/* shut down now */
323 		} else if (caught_term) {
324 			/*
325 			 * we are going to shut down, but need to
326 			 * allow time for the audit queues in
327 			 * c2audit and for the threads to empty.
328 			 */
329 
330 			p = plugin_head;
331 			while (p != NULL) {
332 				DPRINT((dbfp, "signalling thread %d\n",
333 				    p->plg_tid));
334 				(void) pthread_mutex_lock(&(p->plg_mutex));
335 				p->plg_removed = 1;
336 
337 				if (p->plg_initialized)
338 					(void) pthread_cond_signal(
339 					    &(p->plg_cv));
340 
341 				(void) pthread_mutex_unlock(&(p->plg_mutex));
342 				p = p->plg_next;
343 			}
344 
345 			caught_alrm = 0;
346 			caught_readc  = 0;
347 			caught_term = 0;
348 			caught_nextd = 0;
349 
350 			DPRINT((dbfp,
351 			    "main thread is pausing before exit.\n"));
352 			(void) pthread_mutex_lock(&(main_thr.thd_mutex));
353 			caught_alrm = 0;
354 			(void) alarm(ALRM_TIME);
355 			while (!caught_alrm)
356 				(void) pthread_cond_wait(&(main_thr.thd_cv),
357 				    &(main_thr.thd_mutex));
358 
359 			(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
360 
361 			running = 0;	/* Close down auditing and exit */
362 		} else if (caught_readc) {
363 			/*
364 			 * if both hup and usr1 are caught, the logic in
365 			 * loadauditlist() results in hup winning.  The
366 			 * result will be that the audit file is not rolled
367 			 * over unless audit_control actually changed.
368 			 *
369 			 * They want to reread the audit_control file.
370 			 * Set reset_list which will return us to the
371 			 * main while loop in the main routine.
372 			 */
373 			caught_readc = 0;
374 			reset_list = 1;
375 		} else if (caught_nextd) {
376 			/*
377 			 * This is a special case for the binfile
378 			 * plugin. (audit -n)  NULL out kvlist
379 			 * so binfile won't re-read audit_control
380 			 */
381 			caught_nextd = 0;
382 			reset_file = 1;
383 			if (binfile != NULL) {
384 				_kva_free(binfile->plg_kvlist);
385 				binfile->plg_kvlist = NULL;
386 				binfile->plg_reopen = 1;
387 			}
388 		}
389 	}	/* end while (running) */
390 	auditd_thread_close();
391 
392 	auditd_exit(0);
393 	return (0);
394 }
395 
396 /*
397  * my_sleep - sleep for SLEEP_TIME seconds but only accept the signals
398  *	that we want to accept.  (Premature termination just means the
399  *	caller retries more often, not a big deal.)
400  */
401 
402 static void
403 my_sleep()
404 {
405 	DPRINT((dbfp, "auditd: sleeping for 20 seconds\n"));
406 	/*
407 	 * Set timer to "sleep"
408 	 */
409 	(void) alarm(SLEEP_TIME);
410 
411 	DPRINT((dbfp, "main thread is waiting for SIGALRM before exit.\n"));
412 	(void) pthread_mutex_lock(&(main_thr.thd_mutex));
413 	(void) pthread_cond_wait(&(main_thr.thd_cv), &(main_thr.thd_mutex));
414 	(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
415 
416 	if (caught_term) {
417 		DPRINT((dbfp, "normal AU_SIG_DISABLE exit\n"));
418 		/*
419 		 * Exit, as requested.
420 		 */
421 		auditd_thread_close();
422 	}
423 	if (caught_readc)
424 		reset_list = 1;		/* Reread the audit_control file */
425 
426 	caught_readc = 0;
427 	caught_nextd = 0;
428 }
429 
430 /*
431  * search for $ISA/ in path and replace it with "" if auditd
432  * is 32 bit, else "sparcv9/"  The plugin $ISA must match however
433  * auditd was compiled.
434  */
435 
436 static void
437 isa_ified(char *path, char **newpath)
438 {
439 	char	*p, *q;
440 
441 	if (((p = strchr(path, '$')) != NULL) &&
442 	    (strncmp("$ISA/", p, 5) == 0)) {
443 		(void) memcpy(*newpath, path, p - path);
444 		q = *newpath + (p - path);
445 #ifdef __sparcv9
446 		q += strlcpy(q, "sparcv9/", avail_length);
447 #endif
448 		(void) strcpy(q, p + 5);
449 	} else
450 		*newpath = path;
451 }
452 
453 /*
454  * init_plugin first searches the existing plugin list to see
455  * if the plugin already has been defined; if not, it creates it
456  * and links it into the list.  It returns a pointer to the found
457  * or created struct.  A change of path in audit_control for a
458  * given plugin will cause a miss.
459  */
460 /*
461  * for 64 bits, the path name can grow 3 bytes (minus 5 for the
462  * removed "$ISA" and plus 8 for the added "sparcv9/"
463  */
464 
465 #define	ISA_GROW	8 - 5
466 
467 static plugin_t *
468 init_plugin(char *name, kva_t *list, int cnt_flag)
469 {
470 	plugin_t	*p, *q;
471 	char		filepath[MAXPATHLEN + 1 + ISA_GROW];
472 	char		*path = filepath;
473 
474 	if (*name != '/') {
475 #ifdef  __sparcv9
476 		(void) strcpy(filepath, "/usr/lib/security/sparcv9/");
477 #else
478 		(void) strcpy(filepath, "/usr/lib/security/");
479 #endif
480 		if (strlcat(filepath, name, MAXPATHLEN) >= MAXPATHLEN)
481 			return (NULL);
482 	} else {
483 		if (strlen(name) > MAXPATHLEN + ISA_GROW)
484 			return (NULL);
485 		isa_ified(name, &path);
486 	}
487 	p = plugin_head;
488 	q = plugin_head;
489 	while (p != NULL) {
490 		if (p->plg_path != NULL) {
491 			if (strcmp(p->plg_path, path) == 0) {
492 				p->plg_removed = 0;
493 				p->plg_to_be_removed = 0;
494 				p->plg_cnt = cnt_flag;
495 
496 				_kva_free(p->plg_kvlist);
497 				p->plg_kvlist = list;
498 				p->plg_reopen = 1;
499 				DPRINT((dbfp, "reusing %s\n", p->plg_path));
500 				return (p);
501 			}
502 		}
503 		q = p;
504 		p = p->plg_next;
505 	}
506 	DPRINT((dbfp, "creating new plugin structure for %s\n", path));
507 
508 	p = malloc(sizeof (plugin_t));
509 
510 	if (p == NULL) {
511 		perror("auditd");
512 		return (NULL);
513 	}
514 	if (q == NULL)
515 		plugin_head = p;
516 	else
517 		q->plg_next = p;
518 
519 	p->plg_next = NULL;
520 	p->plg_initialized = 0;
521 	p->plg_reopen = 1;
522 	p->plg_tid = 0;
523 	p->plg_removed = 0;
524 	p->plg_to_be_removed = 0;
525 	p->plg_tossed = 0;
526 	p->plg_queued = 0;
527 	p->plg_output = 0;
528 	p->plg_sequence = 1;
529 	p->plg_last_seq_out = 0;
530 	p->plg_path = strdup(path);
531 	p->plg_kvlist = list;
532 	p->plg_cnt = cnt_flag;
533 	p->plg_retry_time = SLEEP_TIME;
534 	p->plg_qmax = 0;
535 	p->plg_save_q_copy = NULL;
536 
537 	DPRINT((dbfp, "created plugin:  %s\n", path));
538 	return (p);
539 }
540 
541 /*
542  * loadauditlist - read the directory list from the audit_control file.
543  *		   to determine if a binary file is to be written.
544  *		 - read the plugin entries from the audit_control file
545  *
546  * globals -
547  *
548  *	plugin queues
549  *
550  * success is when at least one plug in is defined.
551  *
552  * set cnt policy here based on auditconfig setting.  future could
553  * have a policy = {+|-}cnt entry per plugin with auditconfig providing the
554  * default.
555  */
556 
557 static void
558 loadauditlist()
559 {
560 	char		buf[MAXPATHLEN];
561 	char		*value;
562 	plugin_t	*p;
563 	int		acresult;
564 	int		wait_count = 0;
565 	kva_t		*kvlist;
566 	long		policy;
567 	int		cnt_flag;
568 	struct au_qctrl	kqmax;
569 	au_acinfo_t	*ach = NULL;
570 	int		got_dir = 0;
571 	int		have_plugin = 0;
572 	char		*endptr;
573 
574 	if (auditon(A_GETPOLICY, (char *)&policy, 0) == -1) {
575 		DPRINT((dbfp, "auditon(A_GETPOLICY...) failed (exit)\n"));
576 		__audit_dowarn("auditoff", "", 0);
577 		auditd_thread_close();
578 		auditd_exit(5);
579 	}
580 	cnt_flag = ((policy & AUDIT_CNT) != 0) ? 1 : 0;
581 	DPRINT((dbfp, "loadauditlist:  policy is to %s\n", (cnt_flag == 1) ?
582 	    "continue" : "block"));
583 
584 #if DEBUG
585 	if (auditon(A_GETCOND, (caddr_t)&acresult, (int)sizeof (int)) !=
586 	    0)
587 		DPRINT((dbfp, "auditon(A_GETCOND...) failed (exit)\n"));
588 #endif
589 	DPRINT((dbfp, "audit cond = %d (1 is on)\n", acresult));
590 
591 
592 	if (auditon(A_GETQCTRL, (char *)&kqmax, sizeof (struct au_qctrl)) !=
593 	    0) {
594 		DPRINT((dbfp, "auditon(A_GETQCTRL...) failed (exit)\n"));
595 		__audit_dowarn("auditoff", "", 0);
596 		auditd_thread_close();
597 		auditd_exit(6);
598 	}
599 	kqmax.aq_hiwater *= 5;		/* RAM is cheaper in userspace */
600 	DPRINT((dbfp, "auditd: reading audit_control\n"));
601 
602 	p = plugin_head;
603 	/*
604 	 * two-step on setting p->plg_removed because the input thread
605 	 * in doorway.c uses p->plg_removed to decide if the plugin is
606 	 * active.
607 	 */
608 	while (p != NULL) {
609 		DPRINT((dbfp, "loadauditlist:  %X, %s previously created\n",
610 		    p, p->plg_path));
611 		p->plg_to_be_removed = 1;	/* tentative removal */
612 		p = p->plg_next;
613 	}
614 	/*
615 	 * have_plugin may over count by one if both a "dir" entry
616 	 * and a "plugin" entry for binfile are found.  All that
617 	 * matters is that it be zero if no plugin or dir entries
618 	 * are found.
619 	 */
620 	have_plugin = 0;
621 	for (;;) {
622 		/* NULL == use standard path for audit_control */
623 		ach = _openac(NULL);
624 		/*
625 		 * loop until a directory entry is found (0) or eof (-1)
626 		 */
627 		while (((acresult = _getacdir(ach, buf, sizeof (buf))) != 0) &&
628 		    acresult != -1) {
629 		}
630 		if (acresult == 0) {
631 			DPRINT((dbfp,
632 			    "loadauditlist: "
633 			    "got binfile via old config syntax\n"));
634 			/*
635 			 * A directory entry was found.
636 			 */
637 			got_dir = 1;
638 			kvlist = _str2kva("name=audit_binfile.so.1",
639 			    "=", ";");
640 
641 			p = init_plugin("audit_binfile.so.1", kvlist, cnt_flag);
642 
643 			if (p != NULL) {
644 				binfile = p;
645 				p->plg_qmax = kqmax.aq_hiwater;
646 				have_plugin++;
647 			}
648 		}
649 		/*
650 		 * collect plugin entries.  If there is an entry for
651 		 * binfile.so.1, the parameters from the plugin line
652 		 * override those set above.  For binfile, p_dir is
653 		 * required only if dir wasn't specified elsewhere in
654 		 * audit_control
655 		 */
656 		_rewindac(ach);
657 		while ((acresult = _getacplug(ach, &kvlist)) == 0) {
658 			value = kva_match(kvlist, "name");
659 			if (value == NULL)
660 				break;
661 			DPRINT((dbfp, "loadauditlist: have an entry for %s\n",
662 			    value));
663 			p = init_plugin(value, kvlist, cnt_flag);
664 			if (p == NULL)
665 				continue;
666 
667 			if (strstr(value, "/audit_binfile.so") != NULL) {
668 				binfile = p;
669 				if (!got_dir &&
670 				    (kva_match(kvlist, "p_dir") ==
671 				    NULL)) {
672 					__audit_dowarn("getacdir", "",
673 					    wait_count);
674 				}
675 			}
676 			p->plg_qmax = kqmax.aq_hiwater; /* default */
677 			value = kva_match(kvlist, "qsize");
678 			if (value != NULL) {
679 				long	tmp;
680 
681 				tmp = strtol(value, &endptr, 10);
682 				if (*endptr == '\0')
683 					p->plg_qmax = tmp;
684 			}
685 			DPRINT((dbfp, "%s queue max = %d\n",
686 				p->plg_path, p->plg_qmax));
687 
688 			have_plugin++;
689 		}
690 		_endac(ach);
691 		if (have_plugin != 0)
692 			break;
693 		/*
694 		 * there was a problem getting the directory
695 		 * list or remote host info from the audit_control file
696 		 */
697 		wait_count++;
698 #if	DEBUG
699 		if (wait_count < 2)
700 			DPRINT((dbfp,
701 			    "auditd: problem getting directory "
702 			    "/ or plugin list from audit_control.\n"));
703 #endif	/* DEBUG */
704 		__audit_dowarn("getacdir", "", wait_count);
705 		/*
706 		 * sleep for SLEEP_TIME seconds.
707 		 */
708 		my_sleep();
709 	}    /* end for(;;) */
710 
711 	p = plugin_head;
712 	while (p != NULL) {
713 		DPRINT((dbfp, "loadauditlist: %s remove flag=%d; cnt=%d\n",
714 		    p->plg_path, p->plg_to_be_removed, p->plg_cnt));
715 		p->plg_removed = p->plg_to_be_removed;
716 		p = p->plg_next;
717 	}
718 }
719 
720 /*
721  * block signals -- thread-specific blocking of the signals expected
722  * by the main thread.
723  */
724 
725 static void
726 block_signals()
727 {
728 	sigset_t	set;
729 
730 	(void) sigfillset(&set);
731 	(void) pthread_sigmask(SIG_BLOCK, &set, NULL);
732 }
733 
734 /*
735  * signal_thread is the designated signal catcher.  It wakes up the
736  * main thread whenever it receives a signal and then goes back to
737  * sleep; it does not exit.  The global variables caught_* let
738  * the main thread which signal was received.
739  *
740  * The thread is created with all signals blocked.
741  */
742 
743 static void
744 signal_thread()
745 {
746 	sigset_t	set;
747 	int		signal_caught;
748 
749 	DPRINT((dbfp, "the signal thread is thread %d\n",
750 	    pthread_self()));
751 
752 	(void) sigemptyset(&set);
753 	(void) sigaddset(&set, SIGALRM);
754 	(void) sigaddset(&set, AU_SIG_DISABLE);
755 	(void) sigaddset(&set, AU_SIG_READ_CONTROL);
756 	(void) sigaddset(&set, AU_SIG_NEXT_DIR);
757 
758 	for (;;) {
759 		signal_caught = sigwait(&set);
760 		switch (signal_caught) {
761 		case SIGALRM:
762 			caught_alrm++;
763 			DPRINT((dbfp, "caught SIGALRM\n"));
764 			break;
765 		case AU_SIG_DISABLE:
766 			caught_term++;
767 			DPRINT((dbfp, "caught AU_SIG_DISABLE\n"));
768 			break;
769 		case AU_SIG_READ_CONTROL:
770 			caught_readc++;
771 			DPRINT((dbfp, "caught AU_SIG_READ_CONTROL\n"));
772 			break;
773 		case AU_SIG_NEXT_DIR:
774 			caught_nextd++;
775 			DPRINT((dbfp, "caught AU_SIG_NEXT_DIR\n"));
776 			break;
777 		default:
778 			DPRINT((dbfp, "caught unexpected signal:  %d\n",
779 			    signal_caught));
780 			break;
781 		}
782 		(void) pthread_cond_signal(&(main_thr.thd_cv));
783 	}
784 }
785 
786 /*
787  * do_sethost - do auditon(2) to set the audit host-id.
788  *		Returns 0 if success, error code or -1 otherwise.
789  */
790 static int
791 do_sethost(void)
792 {
793 	int		err;
794 	char		host_name[MAXHOSTNAMELEN + 1];
795 	auditinfo_addr_t	audit_info;
796 	struct addrinfo	hints;
797 	struct addrinfo	*ai;
798 	int		addr_type;
799 	void		*p;
800 
801 	/* First, get our machine name and convert to IP address */
802 	if ((err = gethostname(host_name, sizeof (host_name)))) {
803 		return (err);
804 	}
805 	(void) memset(&hints, 0, sizeof (hints));
806 	hints.ai_family = PF_INET;
807 	err = getaddrinfo(host_name, NULL, &hints, &ai);
808 	if (err == 0) {
809 		addr_type = AU_IPv4;
810 		/* LINTED */
811 		p = &((struct sockaddr_in *)ai->ai_addr)->sin_addr;
812 	} else {
813 		hints.ai_family = PF_INET6;
814 		err = getaddrinfo(host_name, NULL, &hints, &ai);
815 		if (err != 0) {
816 			return (-1);
817 		}
818 		addr_type = AU_IPv6;
819 		/* LINTED */
820 		p = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
821 	}
822 
823 	/* Get current kernel audit info, and fill in the IP address */
824 	if ((err = auditon(A_GETKAUDIT, (caddr_t)&audit_info,
825 	    sizeof (audit_info))) < 0) {
826 		return (err);
827 	}
828 	audit_info.ai_termid.at_type = addr_type;
829 	(void) memcpy(&audit_info.ai_termid.at_addr[0], p,
830 	    addr_type);
831 
832 	freeaddrinfo(ai);
833 
834 	/* Update the kernel audit info with new IP address */
835 	if ((err = auditon(A_SETKAUDIT, (caddr_t)&audit_info,
836 	    sizeof (audit_info))) < 0) {
837 		return (err);
838 	}
839 
840 	return (0);
841 }
842