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