xref: /illumos-gate/usr/src/cmd/auditconfig/auditconfig.c (revision 528737823843346cf95a4a701612f82089135554)
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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * Copyright (c) 2019, Joyent, Inc.
27  */
28 
29 /*
30  * auditconfig - set and display audit parameters
31  */
32 
33 #include <locale.h>
34 #include <sys/types.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <stdarg.h>
38 #include <unistd.h>
39 #include <errno.h>
40 #include <sys/param.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <strings.h>
44 #include <nlist.h>
45 #include <fcntl.h>
46 #include <sys/socket.h>
47 #include <netdb.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <sys/mkdev.h>
51 #include <sys/param.h>
52 #include <pwd.h>
53 #include <libintl.h>
54 #include <zone.h>
55 #include <libscf_priv.h>
56 #include <tsol/label.h>
57 #include <bsm/libbsm.h>
58 #include <audit_policy.h>
59 #include <audit_scf.h>
60 
61 enum	commands {
62 	AC_ARG_ACONF,
63 	AC_ARG_AUDIT,
64 	AC_ARG_CHKACONF,
65 	AC_ARG_CHKCONF,
66 	AC_ARG_CONF,
67 	AC_ARG_GETASID,
68 	AC_ARG_GETAUDIT,
69 	AC_ARG_GETAUID,
70 	AC_ARG_GETCAR,
71 	AC_ARG_GETCLASS,
72 	AC_ARG_GETCOND,
73 	AC_ARG_GETCWD,
74 	AC_ARG_GETESTATE,
75 	AC_ARG_GETFLAGS,
76 	AC_ARG_GETKAUDIT,
77 	AC_ARG_GETKMASK,
78 	AC_ARG_GETNAFLAGS,
79 	AC_ARG_GETPINFO,
80 	AC_ARG_GETPLUGIN,
81 	AC_ARG_GETPOLICY,
82 	AC_ARG_GETQBUFSZ,
83 	AC_ARG_GETQCTRL,
84 	AC_ARG_GETQDELAY,
85 	AC_ARG_GETQHIWATER,
86 	AC_ARG_GETQLOWATER,
87 	AC_ARG_GETSTAT,
88 	AC_ARG_GETTERMID,
89 	AC_ARG_LSEVENT,
90 	AC_ARG_LSPOLICY,
91 	AC_ARG_SETASID,
92 	AC_ARG_SETAUDIT,
93 	AC_ARG_SETAUID,
94 	AC_ARG_SETCLASS,
95 	AC_ARG_SETFLAGS,
96 	AC_ARG_SETKAUDIT,
97 	AC_ARG_SETKMASK,
98 	AC_ARG_SETNAFLAGS,
99 	AC_ARG_SETPLUGIN,
100 	AC_ARG_SETPMASK,
101 	AC_ARG_SETPOLICY,
102 	AC_ARG_SETQBUFSZ,
103 	AC_ARG_SETQCTRL,
104 	AC_ARG_SETQDELAY,
105 	AC_ARG_SETQHIWATER,
106 	AC_ARG_SETQLOWATER,
107 	AC_ARG_SETSMASK,
108 	AC_ARG_SETSTAT,
109 	AC_ARG_SETUMASK,
110 	AC_ARG_SET_TEMPORARY
111 };
112 
113 #define	AC_KERN_EVENT		0
114 #define	AC_USER_EVENT		1
115 
116 #define	NONE(s) (!strlen(s) ? gettext("none") : s)
117 
118 #define	ONEK 1024
119 
120 /*
121  * remove this after the audit.h is fixed
122  */
123 struct arg_entry {
124 	char		*arg_str;
125 	char		*arg_opts;
126 	enum commands	auditconfig_cmd;
127 	boolean_t	temporary_allowed;	/* -t allowed for the option */
128 };
129 typedef struct arg_entry arg_entry_t;
130 
131 /* arg_table - command option and usage message table */
132 static arg_entry_t arg_table[] = {
133 	{ "-aconf",	"",			AC_ARG_ACONF,	B_FALSE},
134 	{ "-audit",	" event sorf retval string", AC_ARG_AUDIT, B_FALSE},
135 	{ "-chkaconf",	"",			AC_ARG_CHKACONF, B_FALSE},
136 	{ "-chkconf",	"",			AC_ARG_CHKCONF,	B_FALSE},
137 	{ "-conf",	"",			AC_ARG_CONF,	B_FALSE},
138 	{ "-getasid",	"",			AC_ARG_GETASID,	B_FALSE},
139 	{ "-getaudit",	"",			AC_ARG_GETAUDIT, B_FALSE},
140 	{ "-getauid",	"",			AC_ARG_GETAUID, B_FALSE},
141 	{ "-getcar",	"",			AC_ARG_GETCAR,	B_FALSE},
142 	{ "-getclass",	" event",		AC_ARG_GETCLASS, B_FALSE},
143 	{ "-getcond",	"",			AC_ARG_GETCOND,	B_FALSE},
144 	{ "-getcwd",	"",			AC_ARG_GETCWD,	B_FALSE},
145 	{ "-getestate",	" event",		AC_ARG_GETESTATE, B_FALSE},
146 	{ "-getflags",	"",			AC_ARG_GETFLAGS, B_FALSE},
147 	{ "-getkaudit",	"",			AC_ARG_GETKAUDIT, B_FALSE},
148 	{ "-getkmask",	"",			AC_ARG_GETKMASK, B_FALSE},
149 	{ "-getnaflags", "",			AC_ARG_GETNAFLAGS, B_FALSE},
150 	{ "-getpinfo",	" pid",			AC_ARG_GETPINFO, B_FALSE},
151 	{ "-getplugin",	" [plugin]",		AC_ARG_GETPLUGIN, B_FALSE},
152 	{ "-getpolicy",	"",			AC_ARG_GETPOLICY, B_TRUE},
153 	{ "-getqbufsz",	"",			AC_ARG_GETQBUFSZ, B_TRUE},
154 	{ "-getqctrl",	"",			AC_ARG_GETQCTRL, B_TRUE},
155 	{ "-getqdelay",	"",			AC_ARG_GETQDELAY, B_TRUE},
156 	{ "-getqhiwater", "",			AC_ARG_GETQHIWATER, B_TRUE},
157 	{ "-getqlowater", "",			AC_ARG_GETQLOWATER, B_TRUE},
158 	{ "-getstat",	"",			AC_ARG_GETSTAT,	B_FALSE},
159 	{ "-gettid",	"",			AC_ARG_GETTERMID, B_FALSE},
160 	{ "-lsevent",	"",			AC_ARG_LSEVENT,	B_FALSE},
161 	{ "-lspolicy",	"",			AC_ARG_LSPOLICY, B_FALSE},
162 	{ "-setasid",	" asid [cmd]",		AC_ARG_SETASID,	B_FALSE},
163 	{ "-setaudit",	" auid audit_flags termid asid [cmd]",
164 						AC_ARG_SETAUDIT, B_FALSE},
165 	{ "-setauid",	" auid [cmd]",		AC_ARG_SETAUID,	B_FALSE},
166 	{ "-setclass",	" event audit_flags",	AC_ARG_SETCLASS, B_FALSE},
167 	{ "-setflags",	" audit_flags",		AC_ARG_SETFLAGS, B_FALSE},
168 	{ "-setkaudit",	" type IP_address",	AC_ARG_SETKAUDIT, B_FALSE},
169 	{ "-setkmask",	" audit_flags",		AC_ARG_SETKMASK, B_FALSE},
170 	{ "-setnaflags", " audit_naflags",	AC_ARG_SETNAFLAGS, B_FALSE},
171 	{ "-setplugin",	" name active|inactive [attributes [qsize]]",
172 						AC_ARG_SETPLUGIN, B_FALSE},
173 	{ "-setpmask",	" pid audit_flags",	AC_ARG_SETPMASK, B_FALSE},
174 	{ "-setpolicy",	" [+|-]policy_flags",	AC_ARG_SETPOLICY, B_TRUE},
175 	{ "-setqbufsz",	" bufsz",		AC_ARG_SETQBUFSZ, B_TRUE},
176 	{ "-setqctrl",	" hiwater lowater bufsz delay",
177 						AC_ARG_SETQCTRL, B_TRUE},
178 	{ "-setqdelay",	" delay",		AC_ARG_SETQDELAY, B_TRUE},
179 	{ "-setqhiwater", " hiwater",		AC_ARG_SETQHIWATER, B_TRUE},
180 	{ "-setqlowater", " lowater",		AC_ARG_SETQLOWATER, B_TRUE},
181 	{ "-setsmask",	" asid audit_flags",	AC_ARG_SETSMASK, B_FALSE},
182 	{ "-setstat",	"",			AC_ARG_SETSTAT, B_FALSE},
183 	{ "-setumask",	" user audit_flags",	AC_ARG_SETUMASK, B_FALSE},
184 	{ "-t",		"",			AC_ARG_SET_TEMPORARY, B_FALSE},
185 };
186 
187 #define	ARG_TBL_SZ (sizeof (arg_table) / sizeof (arg_entry_t))
188 
189 char	*progname = "auditconfig";
190 
191 /*
192  * temporary_set true to get/set only kernel settings,
193  *		 false to get/set kernel settings and service properties
194  */
195 static boolean_t temporary_set = B_FALSE;
196 
197 static au_event_ent_t *egetauevnam(char *event_name);
198 static au_event_ent_t *egetauevnum(au_event_t event_number);
199 static int arg_ent_compare(const void *aep1, const void *aep2);
200 static char *cond2str(void);
201 static int policy2str(uint32_t policy, char *policy_str, size_t len);
202 static int str2type(char *s, uint_t *type);
203 static int str2policy(char *policy_str, uint32_t *policy_mask);
204 static int str2ipaddr(char *s, uint32_t *addr, uint32_t type);
205 static int strisipaddr(char *s);
206 static int strisnum(char *s);
207 static arg_entry_t *get_arg_ent(char *arg_str);
208 static uid_t get_user_id(char *user);
209 static void chk_arg_len(char *argv, uint_t len);
210 static void chk_event_num(int etype, au_event_t event);
211 static void chk_event_str(int etype, char *event_str);
212 static void chk_known_plugin(char *plugin_str);
213 static void chk_retval(char *retval_str);
214 static void chk_sorf(char *sorf_str);
215 static void do_aconf(void);
216 static void do_args(char **argv, au_mask_t *mask);
217 static void do_audit(char *, char, int, char *);
218 static void do_chkaconf(void);
219 static void do_chkconf(void);
220 static void do_conf(void);
221 static void do_getasid(void);
222 static void do_getaudit(void);
223 static void do_getkaudit(void);
224 static void do_setkaudit(char *t, char *s);
225 static void do_getauid(void);
226 static void do_getcar(void);
227 static void do_getclass(char *event_str);
228 static void do_getcond(void);
229 static void do_getcwd(void);
230 static void do_getflags(void);
231 static void do_getkmask(void);
232 static void do_getnaflags(void);
233 static void do_getpinfo(char *pid_str);
234 static void do_getplugin(char *plugin_str);
235 static void do_getpolicy(void);
236 static void do_getqbufsz(void);
237 static void do_getqctrl(void);
238 static void do_getqdelay(void);
239 static void do_getqhiwater(void);
240 static void do_getqlowater(void);
241 static void do_getstat(void);
242 static void do_gettermid(void);
243 static void do_lsevent(void);
244 static void do_lspolicy(void);
245 static void do_setasid(char *sid_str, char **argv);
246 static void do_setaudit(char *user_str, char *mask_str, char *tid_str,
247     char *sid_str, char **argv);
248 static void do_setauid(char *user, char **argv);
249 static void do_setclass(char *event_str, au_mask_t *mask);
250 static void do_setflags(char *audit_flags, au_mask_t *amask);
251 static void do_setkmask(au_mask_t *pmask);
252 static void do_setnaflags(char *audit_naflags, au_mask_t *namask);
253 static void do_setpmask(char *pid_str, au_mask_t *mask);
254 static void do_setsmask(char *asid_str, au_mask_t *mask);
255 static void do_setumask(char *auid_str, au_mask_t *mask);
256 static void do_setplugin(char *plugin_str, boolean_t plugin_state,
257     char *plugin_attr, int plugin_qsize);
258 static void do_setpolicy(char *policy_str);
259 static void do_setqbufsz(char *bufsz);
260 static void do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay);
261 static void do_setqdelay(char *delay);
262 static void do_setqhiwater(char *hiwater);
263 static void do_setqlowater(char *lowater);
264 static void do_setstat(void);
265 static void str2tid(char *tid_str, au_tid_addr_t *tp);
266 
267 static void eauditon(int cmd, caddr_t data, int length);
268 static void echkflags(char *auditflags, au_mask_t *mask);
269 static void egetaudit(auditinfo_addr_t *ai, int size);
270 static void egetauditflagsbin(char *auditflags, au_mask_t *pmask);
271 static void egetauid(au_id_t *auid);
272 static void egetkaudit(auditinfo_addr_t *ai, int size);
273 static void esetaudit(auditinfo_addr_t *ai, int size);
274 static void esetauid(au_id_t *auid);
275 static void esetkaudit(auditinfo_addr_t *ai, int size);
276 static void execit(char **argv);
277 static void exit_error(char *fmt, ...);
278 static void exit_usage(int status);
279 static void parse_args(int argc, char **argv, au_mask_t *mask);
280 static void print_asid(au_asid_t asid);
281 static void print_auid(au_id_t auid);
282 static void print_mask(char *desc, au_mask_t *pmp);
283 static void print_plugin(char *plugin_name, kva_t *plugin_kva);
284 static void print_tid_ex(au_tid_addr_t *tidp);
285 
286 #if !defined(TEXT_DOMAIN)
287 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
288 #endif
289 
290 int
291 main(int argc, char **argv)
292 {
293 	au_mask_t mask;			/* for options manipulating flags */
294 
295 	(void) setlocale(LC_ALL, "");
296 	(void) textdomain(TEXT_DOMAIN);
297 
298 	if (argc == 1) {
299 		exit_usage(0);
300 	}
301 
302 	if (argc == 2 &&
303 	    (argv[1][0] == '?' ||
304 	    strcmp(argv[1], "-h") == 0 ||
305 	    strcmp(argv[1], "-?") == 0)) {
306 		exit_usage(0);
307 	}
308 
309 	parse_args(argc, argv, &mask);
310 	do_args(argv, &mask);
311 
312 	return (0);
313 }
314 
315 /*
316  * parse_args()
317  *     Desc: Checks command line argument syntax.
318  *     Inputs: Command line argv;
319  *     Returns: If a syntax error is detected, a usage message is printed
320  *              and exit() is called. If a syntax error is not detected,
321  *              parse_args() returns without a value.
322  */
323 static void
324 parse_args(int argc, char **argv, au_mask_t *mask)
325 {
326 	arg_entry_t *ae;
327 
328 	uint_t type;
329 	uint_t addr[4];
330 
331 	for (++argv; *argv; argv++) {
332 		if ((ae = get_arg_ent(*argv)) == NULL) {
333 			exit_usage(1);
334 		}
335 
336 		switch (ae->auditconfig_cmd) {
337 
338 		case AC_ARG_AUDIT:
339 			++argv;
340 			if (!*argv)
341 				exit_usage(1);
342 			if (strisnum(*argv)) {
343 				chk_event_num(AC_USER_EVENT,
344 				    (au_event_t)atol(*argv));
345 			} else {
346 				chk_event_str(AC_USER_EVENT, *argv);
347 			}
348 			++argv;
349 			if (!*argv)
350 				exit_usage(1);
351 			chk_sorf(*argv);
352 			++argv;
353 			if (!*argv)
354 				exit_usage(1);
355 			chk_retval(*argv);
356 			++argv;
357 			if (!*argv)
358 				exit_usage(1);
359 			break;
360 
361 		case AC_ARG_CHKCONF:
362 		case AC_ARG_CONF:
363 		case AC_ARG_ACONF:
364 		case AC_ARG_CHKACONF:
365 		case AC_ARG_GETASID:
366 		case AC_ARG_GETAUID:
367 		case AC_ARG_GETAUDIT:
368 		case AC_ARG_GETKAUDIT:
369 			break;
370 
371 		case AC_ARG_GETCLASS:
372 		case AC_ARG_GETESTATE:
373 			++argv;
374 			if (!*argv)
375 				exit_usage(1);
376 			if (strisnum(*argv)) {
377 				chk_event_num(AC_KERN_EVENT,
378 				    (au_event_t)atol(*argv));
379 			} else {
380 				chk_event_str(AC_KERN_EVENT, *argv);
381 			}
382 			break;
383 
384 		case AC_ARG_GETCAR:
385 		case AC_ARG_GETCOND:
386 		case AC_ARG_GETCWD:
387 		case AC_ARG_GETFLAGS:
388 		case AC_ARG_GETKMASK:
389 		case AC_ARG_GETNAFLAGS:
390 			break;
391 
392 		case AC_ARG_GETPLUGIN:
393 			if (*++argv == NULL) {
394 				--argv;
395 				break;
396 			}
397 			if (get_arg_ent(*argv) != NULL) {
398 				--argv;
399 			} else {
400 				chk_arg_len(*argv, PLUGIN_MAXBUF);
401 				chk_known_plugin(*argv);
402 			}
403 			break;
404 
405 		case AC_ARG_GETPOLICY:
406 		case AC_ARG_GETQBUFSZ:
407 		case AC_ARG_GETQCTRL:
408 		case AC_ARG_GETQDELAY:
409 		case AC_ARG_GETQHIWATER:
410 		case AC_ARG_GETQLOWATER:
411 		case AC_ARG_GETSTAT:
412 		case AC_ARG_GETTERMID:
413 		case AC_ARG_LSEVENT:
414 		case AC_ARG_LSPOLICY:
415 			break;
416 
417 		case AC_ARG_SETASID:
418 		case AC_ARG_SETAUID:
419 		case AC_ARG_SETAUDIT:
420 			++argv;
421 			if (!*argv)
422 				exit_usage(1);
423 
424 			while (*argv)
425 				++argv;
426 			--argv;
427 
428 			break;
429 
430 		case AC_ARG_SETKAUDIT:
431 			++argv;
432 			if (!*argv)
433 				exit_usage(1);
434 			if (str2type (*argv, &type))
435 				exit_error(gettext(
436 				    "Invalid IP address type specified."));
437 			++argv;
438 			if (!*argv)
439 				exit_usage(1);
440 
441 			if (str2ipaddr(*argv, addr, type))
442 				exit_error(
443 				    gettext("Invalid IP address specified."));
444 			break;
445 
446 		case AC_ARG_SETCLASS:
447 			++argv;
448 			if (!*argv)
449 				exit_usage(1);
450 			if (strisnum(*argv))
451 				chk_event_num(AC_KERN_EVENT,
452 				    (au_event_t)atol(*argv));
453 			else
454 				chk_event_str(AC_KERN_EVENT, *argv);
455 			++argv;
456 			if (!*argv)
457 				exit_usage(1);
458 			echkflags(*argv, mask);
459 			break;
460 
461 		case AC_ARG_SETFLAGS:
462 			++argv;
463 			if (!*argv)
464 				exit_usage(1);
465 			chk_arg_len(*argv, PRESELECTION_MAXBUF);
466 			echkflags(*argv, mask);
467 			break;
468 
469 		case AC_ARG_SETKMASK:
470 			++argv;
471 			if (!*argv)
472 				exit_usage(1);
473 			echkflags(*argv, mask);
474 			break;
475 
476 		case AC_ARG_SETNAFLAGS:
477 			++argv;
478 			if (!*argv)
479 				exit_usage(1);
480 			chk_arg_len(*argv, PRESELECTION_MAXBUF);
481 			echkflags(*argv, mask);
482 			break;
483 
484 		case AC_ARG_SETPLUGIN:
485 			if (*++argv == NULL || get_arg_ent(*argv) != NULL) {
486 				exit_usage(1);
487 			}
488 			chk_known_plugin(*argv);
489 			chk_arg_len(*argv, PLUGIN_MAXBUF);
490 			if (*++argv == NULL || strcmp(*argv, "active") != 0 &&
491 			    strcmp(*argv, "inactive") != 0) {
492 				exit_usage(1);
493 			}
494 			if (*++argv == NULL || get_arg_ent(*argv) != NULL) {
495 				--argv;
496 				break;
497 			}
498 			chk_arg_len(*argv, PLUGIN_MAXATT);
499 			if (*++argv == NULL || get_arg_ent(*argv) != NULL) {
500 				--argv;
501 				break;
502 			}
503 			if (atoi(*argv) < 0) {
504 				exit_error(gettext("Incorrect qsize specified "
505 				    "(%s)."), *argv);
506 			}
507 			break;
508 
509 		case AC_ARG_SETPOLICY:
510 			++argv;
511 			if (!*argv)
512 				exit_usage(1);
513 			break;
514 
515 		case AC_ARG_SETSTAT:
516 			break;
517 
518 		case AC_ARG_GETPINFO:
519 			++argv;
520 			if (!*argv)
521 				exit_usage(1);
522 			break;
523 
524 		case AC_ARG_SETPMASK:
525 			++argv;
526 			if (!*argv)
527 				exit_usage(1);
528 			++argv;
529 			if (!*argv)
530 				exit_usage(1);
531 			echkflags(*argv, mask);
532 			break;
533 
534 		case AC_ARG_SETQBUFSZ:
535 			++argv;
536 			if (!*argv)
537 				exit_usage(1);
538 			if (!strisnum(*argv))
539 				exit_error(gettext("Invalid bufsz specified."));
540 			break;
541 
542 		case AC_ARG_SETQCTRL:
543 			++argv;
544 			if (!*argv)
545 				exit_usage(1);
546 			if (!strisnum(*argv))
547 				exit_error(
548 				    gettext("Invalid hiwater specified."));
549 			++argv;
550 			if (!*argv)
551 				exit_usage(1);
552 			if (!strisnum(*argv))
553 				exit_error(
554 				    gettext("Invalid lowater specified."));
555 			++argv;
556 			if (!*argv)
557 				exit_usage(1);
558 			if (!strisnum(*argv))
559 				exit_error(gettext("Invalid bufsz specified."));
560 			++argv;
561 			if (!*argv)
562 				exit_usage(1);
563 			if (!strisnum(*argv))
564 				exit_error(gettext("Invalid delay specified."));
565 			break;
566 
567 		case AC_ARG_SETQDELAY:
568 			++argv;
569 			if (!*argv)
570 				exit_usage(1);
571 			if (!strisnum(*argv))
572 				exit_error(gettext("Invalid delay specified."));
573 			break;
574 
575 		case AC_ARG_SETQHIWATER:
576 			++argv;
577 			if (!*argv)
578 				exit_usage(1);
579 			if (!strisnum(*argv)) {
580 				exit_error(
581 				    gettext("Invalid hiwater specified."));
582 			}
583 			break;
584 
585 		case AC_ARG_SETQLOWATER:
586 			++argv;
587 			if (!*argv)
588 				exit_usage(1);
589 			if (!strisnum(*argv)) {
590 				exit_error(
591 				    gettext("Invalid lowater specified."));
592 			}
593 			break;
594 
595 		case AC_ARG_SETSMASK:
596 		case AC_ARG_SETUMASK:
597 			++argv;
598 			if (!*argv)
599 				exit_usage(1);
600 			++argv;
601 			if (!*argv)
602 				exit_usage(1);
603 			echkflags(*argv, mask);
604 			break;
605 
606 		case AC_ARG_SET_TEMPORARY:
607 			/* Do not accept single -t option. */
608 			if (argc == 2) {
609 				exit_error(
610 				    gettext("Only the -t option specified "
611 				    "(it is not a standalone option)."));
612 			}
613 			temporary_set = B_TRUE;
614 			break;
615 
616 		default:
617 			exit_error(gettext("Internal error #1."));
618 			break;
619 		}
620 	}
621 }
622 
623 
624 /*
625  * do_args() - do command line arguments in the order in which they appear.
626  * Function return values returned by the underlying functions; the semantics
627  * they should follow is to return B_TRUE on successful execution, B_FALSE
628  * otherwise.
629  */
630 static void
631 do_args(char **argv, au_mask_t *mask)
632 {
633 	arg_entry_t	*ae;
634 
635 	for (++argv; *argv; argv++) {
636 		ae = get_arg_ent(*argv);
637 
638 		switch (ae->auditconfig_cmd) {
639 
640 		case AC_ARG_AUDIT:
641 			{
642 				char sorf;
643 				int  retval;
644 				char *event_name;
645 				char *audit_str;
646 
647 				++argv;
648 				event_name = *argv;
649 				++argv;
650 				sorf = (char)atoi(*argv);
651 				++argv;
652 				retval = atoi(*argv);
653 				++argv;
654 				audit_str = *argv;
655 				do_audit(event_name, sorf, retval, audit_str);
656 			}
657 			break;
658 
659 		case AC_ARG_CHKCONF:
660 			do_chkconf();
661 			break;
662 
663 		case AC_ARG_CONF:
664 			do_conf();
665 			break;
666 
667 		case AC_ARG_CHKACONF:
668 			do_chkaconf();
669 			break;
670 
671 		case AC_ARG_ACONF:
672 			do_aconf();
673 			break;
674 
675 		case AC_ARG_GETASID:
676 			do_getasid();
677 			break;
678 
679 		case AC_ARG_GETAUID:
680 			do_getauid();
681 			break;
682 
683 		case AC_ARG_GETAUDIT:
684 			do_getaudit();
685 			break;
686 
687 		case AC_ARG_GETKAUDIT:
688 			do_getkaudit();
689 			break;
690 
691 		case AC_ARG_GETCLASS:
692 		case AC_ARG_GETESTATE:
693 			++argv;
694 			do_getclass(*argv);
695 			break;
696 
697 		case AC_ARG_GETCAR:
698 			do_getcar();
699 			break;
700 
701 		case AC_ARG_GETCOND:
702 			do_getcond();
703 			break;
704 
705 		case AC_ARG_GETCWD:
706 			do_getcwd();
707 			break;
708 
709 		case AC_ARG_GETFLAGS:
710 			do_getflags();
711 			break;
712 
713 		case AC_ARG_GETKMASK:
714 			do_getkmask();
715 			break;
716 
717 		case AC_ARG_GETNAFLAGS:
718 			do_getnaflags();
719 			break;
720 
721 		case AC_ARG_GETPLUGIN:
722 			{
723 				char	*plugin_str = NULL;
724 
725 				++argv;
726 				if (*argv != NULL) {
727 					if (get_arg_ent(*argv) != NULL) {
728 						--argv;
729 					} else {
730 						plugin_str = *argv;
731 					}
732 				} else {
733 					--argv;
734 				}
735 
736 				do_getplugin(plugin_str);
737 			}
738 			break;
739 
740 		case AC_ARG_GETPOLICY:
741 			do_getpolicy();
742 			break;
743 
744 		case AC_ARG_GETQBUFSZ:
745 			do_getqbufsz();
746 			break;
747 
748 		case AC_ARG_GETQCTRL:
749 			do_getqctrl();
750 			break;
751 
752 		case AC_ARG_GETQDELAY:
753 			do_getqdelay();
754 			break;
755 
756 		case AC_ARG_GETQHIWATER:
757 			do_getqhiwater();
758 			break;
759 
760 		case AC_ARG_GETQLOWATER:
761 			do_getqlowater();
762 			break;
763 
764 		case AC_ARG_GETSTAT:
765 			do_getstat();
766 			break;
767 
768 		case AC_ARG_GETTERMID:
769 			do_gettermid();
770 			break;
771 
772 		case AC_ARG_LSEVENT:
773 			do_lsevent();
774 			break;
775 
776 		case AC_ARG_LSPOLICY:
777 			do_lspolicy();
778 			break;
779 
780 		case AC_ARG_SETASID:
781 			{
782 				char *sid_str;
783 
784 				++argv;
785 				sid_str = *argv;
786 				++argv;
787 				do_setasid(sid_str, argv);
788 			}
789 			break;
790 
791 		case AC_ARG_SETAUID:
792 			{
793 				char *user;
794 
795 				++argv;
796 				user = *argv;
797 				++argv;
798 				do_setauid(user, argv);
799 			}
800 			break;
801 
802 		case AC_ARG_SETAUDIT:
803 			{
804 				char *user_str;
805 				char *mask_str;
806 				char *tid_str;
807 				char *sid_str;
808 
809 				++argv;
810 				user_str = *argv;
811 				++argv;
812 				mask_str = *argv;
813 				++argv;
814 				tid_str = *argv;
815 				++argv;
816 				sid_str = *argv;
817 				++argv;
818 				do_setaudit(user_str, mask_str, tid_str,
819 				    sid_str, argv);
820 			}
821 			break;
822 
823 		case AC_ARG_SETKAUDIT:
824 			{
825 				char *address_type, *address;
826 
827 				++argv; address_type = *argv;
828 				++argv; address = *argv;
829 				do_setkaudit(address_type, address);
830 			}
831 			break;
832 
833 		case AC_ARG_SETCLASS:
834 			{
835 				char *event_str;
836 
837 				++argv;
838 				event_str = *argv;
839 				do_setclass(event_str, mask);
840 
841 				++argv;
842 			}
843 			break;
844 
845 		case AC_ARG_SETFLAGS:
846 			++argv;
847 			do_setflags(*argv, mask);
848 			break;
849 
850 		case AC_ARG_SETKMASK:
851 			++argv;
852 			do_setkmask(mask);
853 			break;
854 
855 		case AC_ARG_SETNAFLAGS:
856 			++argv;
857 			do_setnaflags(*argv, mask);
858 			break;
859 
860 		case AC_ARG_SETPLUGIN:
861 			{
862 				char		*plugin_str = NULL;
863 				boolean_t	plugin_state = B_FALSE;
864 				char		*plugin_att = NULL;
865 				int		plugin_qsize = -1;
866 
867 				plugin_str = *++argv;
868 				if (strcmp(*++argv, "active") == 0) {
869 					plugin_state = B_TRUE;
870 				}
871 				if (*++argv != NULL &&
872 				    get_arg_ent(*argv) == NULL) {
873 					plugin_att = *argv;
874 					if (*++argv != NULL &&
875 					    get_arg_ent(*argv) == NULL) {
876 						plugin_qsize = atoi(*argv);
877 					} else {
878 						--argv;
879 					}
880 				} else {
881 					--argv;
882 				}
883 
884 				do_setplugin(plugin_str, plugin_state,
885 				    plugin_att, plugin_qsize);
886 			}
887 			break;
888 
889 		case AC_ARG_SETPOLICY:
890 			++argv;
891 			do_setpolicy(*argv);
892 			break;
893 
894 		case AC_ARG_GETPINFO:
895 			{
896 				char *pid_str;
897 
898 				++argv;
899 				pid_str = *argv;
900 				do_getpinfo(pid_str);
901 			}
902 			break;
903 
904 		case AC_ARG_SETPMASK:
905 			{
906 				char *pid_str;
907 
908 				++argv;
909 				pid_str = *argv;
910 				do_setpmask(pid_str, mask);
911 
912 				++argv;
913 			}
914 			break;
915 
916 		case AC_ARG_SETSTAT:
917 			do_setstat();
918 			break;
919 
920 		case AC_ARG_SETQBUFSZ:
921 			++argv;
922 			do_setqbufsz(*argv);
923 			break;
924 
925 		case AC_ARG_SETQCTRL:
926 			{
927 				char *hiwater, *lowater, *bufsz, *delay;
928 
929 				++argv; hiwater = *argv;
930 				++argv; lowater = *argv;
931 				++argv; bufsz = *argv;
932 				++argv; delay = *argv;
933 				do_setqctrl(hiwater, lowater, bufsz, delay);
934 			}
935 			break;
936 		case AC_ARG_SETQDELAY:
937 			++argv;
938 			do_setqdelay(*argv);
939 			break;
940 
941 		case AC_ARG_SETQHIWATER:
942 			++argv;
943 			do_setqhiwater(*argv);
944 			break;
945 
946 		case AC_ARG_SETQLOWATER:
947 			++argv;
948 			do_setqlowater(*argv);
949 			break;
950 
951 		case AC_ARG_SETSMASK:
952 			{
953 				char *asid_str;
954 
955 				++argv;
956 				asid_str = *argv;
957 				do_setsmask(asid_str, mask);
958 
959 				++argv;
960 			}
961 			break;
962 		case AC_ARG_SETUMASK:
963 			{
964 				char *auid_str;
965 
966 				++argv;
967 				auid_str = *argv;
968 				do_setumask(auid_str, mask);
969 
970 				++argv;
971 			}
972 			break;
973 		case AC_ARG_SET_TEMPORARY:
974 			break;
975 
976 		default:
977 			exit_error(gettext("Internal error #2."));
978 			break;
979 		}
980 	}
981 }
982 
983 /*
984  * do_chkconf() - the returned value is for the global zone unless AUDIT_PERZONE
985  * is set.
986  */
987 static void
988 do_chkconf(void)
989 {
990 	register au_event_ent_t *evp;
991 	au_mask_t pmask;
992 	char conf_aflags[256];
993 	char run_aflags[256];
994 	au_stat_t as;
995 	int class;
996 	int			len;
997 	struct au_evclass_map	cmap;
998 
999 	pmask.am_success = pmask.am_failure = 0;
1000 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
1001 
1002 	setauevent();
1003 	if (getauevent() == NULL) {
1004 		exit_error(gettext("NO AUDIT EVENTS: Could not read %s\n."),
1005 		    AUDITEVENTFILE);
1006 	}
1007 
1008 	setauevent();
1009 	while ((evp = getauevent()) != NULL) {
1010 		cmap.ec_number = evp->ae_number;
1011 		len = sizeof (struct au_evclass_map);
1012 		if (evp->ae_number <= as.as_numevent) {
1013 			if (auditon(A_GETCLASS, (caddr_t)&cmap, len) == -1) {
1014 				(void) printf("%s(%hu):%s",
1015 				    evp->ae_name, evp->ae_number,
1016 				    gettext("UNKNOWN EVENT: Could not get "
1017 				    "class for event. Configuration may "
1018 				    "be bad.\n"));
1019 			} else {
1020 				class = cmap.ec_class;
1021 				if (class != evp->ae_class) {
1022 					conf_aflags[0] = run_aflags[0] = '\0';
1023 					pmask.am_success = class;
1024 					pmask.am_failure = class;
1025 					(void) getauditflagschar(run_aflags,
1026 					    &pmask, 0);
1027 					pmask.am_success = evp->ae_class;
1028 					pmask.am_failure = evp->ae_class;
1029 					(void) getauditflagschar(conf_aflags,
1030 					    &pmask, 0);
1031 
1032 					(void) printf(gettext(
1033 					    "%s(%hu): CLASS MISMATCH: "
1034 					    "runtime class (%s) != "
1035 					    "configured class (%s)\n"),
1036 					    evp->ae_name, evp->ae_number,
1037 					    NONE(run_aflags),
1038 					    NONE(conf_aflags));
1039 				}
1040 			}
1041 		}
1042 	}
1043 	endauevent();
1044 }
1045 
1046 /*
1047  * do_conf() - configure the kernel events. The value returned to the user is
1048  * for the global zone unless AUDIT_PERZONE is set.
1049  */
1050 static void
1051 do_conf(void)
1052 {
1053 	register au_event_ent_t *evp;
1054 	register int i;
1055 	au_evclass_map_t ec;
1056 	au_stat_t as;
1057 
1058 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
1059 
1060 	i = 0;
1061 	setauevent();
1062 	while ((evp = getauevent()) != NULL) {
1063 		if (evp->ae_number <= as.as_numevent) {
1064 			++i;
1065 			ec.ec_number = evp->ae_number;
1066 			ec.ec_class = evp->ae_class;
1067 			eauditon(A_SETCLASS, (caddr_t)&ec, sizeof (ec));
1068 		}
1069 	}
1070 	endauevent();
1071 	(void) printf(gettext("Configured %d kernel events.\n"), i);
1072 
1073 }
1074 
1075 /*
1076  * do_chkaconf() - report a mismatch if the runtime class mask of a kernel audit
1077  * event does not match the configured class mask. The value returned to the
1078  * user is for the global zone unless AUDIT_PERZONE is set.
1079  */
1080 static void
1081 do_chkaconf(void)
1082 {
1083 	char		*namask_cfg;
1084 	au_mask_t	pmask, kmask;
1085 
1086 	if (!do_getnaflags_scf(&namask_cfg) || namask_cfg == NULL) {
1087 		exit_error(gettext("Could not get configured value."));
1088 	}
1089 	egetauditflagsbin(namask_cfg, &pmask);
1090 
1091 	eauditon(A_GETKMASK, (caddr_t)&kmask, sizeof (kmask));
1092 
1093 	if ((pmask.am_success != kmask.am_success) ||
1094 	    (pmask.am_failure != kmask.am_failure)) {
1095 		char kbuf[2048];
1096 		if (getauditflagschar(kbuf, &kmask, 0) < 0) {
1097 			free(namask_cfg);
1098 			(void) fprintf(stderr,
1099 			    gettext("bad kernel non-attributable mask\n"));
1100 			exit(1);
1101 		}
1102 		(void) printf(
1103 		    gettext("non-attributable event flags mismatch:\n"));
1104 		(void) printf(gettext("active non-attributable audit flags "
1105 		    "= %s\n"), kbuf);
1106 		(void) printf(gettext("configured non-attributable audit flags "
1107 		    "= %s\n"), namask_cfg);
1108 	}
1109 	free(namask_cfg);
1110 }
1111 
1112 /*
1113  * do_aconf - configures the non-attributable events. The value returned to the
1114  * user is for the global zone unless AUDIT_PERZONE is set.
1115  */
1116 static void
1117 do_aconf(void)
1118 {
1119 	au_mask_t	namask;
1120 	char		*namask_cfg;
1121 
1122 	if (!do_getnaflags_scf(&namask_cfg) || namask_cfg == NULL) {
1123 		exit_error(gettext("Could not get configured value."));
1124 	}
1125 	egetauditflagsbin(namask_cfg, &namask);
1126 	free(namask_cfg);
1127 
1128 	eauditon(A_SETKMASK, (caddr_t)&namask, sizeof (namask));
1129 	(void) printf(gettext("Configured non-attributable event mask.\n"));
1130 }
1131 
1132 /*
1133  * do_audit() - construct an audit record for audit event event using the
1134  * process's audit characteristics containing a text token string audit_str. The
1135  * return token is constructed from the success/failure flag sort. Returned
1136  * value retval is an errno value.
1137  */
1138 static void
1139 do_audit(char *event, char sorf, int retval, char *audit_str)
1140 {
1141 	int rtn;
1142 	int rd;
1143 	au_event_t event_num;
1144 	au_event_ent_t *evp;
1145 	auditinfo_addr_t ai;
1146 	token_t *tokp;
1147 
1148 	egetaudit(&ai, sizeof (ai));
1149 
1150 	if (strisnum(event)) {
1151 		event_num = (au_event_t)atoi(event);
1152 		evp = egetauevnum(event_num);
1153 	} else {
1154 		evp = egetauevnam(event);
1155 	}
1156 
1157 	rtn = au_preselect(evp->ae_number, &ai.ai_mask, (int)sorf,
1158 	    AU_PRS_USECACHE);
1159 
1160 	if (rtn == -1) {
1161 		exit_error("%s\n%s %hu\n",
1162 		    gettext("Check audit event configuration."),
1163 		    gettext("Could not get audit class for event number"),
1164 		    evp->ae_number);
1165 	}
1166 
1167 	/* record is preselected */
1168 	if (rtn == 1) {
1169 		if ((rd = au_open()) == -1) {
1170 			exit_error(gettext(
1171 			    "Could not get and audit record descriptor\n"));
1172 		}
1173 		if ((tokp = au_to_me()) == NULL) {
1174 			exit_error(
1175 			    gettext("Could not allocate subject token\n"));
1176 		}
1177 		if (au_write(rd, tokp) == -1) {
1178 			exit_error(gettext("Could not construct subject token "
1179 			    "of audit record\n"));
1180 		}
1181 		if (is_system_labeled()) {
1182 			if ((tokp = au_to_mylabel()) == NULL) {
1183 				exit_error(gettext(
1184 				    "Could not allocate label token\n"));
1185 			}
1186 			if (au_write(rd, tokp) == -1) {
1187 				exit_error(gettext("Could not "
1188 				    "construct label token of audit record\n"));
1189 			}
1190 		}
1191 
1192 		if ((tokp = au_to_text(audit_str)) == NULL)
1193 			exit_error(gettext("Could not allocate text token\n"));
1194 		if (au_write(rd, tokp) == -1)
1195 			exit_error(gettext("Could not construct text token of "
1196 			    "audit record\n"));
1197 #ifdef _LP64
1198 		if ((tokp = au_to_return64(sorf, retval)) == NULL)
1199 #else
1200 		if ((tokp = au_to_return32(sorf, retval)) == NULL)
1201 #endif
1202 			exit_error(
1203 			    gettext("Could not allocate return token\n"));
1204 		if (au_write(rd, tokp) == -1) {
1205 			exit_error(gettext("Could not construct return token "
1206 			    "of audit record\n"));
1207 		}
1208 		if (au_close(rd, 1, evp->ae_number) == -1) {
1209 			exit_error(
1210 			    gettext("Could not write audit record: %s\n"),
1211 			    strerror(errno));
1212 		}
1213 	}
1214 }
1215 
1216 /*
1217  * do_getauid() - print the audit id of the current process.
1218  */
1219 static void
1220 do_getauid(void)
1221 {
1222 	au_id_t auid;
1223 
1224 	egetauid(&auid);
1225 	print_auid(auid);
1226 }
1227 
1228 /*
1229  * do_getaudit() - print the audit characteristics of the current process.
1230  */
1231 static void
1232 do_getaudit(void)
1233 {
1234 	auditinfo_addr_t ai;
1235 
1236 	egetaudit(&ai, sizeof (ai));
1237 	print_auid(ai.ai_auid);
1238 	print_mask(gettext("process preselection mask"), &ai.ai_mask);
1239 	print_tid_ex(&ai.ai_termid);
1240 	print_asid(ai.ai_asid);
1241 }
1242 
1243 /*
1244  * do_getkaudit() - print the audit characteristics of the current zone.
1245  */
1246 static void
1247 do_getkaudit(void)
1248 {
1249 	auditinfo_addr_t ai;
1250 
1251 	egetkaudit(&ai, sizeof (ai));
1252 	print_auid(ai.ai_auid);
1253 	print_mask(gettext("process preselection mask"), &ai.ai_mask);
1254 	print_tid_ex(&ai.ai_termid);
1255 	print_asid(ai.ai_asid);
1256 }
1257 
1258 /*
1259  * do_setkaudit() - set IP address_type/address of machine to specified values;
1260  * valid per zone if AUDIT_PERZONE is set, else only in global zone.
1261  */
1262 static void
1263 do_setkaudit(char *t, char *s)
1264 {
1265 	uint_t type;
1266 	auditinfo_addr_t ai;
1267 
1268 	egetkaudit(&ai, sizeof (ai));
1269 	(void) str2type(t, &type);
1270 	(void) str2ipaddr(s, &ai.ai_termid.at_addr[0], type);
1271 	ai.ai_termid.at_type = type;
1272 	esetkaudit(&ai, sizeof (ai));
1273 }
1274 
1275 /*
1276  * do_getcar() - print the zone-relative root
1277  */
1278 static void
1279 do_getcar(void)
1280 {
1281 	char path[MAXPATHLEN];
1282 
1283 	eauditon(A_GETCAR, (caddr_t)path, sizeof (path));
1284 	(void) printf(gettext("current active root = %s\n"), path);
1285 }
1286 
1287 /*
1288  * do_getclass() - print the preselection mask associated with the specified
1289  * kernel audit event. The displayed value is for the global zone unless
1290  * AUDIT_PERZONE is set.
1291  */
1292 static void
1293 do_getclass(char *event_str)
1294 {
1295 	au_evclass_map_t ec;
1296 	au_event_ent_t *evp;
1297 	au_event_t event_number;
1298 	char *event_name;
1299 
1300 	if (strisnum(event_str)) {
1301 		event_number = atol(event_str);
1302 		if ((evp = egetauevnum(event_number)) != NULL) {
1303 			event_number = evp->ae_number;
1304 			event_name = evp->ae_name;
1305 		} else {
1306 			event_name = gettext("unknown");
1307 		}
1308 	} else {
1309 		event_name = event_str;
1310 		if ((evp = egetauevnam(event_str)) != NULL) {
1311 			event_number = evp->ae_number;
1312 		}
1313 	}
1314 
1315 	ec.ec_number = event_number;
1316 	eauditon(A_GETCLASS, (caddr_t)&ec, 0);
1317 
1318 	(void) printf(gettext("audit class mask for event %s(%hu) = 0x%x\n"),
1319 	    event_name, event_number, ec.ec_class);
1320 }
1321 
1322 /*
1323  * do_getcond() - the printed value is for the global zone unless
1324  * AUDIT_PERZONE is set. (AUC_DISABLED is always global, the other states are
1325  * per zone if AUDIT_PERZONE is set)
1326  */
1327 static void
1328 do_getcond(void)
1329 {
1330 	(void) printf(gettext("audit condition = %s\n"), cond2str());
1331 }
1332 
1333 /*
1334  * do_getcwd() - the printed path is relative to the current zone root
1335  */
1336 static void
1337 do_getcwd(void)
1338 {
1339 	char path[MAXPATHLEN];
1340 
1341 	eauditon(A_GETCWD, (caddr_t)path, sizeof (path));
1342 	(void) printf(gettext("current working directory = %s\n"), path);
1343 }
1344 
1345 /*
1346  * do_getflags() - the printed value is for the global zone unless AUDIT_PERZONE
1347  * is set.
1348  */
1349 static void
1350 do_getflags(void)
1351 {
1352 	au_mask_t	amask;
1353 	char		*amask_cfg;
1354 
1355 	eauditon(A_GETAMASK, (caddr_t)&amask, sizeof (amask));
1356 	print_mask(gettext("active user default audit flags"), &amask);
1357 
1358 	if (!do_getflags_scf(&amask_cfg) || amask_cfg == NULL) {
1359 		exit_error(gettext("Could not get configured value."));
1360 	}
1361 	egetauditflagsbin(amask_cfg, &amask);
1362 	print_mask(gettext("configured user default audit flags"), &amask);
1363 	free(amask_cfg);
1364 }
1365 
1366 /*
1367  * do_getkmask() - the printed value is for the global zone unless AUDIT_PERZONE
1368  * is set.
1369  */
1370 static void
1371 do_getkmask(void)
1372 {
1373 	au_mask_t pmask;
1374 
1375 	eauditon(A_GETKMASK, (caddr_t)&pmask, sizeof (pmask));
1376 	print_mask(gettext("active non-attributable audit flags"), &pmask);
1377 }
1378 
1379 /*
1380  * do_getnaflags() - the printed value is for the global zone unless
1381  * AUDIT_PERZONE is set.
1382  */
1383 static void
1384 do_getnaflags(void)
1385 {
1386 	au_mask_t	namask;
1387 	char		*namask_cfg;
1388 
1389 	eauditon(A_GETKMASK, (caddr_t)&namask, sizeof (namask));
1390 	print_mask(gettext("active non-attributable audit flags"), &namask);
1391 
1392 	if (!do_getnaflags_scf(&namask_cfg) || namask_cfg == NULL) {
1393 		exit_error(gettext("Could not get configured value."));
1394 	}
1395 	egetauditflagsbin(namask_cfg, &namask);
1396 	print_mask(gettext("configured non-attributable audit flags"), &namask);
1397 	free(namask_cfg);
1398 }
1399 
1400 /*
1401  * do_getpolicy() - print active and configured kernel audit policy relative to
1402  * the current zone.
1403  */
1404 static void
1405 do_getpolicy(void)
1406 {
1407 	char			policy_str[1024];
1408 	uint32_t		policy;
1409 
1410 	if (!temporary_set) {
1411 		if (!do_getpolicy_scf(&policy)) {
1412 			exit_error(gettext("Could not get configured values."));
1413 		}
1414 		(void) policy2str(policy, policy_str, sizeof (policy_str));
1415 		(void) printf(gettext("configured audit policies = %s\n"),
1416 		    policy_str);
1417 	}
1418 
1419 	eauditon(A_GETPOLICY, (caddr_t)&policy, 0);
1420 	(void) policy2str(policy, policy_str, sizeof (policy_str));
1421 	(void) printf(gettext("active audit policies = %s\n"), policy_str);
1422 }
1423 
1424 
1425 /*
1426  * do_getpinfo() - print the audit ID, preselection mask, terminal ID, and
1427  * audit session ID for the specified process.
1428  */
1429 static void
1430 do_getpinfo(char *pid_str)
1431 {
1432 	struct auditpinfo_addr ap;
1433 
1434 	if (strisnum(pid_str))
1435 		ap.ap_pid = (pid_t)atoi(pid_str);
1436 	else
1437 		exit_usage(1);
1438 
1439 	eauditon(A_GETPINFO_ADDR, (caddr_t)&ap, sizeof (ap));
1440 
1441 	print_auid(ap.ap_auid);
1442 	print_mask(gettext("process preselection mask"), &(ap.ap_mask));
1443 	print_tid_ex(&(ap.ap_termid));
1444 	print_asid(ap.ap_asid);
1445 }
1446 
1447 /*
1448  * do_getplugin() - print plugin configuration.
1449  */
1450 static void
1451 do_getplugin(char *plugin_str)
1452 {
1453 	scf_plugin_kva_node_t	*plugin_kva_ll;
1454 	scf_plugin_kva_node_t	*plugin_kva_ll_head;
1455 
1456 	if (!do_getpluginconfig_scf(plugin_str, &plugin_kva_ll)) {
1457 		exit_error(gettext("Could not get plugin configuration."));
1458 	}
1459 
1460 	plugin_kva_ll_head = plugin_kva_ll;
1461 
1462 	while (plugin_kva_ll != NULL) {
1463 		print_plugin(plugin_kva_ll->plugin_name,
1464 		    plugin_kva_ll->plugin_kva);
1465 		plugin_kva_ll = plugin_kva_ll->next;
1466 		if (plugin_kva_ll != NULL) {
1467 			(void) printf("\n");
1468 		}
1469 	}
1470 	plugin_kva_ll_free(plugin_kva_ll_head);
1471 }
1472 
1473 /*
1474  * do_getqbufsz() - print the active and configured audit queue write buffer
1475  * size relative to the current zone.
1476  */
1477 static void
1478 do_getqbufsz(void)
1479 {
1480 	struct au_qctrl qctrl;
1481 
1482 	if (!temporary_set) {
1483 		if (!do_getqbufsz_scf(&qctrl.aq_bufsz)) {
1484 			exit_error(gettext("Could not get configured value."));
1485 		}
1486 
1487 		if (qctrl.aq_bufsz == 0) {
1488 			(void) printf(gettext(
1489 			    "no configured audit queue buffer size\n"));
1490 		} else {
1491 			(void) printf(gettext("configured audit queue "
1492 			    "buffer size (bytes) = %d\n"), qctrl.aq_bufsz);
1493 		}
1494 	}
1495 
1496 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1497 	(void) printf(gettext("active audit queue buffer size (bytes) = %d\n"),
1498 	    qctrl.aq_bufsz);
1499 }
1500 
1501 /*
1502  * do_getqctrl() - print the configured and active audit queue write buffer
1503  * size, audit queue hiwater mark, audit queue lowater mark, audit queue prod
1504  * interval (ticks) relative to the current zone.
1505  */
1506 static void
1507 do_getqctrl(void)
1508 {
1509 	struct au_qctrl	qctrl;
1510 
1511 	if (!temporary_set) {
1512 		if (!do_getqctrl_scf(&qctrl)) {
1513 			exit_error(gettext("Could not get configured values."));
1514 		}
1515 
1516 		if (qctrl.aq_hiwater == 0) {
1517 			(void) printf(gettext(
1518 			    "no configured audit queue hiwater mark\n"));
1519 		} else {
1520 			(void) printf(gettext("configured audit queue "
1521 			    "hiwater mark (records) = %d\n"), qctrl.aq_hiwater);
1522 		}
1523 		if (qctrl.aq_lowater == 0) {
1524 			(void) printf(gettext(
1525 			    "no configured audit queue lowater mark\n"));
1526 		} else {
1527 			(void) printf(gettext("configured audit queue "
1528 			    "lowater mark (records) = %d\n"), qctrl.aq_lowater);
1529 		}
1530 		if (qctrl.aq_bufsz == 0) {
1531 			(void) printf(gettext(
1532 			    "no configured audit queue buffer size\n"));
1533 		} else {
1534 			(void) printf(gettext("configured audit queue "
1535 			    "buffer size (bytes) = %d\n"), qctrl.aq_bufsz);
1536 		}
1537 		if (qctrl.aq_delay == 0) {
1538 			(void) printf(gettext(
1539 			    "no configured audit queue delay\n"));
1540 		} else {
1541 			(void) printf(gettext("configured audit queue "
1542 			    "delay (ticks) = %ld\n"), qctrl.aq_delay);
1543 		}
1544 	}
1545 
1546 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1547 	(void) printf(gettext("active audit queue hiwater mark "
1548 	    "(records) = %d\n"), qctrl.aq_hiwater);
1549 	(void) printf(gettext("active audit queue lowater mark "
1550 	    "(records) = %d\n"), qctrl.aq_lowater);
1551 	(void) printf(gettext("active audit queue buffer size (bytes) = %d\n"),
1552 	    qctrl.aq_bufsz);
1553 	(void) printf(gettext("active audit queue delay (ticks) = %ld\n"),
1554 	    qctrl.aq_delay);
1555 }
1556 
1557 /*
1558  * do_getqdelay() - print, relative to the current zone, the configured and
1559  * active interval at which audit queue is prodded to start output.
1560  */
1561 static void
1562 do_getqdelay(void)
1563 {
1564 	struct au_qctrl qctrl;
1565 
1566 	if (!temporary_set) {
1567 		if (!do_getqdelay_scf(&qctrl.aq_delay)) {
1568 			exit_error(gettext("Could not get configured value."));
1569 		}
1570 
1571 		if (qctrl.aq_delay == 0) {
1572 			(void) printf(gettext(
1573 			    "no configured audit queue delay\n"));
1574 		} else {
1575 			(void) printf(gettext("configured audit queue "
1576 			    "delay (ticks) = %ld\n"), qctrl.aq_delay);
1577 		}
1578 	}
1579 
1580 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1581 	(void) printf(gettext("active audit queue delay (ticks) = %ld\n"),
1582 	    qctrl.aq_delay);
1583 }
1584 
1585 /*
1586  * do_getqhiwater() - print, relative to the current zone, the high water
1587  * point in undelivered audit records when audit generation will block.
1588  */
1589 static void
1590 do_getqhiwater(void)
1591 {
1592 	struct au_qctrl qctrl;
1593 
1594 	if (!temporary_set) {
1595 		if (!do_getqhiwater_scf(&qctrl.aq_hiwater)) {
1596 			exit_error(gettext("Could not get configured value."));
1597 		}
1598 
1599 		if (qctrl.aq_hiwater == 0) {
1600 			(void) printf(gettext(
1601 			    "no configured audit queue hiwater mark\n"));
1602 		} else {
1603 			(void) printf(gettext("configured audit queue "
1604 			    "hiwater mark (records) = %d\n"), qctrl.aq_hiwater);
1605 		}
1606 	}
1607 
1608 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1609 	(void) printf(gettext("active audit queue hiwater mark "
1610 	    "(records) = %d\n"), qctrl.aq_hiwater);
1611 }
1612 
1613 /*
1614  * do_getqlowater() - print, relative to the current zone, the low water point
1615  * in undelivered audit records where blocked processes will resume.
1616  */
1617 static void
1618 do_getqlowater(void)
1619 {
1620 	struct au_qctrl qctrl;
1621 
1622 	if (!temporary_set) {
1623 		if (!do_getqlowater_scf(&qctrl.aq_lowater)) {
1624 			exit_error(gettext("Could not get configured value."));
1625 		}
1626 
1627 		if (qctrl.aq_lowater == 0) {
1628 			(void) printf(gettext(
1629 			    "no configured audit queue lowater mark\n"));
1630 		} else {
1631 			(void) printf(gettext("configured audit queue "
1632 			    "lowater mark (records) = %d\n"), qctrl.aq_lowater);
1633 		}
1634 	}
1635 
1636 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1637 	(void) printf(gettext("active audit queue lowater mark "
1638 	    "(records) = %d\n"), qctrl.aq_lowater);
1639 }
1640 
1641 /*
1642  * do_getasid() - print out the audit session-ID.
1643  */
1644 static void
1645 do_getasid(void)
1646 {
1647 	auditinfo_addr_t ai;
1648 
1649 	if (getaudit_addr(&ai, sizeof (ai))) {
1650 		exit_error(gettext("getaudit_addr(2) failed"));
1651 	}
1652 	print_asid(ai.ai_asid);
1653 }
1654 
1655 /*
1656  * do_getstat() - the printed statistics are for the entire system unless
1657  * AUDIT_PERZONE is set.
1658  */
1659 static void
1660 do_getstat(void)
1661 {
1662 	au_stat_t as;
1663 	int offset[12];   /* used to line the header up correctly */
1664 	char buf[512];
1665 
1666 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
1667 	(void) sprintf(buf, "%4lu %n%4lu %n%4lu %n%4lu %n%4lu %n%4lu %n%4lu "
1668 	    "%n%4lu %n%4lu %n%4lu %n%4lu %n%4lu%n",
1669 	    (ulong_t)as.as_generated,	&(offset[0]),
1670 	    (ulong_t)as.as_nonattrib,	&(offset[1]),
1671 	    (ulong_t)as.as_kernel,	&(offset[2]),
1672 	    (ulong_t)as.as_audit,	&(offset[3]),
1673 	    (ulong_t)as.as_auditctl,	&(offset[4]),
1674 	    (ulong_t)as.as_enqueue,	&(offset[5]),
1675 	    (ulong_t)as.as_written,	&(offset[6]),
1676 	    (ulong_t)as.as_wblocked,	&(offset[7]),
1677 	    (ulong_t)as.as_rblocked,	&(offset[8]),
1678 	    (ulong_t)as.as_dropped,	&(offset[9]),
1679 	    (ulong_t)as.as_totalsize / ONEK, &(offset[10]),
1680 	    (ulong_t)as.as_memused / ONEK, &(offset[11]));
1681 
1682 	/*
1683 	 * TRANSLATION_NOTE
1684 	 *	Print a properly aligned header.
1685 	 */
1686 	(void) printf("%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s\n",
1687 	    offset[0] - 1,		gettext("gen"),
1688 	    offset[1] - offset[0] -1,	gettext("nona"),
1689 	    offset[2] - offset[1] -1,	gettext("kern"),
1690 	    offset[3] - offset[2] -1,	gettext("aud"),
1691 	    offset[4] - offset[3] -1,	gettext("ctl"),
1692 	    offset[5] - offset[4] -1,	gettext("enq"),
1693 	    offset[6] - offset[5] -1,	gettext("wrtn"),
1694 	    offset[7] - offset[6] -1,	gettext("wblk"),
1695 	    offset[8] - offset[7] -1,	gettext("rblk"),
1696 	    offset[9] - offset[8] -1,	gettext("drop"),
1697 	    offset[10] - offset[9] -1,	gettext("tot"),
1698 	    offset[11] - offset[10],	gettext("mem"));
1699 
1700 	(void) printf("%s\n", buf);
1701 }
1702 
1703 /*
1704  * do_gettermid() - print audit terminal ID for current process.
1705  */
1706 static void
1707 do_gettermid(void)
1708 {
1709 	auditinfo_addr_t ai;
1710 
1711 	if (getaudit_addr(&ai, sizeof (ai))) {
1712 		exit_error(gettext("getaudit_addr(2) failed"));
1713 	}
1714 	print_tid_ex(&ai.ai_termid);
1715 }
1716 
1717 /*
1718  * do_lsevent() - display the active kernel and user level audit event
1719  * information. The printed events are for the global zone unless AUDIT_PERZONE
1720  * is set.
1721  */
1722 static void
1723 do_lsevent(void)
1724 {
1725 	register au_event_ent_t *evp;
1726 	au_mask_t pmask;
1727 	char auflags[256];
1728 
1729 	setauevent();
1730 	if (getauevent() == NULL) {
1731 		exit_error(gettext("NO AUDIT EVENTS: Could not read %s\n."),
1732 		    AUDITEVENTFILE);
1733 	}
1734 
1735 	setauevent();
1736 	while ((evp = getauevent()) != NULL) {
1737 		pmask.am_success = pmask.am_failure = evp->ae_class;
1738 		if (getauditflagschar(auflags, &pmask, 0) == -1)
1739 			(void) strcpy(auflags, "unknown");
1740 		(void) printf("%-30s %5hu %s %s\n",
1741 		    evp->ae_name, evp->ae_number, auflags, evp->ae_desc);
1742 	}
1743 	endauevent();
1744 }
1745 
1746 /*
1747  * do_lspolicy() - display the kernel audit policies with a description  of each
1748  * policy. The printed value is for the global zone unless AUDIT_PERZONE is set.
1749  */
1750 static void
1751 do_lspolicy(void)
1752 {
1753 	int i;
1754 
1755 	/*
1756 	 * TRANSLATION_NOTE
1757 	 *	Print a properly aligned header.
1758 	 */
1759 	(void) printf(gettext("policy string    description:\n"));
1760 	for (i = 0; i < POLICY_TBL_SZ; i++) {
1761 		(void) printf("%-17s%s\n", policy_table[i].policy_str,
1762 		    gettext(policy_table[i].policy_desc));
1763 	}
1764 }
1765 
1766 /*
1767  * do_setasid() - execute shell or cmd with specified session-ID.
1768  */
1769 static void
1770 do_setasid(char *sid_str, char **argv)
1771 {
1772 	struct auditinfo_addr ai;
1773 
1774 	if (getaudit_addr(&ai, sizeof (ai))) {
1775 		exit_error(gettext("getaudit_addr(2) failed"));
1776 	}
1777 	ai.ai_asid = (au_asid_t)atol(sid_str);
1778 	if (setaudit_addr(&ai, sizeof (ai))) {
1779 		exit_error(gettext("setaudit_addr(2) failed"));
1780 	}
1781 	execit(argv);
1782 }
1783 
1784 /*
1785  * do_setaudit() - execute shell or cmd with specified audit characteristics.
1786  */
1787 static void
1788 do_setaudit(char *user_str, char *mask_str, char *tid_str, char *sid_str,
1789     char **argv)
1790 {
1791 	auditinfo_addr_t ai;
1792 
1793 	ai.ai_auid = (au_id_t)get_user_id(user_str);
1794 	egetauditflagsbin(mask_str, &ai.ai_mask),
1795 	    str2tid(tid_str, &ai.ai_termid);
1796 	ai.ai_asid = (au_asid_t)atol(sid_str);
1797 
1798 	esetaudit(&ai, sizeof (ai));
1799 	execit(argv);
1800 }
1801 
1802 /*
1803  * do_setauid() - execute shell or cmd with specified audit-ID.
1804  */
1805 static void
1806 do_setauid(char *user, char **argv)
1807 {
1808 	au_id_t auid;
1809 
1810 	auid = get_user_id(user);
1811 	esetauid(&auid);
1812 	execit(argv);
1813 }
1814 
1815 /*
1816  * do_setpmask() - set the preselection mask of the specified process; valid
1817  * per zone if AUDIT_PERZONE is set, else only in global zone.
1818  */
1819 static void
1820 do_setpmask(char *pid_str, au_mask_t *mask)
1821 {
1822 	struct auditpinfo ap;
1823 
1824 	if (strisnum(pid_str)) {
1825 		ap.ap_pid = (pid_t)atoi(pid_str);
1826 	} else {
1827 		exit_usage(1);
1828 	}
1829 
1830 	ap.ap_mask.am_success = mask->am_success;
1831 	ap.ap_mask.am_failure = mask->am_failure;
1832 
1833 	eauditon(A_SETPMASK, (caddr_t)&ap, sizeof (ap));
1834 }
1835 
1836 /*
1837  * do_setsmask() - set the preselection mask of all processes with the specified
1838  * audit session-ID; valid per zone if AUDIT_PERZONE is set, else only in global
1839  * zone.
1840  */
1841 static void
1842 do_setsmask(char *asid_str, au_mask_t *mask)
1843 {
1844 	struct auditinfo ainfo;
1845 
1846 	if (strisnum(asid_str)) {
1847 		ainfo.ai_asid = (au_asid_t)atoi(asid_str);
1848 	} else {
1849 		exit_usage(1);
1850 	}
1851 
1852 	ainfo.ai_mask.am_success = mask->am_success;
1853 	ainfo.ai_mask.am_failure = mask->am_failure;
1854 
1855 	eauditon(A_SETSMASK, (caddr_t)&ainfo, sizeof (ainfo));
1856 }
1857 
1858 /*
1859  * do_setumask() -  set the preselection mask of all processes with the
1860  * specified audit-ID; valid per zone if AUDIT_PERZONE is set, else only in
1861  * global zone.
1862  */
1863 static void
1864 do_setumask(char *auid_str, au_mask_t *mask)
1865 {
1866 	struct auditinfo ainfo;
1867 
1868 	if (strisnum(auid_str)) {
1869 		ainfo.ai_auid = (au_id_t)atoi(auid_str);
1870 	} else {
1871 		exit_usage(1);
1872 	}
1873 
1874 	ainfo.ai_mask.am_success = mask->am_success;
1875 	ainfo.ai_mask.am_failure = mask->am_failure;
1876 
1877 	eauditon(A_SETUMASK, (caddr_t)&ainfo, sizeof (ainfo));
1878 }
1879 
1880 /*
1881  * do_setstat() - reset audit statistics counters; local zone use is valid if
1882  * AUDIT_PERZONE is set, otherwise the syscall returns EPERM.
1883  */
1884 static void
1885 do_setstat(void)
1886 {
1887 	au_stat_t as;
1888 
1889 	as.as_audit	= (uint_t)-1;
1890 	as.as_auditctl	= (uint_t)-1;
1891 	as.as_dropped	= (uint_t)-1;
1892 	as.as_enqueue	= (uint_t)-1;
1893 	as.as_generated	= (uint_t)-1;
1894 	as.as_kernel	= (uint_t)-1;
1895 	as.as_nonattrib	= (uint_t)-1;
1896 	as.as_rblocked	= (uint_t)-1;
1897 	as.as_totalsize	= (uint_t)-1;
1898 	as.as_wblocked	= (uint_t)-1;
1899 	as.as_written	= (uint_t)-1;
1900 
1901 	eauditon(A_SETSTAT, (caddr_t)&as, sizeof (as));
1902 	(void) printf("%s\n", gettext("audit stats reset"));
1903 }
1904 
1905 /*
1906  * do_setclass() - map the kernel event event_str to the classes specified by
1907  * audit flags (mask); valid per zone if AUDIT_PERZONE is set, else only in
1908  * global zone.
1909  */
1910 static void
1911 do_setclass(char *event_str, au_mask_t *mask)
1912 {
1913 	au_event_t event;
1914 	au_evclass_map_t ec;
1915 	au_event_ent_t *evp;
1916 
1917 	if (strisnum(event_str)) {
1918 		event = (uint_t)atol(event_str);
1919 	} else {
1920 		if ((evp = egetauevnam(event_str)) != NULL) {
1921 			event = evp->ae_number;
1922 		}
1923 	}
1924 
1925 	ec.ec_number = event;
1926 	ec.ec_class = (mask->am_success | mask->am_failure);
1927 
1928 	eauditon(A_SETCLASS, (caddr_t)&ec, sizeof (ec));
1929 }
1930 
1931 /*
1932  * do_setflags() - set configured and active default user preselection masks;
1933  * valid per zone if AUDIT_PERZONE is set, else only in global zone.
1934  */
1935 static void
1936 do_setflags(char *audit_flags, au_mask_t *amask)
1937 {
1938 	eauditon(A_SETAMASK, (caddr_t)amask, sizeof (*amask));
1939 
1940 	if (!do_setflags_scf(audit_flags)) {
1941 		print_mask(gettext("active user default audit flags"), amask);
1942 		exit_error(gettext("Could not store configuration value."));
1943 	}
1944 	print_mask(gettext("user default audit flags"), amask);
1945 }
1946 
1947 /*
1948  * do_setkmask() - set non-attributable audit flags of machine; valid per zone
1949  * if AUDIT_PERZONE is set, else only in global zone.
1950  */
1951 static void
1952 do_setkmask(au_mask_t *pmask)
1953 {
1954 	eauditon(A_SETKMASK, (caddr_t)pmask, sizeof (*pmask));
1955 	print_mask(gettext("active non-attributable audit flags"), pmask);
1956 }
1957 
1958 /*
1959  * do_setnaflags() - set configured and active non-attributable selection flags
1960  * of machine; valid per zone if AUDIT_PERZONE is set, else only in global zone.
1961  */
1962 static void
1963 do_setnaflags(char *audit_naflags, au_mask_t *namask)
1964 {
1965 	eauditon(A_SETKMASK, (caddr_t)namask, sizeof (*namask));
1966 
1967 	if (!do_setnaflags_scf(audit_naflags)) {
1968 		print_mask(
1969 		    gettext("active non-attributable audit flags"), namask);
1970 		exit_error(gettext("Could not store configuration value."));
1971 	}
1972 	print_mask(gettext("non-attributable audit flags"), namask);
1973 }
1974 
1975 /*
1976  * do_setplugin() - set the given plugin plugin_str configuration values.
1977  */
1978 static void
1979 do_setplugin(char *plugin_str, boolean_t plugin_state, char *plugin_attr,
1980     int plugin_qsize)
1981 {
1982 	if (!do_setpluginconfig_scf(plugin_str, plugin_state, plugin_attr,
1983 	    plugin_qsize)) {
1984 		exit_error(gettext("Could not set plugin configuration."));
1985 	}
1986 }
1987 
1988 /*
1989  * do_setpolicy() - set the active and configured kernel audit policy; active
1990  * values can be changed per zone if AUDIT_PERZONE is set, else only in global
1991  * zone.
1992  *
1993  * ahlt and perzone are global zone only. The kernel ensures that a local zone
1994  * can't change ahlt and perzone (EINVAL).
1995  */
1996 static void
1997 do_setpolicy(char *policy_str)
1998 {
1999 	uint32_t	policy = 0;
2000 
2001 	switch (str2policy(policy_str, &policy)) {
2002 	case 0:
2003 		if (!temporary_set) {
2004 			if (!do_getpolicy_scf(&policy)) {
2005 				exit_error(gettext("Unable to get current "
2006 				    "policy values from the SMF repository"));
2007 			}
2008 			(void) str2policy(policy_str, &policy);
2009 
2010 			if (!do_setpolicy_scf(policy)) {
2011 				exit_error(gettext("Could not store "
2012 				    "configuration values."));
2013 			}
2014 		}
2015 		eauditon(A_SETPOLICY, (caddr_t)&policy, 0);
2016 		break;
2017 	case 2:
2018 		exit_error(gettext("policy (%s) invalid in a local zone."),
2019 		    policy_str);
2020 		break;
2021 	default:
2022 		exit_error(gettext("Invalid policy (%s) specified."),
2023 		    policy_str);
2024 		break;
2025 	}
2026 }
2027 
2028 /*
2029  * do_setqbufsz() - set the active and configured audit queue write buffer size
2030  * (bytes); active values can be changed per zone if AUDIT_PERZONE is set, else
2031  * only in global zone.
2032  */
2033 static void
2034 do_setqbufsz(char *bufsz)
2035 {
2036 	struct au_qctrl qctrl;
2037 
2038 	if (!temporary_set) {
2039 		qctrl.aq_bufsz = (size_t)atol(bufsz);
2040 		if (!do_setqbufsz_scf(&qctrl.aq_bufsz)) {
2041 			exit_error(gettext(
2042 			    "Could not store configuration value."));
2043 		}
2044 		if (qctrl.aq_bufsz == 0) {
2045 			return;
2046 		}
2047 	}
2048 
2049 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
2050 	qctrl.aq_bufsz = (size_t)atol(bufsz);
2051 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
2052 }
2053 
2054 /*
2055  * do_setqctrl() - set the active and configured audit queue write buffer size
2056  * (bytes), hiwater audit record count, lowater audit record count, and wakeup
2057  * interval (ticks); active values can be changed per zone if AUDIT_PERZONE is
2058  * set, else only in global zone.
2059  */
2060 static void
2061 do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay)
2062 {
2063 	struct au_qctrl	qctrl;
2064 
2065 	qctrl.aq_hiwater = (size_t)atol(hiwater);
2066 	qctrl.aq_lowater = (size_t)atol(lowater);
2067 	qctrl.aq_bufsz = (size_t)atol(bufsz);
2068 	qctrl.aq_delay = (clock_t)atol(delay);
2069 
2070 	if (!temporary_set) {
2071 		struct au_qctrl qctrl_act;
2072 
2073 		if (!do_setqctrl_scf(&qctrl)) {
2074 			exit_error(gettext(
2075 			    "Could not store configuration values."));
2076 		}
2077 
2078 		eauditon(A_GETQCTRL, (caddr_t)&qctrl_act, 0);
2079 		if (qctrl.aq_hiwater == 0) {
2080 			qctrl.aq_hiwater = qctrl_act.aq_hiwater;
2081 		}
2082 		if (qctrl.aq_lowater == 0) {
2083 			qctrl.aq_lowater = qctrl_act.aq_lowater;
2084 		}
2085 		if (qctrl.aq_bufsz == 0) {
2086 			qctrl.aq_bufsz = qctrl_act.aq_bufsz;
2087 		}
2088 		if (qctrl.aq_delay == 0) {
2089 			qctrl.aq_delay = qctrl_act.aq_delay;
2090 		}
2091 	}
2092 
2093 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
2094 }
2095 
2096 /*
2097  * do_setqdelay() - set the active and configured audit queue wakeup interval
2098  * (ticks); active values can be changed per zone if AUDIT_PERZONE is set, else
2099  * only in global zone.
2100  */
2101 static void
2102 do_setqdelay(char *delay)
2103 {
2104 	struct au_qctrl qctrl;
2105 
2106 	if (!temporary_set) {
2107 		qctrl.aq_delay = (clock_t)atol(delay);
2108 		if (!do_setqdelay_scf(&qctrl.aq_delay)) {
2109 			exit_error(gettext(
2110 			    "Could not store configuration value."));
2111 		}
2112 		if (qctrl.aq_delay == 0) {
2113 			return;
2114 		}
2115 	}
2116 
2117 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
2118 	qctrl.aq_delay = (clock_t)atol(delay);
2119 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
2120 }
2121 
2122 /*
2123  * do_setqhiwater() - sets the active and configured number of undelivered audit
2124  * records in the audit queue at which audit record generation blocks; active
2125  * values can be changed per zone if AUDIT_PERZONE is set, else only in global
2126  * zone.
2127  */
2128 static void
2129 do_setqhiwater(char *hiwater)
2130 {
2131 	struct au_qctrl qctrl;
2132 
2133 	if (!temporary_set) {
2134 		qctrl.aq_hiwater = (size_t)atol(hiwater);
2135 		if (!do_setqhiwater_scf(&qctrl.aq_hiwater)) {
2136 			exit_error(gettext(
2137 			    "Could not store configuration value."));
2138 		}
2139 		if (qctrl.aq_hiwater == 0) {
2140 			return;
2141 		}
2142 	}
2143 
2144 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
2145 	qctrl.aq_hiwater = (size_t)atol(hiwater);
2146 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
2147 }
2148 
2149 /*
2150  * do_setqlowater() - set the active and configured number of undelivered audit
2151  * records in the audit queue at which blocked auditing processes unblock;
2152  * active values can be changed per zone if AUDIT_PERZONE is set, else only in
2153  * global zone.
2154  */
2155 static void
2156 do_setqlowater(char *lowater)
2157 {
2158 	struct au_qctrl qctrl;
2159 
2160 	if (!temporary_set) {
2161 		qctrl.aq_lowater = (size_t)atol(lowater);
2162 		if (!do_setqlowater_scf(&qctrl.aq_lowater)) {
2163 			exit_error(gettext(
2164 			    "Could not store configuration value."));
2165 		}
2166 		if (qctrl.aq_lowater == 0) {
2167 			return;
2168 		}
2169 	}
2170 
2171 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
2172 	qctrl.aq_lowater = (size_t)atol(lowater);
2173 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
2174 }
2175 
2176 static void
2177 eauditon(int cmd, caddr_t data, int length)
2178 {
2179 	if (auditon(cmd, data, length) == -1)
2180 		exit_error(gettext("auditon(2) failed."));
2181 }
2182 
2183 static void
2184 egetauid(au_id_t *auid)
2185 {
2186 	if (getauid(auid) == -1)
2187 		exit_error(gettext("getauid(2) failed."));
2188 }
2189 
2190 static void
2191 egetaudit(auditinfo_addr_t *ai, int size)
2192 {
2193 	if (getaudit_addr(ai, size) == -1)
2194 		exit_error(gettext("getaudit_addr(2) failed."));
2195 }
2196 
2197 static void
2198 egetkaudit(auditinfo_addr_t *ai, int size)
2199 {
2200 	if (auditon(A_GETKAUDIT, (char *)ai, size) < 0)
2201 		exit_error(gettext("auditon: A_GETKAUDIT failed."));
2202 }
2203 
2204 static void
2205 esetkaudit(auditinfo_addr_t *ai, int size)
2206 {
2207 	if (auditon(A_SETKAUDIT, (char *)ai, size) < 0)
2208 		exit_error(gettext("auditon: A_SETKAUDIT failed."));
2209 }
2210 
2211 static void
2212 egetauditflagsbin(char *auditflags, au_mask_t *pmask)
2213 {
2214 	if (strcmp(auditflags, "none") == 0) {
2215 		pmask->am_success = pmask->am_failure = 0;
2216 		return;
2217 	}
2218 
2219 	if (getauditflagsbin(auditflags, pmask) < 0) {
2220 		exit_error(gettext("Could not get audit flags (%s)"),
2221 		    auditflags);
2222 	}
2223 }
2224 
2225 static void
2226 echkflags(char *auditflags, au_mask_t *mask)
2227 {
2228 	char		*err = "";
2229 	char		*err_ptr;
2230 
2231 	if (!__chkflags(auditflags, mask, B_FALSE, &err)) {
2232 		err_ptr = err;
2233 		while (*err_ptr != ',' && *err_ptr != '\0') {
2234 			err_ptr++;
2235 		}
2236 		*err_ptr = '\0';
2237 		exit_error(gettext("Unknown audit flags and/or prefixes "
2238 		    "encountered: %s"), err);
2239 	}
2240 }
2241 
2242 static au_event_ent_t *
2243 egetauevnum(au_event_t event_number)
2244 {
2245 	au_event_ent_t *evp;
2246 
2247 	if ((evp = getauevnum(event_number)) == NULL) {
2248 		exit_error(gettext("Could not get audit event %hu"),
2249 		    event_number);
2250 	}
2251 
2252 	return (evp);
2253 }
2254 
2255 static au_event_ent_t *
2256 egetauevnam(char *event_name)
2257 {
2258 	register au_event_ent_t *evp;
2259 
2260 	if ((evp = getauevnam(event_name)) == NULL)
2261 		exit_error(gettext("Could not get audit event %s"), event_name);
2262 
2263 	return (evp);
2264 }
2265 
2266 static void
2267 esetauid(au_id_t *auid)
2268 {
2269 	if (setauid(auid) == -1)
2270 		exit_error(gettext("setauid(2) failed."));
2271 }
2272 
2273 static void
2274 esetaudit(auditinfo_addr_t *ai, int size)
2275 {
2276 	if (setaudit_addr(ai, size) == -1)
2277 		exit_error(gettext("setaudit_addr(2) failed."));
2278 }
2279 
2280 static uid_t
2281 get_user_id(char *user)
2282 {
2283 	struct passwd *pwd;
2284 	uid_t uid;
2285 
2286 	if (isdigit(*user)) {
2287 		uid = atoi(user);
2288 		if ((pwd = getpwuid(uid)) == NULL) {
2289 			exit_error(gettext("Invalid user: %s"), user);
2290 		}
2291 	} else {
2292 		if ((pwd = getpwnam(user)) == NULL) {
2293 			exit_error(gettext("Invalid user: %s"), user);
2294 		}
2295 	}
2296 
2297 	return (pwd->pw_uid);
2298 }
2299 
2300 /*
2301  * get_arg_ent()
2302  *     Inputs: command line argument string
2303  *     Returns ptr to struct arg_entry if found; null, if not found
2304  */
2305 static arg_entry_t *
2306 get_arg_ent(char *arg_str)
2307 {
2308 	arg_entry_t key;
2309 
2310 	key.arg_str = arg_str;
2311 
2312 	return ((arg_entry_t *)bsearch((char *)&key, (char *)arg_table,
2313 	    ARG_TBL_SZ, sizeof (arg_entry_t), arg_ent_compare));
2314 }
2315 
2316 /*
2317  * arg_ent_compare()
2318  *     Compares two command line arguments to determine which is
2319  *       lexicographically greater.
2320  *     Inputs: two argument map table entry pointers
2321  *     Returns: > 1: aep1->arg_str > aep2->arg_str
2322  *              < 1: aep1->arg_str < aep2->arg_str
2323  *                0: aep1->arg_str = aep->arg_str2
2324  */
2325 static int
2326 arg_ent_compare(const void *aep1, const void *aep2)
2327 {
2328 	return (strcmp(((arg_entry_t *)aep1)->arg_str,
2329 	    ((arg_entry_t *)aep2)->arg_str));
2330 }
2331 
2332 /*
2333  * tid_str is major,minor,host  -- host is a name or an ip address
2334  */
2335 static void
2336 str2tid(char *tid_str, au_tid_addr_t *tp)
2337 {
2338 	char *major_str;
2339 	char *minor_str;
2340 	char *host_str = NULL;
2341 	major_t major = 0;
2342 	major_t minor = 0;
2343 	dev_t dev = 0;
2344 	struct hostent *phe;
2345 	int err;
2346 	uint32_t ibuf;
2347 	uint32_t ibuf6[4];
2348 
2349 	tp->at_port = 0;
2350 	tp->at_type = 0;
2351 	bzero(tp->at_addr, 16);
2352 
2353 	major_str = tid_str;
2354 	if ((minor_str = strchr(tid_str, ',')) != NULL) {
2355 		*minor_str = '\0';
2356 		minor_str++;
2357 	}
2358 
2359 	if (minor_str) {
2360 		if ((host_str = strchr(minor_str, ',')) != NULL) {
2361 			*host_str = '\0';
2362 			host_str++;
2363 		}
2364 	}
2365 
2366 	if (major_str)
2367 		major = (major_t)atoi(major_str);
2368 
2369 	if (minor_str)
2370 		minor = (minor_t)atoi(minor_str);
2371 
2372 	if ((dev = makedev(major, minor)) != NODEV)
2373 		tp->at_port = dev;
2374 
2375 	if (host_str) {
2376 		if (strisipaddr(host_str)) {
2377 			if (inet_pton(AF_INET, host_str, &ibuf)) {
2378 				tp->at_addr[0] = ibuf;
2379 				tp->at_type = AU_IPv4;
2380 			} else if (inet_pton(AF_INET6, host_str, ibuf6)) {
2381 				tp->at_addr[0] = ibuf6[0];
2382 				tp->at_addr[1] = ibuf6[1];
2383 				tp->at_addr[2] = ibuf6[2];
2384 				tp->at_addr[3] = ibuf6[3];
2385 				tp->at_type = AU_IPv6;
2386 			}
2387 		} else {
2388 			phe = getipnodebyname((const void *)host_str,
2389 			    AF_INET, 0, &err);
2390 			if (phe == 0) {
2391 				phe = getipnodebyname((const void *)host_str,
2392 				    AF_INET6, 0, &err);
2393 			}
2394 
2395 			if (phe != NULL) {
2396 				if (phe->h_addrtype == AF_INET6) {
2397 					/* address is IPv6 (128 bits) */
2398 					(void) memcpy(&tp->at_addr[0],
2399 					    phe->h_addr_list[0], 16);
2400 					tp->at_type = AU_IPv6;
2401 				} else {
2402 					/* address is IPv4 (32 bits) */
2403 					(void) memcpy(&tp->at_addr[0],
2404 					    phe->h_addr_list[0], 4);
2405 					tp->at_type = AU_IPv4;
2406 				}
2407 				freehostent(phe);
2408 			}
2409 		}
2410 	}
2411 }
2412 
2413 static char *
2414 cond2str(void)
2415 {
2416 	uint_t cond;
2417 
2418 	eauditon(A_GETCOND, (caddr_t)&cond, sizeof (cond));
2419 
2420 	switch (cond) {
2421 
2422 	case AUC_AUDITING:
2423 		return ("auditing");
2424 
2425 	case AUC_NOAUDIT:
2426 	case AUC_INIT_AUDIT:
2427 		return ("noaudit");
2428 
2429 	case AUC_UNSET:
2430 		return ("unset");
2431 
2432 	case AUC_NOSPACE:
2433 		return ("nospace");
2434 
2435 	default:
2436 		return ("");
2437 	}
2438 }
2439 
2440 /*
2441  *	exit = 0, success
2442  *	       1, error
2443  *	       2, bad zone
2444  */
2445 static int
2446 str2policy(char *policy_str, uint32_t *policy_mask)
2447 {
2448 	char		*buf;
2449 	char		*tok;
2450 	char		pfix;
2451 	boolean_t	is_all = B_FALSE;
2452 	uint32_t	pm = 0;
2453 	uint32_t	curp;
2454 
2455 	pfix = *policy_str;
2456 
2457 	if (pfix == '-' || pfix == '+' || pfix == '=')
2458 		++policy_str;
2459 
2460 	if ((buf = strdup(policy_str)) == NULL)
2461 		return (1);
2462 
2463 	for (tok = strtok(buf, ","); tok != NULL; tok = strtok(NULL, ",")) {
2464 		uint32_t tok_pm;
2465 		if (((tok_pm = get_policy(tok)) == 0) &&
2466 		    ((strcasecmp(tok, "none") != 0))) {
2467 			free(buf);
2468 			return (1);
2469 		} else {
2470 			pm |= tok_pm;
2471 			if (tok_pm == ALL_POLICIES) {
2472 				is_all = B_TRUE;
2473 			}
2474 		}
2475 	}
2476 	free(buf);
2477 
2478 	/* reuse policy mask if already set to some value */
2479 	if (*policy_mask != 0) {
2480 		curp = *policy_mask;
2481 	} else {
2482 		(void) auditon(A_GETPOLICY, (caddr_t)&curp, 0);
2483 	}
2484 
2485 	if (pfix == '-') {
2486 		if (!is_all &&
2487 		    (getzoneid() != GLOBAL_ZONEID) &&
2488 		    (pm & ~AUDIT_LOCAL)) {
2489 			return (2);
2490 		}
2491 
2492 		if (getzoneid() != GLOBAL_ZONEID)
2493 			curp &= AUDIT_LOCAL;
2494 		*policy_mask = curp & ~pm;
2495 
2496 	} else if (pfix == '+') {
2497 		/*
2498 		 * In a local zone, accept specifying "all", but not
2499 		 * individually specifying global-zone only policies.
2500 		 * Limit to all locally allowed, so system call doesn't
2501 		 * fail.
2502 		 */
2503 		if (!is_all &&
2504 		    (getzoneid() != GLOBAL_ZONEID) &&
2505 		    (pm & ~AUDIT_LOCAL)) {
2506 			return (2);
2507 		}
2508 
2509 		if (getzoneid() != GLOBAL_ZONEID) {
2510 			curp &= AUDIT_LOCAL;
2511 			if (is_all) {
2512 				pm &= AUDIT_LOCAL;
2513 			}
2514 		}
2515 		*policy_mask = curp | pm;
2516 
2517 	} else {
2518 		/*
2519 		 * In a local zone, accept specifying "all", but not
2520 		 * individually specifying global-zone only policies.
2521 		 * Limit to all locally allowed, so system call doesn't
2522 		 * fail.
2523 		 */
2524 		if (!is_all &&
2525 		    (getzoneid() != GLOBAL_ZONEID) &&
2526 		    (pm & ~AUDIT_LOCAL)) {
2527 			return (2);
2528 		}
2529 
2530 		if (is_all && (getzoneid() != GLOBAL_ZONEID)) {
2531 			pm &= AUDIT_LOCAL;
2532 		}
2533 		*policy_mask = pm;
2534 	}
2535 	return (0);
2536 }
2537 
2538 static int
2539 policy2str(uint32_t policy, char *policy_str, size_t len)
2540 {
2541 	int i, j;
2542 
2543 	if (policy == ALL_POLICIES) {
2544 		(void) strcpy(policy_str, "all");
2545 		return (1);
2546 	}
2547 
2548 	if (policy == NO_POLICIES) {
2549 		(void) strcpy(policy_str, "none");
2550 		return (1);
2551 	}
2552 
2553 	*policy_str = '\0';
2554 
2555 	for (i = 0, j = 0; i < POLICY_TBL_SZ; i++) {
2556 		if (policy & policy_table[i].policy_mask &&
2557 		    policy_table[i].policy_mask != ALL_POLICIES) {
2558 			if (j++) {
2559 				(void) strcat(policy_str, ",");
2560 			}
2561 			(void) strlcat(policy_str, policy_table[i].policy_str,
2562 			    len);
2563 		}
2564 	}
2565 
2566 	if (*policy_str)
2567 		return (0);
2568 
2569 	return (1);
2570 }
2571 
2572 
2573 static int
2574 strisnum(char *s)
2575 {
2576 	if (s == NULL || !*s)
2577 		return (0);
2578 
2579 	for (; *s == '-' || *s == '+'; s++) {
2580 		if (!*s)
2581 			return (0);
2582 	}
2583 
2584 	for (; *s; s++) {
2585 		if (!isdigit(*s))
2586 			return (0);
2587 	}
2588 
2589 	return (1);
2590 }
2591 
2592 static int
2593 strisipaddr(char *s)
2594 {
2595 	int dot = 0;
2596 	int colon = 0;
2597 
2598 	/* no string */
2599 	if ((s == NULL) || (!*s))
2600 		return (0);
2601 
2602 	for (; *s; s++) {
2603 		if (!(isxdigit(*s) || *s != '.' || *s != ':'))
2604 			return (0);
2605 		if (*s == '.')
2606 			dot++;
2607 		if (*s == ':')
2608 			colon++;
2609 	}
2610 
2611 	if (dot && colon)
2612 		return (0);
2613 
2614 	if (!dot && !colon)
2615 		return (0);
2616 
2617 	return (1);
2618 }
2619 
2620 static void
2621 chk_arg_len(char *argv, uint_t len)
2622 {
2623 	if ((strlen(argv) + 1) > len) {
2624 		*(argv + len - 1) = '\0';
2625 		exit_error(gettext("Argument too long (%s..)."), argv);
2626 	}
2627 }
2628 
2629 static void
2630 chk_event_num(int etype, au_event_t event)
2631 {
2632 	au_stat_t as;
2633 
2634 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
2635 
2636 	if (etype == AC_KERN_EVENT) {
2637 		if (event > as.as_numevent) {
2638 			exit_error(gettext(
2639 			    "Invalid kernel audit event number specified.\n"
2640 			    "\t%hu is outside allowable range 0-%d."),
2641 			    event, as.as_numevent);
2642 		}
2643 	} else  {
2644 		/* user event */
2645 		if (event <= as.as_numevent) {
2646 			exit_error(gettext("Invalid user level audit event "
2647 			    "number specified %hu."), event);
2648 		}
2649 	}
2650 }
2651 
2652 static void
2653 chk_event_str(int etype, char *event_str)
2654 {
2655 	au_event_ent_t *evp;
2656 	au_stat_t as;
2657 
2658 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
2659 
2660 	evp = egetauevnam(event_str);
2661 	if (etype == AC_KERN_EVENT && (evp->ae_number > as.as_numevent)) {
2662 		exit_error(gettext(
2663 		    "Invalid kernel audit event string specified.\n"
2664 		    "\t\"%s\" appears to be a user level event. "
2665 		    "Check configuration."), event_str);
2666 	} else if (etype == AC_USER_EVENT &&
2667 	    (evp->ae_number < as.as_numevent)) {
2668 		exit_error(gettext(
2669 		    "Invalid user audit event string specified.\n"
2670 		    "\t\"%s\" appears to be a kernel event. "
2671 		    "Check configuration."), event_str);
2672 	}
2673 }
2674 
2675 static void
2676 chk_known_plugin(char *plugin_str)
2677 {
2678 	if ((strlen(plugin_str) + 1) > PLUGIN_MAXBUF) {
2679 		exit_error(gettext("Plugin name too long.\n"));
2680 	}
2681 
2682 	if (!plugin_avail_scf(plugin_str)) {
2683 		exit_error(gettext("No such plugin configured: %s"),
2684 		    plugin_str);
2685 	}
2686 }
2687 
2688 static void
2689 chk_sorf(char *sorf_str)
2690 {
2691 	if (!strisnum(sorf_str))
2692 		exit_error(gettext("Invalid sorf specified: %s"), sorf_str);
2693 }
2694 
2695 static void
2696 chk_retval(char *retval_str)
2697 {
2698 	if (!strisnum(retval_str))
2699 		exit_error(gettext("Invalid retval specified: %s"), retval_str);
2700 }
2701 
2702 static void
2703 execit(char **argv)
2704 {
2705 	char *args, *args_pos;
2706 	size_t len = 0;
2707 	size_t n = 0;
2708 	char **argv_pos;
2709 
2710 	if (*argv) {
2711 		/* concatenate argument array to be passed to sh -c "..." */
2712 		for (argv_pos = argv; *argv_pos; argv_pos++)
2713 			len += strlen(*argv_pos) + 1;
2714 
2715 		if ((args = malloc(len + 1)) == NULL)
2716 			exit_error(
2717 			    gettext("Allocation for command/arguments failed"));
2718 
2719 		args_pos = args;
2720 		for (argv_pos = argv; *argv_pos; argv_pos++) {
2721 			n += snprintf(args_pos, len - n, "%s ", *argv_pos);
2722 			args_pos = args + n;
2723 		}
2724 		/* strip the last space */
2725 		args[strlen(args)] = '\0';
2726 
2727 		(void) execl("/bin/sh", "sh", "-c", args, NULL);
2728 	} else {
2729 		(void) execl("/bin/sh", "sh", NULL);
2730 	}
2731 
2732 	exit_error(gettext("exec(2) failed"));
2733 }
2734 
2735 static void
2736 exit_usage(int status)
2737 {
2738 	FILE *fp;
2739 	int i;
2740 
2741 	fp = (status ? stderr : stdout);
2742 	(void) fprintf(fp, gettext("usage: %s option ...\n"), progname);
2743 
2744 	for (i = 0; i < ARG_TBL_SZ; i++) {
2745 		/* skip the -t option; it's not a standalone option */
2746 		if (arg_table[i].auditconfig_cmd == AC_ARG_SET_TEMPORARY) {
2747 			continue;
2748 		}
2749 
2750 		(void) fprintf(fp, " %s%s%s\n",
2751 		    arg_table[i].arg_str, arg_table[i].arg_opts,
2752 		    (arg_table[i].temporary_allowed ? " [-t]" : ""));
2753 	}
2754 
2755 	exit(status);
2756 }
2757 
2758 static void
2759 print_asid(au_asid_t asid)
2760 {
2761 	(void) printf(gettext("audit session id = %u\n"), asid);
2762 }
2763 
2764 static void
2765 print_auid(au_id_t auid)
2766 {
2767 	struct passwd *pwd;
2768 	char *username;
2769 
2770 	if ((pwd = getpwuid((uid_t)auid)) != NULL)
2771 		username = pwd->pw_name;
2772 	else
2773 		username = gettext("unknown");
2774 
2775 	(void) printf(gettext("audit id = %s(%d)\n"), username, auid);
2776 }
2777 
2778 static void
2779 print_mask(char *desc, au_mask_t *pmp)
2780 {
2781 	char auflags[512];
2782 
2783 	if (getauditflagschar(auflags, pmp, 0) < 0)
2784 		(void) strlcpy(auflags, gettext("unknown"), sizeof (auflags));
2785 
2786 	(void) printf("%s = %s(0x%x,0x%x)\n",
2787 	    desc, auflags, pmp->am_success, pmp->am_failure);
2788 }
2789 
2790 static void
2791 print_plugin(char *plugin_name, kva_t *plugin_kva)
2792 {
2793 	char		att_str[PLUGIN_MAXATT];
2794 	boolean_t	plugin_active;
2795 	char		*active_str;
2796 	char		*qsize_ptr;
2797 	int		qsize;
2798 
2799 	if ((active_str = kva_match(plugin_kva, "active")) == NULL) {
2800 		(void) printf(gettext("Audit service configuration error: "
2801 		    "\"active\" property not found\n"));
2802 		return;
2803 	}
2804 
2805 	plugin_active = (boolean_t)atoi(active_str);
2806 	qsize_ptr = kva_match(plugin_kva, "qsize");
2807 	qsize = atoi(qsize_ptr == NULL ? "-1" : qsize_ptr);
2808 
2809 	(void) printf(gettext("Plugin: %s (%s)\n"), plugin_name,
2810 	    plugin_active ? "active" : "inactive");
2811 
2812 	free_static_att_kva(plugin_kva);
2813 
2814 	switch (_kva2str(plugin_kva, att_str, PLUGIN_MAXATT, "=", ";")) {
2815 	case 0:
2816 		(void) printf(gettext("\tAttributes: %s\n"), att_str);
2817 		break;
2818 	case 1:
2819 		exit_error(gettext("Internal error - buffer size too small."));
2820 		break;
2821 	default:
2822 		exit_error(gettext("Internal error."));
2823 		break;
2824 	}
2825 
2826 	if (qsize != 0) {
2827 		(void) printf(gettext("\tQueue size: %d %s\n"), qsize,
2828 		    qsize == -1 ? "(internal error: value not available)" : "");
2829 	}
2830 }
2831 
2832 static void
2833 print_tid_ex(au_tid_addr_t *tidp)
2834 {
2835 	struct hostent *phe;
2836 	char *hostname;
2837 	struct in_addr ia;
2838 	uint32_t *addr;
2839 	int err;
2840 	char buf[INET6_ADDRSTRLEN];
2841 	char *bufp;
2842 
2843 
2844 	/* IPV6 or IPV4 address */
2845 	if (tidp->at_type == AU_IPv4) {
2846 		if ((phe = gethostbyaddr((char *)&tidp->at_addr[0],
2847 		    sizeof (tidp->at_addr[0]), AF_INET)) != NULL) {
2848 			hostname = phe->h_name;
2849 		} else {
2850 			hostname = gettext("unknown");
2851 		}
2852 
2853 		ia.s_addr = tidp->at_addr[0];
2854 
2855 		(void) printf(gettext(
2856 		    "terminal id (maj,min,host) = %lu,%lu,%s(%s)\n"),
2857 		    major(tidp->at_port), minor(tidp->at_port),
2858 		    hostname, inet_ntoa(ia));
2859 	} else {
2860 		addr = &tidp->at_addr[0];
2861 		phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
2862 
2863 		bzero(buf, sizeof (buf));
2864 
2865 		(void) inet_ntop(AF_INET6, (void *)addr, buf, sizeof (buf));
2866 		if (phe == NULL) {
2867 			bufp = gettext("unknown");
2868 		} else {
2869 			bufp = phe->h_name;
2870 		}
2871 
2872 		(void) printf(gettext(
2873 		    "terminal id (maj,min,host) = %lu,%lu,%s(%s)\n"),
2874 		    major(tidp->at_port), minor(tidp->at_port),
2875 		    bufp, buf);
2876 		if (phe) {
2877 			freehostent(phe);
2878 		}
2879 	}
2880 }
2881 
2882 static int
2883 str2ipaddr(char *s, uint32_t *addr, uint32_t type)
2884 {
2885 	int j, sl;
2886 	char *ss;
2887 	unsigned int v;
2888 
2889 	bzero(addr, 16);
2890 	if (strisipaddr(s)) {
2891 		if (type == AU_IPv4) {
2892 			if (inet_pton(AF_INET, s, addr)) {
2893 				return (0);
2894 			}
2895 			return (1);
2896 		} else if (type == AU_IPv6) {
2897 			if (inet_pton(AF_INET6, s, addr))
2898 				return (0);
2899 			return (1);
2900 		}
2901 		return (1);
2902 	} else {
2903 		if (type == AU_IPv4) {
2904 			(void) sscanf(s, "%x", &addr[0]);
2905 			return (0);
2906 		} else if (type == AU_IPv6) {
2907 			sl = strlen(s);
2908 			ss = s;
2909 			for (j = 3; j >= 0; j--) {
2910 				if ((sl - 8) <= 0) {
2911 					(void) sscanf(s, "%x", &v);
2912 					addr[j] = v;
2913 					return (0);
2914 				}
2915 				ss = &s[sl-8];
2916 				(void) sscanf(ss, "%x", &v);
2917 				addr[j] = v;
2918 				sl -= 8;
2919 				*ss = '\0';
2920 			}
2921 		}
2922 		return (0);
2923 	}
2924 }
2925 
2926 static int
2927 str2type(char *s, uint_t *type)
2928 {
2929 	if (strcmp(s, "ipv6") == 0) {
2930 		*type = AU_IPv6;
2931 		return (0);
2932 	}
2933 	if (strcmp(s, "ipv4") == 0) {
2934 		*type = AU_IPv4;
2935 		return (0);
2936 	}
2937 
2938 	return (1);
2939 }
2940 
2941 /*
2942  * exit_error() - print an error message along with corresponding system error
2943  * number and error message, then exit. Inputs - program error format and
2944  * message.
2945  */
2946 /*PRINTFLIKE1*/
2947 static void
2948 exit_error(char *fmt, ...)
2949 {
2950 	va_list	args;
2951 
2952 	va_start(args, fmt);
2953 	prt_error_va(fmt, args);
2954 	va_end(args);
2955 
2956 	exit(1);
2957 }
2958