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) 2019 Peter Tribble. 23 */ 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 30 #define _REENTRANT 31 32 #include <ctype.h> 33 #include <errno.h> 34 #include <grp.h> 35 #include <libintl.h> 36 #include <netdb.h> 37 #include <time.h> 38 #include <pwd.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <wchar.h> 43 44 #include <arpa/inet.h> 45 46 #include <bsm/audit.h> 47 #include <bsm/audit_record.h> 48 #include <bsm/libbsm.h> 49 #include <security/pam_appl.h> 50 51 #include <sys/inttypes.h> 52 #include <sys/mkdev.h> 53 #include <sys/types.h> 54 #include <aclutils.h> 55 56 #include "praudit.h" 57 #include "toktable.h" 58 #include "adt_xlate.h" 59 60 static void convertascii(char *p, char *c, int size); 61 static int convertbinary(char *p, char *c, int size); 62 static void eventmodifier2string(au_emod_t emodifier, char *modstring, 63 size_t modlen); 64 static int do_mtime32(pr_context_t *context, int status, int flag, 65 uint32_t scale); 66 static int do_mtime64(pr_context_t *context, int status, int flag, 67 uint64_t scale); 68 69 /* 70 * for uid/gid caches 71 */ 72 static uid_t lastuid = (uid_t)-1; 73 static gid_t lastgid = (gid_t)-1; 74 static char *lastuname = NULL; 75 static char *lastgname = NULL; 76 static char *getname(uid_t); 77 static char *getgroup(gid_t); 78 static struct cachenode *findincache(struct cachenode **, long); 79 #include <utmpx.h> 80 81 struct utmpx utmp; 82 83 #define NMAX (sizeof (utmp.ut_name)) 84 #define SCPYN(a, b) (void) strncpy(a, b, NMAX) 85 86 struct cachenode { /* this struct must be zeroed before using */ 87 struct cachenode *lesschild; /* subtree whose entries < val */ 88 struct cachenode *grtrchild; /* subtree whose entries > val */ 89 long val; /* the uid or gid of this entry */ 90 int initted; /* name has been filled in */ 91 char name[NMAX+1]; /* the string that val maps to */ 92 }; 93 static struct cachenode *names, *groups; 94 95 static struct cachenode * 96 findincache(struct cachenode **head, long val) 97 { 98 struct cachenode **parent = head; 99 struct cachenode *c = *parent; 100 101 while (c != NULL) { 102 if (val == c->val) { 103 /* found it */ 104 return (c); 105 } else if (val < c->val) { 106 parent = &c->lesschild; 107 c = c->lesschild; 108 } else { 109 parent = &c->grtrchild; 110 c = c->grtrchild; 111 } 112 } 113 114 /* not in the cache, make a new entry for it */ 115 c = calloc(1, sizeof (struct cachenode)); 116 if (c == NULL) { 117 perror("praudit"); 118 exit(2); 119 } 120 *parent = c; 121 c->val = val; 122 return (c); 123 } 124 125 /* 126 * get name from cache, or passwd file for a given uid; 127 * lastuid is set to uid. 128 */ 129 static char * 130 getname(uid_t uid) 131 { 132 struct passwd *pwent; 133 struct cachenode *c; 134 135 if ((uid == lastuid) && lastuname) 136 return (lastuname); 137 138 c = findincache(&names, uid); 139 if (c->initted == 0) { 140 if ((pwent = getpwuid(uid)) != NULL) { 141 SCPYN(&c->name[0], pwent->pw_name); 142 } else { 143 (void) sprintf(&c->name[0], "%u", (int)uid); 144 } 145 c->initted = 1; 146 } 147 lastuid = uid; 148 lastuname = &c->name[0]; 149 return (lastuname); 150 } 151 152 /* 153 * get name from cache, or group file for a given gid; 154 * lastgid is set to gid. 155 */ 156 static char * 157 getgroup(gid_t gid) 158 { 159 struct group *grent; 160 struct cachenode *c; 161 162 if ((gid == lastgid) && lastgname) 163 return (lastgname); 164 165 c = findincache(&groups, gid); 166 if (c->initted == 0) { 167 if ((grent = getgrgid(gid)) != NULL) { 168 SCPYN(&c->name[0], grent->gr_name); 169 } else { 170 (void) sprintf(&c->name[0], "%u", (int)gid); 171 } 172 c->initted = 1; 173 } 174 lastgid = gid; 175 lastgname = &c->name[0]; 176 return (lastgname); 177 } 178 179 /* 180 * populate name cache from given file 181 * caller is responsible for opening and closing the file 182 */ 183 void 184 loadnames(FILE *pf) 185 { 186 struct passwd *pwent; 187 struct cachenode *c; 188 189 while ((pwent = fgetpwent(pf)) != NULL) { 190 c = findincache(&names, pwent->pw_uid); 191 if (c->initted == 0) { 192 SCPYN(&c->name[0], pwent->pw_name); 193 c->initted = 1; 194 } 195 } 196 } 197 198 /* 199 * populate group cache from given file 200 * caller is responsible for opening and closing the file 201 */ 202 void 203 loadgroups(FILE *gf) 204 { 205 struct group *grent; 206 struct cachenode *c; 207 208 while ((grent = fgetgrent(gf)) != NULL) { 209 c = findincache(&groups, grent->gr_gid); 210 if (c->initted == 0) { 211 SCPYN(&c->name[0], grent->gr_name); 212 c->initted = 1; 213 } 214 } 215 } 216 217 /* 218 * ------------------------------------------------------ 219 * field widths for arbitrary data token type 220 * ------------------------------------------------------ 221 */ 222 static struct fw { 223 char basic_unit; 224 struct { 225 char print_base; 226 int field_width; 227 } pwidth[5]; 228 } fwidth[] = { 229 /* character data type, 8 bits */ 230 AUR_CHAR, AUP_BINARY, 12, 231 AUP_OCTAL, 6, 232 AUP_DECIMAL, 6, 233 AUP_HEX, 6, 234 AUP_STRING, 1, 235 AUR_BYTE, AUP_BINARY, 12, 236 AUP_OCTAL, 6, 237 AUP_DECIMAL, 6, 238 AUP_HEX, 6, 239 AUP_STRING, 1, 240 AUR_SHORT, AUP_BINARY, 20, 241 AUP_OCTAL, 10, 242 AUP_DECIMAL, 10, 243 AUP_HEX, 8, 244 AUP_STRING, 6, 245 AUR_INT32, AUP_BINARY, 36, 246 AUP_OCTAL, 18, 247 AUP_DECIMAL, 18, 248 AUP_HEX, 12, 249 AUP_STRING, 10, 250 AUR_INT64, AUP_BINARY, 68, 251 AUP_OCTAL, 34, 252 AUP_DECIMAL, 34, 253 AUP_HEX, 20, 254 AUP_STRING, 20}; 255 256 257 static int numwidthentries = sizeof (fwidth) 258 / sizeof (struct fw); 259 260 261 /* 262 * ----------------------------------------------------------------------- 263 * do_newline: 264 * Print a newline, if needed according to various formatting 265 * rules. 266 * return codes : 0 - success 267 * : -1 - error 268 * ----------------------------------------------------------------------- 269 */ 270 int 271 do_newline(pr_context_t *context, int flag) 272 { 273 int retstat = 0; 274 275 if (!(context->format & PRF_ONELINE) && (flag == 1)) 276 retstat = pr_putchar(context, '\n'); 277 else if (!(context->format & PRF_XMLM)) 278 retstat = pr_printf(context, "%s", context->SEPARATOR); 279 280 return (retstat); 281 } 282 283 int 284 open_tag(pr_context_t *context, int tagnum) 285 { 286 int err = 0; 287 token_desc_t *tag; 288 289 /* no-op if not doing XML format */ 290 if (!(context->format & PRF_XMLM)) 291 return (0); 292 293 tag = &tokentable[tagnum]; 294 295 /* 296 * First if needed do an implicit finish of a pending open for an 297 * extended tag. I.e., for the extended tag xxx: 298 * <xxx a=".." b=".."> ... </xxx> 299 * -- insert a close bracket after the last attribute 300 * (in other words, when the 1st non-attribute is opened while 301 * this is pending). Note that only one tag could be pending at 302 * a given time -- it couldn't be nested. 303 */ 304 if (context->pending_flag && (tag->t_type != T_ATTRIBUTE)) { 305 /* complete pending extended open */ 306 err = pr_putchar(context, '>'); 307 if (err != 0) 308 return (err); 309 context->pending_flag = 0; 310 } 311 312 if (is_header_token(tagnum) || is_file_token(tagnum)) { 313 /* File token or new record on new line */ 314 err = pr_putchar(context, '\n'); 315 } else if (is_token(tagnum)) { 316 /* Each token on new line if possible */ 317 err = do_newline(context, 1); 318 } 319 if (err != 0) 320 return (err); 321 322 switch (tag->t_type) { 323 case T_ATTRIBUTE: 324 err = pr_printf(context, " %s=\"", tag->t_tagname); 325 break; 326 case T_ELEMENT: 327 err = pr_printf(context, "<%s>", tag->t_tagname); 328 break; 329 case T_ENCLOSED: 330 err = pr_printf(context, "<%s", tag->t_tagname); 331 break; 332 case T_EXTENDED: 333 err = pr_printf(context, "<%s", tag->t_tagname); 334 if (err == 0) 335 context->pending_flag = tagnum; 336 break; 337 default: 338 break; 339 } 340 341 if (is_header_token(tagnum) && (err == 0)) 342 context->current_rec = tagnum; /* set start of new record */ 343 344 return (err); 345 } 346 347 /* 348 * Do an implicit close of a record when needed. 349 */ 350 int 351 check_close_rec(pr_context_t *context, int tagnum) 352 { 353 int err = 0; 354 355 /* no-op if not doing XML format */ 356 if (!(context->format & PRF_XMLM)) 357 return (0); 358 359 /* 360 * If we're opening a header or the file token (i.e., starting a new 361 * record), if there's a current record in progress do an implicit 362 * close of it. 363 */ 364 if ((is_header_token(tagnum) || is_file_token(tagnum)) && 365 context->current_rec) { 366 err = do_newline(context, 1); 367 if (err == 0) 368 err = close_tag(context, context->current_rec); 369 } 370 371 return (err); 372 } 373 374 /* 375 * explicit finish of a pending open for an extended tag. 376 */ 377 int 378 finish_open_tag(pr_context_t *context) 379 { 380 int err = 0; 381 382 /* no-op if not doing XML format */ 383 if (!(context->format & PRF_XMLM)) 384 return (0); 385 386 if (context->pending_flag) { 387 /* complete pending extended open */ 388 err = pr_putchar(context, '>'); 389 if (err == 0) 390 context->pending_flag = 0; 391 } 392 return (err); 393 } 394 395 int 396 close_tag(pr_context_t *context, int tagnum) 397 { 398 int err = 0; 399 token_desc_t *tag; 400 401 /* no-op if not doing XML format */ 402 if (!(context->format & PRF_XMLM)) 403 return (0); 404 405 tag = &tokentable[tagnum]; 406 407 switch (tag->t_type) { 408 case T_ATTRIBUTE: 409 err = pr_putchar(context, '\"'); 410 break; 411 case T_ELEMENT: 412 err = pr_printf(context, "</%s>", tag->t_tagname); 413 break; 414 case T_ENCLOSED: 415 err = pr_printf(context, "/>"); 416 break; 417 case T_EXTENDED: 418 err = pr_printf(context, "</%s>", tag->t_tagname); 419 break; 420 default: 421 break; 422 } 423 424 if (is_header_token(tagnum) && (err == 0)) 425 context->current_rec = 0; /* closing rec; none current */ 426 427 return (err); 428 } 429 430 /* 431 * ----------------------------------------------------------------------- 432 * process_tag: 433 * Calls the routine corresponding to the tag 434 * Note that to use this mechanism, all such routines must 435 * take 2 ints for their parameters; the first of these is 436 * the current status. 437 * 438 * flag = 1 for newline / delimiter, else 0 439 * return codes : -1 - error 440 * : 0 - successful 441 * ----------------------------------------------------------------------- 442 */ 443 int 444 process_tag(pr_context_t *context, int tagnum, int status, int flag) 445 { 446 int retstat; 447 448 retstat = status; 449 450 if (retstat) 451 return (retstat); 452 453 if ((tagnum > 0) && (tagnum <= MAXTAG) && 454 (tokentable[tagnum].func != NOFUNC)) { 455 retstat = open_tag(context, tagnum); 456 if (!retstat) 457 retstat = (*tokentable[tagnum].func)(context, status, 458 flag); 459 if (!retstat) 460 retstat = close_tag(context, tagnum); 461 return (retstat); 462 } 463 /* here if token id is not in table */ 464 (void) fprintf(stderr, gettext("praudit: No code associated with " 465 "tag id %d\n"), tagnum); 466 return (0); 467 } 468 469 void 470 get_Hname(uint32_t addr, char *buf, size_t buflen) 471 { 472 extern char *inet_ntoa(const struct in_addr); 473 struct hostent *phe; 474 struct in_addr ia; 475 476 phe = gethostbyaddr((const char *)&addr, 4, AF_INET); 477 if (phe == (struct hostent *)0) { 478 ia.s_addr = addr; 479 (void) snprintf(buf, buflen, "%s", inet_ntoa(ia)); 480 return; 481 } 482 ia.s_addr = addr; 483 (void) snprintf(buf, buflen, "%s", phe->h_name); 484 } 485 486 void 487 get_Hname_ex(uint32_t *addr, char *buf, size_t buflen) 488 { 489 struct hostent *phe; 490 int err; 491 492 phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err); 493 494 if (phe == (struct hostent *)0) { 495 (void) inet_ntop(AF_INET6, (void *)addr, buf, buflen); 496 } else 497 (void) snprintf(buf, buflen, "%s", phe->h_name); 498 499 if (phe) 500 freehostent(phe); 501 } 502 503 int 504 pa_hostname(pr_context_t *context, int status, int flag) 505 { 506 int returnstat; 507 uint32_t ip_addr; 508 struct in_addr ia; 509 uval_t uval; 510 char buf[256]; 511 512 if (status < 0) 513 return (status); 514 515 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0) 516 return (returnstat); 517 518 uval.uvaltype = PRA_STRING; 519 520 if (!(context->format & PRF_RAWM)) { 521 uval.string_val = buf; 522 get_Hname(ip_addr, buf, sizeof (buf)); 523 returnstat = pa_print(context, &uval, flag); 524 } else { 525 ia.s_addr = ip_addr; 526 if ((uval.string_val = inet_ntoa(ia)) == NULL) 527 return (-1); 528 returnstat = pa_print(context, &uval, flag); 529 } 530 return (returnstat); 531 } 532 533 int 534 pa_hostname_ex(pr_context_t *context, int status, int flag) 535 { 536 int returnstat; 537 uint32_t ip_type; 538 uint32_t ip_addr[4]; 539 struct in_addr ia; 540 char buf[256]; 541 uval_t uval; 542 543 if (status < 0) 544 return (status); 545 546 /* get ip type */ 547 if ((returnstat = pr_adr_int32(context, (int32_t *)&ip_type, 1)) != 0) 548 return (returnstat); 549 550 /* only IPv4 and IPv6 addresses are legal */ 551 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6)) 552 return (-1); 553 554 /* get ip address */ 555 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0) 556 return (returnstat); 557 558 if ((returnstat = open_tag(context, TAG_HOSTID)) != 0) 559 return (returnstat); 560 561 uval.uvaltype = PRA_STRING; 562 if (ip_type == AU_IPv4) { /* ipv4 address */ 563 if (!(context->format & PRF_RAWM)) { 564 uval.string_val = buf; 565 get_Hname(ip_addr[0], buf, sizeof (buf)); 566 returnstat = pa_print(context, &uval, flag); 567 } else { 568 ia.s_addr = ip_addr[0]; 569 if ((uval.string_val = inet_ntoa(ia)) == NULL) 570 return (-1); 571 returnstat = pa_print(context, &uval, flag); 572 } 573 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */ 574 if (!(context->format & PRF_RAWM)) { 575 uval.string_val = buf; 576 get_Hname_ex(ip_addr, buf, sizeof (buf)); 577 returnstat = pa_print(context, &uval, flag); 578 } else { 579 uval.string_val = (char *)buf; 580 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf, 581 sizeof (buf)); 582 returnstat = pa_print(context, &uval, flag); 583 } 584 } 585 586 if (returnstat != 0) 587 return (returnstat); 588 return (close_tag(context, TAG_HOSTID)); 589 } 590 591 int 592 pa_hostname_so(pr_context_t *context, int status, int flag) 593 { 594 int returnstat; 595 short ip_type; 596 ushort_t ip_port; 597 uint32_t ip_addr[4]; 598 struct in_addr ia; 599 char buf[256]; 600 uval_t uval; 601 602 if (status < 0) 603 return (status); 604 605 /* get ip type */ 606 if ((returnstat = pr_adr_short(context, &ip_type, 1)) != 0) 607 return (returnstat); 608 609 /* only IPv4 and IPv6 addresses are legal */ 610 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6)) 611 return (-1); 612 613 /* get local ip port */ 614 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0) 615 return (returnstat); 616 617 if ((returnstat = open_tag(context, TAG_SOCKEXLPORT)) != 0) 618 return (returnstat); 619 620 uval.uvaltype = PRA_STRING; 621 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port), 622 sizeof (ip_port)); 623 if (uval.string_val) { 624 returnstat = pa_print(context, &uval, 0); 625 free(uval.string_val); 626 } else 627 returnstat = -1; 628 if (returnstat) 629 return (returnstat); 630 631 if ((returnstat = close_tag(context, TAG_SOCKEXLPORT)) != 0) 632 return (returnstat); 633 634 /* get local ip address */ 635 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0) 636 return (returnstat); 637 638 if ((returnstat = open_tag(context, TAG_SOCKEXLADDR)) != 0) 639 return (returnstat); 640 641 if (ip_type == AU_IPv4) { /* ipv4 address */ 642 643 if (!(context->format & PRF_RAWM)) { 644 uval.string_val = buf; 645 get_Hname(ip_addr[0], buf, sizeof (buf)); 646 returnstat = pa_print(context, &uval, 0); 647 } else { 648 ia.s_addr = ip_addr[0]; 649 if ((uval.string_val = inet_ntoa(ia)) == NULL) 650 return (-1); 651 returnstat = pa_print(context, &uval, 0); 652 } 653 654 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */ 655 656 if (!(context->format & PRF_RAWM)) { 657 uval.string_val = buf; 658 get_Hname_ex(ip_addr, buf, sizeof (buf)); 659 returnstat = pa_print(context, &uval, 0); 660 } else { 661 uval.string_val = (char *)buf; 662 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf, 663 sizeof (buf)); 664 returnstat = pa_print(context, &uval, 0); 665 } 666 } else 667 returnstat = -1; 668 669 if (returnstat) 670 return (returnstat); 671 672 if ((returnstat = close_tag(context, TAG_SOCKEXLADDR)) != 0) 673 return (returnstat); 674 675 /* get foreign ip port */ 676 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0) 677 return (returnstat); 678 679 if ((returnstat = open_tag(context, TAG_SOCKEXFPORT)) != 0) 680 return (returnstat); 681 682 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port), 683 sizeof (ip_port)); 684 if (uval.string_val) { 685 returnstat = pa_print(context, &uval, 0); 686 free(uval.string_val); 687 } else 688 returnstat = -1; 689 690 if (returnstat) 691 return (returnstat); 692 693 if ((returnstat = close_tag(context, TAG_SOCKEXFPORT)) != 0) 694 return (returnstat); 695 696 /* get foreign ip address */ 697 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0) 698 return (returnstat); 699 700 if ((returnstat = open_tag(context, TAG_SOCKEXFADDR)) != 0) 701 return (returnstat); 702 703 if (ip_type == AU_IPv4) { /* ipv4 address */ 704 705 if (!(context->format & PRF_RAWM)) { 706 uval.string_val = buf; 707 get_Hname(ip_addr[0], buf, sizeof (buf)); 708 returnstat = pa_print(context, &uval, flag); 709 } else { 710 ia.s_addr = ip_addr[0]; 711 if ((uval.string_val = inet_ntoa(ia)) == NULL) 712 return (-1); 713 returnstat = pa_print(context, &uval, flag); 714 } 715 716 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */ 717 718 if (!(context->format & PRF_RAWM)) { 719 uval.string_val = buf; 720 get_Hname_ex(ip_addr, buf, sizeof (buf)); 721 returnstat = pa_print(context, &uval, flag); 722 } else { 723 uval.string_val = (char *)buf; 724 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf, 725 sizeof (buf)); 726 returnstat = pa_print(context, &uval, flag); 727 } 728 } else 729 returnstat = -1; 730 731 if (returnstat) 732 return (returnstat); 733 734 if ((returnstat = close_tag(context, TAG_SOCKEXFADDR)) != 0) 735 return (returnstat); 736 737 return (returnstat); 738 } 739 740 741 #define NBITSMAJOR64 32 /* # of major device bits in 64-bit Solaris */ 742 #define NBITSMINOR64 32 /* # of minor device bits in 64-bit Solaris */ 743 #define MAXMAJ64 0xfffffffful /* max major value */ 744 #define MAXMIN64 0xfffffffful /* max minor value */ 745 746 #define NBITSMAJOR32 14 /* # of SVR4 major device bits */ 747 #define NBITSMINOR32 18 /* # of SVR4 minor device bits */ 748 #define NMAXMAJ32 0x3fff /* SVR4 max major value */ 749 #define NMAXMIN32 0x3ffff /* MAX minor for 3b2 software drivers. */ 750 751 752 static int32_t 753 minor_64(uint64_t dev) 754 { 755 if (dev == NODEV) { 756 errno = EINVAL; 757 return (NODEV); 758 } 759 return (int32_t)(dev & MAXMIN64); 760 } 761 762 static int32_t 763 major_64(uint64_t dev) 764 { 765 uint32_t maj; 766 767 maj = (uint32_t)(dev >> NBITSMINOR64); 768 769 if (dev == NODEV || maj > MAXMAJ64) { 770 errno = EINVAL; 771 return (NODEV); 772 } 773 return (int32_t)(maj); 774 } 775 776 static int32_t 777 minor_32(uint32_t dev) 778 { 779 if (dev == NODEV) { 780 errno = EINVAL; 781 return (NODEV); 782 } 783 return (int32_t)(dev & MAXMIN32); 784 } 785 786 static int32_t 787 major_32(uint32_t dev) 788 { 789 uint32_t maj; 790 791 maj = (uint32_t)(dev >> NBITSMINOR32); 792 793 if (dev == NODEV || maj > MAXMAJ32) { 794 errno = EINVAL; 795 return (NODEV); 796 } 797 return (int32_t)(maj); 798 } 799 800 801 /* 802 * ----------------------------------------------------------------------- 803 * pa_tid() : Process terminal id and display contents 804 * return codes : -1 - error 805 * : 0 - successful 806 * 807 * terminal id port adr_int32 808 * terminal id machine adr_int32 809 * ----------------------------------------------------------------------- 810 */ 811 int 812 pa_tid32(pr_context_t *context, int status, int flag) 813 { 814 int returnstat; 815 int32_t dev_maj_min; 816 uint32_t ip_addr; 817 struct in_addr ia; 818 char *ipstring; 819 char buf[256]; 820 uval_t uval; 821 822 if (status < 0) 823 return (status); 824 825 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0) 826 return (returnstat); 827 828 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0) 829 return (returnstat); 830 831 uval.uvaltype = PRA_STRING; 832 uval.string_val = buf; 833 834 if (!(context->format & PRF_RAWM)) { 835 char hostname[256]; 836 837 get_Hname(ip_addr, hostname, sizeof (hostname)); 838 (void) snprintf(buf, sizeof (buf), "%d %d %s", 839 major_32(dev_maj_min), 840 minor_32(dev_maj_min), 841 hostname); 842 return (pa_print(context, &uval, flag)); 843 } 844 845 ia.s_addr = ip_addr; 846 if ((ipstring = inet_ntoa(ia)) == NULL) 847 return (-1); 848 849 (void) snprintf(buf, sizeof (buf), "%d %d %s", major_32(dev_maj_min), 850 minor_32(dev_maj_min), 851 ipstring); 852 853 return (pa_print(context, &uval, flag)); 854 } 855 856 int 857 pa_tid32_ex(pr_context_t *context, int status, int flag) 858 { 859 int returnstat; 860 int32_t dev_maj_min; 861 uint32_t ip_addr[16]; 862 uint32_t ip_type; 863 struct in_addr ia; 864 char *ipstring; 865 char hostname[256]; 866 char buf[256]; 867 char tbuf[256]; 868 uval_t uval; 869 870 if (status < 0) 871 return (status); 872 873 /* get port info */ 874 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0) 875 return (returnstat); 876 877 /* get address type */ 878 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0) 879 return (returnstat); 880 881 /* legal address types are either AU_IPv4 or AU_IPv6 only */ 882 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6)) 883 return (-1); 884 885 /* get address (4/16) */ 886 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0) 887 return (returnstat); 888 889 uval.uvaltype = PRA_STRING; 890 if (ip_type == AU_IPv4) { 891 uval.string_val = buf; 892 893 if (!(context->format & PRF_RAWM)) { 894 get_Hname(ip_addr[0], hostname, sizeof (hostname)); 895 (void) snprintf(buf, sizeof (buf), "%d %d %s", 896 major_32(dev_maj_min), minor_32(dev_maj_min), 897 hostname); 898 return (pa_print(context, &uval, flag)); 899 } 900 901 ia.s_addr = ip_addr[0]; 902 if ((ipstring = inet_ntoa(ia)) == NULL) 903 return (-1); 904 905 (void) snprintf(buf, sizeof (buf), "%d %d %s", 906 major_32(dev_maj_min), minor_32(dev_maj_min), ipstring); 907 908 return (pa_print(context, &uval, flag)); 909 } else { 910 uval.string_val = buf; 911 912 if (!(context->format & PRF_RAWM)) { 913 get_Hname_ex(ip_addr, hostname, sizeof (hostname)); 914 (void) snprintf(buf, sizeof (buf), "%d %d %s", 915 major_32(dev_maj_min), minor_32(dev_maj_min), 916 hostname); 917 return (pa_print(context, &uval, flag)); 918 } 919 920 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf, 921 sizeof (tbuf)); 922 923 (void) snprintf(buf, sizeof (buf), "%d %d %s", 924 major_32(dev_maj_min), minor_32(dev_maj_min), tbuf); 925 926 return (pa_print(context, &uval, flag)); 927 } 928 } 929 930 int 931 pa_ip_addr(pr_context_t *context, int status, int flag) 932 { 933 int returnstat; 934 uval_t uval; 935 uint32_t ip_addr[4]; 936 uint32_t ip_type; 937 struct in_addr ia; 938 char *ipstring; 939 char hostname[256]; 940 char buf[256]; 941 char tbuf[256]; 942 943 if (status < 0) 944 return (status); 945 946 /* get address type */ 947 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0) 948 return (returnstat); 949 950 /* legal address type is AU_IPv4 or AU_IPv6 */ 951 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6)) 952 return (-1); 953 954 /* get address (4/16) */ 955 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0) 956 return (returnstat); 957 958 uval.uvaltype = PRA_STRING; 959 if (ip_type == AU_IPv4) { 960 uval.string_val = buf; 961 962 if (!(context->format & PRF_RAWM)) { 963 get_Hname(ip_addr[0], hostname, sizeof (hostname)); 964 (void) snprintf(buf, sizeof (buf), "%s", hostname); 965 return (pa_print(context, &uval, flag)); 966 } 967 968 ia.s_addr = ip_addr[0]; 969 if ((ipstring = inet_ntoa(ia)) == NULL) 970 return (-1); 971 972 (void) snprintf(buf, sizeof (buf), "%s", ipstring); 973 974 return (pa_print(context, &uval, flag)); 975 } else { 976 uval.string_val = buf; 977 978 if (!(context->format & PRF_RAWM)) { 979 get_Hname_ex(ip_addr, hostname, sizeof (hostname)); 980 (void) snprintf(buf, sizeof (buf), "%s", 981 hostname); 982 return (pa_print(context, &uval, flag)); 983 } 984 985 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf, 986 sizeof (tbuf)); 987 988 (void) snprintf(buf, sizeof (buf), "%s", tbuf); 989 990 return (pa_print(context, &uval, flag)); 991 } 992 993 } 994 995 int 996 pa_tid64(pr_context_t *context, int status, int flag) 997 { 998 int returnstat; 999 int64_t dev_maj_min; 1000 uint32_t ip_addr; 1001 struct in_addr ia; 1002 char *ipstring; 1003 char buf[256]; 1004 uval_t uval; 1005 1006 if (status < 0) 1007 return (status); 1008 1009 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0) 1010 return (returnstat); 1011 1012 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0) 1013 return (returnstat); 1014 1015 uval.uvaltype = PRA_STRING; 1016 uval.string_val = buf; 1017 1018 if (!(context->format & PRF_RAWM)) { 1019 char hostname[256]; 1020 1021 get_Hname(ip_addr, hostname, sizeof (hostname)); 1022 (void) snprintf(buf, sizeof (buf), "%d %d %s", 1023 major_64(dev_maj_min), minor_64(dev_maj_min), hostname); 1024 return (pa_print(context, &uval, flag)); 1025 } 1026 1027 ia.s_addr = ip_addr; 1028 if ((ipstring = inet_ntoa(ia)) == NULL) 1029 return (-1); 1030 1031 (void) snprintf(buf, sizeof (buf), "%d %d %s", 1032 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring); 1033 1034 return (pa_print(context, &uval, flag)); 1035 } 1036 1037 int 1038 pa_tid64_ex(pr_context_t *context, int status, int flag) 1039 { 1040 int returnstat; 1041 int64_t dev_maj_min; 1042 uint32_t ip_addr[4]; 1043 uint32_t ip_type; 1044 struct in_addr ia; 1045 char *ipstring; 1046 char hostname[256]; 1047 char buf[256]; 1048 char tbuf[256]; 1049 uval_t uval; 1050 1051 if (status < 0) 1052 return (status); 1053 1054 /* get port info */ 1055 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0) 1056 return (returnstat); 1057 1058 /* get address type */ 1059 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0) 1060 return (returnstat); 1061 1062 /* legal address types are either AU_IPv4 or AU_IPv6 only */ 1063 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6)) 1064 return (-1); 1065 1066 /* get address (4/16) */ 1067 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, ip_type)) != 0) 1068 return (returnstat); 1069 1070 uval.uvaltype = PRA_STRING; 1071 if (ip_type == AU_IPv4) { 1072 uval.string_val = buf; 1073 1074 if (!(context->format & PRF_RAWM)) { 1075 get_Hname(ip_addr[0], hostname, sizeof (hostname)); 1076 uval.string_val = buf; 1077 (void) snprintf(buf, sizeof (buf), "%d %d %s", 1078 major_64(dev_maj_min), minor_64(dev_maj_min), 1079 hostname); 1080 return (pa_print(context, &uval, flag)); 1081 } 1082 1083 ia.s_addr = ip_addr[0]; 1084 if ((ipstring = inet_ntoa(ia)) == NULL) 1085 return (-1); 1086 1087 (void) snprintf(buf, sizeof (buf), "%d %d %s", 1088 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring); 1089 1090 return (pa_print(context, &uval, flag)); 1091 } else { 1092 uval.string_val = buf; 1093 1094 if (!(context->format & PRF_RAWM)) { 1095 get_Hname_ex(ip_addr, hostname, sizeof (hostname)); 1096 (void) snprintf(buf, sizeof (buf), "%d %d %s", 1097 major_64(dev_maj_min), minor_64(dev_maj_min), 1098 hostname); 1099 return (pa_print(context, &uval, flag)); 1100 } 1101 1102 (void) inet_ntop(AF_INET6, (void *)ip_addr, tbuf, 1103 sizeof (tbuf)); 1104 1105 (void) snprintf(buf, sizeof (buf), "%d %d %s", 1106 major_64(dev_maj_min), minor_64(dev_maj_min), tbuf); 1107 1108 return (pa_print(context, &uval, flag)); 1109 } 1110 } 1111 1112 1113 /* 1114 * ---------------------------------------------------------------- 1115 * findfieldwidth: 1116 * Returns the field width based on the basic unit and print mode. 1117 * This routine is called to determine the field width for the 1118 * data items in the arbitrary data token where the tokens are 1119 * to be printed in more than one line. The field width can be 1120 * found in the fwidth structure. 1121 * 1122 * Input parameters: 1123 * basicunit Can be one of AUR_CHAR, AUR_BYTE, AUR_SHORT, 1124 * AUR_INT32, or AUR_INT64 1125 * howtoprint Print mode. Can be one of AUP_BINARY, AUP_OCTAL, 1126 * AUP_DECIMAL, or AUP_HEX. 1127 * ---------------------------------------------------------------- 1128 */ 1129 int 1130 findfieldwidth(char basicunit, char howtoprint) 1131 { 1132 int i, j; 1133 1134 for (i = 0; i < numwidthentries; i++) { 1135 if (fwidth[i].basic_unit == basicunit) { 1136 for (j = 0; j <= 4; j++) { 1137 if (fwidth[i].pwidth[j].print_base == 1138 howtoprint) { 1139 return ( 1140 fwidth[i].pwidth[j].field_width); 1141 } 1142 } 1143 /* 1144 * if we got here, then we didn't get what we were after 1145 */ 1146 return (0); 1147 } 1148 } 1149 /* if we got here, we didn't get what we wanted either */ 1150 return (0); 1151 } 1152 1153 1154 /* 1155 * ----------------------------------------------------------------------- 1156 * pa_cmd: Retrieves the cmd item from the input stream. 1157 * return codes : -1 - error 1158 * : 0 - successful 1159 * ----------------------------------------------------------------------- 1160 */ 1161 int 1162 pa_cmd(pr_context_t *context, int status, int flag) 1163 { 1164 char *cmd; /* cmd */ 1165 short length; 1166 int returnstat; 1167 uval_t uval; 1168 1169 /* 1170 * We need to know how much space to allocate for our string, so 1171 * read the length first, then call pr_adr_char to read those bytes. 1172 */ 1173 if (status >= 0) { 1174 if (pr_adr_short(context, &length, 1) == 0) { 1175 if ((cmd = (char *)malloc(length + 1)) == NULL) 1176 return (-1); 1177 if (pr_adr_char(context, cmd, length) == 0) { 1178 uval.uvaltype = PRA_STRING; 1179 uval.string_val = cmd; 1180 returnstat = pa_print(context, &uval, flag); 1181 } else { 1182 returnstat = -1; 1183 } 1184 free(cmd); 1185 return (returnstat); 1186 } else 1187 return (-1); 1188 } else 1189 return (status); 1190 } 1191 1192 1193 1194 /* 1195 * ----------------------------------------------------------------------- 1196 * pa_adr_byte : Issues pr_adr_char to retrieve the next ADR item from 1197 * the input stream pointed to by audit_adr, and prints it 1198 * as an integer if status >= 0 1199 * return codes : -1 - error 1200 * : 0 - successful 1201 * ----------------------------------------------------------------------- 1202 */ 1203 int 1204 pa_adr_byte(pr_context_t *context, int status, int flag) 1205 { 1206 char c; 1207 uval_t uval; 1208 1209 if (status >= 0) { 1210 if (pr_adr_char(context, &c, 1) == 0) { 1211 uval.uvaltype = PRA_BYTE; 1212 uval.char_val = c; 1213 return (pa_print(context, &uval, flag)); 1214 } else 1215 return (-1); 1216 } else 1217 return (status); 1218 } 1219 1220 /* 1221 * ----------------------------------------------------------------------- 1222 * pa_adr_charhex: Issues pr_adr_char to retrieve the next ADR item from 1223 * the input stream pointed to by audit_adr, and prints it 1224 * in hexadecimal if status >= 0 1225 * return codes : -1 - error 1226 * : 0 - successful 1227 * ----------------------------------------------------------------------- 1228 */ 1229 int 1230 pa_adr_charhex(pr_context_t *context, int status, int flag) 1231 { 1232 char p[2]; 1233 int returnstat; 1234 uval_t uval; 1235 1236 if (status >= 0) { 1237 p[0] = p[1] = 0; 1238 1239 if ((returnstat = pr_adr_char(context, p, 1)) == 0) { 1240 uval.uvaltype = PRA_STRING; 1241 uval.string_val = hexconvert(p, sizeof (char), 1242 sizeof (char)); 1243 if (uval.string_val) { 1244 returnstat = pa_print(context, &uval, flag); 1245 free(uval.string_val); 1246 } 1247 } 1248 return (returnstat); 1249 } else 1250 return (status); 1251 } 1252 1253 /* 1254 * ----------------------------------------------------------------------- 1255 * pa_adr_int32 : Issues pr_adr_int32 to retrieve the next ADR item from the 1256 * input stream pointed to by audit_adr, and prints it 1257 * if status >= 0 1258 * return codes : -1 - error 1259 * : 0 - successful 1260 * ----------------------------------------------------------------------- 1261 */ 1262 int 1263 pa_adr_int32(pr_context_t *context, int status, int flag) 1264 { 1265 int32_t c; 1266 uval_t uval; 1267 1268 if (status >= 0) { 1269 if (pr_adr_int32(context, &c, 1) == 0) { 1270 uval.uvaltype = PRA_INT32; 1271 uval.int32_val = c; 1272 return (pa_print(context, &uval, flag)); 1273 } else 1274 return (-1); 1275 } else 1276 return (status); 1277 } 1278 1279 1280 1281 1282 /* 1283 * ----------------------------------------------------------------------- 1284 * pa_adr_int64 : Issues pr_adr_int64 to retrieve the next ADR item from the 1285 * input stream pointed to by audit_adr, and prints it 1286 * if status >= 0 1287 * return codes : -1 - error 1288 * : 0 - successful 1289 * ----------------------------------------------------------------------- 1290 */ 1291 int 1292 pa_adr_int64(pr_context_t *context, int status, int flag) 1293 { 1294 int64_t c; 1295 uval_t uval; 1296 1297 if (status >= 0) { 1298 if (pr_adr_int64(context, &c, 1) == 0) { 1299 uval.uvaltype = PRA_INT64; 1300 uval.int64_val = c; 1301 return (pa_print(context, &uval, flag)); 1302 } else 1303 return (-1); 1304 } else 1305 return (status); 1306 } 1307 1308 /* 1309 * ----------------------------------------------------------------------- 1310 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the 1311 * input stream pointed to by audit_adr, and prints it 1312 * in hexadecimal if status >= 0 1313 * return codes : -1 - error 1314 * : 0 - successful 1315 * ----------------------------------------------------------------------- 1316 */ 1317 int 1318 pa_adr_int32hex(pr_context_t *context, int status, int flag) 1319 { 1320 int32_t l; 1321 int returnstat; 1322 uval_t uval; 1323 1324 if (status >= 0) { 1325 if ((returnstat = pr_adr_int32(context, &l, 1)) == 0) { 1326 uval.uvaltype = PRA_HEX32; 1327 uval.int32_val = l; 1328 returnstat = pa_print(context, &uval, flag); 1329 } 1330 return (returnstat); 1331 } else 1332 return (status); 1333 } 1334 1335 /* 1336 * ----------------------------------------------------------------------- 1337 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the 1338 * input stream pointed to by audit_adr, and prints it 1339 * in hexadecimal if status >= 0 1340 * return codes : -1 - error 1341 * : 0 - successful 1342 * ----------------------------------------------------------------------- 1343 */ 1344 int 1345 pa_adr_int64hex(pr_context_t *context, int status, int flag) 1346 { 1347 int64_t l; 1348 int returnstat; 1349 uval_t uval; 1350 1351 if (status >= 0) { 1352 if ((returnstat = pr_adr_int64(context, &l, 1)) == 0) { 1353 uval.uvaltype = PRA_HEX64; 1354 uval.int64_val = l; 1355 returnstat = pa_print(context, &uval, flag); 1356 } 1357 return (returnstat); 1358 } else 1359 return (status); 1360 } 1361 1362 1363 /* 1364 * ------------------------------------------------------------------- 1365 * bu2string: Maps a print basic unit type to a string. 1366 * returns : The string mapping or "unknown basic unit type". 1367 * ------------------------------------------------------------------- 1368 */ 1369 char * 1370 bu2string(char basic_unit) 1371 { 1372 register int i; 1373 1374 struct bu_map_ent { 1375 char basic_unit; 1376 char *string; 1377 }; 1378 1379 /* 1380 * TRANSLATION_NOTE 1381 * These names are data units when displaying the arbitrary data 1382 * token. 1383 */ 1384 1385 static struct bu_map_ent bu_map[] = { 1386 { AUR_BYTE, "byte" }, 1387 { AUR_CHAR, "char" }, 1388 { AUR_SHORT, "short" }, 1389 { AUR_INT32, "int32" }, 1390 { AUR_INT64, "int64" } }; 1391 1392 for (i = 0; i < sizeof (bu_map) / sizeof (struct bu_map_ent); i++) 1393 if (basic_unit == bu_map[i].basic_unit) 1394 return (gettext(bu_map[i].string)); 1395 1396 return (gettext("unknown basic unit type")); 1397 } 1398 1399 1400 /* 1401 * ------------------------------------------------------------------- 1402 * eventmodifier2string: Maps event modifier flags to a readable string. 1403 * returns: The string mapping or "none". 1404 * ------------------------------------------------------------------- 1405 */ 1406 static void 1407 eventmodifier2string(au_emod_t emodifier, char *modstring, size_t modlen) 1408 { 1409 register int i, j; 1410 1411 struct em_map_ent { 1412 int mask; 1413 char *string; 1414 }; 1415 1416 /* 1417 * TRANSLATION_NOTE 1418 * These abbreviations represent the event modifier field of the 1419 * header token. To gain a better understanding of each modifier, 1420 * read 1421 * System Administration Guide: Security Services >> Solaris Auditing 1422 * at http://docs.sun.com. 1423 */ 1424 1425 static struct em_map_ent em_map[] = { 1426 { (int)PAD_READ, "rd" }, /* data read from object */ 1427 { (int)PAD_WRITE, "wr" }, /* data written to object */ 1428 { (int)PAD_SPRIVUSE, "sp" }, /* successfully used priv */ 1429 { (int)PAD_FPRIVUSE, "fp" }, /* failed use of priv */ 1430 { (int)PAD_NONATTR, "na" }, /* non-attributable event */ 1431 { (int)PAD_FAILURE, "fe" } /* fail audit event */ 1432 }; 1433 1434 modstring[0] = '\0'; 1435 1436 for (i = 0, j = 0; i < sizeof (em_map) / sizeof (struct em_map_ent); 1437 i++) { 1438 if ((int)emodifier & em_map[i].mask) { 1439 if (j++) 1440 (void) strlcat(modstring, ":", modlen); 1441 (void) strlcat(modstring, em_map[i].string, modlen); 1442 } 1443 } 1444 } 1445 1446 1447 /* 1448 * --------------------------------------------------------- 1449 * convert_char_to_string: 1450 * Converts a byte to string depending on the print mode 1451 * input : printmode, which may be one of AUP_BINARY, 1452 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX 1453 * c, which is the byte to convert 1454 * output : p, which is a pointer to the location where 1455 * the resulting string is to be stored 1456 * ---------------------------------------------------------- 1457 */ 1458 1459 int 1460 convert_char_to_string(char printmode, char c, char *p) 1461 { 1462 union { 1463 char c1[4]; 1464 int c2; 1465 } dat; 1466 1467 dat.c2 = 0; 1468 dat.c1[3] = c; 1469 1470 if (printmode == AUP_BINARY) 1471 (void) convertbinary(p, &c, sizeof (char)); 1472 else if (printmode == AUP_OCTAL) 1473 (void) sprintf(p, "%o", (int)dat.c2); 1474 else if (printmode == AUP_DECIMAL) 1475 (void) sprintf(p, "%d", c); 1476 else if (printmode == AUP_HEX) 1477 (void) sprintf(p, "0x%x", (int)dat.c2); 1478 else if (printmode == AUP_STRING) 1479 convertascii(p, &c, sizeof (char)); 1480 return (0); 1481 } 1482 1483 /* 1484 * -------------------------------------------------------------- 1485 * convert_short_to_string: 1486 * Converts a short integer to string depending on the print mode 1487 * input : printmode, which may be one of AUP_BINARY, 1488 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX 1489 * c, which is the short integer to convert 1490 * output : p, which is a pointer to the location where 1491 * the resulting string is to be stored 1492 * --------------------------------------------------------------- 1493 */ 1494 int 1495 convert_short_to_string(char printmode, short c, char *p) 1496 { 1497 union { 1498 short c1[2]; 1499 int c2; 1500 } dat; 1501 1502 dat.c2 = 0; 1503 dat.c1[1] = c; 1504 1505 if (printmode == AUP_BINARY) 1506 (void) convertbinary(p, (char *)&c, sizeof (short)); 1507 else if (printmode == AUP_OCTAL) 1508 (void) sprintf(p, "%o", (int)dat.c2); 1509 else if (printmode == AUP_DECIMAL) 1510 (void) sprintf(p, "%hd", c); 1511 else if (printmode == AUP_HEX) 1512 (void) sprintf(p, "0x%x", (int)dat.c2); 1513 else if (printmode == AUP_STRING) 1514 convertascii(p, (char *)&c, sizeof (short)); 1515 return (0); 1516 } 1517 1518 /* 1519 * --------------------------------------------------------- 1520 * convert_int32_to_string: 1521 * Converts a integer to string depending on the print mode 1522 * input : printmode, which may be one of AUP_BINARY, 1523 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX 1524 * c, which is the integer to convert 1525 * output : p, which is a pointer to the location where 1526 * the resulting string is to be stored 1527 * ---------------------------------------------------------- 1528 */ 1529 int 1530 convert_int32_to_string(char printmode, int32_t c, char *p) 1531 { 1532 if (printmode == AUP_BINARY) 1533 (void) convertbinary(p, (char *)&c, sizeof (int32_t)); 1534 else if (printmode == AUP_OCTAL) 1535 (void) sprintf(p, "%o", c); 1536 else if (printmode == AUP_DECIMAL) 1537 (void) sprintf(p, "%d", c); 1538 else if (printmode == AUP_HEX) 1539 (void) sprintf(p, "0x%x", c); 1540 else if (printmode == AUP_STRING) 1541 convertascii(p, (char *)&c, sizeof (int)); 1542 return (0); 1543 } 1544 1545 /* 1546 * --------------------------------------------------------- 1547 * convert_int64_to_string: 1548 * Converts a integer to string depending on the print mode 1549 * input : printmode, which may be one of AUP_BINARY, 1550 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX 1551 * c, which is the integer to convert 1552 * output : p, which is a pointer to the location where 1553 * the resulting string is to be stored 1554 * ---------------------------------------------------------- 1555 */ 1556 int 1557 convert_int64_to_string(char printmode, int64_t c, char *p) 1558 { 1559 if (printmode == AUP_BINARY) 1560 (void) convertbinary(p, (char *)&c, sizeof (int64_t)); 1561 else if (printmode == AUP_OCTAL) 1562 (void) sprintf(p, "%"PRIo64, c); 1563 else if (printmode == AUP_DECIMAL) 1564 (void) sprintf(p, "%"PRId64, c); 1565 else if (printmode == AUP_HEX) 1566 (void) sprintf(p, "0x%"PRIx64, c); 1567 else if (printmode == AUP_STRING) 1568 convertascii(p, (char *)&c, sizeof (int64_t)); 1569 return (0); 1570 } 1571 1572 1573 /* 1574 * ----------------------------------------------------------- 1575 * convertbinary: 1576 * Converts a unit c of 'size' bytes long into a binary string 1577 * and returns it into the position pointed to by p 1578 * ------------------------------------------------------------ 1579 */ 1580 int 1581 convertbinary(char *p, char *c, int size) 1582 { 1583 char *s, *t, *ss; 1584 int i, j; 1585 1586 if ((s = (char *)malloc(8 * size + 1)) == NULL) 1587 return (0); 1588 1589 ss = s; 1590 1591 /* first convert to binary */ 1592 t = s; 1593 for (i = 0; i < size; i++) { 1594 for (j = 0; j < 8; j++) 1595 (void) sprintf(t++, "%d", ((*c >> (7 - j)) & (0x01))); 1596 c++; 1597 } 1598 *t = '\0'; 1599 1600 /* now string leading zero's if any */ 1601 j = strlen(s) - 1; 1602 for (i = 0; i < j; i++) { 1603 if (*s != '0') 1604 break; 1605 else 1606 s++; 1607 } 1608 1609 /* now copy the contents of s to p */ 1610 t = p; 1611 for (i = 0; i < (8 * size + 1); i++) { 1612 if (*s == '\0') { 1613 *t = '\0'; 1614 break; 1615 } 1616 *t++ = *s++; 1617 } 1618 free(ss); 1619 1620 return (1); 1621 } 1622 1623 1624 static char hex[] = "0123456789abcdef"; 1625 /* 1626 * ------------------------------------------------------------------- 1627 * hexconvert : Converts a string of (size) bytes to hexadecimal, and 1628 * returns the hexadecimal string. 1629 * returns : - NULL if memory cannot be allocated for the string, or 1630 * - pointer to the hexadecimal string if successful 1631 * ------------------------------------------------------------------- 1632 */ 1633 char * 1634 hexconvert(char *c, int size, int chunk) 1635 { 1636 register char *s, *t; 1637 register int i, j, k; 1638 int numchunks; 1639 int leftovers; 1640 1641 if (size <= 0) 1642 return (NULL); 1643 1644 if ((s = (char *)malloc((size * 5) + 1)) == NULL) 1645 return (NULL); 1646 1647 if (chunk > size || chunk <= 0) 1648 chunk = size; 1649 1650 numchunks = size / chunk; 1651 leftovers = size % chunk; 1652 1653 t = s; 1654 for (i = j = 0; i < numchunks; i++) { 1655 if (j++) { 1656 *t++ = ' '; 1657 } 1658 *t++ = '0'; 1659 *t++ = 'x'; 1660 for (k = 0; k < chunk; k++) { 1661 *t++ = hex[(uint_t)((uchar_t)*c >> 4)]; 1662 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)]; 1663 c++; 1664 } 1665 } 1666 1667 if (leftovers) { 1668 *t++ = ' '; 1669 *t++ = '0'; 1670 *t++ = 'x'; 1671 for (i = 0; i < leftovers; i++) { 1672 *t++ = hex[(uint_t)((uchar_t)*c >> 4)]; 1673 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)]; 1674 c++; 1675 } 1676 } 1677 1678 *t = '\0'; 1679 return (s); 1680 } 1681 1682 1683 /* 1684 * ------------------------------------------------------------------- 1685 * htp2string: Maps a print suggestion to a string. 1686 * returns : The string mapping or "unknown print suggestion". 1687 * ------------------------------------------------------------------- 1688 */ 1689 char * 1690 htp2string(char print_sugg) 1691 { 1692 register int i; 1693 1694 struct htp_map_ent { 1695 char print_sugg; 1696 char *print_string; 1697 }; 1698 1699 /* 1700 * TRANSLATION_NOTE 1701 * These names are data types when displaying the arbitrary data 1702 * token. 1703 */ 1704 1705 static struct htp_map_ent htp_map[] = { 1706 { AUP_BINARY, "binary" }, 1707 { AUP_OCTAL, "octal" }, 1708 { AUP_DECIMAL, "decimal" }, 1709 { AUP_HEX, "hexadecimal" }, 1710 { AUP_STRING, "string" } }; 1711 1712 for (i = 0; i < sizeof (htp_map) / sizeof (struct htp_map_ent); i++) 1713 if (print_sugg == htp_map[i].print_sugg) 1714 return (gettext(htp_map[i].print_string)); 1715 1716 return (gettext("unknown print suggestion")); 1717 } 1718 1719 /* 1720 * ---------------------------------------------------------------------- 1721 * pa_adr_short: Issues pr_adr_short to retrieve the next ADR item from the 1722 * input stream pointed to by audit_adr, and prints it 1723 * if status >= 0 1724 * return codes: -1 - error 1725 * : 0 - successful 1726 * ---------------------------------------------------------------------- 1727 */ 1728 int 1729 pa_adr_short(pr_context_t *context, int status, int flag) 1730 { 1731 short c; 1732 uval_t uval; 1733 1734 if (status >= 0) { 1735 if (pr_adr_short(context, &c, 1) == 0) { 1736 uval.uvaltype = PRA_SHORT; 1737 uval.short_val = c; 1738 return (pa_print(context, &uval, flag)); 1739 } else 1740 return (-1); 1741 } else 1742 return (status); 1743 } 1744 1745 /* 1746 * ----------------------------------------------------------------------- 1747 * pa_adr_shorthex: Issues pr_adr_short to retrieve the next ADR item from the 1748 * input stream pointed to by audit_adr, and prints it 1749 * in hexadecimal if status >= 0 1750 * return codes : -1 - error 1751 * : 0 - successful 1752 * ----------------------------------------------------------------------- 1753 */ 1754 int 1755 pa_adr_shorthex(pr_context_t *context, int status, int flag) 1756 { 1757 short s; 1758 int returnstat; 1759 uval_t uval; 1760 1761 if (status >= 0) { 1762 if ((returnstat = pr_adr_short(context, &s, 1)) == 0) { 1763 uval.uvaltype = PRA_STRING; 1764 uval.string_val = hexconvert((char *)&s, sizeof (s), 1765 sizeof (s)); 1766 if (uval.string_val) { 1767 returnstat = pa_print(context, &uval, flag); 1768 free(uval.string_val); 1769 } 1770 } 1771 return (returnstat); 1772 } else 1773 return (status); 1774 } 1775 1776 1777 /* 1778 * ----------------------------------------------------------------------- 1779 * pa_adr_string: Retrieves a string from the input stream and prints it 1780 * if status >= 0 1781 * return codes : -1 - error 1782 * : 0 - successful 1783 * ----------------------------------------------------------------------- 1784 */ 1785 int 1786 pa_adr_string(pr_context_t *context, int status, int flag) 1787 { 1788 char *c; 1789 short length; 1790 int returnstat; 1791 uval_t uval; 1792 1793 /* 1794 * We need to know how much space to allocate for our string, so 1795 * read the length first, then call pr_adr_char to read those bytes. 1796 */ 1797 if (status < 0) 1798 return (status); 1799 1800 if ((returnstat = pr_adr_short(context, &length, 1)) != 0) 1801 return (returnstat); 1802 if ((c = (char *)malloc(length + 1)) == NULL) 1803 return (-1); 1804 if ((returnstat = pr_adr_char(context, c, length)) != 0) { 1805 free(c); 1806 return (returnstat); 1807 } 1808 1809 uval.uvaltype = PRA_STRING; 1810 uval.string_val = c; 1811 returnstat = pa_print(context, &uval, flag); 1812 free(c); 1813 return (returnstat); 1814 } 1815 1816 /* 1817 * ----------------------------------------------------------------------- 1818 * pa_file_string: Retrieves a file string from the input stream and prints it 1819 * if status >= 0 1820 * return codes : -1 - error 1821 * : 0 - successful 1822 * ----------------------------------------------------------------------- 1823 */ 1824 int 1825 pa_file_string(pr_context_t *context, int status, int flag) 1826 { 1827 char *c; 1828 char *p; 1829 short length; 1830 int returnstat; 1831 uval_t uval; 1832 1833 /* 1834 * We need to know how much space to allocate for our string, so 1835 * read the length first, then call pr_adr_char to read those bytes. 1836 */ 1837 if (status < 0) 1838 return (status); 1839 1840 if ((returnstat = pr_adr_short(context, &length, 1)) != 0) 1841 return (returnstat); 1842 if ((c = (char *)malloc(length + 1)) == NULL) 1843 return (-1); 1844 if ((p = (char *)malloc((length * 4) + 1)) == NULL) { 1845 free(c); 1846 return (-1); 1847 } 1848 if ((returnstat = pr_adr_char(context, c, length)) != 0) { 1849 free(c); 1850 free(p); 1851 return (returnstat); 1852 } 1853 1854 if (is_file_token(context->tokenid)) 1855 context->audit_rec_len += length; 1856 1857 convertascii(p, c, length - 1); 1858 uval.uvaltype = PRA_STRING; 1859 uval.string_val = p; 1860 1861 if (returnstat == 0) 1862 returnstat = finish_open_tag(context); 1863 1864 if (returnstat == 0) 1865 returnstat = pa_print(context, &uval, flag); 1866 1867 free(c); 1868 free(p); 1869 return (returnstat); 1870 } 1871 1872 static int 1873 pa_putstr_xml(pr_context_t *context, int printable, char *str, size_t len) 1874 { 1875 int err; 1876 1877 if (!printable) { 1878 /* 1879 * Unprintable chars should always be converted to the 1880 * visible form. If there are unprintable characters which 1881 * require special treatment in xml, those should be 1882 * handled here. 1883 */ 1884 do { 1885 err = pr_printf(context, "\\%03o", 1886 (unsigned char)*str++); 1887 } while (err == 0 && --len != 0); 1888 return (err); 1889 } 1890 /* printable characters */ 1891 if (len == 1) { 1892 /* 1893 * check for the special chars only when char size was 1 1894 * ie, ignore special chars appear in the middle of multibyte 1895 * sequence. 1896 */ 1897 1898 /* Escape for XML */ 1899 switch (*str) { 1900 case '&': 1901 err = pr_printf(context, "%s", "&"); 1902 break; 1903 1904 case '<': 1905 err = pr_printf(context, "%s", "<"); 1906 break; 1907 1908 case '>': 1909 err = pr_printf(context, "%s", ">"); 1910 break; 1911 1912 case '\"': 1913 err = pr_printf(context, "%s", """); 1914 break; 1915 1916 case '\'': 1917 err = pr_printf(context, "%s", "'"); 1918 break; 1919 1920 default: 1921 err = pr_putchar(context, *str); 1922 break; 1923 } 1924 return (err); 1925 } 1926 do { 1927 err = pr_putchar(context, *str++); 1928 } while (err == 0 && --len != 0); 1929 return (err); 1930 } 1931 1932 static int 1933 pa_putstr(pr_context_t *context, int printable, char *str, size_t len) 1934 { 1935 int err; 1936 1937 if (context->format & PRF_XMLM) 1938 return (pa_putstr_xml(context, printable, str, len)); 1939 1940 if (!printable) { 1941 do { 1942 err = pr_printf(context, "\\%03o", 1943 (unsigned char)*str++); 1944 } while (err == 0 && --len != 0); 1945 return (err); 1946 } 1947 do { 1948 err = pr_putchar(context, *str++); 1949 } while (err == 0 && --len != 0); 1950 return (err); 1951 } 1952 1953 int 1954 pa_string(pr_context_t *context, int status, int flag) 1955 { 1956 int rstat, wstat; 1957 int i, printable, eos; 1958 int mlen, rlen; 1959 int mbmax = MB_CUR_MAX; 1960 wchar_t wc; 1961 char mbuf[MB_LEN_MAX + 1]; 1962 char c; 1963 1964 if (status < 0) 1965 return (status); 1966 1967 rstat = wstat = 0; 1968 1969 if (mbmax == 1) { 1970 while (wstat == 0) { 1971 if ((rstat = pr_adr_char(context, &c, 1)) < 0) 1972 break; 1973 if (c == '\0') 1974 break; 1975 printable = isprint((unsigned char)c); 1976 wstat = pa_putstr(context, printable, &c, 1); 1977 } 1978 goto done; 1979 } 1980 1981 mlen = eos = 0; 1982 while (wstat == 0) { 1983 rlen = 0; 1984 do { 1985 if (!eos) { 1986 rstat = pr_adr_char(context, &c, 1); 1987 if (rstat != 0 || c == '\0') 1988 eos = 1; 1989 else 1990 mbuf[mlen++] = c; 1991 } 1992 rlen = mbtowc(&wc, mbuf, mlen); 1993 } while (!eos && mlen < mbmax && rlen <= 0); 1994 1995 if (mlen == 0) 1996 break; /* end of string */ 1997 1998 if (rlen <= 0) { /* no good sequence */ 1999 rlen = 1; 2000 printable = 0; 2001 } else { 2002 printable = iswprint(wc); 2003 } 2004 wstat = pa_putstr(context, printable, mbuf, rlen); 2005 mlen -= rlen; 2006 if (mlen > 0) { 2007 for (i = 0; i < mlen; i++) 2008 mbuf[i] = mbuf[rlen + i]; 2009 } 2010 } 2011 2012 done: 2013 if (wstat == 0) 2014 wstat = do_newline(context, flag); 2015 2016 return ((rstat != 0 || wstat != 0) ? -1 : 0); 2017 } 2018 2019 /* 2020 * ----------------------------------------------------------------------- 2021 * pa_adr_u_int32: Issues pr_adr_u_int32 to retrieve the next ADR item from 2022 * the input stream pointed to by audit_adr, and prints it 2023 * if status = 0 2024 * return codes : -1 - error 2025 * : 0 - successful 2026 * ----------------------------------------------------------------------- 2027 */ 2028 2029 2030 int 2031 pa_adr_u_int32(pr_context_t *context, int status, int flag) 2032 { 2033 uint32_t c; 2034 uval_t uval; 2035 2036 if (status >= 0) { 2037 if (pr_adr_u_int32(context, &c, 1) == 0) { 2038 uval.uvaltype = PRA_UINT32; 2039 uval.uint32_val = c; 2040 return (pa_print(context, &uval, flag)); 2041 } else 2042 return (-1); 2043 } else 2044 return (status); 2045 } 2046 2047 2048 2049 /* 2050 * ----------------------------------------------------------------------- 2051 * pa_adr_u_int64: Issues pr_adr_u_int64 to retrieve the next ADR item from the 2052 * input stream pointed to by audit_adr, and prints it 2053 * if status = 0 2054 * return codes : -1 - error 2055 * : 0 - successful 2056 * ----------------------------------------------------------------------- 2057 */ 2058 int 2059 pa_adr_u_int64(pr_context_t *context, int status, int flag) 2060 { 2061 uint64_t c; 2062 uval_t uval; 2063 2064 if (status >= 0) { 2065 if (pr_adr_u_int64(context, &c, 1) == 0) { 2066 uval.uvaltype = PRA_UINT64; 2067 uval.uint64_val = c; 2068 return (pa_print(context, &uval, flag)); 2069 } else 2070 return (-1); 2071 } else 2072 return (status); 2073 } 2074 2075 2076 /* 2077 * ----------------------------------------------------------------------- 2078 * pa_adr_u_short: Issues pr_adr_u_short to retrieve the next ADR item from 2079 * the input stream pointed to by audit_adr, and prints it 2080 * if status = 0 2081 * return codes : -1 - error 2082 * : 0 - successful 2083 * ----------------------------------------------------------------------- 2084 */ 2085 int 2086 pa_adr_u_short(pr_context_t *context, int status, int flag) 2087 { 2088 ushort_t c; 2089 uval_t uval; 2090 2091 if (status >= 0) { 2092 if (pr_adr_u_short(context, &c, 1) == 0) { 2093 uval.uvaltype = PRA_USHORT; 2094 uval.ushort_val = c; 2095 return (pa_print(context, &uval, flag)); 2096 } else 2097 return (-1); 2098 } else 2099 return (status); 2100 } 2101 2102 /* 2103 * ----------------------------------------------------------------------- 2104 * pa_reclen: Issues pr_adr_u_long to retrieve the length of the record 2105 * from the input stream pointed to by audit_adr, 2106 * and prints it (unless format is XML) if status = 0 2107 * return codes : -1 - error 2108 * : 0 - successful 2109 * ----------------------------------------------------------------------- 2110 */ 2111 int 2112 pa_reclen(pr_context_t *context, int status) 2113 { 2114 uint32_t c; 2115 uval_t uval; 2116 2117 if (status >= 0) { 2118 if ((int)pr_adr_u_int32(context, &c, 1) == 0) { 2119 context->audit_rec_len = c; 2120 2121 /* Don't print this for XML format */ 2122 if (context->format & PRF_XMLM) { 2123 return (0); 2124 } else { 2125 uval.uvaltype = PRA_UINT32; 2126 uval.uint32_val = c; 2127 return (pa_print(context, &uval, 0)); 2128 } 2129 } else 2130 return (-1); 2131 } else 2132 return (status); 2133 } 2134 2135 /* 2136 * ----------------------------------------------------------------------- 2137 * pa_mode : Issues pr_adr_u_short to retrieve the next ADR item from 2138 * the input stream pointed to by audit_adr, and prints it 2139 * in octal if status = 0 2140 * return codes : -1 - error 2141 * : 0 - successful 2142 * ----------------------------------------------------------------------- 2143 */ 2144 int 2145 pa_mode(pr_context_t *context, int status, int flag) 2146 { 2147 uint32_t c; 2148 uval_t uval; 2149 2150 if (status >= 0) { 2151 if (pr_adr_u_int32(context, &c, 1) == 0) { 2152 uval.uvaltype = PRA_LOCT; 2153 uval.uint32_val = c; 2154 return (pa_print(context, &uval, flag)); 2155 } else 2156 return (-1); 2157 } else 2158 return (status); 2159 } 2160 2161 static int 2162 pa_print_uid(pr_context_t *context, uid_t uid, int status, int flag) 2163 { 2164 int returnstat; 2165 uval_t uval; 2166 2167 if (status < 0) 2168 return (status); 2169 2170 if (context->format & PRF_RAWM) { 2171 /* print in integer form */ 2172 uval.uvaltype = PRA_INT32; 2173 uval.int32_val = uid; 2174 returnstat = pa_print(context, &uval, flag); 2175 } else { 2176 /* print in ASCII form */ 2177 uval.uvaltype = PRA_STRING; 2178 uval.string_val = getname(uid); 2179 returnstat = pa_print(context, &uval, flag); 2180 } 2181 return (returnstat); 2182 } 2183 2184 2185 /* 2186 * ----------------------------------------------------------------------- 2187 * pa_pw_uid() : Issues pr_adr_u_int32 to reads uid from input stream 2188 * pointed to by audit_adr, and displays it in either 2189 * raw form or its ASCII representation, if status >= 0. 2190 * return codes : -1 - error 2191 * : 1 - warning, passwd entry not found 2192 * : 0 - successful 2193 * ----------------------------------------------------------------------- 2194 */ 2195 int 2196 pa_pw_uid(pr_context_t *context, int status, int flag) 2197 { 2198 uint32_t uid; 2199 2200 if (status < 0) 2201 return (status); 2202 2203 if (pr_adr_u_int32(context, &uid, 1) != 0) 2204 /* cannot retrieve uid */ 2205 return (-1); 2206 2207 return (pa_print_uid(context, uid, status, flag)); 2208 } 2209 2210 static int 2211 pa_print_gid(pr_context_t *context, gid_t gid, int status, int flag) 2212 { 2213 int returnstat; 2214 uval_t uval; 2215 2216 if (status < 0) 2217 return (status); 2218 2219 if (context->format & PRF_RAWM) { 2220 /* print in integer form */ 2221 uval.uvaltype = PRA_INT32; 2222 uval.int32_val = gid; 2223 returnstat = pa_print(context, &uval, flag); 2224 } else { 2225 /* print in ASCII form */ 2226 uval.uvaltype = PRA_STRING; 2227 uval.string_val = getgroup(gid); 2228 returnstat = pa_print(context, &uval, flag); 2229 } 2230 return (returnstat); 2231 } 2232 2233 2234 /* 2235 * ----------------------------------------------------------------------- 2236 * pa_gr_uid() : Issues pr_adr_u_int32 to reads group uid from input stream 2237 * pointed to by audit_adr, and displays it in either 2238 * raw form or its ASCII representation, if status >= 0. 2239 * return codes : -1 - error 2240 * : 1 - warning, passwd entry not found 2241 * : 0 - successful 2242 * ----------------------------------------------------------------------- 2243 */ 2244 int 2245 pa_gr_uid(pr_context_t *context, int status, int flag) 2246 { 2247 uint32_t gid; 2248 2249 if (status < 0) 2250 return (status); 2251 2252 if (pr_adr_u_int32(context, &gid, 1) != 0) 2253 /* cannot retrieve gid */ 2254 return (-1); 2255 2256 return (pa_print_gid(context, gid, status, flag)); 2257 } 2258 2259 2260 /* 2261 * ----------------------------------------------------------------------- 2262 * pa_pw_uid_gr_gid() : Issues pr_adr_u_int32 to reads uid or group uid 2263 * from input stream 2264 * pointed to by audit_adr, and displays it in either 2265 * raw form or its ASCII representation, if status >= 0. 2266 * return codes : -1 - error 2267 * : 1 - warning, passwd entry not found 2268 * : 0 - successful 2269 * ----------------------------------------------------------------------- 2270 */ 2271 int 2272 pa_pw_uid_gr_gid(pr_context_t *context, int status, int flag) 2273 { 2274 int returnstat; 2275 uint32_t value; 2276 uval_t uval; 2277 2278 if (status < 0) 2279 return (status); 2280 2281 /* get value of a_type */ 2282 if ((returnstat = pr_adr_u_int32(context, &value, 1)) != 0) 2283 return (returnstat); 2284 2285 if ((returnstat = open_tag(context, TAG_ACLTYPE)) != 0) 2286 return (returnstat); 2287 2288 uval.uvaltype = PRA_UINT32; 2289 uval.uint32_val = value; 2290 if ((returnstat = pa_print(context, &uval, flag)) != 0) 2291 return (returnstat); 2292 2293 if ((returnstat = close_tag(context, TAG_ACLTYPE)) != 0) 2294 return (returnstat); 2295 2296 if ((returnstat = open_tag(context, TAG_ACLVAL)) != 0) 2297 return (returnstat); 2298 /* 2299 * TRANSLATION_NOTE 2300 * The "mask" and "other" strings refer to the class mask 2301 * and other (or world) entries in an ACL. 2302 * The "unrecognized" string refers to an unrecognized ACL 2303 * entry. 2304 */ 2305 switch (value) { 2306 case USER_OBJ: 2307 case USER: 2308 returnstat = pa_pw_uid(context, returnstat, flag); 2309 break; 2310 case GROUP_OBJ: 2311 case GROUP: 2312 returnstat = pa_gr_uid(context, returnstat, flag); 2313 break; 2314 case CLASS_OBJ: 2315 returnstat = pr_adr_u_int32(context, &value, 1); 2316 if (returnstat != 0) 2317 return (returnstat); 2318 2319 if (!(context->format & PRF_RAWM)) { 2320 uval.uvaltype = PRA_STRING; 2321 uval.string_val = gettext("mask"); 2322 returnstat = pa_print(context, &uval, flag); 2323 } else { 2324 uval.uvaltype = PRA_UINT32; 2325 uval.uint32_val = value; 2326 if ((returnstat = 2327 pa_print(context, &uval, flag)) != 0) { 2328 return (returnstat); 2329 } 2330 } 2331 break; 2332 case OTHER_OBJ: 2333 returnstat = pr_adr_u_int32(context, &value, 1); 2334 if (returnstat != 0) 2335 return (returnstat); 2336 2337 if (!(context->format & PRF_RAWM)) { 2338 uval.uvaltype = PRA_STRING; 2339 uval.string_val = gettext("other"); 2340 returnstat = pa_print(context, &uval, flag); 2341 } else { 2342 uval.uvaltype = PRA_UINT32; 2343 uval.uint32_val = value; 2344 if ((returnstat = 2345 pa_print(context, &uval, flag)) != 0) { 2346 return (returnstat); 2347 } 2348 } 2349 break; 2350 default: 2351 returnstat = pr_adr_u_int32(context, &value, 1); 2352 if (returnstat != 0) 2353 return (returnstat); 2354 2355 if (!(context->format & PRF_RAWM)) { 2356 uval.uvaltype = PRA_STRING; 2357 uval.string_val = gettext("unrecognized"); 2358 returnstat = pa_print(context, &uval, flag); 2359 } else { 2360 uval.uvaltype = PRA_UINT32; 2361 uval.uint32_val = value; 2362 if ((returnstat = 2363 pa_print(context, &uval, flag)) != 0) { 2364 return (returnstat); 2365 } 2366 } 2367 } 2368 2369 if ((returnstat = close_tag(context, TAG_ACLVAL)) != 0) 2370 return (returnstat); 2371 2372 return (returnstat); 2373 } 2374 2375 2376 /* 2377 * ----------------------------------------------------------------------- 2378 * pa_event_modifier(): Issues pr_adr_u_short to retrieve the next ADR item from 2379 * the input stream pointed to by audit_adr. This is the 2380 * event type, and is displayed in hex; 2381 * return codes : -1 - error 2382 * : 0 - successful 2383 * ----------------------------------------------------------------------- 2384 */ 2385 int 2386 pa_event_modifier(pr_context_t *context, int status, int flag) 2387 { 2388 int returnstat; 2389 au_emod_t emodifier; 2390 uval_t uval; 2391 char modstring[64]; 2392 2393 if (status < 0) 2394 return (status); 2395 2396 if ((returnstat = pr_adr_u_short(context, &emodifier, 1)) != 0) 2397 return (returnstat); 2398 2399 /* For XML, only print when modifier is non-zero */ 2400 if (!(context->format & PRF_XMLM) || (emodifier != 0)) { 2401 uval.uvaltype = PRA_STRING; 2402 2403 returnstat = open_tag(context, TAG_EVMOD); 2404 2405 if (returnstat >= 0) { 2406 if (!(context->format & PRF_RAWM)) { 2407 eventmodifier2string(emodifier, modstring, 2408 sizeof (modstring)); 2409 uval.string_val = modstring; 2410 returnstat = pa_print(context, &uval, flag); 2411 } else { 2412 uval.string_val = hexconvert((char *)&emodifier, 2413 sizeof (emodifier), sizeof (emodifier)); 2414 if (uval.string_val) { 2415 returnstat = pa_print(context, &uval, 2416 flag); 2417 free(uval.string_val); 2418 } 2419 } 2420 } 2421 if (returnstat >= 0) 2422 returnstat = close_tag(context, TAG_EVMOD); 2423 } 2424 2425 return (returnstat); 2426 } 2427 2428 2429 /* 2430 * ----------------------------------------------------------------------- 2431 * pa_event_type(): Issues pr_adr_u_short to retrieve the next ADR item from 2432 * the input stream pointed to by audit_adr. This is the 2433 * event type, and is displayed in either raw or 2434 * ASCII form as appropriate 2435 * return codes : -1 - error 2436 * : 0 - successful 2437 * ----------------------------------------------------------------------- 2438 */ 2439 int 2440 pa_event_type(pr_context_t *context, int status, int flag) 2441 { 2442 au_event_t etype; 2443 int returnstat; 2444 au_event_ent_t *p_event = NULL; 2445 uval_t uval; 2446 2447 if (status >= 0) { 2448 if ((returnstat = pr_adr_u_short(context, &etype, 1)) == 0) { 2449 if (!(context->format & PRF_RAWM)) { 2450 uval.uvaltype = PRA_STRING; 2451 if (context->format & PRF_NOCACHE) { 2452 p_event = getauevnum(etype); 2453 } else { 2454 (void) cacheauevent(&p_event, etype); 2455 } 2456 if (p_event != NULL) { 2457 if (context->format & PRF_SHORTM) 2458 uval.string_val = 2459 p_event->ae_name; 2460 else 2461 uval.string_val = 2462 p_event->ae_desc; 2463 } else { 2464 uval.string_val = 2465 gettext("invalid event number"); 2466 } 2467 returnstat = pa_print(context, &uval, flag); 2468 } else { 2469 uval.uvaltype = PRA_USHORT; 2470 uval.ushort_val = etype; 2471 returnstat = pa_print(context, &uval, flag); 2472 } 2473 } 2474 return (returnstat); 2475 } else 2476 return (status); 2477 2478 } 2479 2480 2481 /* 2482 * Print time from struct timeval to millisecond resolution. 2483 * 2484 * typedef long time_t; time of day in seconds 2485 * typedef long useconds_t; signed # of microseconds 2486 * 2487 * struct timeval { 2488 * time_t tv_sec; seconds 2489 * suseconds_t tv_usec; and microseconds 2490 * }; 2491 */ 2492 2493 int 2494 pa_utime32(pr_context_t *context, int status, int flag) 2495 { 2496 uint32_t scale = 1000; /* usec to msec */ 2497 2498 return (do_mtime32(context, status, flag, scale)); 2499 } 2500 2501 /* 2502 * Print time from timestruc_t to millisecond resolution. 2503 * 2504 * typedef struct timespec timestruct_t; 2505 * struct timespec{ 2506 * time_t tv_sec; seconds 2507 * long tv_nsec; and nanoseconds 2508 * }; 2509 */ 2510 int 2511 pa_ntime32(pr_context_t *context, int status, int flag) 2512 { 2513 uint32_t scale = 1000000; /* nsec to msec */ 2514 2515 return (do_mtime32(context, status, flag, scale)); 2516 } 2517 2518 /* 2519 * Format the timezone +/- HH:MM and terminate the string 2520 * Note tm and tv_sec are the same time. 2521 * Too bad strftime won't produce an ISO 8601 time zone numeric 2522 */ 2523 2524 #define MINS (24L * 60) 2525 static void 2526 tzone(struct tm *tm, time_t *tv_sec, char *p) 2527 { 2528 struct tm *gmt; 2529 int min_off; 2530 2531 gmt = gmtime(tv_sec); 2532 2533 min_off = ((tm->tm_hour - gmt->tm_hour) * 60) + 2534 (tm->tm_min - gmt->tm_min); 2535 2536 if (tm->tm_year < gmt->tm_year) /* cross new year */ 2537 min_off -= MINS; 2538 else if (tm->tm_year > gmt->tm_year) 2539 min_off += MINS; 2540 else if (tm->tm_yday < gmt->tm_yday) /* cross dateline */ 2541 min_off -= MINS; 2542 else if (tm->tm_yday > gmt->tm_yday) 2543 min_off += MINS; 2544 2545 if (min_off < 0) { 2546 min_off = -min_off; 2547 *p++ = '-'; 2548 } else { 2549 *p++ = '+'; 2550 } 2551 2552 *p++ = min_off / 600 + '0'; /* 10s of hours */ 2553 min_off = min_off - min_off / 600 * 600; 2554 *p++ = min_off / 60 % 10 + '0'; /* hours */ 2555 min_off = min_off - min_off / 60 * 60; 2556 *p++ = ':'; 2557 *p++ = min_off / 10 + '0'; /* 10s of minutes */ 2558 *p++ = min_off % 10 + '0'; /* minutes */ 2559 *p = '\0'; 2560 } 2561 2562 /* 2563 * Format the milliseconds in place in the string. 2564 * Borrowed from strftime.c:itoa() 2565 */ 2566 static void 2567 msec32(uint32_t msec, char *p) 2568 { 2569 *p++ = msec / 100 + '0'; 2570 msec = msec - msec / 100 * 100; 2571 *p++ = msec / 10 + '0'; 2572 *p++ = msec % 10 +'0'; 2573 } 2574 2575 /* 2576 * Format time and print relative to scale factor from micro/nano seconds. 2577 */ 2578 static int 2579 do_mtime32(pr_context_t *context, int status, int flag, uint32_t scale) 2580 { 2581 uint32_t t32; 2582 time_t tv_sec; 2583 struct tm tm; 2584 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")]; 2585 int returnstat; 2586 uval_t uval; 2587 2588 if (status < 0) 2589 return (status); 2590 2591 if ((returnstat = open_tag(context, TAG_ISO)) != 0) 2592 return (returnstat); 2593 2594 if ((returnstat = pr_adr_u_int32(context, 2595 (uint32_t *)&tv_sec, 1)) != 0) 2596 return (returnstat); 2597 if ((returnstat = pr_adr_u_int32(context, &t32, 1)) == 0) { 2598 if (!(context->format & PRF_RAWM)) { 2599 (void) localtime_r(&tv_sec, &tm); 2600 (void) strftime(time_created, 2601 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "), 2602 "%Y-%m-%d %H:%M:%S.xxx ", &tm); 2603 msec32(t32/scale, 2604 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]); 2605 tzone(&tm, &tv_sec, 2606 &time_created[ 2607 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]); 2608 uval.uvaltype = PRA_STRING; 2609 uval.string_val = time_created; 2610 } else { 2611 uval.uvaltype = PRA_UINT32; 2612 uval.uint32_val = (uint32_t)tv_sec; 2613 (void) pa_print(context, &uval, 0); 2614 if (context->format & PRF_XMLM) { 2615 uval.uvaltype = PRA_CHAR; 2616 uval.char_val = '.'; 2617 (void) pa_print(context, &uval, 0); 2618 } 2619 uval.uvaltype = PRA_UINT32; 2620 uval.uint32_val = t32; 2621 } 2622 returnstat = pa_print(context, &uval, flag); 2623 } 2624 2625 if (returnstat == 0) 2626 return (close_tag(context, TAG_ISO)); 2627 else 2628 return (returnstat); 2629 } 2630 2631 /* 2632 * Print time from struct timeval to millisecond resolution. 2633 * 2634 * typedef long time_t; time of day in seconds 2635 * typedef long useconds_t; signed # of microseconds 2636 * 2637 * struct timeval { 2638 * time_t tv_sec; seconds 2639 * suseconds_t tv_usec; and microseconds 2640 * }; 2641 */ 2642 2643 int 2644 pa_utime64(pr_context_t *context, int status, int flag) 2645 { 2646 uint64_t scale = 1000; /* usec to msec */ 2647 2648 return (do_mtime64(context, status, flag, scale)); 2649 } 2650 2651 /* 2652 * Print time from timestruc_t to millisecond resolution. 2653 * 2654 * typedef struct timespec timestruct_t; 2655 * struct timespec{ 2656 * time_t tv_sec; seconds 2657 * long tv_nsec; and nanoseconds 2658 * }; 2659 */ 2660 int 2661 pa_ntime64(pr_context_t *context, int status, int flag) 2662 { 2663 uint64_t scale = 1000000; /* nsec to msec */ 2664 2665 return (do_mtime64(context, status, flag, scale)); 2666 } 2667 2668 /* 2669 * Format the milliseconds in place in the string. 2670 * Borrowed from strftime.c:itoa() 2671 */ 2672 static void 2673 msec64(uint64_t msec, char *p) 2674 { 2675 *p++ = msec / 100 + '0'; 2676 msec = msec - msec / 100 * 100; 2677 *p++ = msec / 10 + '0'; 2678 *p++ = msec % 10 +'0'; 2679 } 2680 2681 /* 2682 * Format time and print relative to scale factor from micro/nano seconds. 2683 */ 2684 static int 2685 do_mtime64(pr_context_t *context, int status, int flag, uint64_t scale) 2686 { 2687 uint64_t t64_sec; 2688 uint64_t t64_msec; 2689 time_t tv_sec; 2690 struct tm tm; 2691 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")]; 2692 int returnstat; 2693 uval_t uval; 2694 2695 if (status < 0) 2696 return (status); 2697 2698 if ((returnstat = open_tag(context, TAG_ISO)) != 0) 2699 return (returnstat); 2700 2701 if ((returnstat = pr_adr_u_int64(context, &t64_sec, 1)) != 0) 2702 return (returnstat); 2703 if ((returnstat = pr_adr_u_int64(context, &t64_msec, 1)) == 0) { 2704 if (!(context->format & PRF_RAWM)) { 2705 #ifndef _LP64 2706 /* 2707 * N.B. 2708 * This fails for years from 2038 2709 * The Y2K+38 problem 2710 */ 2711 #endif /* !_LP64 */ 2712 tv_sec = (time_t)t64_sec; 2713 (void) localtime_r(&tv_sec, &tm); 2714 (void) strftime(time_created, 2715 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "), 2716 "%Y-%m-%d %H:%M:%S.xxx ", &tm); 2717 msec64(t64_msec/scale, 2718 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]); 2719 tzone(&tm, &tv_sec, 2720 &time_created[ 2721 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]); 2722 uval.uvaltype = PRA_STRING; 2723 uval.string_val = time_created; 2724 } else { 2725 uval.uvaltype = PRA_UINT64; 2726 uval.uint64_val = t64_sec; 2727 (void) pa_print(context, &uval, 0); 2728 if (context->format & PRF_XMLM) { 2729 uval.uvaltype = PRA_CHAR; 2730 uval.char_val = '.'; 2731 (void) pa_print(context, &uval, 0); 2732 } 2733 uval.uvaltype = PRA_UINT64; 2734 uval.uint64_val = t64_msec; 2735 } 2736 returnstat = pa_print(context, &uval, flag); 2737 } 2738 2739 if (returnstat < 0) 2740 return (returnstat); 2741 2742 return (close_tag(context, TAG_ISO)); 2743 } 2744 2745 /* 2746 * ----------------------------------------------------------------------- 2747 * pa_error() : convert the return token error code. 2748 * 2749 * output : buf string representing return token error code. 2750 * 2751 * ----------------------------------------------------------------------- 2752 */ 2753 void 2754 pa_error(const uchar_t err, char *buf, size_t buflen) 2755 { 2756 if (err == ADT_SUCCESS) { 2757 (void) strlcpy(buf, gettext("success"), buflen); 2758 } else if ((char)err == ADT_FAILURE) { 2759 (void) strlcpy(buf, gettext("failure"), buflen); 2760 } else { 2761 char *emsg = strerror(err); 2762 2763 if (emsg != NULL) { 2764 (void) strlcpy(buf, gettext("failure: "), buflen); 2765 (void) strlcat(buf, emsg, buflen); 2766 } else { 2767 (void) snprintf(buf, buflen, "%s%d", 2768 gettext("failure: "), err); 2769 } 2770 } 2771 } 2772 2773 /* 2774 * ----------------------------------------------------------------------- 2775 * pa_retval() : convert the return token return value code. 2776 * 2777 * input : err, for kernel success 0, or 2778 * failure errno: 0 > & < sys_nerr. 2779 * for userland success ADT_SUCCESS (0) or 2780 * failure ADT_FAILURE (-1). 2781 * pa_error() above has already converted err. 2782 * 2783 * : retval, for kernel arbitrary return value for success, or 2784 * failure: -1. 2785 * for userland, 2786 * >= ADT_FAIL_VALUE < ADT_FAIL_PAM, an adt message code; 2787 * >= ADT_FAIL_PAM, a pam_strerror value; 2788 * < ADT_FAIL_VALUE, supposed to be an errno. 2789 * 2790 * output : buf string representing return token error code. 2791 * 2792 * ----------------------------------------------------------------------- 2793 */ 2794 void 2795 pa_retval(const uchar_t err, const int32_t retval, char *buf, size_t buflen) 2796 { 2797 struct msg_text *msglist; 2798 char *emsg; 2799 2800 /* success or kernel failure */ 2801 if (((char)err == ADT_SUCCESS) || 2802 (retval < 0)) { 2803 2804 (void) snprintf(buf, buflen, "%d", retval); 2805 return; 2806 } 2807 2808 /* userland failure */ 2809 msglist = &adt_msg_text[ADT_LIST_FAIL_VALUE]; 2810 2811 if ((retval + msglist->ml_offset >= msglist->ml_min_index) && 2812 (retval + msglist->ml_offset <= msglist->ml_max_index)) { 2813 2814 (void) strlcpy(buf, 2815 gettext(msglist->ml_msg_list[retval + msglist->ml_offset]), 2816 buflen); 2817 } else if ((retval >= ADT_FAIL_PAM) && 2818 (retval < ADT_FAIL_PAM + PAM_TOTAL_ERRNUM)) { 2819 2820 (void) strlcpy(buf, pam_strerror(NULL, retval - ADT_FAIL_PAM), 2821 buflen); 2822 } else if ((emsg = strerror(retval)) != NULL) { 2823 2824 (void) strlcpy(buf, emsg, buflen); 2825 } else { 2826 2827 (void) snprintf(buf, buflen, "%d", retval); 2828 } 2829 } 2830 2831 /* 2832 * ----------------------------------------------------------------------- 2833 * pa_printstr() : print a given string, translating unprintables 2834 * : as needed. 2835 */ 2836 static int 2837 pa_printstr(pr_context_t *context, char *str) 2838 { 2839 int err = 0; 2840 int len, printable; 2841 int mbmax = MB_CUR_MAX; 2842 wchar_t wc; 2843 char c; 2844 2845 if (mbmax == 1) { 2846 /* fast path */ 2847 while (err == 0 && *str != '\0') { 2848 c = *str++; 2849 printable = isprint((unsigned char)c); 2850 err = pa_putstr(context, printable, &c, 1); 2851 } 2852 return (err); 2853 } 2854 while (err == 0 && *str != '\0') { 2855 len = mbtowc(&wc, str, mbmax); 2856 if (len <= 0) { 2857 len = 1; 2858 printable = 0; 2859 } else { 2860 printable = iswprint(wc); 2861 } 2862 err = pa_putstr(context, printable, str, len); 2863 str += len; 2864 } 2865 return (err); 2866 } 2867 2868 /* 2869 * ----------------------------------------------------------------------- 2870 * pa_print() : print as one str or formatted for easy reading. 2871 * : flag - indicates whether to output a new line for 2872 * : multi-line output. 2873 * : = 0; no new line 2874 * : = 1; new line if regular output 2875 * output : The audit record information is displayed in the 2876 * type specified by uvaltype and value specified in 2877 * uval. The printing of the delimiter or newline is 2878 * determined by PRF_ONELINE, and the flag value, 2879 * as follows: 2880 * +--------+------+------+-----------------+ 2881 * |ONELINE | flag | last | Action | 2882 * +--------+------+------+-----------------+ 2883 * | Y | Y | T | print new line | 2884 * | Y | Y | F | print delimiter | 2885 * | Y | N | T | print new line | 2886 * | Y | N | F | print delimiter | 2887 * | N | Y | T | print new line | 2888 * | N | Y | F | print new line | 2889 * | N | N | T | print new line | 2890 * | N | N | F | print delimiter | 2891 * +--------+------+------+-----------------+ 2892 * 2893 * return codes : -1 - error 2894 * 0 - successful 2895 * ----------------------------------------------------------------------- 2896 */ 2897 int 2898 pa_print(pr_context_t *context, uval_t *uval, int flag) 2899 { 2900 int returnstat = 0; 2901 int last; 2902 2903 switch (uval->uvaltype) { 2904 case PRA_INT32: 2905 returnstat = pr_printf(context, "%d", uval->int32_val); 2906 break; 2907 case PRA_UINT32: 2908 returnstat = pr_printf(context, "%u", uval->uint32_val); 2909 break; 2910 case PRA_INT64: 2911 returnstat = pr_printf(context, "%"PRId64, uval->int64_val); 2912 break; 2913 case PRA_UINT64: 2914 returnstat = pr_printf(context, "%"PRIu64, uval->uint64_val); 2915 break; 2916 case PRA_SHORT: 2917 returnstat = pr_printf(context, "%hd", uval->short_val); 2918 break; 2919 case PRA_USHORT: 2920 returnstat = pr_printf(context, "%hu", uval->ushort_val); 2921 break; 2922 case PRA_CHAR: 2923 returnstat = pr_printf(context, "%c", uval->char_val); 2924 break; 2925 case PRA_BYTE: 2926 returnstat = pr_printf(context, "%d", uval->char_val); 2927 break; 2928 case PRA_STRING: 2929 returnstat = pa_printstr(context, uval->string_val); 2930 break; 2931 case PRA_HEX32: 2932 returnstat = pr_printf(context, "0x%x", uval->int32_val); 2933 break; 2934 case PRA_HEX64: 2935 returnstat = pr_printf(context, "0x%"PRIx64, uval->int64_val); 2936 break; 2937 case PRA_SHEX: 2938 returnstat = pr_printf(context, "0x%hx", uval->short_val); 2939 break; 2940 case PRA_OCT: 2941 returnstat = pr_printf(context, "%ho", uval->ushort_val); 2942 break; 2943 case PRA_LOCT: 2944 returnstat = pr_printf(context, "%o", (int)uval->uint32_val); 2945 break; 2946 default: 2947 (void) fprintf(stderr, gettext("praudit: Unknown type.\n")); 2948 returnstat = -1; 2949 break; 2950 } 2951 if (returnstat < 0) 2952 return (returnstat); 2953 2954 last = (context->audit_adr->adr_now == 2955 (context->audit_rec_start + context->audit_rec_len)); 2956 2957 if (!(context->format & PRF_XMLM)) { 2958 if (!(context->format & PRF_ONELINE)) { 2959 if ((flag == 1) || last) 2960 returnstat = pr_putchar(context, '\n'); 2961 else 2962 returnstat = pr_printf(context, "%s", 2963 context->SEPARATOR); 2964 } else { 2965 if (!last) 2966 returnstat = pr_printf(context, "%s", 2967 context->SEPARATOR); 2968 else 2969 returnstat = pr_putchar(context, '\n'); 2970 } 2971 } 2972 return (returnstat); 2973 } 2974 2975 static struct cntrl_mapping { 2976 char from; 2977 char to; 2978 } cntrl_map[] = { 2979 '\0', '0', 2980 '\a', 'a', 2981 '\b', 'b', 2982 '\t', 't', 2983 '\f', 'f', 2984 '\n', 'n', 2985 '\r', 'r', 2986 '\v', 'v' 2987 }; 2988 2989 static int cntrl_map_entries = sizeof (cntrl_map) 2990 / sizeof (struct cntrl_mapping); 2991 2992 /* 2993 * Convert binary data to ASCII for printing. 2994 */ 2995 void 2996 convertascii(char *p, char *c, int size) 2997 { 2998 int i, j, uc; 2999 3000 for (i = 0; i < size; i++) { 3001 uc = (unsigned char)*(c + i); 3002 if (isascii(uc)) { 3003 if (iscntrl(uc)) { 3004 for (j = 0; j < cntrl_map_entries; j++) { 3005 if (cntrl_map[j].from == uc) { 3006 *p++ = '\\'; 3007 *p++ = cntrl_map[j].to; 3008 break; 3009 } 3010 } 3011 if (j == cntrl_map_entries) { 3012 *p++ = '^'; 3013 *p++ = (char)(uc ^ 0100); 3014 } 3015 } else { 3016 *p++ = (char)uc; 3017 } 3018 } else { 3019 p += sprintf(p, "\\%03o", uc); 3020 } 3021 } 3022 *p = '\0'; 3023 } 3024 3025 /* 3026 * ----------------------------------------------------------------------- 3027 * pa_xgeneric: Process Xobject token and display contents 3028 * This routine will handle many of the attribute 3029 * types introduced in TS 2.x, such as: 3030 * 3031 * AUT_XCOLORMAP, AUT_XCURSOR, AUT_XFONT, 3032 * AUT_XGC, AUT_XPIXMAP, AUT_XWINDOW 3033 * 3034 * NOTE: At the time of call, the token id has been retrieved 3035 * 3036 * return codes : -1 - error 3037 * : 0 - successful 3038 * NOTE: At the time of call, the xatom token id has been retrieved 3039 * 3040 * Format of xobj 3041 * text token id adr_char 3042 * XID adr_u_int32 3043 * creator uid adr_pw_uid 3044 * ----------------------------------------------------------------------- 3045 */ 3046 int 3047 pa_xgeneric(pr_context_t *context) 3048 { 3049 int returnstat; 3050 3051 returnstat = process_tag(context, TAG_XID, 0, 0); 3052 return (process_tag(context, TAG_XCUID, returnstat, 1)); 3053 } 3054 3055 3056 /* 3057 * ------------------------------------------------------------------------ 3058 * pa_liaison : Issues pr_adr_char to retrieve the next ADR item from the 3059 * input stream pointed to by audit_adr, and prints it 3060 * if status >= 0 either in ASCII or raw form 3061 * return codes : -1 - error 3062 * : 0 - successful 3063 * : 1 - warning, unknown label type 3064 * ----------------------------------------------------------------------- 3065 */ 3066 int 3067 pa_liaison(pr_context_t *context, int status, int flag) 3068 { 3069 int returnstat; 3070 int32_t li; 3071 uval_t uval; 3072 3073 if (status >= 0) { 3074 if ((returnstat = pr_adr_int32(context, &li, 1)) != 0) { 3075 return (returnstat); 3076 } 3077 if (!(context->format & PRF_RAWM)) { 3078 uval.uvaltype = PRA_UINT32; 3079 uval.uint32_val = li; 3080 returnstat = pa_print(context, &uval, flag); 3081 } 3082 /* print in hexadecimal form */ 3083 if ((context->format & PRF_RAWM) || (returnstat == 1)) { 3084 uval.uvaltype = PRA_HEX32; 3085 uval.uint32_val = li; 3086 returnstat = pa_print(context, &uval, flag); 3087 } 3088 return (returnstat); 3089 } else 3090 return (status); 3091 } 3092 3093 /* 3094 * ------------------------------------------------------------------------ 3095 * pa_xid : Issues pr_adr_int32 to retrieve the XID from the input 3096 * stream pointed to by audit_adr, and prints it if 3097 * status >= 0 either in ASCII or raw form 3098 * return codes : -1 - error 3099 * : 0 - successful 3100 * : 1 - warning, unknown label type 3101 * ------------------------------------------------------------------------ 3102 */ 3103 3104 int 3105 pa_xid(pr_context_t *context, int status, int flag) 3106 { 3107 int returnstat; 3108 int32_t xid; 3109 uval_t uval; 3110 3111 if (status < 0) 3112 return (status); 3113 3114 /* get XID from stream */ 3115 if ((returnstat = pr_adr_int32(context, (int32_t *)&xid, 1)) != 0) 3116 return (returnstat); 3117 3118 if (!(context->format & PRF_RAWM)) { 3119 uval.uvaltype = PRA_STRING; 3120 uval.string_val = hexconvert((char *)&xid, sizeof (xid), 3121 sizeof (xid)); 3122 if (uval.string_val) { 3123 returnstat = pa_print(context, &uval, flag); 3124 free(uval.string_val); 3125 } 3126 } else { 3127 uval.uvaltype = PRA_INT32; 3128 uval.int32_val = xid; 3129 returnstat = pa_print(context, &uval, flag); 3130 } 3131 3132 return (returnstat); 3133 } 3134 3135 static int 3136 pa_ace_flags(pr_context_t *context, ace_t *ace, int status, int flag) 3137 { 3138 int returnstat; 3139 uval_t uval; 3140 3141 if (status < 0) 3142 return (status); 3143 3144 /* 3145 * TRANSLATION_NOTE 3146 * ace->a_flags refers to access flags of ZFS/NFSv4 ACL entry. 3147 */ 3148 if ((returnstat = open_tag(context, TAG_ACEFLAGS)) != 0) 3149 return (returnstat); 3150 if (!(context->format & PRF_RAWM)) { 3151 uval.uvaltype = PRA_STRING; 3152 switch (ace->a_flags & ACE_TYPE_FLAGS) { 3153 case ACE_OWNER: 3154 uval.string_val = gettext(OWNERAT_TXT); 3155 break; 3156 case ACE_GROUP | ACE_IDENTIFIER_GROUP: 3157 uval.string_val = gettext(GROUPAT_TXT); 3158 break; 3159 case ACE_IDENTIFIER_GROUP: 3160 uval.string_val = gettext(GROUP_TXT); 3161 break; 3162 case ACE_EVERYONE: 3163 uval.string_val = gettext(EVERYONEAT_TXT); 3164 break; 3165 case 0: 3166 uval.string_val = gettext(USER_TXT); 3167 break; 3168 default: 3169 uval.uvaltype = PRA_USHORT; 3170 uval.uint32_val = ace->a_flags; 3171 } 3172 } else { 3173 uval.uvaltype = PRA_USHORT; 3174 uval.uint32_val = ace->a_flags; 3175 } 3176 if ((returnstat = pa_print(context, &uval, flag)) != 0) 3177 return (returnstat); 3178 return (close_tag(context, TAG_ACEFLAGS)); 3179 } 3180 3181 static int 3182 pa_ace_who(pr_context_t *context, ace_t *ace, int status, int flag) 3183 { 3184 int returnstat; 3185 3186 if (status < 0) 3187 return (status); 3188 3189 /* 3190 * TRANSLATION_NOTE 3191 * ace->a_who refers to user id or group id of ZFS/NFSv4 ACL entry. 3192 */ 3193 if ((returnstat = open_tag(context, TAG_ACEID)) != 0) 3194 return (returnstat); 3195 switch (ace->a_flags & ACE_TYPE_FLAGS) { 3196 case ACE_IDENTIFIER_GROUP: /* group id */ 3197 returnstat = pa_print_gid(context, ace->a_who, returnstat, 3198 flag); 3199 break; 3200 default: /* user id */ 3201 returnstat = pa_print_uid(context, ace->a_who, returnstat, 3202 flag); 3203 break; 3204 } 3205 if (returnstat < 0) 3206 return (returnstat); 3207 return (close_tag(context, TAG_ACEID)); 3208 } 3209 3210 /* 3211 * Appends what to str, (re)allocating str if necessary. 3212 */ 3213 #define INITIAL_ALLOC 256 3214 static int 3215 strappend(char **str, char *what, size_t *alloc) 3216 { 3217 char *s, *newstr; 3218 size_t needed; 3219 3220 s = *str; 3221 3222 if (s == NULL) { 3223 s = malloc(INITIAL_ALLOC); 3224 if (s == NULL) { 3225 *alloc = 0; 3226 return (-1); 3227 } 3228 *alloc = INITIAL_ALLOC; 3229 s[0] = '\0'; 3230 *str = s; 3231 } 3232 3233 needed = strlen(s) + strlen(what) + 1; 3234 if (*alloc < needed) { 3235 newstr = realloc(s, needed); 3236 if (newstr == NULL) 3237 return (-1); 3238 s = newstr; 3239 *alloc = needed; 3240 *str = s; 3241 } 3242 (void) strlcat(s, what, *alloc); 3243 3244 return (0); 3245 } 3246 3247 static int 3248 pa_ace_access_mask(pr_context_t *context, ace_t *ace, int status, int flag) 3249 { 3250 int returnstat, i; 3251 uval_t uval; 3252 char *permstr = NULL; 3253 size_t permstr_alloc = 0; 3254 3255 if (status < 0) 3256 return (status); 3257 3258 /* 3259 * TRANSLATION_NOTE 3260 * ace->a_access_mask refers to access mask of ZFS/NFSv4 ACL entry. 3261 */ 3262 if ((returnstat = open_tag(context, TAG_ACEMASK)) != 0) 3263 return (returnstat); 3264 if (context->format & PRF_SHORTM && 3265 ((permstr = malloc(15)) != NULL)) { 3266 for (i = 0; i < 14; i++) 3267 permstr[i] = '-'; 3268 3269 if (ace->a_access_mask & ACE_READ_DATA) 3270 permstr[0] = 'r'; 3271 if (ace->a_access_mask & ACE_WRITE_DATA) 3272 permstr[1] = 'w'; 3273 if (ace->a_access_mask & ACE_EXECUTE) 3274 permstr[2] = 'x'; 3275 if (ace->a_access_mask & ACE_APPEND_DATA) 3276 permstr[3] = 'p'; 3277 if (ace->a_access_mask & ACE_DELETE) 3278 permstr[4] = 'd'; 3279 if (ace->a_access_mask & ACE_DELETE_CHILD) 3280 permstr[5] = 'D'; 3281 if (ace->a_access_mask & ACE_READ_ATTRIBUTES) 3282 permstr[6] = 'a'; 3283 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES) 3284 permstr[7] = 'A'; 3285 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS) 3286 permstr[8] = 'R'; 3287 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS) 3288 permstr[9] = 'W'; 3289 if (ace->a_access_mask & ACE_READ_ACL) 3290 permstr[10] = 'c'; 3291 if (ace->a_access_mask & ACE_WRITE_ACL) 3292 permstr[11] = 'C'; 3293 if (ace->a_access_mask & ACE_WRITE_OWNER) 3294 permstr[12] = 'o'; 3295 if (ace->a_access_mask & ACE_SYNCHRONIZE) 3296 permstr[13] = 's'; 3297 permstr[14] = '\0'; 3298 uval.uvaltype = PRA_STRING; 3299 uval.string_val = permstr; 3300 } else if (!(context->format & PRF_RAWM)) { 3301 3302 /* 3303 * Note this differs from acltext.c:ace_perm_txt() 3304 * because we don't know if the acl belongs to a file 3305 * or directory. ace mask value are the same 3306 * nonetheless, see sys/acl.h 3307 */ 3308 if (ace->a_access_mask & ACE_LIST_DIRECTORY) { 3309 returnstat = strappend(&permstr, gettext(READ_DIR_TXT), 3310 &permstr_alloc); 3311 } 3312 if (ace->a_access_mask & ACE_ADD_FILE) { 3313 returnstat = strappend(&permstr, gettext(ADD_FILE_TXT), 3314 &permstr_alloc); 3315 } 3316 if (ace->a_access_mask & ACE_ADD_SUBDIRECTORY) { 3317 returnstat = strappend(&permstr, gettext(ADD_DIR_TXT), 3318 &permstr_alloc); 3319 } 3320 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS) { 3321 returnstat = strappend(&permstr, 3322 gettext(READ_XATTR_TXT), &permstr_alloc); 3323 } 3324 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS) { 3325 returnstat = strappend(&permstr, 3326 gettext(WRITE_XATTR_TXT), &permstr_alloc); 3327 } 3328 if (ace->a_access_mask & ACE_EXECUTE) { 3329 returnstat = strappend(&permstr, 3330 gettext(EXECUTE_TXT), &permstr_alloc); 3331 } 3332 if (ace->a_access_mask & ACE_DELETE_CHILD) { 3333 returnstat = strappend(&permstr, 3334 gettext(DELETE_CHILD_TXT), &permstr_alloc); 3335 } 3336 if (ace->a_access_mask & ACE_READ_ATTRIBUTES) { 3337 returnstat = strappend(&permstr, 3338 gettext(READ_ATTRIBUTES_TXT), &permstr_alloc); 3339 } 3340 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES) { 3341 returnstat = strappend(&permstr, 3342 gettext(WRITE_ATTRIBUTES_TXT), &permstr_alloc); 3343 } 3344 if (ace->a_access_mask & ACE_DELETE) { 3345 returnstat = strappend(&permstr, gettext(DELETE_TXT), 3346 &permstr_alloc); 3347 } 3348 if (ace->a_access_mask & ACE_READ_ACL) { 3349 returnstat = strappend(&permstr, gettext(READ_ACL_TXT), 3350 &permstr_alloc); 3351 } 3352 if (ace->a_access_mask & ACE_WRITE_ACL) { 3353 returnstat = strappend(&permstr, gettext(WRITE_ACL_TXT), 3354 &permstr_alloc); 3355 } 3356 if (ace->a_access_mask & ACE_WRITE_OWNER) { 3357 returnstat = strappend(&permstr, 3358 gettext(WRITE_OWNER_TXT), &permstr_alloc); 3359 } 3360 if (ace->a_access_mask & ACE_SYNCHRONIZE) { 3361 returnstat = strappend(&permstr, 3362 gettext(SYNCHRONIZE_TXT), &permstr_alloc); 3363 } 3364 if (permstr[strlen(permstr) - 1] == '/') 3365 permstr[strlen(permstr) - 1] = '\0'; 3366 uval.uvaltype = PRA_STRING; 3367 uval.string_val = permstr; 3368 } 3369 if ((permstr == NULL) || (returnstat != 0) || 3370 (context->format & PRF_RAWM)) { 3371 uval.uvaltype = PRA_UINT32; 3372 uval.uint32_val = ace->a_access_mask; 3373 } 3374 returnstat = pa_print(context, &uval, flag); 3375 3376 if (permstr != NULL) 3377 free(permstr); 3378 if (returnstat != 0) 3379 return (returnstat); 3380 return (close_tag(context, TAG_ACEMASK)); 3381 } 3382 3383 static int 3384 pa_ace_type(pr_context_t *context, ace_t *ace, int status, int flag) 3385 { 3386 int returnstat; 3387 uval_t uval; 3388 3389 if (status < 0) 3390 return (status); 3391 3392 /* 3393 * TRANSLATION_NOTE 3394 * ace->a_type refers to access type of ZFS/NFSv4 ACL entry. 3395 */ 3396 if ((returnstat = open_tag(context, TAG_ACETYPE)) != 0) 3397 return (returnstat); 3398 if (!(context->format & PRF_RAWM)) { 3399 uval.uvaltype = PRA_STRING; 3400 switch (ace->a_type) { 3401 case ACE_ACCESS_ALLOWED_ACE_TYPE: 3402 uval.string_val = gettext(ALLOW_TXT); 3403 break; 3404 case ACE_ACCESS_DENIED_ACE_TYPE: 3405 uval.string_val = gettext(DENY_TXT); 3406 break; 3407 case ACE_SYSTEM_AUDIT_ACE_TYPE: 3408 uval.string_val = gettext(AUDIT_TXT); 3409 break; 3410 case ACE_SYSTEM_ALARM_ACE_TYPE: 3411 uval.string_val = gettext(ALARM_TXT); 3412 break; 3413 default: 3414 uval.string_val = gettext(UNKNOWN_TXT); 3415 } 3416 } else { 3417 uval.uvaltype = PRA_USHORT; 3418 uval.uint32_val = ace->a_type; 3419 } 3420 if ((returnstat = pa_print(context, &uval, flag)) != 0) 3421 return (returnstat); 3422 return (close_tag(context, TAG_ACETYPE)); 3423 } 3424 3425 int 3426 pa_ace(pr_context_t *context, int status, int flag) 3427 { 3428 int returnstat; 3429 ace_t ace; 3430 3431 if (status < 0) 3432 return (status); 3433 3434 if ((returnstat = pr_adr_u_int32(context, &ace.a_who, 1)) != 0) 3435 return (returnstat); 3436 if ((returnstat = pr_adr_u_int32(context, &ace.a_access_mask, 1)) != 0) 3437 return (returnstat); 3438 if ((returnstat = pr_adr_u_short(context, &ace.a_flags, 1)) != 0) 3439 return (returnstat); 3440 if ((returnstat = pr_adr_u_short(context, &ace.a_type, 1)) != 0) 3441 return (returnstat); 3442 3443 if ((returnstat = pa_ace_flags(context, &ace, returnstat, 0)) != 0) 3444 return (returnstat); 3445 /* pa_ace_who can returns 1 if uid/gid is not found */ 3446 if ((returnstat = pa_ace_who(context, &ace, returnstat, 0)) < 0) 3447 return (returnstat); 3448 if ((returnstat = pa_ace_access_mask(context, &ace, 3449 returnstat, 0)) != 0) 3450 return (returnstat); 3451 return (pa_ace_type(context, &ace, returnstat, flag)); 3452 } 3453