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