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