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 } 2958