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