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 
  61 enum    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  */
 123 struct 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 };
 129 typedef struct arg_entry arg_entry_t;
 130 
 131 /* arg_table - command option and usage message table */
 132 static 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 
 189 char    *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  */
 195 static boolean_t temporary_set = B_FALSE;
 196 
 197 static au_event_ent_t *egetauevnam(char *event_name);
 198 static au_event_ent_t *egetauevnum(au_event_t event_number);
 199 static int arg_ent_compare(const void *aep1, const void *aep2);
 200 static char *cond2str(void);
 201 static int policy2str(uint32_t policy, char *policy_str, size_t len);
 202 static int str2type(char *s, uint_t *type);
 203 static int str2policy(char *policy_str, uint32_t *policy_mask);
 204 static int str2ipaddr(char *s, uint32_t *addr, uint32_t type);
 205 static int strisipaddr(char *s);
 206 static int strisnum(char *s);
 207 static arg_entry_t *get_arg_ent(char *arg_str);
 208 static uid_t get_user_id(char *user);
 209 static void chk_arg_len(char *argv, uint_t len);
 210 static void chk_event_num(int etype, au_event_t event);
 211 static void chk_event_str(int etype, char *event_str);
 212 static void chk_known_plugin(char *plugin_str);
 213 static void chk_retval(char *retval_str);
 214 static void chk_sorf(char *sorf_str);
 215 static void do_aconf(void);
 216 static void do_args(char **argv, au_mask_t *mask);
 217 static void do_audit(char *, char, int, char *);
 218 static void do_chkaconf(void);
 219 static void do_chkconf(void);
 220 static void do_conf(void);
 221 static void do_getasid(void);
 222 static void do_getaudit(void);
 223 static void do_getkaudit(void);
 224 static void do_setkaudit(char *t, char *s);
 225 static void do_getauid(void);
 226 static void do_getcar(void);
 227 static void do_getclass(char *event_str);
 228 static void do_getcond(void);
 229 static void do_getcwd(void);
 230 static void do_getflags(void);
 231 static void do_getkmask(void);
 232 static void do_getnaflags(void);
 233 static void do_getpinfo(char *pid_str);
 234 static void do_getplugin(char *plugin_str);
 235 static void do_getpolicy(void);
 236 static void do_getqbufsz(void);
 237 static void do_getqctrl(void);
 238 static void do_getqdelay(void);
 239 static void do_getqhiwater(void);
 240 static void do_getqlowater(void);
 241 static void do_getstat(void);
 242 static void do_gettermid(void);
 243 static void do_lsevent(void);
 244 static void do_lspolicy(void);
 245 static void do_setasid(char *sid_str, char **argv);
 246 static void do_setaudit(char *user_str, char *mask_str, char *tid_str,
 247     char *sid_str, char **argv);
 248 static void do_setauid(char *user, char **argv);
 249 static void do_setclass(char *event_str, au_mask_t *mask);
 250 static void do_setflags(char *audit_flags, au_mask_t *amask);
 251 static void do_setkmask(au_mask_t *pmask);
 252 static void do_setnaflags(char *audit_naflags, au_mask_t *namask);
 253 static void do_setpmask(char *pid_str, au_mask_t *mask);
 254 static void do_setsmask(char *asid_str, au_mask_t *mask);
 255 static void do_setumask(char *auid_str, au_mask_t *mask);
 256 static void do_setplugin(char *plugin_str, boolean_t plugin_state,
 257     char *plugin_attr, int plugin_qsize);
 258 static void do_setpolicy(char *policy_str);
 259 static void do_setqbufsz(char *bufsz);
 260 static void do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay);
 261 static void do_setqdelay(char *delay);
 262 static void do_setqhiwater(char *hiwater);
 263 static void do_setqlowater(char *lowater);
 264 static void do_setstat(void);
 265 static void str2tid(char *tid_str, au_tid_addr_t *tp);
 266 
 267 static void eauditon(int cmd, caddr_t data, int length);
 268 static void echkflags(char *auditflags, au_mask_t *mask);
 269 static void egetaudit(auditinfo_addr_t *ai, int size);
 270 static void egetauditflagsbin(char *auditflags, au_mask_t *pmask);
 271 static void egetauid(au_id_t *auid);
 272 static void egetkaudit(auditinfo_addr_t *ai, int size);
 273 static void esetaudit(auditinfo_addr_t *ai, int size);
 274 static void esetauid(au_id_t *auid);
 275 static void esetkaudit(auditinfo_addr_t *ai, int size);
 276 static void execit(char **argv);
 277 static void exit_error(char *fmt, ...);
 278 static void exit_usage(int status);
 279 static void parse_args(int argc, char **argv, au_mask_t *mask);
 280 static void print_asid(au_asid_t asid);
 281 static void print_auid(au_id_t auid);
 282 static void print_mask(char *desc, au_mask_t *pmp);
 283 static void print_plugin(char *plugin_name, kva_t *plugin_kva);
 284 static 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 
 290 int
 291 main(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  */
 323 static void
 324 parse_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  */
 630 static void
 631 do_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  */
 987 static void
 988 do_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  */
1050 static void
1051 do_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  */
1080 static void
1081 do_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  */
1116 static void
1117 do_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  */
1138 static void
1139 do_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  */
1219 static void
1220 do_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  */
1231 static void
1232 do_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  */
1246 static void
1247 do_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  */
1262 static void
1263 do_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  */
1278 static void
1279 do_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  */
1292 static void
1293 do_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  */
1327 static void
1328 do_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  */
1336 static void
1337 do_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  */
1349 static void
1350 do_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  */
1370 static void
1371 do_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  */
1383 static void
1384 do_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  */
1404 static void
1405 do_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  */
1429 static void
1430 do_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  */
1450 static void
1451 do_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  */
1477 static void
1478 do_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  */
1506 static void
1507 do_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  */
1561 static void
1562 do_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  */
1589 static void
1590 do_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  */
1617 static void
1618 do_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  */
1644 static void
1645 do_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  */
1659 static void
1660 do_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  */
1706 static void
1707 do_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  */
1722 static void
1723 do_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  */
1750 static void
1751 do_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  */
1769 static void
1770 do_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  */
1787 static void
1788 do_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  */
1805 static void
1806 do_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  */
1819 static void
1820 do_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  */
1841 static void
1842 do_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  */
1863 static void
1864 do_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  */
1884 static void
1885 do_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  */
1910 static void
1911 do_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  */
1935 static void
1936 do_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  */
1951 static void
1952 do_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  */
1962 static void
1963 do_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  */
1978 static void
1979 do_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  */
1996 static void
1997 do_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  */
2033 static void
2034 do_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  */
2060 static void
2061 do_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  */
2101 static void
2102 do_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  */
2128 static void
2129 do_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  */
2155 static void
2156 do_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 
2176 static void
2177 eauditon(int cmd, caddr_t data, int length)
2178 {
2179         if (auditon(cmd, data, length) == -1)
2180                 exit_error(gettext("auditon(2) failed."));
2181 }
2182 
2183 static void
2184 egetauid(au_id_t *auid)
2185 {
2186         if (getauid(auid) == -1)
2187                 exit_error(gettext("getauid(2) failed."));
2188 }
2189 
2190 static void
2191 egetaudit(auditinfo_addr_t *ai, int size)
2192 {
2193         if (getaudit_addr(ai, size) == -1)
2194                 exit_error(gettext("getaudit_addr(2) failed."));
2195 }
2196 
2197 static void
2198 egetkaudit(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 
2204 static void
2205 esetkaudit(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 
2211 static void
2212 egetauditflagsbin(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 
2225 static void
2226 echkflags(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 
2242 static au_event_ent_t *
2243 egetauevnum(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 
2255 static au_event_ent_t *
2256 egetauevnam(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 
2266 static void
2267 esetauid(au_id_t *auid)
2268 {
2269         if (setauid(auid) == -1)
2270                 exit_error(gettext("setauid(2) failed."));
2271 }
2272 
2273 static void
2274 esetaudit(auditinfo_addr_t *ai, int size)
2275 {
2276         if (setaudit_addr(ai, size) == -1)
2277                 exit_error(gettext("setaudit_addr(2) failed."));
2278 }
2279 
2280 static uid_t
2281 get_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  */
2305 static arg_entry_t *
2306 get_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  */
2325 static int
2326 arg_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  */
2335 static void
2336 str2tid(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 
2413 static char *
2414 cond2str(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  */
2445 static int
2446 str2policy(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 
2538 static int
2539 policy2str(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 
2573 static int
2574 strisnum(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 
2592 static int
2593 strisipaddr(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 
2620 static void
2621 chk_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 
2629 static void
2630 chk_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 
2652 static void
2653 chk_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 
2675 static void
2676 chk_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 
2688 static void
2689 chk_sorf(char *sorf_str)
2690 {
2691         if (!strisnum(sorf_str))
2692                 exit_error(gettext("Invalid sorf specified: %s"), sorf_str);
2693 }
2694 
2695 static void
2696 chk_retval(char *retval_str)
2697 {
2698         if (!strisnum(retval_str))
2699                 exit_error(gettext("Invalid retval specified: %s"), retval_str);
2700 }
2701 
2702 static void
2703 execit(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 
2735 static void
2736 exit_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 
2758 static void
2759 print_asid(au_asid_t asid)
2760 {
2761         (void) printf(gettext("audit session id = %u\n"), asid);
2762 }
2763 
2764 static void
2765 print_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 
2778 static void
2779 print_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 
2790 static void
2791 print_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 
2832 static void
2833 print_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 
2882 static int
2883 str2ipaddr(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 
2926 static int
2927 str2type(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*/
2947 static void
2948 exit_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 }