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