dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / praudit / format.c
blob321038ae4c36576db05f33fbf0d252a5c8d52e82
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.
26 #include <ctype.h>
27 #include <errno.h>
28 #include <grp.h>
29 #include <libintl.h>
30 #include <netdb.h>
31 #include <time.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <wchar.h>
38 #include <arpa/inet.h>
40 #include <bsm/audit.h>
41 #include <bsm/audit_record.h>
42 #include <bsm/libbsm.h>
43 #include <security/pam_appl.h>
45 #include <sys/inttypes.h>
46 #include <sys/mkdev.h>
47 #include <sys/types.h>
48 #include <aclutils.h>
50 #include "praudit.h"
51 #include "toktable.h"
52 #include "adt_xlate.h"
54 static void convertascii(char *p, char *c, int size);
55 static int convertbinary(char *p, char *c, int size);
56 static void eventmodifier2string(au_emod_t emodifier, char *modstring,
57 size_t modlen);
58 static int do_mtime32(pr_context_t *context, int status, int flag,
59 uint32_t scale);
60 static int do_mtime64(pr_context_t *context, int status, int flag,
61 uint64_t scale);
64 * ------------------------------------------------------
65 * field widths for arbitrary data token type
66 * ------------------------------------------------------
68 static struct fw {
69 char basic_unit;
70 struct {
71 char print_base;
72 int field_width;
73 } pwidth[5];
74 } fwidth[] = {
75 /* character data type, 8 bits */
76 AUR_CHAR, AUP_BINARY, 12,
77 AUP_OCTAL, 6,
78 AUP_DECIMAL, 6,
79 AUP_HEX, 6,
80 AUP_STRING, 1,
81 AUR_BYTE, AUP_BINARY, 12,
82 AUP_OCTAL, 6,
83 AUP_DECIMAL, 6,
84 AUP_HEX, 6,
85 AUP_STRING, 1,
86 AUR_SHORT, AUP_BINARY, 20,
87 AUP_OCTAL, 10,
88 AUP_DECIMAL, 10,
89 AUP_HEX, 8,
90 AUP_STRING, 6,
91 AUR_INT32, AUP_BINARY, 36,
92 AUP_OCTAL, 18,
93 AUP_DECIMAL, 18,
94 AUP_HEX, 12,
95 AUP_STRING, 10,
96 AUR_INT64, AUP_BINARY, 68,
97 AUP_OCTAL, 34,
98 AUP_DECIMAL, 34,
99 AUP_HEX, 20,
100 AUP_STRING, 20};
103 static int numwidthentries = sizeof (fwidth)
104 / sizeof (struct fw);
108 * -----------------------------------------------------------------------
109 * do_newline:
110 * Print a newline, if needed according to various formatting
111 * rules.
112 * return codes : 0 - success
113 * : -1 - error
114 * -----------------------------------------------------------------------
117 do_newline(pr_context_t *context, int flag)
119 int retstat = 0;
121 if (!(context->format & PRF_ONELINE) && (flag == 1))
122 retstat = pr_putchar(context, '\n');
123 else if (!(context->format & PRF_XMLM))
124 retstat = pr_printf(context, "%s", context->SEPARATOR);
126 return (retstat);
130 open_tag(pr_context_t *context, int tagnum)
132 int err = 0;
133 token_desc_t *tag;
135 /* no-op if not doing XML format */
136 if (!(context->format & PRF_XMLM))
137 return (0);
139 tag = &tokentable[tagnum];
142 * First if needed do an implicit finish of a pending open for an
143 * extended tag. I.e., for the extended tag xxx:
144 * <xxx a=".." b=".."> ... </xxx>
145 * -- insert a close bracket after the last attribute
146 * (in other words, when the 1st non-attribute is opened while
147 * this is pending). Note that only one tag could be pending at
148 * a given time -- it couldn't be nested.
150 if (context->pending_flag && (tag->t_type != T_ATTRIBUTE)) {
151 /* complete pending extended open */
152 err = pr_putchar(context, '>');
153 if (err != 0)
154 return (err);
155 context->pending_flag = 0;
158 if (is_header_token(tagnum) || is_file_token(tagnum)) {
159 /* File token or new record on new line */
160 err = pr_putchar(context, '\n');
161 } else if (is_token(tagnum)) {
162 /* Each token on new line if possible */
163 err = do_newline(context, 1);
165 if (err != 0)
166 return (err);
168 switch (tag->t_type) {
169 case T_ATTRIBUTE:
170 err = pr_printf(context, " %s=\"", tag->t_tagname);
171 break;
172 case T_ELEMENT:
173 err = pr_printf(context, "<%s>", tag->t_tagname);
174 break;
175 case T_ENCLOSED:
176 err = pr_printf(context, "<%s", tag->t_tagname);
177 break;
178 case T_EXTENDED:
179 err = pr_printf(context, "<%s", tag->t_tagname);
180 if (err == 0)
181 context->pending_flag = tagnum;
182 break;
183 default:
184 break;
187 if (is_header_token(tagnum) && (err == 0))
188 context->current_rec = tagnum; /* set start of new record */
190 return (err);
194 * Do an implicit close of a record when needed.
197 check_close_rec(pr_context_t *context, int tagnum)
199 int err = 0;
201 /* no-op if not doing XML format */
202 if (!(context->format & PRF_XMLM))
203 return (0);
206 * If we're opening a header or the file token (i.e., starting a new
207 * record), if there's a current record in progress do an implicit
208 * close of it.
210 if ((is_header_token(tagnum) || is_file_token(tagnum)) &&
211 context->current_rec) {
212 err = do_newline(context, 1);
213 if (err == 0)
214 err = close_tag(context, context->current_rec);
217 return (err);
221 * explicit finish of a pending open for an extended tag.
224 finish_open_tag(pr_context_t *context)
226 int err = 0;
228 /* no-op if not doing XML format */
229 if (!(context->format & PRF_XMLM))
230 return (0);
232 if (context->pending_flag) {
233 /* complete pending extended open */
234 err = pr_putchar(context, '>');
235 if (err == 0)
236 context->pending_flag = 0;
238 return (err);
242 close_tag(pr_context_t *context, int tagnum)
244 int err = 0;
245 token_desc_t *tag;
247 /* no-op if not doing XML format */
248 if (!(context->format & PRF_XMLM))
249 return (0);
251 tag = &tokentable[tagnum];
253 switch (tag->t_type) {
254 case T_ATTRIBUTE:
255 err = pr_putchar(context, '\"');
256 break;
257 case T_ELEMENT:
258 err = pr_printf(context, "</%s>", tag->t_tagname);
259 break;
260 case T_ENCLOSED:
261 err = pr_printf(context, "/>");
262 break;
263 case T_EXTENDED:
264 err = pr_printf(context, "</%s>", tag->t_tagname);
265 break;
266 default:
267 break;
270 if (is_header_token(tagnum) && (err == 0))
271 context->current_rec = 0; /* closing rec; none current */
273 return (err);
277 * -----------------------------------------------------------------------
278 * process_tag:
279 * Calls the routine corresponding to the tag
280 * Note that to use this mechanism, all such routines must
281 * take 2 ints for their parameters; the first of these is
282 * the current status.
284 * flag = 1 for newline / delimiter, else 0
285 * return codes : -1 - error
286 * : 0 - successful
287 * -----------------------------------------------------------------------
290 process_tag(pr_context_t *context, int tagnum, int status, int flag)
292 int retstat;
294 retstat = status;
296 if (retstat)
297 return (retstat);
299 if ((tagnum > 0) && (tagnum <= MAXTAG) &&
300 (tokentable[tagnum].func != NOFUNC)) {
301 retstat = open_tag(context, tagnum);
302 if (!retstat)
303 retstat = (*tokentable[tagnum].func)(context, status,
304 flag);
305 if (!retstat)
306 retstat = close_tag(context, tagnum);
307 return (retstat);
309 /* here if token id is not in table */
310 (void) fprintf(stderr, gettext("praudit: No code associated with "
311 "tag id %d\n"), tagnum);
312 return (0);
315 void
316 get_Hname(uint32_t addr, char *buf, size_t buflen)
318 extern char *inet_ntoa(const struct in_addr);
319 struct hostent *phe;
320 struct in_addr ia;
322 phe = gethostbyaddr((const char *)&addr, 4, AF_INET);
323 if (phe == NULL) {
324 ia.s_addr = addr;
325 (void) snprintf(buf, buflen, "%s", inet_ntoa(ia));
326 return;
328 ia.s_addr = addr;
329 (void) snprintf(buf, buflen, "%s", phe->h_name);
332 void
333 get_Hname_ex(uint32_t *addr, char *buf, size_t buflen)
335 struct hostent *phe;
336 int err;
338 phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
340 if (phe == NULL) {
341 (void) inet_ntop(AF_INET6, (void *)addr, buf, buflen);
342 } else
343 (void) snprintf(buf, buflen, "%s", phe->h_name);
345 if (phe)
346 freehostent(phe);
350 pa_hostname(pr_context_t *context, int status, int flag)
352 int returnstat;
353 uint32_t ip_addr;
354 struct in_addr ia;
355 uval_t uval;
356 char buf[256];
358 if (status < 0)
359 return (status);
361 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
362 return (returnstat);
364 uval.uvaltype = PRA_STRING;
366 if (!(context->format & PRF_RAWM)) {
367 uval.string_val = buf;
368 get_Hname(ip_addr, buf, sizeof (buf));
369 returnstat = pa_print(context, &uval, flag);
370 } else {
371 ia.s_addr = ip_addr;
372 if ((uval.string_val = inet_ntoa(ia)) == NULL)
373 return (-1);
374 returnstat = pa_print(context, &uval, flag);
376 return (returnstat);
380 pa_hostname_ex(pr_context_t *context, int status, int flag)
382 int returnstat;
383 uint32_t ip_type;
384 uint32_t ip_addr[4];
385 struct in_addr ia;
386 char buf[256];
387 uval_t uval;
389 if (status < 0)
390 return (status);
392 /* get ip type */
393 if ((returnstat = pr_adr_int32(context, (int32_t *)&ip_type, 1)) != 0)
394 return (returnstat);
396 /* only IPv4 and IPv6 addresses are legal */
397 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
398 return (-1);
400 /* get ip address */
401 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
402 return (returnstat);
404 if ((returnstat = open_tag(context, TAG_HOSTID)) != 0)
405 return (returnstat);
407 uval.uvaltype = PRA_STRING;
408 if (ip_type == AU_IPv4) { /* ipv4 address */
409 if (!(context->format & PRF_RAWM)) {
410 uval.string_val = buf;
411 get_Hname(ip_addr[0], buf, sizeof (buf));
412 returnstat = pa_print(context, &uval, flag);
413 } else {
414 ia.s_addr = ip_addr[0];
415 if ((uval.string_val = inet_ntoa(ia)) == NULL)
416 return (-1);
417 returnstat = pa_print(context, &uval, flag);
419 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
420 if (!(context->format & PRF_RAWM)) {
421 uval.string_val = buf;
422 get_Hname_ex(ip_addr, buf, sizeof (buf));
423 returnstat = pa_print(context, &uval, flag);
424 } else {
425 uval.string_val = (char *)buf;
426 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
427 sizeof (buf));
428 returnstat = pa_print(context, &uval, flag);
432 if (returnstat != 0)
433 return (returnstat);
434 return (close_tag(context, TAG_HOSTID));
438 pa_hostname_so(pr_context_t *context, int status, int flag)
440 int returnstat;
441 short ip_type;
442 ushort_t ip_port;
443 uint32_t ip_addr[4];
444 struct in_addr ia;
445 char buf[256];
446 uval_t uval;
448 if (status < 0)
449 return (status);
451 /* get ip type */
452 if ((returnstat = pr_adr_short(context, &ip_type, 1)) != 0)
453 return (returnstat);
455 /* only IPv4 and IPv6 addresses are legal */
456 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
457 return (-1);
459 /* get local ip port */
460 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
461 return (returnstat);
463 if ((returnstat = open_tag(context, TAG_SOCKEXLPORT)) != 0)
464 return (returnstat);
466 uval.uvaltype = PRA_STRING;
467 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
468 sizeof (ip_port));
469 if (uval.string_val) {
470 returnstat = pa_print(context, &uval, 0);
471 free(uval.string_val);
472 } else
473 returnstat = -1;
474 if (returnstat)
475 return (returnstat);
477 if ((returnstat = close_tag(context, TAG_SOCKEXLPORT)) != 0)
478 return (returnstat);
480 /* get local ip address */
481 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
482 return (returnstat);
484 if ((returnstat = open_tag(context, TAG_SOCKEXLADDR)) != 0)
485 return (returnstat);
487 if (ip_type == AU_IPv4) { /* ipv4 address */
489 if (!(context->format & PRF_RAWM)) {
490 uval.string_val = buf;
491 get_Hname(ip_addr[0], buf, sizeof (buf));
492 returnstat = pa_print(context, &uval, 0);
493 } else {
494 ia.s_addr = ip_addr[0];
495 if ((uval.string_val = inet_ntoa(ia)) == NULL)
496 return (-1);
497 returnstat = pa_print(context, &uval, 0);
500 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
502 if (!(context->format & PRF_RAWM)) {
503 uval.string_val = buf;
504 get_Hname_ex(ip_addr, buf, sizeof (buf));
505 returnstat = pa_print(context, &uval, 0);
506 } else {
507 uval.string_val = (char *)buf;
508 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
509 sizeof (buf));
510 returnstat = pa_print(context, &uval, 0);
512 } else
513 returnstat = -1;
515 if (returnstat)
516 return (returnstat);
518 if ((returnstat = close_tag(context, TAG_SOCKEXLADDR)) != 0)
519 return (returnstat);
521 /* get foreign ip port */
522 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
523 return (returnstat);
525 if ((returnstat = open_tag(context, TAG_SOCKEXFPORT)) != 0)
526 return (returnstat);
528 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
529 sizeof (ip_port));
530 if (uval.string_val) {
531 returnstat = pa_print(context, &uval, 0);
532 free(uval.string_val);
533 } else
534 returnstat = -1;
536 if (returnstat)
537 return (returnstat);
539 if ((returnstat = close_tag(context, TAG_SOCKEXFPORT)) != 0)
540 return (returnstat);
542 /* get foreign ip address */
543 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
544 return (returnstat);
546 if ((returnstat = open_tag(context, TAG_SOCKEXFADDR)) != 0)
547 return (returnstat);
549 if (ip_type == AU_IPv4) { /* ipv4 address */
551 if (!(context->format & PRF_RAWM)) {
552 uval.string_val = buf;
553 get_Hname(ip_addr[0], buf, sizeof (buf));
554 returnstat = pa_print(context, &uval, flag);
555 } else {
556 ia.s_addr = ip_addr[0];
557 if ((uval.string_val = inet_ntoa(ia)) == NULL)
558 return (-1);
559 returnstat = pa_print(context, &uval, flag);
562 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
564 if (!(context->format & PRF_RAWM)) {
565 uval.string_val = buf;
566 get_Hname_ex(ip_addr, buf, sizeof (buf));
567 returnstat = pa_print(context, &uval, flag);
568 } else {
569 uval.string_val = (char *)buf;
570 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
571 sizeof (buf));
572 returnstat = pa_print(context, &uval, flag);
574 } else
575 returnstat = -1;
577 if (returnstat)
578 return (returnstat);
580 if ((returnstat = close_tag(context, TAG_SOCKEXFADDR)) != 0)
581 return (returnstat);
583 return (returnstat);
587 #define NBITSMAJOR64 32 /* # of major device bits in 64-bit Solaris */
588 #define NBITSMINOR64 32 /* # of minor device bits in 64-bit Solaris */
589 #define MAXMAJ64 0xfffffffful /* max major value */
590 #define MAXMIN64 0xfffffffful /* max minor value */
592 #define NBITSMAJOR32 14 /* # of SVR4 major device bits */
593 #define NBITSMINOR32 18 /* # of SVR4 minor device bits */
594 #define NMAXMAJ32 0x3fff /* SVR4 max major value */
595 #define NMAXMIN32 0x3ffff /* MAX minor for 3b2 software drivers. */
598 static int32_t
599 minor_64(uint64_t dev)
601 if (dev == NODEV) {
602 errno = EINVAL;
603 return (NODEV);
605 return (int32_t)(dev & MAXMIN64);
608 static int32_t
609 major_64(uint64_t dev)
611 uint32_t maj;
613 maj = (uint32_t)(dev >> NBITSMINOR64);
615 if (dev == NODEV || maj > MAXMAJ64) {
616 errno = EINVAL;
617 return (NODEV);
619 return (int32_t)(maj);
622 static int32_t
623 minor_32(uint32_t dev)
625 if (dev == NODEV) {
626 errno = EINVAL;
627 return (NODEV);
629 return (int32_t)(dev & MAXMIN32);
632 static int32_t
633 major_32(uint32_t dev)
635 uint32_t maj;
637 maj = (uint32_t)(dev >> NBITSMINOR32);
639 if (dev == NODEV || maj > MAXMAJ32) {
640 errno = EINVAL;
641 return (NODEV);
643 return (int32_t)(maj);
648 * -----------------------------------------------------------------------
649 * pa_tid() : Process terminal id and display contents
650 * return codes : -1 - error
651 * : 0 - successful
653 * terminal id port adr_int32
654 * terminal id machine adr_int32
655 * -----------------------------------------------------------------------
658 pa_tid32(pr_context_t *context, int status, int flag)
660 int returnstat;
661 int32_t dev_maj_min;
662 uint32_t ip_addr;
663 struct in_addr ia;
664 char *ipstring;
665 char buf[256];
666 uval_t uval;
668 if (status < 0)
669 return (status);
671 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
672 return (returnstat);
674 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
675 return (returnstat);
677 uval.uvaltype = PRA_STRING;
678 uval.string_val = buf;
680 if (!(context->format & PRF_RAWM)) {
681 char hostname[256];
683 get_Hname(ip_addr, hostname, sizeof (hostname));
684 (void) snprintf(buf, sizeof (buf), "%d %d %s",
685 major_32(dev_maj_min),
686 minor_32(dev_maj_min),
687 hostname);
688 return (pa_print(context, &uval, flag));
691 ia.s_addr = ip_addr;
692 if ((ipstring = inet_ntoa(ia)) == NULL)
693 return (-1);
695 (void) snprintf(buf, sizeof (buf), "%d %d %s", major_32(dev_maj_min),
696 minor_32(dev_maj_min),
697 ipstring);
699 return (pa_print(context, &uval, flag));
703 pa_tid32_ex(pr_context_t *context, int status, int flag)
705 int returnstat;
706 int32_t dev_maj_min;
707 uint32_t ip_addr[16];
708 uint32_t ip_type;
709 struct in_addr ia;
710 char *ipstring;
711 char hostname[256];
712 char buf[256];
713 char tbuf[256];
714 uval_t uval;
716 if (status < 0)
717 return (status);
719 /* get port info */
720 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
721 return (returnstat);
723 /* get address type */
724 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
725 return (returnstat);
727 /* legal address types are either AU_IPv4 or AU_IPv6 only */
728 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
729 return (-1);
731 /* get address (4/16) */
732 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
733 return (returnstat);
735 uval.uvaltype = PRA_STRING;
736 if (ip_type == AU_IPv4) {
737 uval.string_val = buf;
739 if (!(context->format & PRF_RAWM)) {
740 get_Hname(ip_addr[0], hostname, sizeof (hostname));
741 (void) snprintf(buf, sizeof (buf), "%d %d %s",
742 major_32(dev_maj_min), minor_32(dev_maj_min),
743 hostname);
744 return (pa_print(context, &uval, flag));
747 ia.s_addr = ip_addr[0];
748 if ((ipstring = inet_ntoa(ia)) == NULL)
749 return (-1);
751 (void) snprintf(buf, sizeof (buf), "%d %d %s",
752 major_32(dev_maj_min), minor_32(dev_maj_min), ipstring);
754 return (pa_print(context, &uval, flag));
755 } else {
756 uval.string_val = buf;
758 if (!(context->format & PRF_RAWM)) {
759 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
760 (void) snprintf(buf, sizeof (buf), "%d %d %s",
761 major_32(dev_maj_min), minor_32(dev_maj_min),
762 hostname);
763 return (pa_print(context, &uval, flag));
766 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
767 sizeof (tbuf));
769 (void) snprintf(buf, sizeof (buf), "%d %d %s",
770 major_32(dev_maj_min), minor_32(dev_maj_min), tbuf);
772 return (pa_print(context, &uval, flag));
777 pa_ip_addr(pr_context_t *context, int status, int flag)
779 int returnstat;
780 uval_t uval;
781 uint32_t ip_addr[4];
782 uint32_t ip_type;
783 struct in_addr ia;
784 char *ipstring;
785 char hostname[256];
786 char buf[256];
787 char tbuf[256];
789 if (status < 0)
790 return (status);
792 /* get address type */
793 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
794 return (returnstat);
796 /* legal address type is AU_IPv4 or AU_IPv6 */
797 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
798 return (-1);
800 /* get address (4/16) */
801 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
802 return (returnstat);
804 uval.uvaltype = PRA_STRING;
805 if (ip_type == AU_IPv4) {
806 uval.string_val = buf;
808 if (!(context->format & PRF_RAWM)) {
809 get_Hname(ip_addr[0], hostname, sizeof (hostname));
810 (void) snprintf(buf, sizeof (buf), "%s", hostname);
811 return (pa_print(context, &uval, flag));
814 ia.s_addr = ip_addr[0];
815 if ((ipstring = inet_ntoa(ia)) == NULL)
816 return (-1);
818 (void) snprintf(buf, sizeof (buf), "%s", ipstring);
820 return (pa_print(context, &uval, flag));
821 } else {
822 uval.string_val = buf;
824 if (!(context->format & PRF_RAWM)) {
825 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
826 (void) snprintf(buf, sizeof (buf), "%s",
827 hostname);
828 return (pa_print(context, &uval, flag));
831 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
832 sizeof (tbuf));
834 (void) snprintf(buf, sizeof (buf), "%s", tbuf);
836 return (pa_print(context, &uval, flag));
842 pa_tid64(pr_context_t *context, int status, int flag)
844 int returnstat;
845 int64_t dev_maj_min;
846 uint32_t ip_addr;
847 struct in_addr ia;
848 char *ipstring;
849 char buf[256];
850 uval_t uval;
852 if (status < 0)
853 return (status);
855 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
856 return (returnstat);
858 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
859 return (returnstat);
861 uval.uvaltype = PRA_STRING;
862 uval.string_val = buf;
864 if (!(context->format & PRF_RAWM)) {
865 char hostname[256];
867 get_Hname(ip_addr, hostname, sizeof (hostname));
868 (void) snprintf(buf, sizeof (buf), "%d %d %s",
869 major_64(dev_maj_min), minor_64(dev_maj_min), hostname);
870 return (pa_print(context, &uval, flag));
873 ia.s_addr = ip_addr;
874 if ((ipstring = inet_ntoa(ia)) == NULL)
875 return (-1);
877 (void) snprintf(buf, sizeof (buf), "%d %d %s",
878 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
880 return (pa_print(context, &uval, flag));
884 pa_tid64_ex(pr_context_t *context, int status, int flag)
886 int returnstat;
887 int64_t dev_maj_min;
888 uint32_t ip_addr[4];
889 uint32_t ip_type;
890 struct in_addr ia;
891 char *ipstring;
892 char hostname[256];
893 char buf[256];
894 char tbuf[256];
895 uval_t uval;
897 if (status < 0)
898 return (status);
900 /* get port info */
901 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
902 return (returnstat);
904 /* get address type */
905 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
906 return (returnstat);
908 /* legal address types are either AU_IPv4 or AU_IPv6 only */
909 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
910 return (-1);
912 /* get address (4/16) */
913 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, ip_type)) != 0)
914 return (returnstat);
916 uval.uvaltype = PRA_STRING;
917 if (ip_type == AU_IPv4) {
918 uval.string_val = buf;
920 if (!(context->format & PRF_RAWM)) {
921 get_Hname(ip_addr[0], hostname, sizeof (hostname));
922 uval.string_val = buf;
923 (void) snprintf(buf, sizeof (buf), "%d %d %s",
924 major_64(dev_maj_min), minor_64(dev_maj_min),
925 hostname);
926 return (pa_print(context, &uval, flag));
929 ia.s_addr = ip_addr[0];
930 if ((ipstring = inet_ntoa(ia)) == NULL)
931 return (-1);
933 (void) snprintf(buf, sizeof (buf), "%d %d %s",
934 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
936 return (pa_print(context, &uval, flag));
937 } else {
938 uval.string_val = buf;
940 if (!(context->format & PRF_RAWM)) {
941 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
942 (void) snprintf(buf, sizeof (buf), "%d %d %s",
943 major_64(dev_maj_min), minor_64(dev_maj_min),
944 hostname);
945 return (pa_print(context, &uval, flag));
948 (void) inet_ntop(AF_INET6, (void *)ip_addr, tbuf,
949 sizeof (tbuf));
951 (void) snprintf(buf, sizeof (buf), "%d %d %s",
952 major_64(dev_maj_min), minor_64(dev_maj_min), tbuf);
954 return (pa_print(context, &uval, flag));
960 * ----------------------------------------------------------------
961 * findfieldwidth:
962 * Returns the field width based on the basic unit and print mode.
963 * This routine is called to determine the field width for the
964 * data items in the arbitrary data token where the tokens are
965 * to be printed in more than one line. The field width can be
966 * found in the fwidth structure.
968 * Input parameters:
969 * basicunit Can be one of AUR_CHAR, AUR_BYTE, AUR_SHORT,
970 * AUR_INT32, or AUR_INT64
971 * howtoprint Print mode. Can be one of AUP_BINARY, AUP_OCTAL,
972 * AUP_DECIMAL, or AUP_HEX.
973 * ----------------------------------------------------------------
976 findfieldwidth(char basicunit, char howtoprint)
978 int i, j;
980 for (i = 0; i < numwidthentries; i++) {
981 if (fwidth[i].basic_unit == basicunit) {
982 for (j = 0; j <= 4; j++) {
983 if (fwidth[i].pwidth[j].print_base ==
984 howtoprint) {
985 return (
986 fwidth[i].pwidth[j].field_width);
990 * if we got here, then we didn't get what we were after
992 return (0);
995 /* if we got here, we didn't get what we wanted either */
996 return (0);
1001 * -----------------------------------------------------------------------
1002 * pa_cmd: Retrieves the cmd item from the input stream.
1003 * return codes : -1 - error
1004 * : 0 - successful
1005 * -----------------------------------------------------------------------
1008 pa_cmd(pr_context_t *context, int status, int flag)
1010 char *cmd; /* cmd */
1011 short length;
1012 int returnstat;
1013 uval_t uval;
1016 * We need to know how much space to allocate for our string, so
1017 * read the length first, then call pr_adr_char to read those bytes.
1019 if (status >= 0) {
1020 if (pr_adr_short(context, &length, 1) == 0) {
1021 if ((cmd = (char *)malloc(length + 1)) == NULL)
1022 return (-1);
1023 if (pr_adr_char(context, cmd, length) == 0) {
1024 uval.uvaltype = PRA_STRING;
1025 uval.string_val = cmd;
1026 returnstat = pa_print(context, &uval, flag);
1027 } else {
1028 returnstat = -1;
1030 free(cmd);
1031 return (returnstat);
1032 } else
1033 return (-1);
1034 } else
1035 return (status);
1041 * -----------------------------------------------------------------------
1042 * pa_adr_byte : Issues pr_adr_char to retrieve the next ADR item from
1043 * the input stream pointed to by audit_adr, and prints it
1044 * as an integer if status >= 0
1045 * return codes : -1 - error
1046 * : 0 - successful
1047 * -----------------------------------------------------------------------
1050 pa_adr_byte(pr_context_t *context, int status, int flag)
1052 char c;
1053 uval_t uval;
1055 if (status >= 0) {
1056 if (pr_adr_char(context, &c, 1) == 0) {
1057 uval.uvaltype = PRA_BYTE;
1058 uval.char_val = c;
1059 return (pa_print(context, &uval, flag));
1060 } else
1061 return (-1);
1062 } else
1063 return (status);
1067 * -----------------------------------------------------------------------
1068 * pa_adr_charhex: Issues pr_adr_char to retrieve the next ADR item from
1069 * the input stream pointed to by audit_adr, and prints it
1070 * in hexadecimal if status >= 0
1071 * return codes : -1 - error
1072 * : 0 - successful
1073 * -----------------------------------------------------------------------
1076 pa_adr_charhex(pr_context_t *context, int status, int flag)
1078 char p[2];
1079 int returnstat;
1080 uval_t uval;
1082 if (status >= 0) {
1083 p[0] = p[1] = 0;
1085 if ((returnstat = pr_adr_char(context, p, 1)) == 0) {
1086 uval.uvaltype = PRA_STRING;
1087 uval.string_val = hexconvert(p, sizeof (char),
1088 sizeof (char));
1089 if (uval.string_val) {
1090 returnstat = pa_print(context, &uval, flag);
1091 free(uval.string_val);
1094 return (returnstat);
1095 } else
1096 return (status);
1100 * -----------------------------------------------------------------------
1101 * pa_adr_int32 : Issues pr_adr_int32 to retrieve the next ADR item from the
1102 * input stream pointed to by audit_adr, and prints it
1103 * if status >= 0
1104 * return codes : -1 - error
1105 * : 0 - successful
1106 * -----------------------------------------------------------------------
1109 pa_adr_int32(pr_context_t *context, int status, int flag)
1111 int32_t c;
1112 uval_t uval;
1114 if (status >= 0) {
1115 if (pr_adr_int32(context, &c, 1) == 0) {
1116 uval.uvaltype = PRA_INT32;
1117 uval.int32_val = c;
1118 return (pa_print(context, &uval, flag));
1119 } else
1120 return (-1);
1121 } else
1122 return (status);
1129 * -----------------------------------------------------------------------
1130 * pa_adr_int64 : Issues pr_adr_int64 to retrieve the next ADR item from the
1131 * input stream pointed to by audit_adr, and prints it
1132 * if status >= 0
1133 * return codes : -1 - error
1134 * : 0 - successful
1135 * -----------------------------------------------------------------------
1138 pa_adr_int64(pr_context_t *context, int status, int flag)
1140 int64_t c;
1141 uval_t uval;
1143 if (status >= 0) {
1144 if (pr_adr_int64(context, &c, 1) == 0) {
1145 uval.uvaltype = PRA_INT64;
1146 uval.int64_val = c;
1147 return (pa_print(context, &uval, flag));
1148 } else
1149 return (-1);
1150 } else
1151 return (status);
1155 * -----------------------------------------------------------------------
1156 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1157 * input stream pointed to by audit_adr, and prints it
1158 * in hexadecimal if status >= 0
1159 * return codes : -1 - error
1160 * : 0 - successful
1161 * -----------------------------------------------------------------------
1164 pa_adr_int32hex(pr_context_t *context, int status, int flag)
1166 int32_t l;
1167 int returnstat;
1168 uval_t uval;
1170 if (status >= 0) {
1171 if ((returnstat = pr_adr_int32(context, &l, 1)) == 0) {
1172 uval.uvaltype = PRA_HEX32;
1173 uval.int32_val = l;
1174 returnstat = pa_print(context, &uval, flag);
1176 return (returnstat);
1177 } else
1178 return (status);
1182 * -----------------------------------------------------------------------
1183 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1184 * input stream pointed to by audit_adr, and prints it
1185 * in hexadecimal if status >= 0
1186 * return codes : -1 - error
1187 * : 0 - successful
1188 * -----------------------------------------------------------------------
1191 pa_adr_int64hex(pr_context_t *context, int status, int flag)
1193 int64_t l;
1194 int returnstat;
1195 uval_t uval;
1197 if (status >= 0) {
1198 if ((returnstat = pr_adr_int64(context, &l, 1)) == 0) {
1199 uval.uvaltype = PRA_HEX64;
1200 uval.int64_val = l;
1201 returnstat = pa_print(context, &uval, flag);
1203 return (returnstat);
1204 } else
1205 return (status);
1210 * -------------------------------------------------------------------
1211 * bu2string: Maps a print basic unit type to a string.
1212 * returns : The string mapping or "unknown basic unit type".
1213 * -------------------------------------------------------------------
1215 char *
1216 bu2string(char basic_unit)
1218 register int i;
1220 struct bu_map_ent {
1221 char basic_unit;
1222 char *string;
1226 * TRANSLATION_NOTE
1227 * These names are data units when displaying the arbitrary data
1228 * token.
1231 static struct bu_map_ent bu_map[] = {
1232 { AUR_BYTE, "byte" },
1233 { AUR_CHAR, "char" },
1234 { AUR_SHORT, "short" },
1235 { AUR_INT32, "int32" },
1236 { AUR_INT64, "int64" } };
1238 for (i = 0; i < sizeof (bu_map) / sizeof (struct bu_map_ent); i++)
1239 if (basic_unit == bu_map[i].basic_unit)
1240 return (gettext(bu_map[i].string));
1242 return (gettext("unknown basic unit type"));
1247 * -------------------------------------------------------------------
1248 * eventmodifier2string: Maps event modifier flags to a readable string.
1249 * returns: The string mapping or "none".
1250 * -------------------------------------------------------------------
1252 static void
1253 eventmodifier2string(au_emod_t emodifier, char *modstring, size_t modlen)
1255 register int i, j;
1257 struct em_map_ent {
1258 int mask;
1259 char *string;
1263 * TRANSLATION_NOTE
1264 * These abbreviations represent the event modifier field of the
1265 * header token. To gain a better understanding of each modifier,
1266 * read
1267 * System Administration Guide: Security Services >> Solaris Auditing
1268 * at http://docs.sun.com.
1271 static struct em_map_ent em_map[] = {
1272 { (int)PAD_READ, "rd" }, /* data read from object */
1273 { (int)PAD_WRITE, "wr" }, /* data written to object */
1274 { (int)PAD_SPRIVUSE, "sp" }, /* successfully used priv */
1275 { (int)PAD_FPRIVUSE, "fp" }, /* failed use of priv */
1276 { (int)PAD_NONATTR, "na" }, /* non-attributable event */
1277 { (int)PAD_FAILURE, "fe" } /* fail audit event */
1280 modstring[0] = '\0';
1282 for (i = 0, j = 0; i < sizeof (em_map) / sizeof (struct em_map_ent);
1283 i++) {
1284 if ((int)emodifier & em_map[i].mask) {
1285 if (j++)
1286 (void) strlcat(modstring, ":", modlen);
1287 (void) strlcat(modstring, em_map[i].string, modlen);
1294 * ---------------------------------------------------------
1295 * convert_char_to_string:
1296 * Converts a byte to string depending on the print mode
1297 * input : printmode, which may be one of AUP_BINARY,
1298 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1299 * c, which is the byte to convert
1300 * output : p, which is a pointer to the location where
1301 * the resulting string is to be stored
1302 * ----------------------------------------------------------
1306 convert_char_to_string(char printmode, char c, char *p)
1308 union {
1309 char c1[4];
1310 int c2;
1311 } dat;
1313 dat.c2 = 0;
1314 dat.c1[3] = c;
1316 if (printmode == AUP_BINARY)
1317 (void) convertbinary(p, &c, sizeof (char));
1318 else if (printmode == AUP_OCTAL)
1319 (void) sprintf(p, "%o", (int)dat.c2);
1320 else if (printmode == AUP_DECIMAL)
1321 (void) sprintf(p, "%d", c);
1322 else if (printmode == AUP_HEX)
1323 (void) sprintf(p, "0x%x", (int)dat.c2);
1324 else if (printmode == AUP_STRING)
1325 convertascii(p, &c, sizeof (char));
1326 return (0);
1330 * --------------------------------------------------------------
1331 * convert_short_to_string:
1332 * Converts a short integer to string depending on the print mode
1333 * input : printmode, which may be one of AUP_BINARY,
1334 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1335 * c, which is the short integer to convert
1336 * output : p, which is a pointer to the location where
1337 * the resulting string is to be stored
1338 * ---------------------------------------------------------------
1341 convert_short_to_string(char printmode, short c, char *p)
1343 union {
1344 short c1[2];
1345 int c2;
1346 } dat;
1348 dat.c2 = 0;
1349 dat.c1[1] = c;
1351 if (printmode == AUP_BINARY)
1352 (void) convertbinary(p, (char *)&c, sizeof (short));
1353 else if (printmode == AUP_OCTAL)
1354 (void) sprintf(p, "%o", (int)dat.c2);
1355 else if (printmode == AUP_DECIMAL)
1356 (void) sprintf(p, "%hd", c);
1357 else if (printmode == AUP_HEX)
1358 (void) sprintf(p, "0x%x", (int)dat.c2);
1359 else if (printmode == AUP_STRING)
1360 convertascii(p, (char *)&c, sizeof (short));
1361 return (0);
1365 * ---------------------------------------------------------
1366 * convert_int32_to_string:
1367 * Converts a integer to string depending on the print mode
1368 * input : printmode, which may be one of AUP_BINARY,
1369 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1370 * c, which is the integer to convert
1371 * output : p, which is a pointer to the location where
1372 * the resulting string is to be stored
1373 * ----------------------------------------------------------
1376 convert_int32_to_string(char printmode, int32_t c, char *p)
1378 if (printmode == AUP_BINARY)
1379 (void) convertbinary(p, (char *)&c, sizeof (int32_t));
1380 else if (printmode == AUP_OCTAL)
1381 (void) sprintf(p, "%o", c);
1382 else if (printmode == AUP_DECIMAL)
1383 (void) sprintf(p, "%d", c);
1384 else if (printmode == AUP_HEX)
1385 (void) sprintf(p, "0x%x", c);
1386 else if (printmode == AUP_STRING)
1387 convertascii(p, (char *)&c, sizeof (int));
1388 return (0);
1392 * ---------------------------------------------------------
1393 * convert_int64_to_string:
1394 * Converts a integer to string depending on the print mode
1395 * input : printmode, which may be one of AUP_BINARY,
1396 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1397 * c, which is the integer to convert
1398 * output : p, which is a pointer to the location where
1399 * the resulting string is to be stored
1400 * ----------------------------------------------------------
1403 convert_int64_to_string(char printmode, int64_t c, char *p)
1405 if (printmode == AUP_BINARY)
1406 (void) convertbinary(p, (char *)&c, sizeof (int64_t));
1407 else if (printmode == AUP_OCTAL)
1408 (void) sprintf(p, "%"PRIo64, c);
1409 else if (printmode == AUP_DECIMAL)
1410 (void) sprintf(p, "%"PRId64, c);
1411 else if (printmode == AUP_HEX)
1412 (void) sprintf(p, "0x%"PRIx64, c);
1413 else if (printmode == AUP_STRING)
1414 convertascii(p, (char *)&c, sizeof (int64_t));
1415 return (0);
1420 * -----------------------------------------------------------
1421 * convertbinary:
1422 * Converts a unit c of 'size' bytes long into a binary string
1423 * and returns it into the position pointed to by p
1424 * ------------------------------------------------------------
1427 convertbinary(char *p, char *c, int size)
1429 char *s, *t, *ss;
1430 int i, j;
1432 if ((s = (char *)malloc(8 * size + 1)) == NULL)
1433 return (0);
1435 ss = s;
1437 /* first convert to binary */
1438 t = s;
1439 for (i = 0; i < size; i++) {
1440 for (j = 0; j < 8; j++)
1441 (void) sprintf(t++, "%d", ((*c >> (7 - j)) & (0x01)));
1442 c++;
1444 *t = '\0';
1446 /* now string leading zero's if any */
1447 j = strlen(s) - 1;
1448 for (i = 0; i < j; i++) {
1449 if (*s != '0')
1450 break;
1451 else
1452 s++;
1455 /* now copy the contents of s to p */
1456 t = p;
1457 for (i = 0; i < (8 * size + 1); i++) {
1458 if (*s == '\0') {
1459 *t = '\0';
1460 break;
1462 *t++ = *s++;
1464 free(ss);
1466 return (1);
1470 static char hex[] = "0123456789abcdef";
1472 * -------------------------------------------------------------------
1473 * hexconvert : Converts a string of (size) bytes to hexadecimal, and
1474 * returns the hexadecimal string.
1475 * returns : - NULL if memory cannot be allocated for the string, or
1476 * - pointer to the hexadecimal string if successful
1477 * -------------------------------------------------------------------
1479 char *
1480 hexconvert(char *c, int size, int chunk)
1482 register char *s, *t;
1483 register int i, j, k;
1484 int numchunks;
1485 int leftovers;
1487 if (size <= 0)
1488 return (NULL);
1490 if ((s = (char *)malloc((size * 5) + 1)) == NULL)
1491 return (NULL);
1493 if (chunk > size || chunk <= 0)
1494 chunk = size;
1496 numchunks = size / chunk;
1497 leftovers = size % chunk;
1499 t = s;
1500 for (i = j = 0; i < numchunks; i++) {
1501 if (j++) {
1502 *t++ = ' ';
1504 *t++ = '0';
1505 *t++ = 'x';
1506 for (k = 0; k < chunk; k++) {
1507 *t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1508 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1509 c++;
1513 if (leftovers) {
1514 *t++ = ' ';
1515 *t++ = '0';
1516 *t++ = 'x';
1517 for (i = 0; i < leftovers; i++) {
1518 *t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1519 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1520 c++;
1524 *t = '\0';
1525 return (s);
1530 * -------------------------------------------------------------------
1531 * htp2string: Maps a print suggestion to a string.
1532 * returns : The string mapping or "unknown print suggestion".
1533 * -------------------------------------------------------------------
1535 char *
1536 htp2string(char print_sugg)
1538 register int i;
1540 struct htp_map_ent {
1541 char print_sugg;
1542 char *print_string;
1546 * TRANSLATION_NOTE
1547 * These names are data types when displaying the arbitrary data
1548 * token.
1551 static struct htp_map_ent htp_map[] = {
1552 { AUP_BINARY, "binary" },
1553 { AUP_OCTAL, "octal" },
1554 { AUP_DECIMAL, "decimal" },
1555 { AUP_HEX, "hexadecimal" },
1556 { AUP_STRING, "string" } };
1558 for (i = 0; i < sizeof (htp_map) / sizeof (struct htp_map_ent); i++)
1559 if (print_sugg == htp_map[i].print_sugg)
1560 return (gettext(htp_map[i].print_string));
1562 return (gettext("unknown print suggestion"));
1566 * ----------------------------------------------------------------------
1567 * pa_adr_short: Issues pr_adr_short to retrieve the next ADR item from the
1568 * input stream pointed to by audit_adr, and prints it
1569 * if status >= 0
1570 * return codes: -1 - error
1571 * : 0 - successful
1572 * ----------------------------------------------------------------------
1575 pa_adr_short(pr_context_t *context, int status, int flag)
1577 short c;
1578 uval_t uval;
1580 if (status >= 0) {
1581 if (pr_adr_short(context, &c, 1) == 0) {
1582 uval.uvaltype = PRA_SHORT;
1583 uval.short_val = c;
1584 return (pa_print(context, &uval, flag));
1585 } else
1586 return (-1);
1587 } else
1588 return (status);
1592 * -----------------------------------------------------------------------
1593 * pa_adr_shorthex: Issues pr_adr_short to retrieve the next ADR item from the
1594 * input stream pointed to by audit_adr, and prints it
1595 * in hexadecimal if status >= 0
1596 * return codes : -1 - error
1597 * : 0 - successful
1598 * -----------------------------------------------------------------------
1601 pa_adr_shorthex(pr_context_t *context, int status, int flag)
1603 short s;
1604 int returnstat;
1605 uval_t uval;
1607 if (status >= 0) {
1608 if ((returnstat = pr_adr_short(context, &s, 1)) == 0) {
1609 uval.uvaltype = PRA_STRING;
1610 uval.string_val = hexconvert((char *)&s, sizeof (s),
1611 sizeof (s));
1612 if (uval.string_val) {
1613 returnstat = pa_print(context, &uval, flag);
1614 free(uval.string_val);
1617 return (returnstat);
1618 } else
1619 return (status);
1624 * -----------------------------------------------------------------------
1625 * pa_adr_string: Retrieves a string from the input stream and prints it
1626 * if status >= 0
1627 * return codes : -1 - error
1628 * : 0 - successful
1629 * -----------------------------------------------------------------------
1632 pa_adr_string(pr_context_t *context, int status, int flag)
1634 char *c;
1635 short length;
1636 int returnstat;
1637 uval_t uval;
1640 * We need to know how much space to allocate for our string, so
1641 * read the length first, then call pr_adr_char to read those bytes.
1643 if (status < 0)
1644 return (status);
1646 if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1647 return (returnstat);
1648 if ((c = (char *)malloc(length + 1)) == NULL)
1649 return (-1);
1650 if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1651 free(c);
1652 return (returnstat);
1655 uval.uvaltype = PRA_STRING;
1656 uval.string_val = c;
1657 returnstat = pa_print(context, &uval, flag);
1658 free(c);
1659 return (returnstat);
1663 * -----------------------------------------------------------------------
1664 * pa_file_string: Retrieves a file string from the input stream and prints it
1665 * if status >= 0
1666 * return codes : -1 - error
1667 * : 0 - successful
1668 * -----------------------------------------------------------------------
1671 pa_file_string(pr_context_t *context, int status, int flag)
1673 char *c;
1674 char *p;
1675 short length;
1676 int returnstat;
1677 uval_t uval;
1680 * We need to know how much space to allocate for our string, so
1681 * read the length first, then call pr_adr_char to read those bytes.
1683 if (status < 0)
1684 return (status);
1686 if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1687 return (returnstat);
1688 if ((c = (char *)malloc(length + 1)) == NULL)
1689 return (-1);
1690 if ((p = (char *)malloc((length * 4) + 1)) == NULL) {
1691 free(c);
1692 return (-1);
1694 if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1695 free(c);
1696 free(p);
1697 return (returnstat);
1700 if (is_file_token(context->tokenid))
1701 context->audit_rec_len += length;
1703 convertascii(p, c, length - 1);
1704 uval.uvaltype = PRA_STRING;
1705 uval.string_val = p;
1707 if (returnstat == 0)
1708 returnstat = finish_open_tag(context);
1710 if (returnstat == 0)
1711 returnstat = pa_print(context, &uval, flag);
1713 free(c);
1714 free(p);
1715 return (returnstat);
1718 static int
1719 pa_putstr_xml(pr_context_t *context, int printable, char *str, size_t len)
1721 int err;
1723 if (!printable) {
1725 * Unprintable chars should always be converted to the
1726 * visible form. If there are unprintable characters which
1727 * require special treatment in xml, those should be
1728 * handled here.
1730 do {
1731 err = pr_printf(context, "\\%03o",
1732 (unsigned char)*str++);
1733 } while (err == 0 && --len != 0);
1734 return (err);
1736 /* printable characters */
1737 if (len == 1) {
1739 * check for the special chars only when char size was 1
1740 * ie, ignore special chars appear in the middle of multibyte
1741 * sequence.
1744 /* Escape for XML */
1745 switch (*str) {
1746 case '&':
1747 err = pr_printf(context, "%s", "&amp;");
1748 break;
1750 case '<':
1751 err = pr_printf(context, "%s", "&lt;");
1752 break;
1754 case '>':
1755 err = pr_printf(context, "%s", "&gt;");
1756 break;
1758 case '\"':
1759 err = pr_printf(context, "%s", "&quot;");
1760 break;
1762 case '\'':
1763 err = pr_printf(context, "%s", "&apos;");
1764 break;
1766 default:
1767 err = pr_putchar(context, *str);
1768 break;
1770 return (err);
1772 do {
1773 err = pr_putchar(context, *str++);
1774 } while (err == 0 && --len != 0);
1775 return (err);
1778 static int
1779 pa_putstr(pr_context_t *context, int printable, char *str, size_t len)
1781 int err;
1783 if (context->format & PRF_XMLM)
1784 return (pa_putstr_xml(context, printable, str, len));
1786 if (!printable) {
1787 do {
1788 err = pr_printf(context, "\\%03o",
1789 (unsigned char)*str++);
1790 } while (err == 0 && --len != 0);
1791 return (err);
1793 do {
1794 err = pr_putchar(context, *str++);
1795 } while (err == 0 && --len != 0);
1796 return (err);
1800 pa_string(pr_context_t *context, int status, int flag)
1802 int rstat, wstat;
1803 int i, printable, eos;
1804 int mlen, rlen;
1805 int mbmax = MB_CUR_MAX;
1806 wchar_t wc;
1807 char mbuf[MB_LEN_MAX + 1];
1808 char c;
1810 if (status < 0)
1811 return (status);
1813 rstat = wstat = 0;
1815 if (mbmax == 1) {
1816 while (wstat == 0) {
1817 if ((rstat = pr_adr_char(context, &c, 1)) < 0)
1818 break;
1819 if (c == '\0')
1820 break;
1821 printable = isprint((unsigned char)c);
1822 wstat = pa_putstr(context, printable, &c, 1);
1824 goto done;
1827 mlen = eos = 0;
1828 while (wstat == 0) {
1829 rlen = 0;
1830 do {
1831 if (!eos) {
1832 rstat = pr_adr_char(context, &c, 1);
1833 if (rstat != 0 || c == '\0')
1834 eos = 1;
1835 else
1836 mbuf[mlen++] = c;
1838 rlen = mbtowc(&wc, mbuf, mlen);
1839 } while (!eos && mlen < mbmax && rlen <= 0);
1841 if (mlen == 0)
1842 break; /* end of string */
1844 if (rlen <= 0) { /* no good sequence */
1845 rlen = 1;
1846 printable = 0;
1847 } else {
1848 printable = iswprint(wc);
1850 wstat = pa_putstr(context, printable, mbuf, rlen);
1851 mlen -= rlen;
1852 if (mlen > 0) {
1853 for (i = 0; i < mlen; i++)
1854 mbuf[i] = mbuf[rlen + i];
1858 done:
1859 if (wstat == 0)
1860 wstat = do_newline(context, flag);
1862 if (wstat == 0 && context->data_mode == FILEMODE)
1863 (void) fflush(stdout);
1865 return ((rstat != 0 || wstat != 0) ? -1 : 0);
1869 * -----------------------------------------------------------------------
1870 * pa_adr_u_int32: Issues pr_adr_u_int32 to retrieve the next ADR item from
1871 * the input stream pointed to by audit_adr, and prints it
1872 * if status = 0
1873 * return codes : -1 - error
1874 * : 0 - successful
1875 * -----------------------------------------------------------------------
1880 pa_adr_u_int32(pr_context_t *context, int status, int flag)
1882 uint32_t c;
1883 uval_t uval;
1885 if (status >= 0) {
1886 if (pr_adr_u_int32(context, &c, 1) == 0) {
1887 uval.uvaltype = PRA_UINT32;
1888 uval.uint32_val = c;
1889 return (pa_print(context, &uval, flag));
1890 } else
1891 return (-1);
1892 } else
1893 return (status);
1899 * -----------------------------------------------------------------------
1900 * pa_adr_u_int64: Issues pr_adr_u_int64 to retrieve the next ADR item from the
1901 * input stream pointed to by audit_adr, and prints it
1902 * if status = 0
1903 * return codes : -1 - error
1904 * : 0 - successful
1905 * -----------------------------------------------------------------------
1908 pa_adr_u_int64(pr_context_t *context, int status, int flag)
1910 uint64_t c;
1911 uval_t uval;
1913 if (status >= 0) {
1914 if (pr_adr_u_int64(context, &c, 1) == 0) {
1915 uval.uvaltype = PRA_UINT64;
1916 uval.uint64_val = c;
1917 return (pa_print(context, &uval, flag));
1918 } else
1919 return (-1);
1920 } else
1921 return (status);
1926 * -----------------------------------------------------------------------
1927 * pa_adr_u_short: Issues pr_adr_u_short to retrieve the next ADR item from
1928 * the input stream pointed to by audit_adr, and prints it
1929 * if status = 0
1930 * return codes : -1 - error
1931 * : 0 - successful
1932 * -----------------------------------------------------------------------
1935 pa_adr_u_short(pr_context_t *context, int status, int flag)
1937 ushort_t c;
1938 uval_t uval;
1940 if (status >= 0) {
1941 if (pr_adr_u_short(context, &c, 1) == 0) {
1942 uval.uvaltype = PRA_USHORT;
1943 uval.ushort_val = c;
1944 return (pa_print(context, &uval, flag));
1945 } else
1946 return (-1);
1947 } else
1948 return (status);
1952 * -----------------------------------------------------------------------
1953 * pa_reclen: Issues pr_adr_u_long to retrieve the length of the record
1954 * from the input stream pointed to by audit_adr,
1955 * and prints it (unless format is XML) if status = 0
1956 * return codes : -1 - error
1957 * : 0 - successful
1958 * -----------------------------------------------------------------------
1961 pa_reclen(pr_context_t *context, int status)
1963 uint32_t c;
1964 uval_t uval;
1966 if (status >= 0) {
1967 if ((int)pr_adr_u_int32(context, &c, 1) == 0) {
1968 context->audit_rec_len = c;
1970 /* Don't print this for XML format */
1971 if (context->format & PRF_XMLM) {
1972 return (0);
1973 } else {
1974 uval.uvaltype = PRA_UINT32;
1975 uval.uint32_val = c;
1976 return (pa_print(context, &uval, 0));
1978 } else
1979 return (-1);
1980 } else
1981 return (status);
1985 * -----------------------------------------------------------------------
1986 * pa_mode : Issues pr_adr_u_short to retrieve the next ADR item from
1987 * the input stream pointed to by audit_adr, and prints it
1988 * in octal if status = 0
1989 * return codes : -1 - error
1990 * : 0 - successful
1991 * -----------------------------------------------------------------------
1994 pa_mode(pr_context_t *context, int status, int flag)
1996 uint32_t c;
1997 uval_t uval;
1999 if (status >= 0) {
2000 if (pr_adr_u_int32(context, &c, 1) == 0) {
2001 uval.uvaltype = PRA_LOCT;
2002 uval.uint32_val = c;
2003 return (pa_print(context, &uval, flag));
2004 } else
2005 return (-1);
2006 } else
2007 return (status);
2010 static int
2011 pa_print_uid(pr_context_t *context, uid_t uid, int status, int flag)
2013 int returnstat;
2014 struct passwd *pw;
2015 uval_t uval;
2017 if (status < 0)
2018 return (status);
2020 if (!(context->format & PRF_RAWM)) {
2021 /* get password file entry */
2022 if ((pw = getpwuid(uid)) == NULL) {
2023 returnstat = 1;
2024 } else {
2025 /* print in ASCII form */
2026 uval.uvaltype = PRA_STRING;
2027 uval.string_val = pw->pw_name;
2028 returnstat = pa_print(context, &uval, flag);
2031 /* print in integer form */
2032 if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2033 uval.uvaltype = PRA_INT32;
2034 uval.int32_val = uid;
2035 returnstat = pa_print(context, &uval, flag);
2037 return (returnstat);
2042 * -----------------------------------------------------------------------
2043 * pa_pw_uid() : Issues pr_adr_u_int32 to reads uid from input stream
2044 * pointed to by audit_adr, and displays it in either
2045 * raw form or its ASCII representation, if status >= 0.
2046 * return codes : -1 - error
2047 * : 1 - warning, passwd entry not found
2048 * : 0 - successful
2049 * -----------------------------------------------------------------------
2052 pa_pw_uid(pr_context_t *context, int status, int flag)
2054 uint32_t uid;
2056 if (status < 0)
2057 return (status);
2059 if (pr_adr_u_int32(context, &uid, 1) != 0)
2060 /* cannot retrieve uid */
2061 return (-1);
2063 return (pa_print_uid(context, uid, status, flag));
2066 static int
2067 pa_print_gid(pr_context_t *context, gid_t gid, int status, int flag)
2069 int returnstat;
2070 struct group *gr;
2071 uval_t uval;
2073 if (status < 0)
2074 return (status);
2076 if (!(context->format & PRF_RAWM)) {
2077 /* get group file entry */
2078 if ((gr = getgrgid(gid)) == NULL) {
2079 returnstat = 1;
2080 } else {
2081 /* print in ASCII form */
2082 uval.uvaltype = PRA_STRING;
2083 uval.string_val = gr->gr_name;
2084 returnstat = pa_print(context, &uval, flag);
2087 /* print in integer form */
2088 if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2089 uval.uvaltype = PRA_INT32;
2090 uval.int32_val = gid;
2091 returnstat = pa_print(context, &uval, flag);
2093 return (returnstat);
2098 * -----------------------------------------------------------------------
2099 * pa_gr_uid() : Issues pr_adr_u_int32 to reads group uid from input stream
2100 * pointed to by audit_adr, and displays it in either
2101 * raw form or its ASCII representation, if status >= 0.
2102 * return codes : -1 - error
2103 * : 1 - warning, passwd entry not found
2104 * : 0 - successful
2105 * -----------------------------------------------------------------------
2108 pa_gr_uid(pr_context_t *context, int status, int flag)
2110 uint32_t gid;
2112 if (status < 0)
2113 return (status);
2115 if (pr_adr_u_int32(context, &gid, 1) != 0)
2116 /* cannot retrieve gid */
2117 return (-1);
2119 return (pa_print_gid(context, gid, status, flag));
2124 * -----------------------------------------------------------------------
2125 * pa_pw_uid_gr_gid() : Issues pr_adr_u_int32 to reads uid or group uid
2126 * from input stream
2127 * pointed to by audit_adr, and displays it in either
2128 * raw form or its ASCII representation, if status >= 0.
2129 * return codes : -1 - error
2130 * : 1 - warning, passwd entry not found
2131 * : 0 - successful
2132 * -----------------------------------------------------------------------
2135 pa_pw_uid_gr_gid(pr_context_t *context, int status, int flag)
2137 int returnstat;
2138 uint32_t value;
2139 uval_t uval;
2141 if (status < 0)
2142 return (status);
2144 /* get value of a_type */
2145 if ((returnstat = pr_adr_u_int32(context, &value, 1)) != 0)
2146 return (returnstat);
2148 if ((returnstat = open_tag(context, TAG_ACLTYPE)) != 0)
2149 return (returnstat);
2151 uval.uvaltype = PRA_UINT32;
2152 uval.uint32_val = value;
2153 if ((returnstat = pa_print(context, &uval, flag)) != 0)
2154 return (returnstat);
2156 if ((returnstat = close_tag(context, TAG_ACLTYPE)) != 0)
2157 return (returnstat);
2159 if ((returnstat = open_tag(context, TAG_ACLVAL)) != 0)
2160 return (returnstat);
2162 * TRANSLATION_NOTE
2163 * The "mask" and "other" strings refer to the class mask
2164 * and other (or world) entries in an ACL.
2165 * The "unrecognized" string refers to an unrecognized ACL
2166 * entry.
2168 switch (value) {
2169 case USER_OBJ:
2170 case USER:
2171 returnstat = pa_pw_uid(context, returnstat, flag);
2172 break;
2173 case GROUP_OBJ:
2174 case GROUP:
2175 returnstat = pa_gr_uid(context, returnstat, flag);
2176 break;
2177 case CLASS_OBJ:
2178 returnstat = pr_adr_u_int32(context, &value, 1);
2179 if (returnstat != 0)
2180 return (returnstat);
2182 if (!(context->format & PRF_RAWM)) {
2183 uval.uvaltype = PRA_STRING;
2184 uval.string_val = gettext("mask");
2185 returnstat = pa_print(context, &uval, flag);
2186 } else {
2187 uval.uvaltype = PRA_UINT32;
2188 uval.uint32_val = value;
2189 if ((returnstat =
2190 pa_print(context, &uval, flag)) != 0) {
2191 return (returnstat);
2194 break;
2195 case OTHER_OBJ:
2196 returnstat = pr_adr_u_int32(context, &value, 1);
2197 if (returnstat != 0)
2198 return (returnstat);
2200 if (!(context->format & PRF_RAWM)) {
2201 uval.uvaltype = PRA_STRING;
2202 uval.string_val = gettext("other");
2203 returnstat = pa_print(context, &uval, flag);
2204 } else {
2205 uval.uvaltype = PRA_UINT32;
2206 uval.uint32_val = value;
2207 if ((returnstat =
2208 pa_print(context, &uval, flag)) != 0) {
2209 return (returnstat);
2212 break;
2213 default:
2214 returnstat = pr_adr_u_int32(context, &value, 1);
2215 if (returnstat != 0)
2216 return (returnstat);
2218 if (!(context->format & PRF_RAWM)) {
2219 uval.uvaltype = PRA_STRING;
2220 uval.string_val = gettext("unrecognized");
2221 returnstat = pa_print(context, &uval, flag);
2222 } else {
2223 uval.uvaltype = PRA_UINT32;
2224 uval.uint32_val = value;
2225 if ((returnstat =
2226 pa_print(context, &uval, flag)) != 0) {
2227 return (returnstat);
2232 if ((returnstat = close_tag(context, TAG_ACLVAL)) != 0)
2233 return (returnstat);
2235 return (returnstat);
2240 * -----------------------------------------------------------------------
2241 * pa_event_modifier(): Issues pr_adr_u_short to retrieve the next ADR item from
2242 * the input stream pointed to by audit_adr. This is the
2243 * event type, and is displayed in hex;
2244 * return codes : -1 - error
2245 * : 0 - successful
2246 * -----------------------------------------------------------------------
2249 pa_event_modifier(pr_context_t *context, int status, int flag)
2251 int returnstat;
2252 au_emod_t emodifier;
2253 uval_t uval;
2254 char modstring[64];
2256 if (status < 0)
2257 return (status);
2259 if ((returnstat = pr_adr_u_short(context, &emodifier, 1)) != 0)
2260 return (returnstat);
2262 /* For XML, only print when modifier is non-zero */
2263 if (!(context->format & PRF_XMLM) || (emodifier != 0)) {
2264 uval.uvaltype = PRA_STRING;
2266 returnstat = open_tag(context, TAG_EVMOD);
2268 if (returnstat >= 0) {
2269 if (!(context->format & PRF_RAWM)) {
2270 eventmodifier2string(emodifier, modstring,
2271 sizeof (modstring));
2272 uval.string_val = modstring;
2273 returnstat = pa_print(context, &uval, flag);
2274 } else {
2275 uval.string_val = hexconvert((char *)&emodifier,
2276 sizeof (emodifier), sizeof (emodifier));
2277 if (uval.string_val) {
2278 returnstat = pa_print(context, &uval,
2279 flag);
2280 free(uval.string_val);
2284 if (returnstat >= 0)
2285 returnstat = close_tag(context, TAG_EVMOD);
2288 return (returnstat);
2293 * -----------------------------------------------------------------------
2294 * pa_event_type(): Issues pr_adr_u_short to retrieve the next ADR item from
2295 * the input stream pointed to by audit_adr. This is the
2296 * event type, and is displayed in either raw or
2297 * ASCII form as appropriate
2298 * return codes : -1 - error
2299 * : 0 - successful
2300 * -----------------------------------------------------------------------
2303 pa_event_type(pr_context_t *context, int status, int flag)
2305 au_event_t etype;
2306 int returnstat;
2307 au_event_ent_t *p_event = NULL;
2308 uval_t uval;
2310 if (status >= 0) {
2311 if ((returnstat = pr_adr_u_short(context, &etype, 1)) == 0) {
2312 if (!(context->format & PRF_RAWM)) {
2313 uval.uvaltype = PRA_STRING;
2314 if (context->format & PRF_NOCACHE) {
2315 p_event = getauevnum(etype);
2316 } else {
2317 (void) cacheauevent(&p_event, etype);
2319 if (p_event != NULL) {
2320 if (context->format & PRF_SHORTM)
2321 uval.string_val =
2322 p_event->ae_name;
2323 else
2324 uval.string_val =
2325 p_event->ae_desc;
2326 } else {
2327 uval.string_val =
2328 gettext("invalid event number");
2330 returnstat = pa_print(context, &uval, flag);
2331 } else {
2332 uval.uvaltype = PRA_USHORT;
2333 uval.ushort_val = etype;
2334 returnstat = pa_print(context, &uval, flag);
2337 return (returnstat);
2338 } else
2339 return (status);
2345 * Print time from struct timeval to millisecond resolution.
2347 * typedef long time_t; time of day in seconds
2348 * typedef long useconds_t; signed # of microseconds
2350 * struct timeval {
2351 * time_t tv_sec; seconds
2352 * suseconds_t tv_usec; and microseconds
2353 * };
2357 pa_utime32(pr_context_t *context, int status, int flag)
2359 uint32_t scale = 1000; /* usec to msec */
2361 return (do_mtime32(context, status, flag, scale));
2365 * Print time from timestruc_t to millisecond resolution.
2367 * typedef struct timespec timestruct_t;
2368 * struct timespec{
2369 * time_t tv_sec; seconds
2370 * long tv_nsec; and nanoseconds
2371 * };
2374 pa_ntime32(pr_context_t *context, int status, int flag)
2376 uint32_t scale = 1000000; /* nsec to msec */
2378 return (do_mtime32(context, status, flag, scale));
2382 * Format the timezone +/- HH:MM and terminate the string
2383 * Note tm and tv_sec are the same time.
2384 * Too bad strftime won't produce an ISO 8601 time zone numeric
2387 #define MINS (24L * 60)
2388 static void
2389 tzone(struct tm *tm, time_t *tv_sec, char *p)
2391 struct tm *gmt;
2392 int min_off;
2394 gmt = gmtime(tv_sec);
2396 min_off = ((tm->tm_hour - gmt->tm_hour) * 60) +
2397 (tm->tm_min - gmt->tm_min);
2399 if (tm->tm_year < gmt->tm_year) /* cross new year */
2400 min_off -= MINS;
2401 else if (tm->tm_year > gmt->tm_year)
2402 min_off += MINS;
2403 else if (tm->tm_yday < gmt->tm_yday) /* cross dateline */
2404 min_off -= MINS;
2405 else if (tm->tm_yday > gmt->tm_yday)
2406 min_off += MINS;
2408 if (min_off < 0) {
2409 min_off = -min_off;
2410 *p++ = '-';
2411 } else {
2412 *p++ = '+';
2415 *p++ = min_off / 600 + '0'; /* 10s of hours */
2416 min_off = min_off - min_off / 600 * 600;
2417 *p++ = min_off / 60 % 10 + '0'; /* hours */
2418 min_off = min_off - min_off / 60 * 60;
2419 *p++ = ':';
2420 *p++ = min_off / 10 + '0'; /* 10s of minutes */
2421 *p++ = min_off % 10 + '0'; /* minutes */
2422 *p = '\0';
2426 * Format the milliseconds in place in the string.
2427 * Borrowed from strftime.c:itoa()
2429 static void
2430 msec32(uint32_t msec, char *p)
2432 *p++ = msec / 100 + '0';
2433 msec = msec - msec / 100 * 100;
2434 *p++ = msec / 10 + '0';
2435 *p++ = msec % 10 +'0';
2439 * Format time and print relative to scale factor from micro/nano seconds.
2441 static int
2442 do_mtime32(pr_context_t *context, int status, int flag, uint32_t scale)
2444 uint32_t t32;
2445 time_t tv_sec;
2446 struct tm tm;
2447 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2448 int returnstat;
2449 uval_t uval;
2451 if (status < 0)
2452 return (status);
2454 if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2455 return (returnstat);
2457 if ((returnstat = pr_adr_u_int32(context,
2458 (uint32_t *)&tv_sec, 1)) != 0)
2459 return (returnstat);
2460 if ((returnstat = pr_adr_u_int32(context, &t32, 1)) == 0) {
2461 if (!(context->format & PRF_RAWM)) {
2462 (void) localtime_r(&tv_sec, &tm);
2463 (void) strftime(time_created,
2464 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2465 "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2466 msec32(t32/scale,
2467 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2468 tzone(&tm, &tv_sec,
2469 &time_created[
2470 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2471 uval.uvaltype = PRA_STRING;
2472 uval.string_val = time_created;
2473 } else {
2474 uval.uvaltype = PRA_UINT32;
2475 uval.uint32_val = (uint32_t)tv_sec;
2476 (void) pa_print(context, &uval, 0);
2477 if (context->format & PRF_XMLM) {
2478 uval.uvaltype = PRA_CHAR;
2479 uval.char_val = '.';
2480 (void) pa_print(context, &uval, 0);
2482 uval.uvaltype = PRA_UINT32;
2483 uval.uint32_val = t32;
2485 returnstat = pa_print(context, &uval, flag);
2488 if (returnstat == 0)
2489 return (close_tag(context, TAG_ISO));
2490 else
2491 return (returnstat);
2495 * Print time from struct timeval to millisecond resolution.
2497 * typedef long time_t; time of day in seconds
2498 * typedef long useconds_t; signed # of microseconds
2500 * struct timeval {
2501 * time_t tv_sec; seconds
2502 * suseconds_t tv_usec; and microseconds
2503 * };
2507 pa_utime64(pr_context_t *context, int status, int flag)
2509 uint64_t scale = 1000; /* usec to msec */
2511 return (do_mtime64(context, status, flag, scale));
2515 * Print time from timestruc_t to millisecond resolution.
2517 * typedef struct timespec timestruct_t;
2518 * struct timespec{
2519 * time_t tv_sec; seconds
2520 * long tv_nsec; and nanoseconds
2521 * };
2524 pa_ntime64(pr_context_t *context, int status, int flag)
2526 uint64_t scale = 1000000; /* nsec to msec */
2528 return (do_mtime64(context, status, flag, scale));
2532 * Format the milliseconds in place in the string.
2533 * Borrowed from strftime.c:itoa()
2535 static void
2536 msec64(uint64_t msec, char *p)
2538 *p++ = msec / 100 + '0';
2539 msec = msec - msec / 100 * 100;
2540 *p++ = msec / 10 + '0';
2541 *p++ = msec % 10 +'0';
2545 * Format time and print relative to scale factor from micro/nano seconds.
2547 static int
2548 do_mtime64(pr_context_t *context, int status, int flag, uint64_t scale)
2550 uint64_t t64_sec;
2551 uint64_t t64_msec;
2552 time_t tv_sec;
2553 struct tm tm;
2554 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2555 int returnstat;
2556 uval_t uval;
2558 if (status < 0)
2559 return (status);
2561 if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2562 return (returnstat);
2564 if ((returnstat = pr_adr_u_int64(context, &t64_sec, 1)) != 0)
2565 return (returnstat);
2566 if ((returnstat = pr_adr_u_int64(context, &t64_msec, 1)) == 0) {
2567 if (!(context->format & PRF_RAWM)) {
2568 #ifndef _LP64
2570 * N.B.
2571 * This fails for years from 2038
2572 * The Y2K+38 problem
2574 #endif /* !_LP64 */
2575 tv_sec = (time_t)t64_sec;
2576 (void) localtime_r(&tv_sec, &tm);
2577 (void) strftime(time_created,
2578 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2579 "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2580 msec64(t64_msec/scale,
2581 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2582 tzone(&tm, &tv_sec,
2583 &time_created[
2584 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2585 uval.uvaltype = PRA_STRING;
2586 uval.string_val = time_created;
2587 } else {
2588 uval.uvaltype = PRA_UINT64;
2589 uval.uint64_val = t64_sec;
2590 (void) pa_print(context, &uval, 0);
2591 if (context->format & PRF_XMLM) {
2592 uval.uvaltype = PRA_CHAR;
2593 uval.char_val = '.';
2594 (void) pa_print(context, &uval, 0);
2596 uval.uvaltype = PRA_UINT64;
2597 uval.uint64_val = t64_msec;
2599 returnstat = pa_print(context, &uval, flag);
2602 if (returnstat < 0)
2603 return (returnstat);
2605 return (close_tag(context, TAG_ISO));
2609 * -----------------------------------------------------------------------
2610 * pa_error() : convert the return token error code.
2612 * output : buf string representing return token error code.
2614 * -----------------------------------------------------------------------
2616 void
2617 pa_error(const uchar_t err, char *buf, size_t buflen)
2619 if (err == ADT_SUCCESS) {
2620 (void) strlcpy(buf, gettext("success"), buflen);
2621 } else if ((char)err == ADT_FAILURE) {
2622 (void) strlcpy(buf, gettext("failure"), buflen);
2623 } else {
2624 char *emsg = strerror(err);
2626 if (emsg != NULL) {
2627 (void) strlcpy(buf, gettext("failure: "), buflen);
2628 (void) strlcat(buf, emsg, buflen);
2629 } else {
2630 (void) snprintf(buf, buflen, "%s%d",
2631 gettext("failure: "), err);
2637 * -----------------------------------------------------------------------
2638 * pa_retval() : convert the return token return value code.
2640 * input : err, for kernel success 0, or
2641 * failure errno: 0 > & < sys_nerr.
2642 * for userland success ADT_SUCCESS (0) or
2643 * failure ADT_FAILURE (-1).
2644 * pa_error() above has already converted err.
2646 * : retval, for kernel arbitrary return value for success, or
2647 * failure: -1.
2648 * for userland,
2649 * >= ADT_FAIL_VALUE < ADT_FAIL_PAM, an adt message code;
2650 * >= ADT_FAIL_PAM, a pam_strerror value;
2651 * < ADT_FAIL_VALUE, supposed to be an errno.
2653 * output : buf string representing return token error code.
2655 * -----------------------------------------------------------------------
2657 void
2658 pa_retval(const uchar_t err, const int32_t retval, char *buf, size_t buflen)
2660 struct msg_text *msglist;
2661 char *emsg;
2663 /* success or kernel failure */
2664 if (((char)err == ADT_SUCCESS) ||
2665 (retval < 0)) {
2667 (void) snprintf(buf, buflen, "%d", retval);
2668 return;
2671 /* userland failure */
2672 msglist = &adt_msg_text[ADT_LIST_FAIL_VALUE];
2674 if ((retval + msglist->ml_offset >= msglist->ml_min_index) &&
2675 (retval + msglist->ml_offset <= msglist->ml_max_index)) {
2677 (void) strlcpy(buf,
2678 gettext(msglist->ml_msg_list[retval + msglist->ml_offset]),
2679 buflen);
2680 } else if ((retval >= ADT_FAIL_PAM) &&
2681 (retval < ADT_FAIL_PAM + PAM_TOTAL_ERRNUM)) {
2683 (void) strlcpy(buf, pam_strerror(NULL, retval - ADT_FAIL_PAM),
2684 buflen);
2685 } else if ((emsg = strerror(retval)) != NULL) {
2687 (void) strlcpy(buf, emsg, buflen);
2688 } else {
2690 (void) snprintf(buf, buflen, "%d", retval);
2695 * -----------------------------------------------------------------------
2696 * pa_printstr() : print a given string, translating unprintables
2697 * : as needed.
2699 static int
2700 pa_printstr(pr_context_t *context, char *str)
2702 int err = 0;
2703 int len, printable;
2704 int mbmax = MB_CUR_MAX;
2705 wchar_t wc;
2706 char c;
2708 if (mbmax == 1) {
2709 /* fast path */
2710 while (err == 0 && *str != '\0') {
2711 c = *str++;
2712 printable = isprint((unsigned char)c);
2713 err = pa_putstr(context, printable, &c, 1);
2715 return (err);
2717 while (err == 0 && *str != '\0') {
2718 len = mbtowc(&wc, str, mbmax);
2719 if (len <= 0) {
2720 len = 1;
2721 printable = 0;
2722 } else {
2723 printable = iswprint(wc);
2725 err = pa_putstr(context, printable, str, len);
2726 str += len;
2728 return (err);
2732 * -----------------------------------------------------------------------
2733 * pa_print() : print as one str or formatted for easy reading.
2734 * : flag - indicates whether to output a new line for
2735 * : multi-line output.
2736 * : = 0; no new line
2737 * : = 1; new line if regular output
2738 * output : The audit record information is displayed in the
2739 * type specified by uvaltype and value specified in
2740 * uval. The printing of the delimiter or newline is
2741 * determined by PRF_ONELINE, and the flag value,
2742 * as follows:
2743 * +--------+------+------+-----------------+
2744 * |ONELINE | flag | last | Action |
2745 * +--------+------+------+-----------------+
2746 * | Y | Y | T | print new line |
2747 * | Y | Y | F | print delimiter |
2748 * | Y | N | T | print new line |
2749 * | Y | N | F | print delimiter |
2750 * | N | Y | T | print new line |
2751 * | N | Y | F | print new line |
2752 * | N | N | T | print new line |
2753 * | N | N | F | print delimiter |
2754 * +--------+------+------+-----------------+
2756 * return codes : -1 - error
2757 * 0 - successful
2758 * -----------------------------------------------------------------------
2761 pa_print(pr_context_t *context, uval_t *uval, int flag)
2763 int returnstat = 0;
2764 int last;
2766 switch (uval->uvaltype) {
2767 case PRA_INT32:
2768 returnstat = pr_printf(context, "%d", uval->int32_val);
2769 break;
2770 case PRA_UINT32:
2771 returnstat = pr_printf(context, "%u", uval->uint32_val);
2772 break;
2773 case PRA_INT64:
2774 returnstat = pr_printf(context, "%"PRId64, uval->int64_val);
2775 break;
2776 case PRA_UINT64:
2777 returnstat = pr_printf(context, "%"PRIu64, uval->uint64_val);
2778 break;
2779 case PRA_SHORT:
2780 returnstat = pr_printf(context, "%hd", uval->short_val);
2781 break;
2782 case PRA_USHORT:
2783 returnstat = pr_printf(context, "%hu", uval->ushort_val);
2784 break;
2785 case PRA_CHAR:
2786 returnstat = pr_printf(context, "%c", uval->char_val);
2787 break;
2788 case PRA_BYTE:
2789 returnstat = pr_printf(context, "%d", uval->char_val);
2790 break;
2791 case PRA_STRING:
2792 returnstat = pa_printstr(context, uval->string_val);
2793 break;
2794 case PRA_HEX32:
2795 returnstat = pr_printf(context, "0x%x", uval->int32_val);
2796 break;
2797 case PRA_HEX64:
2798 returnstat = pr_printf(context, "0x%"PRIx64, uval->int64_val);
2799 break;
2800 case PRA_SHEX:
2801 returnstat = pr_printf(context, "0x%hx", uval->short_val);
2802 break;
2803 case PRA_OCT:
2804 returnstat = pr_printf(context, "%ho", uval->ushort_val);
2805 break;
2806 case PRA_LOCT:
2807 returnstat = pr_printf(context, "%o", (int)uval->uint32_val);
2808 break;
2809 default:
2810 (void) fprintf(stderr, gettext("praudit: Unknown type.\n"));
2811 returnstat = -1;
2812 break;
2814 if (returnstat < 0)
2815 return (returnstat);
2817 last = (context->audit_adr->adr_now ==
2818 (context->audit_rec_start + context->audit_rec_len));
2820 if (!(context->format & PRF_XMLM)) {
2821 if (!(context->format & PRF_ONELINE)) {
2822 if ((flag == 1) || last)
2823 returnstat = pr_putchar(context, '\n');
2824 else
2825 returnstat = pr_printf(context, "%s",
2826 context->SEPARATOR);
2827 } else {
2828 if (!last)
2829 returnstat = pr_printf(context, "%s",
2830 context->SEPARATOR);
2831 else
2832 returnstat = pr_putchar(context, '\n');
2835 if ((returnstat == 0) && (context->data_mode == FILEMODE))
2836 (void) fflush(stdout);
2838 return (returnstat);
2841 static struct cntrl_mapping {
2842 char from;
2843 char to;
2844 } cntrl_map[] = {
2845 '\0', '0',
2846 '\a', 'a',
2847 '\b', 'b',
2848 '\t', 't',
2849 '\f', 'f',
2850 '\n', 'n',
2851 '\r', 'r',
2852 '\v', 'v'
2855 static int cntrl_map_entries = sizeof (cntrl_map)
2856 / sizeof (struct cntrl_mapping);
2859 * Convert binary data to ASCII for printing.
2861 void
2862 convertascii(char *p, char *c, int size)
2864 int i, j, uc;
2866 for (i = 0; i < size; i++) {
2867 uc = (unsigned char)*(c + i);
2868 if (isascii(uc)) {
2869 if (iscntrl(uc)) {
2870 for (j = 0; j < cntrl_map_entries; j++) {
2871 if (cntrl_map[j].from == uc) {
2872 *p++ = '\\';
2873 *p++ = cntrl_map[j].to;
2874 break;
2877 if (j == cntrl_map_entries) {
2878 *p++ = '^';
2879 *p++ = (char)(uc ^ 0100);
2881 } else {
2882 *p++ = (char)uc;
2884 } else {
2885 p += sprintf(p, "\\%03o", uc);
2888 *p = '\0';
2892 * -----------------------------------------------------------------------
2893 * pa_xgeneric: Process Xobject token and display contents
2894 * This routine will handle many of the attribute
2895 * types introduced in TS 2.x, such as:
2897 * AUT_XCOLORMAP, AUT_XCURSOR, AUT_XFONT,
2898 * AUT_XGC, AUT_XPIXMAP, AUT_XWINDOW
2900 * NOTE: At the time of call, the token id has been retrieved
2902 * return codes : -1 - error
2903 * : 0 - successful
2904 * NOTE: At the time of call, the xatom token id has been retrieved
2906 * Format of xobj
2907 * text token id adr_char
2908 * XID adr_u_int32
2909 * creator uid adr_pw_uid
2910 * -----------------------------------------------------------------------
2913 pa_xgeneric(pr_context_t *context)
2915 int returnstat;
2917 returnstat = process_tag(context, TAG_XID, 0, 0);
2918 return (process_tag(context, TAG_XCUID, returnstat, 1));
2923 * ------------------------------------------------------------------------
2924 * pa_liaison : Issues pr_adr_char to retrieve the next ADR item from the
2925 * input stream pointed to by audit_adr, and prints it
2926 * if status >= 0 either in ASCII or raw form
2927 * return codes : -1 - error
2928 * : 0 - successful
2929 * : 1 - warning, unknown label type
2930 * -----------------------------------------------------------------------
2933 pa_liaison(pr_context_t *context, int status, int flag)
2935 int returnstat;
2936 int32_t li;
2937 uval_t uval;
2939 if (status >= 0) {
2940 if ((returnstat = pr_adr_int32(context, &li, 1)) != 0) {
2941 return (returnstat);
2943 if (!(context->format & PRF_RAWM)) {
2944 uval.uvaltype = PRA_UINT32;
2945 uval.uint32_val = li;
2946 returnstat = pa_print(context, &uval, flag);
2948 /* print in hexadecimal form */
2949 if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2950 uval.uvaltype = PRA_HEX32;
2951 uval.uint32_val = li;
2952 returnstat = pa_print(context, &uval, flag);
2954 return (returnstat);
2955 } else
2956 return (status);
2960 * ------------------------------------------------------------------------
2961 * pa_xid : Issues pr_adr_int32 to retrieve the XID from the input
2962 * stream pointed to by audit_adr, and prints it if
2963 * status >= 0 either in ASCII or raw form
2964 * return codes : -1 - error
2965 * : 0 - successful
2966 * : 1 - warning, unknown label type
2967 * ------------------------------------------------------------------------
2971 pa_xid(pr_context_t *context, int status, int flag)
2973 int returnstat;
2974 int32_t xid;
2975 uval_t uval;
2977 if (status < 0)
2978 return (status);
2980 /* get XID from stream */
2981 if ((returnstat = pr_adr_int32(context, (int32_t *)&xid, 1)) != 0)
2982 return (returnstat);
2984 if (!(context->format & PRF_RAWM)) {
2985 uval.uvaltype = PRA_STRING;
2986 uval.string_val = hexconvert((char *)&xid, sizeof (xid),
2987 sizeof (xid));
2988 if (uval.string_val) {
2989 returnstat = pa_print(context, &uval, flag);
2990 free(uval.string_val);
2992 } else {
2993 uval.uvaltype = PRA_INT32;
2994 uval.int32_val = xid;
2995 returnstat = pa_print(context, &uval, flag);
2998 return (returnstat);
3001 static int
3002 pa_ace_flags(pr_context_t *context, ace_t *ace, int status, int flag)
3004 int returnstat;
3005 uval_t uval;
3007 if (status < 0)
3008 return (status);
3011 * TRANSLATION_NOTE
3012 * ace->a_flags refers to access flags of ZFS/NFSv4 ACL entry.
3014 if ((returnstat = open_tag(context, TAG_ACEFLAGS)) != 0)
3015 return (returnstat);
3016 if (!(context->format & PRF_RAWM)) {
3017 uval.uvaltype = PRA_STRING;
3018 switch (ace->a_flags & ACE_TYPE_FLAGS) {
3019 case ACE_OWNER:
3020 uval.string_val = gettext(OWNERAT_TXT);
3021 break;
3022 case ACE_GROUP | ACE_IDENTIFIER_GROUP:
3023 uval.string_val = gettext(GROUPAT_TXT);
3024 break;
3025 case ACE_IDENTIFIER_GROUP:
3026 uval.string_val = gettext(GROUP_TXT);
3027 break;
3028 case ACE_EVERYONE:
3029 uval.string_val = gettext(EVERYONEAT_TXT);
3030 break;
3031 case 0:
3032 uval.string_val = gettext(USER_TXT);
3033 break;
3034 default:
3035 uval.uvaltype = PRA_USHORT;
3036 uval.uint32_val = ace->a_flags;
3038 } else {
3039 uval.uvaltype = PRA_USHORT;
3040 uval.uint32_val = ace->a_flags;
3042 if ((returnstat = pa_print(context, &uval, flag)) != 0)
3043 return (returnstat);
3044 return (close_tag(context, TAG_ACEFLAGS));
3047 static int
3048 pa_ace_who(pr_context_t *context, ace_t *ace, int status, int flag)
3050 int returnstat;
3052 if (status < 0)
3053 return (status);
3056 * TRANSLATION_NOTE
3057 * ace->a_who refers to user id or group id of ZFS/NFSv4 ACL entry.
3059 if ((returnstat = open_tag(context, TAG_ACEID)) != 0)
3060 return (returnstat);
3061 switch (ace->a_flags & ACE_TYPE_FLAGS) {
3062 case ACE_IDENTIFIER_GROUP: /* group id */
3063 returnstat = pa_print_gid(context, ace->a_who, returnstat,
3064 flag);
3065 break;
3066 default: /* user id */
3067 returnstat = pa_print_uid(context, ace->a_who, returnstat,
3068 flag);
3069 break;
3071 if (returnstat < 0)
3072 return (returnstat);
3073 return (close_tag(context, TAG_ACEID));
3077 * Appends what to str, (re)allocating str if necessary.
3079 #define INITIAL_ALLOC 256
3080 static int
3081 strappend(char **str, char *what, size_t *alloc)
3083 char *s, *newstr;
3084 size_t needed;
3086 s = *str;
3088 if (s == NULL) {
3089 s = malloc(INITIAL_ALLOC);
3090 if (s == NULL) {
3091 *alloc = 0;
3092 return (-1);
3094 *alloc = INITIAL_ALLOC;
3095 s[0] = '\0';
3096 *str = s;
3099 needed = strlen(s) + strlen(what) + 1;
3100 if (*alloc < needed) {
3101 newstr = realloc(s, needed);
3102 if (newstr == NULL)
3103 return (-1);
3104 s = newstr;
3105 *alloc = needed;
3106 *str = s;
3108 (void) strlcat(s, what, *alloc);
3110 return (0);
3113 static int
3114 pa_ace_access_mask(pr_context_t *context, ace_t *ace, int status, int flag)
3116 int returnstat, i;
3117 uval_t uval;
3118 char *permstr = NULL;
3119 size_t permstr_alloc = 0;
3121 if (status < 0)
3122 return (status);
3125 * TRANSLATION_NOTE
3126 * ace->a_access_mask refers to access mask of ZFS/NFSv4 ACL entry.
3128 if ((returnstat = open_tag(context, TAG_ACEMASK)) != 0)
3129 return (returnstat);
3130 if (context->format & PRF_SHORTM &&
3131 ((permstr = malloc(15)) != NULL)) {
3132 for (i = 0; i < 14; i++)
3133 permstr[i] = '-';
3135 if (ace->a_access_mask & ACE_READ_DATA)
3136 permstr[0] = 'r';
3137 if (ace->a_access_mask & ACE_WRITE_DATA)
3138 permstr[1] = 'w';
3139 if (ace->a_access_mask & ACE_EXECUTE)
3140 permstr[2] = 'x';
3141 if (ace->a_access_mask & ACE_APPEND_DATA)
3142 permstr[3] = 'p';
3143 if (ace->a_access_mask & ACE_DELETE)
3144 permstr[4] = 'd';
3145 if (ace->a_access_mask & ACE_DELETE_CHILD)
3146 permstr[5] = 'D';
3147 if (ace->a_access_mask & ACE_READ_ATTRIBUTES)
3148 permstr[6] = 'a';
3149 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES)
3150 permstr[7] = 'A';
3151 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS)
3152 permstr[8] = 'R';
3153 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS)
3154 permstr[9] = 'W';
3155 if (ace->a_access_mask & ACE_READ_ACL)
3156 permstr[10] = 'c';
3157 if (ace->a_access_mask & ACE_WRITE_ACL)
3158 permstr[11] = 'C';
3159 if (ace->a_access_mask & ACE_WRITE_OWNER)
3160 permstr[12] = 'o';
3161 if (ace->a_access_mask & ACE_SYNCHRONIZE)
3162 permstr[13] = 's';
3163 permstr[14] = '\0';
3164 uval.uvaltype = PRA_STRING;
3165 uval.string_val = permstr;
3166 } else if (!(context->format & PRF_RAWM)) {
3169 * Note this differs from acltext.c:ace_perm_txt()
3170 * because we don't know if the acl belongs to a file
3171 * or directory. ace mask value are the same
3172 * nonetheless, see sys/acl.h
3174 if (ace->a_access_mask & ACE_LIST_DIRECTORY) {
3175 returnstat = strappend(&permstr, gettext(READ_DIR_TXT),
3176 &permstr_alloc);
3178 if (ace->a_access_mask & ACE_ADD_FILE) {
3179 returnstat = strappend(&permstr, gettext(ADD_FILE_TXT),
3180 &permstr_alloc);
3182 if (ace->a_access_mask & ACE_ADD_SUBDIRECTORY) {
3183 returnstat = strappend(&permstr, gettext(ADD_DIR_TXT),
3184 &permstr_alloc);
3186 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS) {
3187 returnstat = strappend(&permstr,
3188 gettext(READ_XATTR_TXT), &permstr_alloc);
3190 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS) {
3191 returnstat = strappend(&permstr,
3192 gettext(WRITE_XATTR_TXT), &permstr_alloc);
3194 if (ace->a_access_mask & ACE_EXECUTE) {
3195 returnstat = strappend(&permstr,
3196 gettext(EXECUTE_TXT), &permstr_alloc);
3198 if (ace->a_access_mask & ACE_DELETE_CHILD) {
3199 returnstat = strappend(&permstr,
3200 gettext(DELETE_CHILD_TXT), &permstr_alloc);
3202 if (ace->a_access_mask & ACE_READ_ATTRIBUTES) {
3203 returnstat = strappend(&permstr,
3204 gettext(READ_ATTRIBUTES_TXT), &permstr_alloc);
3206 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES) {
3207 returnstat = strappend(&permstr,
3208 gettext(WRITE_ATTRIBUTES_TXT), &permstr_alloc);
3210 if (ace->a_access_mask & ACE_DELETE) {
3211 returnstat = strappend(&permstr, gettext(DELETE_TXT),
3212 &permstr_alloc);
3214 if (ace->a_access_mask & ACE_READ_ACL) {
3215 returnstat = strappend(&permstr, gettext(READ_ACL_TXT),
3216 &permstr_alloc);
3218 if (ace->a_access_mask & ACE_WRITE_ACL) {
3219 returnstat = strappend(&permstr, gettext(WRITE_ACL_TXT),
3220 &permstr_alloc);
3222 if (ace->a_access_mask & ACE_WRITE_OWNER) {
3223 returnstat = strappend(&permstr,
3224 gettext(WRITE_OWNER_TXT), &permstr_alloc);
3226 if (ace->a_access_mask & ACE_SYNCHRONIZE) {
3227 returnstat = strappend(&permstr,
3228 gettext(SYNCHRONIZE_TXT), &permstr_alloc);
3230 if (permstr[strlen(permstr) - 1] == '/')
3231 permstr[strlen(permstr) - 1] = '\0';
3232 uval.uvaltype = PRA_STRING;
3233 uval.string_val = permstr;
3235 if ((permstr == NULL) || (returnstat != 0) ||
3236 (context->format & PRF_RAWM)) {
3237 uval.uvaltype = PRA_UINT32;
3238 uval.uint32_val = ace->a_access_mask;
3240 returnstat = pa_print(context, &uval, flag);
3242 free(permstr);
3243 if (returnstat != 0)
3244 return (returnstat);
3245 return (close_tag(context, TAG_ACEMASK));
3248 static int
3249 pa_ace_type(pr_context_t *context, ace_t *ace, int status, int flag)
3251 int returnstat;
3252 uval_t uval;
3254 if (status < 0)
3255 return (status);
3258 * TRANSLATION_NOTE
3259 * ace->a_type refers to access type of ZFS/NFSv4 ACL entry.
3261 if ((returnstat = open_tag(context, TAG_ACETYPE)) != 0)
3262 return (returnstat);
3263 if (!(context->format & PRF_RAWM)) {
3264 uval.uvaltype = PRA_STRING;
3265 switch (ace->a_type) {
3266 case ACE_ACCESS_ALLOWED_ACE_TYPE:
3267 uval.string_val = gettext(ALLOW_TXT);
3268 break;
3269 case ACE_ACCESS_DENIED_ACE_TYPE:
3270 uval.string_val = gettext(DENY_TXT);
3271 break;
3272 case ACE_SYSTEM_AUDIT_ACE_TYPE:
3273 uval.string_val = gettext(AUDIT_TXT);
3274 break;
3275 case ACE_SYSTEM_ALARM_ACE_TYPE:
3276 uval.string_val = gettext(ALARM_TXT);
3277 break;
3278 default:
3279 uval.string_val = gettext(UNKNOWN_TXT);
3281 } else {
3282 uval.uvaltype = PRA_USHORT;
3283 uval.uint32_val = ace->a_type;
3285 if ((returnstat = pa_print(context, &uval, flag)) != 0)
3286 return (returnstat);
3287 return (close_tag(context, TAG_ACETYPE));
3291 pa_ace(pr_context_t *context, int status, int flag)
3293 int returnstat;
3294 ace_t ace;
3296 if (status < 0)
3297 return (status);
3299 if ((returnstat = pr_adr_u_int32(context, &ace.a_who, 1)) != 0)
3300 return (returnstat);
3301 if ((returnstat = pr_adr_u_int32(context, &ace.a_access_mask, 1)) != 0)
3302 return (returnstat);
3303 if ((returnstat = pr_adr_u_short(context, &ace.a_flags, 1)) != 0)
3304 return (returnstat);
3305 if ((returnstat = pr_adr_u_short(context, &ace.a_type, 1)) != 0)
3306 return (returnstat);
3308 if ((returnstat = pa_ace_flags(context, &ace, returnstat, 0)) != 0)
3309 return (returnstat);
3310 /* pa_ace_who can returns 1 if uid/gid is not found */
3311 if ((returnstat = pa_ace_who(context, &ace, returnstat, 0)) < 0)
3312 return (returnstat);
3313 if ((returnstat = pa_ace_access_mask(context, &ace,
3314 returnstat, 0)) != 0)
3315 return (returnstat);
3316 return (pa_ace_type(context, &ace, returnstat, flag));