8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / praudit / format.c
blob3acd370513328f1c6ea63ee8726d7b4341d9bc6f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #define _REENTRANT
29 #include <ctype.h>
30 #include <errno.h>
31 #include <grp.h>
32 #include <libintl.h>
33 #include <netdb.h>
34 #include <time.h>
35 #include <pwd.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <wchar.h>
41 #include <arpa/inet.h>
43 #include <bsm/audit.h>
44 #include <bsm/audit_record.h>
45 #include <bsm/libbsm.h>
46 #include <security/pam_appl.h>
48 #include <sys/inttypes.h>
49 #include <sys/mkdev.h>
50 #include <sys/types.h>
51 #include <aclutils.h>
53 #include "praudit.h"
54 #include "toktable.h"
55 #include "adt_xlate.h"
57 static void convertascii(char *p, char *c, int size);
58 static int convertbinary(char *p, char *c, int size);
59 static void eventmodifier2string(au_emod_t emodifier, char *modstring,
60 size_t modlen);
61 static int do_mtime32(pr_context_t *context, int status, int flag,
62 uint32_t scale);
63 static int do_mtime64(pr_context_t *context, int status, int flag,
64 uint64_t scale);
67 * ------------------------------------------------------
68 * field widths for arbitrary data token type
69 * ------------------------------------------------------
71 static struct fw {
72 char basic_unit;
73 struct {
74 char print_base;
75 int field_width;
76 } pwidth[5];
77 } fwidth[] = {
78 /* character data type, 8 bits */
79 AUR_CHAR, AUP_BINARY, 12,
80 AUP_OCTAL, 6,
81 AUP_DECIMAL, 6,
82 AUP_HEX, 6,
83 AUP_STRING, 1,
84 AUR_BYTE, AUP_BINARY, 12,
85 AUP_OCTAL, 6,
86 AUP_DECIMAL, 6,
87 AUP_HEX, 6,
88 AUP_STRING, 1,
89 AUR_SHORT, AUP_BINARY, 20,
90 AUP_OCTAL, 10,
91 AUP_DECIMAL, 10,
92 AUP_HEX, 8,
93 AUP_STRING, 6,
94 AUR_INT32, AUP_BINARY, 36,
95 AUP_OCTAL, 18,
96 AUP_DECIMAL, 18,
97 AUP_HEX, 12,
98 AUP_STRING, 10,
99 AUR_INT64, AUP_BINARY, 68,
100 AUP_OCTAL, 34,
101 AUP_DECIMAL, 34,
102 AUP_HEX, 20,
103 AUP_STRING, 20};
106 static int numwidthentries = sizeof (fwidth)
107 / sizeof (struct fw);
111 * -----------------------------------------------------------------------
112 * do_newline:
113 * Print a newline, if needed according to various formatting
114 * rules.
115 * return codes : 0 - success
116 * : -1 - error
117 * -----------------------------------------------------------------------
120 do_newline(pr_context_t *context, int flag)
122 int retstat = 0;
124 if (!(context->format & PRF_ONELINE) && (flag == 1))
125 retstat = pr_putchar(context, '\n');
126 else if (!(context->format & PRF_XMLM))
127 retstat = pr_printf(context, "%s", context->SEPARATOR);
129 return (retstat);
133 open_tag(pr_context_t *context, int tagnum)
135 int err = 0;
136 token_desc_t *tag;
138 /* no-op if not doing XML format */
139 if (!(context->format & PRF_XMLM))
140 return (0);
142 tag = &tokentable[tagnum];
145 * First if needed do an implicit finish of a pending open for an
146 * extended tag. I.e., for the extended tag xxx:
147 * <xxx a=".." b=".."> ... </xxx>
148 * -- insert a close bracket after the last attribute
149 * (in other words, when the 1st non-attribute is opened while
150 * this is pending). Note that only one tag could be pending at
151 * a given time -- it couldn't be nested.
153 if (context->pending_flag && (tag->t_type != T_ATTRIBUTE)) {
154 /* complete pending extended open */
155 err = pr_putchar(context, '>');
156 if (err != 0)
157 return (err);
158 context->pending_flag = 0;
161 if (is_header_token(tagnum) || is_file_token(tagnum)) {
162 /* File token or new record on new line */
163 err = pr_putchar(context, '\n');
164 } else if (is_token(tagnum)) {
165 /* Each token on new line if possible */
166 err = do_newline(context, 1);
168 if (err != 0)
169 return (err);
171 switch (tag->t_type) {
172 case T_ATTRIBUTE:
173 err = pr_printf(context, " %s=\"", tag->t_tagname);
174 break;
175 case T_ELEMENT:
176 err = pr_printf(context, "<%s>", tag->t_tagname);
177 break;
178 case T_ENCLOSED:
179 err = pr_printf(context, "<%s", tag->t_tagname);
180 break;
181 case T_EXTENDED:
182 err = pr_printf(context, "<%s", tag->t_tagname);
183 if (err == 0)
184 context->pending_flag = tagnum;
185 break;
186 default:
187 break;
190 if (is_header_token(tagnum) && (err == 0))
191 context->current_rec = tagnum; /* set start of new record */
193 return (err);
197 * Do an implicit close of a record when needed.
200 check_close_rec(pr_context_t *context, int tagnum)
202 int err = 0;
204 /* no-op if not doing XML format */
205 if (!(context->format & PRF_XMLM))
206 return (0);
209 * If we're opening a header or the file token (i.e., starting a new
210 * record), if there's a current record in progress do an implicit
211 * close of it.
213 if ((is_header_token(tagnum) || is_file_token(tagnum)) &&
214 context->current_rec) {
215 err = do_newline(context, 1);
216 if (err == 0)
217 err = close_tag(context, context->current_rec);
220 return (err);
224 * explicit finish of a pending open for an extended tag.
227 finish_open_tag(pr_context_t *context)
229 int err = 0;
231 /* no-op if not doing XML format */
232 if (!(context->format & PRF_XMLM))
233 return (0);
235 if (context->pending_flag) {
236 /* complete pending extended open */
237 err = pr_putchar(context, '>');
238 if (err == 0)
239 context->pending_flag = 0;
241 return (err);
245 close_tag(pr_context_t *context, int tagnum)
247 int err = 0;
248 token_desc_t *tag;
250 /* no-op if not doing XML format */
251 if (!(context->format & PRF_XMLM))
252 return (0);
254 tag = &tokentable[tagnum];
256 switch (tag->t_type) {
257 case T_ATTRIBUTE:
258 err = pr_putchar(context, '\"');
259 break;
260 case T_ELEMENT:
261 err = pr_printf(context, "</%s>", tag->t_tagname);
262 break;
263 case T_ENCLOSED:
264 err = pr_printf(context, "/>");
265 break;
266 case T_EXTENDED:
267 err = pr_printf(context, "</%s>", tag->t_tagname);
268 break;
269 default:
270 break;
273 if (is_header_token(tagnum) && (err == 0))
274 context->current_rec = 0; /* closing rec; none current */
276 return (err);
280 * -----------------------------------------------------------------------
281 * process_tag:
282 * Calls the routine corresponding to the tag
283 * Note that to use this mechanism, all such routines must
284 * take 2 ints for their parameters; the first of these is
285 * the current status.
287 * flag = 1 for newline / delimiter, else 0
288 * return codes : -1 - error
289 * : 0 - successful
290 * -----------------------------------------------------------------------
293 process_tag(pr_context_t *context, int tagnum, int status, int flag)
295 int retstat;
297 retstat = status;
299 if (retstat)
300 return (retstat);
302 if ((tagnum > 0) && (tagnum <= MAXTAG) &&
303 (tokentable[tagnum].func != NOFUNC)) {
304 retstat = open_tag(context, tagnum);
305 if (!retstat)
306 retstat = (*tokentable[tagnum].func)(context, status,
307 flag);
308 if (!retstat)
309 retstat = close_tag(context, tagnum);
310 return (retstat);
312 /* here if token id is not in table */
313 (void) fprintf(stderr, gettext("praudit: No code associated with "
314 "tag id %d\n"), tagnum);
315 return (0);
318 void
319 get_Hname(uint32_t addr, char *buf, size_t buflen)
321 extern char *inet_ntoa(const struct in_addr);
322 struct hostent *phe;
323 struct in_addr ia;
325 phe = gethostbyaddr((const char *)&addr, 4, AF_INET);
326 if (phe == (struct hostent *)0) {
327 ia.s_addr = addr;
328 (void) snprintf(buf, buflen, "%s", inet_ntoa(ia));
329 return;
331 ia.s_addr = addr;
332 (void) snprintf(buf, buflen, "%s", phe->h_name);
335 void
336 get_Hname_ex(uint32_t *addr, char *buf, size_t buflen)
338 struct hostent *phe;
339 int err;
341 phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
343 if (phe == (struct hostent *)0) {
344 (void) inet_ntop(AF_INET6, (void *)addr, buf, buflen);
345 } else
346 (void) snprintf(buf, buflen, "%s", phe->h_name);
348 if (phe)
349 freehostent(phe);
353 pa_hostname(pr_context_t *context, int status, int flag)
355 int returnstat;
356 uint32_t ip_addr;
357 struct in_addr ia;
358 uval_t uval;
359 char buf[256];
361 if (status < 0)
362 return (status);
364 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
365 return (returnstat);
367 uval.uvaltype = PRA_STRING;
369 if (!(context->format & PRF_RAWM)) {
370 uval.string_val = buf;
371 get_Hname(ip_addr, buf, sizeof (buf));
372 returnstat = pa_print(context, &uval, flag);
373 } else {
374 ia.s_addr = ip_addr;
375 if ((uval.string_val = inet_ntoa(ia)) == NULL)
376 return (-1);
377 returnstat = pa_print(context, &uval, flag);
379 return (returnstat);
383 pa_hostname_ex(pr_context_t *context, int status, int flag)
385 int returnstat;
386 uint32_t ip_type;
387 uint32_t ip_addr[4];
388 struct in_addr ia;
389 char buf[256];
390 uval_t uval;
392 if (status < 0)
393 return (status);
395 /* get ip type */
396 if ((returnstat = pr_adr_int32(context, (int32_t *)&ip_type, 1)) != 0)
397 return (returnstat);
399 /* only IPv4 and IPv6 addresses are legal */
400 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
401 return (-1);
403 /* get ip address */
404 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
405 return (returnstat);
407 if ((returnstat = open_tag(context, TAG_HOSTID)) != 0)
408 return (returnstat);
410 uval.uvaltype = PRA_STRING;
411 if (ip_type == AU_IPv4) { /* ipv4 address */
412 if (!(context->format & PRF_RAWM)) {
413 uval.string_val = buf;
414 get_Hname(ip_addr[0], buf, sizeof (buf));
415 returnstat = pa_print(context, &uval, flag);
416 } else {
417 ia.s_addr = ip_addr[0];
418 if ((uval.string_val = inet_ntoa(ia)) == NULL)
419 return (-1);
420 returnstat = pa_print(context, &uval, flag);
422 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
423 if (!(context->format & PRF_RAWM)) {
424 uval.string_val = buf;
425 get_Hname_ex(ip_addr, buf, sizeof (buf));
426 returnstat = pa_print(context, &uval, flag);
427 } else {
428 uval.string_val = (char *)buf;
429 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
430 sizeof (buf));
431 returnstat = pa_print(context, &uval, flag);
435 if (returnstat != 0)
436 return (returnstat);
437 return (close_tag(context, TAG_HOSTID));
441 pa_hostname_so(pr_context_t *context, int status, int flag)
443 int returnstat;
444 short ip_type;
445 ushort_t ip_port;
446 uint32_t ip_addr[4];
447 struct in_addr ia;
448 char buf[256];
449 uval_t uval;
451 if (status < 0)
452 return (status);
454 /* get ip type */
455 if ((returnstat = pr_adr_short(context, &ip_type, 1)) != 0)
456 return (returnstat);
458 /* only IPv4 and IPv6 addresses are legal */
459 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
460 return (-1);
462 /* get local ip port */
463 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
464 return (returnstat);
466 if ((returnstat = open_tag(context, TAG_SOCKEXLPORT)) != 0)
467 return (returnstat);
469 uval.uvaltype = PRA_STRING;
470 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
471 sizeof (ip_port));
472 if (uval.string_val) {
473 returnstat = pa_print(context, &uval, 0);
474 free(uval.string_val);
475 } else
476 returnstat = -1;
477 if (returnstat)
478 return (returnstat);
480 if ((returnstat = close_tag(context, TAG_SOCKEXLPORT)) != 0)
481 return (returnstat);
483 /* get local ip address */
484 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
485 return (returnstat);
487 if ((returnstat = open_tag(context, TAG_SOCKEXLADDR)) != 0)
488 return (returnstat);
490 if (ip_type == AU_IPv4) { /* ipv4 address */
492 if (!(context->format & PRF_RAWM)) {
493 uval.string_val = buf;
494 get_Hname(ip_addr[0], buf, sizeof (buf));
495 returnstat = pa_print(context, &uval, 0);
496 } else {
497 ia.s_addr = ip_addr[0];
498 if ((uval.string_val = inet_ntoa(ia)) == NULL)
499 return (-1);
500 returnstat = pa_print(context, &uval, 0);
503 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
505 if (!(context->format & PRF_RAWM)) {
506 uval.string_val = buf;
507 get_Hname_ex(ip_addr, buf, sizeof (buf));
508 returnstat = pa_print(context, &uval, 0);
509 } else {
510 uval.string_val = (char *)buf;
511 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
512 sizeof (buf));
513 returnstat = pa_print(context, &uval, 0);
515 } else
516 returnstat = -1;
518 if (returnstat)
519 return (returnstat);
521 if ((returnstat = close_tag(context, TAG_SOCKEXLADDR)) != 0)
522 return (returnstat);
524 /* get foreign ip port */
525 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
526 return (returnstat);
528 if ((returnstat = open_tag(context, TAG_SOCKEXFPORT)) != 0)
529 return (returnstat);
531 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
532 sizeof (ip_port));
533 if (uval.string_val) {
534 returnstat = pa_print(context, &uval, 0);
535 free(uval.string_val);
536 } else
537 returnstat = -1;
539 if (returnstat)
540 return (returnstat);
542 if ((returnstat = close_tag(context, TAG_SOCKEXFPORT)) != 0)
543 return (returnstat);
545 /* get foreign ip address */
546 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
547 return (returnstat);
549 if ((returnstat = open_tag(context, TAG_SOCKEXFADDR)) != 0)
550 return (returnstat);
552 if (ip_type == AU_IPv4) { /* ipv4 address */
554 if (!(context->format & PRF_RAWM)) {
555 uval.string_val = buf;
556 get_Hname(ip_addr[0], buf, sizeof (buf));
557 returnstat = pa_print(context, &uval, flag);
558 } else {
559 ia.s_addr = ip_addr[0];
560 if ((uval.string_val = inet_ntoa(ia)) == NULL)
561 return (-1);
562 returnstat = pa_print(context, &uval, flag);
565 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
567 if (!(context->format & PRF_RAWM)) {
568 uval.string_val = buf;
569 get_Hname_ex(ip_addr, buf, sizeof (buf));
570 returnstat = pa_print(context, &uval, flag);
571 } else {
572 uval.string_val = (char *)buf;
573 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
574 sizeof (buf));
575 returnstat = pa_print(context, &uval, flag);
577 } else
578 returnstat = -1;
580 if (returnstat)
581 return (returnstat);
583 if ((returnstat = close_tag(context, TAG_SOCKEXFADDR)) != 0)
584 return (returnstat);
586 return (returnstat);
590 #define NBITSMAJOR64 32 /* # of major device bits in 64-bit Solaris */
591 #define NBITSMINOR64 32 /* # of minor device bits in 64-bit Solaris */
592 #define MAXMAJ64 0xfffffffful /* max major value */
593 #define MAXMIN64 0xfffffffful /* max minor value */
595 #define NBITSMAJOR32 14 /* # of SVR4 major device bits */
596 #define NBITSMINOR32 18 /* # of SVR4 minor device bits */
597 #define NMAXMAJ32 0x3fff /* SVR4 max major value */
598 #define NMAXMIN32 0x3ffff /* MAX minor for 3b2 software drivers. */
601 static int32_t
602 minor_64(uint64_t dev)
604 if (dev == NODEV) {
605 errno = EINVAL;
606 return (NODEV);
608 return (int32_t)(dev & MAXMIN64);
611 static int32_t
612 major_64(uint64_t dev)
614 uint32_t maj;
616 maj = (uint32_t)(dev >> NBITSMINOR64);
618 if (dev == NODEV || maj > MAXMAJ64) {
619 errno = EINVAL;
620 return (NODEV);
622 return (int32_t)(maj);
625 static int32_t
626 minor_32(uint32_t dev)
628 if (dev == NODEV) {
629 errno = EINVAL;
630 return (NODEV);
632 return (int32_t)(dev & MAXMIN32);
635 static int32_t
636 major_32(uint32_t dev)
638 uint32_t maj;
640 maj = (uint32_t)(dev >> NBITSMINOR32);
642 if (dev == NODEV || maj > MAXMAJ32) {
643 errno = EINVAL;
644 return (NODEV);
646 return (int32_t)(maj);
651 * -----------------------------------------------------------------------
652 * pa_tid() : Process terminal id and display contents
653 * return codes : -1 - error
654 * : 0 - successful
656 * terminal id port adr_int32
657 * terminal id machine adr_int32
658 * -----------------------------------------------------------------------
661 pa_tid32(pr_context_t *context, int status, int flag)
663 int returnstat;
664 int32_t dev_maj_min;
665 uint32_t ip_addr;
666 struct in_addr ia;
667 char *ipstring;
668 char buf[256];
669 uval_t uval;
671 if (status < 0)
672 return (status);
674 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
675 return (returnstat);
677 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
678 return (returnstat);
680 uval.uvaltype = PRA_STRING;
681 uval.string_val = buf;
683 if (!(context->format & PRF_RAWM)) {
684 char hostname[256];
686 get_Hname(ip_addr, hostname, sizeof (hostname));
687 (void) snprintf(buf, sizeof (buf), "%d %d %s",
688 major_32(dev_maj_min),
689 minor_32(dev_maj_min),
690 hostname);
691 return (pa_print(context, &uval, flag));
694 ia.s_addr = ip_addr;
695 if ((ipstring = inet_ntoa(ia)) == NULL)
696 return (-1);
698 (void) snprintf(buf, sizeof (buf), "%d %d %s", major_32(dev_maj_min),
699 minor_32(dev_maj_min),
700 ipstring);
702 return (pa_print(context, &uval, flag));
706 pa_tid32_ex(pr_context_t *context, int status, int flag)
708 int returnstat;
709 int32_t dev_maj_min;
710 uint32_t ip_addr[16];
711 uint32_t ip_type;
712 struct in_addr ia;
713 char *ipstring;
714 char hostname[256];
715 char buf[256];
716 char tbuf[256];
717 uval_t uval;
719 if (status < 0)
720 return (status);
722 /* get port info */
723 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
724 return (returnstat);
726 /* get address type */
727 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
728 return (returnstat);
730 /* legal address types are either AU_IPv4 or AU_IPv6 only */
731 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
732 return (-1);
734 /* get address (4/16) */
735 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
736 return (returnstat);
738 uval.uvaltype = PRA_STRING;
739 if (ip_type == AU_IPv4) {
740 uval.string_val = buf;
742 if (!(context->format & PRF_RAWM)) {
743 get_Hname(ip_addr[0], hostname, sizeof (hostname));
744 (void) snprintf(buf, sizeof (buf), "%d %d %s",
745 major_32(dev_maj_min), minor_32(dev_maj_min),
746 hostname);
747 return (pa_print(context, &uval, flag));
750 ia.s_addr = ip_addr[0];
751 if ((ipstring = inet_ntoa(ia)) == NULL)
752 return (-1);
754 (void) snprintf(buf, sizeof (buf), "%d %d %s",
755 major_32(dev_maj_min), minor_32(dev_maj_min), ipstring);
757 return (pa_print(context, &uval, flag));
758 } else {
759 uval.string_val = buf;
761 if (!(context->format & PRF_RAWM)) {
762 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
763 (void) snprintf(buf, sizeof (buf), "%d %d %s",
764 major_32(dev_maj_min), minor_32(dev_maj_min),
765 hostname);
766 return (pa_print(context, &uval, flag));
769 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
770 sizeof (tbuf));
772 (void) snprintf(buf, sizeof (buf), "%d %d %s",
773 major_32(dev_maj_min), minor_32(dev_maj_min), tbuf);
775 return (pa_print(context, &uval, flag));
780 pa_ip_addr(pr_context_t *context, int status, int flag)
782 int returnstat;
783 uval_t uval;
784 uint32_t ip_addr[4];
785 uint32_t ip_type;
786 struct in_addr ia;
787 char *ipstring;
788 char hostname[256];
789 char buf[256];
790 char tbuf[256];
792 if (status < 0)
793 return (status);
795 /* get address type */
796 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
797 return (returnstat);
799 /* legal address type is AU_IPv4 or AU_IPv6 */
800 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
801 return (-1);
803 /* get address (4/16) */
804 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
805 return (returnstat);
807 uval.uvaltype = PRA_STRING;
808 if (ip_type == AU_IPv4) {
809 uval.string_val = buf;
811 if (!(context->format & PRF_RAWM)) {
812 get_Hname(ip_addr[0], hostname, sizeof (hostname));
813 (void) snprintf(buf, sizeof (buf), "%s", hostname);
814 return (pa_print(context, &uval, flag));
817 ia.s_addr = ip_addr[0];
818 if ((ipstring = inet_ntoa(ia)) == NULL)
819 return (-1);
821 (void) snprintf(buf, sizeof (buf), "%s", ipstring);
823 return (pa_print(context, &uval, flag));
824 } else {
825 uval.string_val = buf;
827 if (!(context->format & PRF_RAWM)) {
828 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
829 (void) snprintf(buf, sizeof (buf), "%s",
830 hostname);
831 return (pa_print(context, &uval, flag));
834 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
835 sizeof (tbuf));
837 (void) snprintf(buf, sizeof (buf), "%s", tbuf);
839 return (pa_print(context, &uval, flag));
845 pa_tid64(pr_context_t *context, int status, int flag)
847 int returnstat;
848 int64_t dev_maj_min;
849 uint32_t ip_addr;
850 struct in_addr ia;
851 char *ipstring;
852 char buf[256];
853 uval_t uval;
855 if (status < 0)
856 return (status);
858 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
859 return (returnstat);
861 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
862 return (returnstat);
864 uval.uvaltype = PRA_STRING;
865 uval.string_val = buf;
867 if (!(context->format & PRF_RAWM)) {
868 char hostname[256];
870 get_Hname(ip_addr, hostname, sizeof (hostname));
871 (void) snprintf(buf, sizeof (buf), "%d %d %s",
872 major_64(dev_maj_min), minor_64(dev_maj_min), hostname);
873 return (pa_print(context, &uval, flag));
876 ia.s_addr = ip_addr;
877 if ((ipstring = inet_ntoa(ia)) == NULL)
878 return (-1);
880 (void) snprintf(buf, sizeof (buf), "%d %d %s",
881 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
883 return (pa_print(context, &uval, flag));
887 pa_tid64_ex(pr_context_t *context, int status, int flag)
889 int returnstat;
890 int64_t dev_maj_min;
891 uint32_t ip_addr[4];
892 uint32_t ip_type;
893 struct in_addr ia;
894 char *ipstring;
895 char hostname[256];
896 char buf[256];
897 char tbuf[256];
898 uval_t uval;
900 if (status < 0)
901 return (status);
903 /* get port info */
904 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
905 return (returnstat);
907 /* get address type */
908 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
909 return (returnstat);
911 /* legal address types are either AU_IPv4 or AU_IPv6 only */
912 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
913 return (-1);
915 /* get address (4/16) */
916 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, ip_type)) != 0)
917 return (returnstat);
919 uval.uvaltype = PRA_STRING;
920 if (ip_type == AU_IPv4) {
921 uval.string_val = buf;
923 if (!(context->format & PRF_RAWM)) {
924 get_Hname(ip_addr[0], hostname, sizeof (hostname));
925 uval.string_val = buf;
926 (void) snprintf(buf, sizeof (buf), "%d %d %s",
927 major_64(dev_maj_min), minor_64(dev_maj_min),
928 hostname);
929 return (pa_print(context, &uval, flag));
932 ia.s_addr = ip_addr[0];
933 if ((ipstring = inet_ntoa(ia)) == NULL)
934 return (-1);
936 (void) snprintf(buf, sizeof (buf), "%d %d %s",
937 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
939 return (pa_print(context, &uval, flag));
940 } else {
941 uval.string_val = buf;
943 if (!(context->format & PRF_RAWM)) {
944 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
945 (void) snprintf(buf, sizeof (buf), "%d %d %s",
946 major_64(dev_maj_min), minor_64(dev_maj_min),
947 hostname);
948 return (pa_print(context, &uval, flag));
951 (void) inet_ntop(AF_INET6, (void *)ip_addr, tbuf,
952 sizeof (tbuf));
954 (void) snprintf(buf, sizeof (buf), "%d %d %s",
955 major_64(dev_maj_min), minor_64(dev_maj_min), tbuf);
957 return (pa_print(context, &uval, flag));
963 * ----------------------------------------------------------------
964 * findfieldwidth:
965 * Returns the field width based on the basic unit and print mode.
966 * This routine is called to determine the field width for the
967 * data items in the arbitrary data token where the tokens are
968 * to be printed in more than one line. The field width can be
969 * found in the fwidth structure.
971 * Input parameters:
972 * basicunit Can be one of AUR_CHAR, AUR_BYTE, AUR_SHORT,
973 * AUR_INT32, or AUR_INT64
974 * howtoprint Print mode. Can be one of AUP_BINARY, AUP_OCTAL,
975 * AUP_DECIMAL, or AUP_HEX.
976 * ----------------------------------------------------------------
979 findfieldwidth(char basicunit, char howtoprint)
981 int i, j;
983 for (i = 0; i < numwidthentries; i++) {
984 if (fwidth[i].basic_unit == basicunit) {
985 for (j = 0; j <= 4; j++) {
986 if (fwidth[i].pwidth[j].print_base ==
987 howtoprint) {
988 return (
989 fwidth[i].pwidth[j].field_width);
993 * if we got here, then we didn't get what we were after
995 return (0);
998 /* if we got here, we didn't get what we wanted either */
999 return (0);
1004 * -----------------------------------------------------------------------
1005 * pa_cmd: Retrieves the cmd item from the input stream.
1006 * return codes : -1 - error
1007 * : 0 - successful
1008 * -----------------------------------------------------------------------
1011 pa_cmd(pr_context_t *context, int status, int flag)
1013 char *cmd; /* cmd */
1014 short length;
1015 int returnstat;
1016 uval_t uval;
1019 * We need to know how much space to allocate for our string, so
1020 * read the length first, then call pr_adr_char to read those bytes.
1022 if (status >= 0) {
1023 if (pr_adr_short(context, &length, 1) == 0) {
1024 if ((cmd = (char *)malloc(length + 1)) == NULL)
1025 return (-1);
1026 if (pr_adr_char(context, cmd, length) == 0) {
1027 uval.uvaltype = PRA_STRING;
1028 uval.string_val = cmd;
1029 returnstat = pa_print(context, &uval, flag);
1030 } else {
1031 returnstat = -1;
1033 free(cmd);
1034 return (returnstat);
1035 } else
1036 return (-1);
1037 } else
1038 return (status);
1044 * -----------------------------------------------------------------------
1045 * pa_adr_byte : Issues pr_adr_char to retrieve the next ADR item from
1046 * the input stream pointed to by audit_adr, and prints it
1047 * as an integer if status >= 0
1048 * return codes : -1 - error
1049 * : 0 - successful
1050 * -----------------------------------------------------------------------
1053 pa_adr_byte(pr_context_t *context, int status, int flag)
1055 char c;
1056 uval_t uval;
1058 if (status >= 0) {
1059 if (pr_adr_char(context, &c, 1) == 0) {
1060 uval.uvaltype = PRA_BYTE;
1061 uval.char_val = c;
1062 return (pa_print(context, &uval, flag));
1063 } else
1064 return (-1);
1065 } else
1066 return (status);
1070 * -----------------------------------------------------------------------
1071 * pa_adr_charhex: Issues pr_adr_char to retrieve the next ADR item from
1072 * the input stream pointed to by audit_adr, and prints it
1073 * in hexadecimal if status >= 0
1074 * return codes : -1 - error
1075 * : 0 - successful
1076 * -----------------------------------------------------------------------
1079 pa_adr_charhex(pr_context_t *context, int status, int flag)
1081 char p[2];
1082 int returnstat;
1083 uval_t uval;
1085 if (status >= 0) {
1086 p[0] = p[1] = 0;
1088 if ((returnstat = pr_adr_char(context, p, 1)) == 0) {
1089 uval.uvaltype = PRA_STRING;
1090 uval.string_val = hexconvert(p, sizeof (char),
1091 sizeof (char));
1092 if (uval.string_val) {
1093 returnstat = pa_print(context, &uval, flag);
1094 free(uval.string_val);
1097 return (returnstat);
1098 } else
1099 return (status);
1103 * -----------------------------------------------------------------------
1104 * pa_adr_int32 : Issues pr_adr_int32 to retrieve the next ADR item from the
1105 * input stream pointed to by audit_adr, and prints it
1106 * if status >= 0
1107 * return codes : -1 - error
1108 * : 0 - successful
1109 * -----------------------------------------------------------------------
1112 pa_adr_int32(pr_context_t *context, int status, int flag)
1114 int32_t c;
1115 uval_t uval;
1117 if (status >= 0) {
1118 if (pr_adr_int32(context, &c, 1) == 0) {
1119 uval.uvaltype = PRA_INT32;
1120 uval.int32_val = c;
1121 return (pa_print(context, &uval, flag));
1122 } else
1123 return (-1);
1124 } else
1125 return (status);
1132 * -----------------------------------------------------------------------
1133 * pa_adr_int64 : Issues pr_adr_int64 to retrieve the next ADR item from the
1134 * input stream pointed to by audit_adr, and prints it
1135 * if status >= 0
1136 * return codes : -1 - error
1137 * : 0 - successful
1138 * -----------------------------------------------------------------------
1141 pa_adr_int64(pr_context_t *context, int status, int flag)
1143 int64_t c;
1144 uval_t uval;
1146 if (status >= 0) {
1147 if (pr_adr_int64(context, &c, 1) == 0) {
1148 uval.uvaltype = PRA_INT64;
1149 uval.int64_val = c;
1150 return (pa_print(context, &uval, flag));
1151 } else
1152 return (-1);
1153 } else
1154 return (status);
1158 * -----------------------------------------------------------------------
1159 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1160 * input stream pointed to by audit_adr, and prints it
1161 * in hexadecimal if status >= 0
1162 * return codes : -1 - error
1163 * : 0 - successful
1164 * -----------------------------------------------------------------------
1167 pa_adr_int32hex(pr_context_t *context, int status, int flag)
1169 int32_t l;
1170 int returnstat;
1171 uval_t uval;
1173 if (status >= 0) {
1174 if ((returnstat = pr_adr_int32(context, &l, 1)) == 0) {
1175 uval.uvaltype = PRA_HEX32;
1176 uval.int32_val = l;
1177 returnstat = pa_print(context, &uval, flag);
1179 return (returnstat);
1180 } else
1181 return (status);
1185 * -----------------------------------------------------------------------
1186 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1187 * input stream pointed to by audit_adr, and prints it
1188 * in hexadecimal if status >= 0
1189 * return codes : -1 - error
1190 * : 0 - successful
1191 * -----------------------------------------------------------------------
1194 pa_adr_int64hex(pr_context_t *context, int status, int flag)
1196 int64_t l;
1197 int returnstat;
1198 uval_t uval;
1200 if (status >= 0) {
1201 if ((returnstat = pr_adr_int64(context, &l, 1)) == 0) {
1202 uval.uvaltype = PRA_HEX64;
1203 uval.int64_val = l;
1204 returnstat = pa_print(context, &uval, flag);
1206 return (returnstat);
1207 } else
1208 return (status);
1213 * -------------------------------------------------------------------
1214 * bu2string: Maps a print basic unit type to a string.
1215 * returns : The string mapping or "unknown basic unit type".
1216 * -------------------------------------------------------------------
1218 char *
1219 bu2string(char basic_unit)
1221 register int i;
1223 struct bu_map_ent {
1224 char basic_unit;
1225 char *string;
1229 * TRANSLATION_NOTE
1230 * These names are data units when displaying the arbitrary data
1231 * token.
1234 static struct bu_map_ent bu_map[] = {
1235 { AUR_BYTE, "byte" },
1236 { AUR_CHAR, "char" },
1237 { AUR_SHORT, "short" },
1238 { AUR_INT32, "int32" },
1239 { AUR_INT64, "int64" } };
1241 for (i = 0; i < sizeof (bu_map) / sizeof (struct bu_map_ent); i++)
1242 if (basic_unit == bu_map[i].basic_unit)
1243 return (gettext(bu_map[i].string));
1245 return (gettext("unknown basic unit type"));
1250 * -------------------------------------------------------------------
1251 * eventmodifier2string: Maps event modifier flags to a readable string.
1252 * returns: The string mapping or "none".
1253 * -------------------------------------------------------------------
1255 static void
1256 eventmodifier2string(au_emod_t emodifier, char *modstring, size_t modlen)
1258 register int i, j;
1260 struct em_map_ent {
1261 int mask;
1262 char *string;
1266 * TRANSLATION_NOTE
1267 * These abbreviations represent the event modifier field of the
1268 * header token. To gain a better understanding of each modifier,
1269 * read
1270 * System Administration Guide: Security Services >> Solaris Auditing
1271 * at http://docs.sun.com.
1274 static struct em_map_ent em_map[] = {
1275 { (int)PAD_READ, "rd" }, /* data read from object */
1276 { (int)PAD_WRITE, "wr" }, /* data written to object */
1277 { (int)PAD_SPRIVUSE, "sp" }, /* successfully used priv */
1278 { (int)PAD_FPRIVUSE, "fp" }, /* failed use of priv */
1279 { (int)PAD_NONATTR, "na" }, /* non-attributable event */
1280 { (int)PAD_FAILURE, "fe" } /* fail audit event */
1283 modstring[0] = '\0';
1285 for (i = 0, j = 0; i < sizeof (em_map) / sizeof (struct em_map_ent);
1286 i++) {
1287 if ((int)emodifier & em_map[i].mask) {
1288 if (j++)
1289 (void) strlcat(modstring, ":", modlen);
1290 (void) strlcat(modstring, em_map[i].string, modlen);
1297 * ---------------------------------------------------------
1298 * convert_char_to_string:
1299 * Converts a byte to string depending on the print mode
1300 * input : printmode, which may be one of AUP_BINARY,
1301 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1302 * c, which is the byte to convert
1303 * output : p, which is a pointer to the location where
1304 * the resulting string is to be stored
1305 * ----------------------------------------------------------
1309 convert_char_to_string(char printmode, char c, char *p)
1311 union {
1312 char c1[4];
1313 int c2;
1314 } dat;
1316 dat.c2 = 0;
1317 dat.c1[3] = c;
1319 if (printmode == AUP_BINARY)
1320 (void) convertbinary(p, &c, sizeof (char));
1321 else if (printmode == AUP_OCTAL)
1322 (void) sprintf(p, "%o", (int)dat.c2);
1323 else if (printmode == AUP_DECIMAL)
1324 (void) sprintf(p, "%d", c);
1325 else if (printmode == AUP_HEX)
1326 (void) sprintf(p, "0x%x", (int)dat.c2);
1327 else if (printmode == AUP_STRING)
1328 convertascii(p, &c, sizeof (char));
1329 return (0);
1333 * --------------------------------------------------------------
1334 * convert_short_to_string:
1335 * Converts a short integer to string depending on the print mode
1336 * input : printmode, which may be one of AUP_BINARY,
1337 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1338 * c, which is the short integer to convert
1339 * output : p, which is a pointer to the location where
1340 * the resulting string is to be stored
1341 * ---------------------------------------------------------------
1344 convert_short_to_string(char printmode, short c, char *p)
1346 union {
1347 short c1[2];
1348 int c2;
1349 } dat;
1351 dat.c2 = 0;
1352 dat.c1[1] = c;
1354 if (printmode == AUP_BINARY)
1355 (void) convertbinary(p, (char *)&c, sizeof (short));
1356 else if (printmode == AUP_OCTAL)
1357 (void) sprintf(p, "%o", (int)dat.c2);
1358 else if (printmode == AUP_DECIMAL)
1359 (void) sprintf(p, "%hd", c);
1360 else if (printmode == AUP_HEX)
1361 (void) sprintf(p, "0x%x", (int)dat.c2);
1362 else if (printmode == AUP_STRING)
1363 convertascii(p, (char *)&c, sizeof (short));
1364 return (0);
1368 * ---------------------------------------------------------
1369 * convert_int32_to_string:
1370 * Converts a integer to string depending on the print mode
1371 * input : printmode, which may be one of AUP_BINARY,
1372 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1373 * c, which is the integer to convert
1374 * output : p, which is a pointer to the location where
1375 * the resulting string is to be stored
1376 * ----------------------------------------------------------
1379 convert_int32_to_string(char printmode, int32_t c, char *p)
1381 if (printmode == AUP_BINARY)
1382 (void) convertbinary(p, (char *)&c, sizeof (int32_t));
1383 else if (printmode == AUP_OCTAL)
1384 (void) sprintf(p, "%o", c);
1385 else if (printmode == AUP_DECIMAL)
1386 (void) sprintf(p, "%d", c);
1387 else if (printmode == AUP_HEX)
1388 (void) sprintf(p, "0x%x", c);
1389 else if (printmode == AUP_STRING)
1390 convertascii(p, (char *)&c, sizeof (int));
1391 return (0);
1395 * ---------------------------------------------------------
1396 * convert_int64_to_string:
1397 * Converts a integer to string depending on the print mode
1398 * input : printmode, which may be one of AUP_BINARY,
1399 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1400 * c, which is the integer to convert
1401 * output : p, which is a pointer to the location where
1402 * the resulting string is to be stored
1403 * ----------------------------------------------------------
1406 convert_int64_to_string(char printmode, int64_t c, char *p)
1408 if (printmode == AUP_BINARY)
1409 (void) convertbinary(p, (char *)&c, sizeof (int64_t));
1410 else if (printmode == AUP_OCTAL)
1411 (void) sprintf(p, "%"PRIo64, c);
1412 else if (printmode == AUP_DECIMAL)
1413 (void) sprintf(p, "%"PRId64, c);
1414 else if (printmode == AUP_HEX)
1415 (void) sprintf(p, "0x%"PRIx64, c);
1416 else if (printmode == AUP_STRING)
1417 convertascii(p, (char *)&c, sizeof (int64_t));
1418 return (0);
1423 * -----------------------------------------------------------
1424 * convertbinary:
1425 * Converts a unit c of 'size' bytes long into a binary string
1426 * and returns it into the position pointed to by p
1427 * ------------------------------------------------------------
1430 convertbinary(char *p, char *c, int size)
1432 char *s, *t, *ss;
1433 int i, j;
1435 if ((s = (char *)malloc(8 * size + 1)) == NULL)
1436 return (0);
1438 ss = s;
1440 /* first convert to binary */
1441 t = s;
1442 for (i = 0; i < size; i++) {
1443 for (j = 0; j < 8; j++)
1444 (void) sprintf(t++, "%d", ((*c >> (7 - j)) & (0x01)));
1445 c++;
1447 *t = '\0';
1449 /* now string leading zero's if any */
1450 j = strlen(s) - 1;
1451 for (i = 0; i < j; i++) {
1452 if (*s != '0')
1453 break;
1454 else
1455 s++;
1458 /* now copy the contents of s to p */
1459 t = p;
1460 for (i = 0; i < (8 * size + 1); i++) {
1461 if (*s == '\0') {
1462 *t = '\0';
1463 break;
1465 *t++ = *s++;
1467 free(ss);
1469 return (1);
1473 static char hex[] = "0123456789abcdef";
1475 * -------------------------------------------------------------------
1476 * hexconvert : Converts a string of (size) bytes to hexadecimal, and
1477 * returns the hexadecimal string.
1478 * returns : - NULL if memory cannot be allocated for the string, or
1479 * - pointer to the hexadecimal string if successful
1480 * -------------------------------------------------------------------
1482 char *
1483 hexconvert(char *c, int size, int chunk)
1485 register char *s, *t;
1486 register int i, j, k;
1487 int numchunks;
1488 int leftovers;
1490 if (size <= 0)
1491 return (NULL);
1493 if ((s = (char *)malloc((size * 5) + 1)) == NULL)
1494 return (NULL);
1496 if (chunk > size || chunk <= 0)
1497 chunk = size;
1499 numchunks = size / chunk;
1500 leftovers = size % chunk;
1502 t = s;
1503 for (i = j = 0; i < numchunks; i++) {
1504 if (j++) {
1505 *t++ = ' ';
1507 *t++ = '0';
1508 *t++ = 'x';
1509 for (k = 0; k < chunk; k++) {
1510 *t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1511 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1512 c++;
1516 if (leftovers) {
1517 *t++ = ' ';
1518 *t++ = '0';
1519 *t++ = 'x';
1520 for (i = 0; i < leftovers; i++) {
1521 *t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1522 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1523 c++;
1527 *t = '\0';
1528 return (s);
1533 * -------------------------------------------------------------------
1534 * htp2string: Maps a print suggestion to a string.
1535 * returns : The string mapping or "unknown print suggestion".
1536 * -------------------------------------------------------------------
1538 char *
1539 htp2string(char print_sugg)
1541 register int i;
1543 struct htp_map_ent {
1544 char print_sugg;
1545 char *print_string;
1549 * TRANSLATION_NOTE
1550 * These names are data types when displaying the arbitrary data
1551 * token.
1554 static struct htp_map_ent htp_map[] = {
1555 { AUP_BINARY, "binary" },
1556 { AUP_OCTAL, "octal" },
1557 { AUP_DECIMAL, "decimal" },
1558 { AUP_HEX, "hexadecimal" },
1559 { AUP_STRING, "string" } };
1561 for (i = 0; i < sizeof (htp_map) / sizeof (struct htp_map_ent); i++)
1562 if (print_sugg == htp_map[i].print_sugg)
1563 return (gettext(htp_map[i].print_string));
1565 return (gettext("unknown print suggestion"));
1569 * ----------------------------------------------------------------------
1570 * pa_adr_short: Issues pr_adr_short to retrieve the next ADR item from the
1571 * input stream pointed to by audit_adr, and prints it
1572 * if status >= 0
1573 * return codes: -1 - error
1574 * : 0 - successful
1575 * ----------------------------------------------------------------------
1578 pa_adr_short(pr_context_t *context, int status, int flag)
1580 short c;
1581 uval_t uval;
1583 if (status >= 0) {
1584 if (pr_adr_short(context, &c, 1) == 0) {
1585 uval.uvaltype = PRA_SHORT;
1586 uval.short_val = c;
1587 return (pa_print(context, &uval, flag));
1588 } else
1589 return (-1);
1590 } else
1591 return (status);
1595 * -----------------------------------------------------------------------
1596 * pa_adr_shorthex: Issues pr_adr_short to retrieve the next ADR item from the
1597 * input stream pointed to by audit_adr, and prints it
1598 * in hexadecimal if status >= 0
1599 * return codes : -1 - error
1600 * : 0 - successful
1601 * -----------------------------------------------------------------------
1604 pa_adr_shorthex(pr_context_t *context, int status, int flag)
1606 short s;
1607 int returnstat;
1608 uval_t uval;
1610 if (status >= 0) {
1611 if ((returnstat = pr_adr_short(context, &s, 1)) == 0) {
1612 uval.uvaltype = PRA_STRING;
1613 uval.string_val = hexconvert((char *)&s, sizeof (s),
1614 sizeof (s));
1615 if (uval.string_val) {
1616 returnstat = pa_print(context, &uval, flag);
1617 free(uval.string_val);
1620 return (returnstat);
1621 } else
1622 return (status);
1627 * -----------------------------------------------------------------------
1628 * pa_adr_string: Retrieves a string from the input stream and prints it
1629 * if status >= 0
1630 * return codes : -1 - error
1631 * : 0 - successful
1632 * -----------------------------------------------------------------------
1635 pa_adr_string(pr_context_t *context, int status, int flag)
1637 char *c;
1638 short length;
1639 int returnstat;
1640 uval_t uval;
1643 * We need to know how much space to allocate for our string, so
1644 * read the length first, then call pr_adr_char to read those bytes.
1646 if (status < 0)
1647 return (status);
1649 if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1650 return (returnstat);
1651 if ((c = (char *)malloc(length + 1)) == NULL)
1652 return (-1);
1653 if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1654 free(c);
1655 return (returnstat);
1658 uval.uvaltype = PRA_STRING;
1659 uval.string_val = c;
1660 returnstat = pa_print(context, &uval, flag);
1661 free(c);
1662 return (returnstat);
1666 * -----------------------------------------------------------------------
1667 * pa_file_string: Retrieves a file string from the input stream and prints it
1668 * if status >= 0
1669 * return codes : -1 - error
1670 * : 0 - successful
1671 * -----------------------------------------------------------------------
1674 pa_file_string(pr_context_t *context, int status, int flag)
1676 char *c;
1677 char *p;
1678 short length;
1679 int returnstat;
1680 uval_t uval;
1683 * We need to know how much space to allocate for our string, so
1684 * read the length first, then call pr_adr_char to read those bytes.
1686 if (status < 0)
1687 return (status);
1689 if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1690 return (returnstat);
1691 if ((c = (char *)malloc(length + 1)) == NULL)
1692 return (-1);
1693 if ((p = (char *)malloc((length * 4) + 1)) == NULL) {
1694 free(c);
1695 return (-1);
1697 if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1698 free(c);
1699 free(p);
1700 return (returnstat);
1703 if (is_file_token(context->tokenid))
1704 context->audit_rec_len += length;
1706 convertascii(p, c, length - 1);
1707 uval.uvaltype = PRA_STRING;
1708 uval.string_val = p;
1710 if (returnstat == 0)
1711 returnstat = finish_open_tag(context);
1713 if (returnstat == 0)
1714 returnstat = pa_print(context, &uval, flag);
1716 free(c);
1717 free(p);
1718 return (returnstat);
1721 static int
1722 pa_putstr_xml(pr_context_t *context, int printable, char *str, size_t len)
1724 int err;
1726 if (!printable) {
1728 * Unprintable chars should always be converted to the
1729 * visible form. If there are unprintable characters which
1730 * require special treatment in xml, those should be
1731 * handled here.
1733 do {
1734 err = pr_printf(context, "\\%03o",
1735 (unsigned char)*str++);
1736 } while (err == 0 && --len != 0);
1737 return (err);
1739 /* printable characters */
1740 if (len == 1) {
1742 * check for the special chars only when char size was 1
1743 * ie, ignore special chars appear in the middle of multibyte
1744 * sequence.
1747 /* Escape for XML */
1748 switch (*str) {
1749 case '&':
1750 err = pr_printf(context, "%s", "&amp;");
1751 break;
1753 case '<':
1754 err = pr_printf(context, "%s", "&lt;");
1755 break;
1757 case '>':
1758 err = pr_printf(context, "%s", "&gt;");
1759 break;
1761 case '\"':
1762 err = pr_printf(context, "%s", "&quot;");
1763 break;
1765 case '\'':
1766 err = pr_printf(context, "%s", "&apos;");
1767 break;
1769 default:
1770 err = pr_putchar(context, *str);
1771 break;
1773 return (err);
1775 do {
1776 err = pr_putchar(context, *str++);
1777 } while (err == 0 && --len != 0);
1778 return (err);
1781 static int
1782 pa_putstr(pr_context_t *context, int printable, char *str, size_t len)
1784 int err;
1786 if (context->format & PRF_XMLM)
1787 return (pa_putstr_xml(context, printable, str, len));
1789 if (!printable) {
1790 do {
1791 err = pr_printf(context, "\\%03o",
1792 (unsigned char)*str++);
1793 } while (err == 0 && --len != 0);
1794 return (err);
1796 do {
1797 err = pr_putchar(context, *str++);
1798 } while (err == 0 && --len != 0);
1799 return (err);
1803 pa_string(pr_context_t *context, int status, int flag)
1805 int rstat, wstat;
1806 int i, printable, eos;
1807 int mlen, rlen;
1808 int mbmax = MB_CUR_MAX;
1809 wchar_t wc;
1810 char mbuf[MB_LEN_MAX + 1];
1811 char c;
1813 if (status < 0)
1814 return (status);
1816 rstat = wstat = 0;
1818 if (mbmax == 1) {
1819 while (wstat == 0) {
1820 if ((rstat = pr_adr_char(context, &c, 1)) < 0)
1821 break;
1822 if (c == '\0')
1823 break;
1824 printable = isprint((unsigned char)c);
1825 wstat = pa_putstr(context, printable, &c, 1);
1827 goto done;
1830 mlen = eos = 0;
1831 while (wstat == 0) {
1832 rlen = 0;
1833 do {
1834 if (!eos) {
1835 rstat = pr_adr_char(context, &c, 1);
1836 if (rstat != 0 || c == '\0')
1837 eos = 1;
1838 else
1839 mbuf[mlen++] = c;
1841 rlen = mbtowc(&wc, mbuf, mlen);
1842 } while (!eos && mlen < mbmax && rlen <= 0);
1844 if (mlen == 0)
1845 break; /* end of string */
1847 if (rlen <= 0) { /* no good sequence */
1848 rlen = 1;
1849 printable = 0;
1850 } else {
1851 printable = iswprint(wc);
1853 wstat = pa_putstr(context, printable, mbuf, rlen);
1854 mlen -= rlen;
1855 if (mlen > 0) {
1856 for (i = 0; i < mlen; i++)
1857 mbuf[i] = mbuf[rlen + i];
1861 done:
1862 if (wstat == 0)
1863 wstat = do_newline(context, flag);
1865 if (wstat == 0 && context->data_mode == FILEMODE)
1866 (void) fflush(stdout);
1868 return ((rstat != 0 || wstat != 0) ? -1 : 0);
1872 * -----------------------------------------------------------------------
1873 * pa_adr_u_int32: Issues pr_adr_u_int32 to retrieve the next ADR item from
1874 * the input stream pointed to by audit_adr, and prints it
1875 * if status = 0
1876 * return codes : -1 - error
1877 * : 0 - successful
1878 * -----------------------------------------------------------------------
1883 pa_adr_u_int32(pr_context_t *context, int status, int flag)
1885 uint32_t c;
1886 uval_t uval;
1888 if (status >= 0) {
1889 if (pr_adr_u_int32(context, &c, 1) == 0) {
1890 uval.uvaltype = PRA_UINT32;
1891 uval.uint32_val = c;
1892 return (pa_print(context, &uval, flag));
1893 } else
1894 return (-1);
1895 } else
1896 return (status);
1902 * -----------------------------------------------------------------------
1903 * pa_adr_u_int64: Issues pr_adr_u_int64 to retrieve the next ADR item from the
1904 * input stream pointed to by audit_adr, and prints it
1905 * if status = 0
1906 * return codes : -1 - error
1907 * : 0 - successful
1908 * -----------------------------------------------------------------------
1911 pa_adr_u_int64(pr_context_t *context, int status, int flag)
1913 uint64_t c;
1914 uval_t uval;
1916 if (status >= 0) {
1917 if (pr_adr_u_int64(context, &c, 1) == 0) {
1918 uval.uvaltype = PRA_UINT64;
1919 uval.uint64_val = c;
1920 return (pa_print(context, &uval, flag));
1921 } else
1922 return (-1);
1923 } else
1924 return (status);
1929 * -----------------------------------------------------------------------
1930 * pa_adr_u_short: Issues pr_adr_u_short to retrieve the next ADR item from
1931 * the input stream pointed to by audit_adr, and prints it
1932 * if status = 0
1933 * return codes : -1 - error
1934 * : 0 - successful
1935 * -----------------------------------------------------------------------
1938 pa_adr_u_short(pr_context_t *context, int status, int flag)
1940 ushort_t c;
1941 uval_t uval;
1943 if (status >= 0) {
1944 if (pr_adr_u_short(context, &c, 1) == 0) {
1945 uval.uvaltype = PRA_USHORT;
1946 uval.ushort_val = c;
1947 return (pa_print(context, &uval, flag));
1948 } else
1949 return (-1);
1950 } else
1951 return (status);
1955 * -----------------------------------------------------------------------
1956 * pa_reclen: Issues pr_adr_u_long to retrieve the length of the record
1957 * from the input stream pointed to by audit_adr,
1958 * and prints it (unless format is XML) if status = 0
1959 * return codes : -1 - error
1960 * : 0 - successful
1961 * -----------------------------------------------------------------------
1964 pa_reclen(pr_context_t *context, int status)
1966 uint32_t c;
1967 uval_t uval;
1969 if (status >= 0) {
1970 if ((int)pr_adr_u_int32(context, &c, 1) == 0) {
1971 context->audit_rec_len = c;
1973 /* Don't print this for XML format */
1974 if (context->format & PRF_XMLM) {
1975 return (0);
1976 } else {
1977 uval.uvaltype = PRA_UINT32;
1978 uval.uint32_val = c;
1979 return (pa_print(context, &uval, 0));
1981 } else
1982 return (-1);
1983 } else
1984 return (status);
1988 * -----------------------------------------------------------------------
1989 * pa_mode : Issues pr_adr_u_short to retrieve the next ADR item from
1990 * the input stream pointed to by audit_adr, and prints it
1991 * in octal if status = 0
1992 * return codes : -1 - error
1993 * : 0 - successful
1994 * -----------------------------------------------------------------------
1997 pa_mode(pr_context_t *context, int status, int flag)
1999 uint32_t c;
2000 uval_t uval;
2002 if (status >= 0) {
2003 if (pr_adr_u_int32(context, &c, 1) == 0) {
2004 uval.uvaltype = PRA_LOCT;
2005 uval.uint32_val = c;
2006 return (pa_print(context, &uval, flag));
2007 } else
2008 return (-1);
2009 } else
2010 return (status);
2013 static int
2014 pa_print_uid(pr_context_t *context, uid_t uid, int status, int flag)
2016 int returnstat;
2017 struct passwd *pw;
2018 uval_t uval;
2020 if (status < 0)
2021 return (status);
2023 if (!(context->format & PRF_RAWM)) {
2024 /* get password file entry */
2025 if ((pw = getpwuid(uid)) == NULL) {
2026 returnstat = 1;
2027 } else {
2028 /* print in ASCII form */
2029 uval.uvaltype = PRA_STRING;
2030 uval.string_val = pw->pw_name;
2031 returnstat = pa_print(context, &uval, flag);
2034 /* print in integer form */
2035 if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2036 uval.uvaltype = PRA_INT32;
2037 uval.int32_val = uid;
2038 returnstat = pa_print(context, &uval, flag);
2040 return (returnstat);
2045 * -----------------------------------------------------------------------
2046 * pa_pw_uid() : Issues pr_adr_u_int32 to reads uid from input stream
2047 * pointed to by audit_adr, and displays it in either
2048 * raw form or its ASCII representation, if status >= 0.
2049 * return codes : -1 - error
2050 * : 1 - warning, passwd entry not found
2051 * : 0 - successful
2052 * -----------------------------------------------------------------------
2055 pa_pw_uid(pr_context_t *context, int status, int flag)
2057 uint32_t uid;
2059 if (status < 0)
2060 return (status);
2062 if (pr_adr_u_int32(context, &uid, 1) != 0)
2063 /* cannot retrieve uid */
2064 return (-1);
2066 return (pa_print_uid(context, uid, status, flag));
2069 static int
2070 pa_print_gid(pr_context_t *context, gid_t gid, int status, int flag)
2072 int returnstat;
2073 struct group *gr;
2074 uval_t uval;
2076 if (status < 0)
2077 return (status);
2079 if (!(context->format & PRF_RAWM)) {
2080 /* get group file entry */
2081 if ((gr = getgrgid(gid)) == NULL) {
2082 returnstat = 1;
2083 } else {
2084 /* print in ASCII form */
2085 uval.uvaltype = PRA_STRING;
2086 uval.string_val = gr->gr_name;
2087 returnstat = pa_print(context, &uval, flag);
2090 /* print in integer form */
2091 if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2092 uval.uvaltype = PRA_INT32;
2093 uval.int32_val = gid;
2094 returnstat = pa_print(context, &uval, flag);
2096 return (returnstat);
2101 * -----------------------------------------------------------------------
2102 * pa_gr_uid() : Issues pr_adr_u_int32 to reads group uid from input stream
2103 * pointed to by audit_adr, and displays it in either
2104 * raw form or its ASCII representation, if status >= 0.
2105 * return codes : -1 - error
2106 * : 1 - warning, passwd entry not found
2107 * : 0 - successful
2108 * -----------------------------------------------------------------------
2111 pa_gr_uid(pr_context_t *context, int status, int flag)
2113 uint32_t gid;
2115 if (status < 0)
2116 return (status);
2118 if (pr_adr_u_int32(context, &gid, 1) != 0)
2119 /* cannot retrieve gid */
2120 return (-1);
2122 return (pa_print_gid(context, gid, status, flag));
2127 * -----------------------------------------------------------------------
2128 * pa_pw_uid_gr_gid() : Issues pr_adr_u_int32 to reads uid or group uid
2129 * from input stream
2130 * pointed to by audit_adr, and displays it in either
2131 * raw form or its ASCII representation, if status >= 0.
2132 * return codes : -1 - error
2133 * : 1 - warning, passwd entry not found
2134 * : 0 - successful
2135 * -----------------------------------------------------------------------
2138 pa_pw_uid_gr_gid(pr_context_t *context, int status, int flag)
2140 int returnstat;
2141 uint32_t value;
2142 uval_t uval;
2144 if (status < 0)
2145 return (status);
2147 /* get value of a_type */
2148 if ((returnstat = pr_adr_u_int32(context, &value, 1)) != 0)
2149 return (returnstat);
2151 if ((returnstat = open_tag(context, TAG_ACLTYPE)) != 0)
2152 return (returnstat);
2154 uval.uvaltype = PRA_UINT32;
2155 uval.uint32_val = value;
2156 if ((returnstat = pa_print(context, &uval, flag)) != 0)
2157 return (returnstat);
2159 if ((returnstat = close_tag(context, TAG_ACLTYPE)) != 0)
2160 return (returnstat);
2162 if ((returnstat = open_tag(context, TAG_ACLVAL)) != 0)
2163 return (returnstat);
2165 * TRANSLATION_NOTE
2166 * The "mask" and "other" strings refer to the class mask
2167 * and other (or world) entries in an ACL.
2168 * The "unrecognized" string refers to an unrecognized ACL
2169 * entry.
2171 switch (value) {
2172 case USER_OBJ:
2173 case USER:
2174 returnstat = pa_pw_uid(context, returnstat, flag);
2175 break;
2176 case GROUP_OBJ:
2177 case GROUP:
2178 returnstat = pa_gr_uid(context, returnstat, flag);
2179 break;
2180 case CLASS_OBJ:
2181 returnstat = pr_adr_u_int32(context, &value, 1);
2182 if (returnstat != 0)
2183 return (returnstat);
2185 if (!(context->format & PRF_RAWM)) {
2186 uval.uvaltype = PRA_STRING;
2187 uval.string_val = gettext("mask");
2188 returnstat = pa_print(context, &uval, flag);
2189 } else {
2190 uval.uvaltype = PRA_UINT32;
2191 uval.uint32_val = value;
2192 if ((returnstat =
2193 pa_print(context, &uval, flag)) != 0) {
2194 return (returnstat);
2197 break;
2198 case OTHER_OBJ:
2199 returnstat = pr_adr_u_int32(context, &value, 1);
2200 if (returnstat != 0)
2201 return (returnstat);
2203 if (!(context->format & PRF_RAWM)) {
2204 uval.uvaltype = PRA_STRING;
2205 uval.string_val = gettext("other");
2206 returnstat = pa_print(context, &uval, flag);
2207 } else {
2208 uval.uvaltype = PRA_UINT32;
2209 uval.uint32_val = value;
2210 if ((returnstat =
2211 pa_print(context, &uval, flag)) != 0) {
2212 return (returnstat);
2215 break;
2216 default:
2217 returnstat = pr_adr_u_int32(context, &value, 1);
2218 if (returnstat != 0)
2219 return (returnstat);
2221 if (!(context->format & PRF_RAWM)) {
2222 uval.uvaltype = PRA_STRING;
2223 uval.string_val = gettext("unrecognized");
2224 returnstat = pa_print(context, &uval, flag);
2225 } else {
2226 uval.uvaltype = PRA_UINT32;
2227 uval.uint32_val = value;
2228 if ((returnstat =
2229 pa_print(context, &uval, flag)) != 0) {
2230 return (returnstat);
2235 if ((returnstat = close_tag(context, TAG_ACLVAL)) != 0)
2236 return (returnstat);
2238 return (returnstat);
2243 * -----------------------------------------------------------------------
2244 * pa_event_modifier(): Issues pr_adr_u_short to retrieve the next ADR item from
2245 * the input stream pointed to by audit_adr. This is the
2246 * event type, and is displayed in hex;
2247 * return codes : -1 - error
2248 * : 0 - successful
2249 * -----------------------------------------------------------------------
2252 pa_event_modifier(pr_context_t *context, int status, int flag)
2254 int returnstat;
2255 au_emod_t emodifier;
2256 uval_t uval;
2257 char modstring[64];
2259 if (status < 0)
2260 return (status);
2262 if ((returnstat = pr_adr_u_short(context, &emodifier, 1)) != 0)
2263 return (returnstat);
2265 /* For XML, only print when modifier is non-zero */
2266 if (!(context->format & PRF_XMLM) || (emodifier != 0)) {
2267 uval.uvaltype = PRA_STRING;
2269 returnstat = open_tag(context, TAG_EVMOD);
2271 if (returnstat >= 0) {
2272 if (!(context->format & PRF_RAWM)) {
2273 eventmodifier2string(emodifier, modstring,
2274 sizeof (modstring));
2275 uval.string_val = modstring;
2276 returnstat = pa_print(context, &uval, flag);
2277 } else {
2278 uval.string_val = hexconvert((char *)&emodifier,
2279 sizeof (emodifier), sizeof (emodifier));
2280 if (uval.string_val) {
2281 returnstat = pa_print(context, &uval,
2282 flag);
2283 free(uval.string_val);
2287 if (returnstat >= 0)
2288 returnstat = close_tag(context, TAG_EVMOD);
2291 return (returnstat);
2296 * -----------------------------------------------------------------------
2297 * pa_event_type(): Issues pr_adr_u_short to retrieve the next ADR item from
2298 * the input stream pointed to by audit_adr. This is the
2299 * event type, and is displayed in either raw or
2300 * ASCII form as appropriate
2301 * return codes : -1 - error
2302 * : 0 - successful
2303 * -----------------------------------------------------------------------
2306 pa_event_type(pr_context_t *context, int status, int flag)
2308 au_event_t etype;
2309 int returnstat;
2310 au_event_ent_t *p_event = NULL;
2311 uval_t uval;
2313 if (status >= 0) {
2314 if ((returnstat = pr_adr_u_short(context, &etype, 1)) == 0) {
2315 if (!(context->format & PRF_RAWM)) {
2316 uval.uvaltype = PRA_STRING;
2317 if (context->format & PRF_NOCACHE) {
2318 p_event = getauevnum(etype);
2319 } else {
2320 (void) cacheauevent(&p_event, etype);
2322 if (p_event != NULL) {
2323 if (context->format & PRF_SHORTM)
2324 uval.string_val =
2325 p_event->ae_name;
2326 else
2327 uval.string_val =
2328 p_event->ae_desc;
2329 } else {
2330 uval.string_val =
2331 gettext("invalid event number");
2333 returnstat = pa_print(context, &uval, flag);
2334 } else {
2335 uval.uvaltype = PRA_USHORT;
2336 uval.ushort_val = etype;
2337 returnstat = pa_print(context, &uval, flag);
2340 return (returnstat);
2341 } else
2342 return (status);
2348 * Print time from struct timeval to millisecond resolution.
2350 * typedef long time_t; time of day in seconds
2351 * typedef long useconds_t; signed # of microseconds
2353 * struct timeval {
2354 * time_t tv_sec; seconds
2355 * suseconds_t tv_usec; and microseconds
2356 * };
2360 pa_utime32(pr_context_t *context, int status, int flag)
2362 uint32_t scale = 1000; /* usec to msec */
2364 return (do_mtime32(context, status, flag, scale));
2368 * Print time from timestruc_t to millisecond resolution.
2370 * typedef struct timespec timestruct_t;
2371 * struct timespec{
2372 * time_t tv_sec; seconds
2373 * long tv_nsec; and nanoseconds
2374 * };
2377 pa_ntime32(pr_context_t *context, int status, int flag)
2379 uint32_t scale = 1000000; /* nsec to msec */
2381 return (do_mtime32(context, status, flag, scale));
2385 * Format the timezone +/- HH:MM and terminate the string
2386 * Note tm and tv_sec are the same time.
2387 * Too bad strftime won't produce an ISO 8601 time zone numeric
2390 #define MINS (24L * 60)
2391 static void
2392 tzone(struct tm *tm, time_t *tv_sec, char *p)
2394 struct tm *gmt;
2395 int min_off;
2397 gmt = gmtime(tv_sec);
2399 min_off = ((tm->tm_hour - gmt->tm_hour) * 60) +
2400 (tm->tm_min - gmt->tm_min);
2402 if (tm->tm_year < gmt->tm_year) /* cross new year */
2403 min_off -= MINS;
2404 else if (tm->tm_year > gmt->tm_year)
2405 min_off += MINS;
2406 else if (tm->tm_yday < gmt->tm_yday) /* cross dateline */
2407 min_off -= MINS;
2408 else if (tm->tm_yday > gmt->tm_yday)
2409 min_off += MINS;
2411 if (min_off < 0) {
2412 min_off = -min_off;
2413 *p++ = '-';
2414 } else {
2415 *p++ = '+';
2418 *p++ = min_off / 600 + '0'; /* 10s of hours */
2419 min_off = min_off - min_off / 600 * 600;
2420 *p++ = min_off / 60 % 10 + '0'; /* hours */
2421 min_off = min_off - min_off / 60 * 60;
2422 *p++ = ':';
2423 *p++ = min_off / 10 + '0'; /* 10s of minutes */
2424 *p++ = min_off % 10 + '0'; /* minutes */
2425 *p = '\0';
2429 * Format the milliseconds in place in the string.
2430 * Borrowed from strftime.c:itoa()
2432 static void
2433 msec32(uint32_t msec, char *p)
2435 *p++ = msec / 100 + '0';
2436 msec = msec - msec / 100 * 100;
2437 *p++ = msec / 10 + '0';
2438 *p++ = msec % 10 +'0';
2442 * Format time and print relative to scale factor from micro/nano seconds.
2444 static int
2445 do_mtime32(pr_context_t *context, int status, int flag, uint32_t scale)
2447 uint32_t t32;
2448 time_t tv_sec;
2449 struct tm tm;
2450 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2451 int returnstat;
2452 uval_t uval;
2454 if (status < 0)
2455 return (status);
2457 if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2458 return (returnstat);
2460 if ((returnstat = pr_adr_u_int32(context,
2461 (uint32_t *)&tv_sec, 1)) != 0)
2462 return (returnstat);
2463 if ((returnstat = pr_adr_u_int32(context, &t32, 1)) == 0) {
2464 if (!(context->format & PRF_RAWM)) {
2465 (void) localtime_r(&tv_sec, &tm);
2466 (void) strftime(time_created,
2467 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2468 "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2469 msec32(t32/scale,
2470 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2471 tzone(&tm, &tv_sec,
2472 &time_created[
2473 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2474 uval.uvaltype = PRA_STRING;
2475 uval.string_val = time_created;
2476 } else {
2477 uval.uvaltype = PRA_UINT32;
2478 uval.uint32_val = (uint32_t)tv_sec;
2479 (void) pa_print(context, &uval, 0);
2480 if (context->format & PRF_XMLM) {
2481 uval.uvaltype = PRA_CHAR;
2482 uval.char_val = '.';
2483 (void) pa_print(context, &uval, 0);
2485 uval.uvaltype = PRA_UINT32;
2486 uval.uint32_val = t32;
2488 returnstat = pa_print(context, &uval, flag);
2491 if (returnstat == 0)
2492 return (close_tag(context, TAG_ISO));
2493 else
2494 return (returnstat);
2498 * Print time from struct timeval to millisecond resolution.
2500 * typedef long time_t; time of day in seconds
2501 * typedef long useconds_t; signed # of microseconds
2503 * struct timeval {
2504 * time_t tv_sec; seconds
2505 * suseconds_t tv_usec; and microseconds
2506 * };
2510 pa_utime64(pr_context_t *context, int status, int flag)
2512 uint64_t scale = 1000; /* usec to msec */
2514 return (do_mtime64(context, status, flag, scale));
2518 * Print time from timestruc_t to millisecond resolution.
2520 * typedef struct timespec timestruct_t;
2521 * struct timespec{
2522 * time_t tv_sec; seconds
2523 * long tv_nsec; and nanoseconds
2524 * };
2527 pa_ntime64(pr_context_t *context, int status, int flag)
2529 uint64_t scale = 1000000; /* nsec to msec */
2531 return (do_mtime64(context, status, flag, scale));
2535 * Format the milliseconds in place in the string.
2536 * Borrowed from strftime.c:itoa()
2538 static void
2539 msec64(uint64_t msec, char *p)
2541 *p++ = msec / 100 + '0';
2542 msec = msec - msec / 100 * 100;
2543 *p++ = msec / 10 + '0';
2544 *p++ = msec % 10 +'0';
2548 * Format time and print relative to scale factor from micro/nano seconds.
2550 static int
2551 do_mtime64(pr_context_t *context, int status, int flag, uint64_t scale)
2553 uint64_t t64_sec;
2554 uint64_t t64_msec;
2555 time_t tv_sec;
2556 struct tm tm;
2557 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2558 int returnstat;
2559 uval_t uval;
2561 if (status < 0)
2562 return (status);
2564 if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2565 return (returnstat);
2567 if ((returnstat = pr_adr_u_int64(context, &t64_sec, 1)) != 0)
2568 return (returnstat);
2569 if ((returnstat = pr_adr_u_int64(context, &t64_msec, 1)) == 0) {
2570 if (!(context->format & PRF_RAWM)) {
2571 #ifndef _LP64
2573 * N.B.
2574 * This fails for years from 2038
2575 * The Y2K+38 problem
2577 #endif /* !_LP64 */
2578 tv_sec = (time_t)t64_sec;
2579 (void) localtime_r(&tv_sec, &tm);
2580 (void) strftime(time_created,
2581 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2582 "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2583 msec64(t64_msec/scale,
2584 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2585 tzone(&tm, &tv_sec,
2586 &time_created[
2587 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2588 uval.uvaltype = PRA_STRING;
2589 uval.string_val = time_created;
2590 } else {
2591 uval.uvaltype = PRA_UINT64;
2592 uval.uint64_val = t64_sec;
2593 (void) pa_print(context, &uval, 0);
2594 if (context->format & PRF_XMLM) {
2595 uval.uvaltype = PRA_CHAR;
2596 uval.char_val = '.';
2597 (void) pa_print(context, &uval, 0);
2599 uval.uvaltype = PRA_UINT64;
2600 uval.uint64_val = t64_msec;
2602 returnstat = pa_print(context, &uval, flag);
2605 if (returnstat < 0)
2606 return (returnstat);
2608 return (close_tag(context, TAG_ISO));
2612 * -----------------------------------------------------------------------
2613 * pa_error() : convert the return token error code.
2615 * output : buf string representing return token error code.
2617 * -----------------------------------------------------------------------
2619 void
2620 pa_error(const uchar_t err, char *buf, size_t buflen)
2622 if (err == ADT_SUCCESS) {
2623 (void) strlcpy(buf, gettext("success"), buflen);
2624 } else if ((char)err == ADT_FAILURE) {
2625 (void) strlcpy(buf, gettext("failure"), buflen);
2626 } else {
2627 char *emsg = strerror(err);
2629 if (emsg != NULL) {
2630 (void) strlcpy(buf, gettext("failure: "), buflen);
2631 (void) strlcat(buf, emsg, buflen);
2632 } else {
2633 (void) snprintf(buf, buflen, "%s%d",
2634 gettext("failure: "), err);
2640 * -----------------------------------------------------------------------
2641 * pa_retval() : convert the return token return value code.
2643 * input : err, for kernel success 0, or
2644 * failure errno: 0 > & < sys_nerr.
2645 * for userland success ADT_SUCCESS (0) or
2646 * failure ADT_FAILURE (-1).
2647 * pa_error() above has already converted err.
2649 * : retval, for kernel arbitrary return value for success, or
2650 * failure: -1.
2651 * for userland,
2652 * >= ADT_FAIL_VALUE < ADT_FAIL_PAM, an adt message code;
2653 * >= ADT_FAIL_PAM, a pam_strerror value;
2654 * < ADT_FAIL_VALUE, supposed to be an errno.
2656 * output : buf string representing return token error code.
2658 * -----------------------------------------------------------------------
2660 void
2661 pa_retval(const uchar_t err, const int32_t retval, char *buf, size_t buflen)
2663 struct msg_text *msglist;
2664 char *emsg;
2666 /* success or kernel failure */
2667 if (((char)err == ADT_SUCCESS) ||
2668 (retval < 0)) {
2670 (void) snprintf(buf, buflen, "%d", retval);
2671 return;
2674 /* userland failure */
2675 msglist = &adt_msg_text[ADT_LIST_FAIL_VALUE];
2677 if ((retval + msglist->ml_offset >= msglist->ml_min_index) &&
2678 (retval + msglist->ml_offset <= msglist->ml_max_index)) {
2680 (void) strlcpy(buf,
2681 gettext(msglist->ml_msg_list[retval + msglist->ml_offset]),
2682 buflen);
2683 } else if ((retval >= ADT_FAIL_PAM) &&
2684 (retval < ADT_FAIL_PAM + PAM_TOTAL_ERRNUM)) {
2686 (void) strlcpy(buf, pam_strerror(NULL, retval - ADT_FAIL_PAM),
2687 buflen);
2688 } else if ((emsg = strerror(retval)) != NULL) {
2690 (void) strlcpy(buf, emsg, buflen);
2691 } else {
2693 (void) snprintf(buf, buflen, "%d", retval);
2698 * -----------------------------------------------------------------------
2699 * pa_printstr() : print a given string, translating unprintables
2700 * : as needed.
2702 static int
2703 pa_printstr(pr_context_t *context, char *str)
2705 int err = 0;
2706 int len, printable;
2707 int mbmax = MB_CUR_MAX;
2708 wchar_t wc;
2709 char c;
2711 if (mbmax == 1) {
2712 /* fast path */
2713 while (err == 0 && *str != '\0') {
2714 c = *str++;
2715 printable = isprint((unsigned char)c);
2716 err = pa_putstr(context, printable, &c, 1);
2718 return (err);
2720 while (err == 0 && *str != '\0') {
2721 len = mbtowc(&wc, str, mbmax);
2722 if (len <= 0) {
2723 len = 1;
2724 printable = 0;
2725 } else {
2726 printable = iswprint(wc);
2728 err = pa_putstr(context, printable, str, len);
2729 str += len;
2731 return (err);
2735 * -----------------------------------------------------------------------
2736 * pa_print() : print as one str or formatted for easy reading.
2737 * : flag - indicates whether to output a new line for
2738 * : multi-line output.
2739 * : = 0; no new line
2740 * : = 1; new line if regular output
2741 * output : The audit record information is displayed in the
2742 * type specified by uvaltype and value specified in
2743 * uval. The printing of the delimiter or newline is
2744 * determined by PRF_ONELINE, and the flag value,
2745 * as follows:
2746 * +--------+------+------+-----------------+
2747 * |ONELINE | flag | last | Action |
2748 * +--------+------+------+-----------------+
2749 * | Y | Y | T | print new line |
2750 * | Y | Y | F | print delimiter |
2751 * | Y | N | T | print new line |
2752 * | Y | N | F | print delimiter |
2753 * | N | Y | T | print new line |
2754 * | N | Y | F | print new line |
2755 * | N | N | T | print new line |
2756 * | N | N | F | print delimiter |
2757 * +--------+------+------+-----------------+
2759 * return codes : -1 - error
2760 * 0 - successful
2761 * -----------------------------------------------------------------------
2764 pa_print(pr_context_t *context, uval_t *uval, int flag)
2766 int returnstat = 0;
2767 int last;
2769 switch (uval->uvaltype) {
2770 case PRA_INT32:
2771 returnstat = pr_printf(context, "%d", uval->int32_val);
2772 break;
2773 case PRA_UINT32:
2774 returnstat = pr_printf(context, "%u", uval->uint32_val);
2775 break;
2776 case PRA_INT64:
2777 returnstat = pr_printf(context, "%"PRId64, uval->int64_val);
2778 break;
2779 case PRA_UINT64:
2780 returnstat = pr_printf(context, "%"PRIu64, uval->uint64_val);
2781 break;
2782 case PRA_SHORT:
2783 returnstat = pr_printf(context, "%hd", uval->short_val);
2784 break;
2785 case PRA_USHORT:
2786 returnstat = pr_printf(context, "%hu", uval->ushort_val);
2787 break;
2788 case PRA_CHAR:
2789 returnstat = pr_printf(context, "%c", uval->char_val);
2790 break;
2791 case PRA_BYTE:
2792 returnstat = pr_printf(context, "%d", uval->char_val);
2793 break;
2794 case PRA_STRING:
2795 returnstat = pa_printstr(context, uval->string_val);
2796 break;
2797 case PRA_HEX32:
2798 returnstat = pr_printf(context, "0x%x", uval->int32_val);
2799 break;
2800 case PRA_HEX64:
2801 returnstat = pr_printf(context, "0x%"PRIx64, uval->int64_val);
2802 break;
2803 case PRA_SHEX:
2804 returnstat = pr_printf(context, "0x%hx", uval->short_val);
2805 break;
2806 case PRA_OCT:
2807 returnstat = pr_printf(context, "%ho", uval->ushort_val);
2808 break;
2809 case PRA_LOCT:
2810 returnstat = pr_printf(context, "%o", (int)uval->uint32_val);
2811 break;
2812 default:
2813 (void) fprintf(stderr, gettext("praudit: Unknown type.\n"));
2814 returnstat = -1;
2815 break;
2817 if (returnstat < 0)
2818 return (returnstat);
2820 last = (context->audit_adr->adr_now ==
2821 (context->audit_rec_start + context->audit_rec_len));
2823 if (!(context->format & PRF_XMLM)) {
2824 if (!(context->format & PRF_ONELINE)) {
2825 if ((flag == 1) || last)
2826 returnstat = pr_putchar(context, '\n');
2827 else
2828 returnstat = pr_printf(context, "%s",
2829 context->SEPARATOR);
2830 } else {
2831 if (!last)
2832 returnstat = pr_printf(context, "%s",
2833 context->SEPARATOR);
2834 else
2835 returnstat = pr_putchar(context, '\n');
2838 if ((returnstat == 0) && (context->data_mode == FILEMODE))
2839 (void) fflush(stdout);
2841 return (returnstat);
2844 static struct cntrl_mapping {
2845 char from;
2846 char to;
2847 } cntrl_map[] = {
2848 '\0', '0',
2849 '\a', 'a',
2850 '\b', 'b',
2851 '\t', 't',
2852 '\f', 'f',
2853 '\n', 'n',
2854 '\r', 'r',
2855 '\v', 'v'
2858 static int cntrl_map_entries = sizeof (cntrl_map)
2859 / sizeof (struct cntrl_mapping);
2862 * Convert binary data to ASCII for printing.
2864 void
2865 convertascii(char *p, char *c, int size)
2867 int i, j, uc;
2869 for (i = 0; i < size; i++) {
2870 uc = (unsigned char)*(c + i);
2871 if (isascii(uc)) {
2872 if (iscntrl(uc)) {
2873 for (j = 0; j < cntrl_map_entries; j++) {
2874 if (cntrl_map[j].from == uc) {
2875 *p++ = '\\';
2876 *p++ = cntrl_map[j].to;
2877 break;
2880 if (j == cntrl_map_entries) {
2881 *p++ = '^';
2882 *p++ = (char)(uc ^ 0100);
2884 } else {
2885 *p++ = (char)uc;
2887 } else {
2888 p += sprintf(p, "\\%03o", uc);
2891 *p = '\0';
2895 * -----------------------------------------------------------------------
2896 * pa_xgeneric: Process Xobject token and display contents
2897 * This routine will handle many of the attribute
2898 * types introduced in TS 2.x, such as:
2900 * AUT_XCOLORMAP, AUT_XCURSOR, AUT_XFONT,
2901 * AUT_XGC, AUT_XPIXMAP, AUT_XWINDOW
2903 * NOTE: At the time of call, the token id has been retrieved
2905 * return codes : -1 - error
2906 * : 0 - successful
2907 * NOTE: At the time of call, the xatom token id has been retrieved
2909 * Format of xobj
2910 * text token id adr_char
2911 * XID adr_u_int32
2912 * creator uid adr_pw_uid
2913 * -----------------------------------------------------------------------
2916 pa_xgeneric(pr_context_t *context)
2918 int returnstat;
2920 returnstat = process_tag(context, TAG_XID, 0, 0);
2921 return (process_tag(context, TAG_XCUID, returnstat, 1));
2926 * ------------------------------------------------------------------------
2927 * pa_liaison : Issues pr_adr_char to retrieve the next ADR item from the
2928 * input stream pointed to by audit_adr, and prints it
2929 * if status >= 0 either in ASCII or raw form
2930 * return codes : -1 - error
2931 * : 0 - successful
2932 * : 1 - warning, unknown label type
2933 * -----------------------------------------------------------------------
2936 pa_liaison(pr_context_t *context, int status, int flag)
2938 int returnstat;
2939 int32_t li;
2940 uval_t uval;
2942 if (status >= 0) {
2943 if ((returnstat = pr_adr_int32(context, &li, 1)) != 0) {
2944 return (returnstat);
2946 if (!(context->format & PRF_RAWM)) {
2947 uval.uvaltype = PRA_UINT32;
2948 uval.uint32_val = li;
2949 returnstat = pa_print(context, &uval, flag);
2951 /* print in hexadecimal form */
2952 if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2953 uval.uvaltype = PRA_HEX32;
2954 uval.uint32_val = li;
2955 returnstat = pa_print(context, &uval, flag);
2957 return (returnstat);
2958 } else
2959 return (status);
2963 * ------------------------------------------------------------------------
2964 * pa_xid : Issues pr_adr_int32 to retrieve the XID from the input
2965 * stream pointed to by audit_adr, and prints it if
2966 * status >= 0 either in ASCII or raw form
2967 * return codes : -1 - error
2968 * : 0 - successful
2969 * : 1 - warning, unknown label type
2970 * ------------------------------------------------------------------------
2974 pa_xid(pr_context_t *context, int status, int flag)
2976 int returnstat;
2977 int32_t xid;
2978 uval_t uval;
2980 if (status < 0)
2981 return (status);
2983 /* get XID from stream */
2984 if ((returnstat = pr_adr_int32(context, (int32_t *)&xid, 1)) != 0)
2985 return (returnstat);
2987 if (!(context->format & PRF_RAWM)) {
2988 uval.uvaltype = PRA_STRING;
2989 uval.string_val = hexconvert((char *)&xid, sizeof (xid),
2990 sizeof (xid));
2991 if (uval.string_val) {
2992 returnstat = pa_print(context, &uval, flag);
2993 free(uval.string_val);
2995 } else {
2996 uval.uvaltype = PRA_INT32;
2997 uval.int32_val = xid;
2998 returnstat = pa_print(context, &uval, flag);
3001 return (returnstat);
3004 static int
3005 pa_ace_flags(pr_context_t *context, ace_t *ace, int status, int flag)
3007 int returnstat;
3008 uval_t uval;
3010 if (status < 0)
3011 return (status);
3014 * TRANSLATION_NOTE
3015 * ace->a_flags refers to access flags of ZFS/NFSv4 ACL entry.
3017 if ((returnstat = open_tag(context, TAG_ACEFLAGS)) != 0)
3018 return (returnstat);
3019 if (!(context->format & PRF_RAWM)) {
3020 uval.uvaltype = PRA_STRING;
3021 switch (ace->a_flags & ACE_TYPE_FLAGS) {
3022 case ACE_OWNER:
3023 uval.string_val = gettext(OWNERAT_TXT);
3024 break;
3025 case ACE_GROUP | ACE_IDENTIFIER_GROUP:
3026 uval.string_val = gettext(GROUPAT_TXT);
3027 break;
3028 case ACE_IDENTIFIER_GROUP:
3029 uval.string_val = gettext(GROUP_TXT);
3030 break;
3031 case ACE_EVERYONE:
3032 uval.string_val = gettext(EVERYONEAT_TXT);
3033 break;
3034 case 0:
3035 uval.string_val = gettext(USER_TXT);
3036 break;
3037 default:
3038 uval.uvaltype = PRA_USHORT;
3039 uval.uint32_val = ace->a_flags;
3041 } else {
3042 uval.uvaltype = PRA_USHORT;
3043 uval.uint32_val = ace->a_flags;
3045 if ((returnstat = pa_print(context, &uval, flag)) != 0)
3046 return (returnstat);
3047 return (close_tag(context, TAG_ACEFLAGS));
3050 static int
3051 pa_ace_who(pr_context_t *context, ace_t *ace, int status, int flag)
3053 int returnstat;
3055 if (status < 0)
3056 return (status);
3059 * TRANSLATION_NOTE
3060 * ace->a_who refers to user id or group id of ZFS/NFSv4 ACL entry.
3062 if ((returnstat = open_tag(context, TAG_ACEID)) != 0)
3063 return (returnstat);
3064 switch (ace->a_flags & ACE_TYPE_FLAGS) {
3065 case ACE_IDENTIFIER_GROUP: /* group id */
3066 returnstat = pa_print_gid(context, ace->a_who, returnstat,
3067 flag);
3068 break;
3069 default: /* user id */
3070 returnstat = pa_print_uid(context, ace->a_who, returnstat,
3071 flag);
3072 break;
3074 if (returnstat < 0)
3075 return (returnstat);
3076 return (close_tag(context, TAG_ACEID));
3080 * Appends what to str, (re)allocating str if necessary.
3082 #define INITIAL_ALLOC 256
3083 static int
3084 strappend(char **str, char *what, size_t *alloc)
3086 char *s, *newstr;
3087 size_t needed;
3089 s = *str;
3091 if (s == NULL) {
3092 s = malloc(INITIAL_ALLOC);
3093 if (s == NULL) {
3094 *alloc = 0;
3095 return (-1);
3097 *alloc = INITIAL_ALLOC;
3098 s[0] = '\0';
3099 *str = s;
3102 needed = strlen(s) + strlen(what) + 1;
3103 if (*alloc < needed) {
3104 newstr = realloc(s, needed);
3105 if (newstr == NULL)
3106 return (-1);
3107 s = newstr;
3108 *alloc = needed;
3109 *str = s;
3111 (void) strlcat(s, what, *alloc);
3113 return (0);
3116 static int
3117 pa_ace_access_mask(pr_context_t *context, ace_t *ace, int status, int flag)
3119 int returnstat, i;
3120 uval_t uval;
3121 char *permstr = NULL;
3122 size_t permstr_alloc = 0;
3124 if (status < 0)
3125 return (status);
3128 * TRANSLATION_NOTE
3129 * ace->a_access_mask refers to access mask of ZFS/NFSv4 ACL entry.
3131 if ((returnstat = open_tag(context, TAG_ACEMASK)) != 0)
3132 return (returnstat);
3133 if (context->format & PRF_SHORTM &&
3134 ((permstr = malloc(15)) != NULL)) {
3135 for (i = 0; i < 14; i++)
3136 permstr[i] = '-';
3138 if (ace->a_access_mask & ACE_READ_DATA)
3139 permstr[0] = 'r';
3140 if (ace->a_access_mask & ACE_WRITE_DATA)
3141 permstr[1] = 'w';
3142 if (ace->a_access_mask & ACE_EXECUTE)
3143 permstr[2] = 'x';
3144 if (ace->a_access_mask & ACE_APPEND_DATA)
3145 permstr[3] = 'p';
3146 if (ace->a_access_mask & ACE_DELETE)
3147 permstr[4] = 'd';
3148 if (ace->a_access_mask & ACE_DELETE_CHILD)
3149 permstr[5] = 'D';
3150 if (ace->a_access_mask & ACE_READ_ATTRIBUTES)
3151 permstr[6] = 'a';
3152 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES)
3153 permstr[7] = 'A';
3154 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS)
3155 permstr[8] = 'R';
3156 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS)
3157 permstr[9] = 'W';
3158 if (ace->a_access_mask & ACE_READ_ACL)
3159 permstr[10] = 'c';
3160 if (ace->a_access_mask & ACE_WRITE_ACL)
3161 permstr[11] = 'C';
3162 if (ace->a_access_mask & ACE_WRITE_OWNER)
3163 permstr[12] = 'o';
3164 if (ace->a_access_mask & ACE_SYNCHRONIZE)
3165 permstr[13] = 's';
3166 permstr[14] = '\0';
3167 uval.uvaltype = PRA_STRING;
3168 uval.string_val = permstr;
3169 } else if (!(context->format & PRF_RAWM)) {
3172 * Note this differs from acltext.c:ace_perm_txt()
3173 * because we don't know if the acl belongs to a file
3174 * or directory. ace mask value are the same
3175 * nonetheless, see sys/acl.h
3177 if (ace->a_access_mask & ACE_LIST_DIRECTORY) {
3178 returnstat = strappend(&permstr, gettext(READ_DIR_TXT),
3179 &permstr_alloc);
3181 if (ace->a_access_mask & ACE_ADD_FILE) {
3182 returnstat = strappend(&permstr, gettext(ADD_FILE_TXT),
3183 &permstr_alloc);
3185 if (ace->a_access_mask & ACE_ADD_SUBDIRECTORY) {
3186 returnstat = strappend(&permstr, gettext(ADD_DIR_TXT),
3187 &permstr_alloc);
3189 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS) {
3190 returnstat = strappend(&permstr,
3191 gettext(READ_XATTR_TXT), &permstr_alloc);
3193 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS) {
3194 returnstat = strappend(&permstr,
3195 gettext(WRITE_XATTR_TXT), &permstr_alloc);
3197 if (ace->a_access_mask & ACE_EXECUTE) {
3198 returnstat = strappend(&permstr,
3199 gettext(EXECUTE_TXT), &permstr_alloc);
3201 if (ace->a_access_mask & ACE_DELETE_CHILD) {
3202 returnstat = strappend(&permstr,
3203 gettext(DELETE_CHILD_TXT), &permstr_alloc);
3205 if (ace->a_access_mask & ACE_READ_ATTRIBUTES) {
3206 returnstat = strappend(&permstr,
3207 gettext(READ_ATTRIBUTES_TXT), &permstr_alloc);
3209 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES) {
3210 returnstat = strappend(&permstr,
3211 gettext(WRITE_ATTRIBUTES_TXT), &permstr_alloc);
3213 if (ace->a_access_mask & ACE_DELETE) {
3214 returnstat = strappend(&permstr, gettext(DELETE_TXT),
3215 &permstr_alloc);
3217 if (ace->a_access_mask & ACE_READ_ACL) {
3218 returnstat = strappend(&permstr, gettext(READ_ACL_TXT),
3219 &permstr_alloc);
3221 if (ace->a_access_mask & ACE_WRITE_ACL) {
3222 returnstat = strappend(&permstr, gettext(WRITE_ACL_TXT),
3223 &permstr_alloc);
3225 if (ace->a_access_mask & ACE_WRITE_OWNER) {
3226 returnstat = strappend(&permstr,
3227 gettext(WRITE_OWNER_TXT), &permstr_alloc);
3229 if (ace->a_access_mask & ACE_SYNCHRONIZE) {
3230 returnstat = strappend(&permstr,
3231 gettext(SYNCHRONIZE_TXT), &permstr_alloc);
3233 if (permstr[strlen(permstr) - 1] == '/')
3234 permstr[strlen(permstr) - 1] = '\0';
3235 uval.uvaltype = PRA_STRING;
3236 uval.string_val = permstr;
3238 if ((permstr == NULL) || (returnstat != 0) ||
3239 (context->format & PRF_RAWM)) {
3240 uval.uvaltype = PRA_UINT32;
3241 uval.uint32_val = ace->a_access_mask;
3243 returnstat = pa_print(context, &uval, flag);
3245 if (permstr != NULL)
3246 free(permstr);
3247 if (returnstat != 0)
3248 return (returnstat);
3249 return (close_tag(context, TAG_ACEMASK));
3252 static int
3253 pa_ace_type(pr_context_t *context, ace_t *ace, int status, int flag)
3255 int returnstat;
3256 uval_t uval;
3258 if (status < 0)
3259 return (status);
3262 * TRANSLATION_NOTE
3263 * ace->a_type refers to access type of ZFS/NFSv4 ACL entry.
3265 if ((returnstat = open_tag(context, TAG_ACETYPE)) != 0)
3266 return (returnstat);
3267 if (!(context->format & PRF_RAWM)) {
3268 uval.uvaltype = PRA_STRING;
3269 switch (ace->a_type) {
3270 case ACE_ACCESS_ALLOWED_ACE_TYPE:
3271 uval.string_val = gettext(ALLOW_TXT);
3272 break;
3273 case ACE_ACCESS_DENIED_ACE_TYPE:
3274 uval.string_val = gettext(DENY_TXT);
3275 break;
3276 case ACE_SYSTEM_AUDIT_ACE_TYPE:
3277 uval.string_val = gettext(AUDIT_TXT);
3278 break;
3279 case ACE_SYSTEM_ALARM_ACE_TYPE:
3280 uval.string_val = gettext(ALARM_TXT);
3281 break;
3282 default:
3283 uval.string_val = gettext(UNKNOWN_TXT);
3285 } else {
3286 uval.uvaltype = PRA_USHORT;
3287 uval.uint32_val = ace->a_type;
3289 if ((returnstat = pa_print(context, &uval, flag)) != 0)
3290 return (returnstat);
3291 return (close_tag(context, TAG_ACETYPE));
3295 pa_ace(pr_context_t *context, int status, int flag)
3297 int returnstat;
3298 ace_t ace;
3300 if (status < 0)
3301 return (status);
3303 if ((returnstat = pr_adr_u_int32(context, &ace.a_who, 1)) != 0)
3304 return (returnstat);
3305 if ((returnstat = pr_adr_u_int32(context, &ace.a_access_mask, 1)) != 0)
3306 return (returnstat);
3307 if ((returnstat = pr_adr_u_short(context, &ace.a_flags, 1)) != 0)
3308 return (returnstat);
3309 if ((returnstat = pr_adr_u_short(context, &ace.a_type, 1)) != 0)
3310 return (returnstat);
3312 if ((returnstat = pa_ace_flags(context, &ace, returnstat, 0)) != 0)
3313 return (returnstat);
3314 /* pa_ace_who can returns 1 if uid/gid is not found */
3315 if ((returnstat = pa_ace_who(context, &ace, returnstat, 0)) < 0)
3316 return (returnstat);
3317 if ((returnstat = pa_ace_access_mask(context, &ace,
3318 returnstat, 0)) != 0)
3319 return (returnstat);
3320 return (pa_ace_type(context, &ace, returnstat, flag));