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