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