xref: /titanic_50/usr/src/cmd/auditconfig/auditconfig.c (revision 2e219f6b49c86a655169ff268a9ea1af9af87af1)
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 2010 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 		if (qctrl.aq_bufsz == 0) {
1795 			return;
1796 		}
1797 	}
1798 
1799 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1800 	qctrl.aq_bufsz = (size_t)atol(bufsz);
1801 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
1802 }
1803 
1804 /*
1805  * do_setqctrl() - set the active and configured audit queue write buffer size
1806  * (bytes), hiwater audit record count, lowater audit record count, and wakeup
1807  * interval (ticks); active values can be changed per zone if AUDIT_PERZONE is
1808  * set, else only in global zone.
1809  */
1810 static void
1811 do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay)
1812 {
1813 	struct au_qctrl	qctrl;
1814 
1815 	qctrl.aq_hiwater = (size_t)atol(hiwater);
1816 	qctrl.aq_lowater = (size_t)atol(lowater);
1817 	qctrl.aq_bufsz = (size_t)atol(bufsz);
1818 	qctrl.aq_delay = (clock_t)atol(delay);
1819 
1820 	if (!temporary_set) {
1821 		struct au_qctrl qctrl_act;
1822 
1823 		if (!do_setqctrl_scf(&qctrl)) {
1824 			exit_error(gettext(
1825 			    "Could not store configuration values."));
1826 		}
1827 
1828 		eauditon(A_GETQCTRL, (caddr_t)&qctrl_act, 0);
1829 		if (qctrl.aq_hiwater == 0) {
1830 			qctrl.aq_hiwater = qctrl_act.aq_hiwater;
1831 		}
1832 		if (qctrl.aq_lowater == 0) {
1833 			qctrl.aq_lowater = qctrl_act.aq_lowater;
1834 		}
1835 		if (qctrl.aq_bufsz == 0) {
1836 			qctrl.aq_bufsz = qctrl_act.aq_bufsz;
1837 		}
1838 		if (qctrl.aq_delay == 0) {
1839 			qctrl.aq_delay = qctrl_act.aq_delay;
1840 		}
1841 	}
1842 
1843 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
1844 }
1845 
1846 /*
1847  * do_setqdelay() - set the active and configured audit queue wakeup interval
1848  * (ticks); active values can be changed per zone if AUDIT_PERZONE is set, else
1849  * only in global zone.
1850  */
1851 static void
1852 do_setqdelay(char *delay)
1853 {
1854 	struct au_qctrl qctrl;
1855 
1856 	if (!temporary_set) {
1857 		qctrl.aq_delay = (clock_t)atol(delay);
1858 		if (!do_setqdelay_scf(&qctrl.aq_delay)) {
1859 			exit_error(gettext(
1860 			    "Could not store configuration value."));
1861 		}
1862 		if (qctrl.aq_delay == 0) {
1863 			return;
1864 		}
1865 	}
1866 
1867 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1868 	qctrl.aq_delay = (clock_t)atol(delay);
1869 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
1870 }
1871 
1872 /*
1873  * do_setqhiwater() - sets the active and configured number of undelivered audit
1874  * records in the audit queue at which audit record generation blocks; active
1875  * values can be changed per zone if AUDIT_PERZONE is set, else only in global
1876  * zone.
1877  */
1878 static void
1879 do_setqhiwater(char *hiwater)
1880 {
1881 	struct au_qctrl qctrl;
1882 
1883 	if (!temporary_set) {
1884 		qctrl.aq_hiwater = (size_t)atol(hiwater);
1885 		if (!do_setqhiwater_scf(&qctrl.aq_hiwater)) {
1886 			exit_error(gettext(
1887 			    "Could not store configuration value."));
1888 		}
1889 		if (qctrl.aq_hiwater == 0) {
1890 			return;
1891 		}
1892 	}
1893 
1894 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1895 	qctrl.aq_hiwater = (size_t)atol(hiwater);
1896 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
1897 }
1898 
1899 /*
1900  * do_setqlowater() - set the active and configured number of undelivered audit
1901  * records in the audit queue at which blocked auditing processes unblock;
1902  * active values can be changed per zone if AUDIT_PERZONE is set, else only in
1903  * global zone.
1904  */
1905 static void
1906 do_setqlowater(char *lowater)
1907 {
1908 	struct au_qctrl qctrl;
1909 
1910 	if (!temporary_set) {
1911 		qctrl.aq_lowater = (size_t)atol(lowater);
1912 		if (!do_setqlowater_scf(&qctrl.aq_lowater)) {
1913 			exit_error(gettext(
1914 			    "Could not store configuration value."));
1915 		}
1916 		if (qctrl.aq_lowater == 0) {
1917 			return;
1918 		}
1919 	}
1920 
1921 	eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
1922 	qctrl.aq_lowater = (size_t)atol(lowater);
1923 	eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
1924 }
1925 
1926 static void
1927 eauditon(int cmd, caddr_t data, int length)
1928 {
1929 	if (auditon(cmd, data, length) == -1)
1930 		exit_error(gettext("auditon(2) failed."));
1931 }
1932 
1933 static void
1934 egetauid(au_id_t *auid)
1935 {
1936 	if (getauid(auid) == -1)
1937 		exit_error(gettext("getauid(2) failed."));
1938 }
1939 
1940 static void
1941 egetaudit(auditinfo_addr_t *ai, int size)
1942 {
1943 	if (getaudit_addr(ai, size) == -1)
1944 		exit_error(gettext("getaudit_addr(2) failed."));
1945 }
1946 
1947 static void
1948 egetkaudit(auditinfo_addr_t *ai, int size)
1949 {
1950 	if (auditon(A_GETKAUDIT, (char *)ai, size) < 0)
1951 		exit_error(gettext("auditon: A_GETKAUDIT failed."));
1952 }
1953 
1954 static void
1955 esetkaudit(auditinfo_addr_t *ai, int size)
1956 {
1957 	if (auditon(A_SETKAUDIT, (char *)ai, size) < 0)
1958 		exit_error(gettext("auditon: A_SETKAUDIT failed."));
1959 }
1960 
1961 static void
1962 egetauditflagsbin(char *auditflags, au_mask_t *pmask)
1963 {
1964 	pmask->am_success = pmask->am_failure = 0;
1965 
1966 	if (strcmp(auditflags, "none") == 0)
1967 		return;
1968 
1969 	if (getauditflagsbin(auditflags, pmask) < 0) {
1970 		exit_error(gettext("Could not get audit flags (%s)"),
1971 		    auditflags);
1972 	}
1973 }
1974 
1975 static au_event_ent_t *
1976 egetauevnum(au_event_t event_number)
1977 {
1978 	au_event_ent_t *evp;
1979 
1980 	if ((evp = getauevnum(event_number)) == NULL) {
1981 		exit_error(gettext("Could not get audit event %hu"),
1982 		    event_number);
1983 	}
1984 
1985 	return (evp);
1986 }
1987 
1988 static au_event_ent_t *
1989 egetauevnam(char *event_name)
1990 {
1991 	register au_event_ent_t *evp;
1992 
1993 	if ((evp = getauevnam(event_name)) == NULL)
1994 		exit_error(gettext("Could not get audit event %s"), event_name);
1995 
1996 	return (evp);
1997 }
1998 
1999 static void
2000 esetauid(au_id_t *auid)
2001 {
2002 	if (setauid(auid) == -1)
2003 		exit_error(gettext("setauid(2) failed."));
2004 }
2005 
2006 static void
2007 esetaudit(auditinfo_addr_t *ai, int size)
2008 {
2009 	if (setaudit_addr(ai, size) == -1)
2010 		exit_error(gettext("setaudit_addr(2) failed."));
2011 }
2012 
2013 static uid_t
2014 get_user_id(char *user)
2015 {
2016 	struct passwd *pwd;
2017 	uid_t uid;
2018 
2019 	if (isdigit(*user)) {
2020 		uid = atoi(user);
2021 		if ((pwd = getpwuid(uid)) == NULL) {
2022 			exit_error(gettext("Invalid user: %s"), user);
2023 		}
2024 	} else {
2025 		if ((pwd = getpwnam(user)) == NULL) {
2026 			exit_error(gettext("Invalid user: %s"), user);
2027 		}
2028 	}
2029 
2030 	return (pwd->pw_uid);
2031 }
2032 
2033 /*
2034  * get_arg_ent()
2035  *     Inputs: command line argument string
2036  *     Returns ptr to struct arg_entry if found; null, if not found
2037  */
2038 static arg_entry_t *
2039 get_arg_ent(char *arg_str)
2040 {
2041 	arg_entry_t key;
2042 
2043 	key.arg_str = arg_str;
2044 
2045 	return ((arg_entry_t *)bsearch((char *)&key, (char *)arg_table,
2046 	    ARG_TBL_SZ, sizeof (arg_entry_t), arg_ent_compare));
2047 }
2048 
2049 /*
2050  * arg_ent_compare()
2051  *     Compares two command line arguments to determine which is
2052  *       lexicographically greater.
2053  *     Inputs: two argument map table entry pointers
2054  *     Returns: > 1: aep1->arg_str > aep2->arg_str
2055  *              < 1: aep1->arg_str < aep2->arg_str
2056  *                0: aep1->arg_str = aep->arg_str2
2057  */
2058 static int
2059 arg_ent_compare(const void *aep1, const void *aep2)
2060 {
2061 	return (strcmp(((arg_entry_t *)aep1)->arg_str,
2062 	    ((arg_entry_t *)aep2)->arg_str));
2063 }
2064 
2065 /*
2066  * Convert mask of the following forms:
2067  *
2068  *    audit_flags (ie. +lo,-ad,pc)
2069  *    0xffffffff,0xffffffff
2070  *    ffffffff,ffffffff
2071  *    20,20
2072  */
2073 static void
2074 str2mask(char *mask_str, au_mask_t *mp)
2075 {
2076 
2077 	char sp[256];
2078 	char fp[256];
2079 
2080 	mp->am_success = 0;
2081 	mp->am_failure = 0;
2082 
2083 	/*
2084 	 * a mask of the form +aa,bb,cc,-dd or
2085 	 * a mask of the form 0xffffffff,0xffffffff or 1,1
2086 	 */
2087 	if (strisflags(mask_str)) {
2088 		egetauditflagsbin(mask_str, mp);
2089 	} else {
2090 		strsplit(mask_str, sp, fp, ',');
2091 
2092 		if (strlen(sp) > (size_t)2 && !strncasecmp(sp, "0x", 2)) {
2093 			(void) sscanf(sp + 2, "%x", &mp->am_success);
2094 		} else {
2095 			(void) sscanf(sp, "%u", &mp->am_success);
2096 		}
2097 
2098 		if (strlen(fp) > (size_t)2 && !strncasecmp(fp, "0x", 2)) {
2099 			(void) sscanf(fp + 2, "%x", &mp->am_failure);
2100 		} else {
2101 			(void) sscanf(fp, "%u", &mp->am_failure);
2102 		}
2103 	}
2104 }
2105 
2106 /*
2107  * tid_str is major,minor,host  -- host is a name or an ip address
2108  */
2109 static void
2110 str2tid(char *tid_str, au_tid_addr_t *tp)
2111 {
2112 	char *major_str;
2113 	char *minor_str;
2114 	char *host_str = NULL;
2115 	major_t major = 0;
2116 	major_t minor = 0;
2117 	dev_t dev = 0;
2118 	struct hostent *phe;
2119 	int err;
2120 	uint32_t ibuf;
2121 	uint32_t ibuf6[4];
2122 
2123 	tp->at_port = 0;
2124 	tp->at_type = 0;
2125 	bzero(tp->at_addr, 16);
2126 
2127 	major_str = tid_str;
2128 	if ((minor_str = strchr(tid_str, ',')) != NULL) {
2129 		*minor_str = '\0';
2130 		minor_str++;
2131 	}
2132 
2133 	if (minor_str) {
2134 		if ((host_str = strchr(minor_str, ',')) != NULL) {
2135 			*host_str = '\0';
2136 			host_str++;
2137 		}
2138 	}
2139 
2140 	if (major_str)
2141 		major = (major_t)atoi(major_str);
2142 
2143 	if (minor_str)
2144 		minor = (minor_t)atoi(minor_str);
2145 
2146 	if ((dev = makedev(major, minor)) != NODEV)
2147 		tp->at_port = dev;
2148 
2149 	if (host_str) {
2150 		if (strisipaddr(host_str)) {
2151 			if (inet_pton(AF_INET, host_str, &ibuf)) {
2152 				tp->at_addr[0] = ibuf;
2153 				tp->at_type = AU_IPv4;
2154 			} else if (inet_pton(AF_INET6, host_str, ibuf6)) {
2155 				tp->at_addr[0] = ibuf6[0];
2156 				tp->at_addr[1] = ibuf6[1];
2157 				tp->at_addr[2] = ibuf6[2];
2158 				tp->at_addr[3] = ibuf6[3];
2159 				tp->at_type = AU_IPv6;
2160 			}
2161 		} else {
2162 			phe = getipnodebyname((const void *)host_str,
2163 			    AF_INET, 0, &err);
2164 			if (phe == 0) {
2165 				phe = getipnodebyname((const void *)host_str,
2166 				    AF_INET6, 0, &err);
2167 			}
2168 
2169 			if (phe != NULL) {
2170 				if (phe->h_addrtype == AF_INET6) {
2171 					/* address is IPv6 (128 bits) */
2172 					(void) memcpy(&tp->at_addr[0],
2173 					    phe->h_addr_list[0], 16);
2174 					tp->at_type = AU_IPv6;
2175 				} else {
2176 					/* address is IPv4 (32 bits) */
2177 					(void) memcpy(&tp->at_addr[0],
2178 					    phe->h_addr_list[0], 4);
2179 					tp->at_type = AU_IPv4;
2180 				}
2181 				freehostent(phe);
2182 			}
2183 		}
2184 	}
2185 }
2186 
2187 static char *
2188 cond2str(void)
2189 {
2190 	uint_t cond;
2191 
2192 	eauditon(A_GETCOND, (caddr_t)&cond, (int)sizeof (cond));
2193 
2194 	switch (cond) {
2195 
2196 	case AUC_AUDITING:
2197 		return ("auditing");
2198 
2199 	case AUC_NOAUDIT:
2200 	case AUC_INIT_AUDIT:
2201 		return ("noaudit");
2202 
2203 	case AUC_UNSET:
2204 		return ("unset");
2205 
2206 	case AUC_NOSPACE:
2207 		return ("nospace");
2208 
2209 	default:
2210 		return ("");
2211 	}
2212 }
2213 
2214 /*
2215  * 	exit = 0, success
2216  *	       1, error
2217  *	       2, bad zone
2218  */
2219 static int
2220 str2policy(char *policy_str, uint32_t *policy_mask)
2221 {
2222 	char		*buf;
2223 	char		*tok;
2224 	char		pfix;
2225 	boolean_t	is_all = B_FALSE;
2226 	uint32_t	pm = 0;
2227 	uint32_t	curp;
2228 
2229 	pfix = *policy_str;
2230 
2231 	if (pfix == '-' || pfix == '+' || pfix == '=')
2232 		++policy_str;
2233 
2234 	if ((buf = strdup(policy_str)) == NULL)
2235 		return (1);
2236 
2237 	for (tok = strtok(buf, ","); tok != NULL; tok = strtok(NULL, ",")) {
2238 		uint32_t tok_pm;
2239 		if (((tok_pm = get_policy(tok)) == 0) &&
2240 		    ((strcasecmp(tok, "none") != 0))) {
2241 			free(buf);
2242 			return (1);
2243 		} else {
2244 			pm |= tok_pm;
2245 			if (tok_pm == ALL_POLICIES) {
2246 				is_all = B_TRUE;
2247 			}
2248 		}
2249 	}
2250 	free(buf);
2251 
2252 	/* reuse policy mask if already set to some value */
2253 	if (*policy_mask != 0) {
2254 		curp = *policy_mask;
2255 	} else {
2256 		(void) auditon(A_GETPOLICY, (caddr_t)&curp, 0);
2257 	}
2258 
2259 	if (pfix == '-') {
2260 		if (!is_all &&
2261 		    (getzoneid() != GLOBAL_ZONEID) &&
2262 		    (pm & ~AUDIT_LOCAL)) {
2263 			return (2);
2264 		}
2265 
2266 		if (getzoneid() != GLOBAL_ZONEID)
2267 			curp &= AUDIT_LOCAL;
2268 		*policy_mask = curp & ~pm;
2269 
2270 	} else if (pfix == '+') {
2271 		/*
2272 		 * In a local zone, accept specifying "all", but not
2273 		 * individually specifying global-zone only policies.
2274 		 * Limit to all locally allowed, so system call doesn't
2275 		 * fail.
2276 		 */
2277 		if (!is_all &&
2278 		    (getzoneid() != GLOBAL_ZONEID) &&
2279 		    (pm & ~AUDIT_LOCAL)) {
2280 			return (2);
2281 		}
2282 
2283 		if (getzoneid() != GLOBAL_ZONEID) {
2284 			curp &= AUDIT_LOCAL;
2285 			if (is_all) {
2286 				pm &= AUDIT_LOCAL;
2287 			}
2288 		}
2289 		*policy_mask = curp | pm;
2290 
2291 	} else {
2292 		/*
2293 		 * In a local zone, accept specifying "all", but not
2294 		 * individually specifying global-zone only policies.
2295 		 * Limit to all locally allowed, so system call doesn't
2296 		 * fail.
2297 		 */
2298 		if (!is_all &&
2299 		    (getzoneid() != GLOBAL_ZONEID) &&
2300 		    (pm & ~AUDIT_LOCAL)) {
2301 			return (2);
2302 		}
2303 
2304 		if (is_all && (getzoneid() != GLOBAL_ZONEID)) {
2305 			pm &= AUDIT_LOCAL;
2306 		}
2307 		*policy_mask = pm;
2308 	}
2309 	return (0);
2310 }
2311 
2312 static int
2313 policy2str(uint32_t policy, char *policy_str, size_t len)
2314 {
2315 	int i, j;
2316 
2317 	if (policy == ALL_POLICIES) {
2318 		(void) strcpy(policy_str, "all");
2319 		return (1);
2320 	}
2321 
2322 	if (policy == NO_POLICIES) {
2323 		(void) strcpy(policy_str, "none");
2324 		return (1);
2325 	}
2326 
2327 	*policy_str = '\0';
2328 
2329 	for (i = 0, j = 0; i < POLICY_TBL_SZ; i++) {
2330 		if (policy & policy_table[i].policy_mask &&
2331 		    policy_table[i].policy_mask != ALL_POLICIES) {
2332 			if (j++) {
2333 				(void) strcat(policy_str, ",");
2334 			}
2335 			(void) strlcat(policy_str, policy_table[i].policy_str,
2336 			    len);
2337 		}
2338 	}
2339 
2340 	if (*policy_str)
2341 		return (0);
2342 
2343 	return (1);
2344 }
2345 
2346 
2347 static int
2348 strisnum(char *s)
2349 {
2350 	if (s == NULL || !*s)
2351 		return (0);
2352 
2353 	for (; *s == '-' || *s == '+'; s++)
2354 
2355 	if (!*s)
2356 		return (0);
2357 
2358 	for (; *s; s++)
2359 		if (!isdigit(*s))
2360 			return (0);
2361 
2362 	return (1);
2363 }
2364 
2365 static int
2366 strisflags(char *s)
2367 {
2368 	if (s == NULL || !*s)
2369 		return (0);
2370 
2371 	for (; *s; s++) {
2372 		if (!isalpha(*s) &&
2373 		    (*s != '+' && *s != '-' && *s != '^' && *s != ','))
2374 			return (0);
2375 	}
2376 
2377 	return (1);
2378 }
2379 
2380 static int
2381 strisipaddr(char *s)
2382 {
2383 	int dot = 0;
2384 	int colon = 0;
2385 
2386 	/* no string */
2387 	if ((s == NULL) || (!*s))
2388 		return (0);
2389 
2390 	for (; *s; s++) {
2391 		if (!(isxdigit(*s) || *s != '.' || *s != ':'))
2392 			return (0);
2393 		if (*s == '.')
2394 			dot++;
2395 		if (*s == ':')
2396 			colon++;
2397 	}
2398 
2399 	if (dot && colon)
2400 		return (0);
2401 
2402 	if (!dot && !colon)
2403 		return (0);
2404 
2405 	return (1);
2406 }
2407 
2408 static void
2409 strsplit(char *s, char *p1, char *p2, char c)
2410 {
2411 	*p1 = *p2 = '\0';
2412 
2413 	while (*s != '\0' && *s != c)
2414 		*p1++ = *s++;
2415 	*p1 = '\0';
2416 	s++;
2417 
2418 	while (*s != '\0')
2419 		*p2++ = *s++;
2420 	*p2 = '\0';
2421 }
2422 
2423 static void
2424 chk_event_num(int etype, au_event_t event)
2425 {
2426 	au_stat_t as;
2427 
2428 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
2429 
2430 	if (etype == AC_KERN_EVENT) {
2431 		if (event > as.as_numevent) {
2432 			exit_error(gettext(
2433 			    "Invalid kernel audit event number specified.\n"
2434 			    "\t%hu is outside allowable range 0-%d."),
2435 			    event, as.as_numevent);
2436 		}
2437 	} else  {
2438 		/* user event */
2439 		if (event <= as.as_numevent) {
2440 			exit_error(gettext("Invalid user level audit event "
2441 			    "number specified %hu."), event);
2442 		}
2443 	}
2444 }
2445 
2446 static void
2447 chk_event_str(int etype, char *event_str)
2448 {
2449 	au_event_ent_t *evp;
2450 	au_stat_t as;
2451 
2452 	eauditon(A_GETSTAT, (caddr_t)&as, 0);
2453 
2454 	evp = egetauevnam(event_str);
2455 	if (etype == AC_KERN_EVENT && (evp->ae_number > as.as_numevent)) {
2456 		exit_error(gettext(
2457 		    "Invalid kernel audit event string specified.\n"
2458 		    "\t\"%s\" appears to be a user level event. "
2459 		    "Check configuration."), event_str);
2460 	} else if (etype == AC_USER_EVENT &&
2461 	    (evp->ae_number < as.as_numevent)) {
2462 		exit_error(gettext(
2463 		    "Invalid user audit event string specified.\n"
2464 		    "\t\"%s\" appears to be a kernel event. "
2465 		    "Check configuration."), event_str);
2466 	}
2467 }
2468 
2469 static void
2470 chk_sorf(char *sorf_str)
2471 {
2472 	if (!strisnum(sorf_str))
2473 		exit_error(gettext("Invalid sorf specified: %s"), sorf_str);
2474 }
2475 
2476 static void
2477 chk_retval(char *retval_str)
2478 {
2479 	if (!strisnum(retval_str))
2480 		exit_error(gettext("Invalid retval specified: %s"), retval_str);
2481 }
2482 
2483 static void
2484 execit(char **argv)
2485 {
2486 	char *args, *args_pos;
2487 	size_t len = 0;
2488 	size_t n = 0;
2489 	char **argv_pos;
2490 
2491 	if (*argv) {
2492 		/* concatenate argument array to be passed to sh -c "..." */
2493 		for (argv_pos = argv; *argv_pos; argv_pos++)
2494 			len += strlen(*argv_pos) + 1;
2495 
2496 		if ((args = malloc(len + 1)) == NULL)
2497 			exit_error(
2498 			    gettext("Allocation for command/arguments failed"));
2499 
2500 		args_pos = args;
2501 		for (argv_pos = argv; *argv_pos; argv_pos++) {
2502 			n += snprintf(args_pos, len - n, "%s ", *argv_pos);
2503 			args_pos = args + n;
2504 		}
2505 		/* strip the last space */
2506 		args[strlen(args)] = '\0';
2507 
2508 		(void) execl("/bin/sh", "sh", "-c", args, NULL);
2509 	} else {
2510 		(void) execl("/bin/sh", "sh", NULL);
2511 	}
2512 
2513 	exit_error(gettext("exec(2) failed"));
2514 }
2515 
2516 static void
2517 exit_usage(int status)
2518 {
2519 	FILE *fp;
2520 	int i;
2521 
2522 	fp = (status ? stderr : stdout);
2523 	(void) fprintf(fp, gettext("usage: %s option ...\n"), progname);
2524 
2525 	for (i = 0; i < ARG_TBL_SZ; i++) {
2526 		/* skip the -t option; it's not a standalone option */
2527 		if (arg_table[i].auditconfig_cmd == AC_ARG_SET_TEMPORARY) {
2528 			continue;
2529 		}
2530 
2531 		(void) fprintf(fp, " %s%s%s\n",
2532 		    arg_table[i].arg_str, arg_table[i].arg_opts,
2533 		    (arg_table[i].temporary_allowed ? " [-t]" : ""));
2534 	}
2535 
2536 	exit(status);
2537 }
2538 
2539 static void
2540 print_asid(au_asid_t asid)
2541 {
2542 	(void) printf(gettext("audit session id = %u\n"), asid);
2543 }
2544 
2545 static void
2546 print_auid(au_id_t auid)
2547 {
2548 	struct passwd *pwd;
2549 	char *username;
2550 
2551 	if ((pwd = getpwuid((uid_t)auid)) != NULL)
2552 		username = pwd->pw_name;
2553 	else
2554 		username = gettext("unknown");
2555 
2556 	(void) printf(gettext("audit id = %s(%d)\n"), username, auid);
2557 }
2558 
2559 static void
2560 print_mask(char *desc, au_mask_t *pmp)
2561 {
2562 	char auflags[512];
2563 
2564 	if (getauditflagschar(auflags, pmp, NULL) < 0)
2565 		(void) strlcpy(auflags, gettext("unknown"), sizeof (auflags));
2566 
2567 	(void) printf("%s = %s(0x%x,0x%x)\n",
2568 	    desc, auflags, pmp->am_success, pmp->am_failure);
2569 }
2570 
2571 static void
2572 print_tid_ex(au_tid_addr_t *tidp)
2573 {
2574 	struct hostent *phe;
2575 	char *hostname;
2576 	struct in_addr ia;
2577 	uint32_t *addr;
2578 	int err;
2579 	char buf[INET6_ADDRSTRLEN];
2580 	char *bufp;
2581 
2582 
2583 	/* IPV6 or IPV4 address */
2584 	if (tidp->at_type == AU_IPv4) {
2585 		if ((phe = gethostbyaddr((char *)&tidp->at_addr[0],
2586 		    sizeof (tidp->at_addr[0]), AF_INET)) != NULL) {
2587 			hostname = phe->h_name;
2588 		} else {
2589 			hostname = gettext("unknown");
2590 		}
2591 
2592 		ia.s_addr = tidp->at_addr[0];
2593 
2594 		(void) printf(gettext(
2595 		    "terminal id (maj,min,host) = %lu,%lu,%s(%s)\n"),
2596 		    major(tidp->at_port), minor(tidp->at_port),
2597 		    hostname, inet_ntoa(ia));
2598 	} else {
2599 		addr = &tidp->at_addr[0];
2600 		phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
2601 
2602 		bzero(buf, sizeof (buf));
2603 
2604 		(void) inet_ntop(AF_INET6, (void *)addr, buf, sizeof (buf));
2605 		if (phe == NULL) {
2606 			bufp = gettext("unknown");
2607 		} else {
2608 			bufp = phe->h_name;
2609 		}
2610 
2611 		(void) printf(gettext(
2612 		    "terminal id (maj,min,host) = %lu,%lu,%s(%s)\n"),
2613 		    major(tidp->at_port), minor(tidp->at_port),
2614 		    bufp, buf);
2615 		if (phe) {
2616 			freehostent(phe);
2617 		}
2618 	}
2619 }
2620 
2621 static int
2622 str2ipaddr(char *s, uint32_t *addr, uint32_t type)
2623 {
2624 	int j, sl;
2625 	char *ss;
2626 	unsigned int v;
2627 
2628 	bzero(addr, 16);
2629 	if (strisipaddr(s)) {
2630 		if (type == AU_IPv4) {
2631 			if (inet_pton(AF_INET, s, addr)) {
2632 				return (0);
2633 			}
2634 			return (1);
2635 		} else if (type == AU_IPv6) {
2636 			if (inet_pton(AF_INET6, s, addr))
2637 				return (0);
2638 			return (1);
2639 		}
2640 		return (1);
2641 	} else {
2642 		if (type == AU_IPv4) {
2643 			(void) sscanf(s, "%x", &addr[0]);
2644 			return (0);
2645 		} else if (type == AU_IPv6) {
2646 			sl = strlen(s);
2647 			ss = s;
2648 			for (j = 3; j >= 0; j--) {
2649 				if ((sl - 8) <= 0) {
2650 					(void) sscanf(s, "%x", &v);
2651 					addr[j] = v;
2652 					return (0);
2653 				}
2654 				ss = &s[sl-8];
2655 				(void) sscanf(ss, "%x", &v);
2656 				addr[j] = v;
2657 				sl -= 8;
2658 				*ss = '\0';
2659 			}
2660 		}
2661 		return (0);
2662 	}
2663 }
2664 
2665 static int
2666 str2type(char *s, uint_t *type)
2667 {
2668 	if (strcmp(s, "ipv6") == 0) {
2669 		*type = AU_IPv6;
2670 		return (0);
2671 	}
2672 	if (strcmp(s, "ipv4") == 0) {
2673 		*type = AU_IPv4;
2674 		return (0);
2675 	}
2676 
2677 	return (1);
2678 }
2679 
2680 /*
2681  * exit_error() - print an error message along with corresponding system error
2682  * number and error message, then exit. Inputs - program error format and
2683  * message.
2684  */
2685 /*PRINTFLIKE1*/
2686 static void
2687 exit_error(char *fmt, ...)
2688 {
2689 	va_list	args;
2690 
2691 	va_start(args, fmt);
2692 	prt_error_va(fmt, args);
2693 	va_end(args);
2694 
2695 	exit(1);
2696 }
2697