Merge commit '00f1a4f432b3d8aad1aa270e91c44c57f03ef407'
[unleashed.git] / usr / src / cmd / praudit / format.c
blob2d824727efaf2de10776393407121f083c1f9112
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 * for uid/gid caches
66 static uid_t lastuid = (uid_t)-1;
67 static gid_t lastgid = (gid_t)-1;
68 static char *lastuname = NULL;
69 static char *lastgname = NULL;
70 static char *getname(uid_t);
71 static char *getgroup(gid_t);
72 static struct cachenode *findincache(struct cachenode **, long);
73 #include <utmpx.h>
75 struct utmpx utmp;
77 #define NMAX (sizeof (utmp.ut_name))
78 #define SCPYN(a, b) (void) strncpy(a, b, NMAX)
80 struct cachenode { /* this struct must be zeroed before using */
81 struct cachenode *lesschild; /* subtree whose entries < val */
82 struct cachenode *grtrchild; /* subtree whose entries > val */
83 long val; /* the uid or gid of this entry */
84 int initted; /* name has been filled in */
85 char name[NMAX+1]; /* the string that val maps to */
87 static struct cachenode *names, *groups;
89 static struct cachenode *
90 findincache(struct cachenode **head, long val)
92 struct cachenode **parent = head;
93 struct cachenode *c = *parent;
95 while (c != NULL) {
96 if (val == c->val) {
97 /* found it */
98 return (c);
99 } else if (val < c->val) {
100 parent = &c->lesschild;
101 c = c->lesschild;
102 } else {
103 parent = &c->grtrchild;
104 c = c->grtrchild;
108 /* not in the cache, make a new entry for it */
109 c = calloc(1, sizeof (struct cachenode));
110 if (c == NULL) {
111 perror("praudit");
112 exit(2);
114 *parent = c;
115 c->val = val;
116 return (c);
120 * get name from cache, or passwd file for a given uid;
121 * lastuid is set to uid.
123 static char *
124 getname(uid_t uid)
126 struct passwd *pwent;
127 struct cachenode *c;
129 if ((uid == lastuid) && lastuname)
130 return (lastuname);
132 c = findincache(&names, uid);
133 if (c->initted == 0) {
134 if ((pwent = getpwuid(uid)) != NULL) {
135 SCPYN(&c->name[0], pwent->pw_name);
136 } else {
137 (void) sprintf(&c->name[0], "%u", (int)uid);
139 c->initted = 1;
141 lastuid = uid;
142 lastuname = &c->name[0];
143 return (lastuname);
147 * get name from cache, or group file for a given gid;
148 * lastgid is set to gid.
150 static char *
151 getgroup(gid_t gid)
153 struct group *grent;
154 struct cachenode *c;
156 if ((gid == lastgid) && lastgname)
157 return (lastgname);
159 c = findincache(&groups, gid);
160 if (c->initted == 0) {
161 if ((grent = getgrgid(gid)) != NULL) {
162 SCPYN(&c->name[0], grent->gr_name);
163 } else {
164 (void) sprintf(&c->name[0], "%u", (int)gid);
166 c->initted = 1;
168 lastgid = gid;
169 lastgname = &c->name[0];
170 return (lastgname);
174 * ------------------------------------------------------
175 * field widths for arbitrary data token type
176 * ------------------------------------------------------
178 static struct fw {
179 char basic_unit;
180 struct {
181 char print_base;
182 int field_width;
183 } pwidth[5];
184 } fwidth[] = {
185 /* character data type, 8 bits */
186 AUR_CHAR, AUP_BINARY, 12,
187 AUP_OCTAL, 6,
188 AUP_DECIMAL, 6,
189 AUP_HEX, 6,
190 AUP_STRING, 1,
191 AUR_BYTE, AUP_BINARY, 12,
192 AUP_OCTAL, 6,
193 AUP_DECIMAL, 6,
194 AUP_HEX, 6,
195 AUP_STRING, 1,
196 AUR_SHORT, AUP_BINARY, 20,
197 AUP_OCTAL, 10,
198 AUP_DECIMAL, 10,
199 AUP_HEX, 8,
200 AUP_STRING, 6,
201 AUR_INT32, AUP_BINARY, 36,
202 AUP_OCTAL, 18,
203 AUP_DECIMAL, 18,
204 AUP_HEX, 12,
205 AUP_STRING, 10,
206 AUR_INT64, AUP_BINARY, 68,
207 AUP_OCTAL, 34,
208 AUP_DECIMAL, 34,
209 AUP_HEX, 20,
210 AUP_STRING, 20};
213 static int numwidthentries = sizeof (fwidth)
214 / sizeof (struct fw);
218 * -----------------------------------------------------------------------
219 * do_newline:
220 * Print a newline, if needed according to various formatting
221 * rules.
222 * return codes : 0 - success
223 * : -1 - error
224 * -----------------------------------------------------------------------
227 do_newline(pr_context_t *context, int flag)
229 int retstat = 0;
231 if (!(context->format & PRF_ONELINE) && (flag == 1))
232 retstat = pr_putchar(context, '\n');
233 else if (!(context->format & PRF_XMLM))
234 retstat = pr_printf(context, "%s", context->SEPARATOR);
236 return (retstat);
240 open_tag(pr_context_t *context, int tagnum)
242 int err = 0;
243 token_desc_t *tag;
245 /* no-op if not doing XML format */
246 if (!(context->format & PRF_XMLM))
247 return (0);
249 tag = &tokentable[tagnum];
252 * First if needed do an implicit finish of a pending open for an
253 * extended tag. I.e., for the extended tag xxx:
254 * <xxx a=".." b=".."> ... </xxx>
255 * -- insert a close bracket after the last attribute
256 * (in other words, when the 1st non-attribute is opened while
257 * this is pending). Note that only one tag could be pending at
258 * a given time -- it couldn't be nested.
260 if (context->pending_flag && (tag->t_type != T_ATTRIBUTE)) {
261 /* complete pending extended open */
262 err = pr_putchar(context, '>');
263 if (err != 0)
264 return (err);
265 context->pending_flag = 0;
268 if (is_header_token(tagnum) || is_file_token(tagnum)) {
269 /* File token or new record on new line */
270 err = pr_putchar(context, '\n');
271 } else if (is_token(tagnum)) {
272 /* Each token on new line if possible */
273 err = do_newline(context, 1);
275 if (err != 0)
276 return (err);
278 switch (tag->t_type) {
279 case T_ATTRIBUTE:
280 err = pr_printf(context, " %s=\"", tag->t_tagname);
281 break;
282 case T_ELEMENT:
283 err = pr_printf(context, "<%s>", tag->t_tagname);
284 break;
285 case T_ENCLOSED:
286 err = pr_printf(context, "<%s", tag->t_tagname);
287 break;
288 case T_EXTENDED:
289 err = pr_printf(context, "<%s", tag->t_tagname);
290 if (err == 0)
291 context->pending_flag = tagnum;
292 break;
293 default:
294 break;
297 if (is_header_token(tagnum) && (err == 0))
298 context->current_rec = tagnum; /* set start of new record */
300 return (err);
304 * Do an implicit close of a record when needed.
307 check_close_rec(pr_context_t *context, int tagnum)
309 int err = 0;
311 /* no-op if not doing XML format */
312 if (!(context->format & PRF_XMLM))
313 return (0);
316 * If we're opening a header or the file token (i.e., starting a new
317 * record), if there's a current record in progress do an implicit
318 * close of it.
320 if ((is_header_token(tagnum) || is_file_token(tagnum)) &&
321 context->current_rec) {
322 err = do_newline(context, 1);
323 if (err == 0)
324 err = close_tag(context, context->current_rec);
327 return (err);
331 * explicit finish of a pending open for an extended tag.
334 finish_open_tag(pr_context_t *context)
336 int err = 0;
338 /* no-op if not doing XML format */
339 if (!(context->format & PRF_XMLM))
340 return (0);
342 if (context->pending_flag) {
343 /* complete pending extended open */
344 err = pr_putchar(context, '>');
345 if (err == 0)
346 context->pending_flag = 0;
348 return (err);
352 close_tag(pr_context_t *context, int tagnum)
354 int err = 0;
355 token_desc_t *tag;
357 /* no-op if not doing XML format */
358 if (!(context->format & PRF_XMLM))
359 return (0);
361 tag = &tokentable[tagnum];
363 switch (tag->t_type) {
364 case T_ATTRIBUTE:
365 err = pr_putchar(context, '\"');
366 break;
367 case T_ELEMENT:
368 err = pr_printf(context, "</%s>", tag->t_tagname);
369 break;
370 case T_ENCLOSED:
371 err = pr_printf(context, "/>");
372 break;
373 case T_EXTENDED:
374 err = pr_printf(context, "</%s>", tag->t_tagname);
375 break;
376 default:
377 break;
380 if (is_header_token(tagnum) && (err == 0))
381 context->current_rec = 0; /* closing rec; none current */
383 return (err);
387 * -----------------------------------------------------------------------
388 * process_tag:
389 * Calls the routine corresponding to the tag
390 * Note that to use this mechanism, all such routines must
391 * take 2 ints for their parameters; the first of these is
392 * the current status.
394 * flag = 1 for newline / delimiter, else 0
395 * return codes : -1 - error
396 * : 0 - successful
397 * -----------------------------------------------------------------------
400 process_tag(pr_context_t *context, int tagnum, int status, int flag)
402 int retstat;
404 retstat = status;
406 if (retstat)
407 return (retstat);
409 if ((tagnum > 0) && (tagnum <= MAXTAG) &&
410 (tokentable[tagnum].func != NOFUNC)) {
411 retstat = open_tag(context, tagnum);
412 if (!retstat)
413 retstat = (*tokentable[tagnum].func)(context, status,
414 flag);
415 if (!retstat)
416 retstat = close_tag(context, tagnum);
417 return (retstat);
419 /* here if token id is not in table */
420 (void) fprintf(stderr, gettext("praudit: No code associated with "
421 "tag id %d\n"), tagnum);
422 return (0);
425 void
426 get_Hname(uint32_t addr, char *buf, size_t buflen)
428 extern char *inet_ntoa(const struct in_addr);
429 struct hostent *phe;
430 struct in_addr ia;
432 phe = gethostbyaddr((const char *)&addr, 4, AF_INET);
433 if (phe == NULL) {
434 ia.s_addr = addr;
435 (void) snprintf(buf, buflen, "%s", inet_ntoa(ia));
436 return;
438 ia.s_addr = addr;
439 (void) snprintf(buf, buflen, "%s", phe->h_name);
442 void
443 get_Hname_ex(uint32_t *addr, char *buf, size_t buflen)
445 struct hostent *phe;
446 int err;
448 phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
450 if (phe == NULL) {
451 (void) inet_ntop(AF_INET6, (void *)addr, buf, buflen);
452 } else
453 (void) snprintf(buf, buflen, "%s", phe->h_name);
455 if (phe)
456 freehostent(phe);
460 pa_hostname(pr_context_t *context, int status, int flag)
462 int returnstat;
463 uint32_t ip_addr;
464 struct in_addr ia;
465 uval_t uval;
466 char buf[256];
468 if (status < 0)
469 return (status);
471 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
472 return (returnstat);
474 uval.uvaltype = PRA_STRING;
476 if (!(context->format & PRF_RAWM)) {
477 uval.string_val = buf;
478 get_Hname(ip_addr, buf, sizeof (buf));
479 returnstat = pa_print(context, &uval, flag);
480 } else {
481 ia.s_addr = ip_addr;
482 if ((uval.string_val = inet_ntoa(ia)) == NULL)
483 return (-1);
484 returnstat = pa_print(context, &uval, flag);
486 return (returnstat);
490 pa_hostname_ex(pr_context_t *context, int status, int flag)
492 int returnstat;
493 uint32_t ip_type;
494 uint32_t ip_addr[4];
495 struct in_addr ia;
496 char buf[256];
497 uval_t uval;
499 if (status < 0)
500 return (status);
502 /* get ip type */
503 if ((returnstat = pr_adr_int32(context, (int32_t *)&ip_type, 1)) != 0)
504 return (returnstat);
506 /* only IPv4 and IPv6 addresses are legal */
507 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
508 return (-1);
510 /* get ip address */
511 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
512 return (returnstat);
514 if ((returnstat = open_tag(context, TAG_HOSTID)) != 0)
515 return (returnstat);
517 uval.uvaltype = PRA_STRING;
518 if (ip_type == AU_IPv4) { /* ipv4 address */
519 if (!(context->format & PRF_RAWM)) {
520 uval.string_val = buf;
521 get_Hname(ip_addr[0], buf, sizeof (buf));
522 returnstat = pa_print(context, &uval, flag);
523 } else {
524 ia.s_addr = ip_addr[0];
525 if ((uval.string_val = inet_ntoa(ia)) == NULL)
526 return (-1);
527 returnstat = pa_print(context, &uval, flag);
529 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
530 if (!(context->format & PRF_RAWM)) {
531 uval.string_val = buf;
532 get_Hname_ex(ip_addr, buf, sizeof (buf));
533 returnstat = pa_print(context, &uval, flag);
534 } else {
535 uval.string_val = (char *)buf;
536 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
537 sizeof (buf));
538 returnstat = pa_print(context, &uval, flag);
542 if (returnstat != 0)
543 return (returnstat);
544 return (close_tag(context, TAG_HOSTID));
548 pa_hostname_so(pr_context_t *context, int status, int flag)
550 int returnstat;
551 short ip_type;
552 ushort_t ip_port;
553 uint32_t ip_addr[4];
554 struct in_addr ia;
555 char buf[256];
556 uval_t uval;
558 if (status < 0)
559 return (status);
561 /* get ip type */
562 if ((returnstat = pr_adr_short(context, &ip_type, 1)) != 0)
563 return (returnstat);
565 /* only IPv4 and IPv6 addresses are legal */
566 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
567 return (-1);
569 /* get local ip port */
570 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
571 return (returnstat);
573 if ((returnstat = open_tag(context, TAG_SOCKEXLPORT)) != 0)
574 return (returnstat);
576 uval.uvaltype = PRA_STRING;
577 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
578 sizeof (ip_port));
579 if (uval.string_val) {
580 returnstat = pa_print(context, &uval, 0);
581 free(uval.string_val);
582 } else
583 returnstat = -1;
584 if (returnstat)
585 return (returnstat);
587 if ((returnstat = close_tag(context, TAG_SOCKEXLPORT)) != 0)
588 return (returnstat);
590 /* get local ip address */
591 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
592 return (returnstat);
594 if ((returnstat = open_tag(context, TAG_SOCKEXLADDR)) != 0)
595 return (returnstat);
597 if (ip_type == AU_IPv4) { /* ipv4 address */
599 if (!(context->format & PRF_RAWM)) {
600 uval.string_val = buf;
601 get_Hname(ip_addr[0], buf, sizeof (buf));
602 returnstat = pa_print(context, &uval, 0);
603 } else {
604 ia.s_addr = ip_addr[0];
605 if ((uval.string_val = inet_ntoa(ia)) == NULL)
606 return (-1);
607 returnstat = pa_print(context, &uval, 0);
610 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
612 if (!(context->format & PRF_RAWM)) {
613 uval.string_val = buf;
614 get_Hname_ex(ip_addr, buf, sizeof (buf));
615 returnstat = pa_print(context, &uval, 0);
616 } else {
617 uval.string_val = (char *)buf;
618 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
619 sizeof (buf));
620 returnstat = pa_print(context, &uval, 0);
622 } else
623 returnstat = -1;
625 if (returnstat)
626 return (returnstat);
628 if ((returnstat = close_tag(context, TAG_SOCKEXLADDR)) != 0)
629 return (returnstat);
631 /* get foreign ip port */
632 if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
633 return (returnstat);
635 if ((returnstat = open_tag(context, TAG_SOCKEXFPORT)) != 0)
636 return (returnstat);
638 uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
639 sizeof (ip_port));
640 if (uval.string_val) {
641 returnstat = pa_print(context, &uval, 0);
642 free(uval.string_val);
643 } else
644 returnstat = -1;
646 if (returnstat)
647 return (returnstat);
649 if ((returnstat = close_tag(context, TAG_SOCKEXFPORT)) != 0)
650 return (returnstat);
652 /* get foreign ip address */
653 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
654 return (returnstat);
656 if ((returnstat = open_tag(context, TAG_SOCKEXFADDR)) != 0)
657 return (returnstat);
659 if (ip_type == AU_IPv4) { /* ipv4 address */
661 if (!(context->format & PRF_RAWM)) {
662 uval.string_val = buf;
663 get_Hname(ip_addr[0], buf, sizeof (buf));
664 returnstat = pa_print(context, &uval, flag);
665 } else {
666 ia.s_addr = ip_addr[0];
667 if ((uval.string_val = inet_ntoa(ia)) == NULL)
668 return (-1);
669 returnstat = pa_print(context, &uval, flag);
672 } else if (ip_type == AU_IPv6) { /* IPv6 addresss (128 bits) */
674 if (!(context->format & PRF_RAWM)) {
675 uval.string_val = buf;
676 get_Hname_ex(ip_addr, buf, sizeof (buf));
677 returnstat = pa_print(context, &uval, flag);
678 } else {
679 uval.string_val = (char *)buf;
680 (void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
681 sizeof (buf));
682 returnstat = pa_print(context, &uval, flag);
684 } else
685 returnstat = -1;
687 if (returnstat)
688 return (returnstat);
690 if ((returnstat = close_tag(context, TAG_SOCKEXFADDR)) != 0)
691 return (returnstat);
693 return (returnstat);
697 #define NBITSMAJOR64 32 /* # of major device bits in 64-bit Solaris */
698 #define NBITSMINOR64 32 /* # of minor device bits in 64-bit Solaris */
699 #define MAXMAJ64 0xfffffffful /* max major value */
700 #define MAXMIN64 0xfffffffful /* max minor value */
702 #define NBITSMAJOR32 14 /* # of SVR4 major device bits */
703 #define NBITSMINOR32 18 /* # of SVR4 minor device bits */
704 #define NMAXMAJ32 0x3fff /* SVR4 max major value */
705 #define NMAXMIN32 0x3ffff /* MAX minor for 3b2 software drivers. */
708 static int32_t
709 minor_64(uint64_t dev)
711 if (dev == NODEV) {
712 errno = EINVAL;
713 return (NODEV);
715 return (int32_t)(dev & MAXMIN64);
718 static int32_t
719 major_64(uint64_t dev)
721 uint32_t maj;
723 maj = (uint32_t)(dev >> NBITSMINOR64);
725 if (dev == NODEV || maj > MAXMAJ64) {
726 errno = EINVAL;
727 return (NODEV);
729 return (int32_t)(maj);
732 static int32_t
733 minor_32(uint32_t dev)
735 if (dev == NODEV) {
736 errno = EINVAL;
737 return (NODEV);
739 return (int32_t)(dev & MAXMIN32);
742 static int32_t
743 major_32(uint32_t dev)
745 uint32_t maj;
747 maj = (uint32_t)(dev >> NBITSMINOR32);
749 if (dev == NODEV || maj > MAXMAJ32) {
750 errno = EINVAL;
751 return (NODEV);
753 return (int32_t)(maj);
758 * -----------------------------------------------------------------------
759 * pa_tid() : Process terminal id and display contents
760 * return codes : -1 - error
761 * : 0 - successful
763 * terminal id port adr_int32
764 * terminal id machine adr_int32
765 * -----------------------------------------------------------------------
768 pa_tid32(pr_context_t *context, int status, int flag)
770 int returnstat;
771 int32_t dev_maj_min;
772 uint32_t ip_addr;
773 struct in_addr ia;
774 char *ipstring;
775 char buf[256];
776 uval_t uval;
778 if (status < 0)
779 return (status);
781 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
782 return (returnstat);
784 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
785 return (returnstat);
787 uval.uvaltype = PRA_STRING;
788 uval.string_val = buf;
790 if (!(context->format & PRF_RAWM)) {
791 char hostname[256];
793 get_Hname(ip_addr, hostname, sizeof (hostname));
794 (void) snprintf(buf, sizeof (buf), "%d %d %s",
795 major_32(dev_maj_min),
796 minor_32(dev_maj_min),
797 hostname);
798 return (pa_print(context, &uval, flag));
801 ia.s_addr = ip_addr;
802 if ((ipstring = inet_ntoa(ia)) == NULL)
803 return (-1);
805 (void) snprintf(buf, sizeof (buf), "%d %d %s", major_32(dev_maj_min),
806 minor_32(dev_maj_min),
807 ipstring);
809 return (pa_print(context, &uval, flag));
813 pa_tid32_ex(pr_context_t *context, int status, int flag)
815 int returnstat;
816 int32_t dev_maj_min;
817 uint32_t ip_addr[16];
818 uint32_t ip_type;
819 struct in_addr ia;
820 char *ipstring;
821 char hostname[256];
822 char buf[256];
823 char tbuf[256];
824 uval_t uval;
826 if (status < 0)
827 return (status);
829 /* get port info */
830 if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
831 return (returnstat);
833 /* get address type */
834 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
835 return (returnstat);
837 /* legal address types are either AU_IPv4 or AU_IPv6 only */
838 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
839 return (-1);
841 /* get address (4/16) */
842 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
843 return (returnstat);
845 uval.uvaltype = PRA_STRING;
846 if (ip_type == AU_IPv4) {
847 uval.string_val = buf;
849 if (!(context->format & PRF_RAWM)) {
850 get_Hname(ip_addr[0], hostname, sizeof (hostname));
851 (void) snprintf(buf, sizeof (buf), "%d %d %s",
852 major_32(dev_maj_min), minor_32(dev_maj_min),
853 hostname);
854 return (pa_print(context, &uval, flag));
857 ia.s_addr = ip_addr[0];
858 if ((ipstring = inet_ntoa(ia)) == NULL)
859 return (-1);
861 (void) snprintf(buf, sizeof (buf), "%d %d %s",
862 major_32(dev_maj_min), minor_32(dev_maj_min), ipstring);
864 return (pa_print(context, &uval, flag));
865 } else {
866 uval.string_val = buf;
868 if (!(context->format & PRF_RAWM)) {
869 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
870 (void) snprintf(buf, sizeof (buf), "%d %d %s",
871 major_32(dev_maj_min), minor_32(dev_maj_min),
872 hostname);
873 return (pa_print(context, &uval, flag));
876 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
877 sizeof (tbuf));
879 (void) snprintf(buf, sizeof (buf), "%d %d %s",
880 major_32(dev_maj_min), minor_32(dev_maj_min), tbuf);
882 return (pa_print(context, &uval, flag));
887 pa_ip_addr(pr_context_t *context, int status, int flag)
889 int returnstat;
890 uval_t uval;
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];
899 if (status < 0)
900 return (status);
902 /* get address type */
903 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
904 return (returnstat);
906 /* legal address type is AU_IPv4 or AU_IPv6 */
907 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
908 return (-1);
910 /* get address (4/16) */
911 if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
912 return (returnstat);
914 uval.uvaltype = PRA_STRING;
915 if (ip_type == AU_IPv4) {
916 uval.string_val = buf;
918 if (!(context->format & PRF_RAWM)) {
919 get_Hname(ip_addr[0], hostname, sizeof (hostname));
920 (void) snprintf(buf, sizeof (buf), "%s", hostname);
921 return (pa_print(context, &uval, flag));
924 ia.s_addr = ip_addr[0];
925 if ((ipstring = inet_ntoa(ia)) == NULL)
926 return (-1);
928 (void) snprintf(buf, sizeof (buf), "%s", ipstring);
930 return (pa_print(context, &uval, flag));
931 } else {
932 uval.string_val = buf;
934 if (!(context->format & PRF_RAWM)) {
935 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
936 (void) snprintf(buf, sizeof (buf), "%s",
937 hostname);
938 return (pa_print(context, &uval, flag));
941 (void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
942 sizeof (tbuf));
944 (void) snprintf(buf, sizeof (buf), "%s", tbuf);
946 return (pa_print(context, &uval, flag));
952 pa_tid64(pr_context_t *context, int status, int flag)
954 int returnstat;
955 int64_t dev_maj_min;
956 uint32_t ip_addr;
957 struct in_addr ia;
958 char *ipstring;
959 char buf[256];
960 uval_t uval;
962 if (status < 0)
963 return (status);
965 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
966 return (returnstat);
968 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
969 return (returnstat);
971 uval.uvaltype = PRA_STRING;
972 uval.string_val = buf;
974 if (!(context->format & PRF_RAWM)) {
975 char hostname[256];
977 get_Hname(ip_addr, hostname, sizeof (hostname));
978 (void) snprintf(buf, sizeof (buf), "%d %d %s",
979 major_64(dev_maj_min), minor_64(dev_maj_min), hostname);
980 return (pa_print(context, &uval, flag));
983 ia.s_addr = ip_addr;
984 if ((ipstring = inet_ntoa(ia)) == NULL)
985 return (-1);
987 (void) snprintf(buf, sizeof (buf), "%d %d %s",
988 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
990 return (pa_print(context, &uval, flag));
994 pa_tid64_ex(pr_context_t *context, int status, int flag)
996 int returnstat;
997 int64_t dev_maj_min;
998 uint32_t ip_addr[4];
999 uint32_t ip_type;
1000 struct in_addr ia;
1001 char *ipstring;
1002 char hostname[256];
1003 char buf[256];
1004 char tbuf[256];
1005 uval_t uval;
1007 if (status < 0)
1008 return (status);
1010 /* get port info */
1011 if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
1012 return (returnstat);
1014 /* get address type */
1015 if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
1016 return (returnstat);
1018 /* legal address types are either AU_IPv4 or AU_IPv6 only */
1019 if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
1020 return (-1);
1022 /* get address (4/16) */
1023 if ((returnstat = pr_adr_char(context, (char *)&ip_addr, ip_type)) != 0)
1024 return (returnstat);
1026 uval.uvaltype = PRA_STRING;
1027 if (ip_type == AU_IPv4) {
1028 uval.string_val = buf;
1030 if (!(context->format & PRF_RAWM)) {
1031 get_Hname(ip_addr[0], hostname, sizeof (hostname));
1032 uval.string_val = buf;
1033 (void) snprintf(buf, sizeof (buf), "%d %d %s",
1034 major_64(dev_maj_min), minor_64(dev_maj_min),
1035 hostname);
1036 return (pa_print(context, &uval, flag));
1039 ia.s_addr = ip_addr[0];
1040 if ((ipstring = inet_ntoa(ia)) == NULL)
1041 return (-1);
1043 (void) snprintf(buf, sizeof (buf), "%d %d %s",
1044 major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
1046 return (pa_print(context, &uval, flag));
1047 } else {
1048 uval.string_val = buf;
1050 if (!(context->format & PRF_RAWM)) {
1051 get_Hname_ex(ip_addr, hostname, sizeof (hostname));
1052 (void) snprintf(buf, sizeof (buf), "%d %d %s",
1053 major_64(dev_maj_min), minor_64(dev_maj_min),
1054 hostname);
1055 return (pa_print(context, &uval, flag));
1058 (void) inet_ntop(AF_INET6, (void *)ip_addr, tbuf,
1059 sizeof (tbuf));
1061 (void) snprintf(buf, sizeof (buf), "%d %d %s",
1062 major_64(dev_maj_min), minor_64(dev_maj_min), tbuf);
1064 return (pa_print(context, &uval, flag));
1070 * ----------------------------------------------------------------
1071 * findfieldwidth:
1072 * Returns the field width based on the basic unit and print mode.
1073 * This routine is called to determine the field width for the
1074 * data items in the arbitrary data token where the tokens are
1075 * to be printed in more than one line. The field width can be
1076 * found in the fwidth structure.
1078 * Input parameters:
1079 * basicunit Can be one of AUR_CHAR, AUR_BYTE, AUR_SHORT,
1080 * AUR_INT32, or AUR_INT64
1081 * howtoprint Print mode. Can be one of AUP_BINARY, AUP_OCTAL,
1082 * AUP_DECIMAL, or AUP_HEX.
1083 * ----------------------------------------------------------------
1086 findfieldwidth(char basicunit, char howtoprint)
1088 int i, j;
1090 for (i = 0; i < numwidthentries; i++) {
1091 if (fwidth[i].basic_unit == basicunit) {
1092 for (j = 0; j <= 4; j++) {
1093 if (fwidth[i].pwidth[j].print_base ==
1094 howtoprint) {
1095 return (
1096 fwidth[i].pwidth[j].field_width);
1100 * if we got here, then we didn't get what we were after
1102 return (0);
1105 /* if we got here, we didn't get what we wanted either */
1106 return (0);
1111 * -----------------------------------------------------------------------
1112 * pa_cmd: Retrieves the cmd item from the input stream.
1113 * return codes : -1 - error
1114 * : 0 - successful
1115 * -----------------------------------------------------------------------
1118 pa_cmd(pr_context_t *context, int status, int flag)
1120 char *cmd; /* cmd */
1121 short length;
1122 int returnstat;
1123 uval_t uval;
1126 * We need to know how much space to allocate for our string, so
1127 * read the length first, then call pr_adr_char to read those bytes.
1129 if (status >= 0) {
1130 if (pr_adr_short(context, &length, 1) == 0) {
1131 if ((cmd = (char *)malloc(length + 1)) == NULL)
1132 return (-1);
1133 if (pr_adr_char(context, cmd, length) == 0) {
1134 uval.uvaltype = PRA_STRING;
1135 uval.string_val = cmd;
1136 returnstat = pa_print(context, &uval, flag);
1137 } else {
1138 returnstat = -1;
1140 free(cmd);
1141 return (returnstat);
1142 } else
1143 return (-1);
1144 } else
1145 return (status);
1151 * -----------------------------------------------------------------------
1152 * pa_adr_byte : Issues pr_adr_char to retrieve the next ADR item from
1153 * the input stream pointed to by audit_adr, and prints it
1154 * as an integer if status >= 0
1155 * return codes : -1 - error
1156 * : 0 - successful
1157 * -----------------------------------------------------------------------
1160 pa_adr_byte(pr_context_t *context, int status, int flag)
1162 char c;
1163 uval_t uval;
1165 if (status >= 0) {
1166 if (pr_adr_char(context, &c, 1) == 0) {
1167 uval.uvaltype = PRA_BYTE;
1168 uval.char_val = c;
1169 return (pa_print(context, &uval, flag));
1170 } else
1171 return (-1);
1172 } else
1173 return (status);
1177 * -----------------------------------------------------------------------
1178 * pa_adr_charhex: Issues pr_adr_char to retrieve the next ADR item from
1179 * the input stream pointed to by audit_adr, and prints it
1180 * in hexadecimal if status >= 0
1181 * return codes : -1 - error
1182 * : 0 - successful
1183 * -----------------------------------------------------------------------
1186 pa_adr_charhex(pr_context_t *context, int status, int flag)
1188 char p[2];
1189 int returnstat;
1190 uval_t uval;
1192 if (status >= 0) {
1193 p[0] = p[1] = 0;
1195 if ((returnstat = pr_adr_char(context, p, 1)) == 0) {
1196 uval.uvaltype = PRA_STRING;
1197 uval.string_val = hexconvert(p, sizeof (char),
1198 sizeof (char));
1199 if (uval.string_val) {
1200 returnstat = pa_print(context, &uval, flag);
1201 free(uval.string_val);
1204 return (returnstat);
1205 } else
1206 return (status);
1210 * -----------------------------------------------------------------------
1211 * pa_adr_int32 : Issues pr_adr_int32 to retrieve the next ADR item from the
1212 * input stream pointed to by audit_adr, and prints it
1213 * if status >= 0
1214 * return codes : -1 - error
1215 * : 0 - successful
1216 * -----------------------------------------------------------------------
1219 pa_adr_int32(pr_context_t *context, int status, int flag)
1221 int32_t c;
1222 uval_t uval;
1224 if (status >= 0) {
1225 if (pr_adr_int32(context, &c, 1) == 0) {
1226 uval.uvaltype = PRA_INT32;
1227 uval.int32_val = c;
1228 return (pa_print(context, &uval, flag));
1229 } else
1230 return (-1);
1231 } else
1232 return (status);
1239 * -----------------------------------------------------------------------
1240 * pa_adr_int64 : Issues pr_adr_int64 to retrieve the next ADR item from the
1241 * input stream pointed to by audit_adr, and prints it
1242 * if status >= 0
1243 * return codes : -1 - error
1244 * : 0 - successful
1245 * -----------------------------------------------------------------------
1248 pa_adr_int64(pr_context_t *context, int status, int flag)
1250 int64_t c;
1251 uval_t uval;
1253 if (status >= 0) {
1254 if (pr_adr_int64(context, &c, 1) == 0) {
1255 uval.uvaltype = PRA_INT64;
1256 uval.int64_val = c;
1257 return (pa_print(context, &uval, flag));
1258 } else
1259 return (-1);
1260 } else
1261 return (status);
1265 * -----------------------------------------------------------------------
1266 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1267 * input stream pointed to by audit_adr, and prints it
1268 * in hexadecimal if status >= 0
1269 * return codes : -1 - error
1270 * : 0 - successful
1271 * -----------------------------------------------------------------------
1274 pa_adr_int32hex(pr_context_t *context, int status, int flag)
1276 int32_t l;
1277 int returnstat;
1278 uval_t uval;
1280 if (status >= 0) {
1281 if ((returnstat = pr_adr_int32(context, &l, 1)) == 0) {
1282 uval.uvaltype = PRA_HEX32;
1283 uval.int32_val = l;
1284 returnstat = pa_print(context, &uval, flag);
1286 return (returnstat);
1287 } else
1288 return (status);
1292 * -----------------------------------------------------------------------
1293 * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1294 * input stream pointed to by audit_adr, and prints it
1295 * in hexadecimal if status >= 0
1296 * return codes : -1 - error
1297 * : 0 - successful
1298 * -----------------------------------------------------------------------
1301 pa_adr_int64hex(pr_context_t *context, int status, int flag)
1303 int64_t l;
1304 int returnstat;
1305 uval_t uval;
1307 if (status >= 0) {
1308 if ((returnstat = pr_adr_int64(context, &l, 1)) == 0) {
1309 uval.uvaltype = PRA_HEX64;
1310 uval.int64_val = l;
1311 returnstat = pa_print(context, &uval, flag);
1313 return (returnstat);
1314 } else
1315 return (status);
1320 * -------------------------------------------------------------------
1321 * bu2string: Maps a print basic unit type to a string.
1322 * returns : The string mapping or "unknown basic unit type".
1323 * -------------------------------------------------------------------
1325 char *
1326 bu2string(char basic_unit)
1328 register int i;
1330 struct bu_map_ent {
1331 char basic_unit;
1332 char *string;
1336 * TRANSLATION_NOTE
1337 * These names are data units when displaying the arbitrary data
1338 * token.
1341 static struct bu_map_ent bu_map[] = {
1342 { AUR_BYTE, "byte" },
1343 { AUR_CHAR, "char" },
1344 { AUR_SHORT, "short" },
1345 { AUR_INT32, "int32" },
1346 { AUR_INT64, "int64" } };
1348 for (i = 0; i < sizeof (bu_map) / sizeof (struct bu_map_ent); i++)
1349 if (basic_unit == bu_map[i].basic_unit)
1350 return (gettext(bu_map[i].string));
1352 return (gettext("unknown basic unit type"));
1357 * -------------------------------------------------------------------
1358 * eventmodifier2string: Maps event modifier flags to a readable string.
1359 * returns: The string mapping or "none".
1360 * -------------------------------------------------------------------
1362 static void
1363 eventmodifier2string(au_emod_t emodifier, char *modstring, size_t modlen)
1365 register int i, j;
1367 struct em_map_ent {
1368 int mask;
1369 char *string;
1373 * TRANSLATION_NOTE
1374 * These abbreviations represent the event modifier field of the
1375 * header token. To gain a better understanding of each modifier,
1376 * read
1377 * System Administration Guide: Security Services >> Solaris Auditing
1378 * at http://docs.sun.com.
1381 static struct em_map_ent em_map[] = {
1382 { (int)PAD_READ, "rd" }, /* data read from object */
1383 { (int)PAD_WRITE, "wr" }, /* data written to object */
1384 { (int)PAD_SPRIVUSE, "sp" }, /* successfully used priv */
1385 { (int)PAD_FPRIVUSE, "fp" }, /* failed use of priv */
1386 { (int)PAD_NONATTR, "na" }, /* non-attributable event */
1387 { (int)PAD_FAILURE, "fe" } /* fail audit event */
1390 modstring[0] = '\0';
1392 for (i = 0, j = 0; i < sizeof (em_map) / sizeof (struct em_map_ent);
1393 i++) {
1394 if ((int)emodifier & em_map[i].mask) {
1395 if (j++)
1396 (void) strlcat(modstring, ":", modlen);
1397 (void) strlcat(modstring, em_map[i].string, modlen);
1404 * ---------------------------------------------------------
1405 * convert_char_to_string:
1406 * Converts a byte to string depending on the print mode
1407 * input : printmode, which may be one of AUP_BINARY,
1408 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1409 * c, which is the byte to convert
1410 * output : p, which is a pointer to the location where
1411 * the resulting string is to be stored
1412 * ----------------------------------------------------------
1416 convert_char_to_string(char printmode, char c, char *p)
1418 union {
1419 char c1[4];
1420 int c2;
1421 } dat;
1423 dat.c2 = 0;
1424 dat.c1[3] = c;
1426 if (printmode == AUP_BINARY)
1427 (void) convertbinary(p, &c, sizeof (char));
1428 else if (printmode == AUP_OCTAL)
1429 (void) sprintf(p, "%o", (int)dat.c2);
1430 else if (printmode == AUP_DECIMAL)
1431 (void) sprintf(p, "%d", c);
1432 else if (printmode == AUP_HEX)
1433 (void) sprintf(p, "0x%x", (int)dat.c2);
1434 else if (printmode == AUP_STRING)
1435 convertascii(p, &c, sizeof (char));
1436 return (0);
1440 * --------------------------------------------------------------
1441 * convert_short_to_string:
1442 * Converts a short integer to string depending on the print mode
1443 * input : printmode, which may be one of AUP_BINARY,
1444 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1445 * c, which is the short integer to convert
1446 * output : p, which is a pointer to the location where
1447 * the resulting string is to be stored
1448 * ---------------------------------------------------------------
1451 convert_short_to_string(char printmode, short c, char *p)
1453 union {
1454 short c1[2];
1455 int c2;
1456 } dat;
1458 dat.c2 = 0;
1459 dat.c1[1] = c;
1461 if (printmode == AUP_BINARY)
1462 (void) convertbinary(p, (char *)&c, sizeof (short));
1463 else if (printmode == AUP_OCTAL)
1464 (void) sprintf(p, "%o", (int)dat.c2);
1465 else if (printmode == AUP_DECIMAL)
1466 (void) sprintf(p, "%hd", c);
1467 else if (printmode == AUP_HEX)
1468 (void) sprintf(p, "0x%x", (int)dat.c2);
1469 else if (printmode == AUP_STRING)
1470 convertascii(p, (char *)&c, sizeof (short));
1471 return (0);
1475 * ---------------------------------------------------------
1476 * convert_int32_to_string:
1477 * Converts a integer to string depending on the print mode
1478 * input : printmode, which may be one of AUP_BINARY,
1479 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1480 * c, which is the integer to convert
1481 * output : p, which is a pointer to the location where
1482 * the resulting string is to be stored
1483 * ----------------------------------------------------------
1486 convert_int32_to_string(char printmode, int32_t c, char *p)
1488 if (printmode == AUP_BINARY)
1489 (void) convertbinary(p, (char *)&c, sizeof (int32_t));
1490 else if (printmode == AUP_OCTAL)
1491 (void) sprintf(p, "%o", c);
1492 else if (printmode == AUP_DECIMAL)
1493 (void) sprintf(p, "%d", c);
1494 else if (printmode == AUP_HEX)
1495 (void) sprintf(p, "0x%x", c);
1496 else if (printmode == AUP_STRING)
1497 convertascii(p, (char *)&c, sizeof (int));
1498 return (0);
1502 * ---------------------------------------------------------
1503 * convert_int64_to_string:
1504 * Converts a integer to string depending on the print mode
1505 * input : printmode, which may be one of AUP_BINARY,
1506 * AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1507 * c, which is the integer to convert
1508 * output : p, which is a pointer to the location where
1509 * the resulting string is to be stored
1510 * ----------------------------------------------------------
1513 convert_int64_to_string(char printmode, int64_t c, char *p)
1515 if (printmode == AUP_BINARY)
1516 (void) convertbinary(p, (char *)&c, sizeof (int64_t));
1517 else if (printmode == AUP_OCTAL)
1518 (void) sprintf(p, "%"PRIo64, c);
1519 else if (printmode == AUP_DECIMAL)
1520 (void) sprintf(p, "%"PRId64, c);
1521 else if (printmode == AUP_HEX)
1522 (void) sprintf(p, "0x%"PRIx64, c);
1523 else if (printmode == AUP_STRING)
1524 convertascii(p, (char *)&c, sizeof (int64_t));
1525 return (0);
1530 * -----------------------------------------------------------
1531 * convertbinary:
1532 * Converts a unit c of 'size' bytes long into a binary string
1533 * and returns it into the position pointed to by p
1534 * ------------------------------------------------------------
1537 convertbinary(char *p, char *c, int size)
1539 char *s, *t, *ss;
1540 int i, j;
1542 if ((s = (char *)malloc(8 * size + 1)) == NULL)
1543 return (0);
1545 ss = s;
1547 /* first convert to binary */
1548 t = s;
1549 for (i = 0; i < size; i++) {
1550 for (j = 0; j < 8; j++)
1551 (void) sprintf(t++, "%d", ((*c >> (7 - j)) & (0x01)));
1552 c++;
1554 *t = '\0';
1556 /* now string leading zero's if any */
1557 j = strlen(s) - 1;
1558 for (i = 0; i < j; i++) {
1559 if (*s != '0')
1560 break;
1561 else
1562 s++;
1565 /* now copy the contents of s to p */
1566 t = p;
1567 for (i = 0; i < (8 * size + 1); i++) {
1568 if (*s == '\0') {
1569 *t = '\0';
1570 break;
1572 *t++ = *s++;
1574 free(ss);
1576 return (1);
1580 static char hex[] = "0123456789abcdef";
1582 * -------------------------------------------------------------------
1583 * hexconvert : Converts a string of (size) bytes to hexadecimal, and
1584 * returns the hexadecimal string.
1585 * returns : - NULL if memory cannot be allocated for the string, or
1586 * - pointer to the hexadecimal string if successful
1587 * -------------------------------------------------------------------
1589 char *
1590 hexconvert(char *c, int size, int chunk)
1592 register char *s, *t;
1593 register int i, j, k;
1594 int numchunks;
1595 int leftovers;
1597 if (size <= 0)
1598 return (NULL);
1600 if ((s = (char *)malloc((size * 5) + 1)) == NULL)
1601 return (NULL);
1603 if (chunk > size || chunk <= 0)
1604 chunk = size;
1606 numchunks = size / chunk;
1607 leftovers = size % chunk;
1609 t = s;
1610 for (i = j = 0; i < numchunks; i++) {
1611 if (j++) {
1612 *t++ = ' ';
1614 *t++ = '0';
1615 *t++ = 'x';
1616 for (k = 0; k < chunk; k++) {
1617 *t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1618 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1619 c++;
1623 if (leftovers) {
1624 *t++ = ' ';
1625 *t++ = '0';
1626 *t++ = 'x';
1627 for (i = 0; i < leftovers; i++) {
1628 *t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1629 *t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1630 c++;
1634 *t = '\0';
1635 return (s);
1640 * -------------------------------------------------------------------
1641 * htp2string: Maps a print suggestion to a string.
1642 * returns : The string mapping or "unknown print suggestion".
1643 * -------------------------------------------------------------------
1645 char *
1646 htp2string(char print_sugg)
1648 register int i;
1650 struct htp_map_ent {
1651 char print_sugg;
1652 char *print_string;
1656 * TRANSLATION_NOTE
1657 * These names are data types when displaying the arbitrary data
1658 * token.
1661 static struct htp_map_ent htp_map[] = {
1662 { AUP_BINARY, "binary" },
1663 { AUP_OCTAL, "octal" },
1664 { AUP_DECIMAL, "decimal" },
1665 { AUP_HEX, "hexadecimal" },
1666 { AUP_STRING, "string" } };
1668 for (i = 0; i < sizeof (htp_map) / sizeof (struct htp_map_ent); i++)
1669 if (print_sugg == htp_map[i].print_sugg)
1670 return (gettext(htp_map[i].print_string));
1672 return (gettext("unknown print suggestion"));
1676 * ----------------------------------------------------------------------
1677 * pa_adr_short: Issues pr_adr_short to retrieve the next ADR item from the
1678 * input stream pointed to by audit_adr, and prints it
1679 * if status >= 0
1680 * return codes: -1 - error
1681 * : 0 - successful
1682 * ----------------------------------------------------------------------
1685 pa_adr_short(pr_context_t *context, int status, int flag)
1687 short c;
1688 uval_t uval;
1690 if (status >= 0) {
1691 if (pr_adr_short(context, &c, 1) == 0) {
1692 uval.uvaltype = PRA_SHORT;
1693 uval.short_val = c;
1694 return (pa_print(context, &uval, flag));
1695 } else
1696 return (-1);
1697 } else
1698 return (status);
1702 * -----------------------------------------------------------------------
1703 * pa_adr_shorthex: Issues pr_adr_short to retrieve the next ADR item from the
1704 * input stream pointed to by audit_adr, and prints it
1705 * in hexadecimal if status >= 0
1706 * return codes : -1 - error
1707 * : 0 - successful
1708 * -----------------------------------------------------------------------
1711 pa_adr_shorthex(pr_context_t *context, int status, int flag)
1713 short s;
1714 int returnstat;
1715 uval_t uval;
1717 if (status >= 0) {
1718 if ((returnstat = pr_adr_short(context, &s, 1)) == 0) {
1719 uval.uvaltype = PRA_STRING;
1720 uval.string_val = hexconvert((char *)&s, sizeof (s),
1721 sizeof (s));
1722 if (uval.string_val) {
1723 returnstat = pa_print(context, &uval, flag);
1724 free(uval.string_val);
1727 return (returnstat);
1728 } else
1729 return (status);
1734 * -----------------------------------------------------------------------
1735 * pa_adr_string: Retrieves a string from the input stream and prints it
1736 * if status >= 0
1737 * return codes : -1 - error
1738 * : 0 - successful
1739 * -----------------------------------------------------------------------
1742 pa_adr_string(pr_context_t *context, int status, int flag)
1744 char *c;
1745 short length;
1746 int returnstat;
1747 uval_t uval;
1750 * We need to know how much space to allocate for our string, so
1751 * read the length first, then call pr_adr_char to read those bytes.
1753 if (status < 0)
1754 return (status);
1756 if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1757 return (returnstat);
1758 if ((c = (char *)malloc(length + 1)) == NULL)
1759 return (-1);
1760 if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1761 free(c);
1762 return (returnstat);
1765 uval.uvaltype = PRA_STRING;
1766 uval.string_val = c;
1767 returnstat = pa_print(context, &uval, flag);
1768 free(c);
1769 return (returnstat);
1773 * -----------------------------------------------------------------------
1774 * pa_file_string: Retrieves a file string from the input stream and prints it
1775 * if status >= 0
1776 * return codes : -1 - error
1777 * : 0 - successful
1778 * -----------------------------------------------------------------------
1781 pa_file_string(pr_context_t *context, int status, int flag)
1783 char *c;
1784 char *p;
1785 short length;
1786 int returnstat;
1787 uval_t uval;
1790 * We need to know how much space to allocate for our string, so
1791 * read the length first, then call pr_adr_char to read those bytes.
1793 if (status < 0)
1794 return (status);
1796 if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1797 return (returnstat);
1798 if ((c = (char *)malloc(length + 1)) == NULL)
1799 return (-1);
1800 if ((p = (char *)malloc((length * 4) + 1)) == NULL) {
1801 free(c);
1802 return (-1);
1804 if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1805 free(c);
1806 free(p);
1807 return (returnstat);
1810 if (is_file_token(context->tokenid))
1811 context->audit_rec_len += length;
1813 convertascii(p, c, length - 1);
1814 uval.uvaltype = PRA_STRING;
1815 uval.string_val = p;
1817 if (returnstat == 0)
1818 returnstat = finish_open_tag(context);
1820 if (returnstat == 0)
1821 returnstat = pa_print(context, &uval, flag);
1823 free(c);
1824 free(p);
1825 return (returnstat);
1828 static int
1829 pa_putstr_xml(pr_context_t *context, int printable, char *str, size_t len)
1831 int err;
1833 if (!printable) {
1835 * Unprintable chars should always be converted to the
1836 * visible form. If there are unprintable characters which
1837 * require special treatment in xml, those should be
1838 * handled here.
1840 do {
1841 err = pr_printf(context, "\\%03o",
1842 (unsigned char)*str++);
1843 } while (err == 0 && --len != 0);
1844 return (err);
1846 /* printable characters */
1847 if (len == 1) {
1849 * check for the special chars only when char size was 1
1850 * ie, ignore special chars appear in the middle of multibyte
1851 * sequence.
1854 /* Escape for XML */
1855 switch (*str) {
1856 case '&':
1857 err = pr_printf(context, "%s", "&amp;");
1858 break;
1860 case '<':
1861 err = pr_printf(context, "%s", "&lt;");
1862 break;
1864 case '>':
1865 err = pr_printf(context, "%s", "&gt;");
1866 break;
1868 case '\"':
1869 err = pr_printf(context, "%s", "&quot;");
1870 break;
1872 case '\'':
1873 err = pr_printf(context, "%s", "&apos;");
1874 break;
1876 default:
1877 err = pr_putchar(context, *str);
1878 break;
1880 return (err);
1882 do {
1883 err = pr_putchar(context, *str++);
1884 } while (err == 0 && --len != 0);
1885 return (err);
1888 static int
1889 pa_putstr(pr_context_t *context, int printable, char *str, size_t len)
1891 int err;
1893 if (context->format & PRF_XMLM)
1894 return (pa_putstr_xml(context, printable, str, len));
1896 if (!printable) {
1897 do {
1898 err = pr_printf(context, "\\%03o",
1899 (unsigned char)*str++);
1900 } while (err == 0 && --len != 0);
1901 return (err);
1903 do {
1904 err = pr_putchar(context, *str++);
1905 } while (err == 0 && --len != 0);
1906 return (err);
1910 pa_string(pr_context_t *context, int status, int flag)
1912 int rstat, wstat;
1913 int i, printable, eos;
1914 int mlen, rlen;
1915 int mbmax = MB_CUR_MAX;
1916 wchar_t wc;
1917 char mbuf[MB_LEN_MAX + 1];
1918 char c;
1920 if (status < 0)
1921 return (status);
1923 rstat = wstat = 0;
1925 if (mbmax == 1) {
1926 while (wstat == 0) {
1927 if ((rstat = pr_adr_char(context, &c, 1)) < 0)
1928 break;
1929 if (c == '\0')
1930 break;
1931 printable = isprint((unsigned char)c);
1932 wstat = pa_putstr(context, printable, &c, 1);
1934 goto done;
1937 mlen = eos = 0;
1938 while (wstat == 0) {
1939 rlen = 0;
1940 do {
1941 if (!eos) {
1942 rstat = pr_adr_char(context, &c, 1);
1943 if (rstat != 0 || c == '\0')
1944 eos = 1;
1945 else
1946 mbuf[mlen++] = c;
1948 rlen = mbtowc(&wc, mbuf, mlen);
1949 } while (!eos && mlen < mbmax && rlen <= 0);
1951 if (mlen == 0)
1952 break; /* end of string */
1954 if (rlen <= 0) { /* no good sequence */
1955 rlen = 1;
1956 printable = 0;
1957 } else {
1958 printable = iswprint(wc);
1960 wstat = pa_putstr(context, printable, mbuf, rlen);
1961 mlen -= rlen;
1962 if (mlen > 0) {
1963 for (i = 0; i < mlen; i++)
1964 mbuf[i] = mbuf[rlen + i];
1968 done:
1969 if (wstat == 0)
1970 wstat = do_newline(context, flag);
1972 return ((rstat != 0 || wstat != 0) ? -1 : 0);
1976 * -----------------------------------------------------------------------
1977 * pa_adr_u_int32: Issues pr_adr_u_int32 to retrieve the next ADR item from
1978 * the input stream pointed to by audit_adr, and prints it
1979 * if status = 0
1980 * return codes : -1 - error
1981 * : 0 - successful
1982 * -----------------------------------------------------------------------
1987 pa_adr_u_int32(pr_context_t *context, int status, int flag)
1989 uint32_t c;
1990 uval_t uval;
1992 if (status >= 0) {
1993 if (pr_adr_u_int32(context, &c, 1) == 0) {
1994 uval.uvaltype = PRA_UINT32;
1995 uval.uint32_val = c;
1996 return (pa_print(context, &uval, flag));
1997 } else
1998 return (-1);
1999 } else
2000 return (status);
2006 * -----------------------------------------------------------------------
2007 * pa_adr_u_int64: Issues pr_adr_u_int64 to retrieve the next ADR item from the
2008 * input stream pointed to by audit_adr, and prints it
2009 * if status = 0
2010 * return codes : -1 - error
2011 * : 0 - successful
2012 * -----------------------------------------------------------------------
2015 pa_adr_u_int64(pr_context_t *context, int status, int flag)
2017 uint64_t c;
2018 uval_t uval;
2020 if (status >= 0) {
2021 if (pr_adr_u_int64(context, &c, 1) == 0) {
2022 uval.uvaltype = PRA_UINT64;
2023 uval.uint64_val = c;
2024 return (pa_print(context, &uval, flag));
2025 } else
2026 return (-1);
2027 } else
2028 return (status);
2033 * -----------------------------------------------------------------------
2034 * pa_adr_u_short: Issues pr_adr_u_short to retrieve the next ADR item from
2035 * the input stream pointed to by audit_adr, and prints it
2036 * if status = 0
2037 * return codes : -1 - error
2038 * : 0 - successful
2039 * -----------------------------------------------------------------------
2042 pa_adr_u_short(pr_context_t *context, int status, int flag)
2044 ushort_t c;
2045 uval_t uval;
2047 if (status >= 0) {
2048 if (pr_adr_u_short(context, &c, 1) == 0) {
2049 uval.uvaltype = PRA_USHORT;
2050 uval.ushort_val = c;
2051 return (pa_print(context, &uval, flag));
2052 } else
2053 return (-1);
2054 } else
2055 return (status);
2059 * -----------------------------------------------------------------------
2060 * pa_reclen: Issues pr_adr_u_long to retrieve the length of the record
2061 * from the input stream pointed to by audit_adr,
2062 * and prints it (unless format is XML) if status = 0
2063 * return codes : -1 - error
2064 * : 0 - successful
2065 * -----------------------------------------------------------------------
2068 pa_reclen(pr_context_t *context, int status)
2070 uint32_t c;
2071 uval_t uval;
2073 if (status >= 0) {
2074 if ((int)pr_adr_u_int32(context, &c, 1) == 0) {
2075 context->audit_rec_len = c;
2077 /* Don't print this for XML format */
2078 if (context->format & PRF_XMLM) {
2079 return (0);
2080 } else {
2081 uval.uvaltype = PRA_UINT32;
2082 uval.uint32_val = c;
2083 return (pa_print(context, &uval, 0));
2085 } else
2086 return (-1);
2087 } else
2088 return (status);
2092 * -----------------------------------------------------------------------
2093 * pa_mode : Issues pr_adr_u_short to retrieve the next ADR item from
2094 * the input stream pointed to by audit_adr, and prints it
2095 * in octal if status = 0
2096 * return codes : -1 - error
2097 * : 0 - successful
2098 * -----------------------------------------------------------------------
2101 pa_mode(pr_context_t *context, int status, int flag)
2103 uint32_t c;
2104 uval_t uval;
2106 if (status >= 0) {
2107 if (pr_adr_u_int32(context, &c, 1) == 0) {
2108 uval.uvaltype = PRA_LOCT;
2109 uval.uint32_val = c;
2110 return (pa_print(context, &uval, flag));
2111 } else
2112 return (-1);
2113 } else
2114 return (status);
2117 static int
2118 pa_print_uid(pr_context_t *context, uid_t uid, int status, int flag)
2120 int returnstat;
2121 uval_t uval;
2123 if (status < 0)
2124 return (status);
2126 if (context->format & PRF_RAWM) {
2127 /* print in integer form */
2128 uval.uvaltype = PRA_INT32;
2129 uval.int32_val = uid;
2130 returnstat = pa_print(context, &uval, flag);
2131 } else {
2132 /* print in ASCII form */
2133 uval.uvaltype = PRA_STRING;
2134 uval.string_val = getname(uid);
2135 returnstat = pa_print(context, &uval, flag);
2137 return (returnstat);
2142 * -----------------------------------------------------------------------
2143 * pa_pw_uid() : Issues pr_adr_u_int32 to reads uid from input stream
2144 * pointed to by audit_adr, and displays it in either
2145 * raw form or its ASCII representation, if status >= 0.
2146 * return codes : -1 - error
2147 * : 1 - warning, passwd entry not found
2148 * : 0 - successful
2149 * -----------------------------------------------------------------------
2152 pa_pw_uid(pr_context_t *context, int status, int flag)
2154 uint32_t uid;
2156 if (status < 0)
2157 return (status);
2159 if (pr_adr_u_int32(context, &uid, 1) != 0)
2160 /* cannot retrieve uid */
2161 return (-1);
2163 return (pa_print_uid(context, uid, status, flag));
2166 static int
2167 pa_print_gid(pr_context_t *context, gid_t gid, int status, int flag)
2169 int returnstat;
2170 uval_t uval;
2172 if (status < 0)
2173 return (status);
2175 if (context->format & PRF_RAWM) {
2176 /* print in integer form */
2177 uval.uvaltype = PRA_INT32;
2178 uval.int32_val = gid;
2179 returnstat = pa_print(context, &uval, flag);
2180 } else {
2181 /* print in ASCII form */
2182 uval.uvaltype = PRA_STRING;
2183 uval.string_val = getgroup(gid);
2184 returnstat = pa_print(context, &uval, flag);
2186 return (returnstat);
2191 * -----------------------------------------------------------------------
2192 * pa_gr_uid() : Issues pr_adr_u_int32 to reads group uid from input stream
2193 * pointed to by audit_adr, and displays it in either
2194 * raw form or its ASCII representation, if status >= 0.
2195 * return codes : -1 - error
2196 * : 1 - warning, passwd entry not found
2197 * : 0 - successful
2198 * -----------------------------------------------------------------------
2201 pa_gr_uid(pr_context_t *context, int status, int flag)
2203 uint32_t gid;
2205 if (status < 0)
2206 return (status);
2208 if (pr_adr_u_int32(context, &gid, 1) != 0)
2209 /* cannot retrieve gid */
2210 return (-1);
2212 return (pa_print_gid(context, gid, status, flag));
2217 * -----------------------------------------------------------------------
2218 * pa_pw_uid_gr_gid() : Issues pr_adr_u_int32 to reads uid or group uid
2219 * from input stream
2220 * pointed to by audit_adr, and displays it in either
2221 * raw form or its ASCII representation, if status >= 0.
2222 * return codes : -1 - error
2223 * : 1 - warning, passwd entry not found
2224 * : 0 - successful
2225 * -----------------------------------------------------------------------
2228 pa_pw_uid_gr_gid(pr_context_t *context, int status, int flag)
2230 int returnstat;
2231 uint32_t value;
2232 uval_t uval;
2234 if (status < 0)
2235 return (status);
2237 /* get value of a_type */
2238 if ((returnstat = pr_adr_u_int32(context, &value, 1)) != 0)
2239 return (returnstat);
2241 if ((returnstat = open_tag(context, TAG_ACLTYPE)) != 0)
2242 return (returnstat);
2244 uval.uvaltype = PRA_UINT32;
2245 uval.uint32_val = value;
2246 if ((returnstat = pa_print(context, &uval, flag)) != 0)
2247 return (returnstat);
2249 if ((returnstat = close_tag(context, TAG_ACLTYPE)) != 0)
2250 return (returnstat);
2252 if ((returnstat = open_tag(context, TAG_ACLVAL)) != 0)
2253 return (returnstat);
2255 * TRANSLATION_NOTE
2256 * The "mask" and "other" strings refer to the class mask
2257 * and other (or world) entries in an ACL.
2258 * The "unrecognized" string refers to an unrecognized ACL
2259 * entry.
2261 switch (value) {
2262 case USER_OBJ:
2263 case USER:
2264 returnstat = pa_pw_uid(context, returnstat, flag);
2265 break;
2266 case GROUP_OBJ:
2267 case GROUP:
2268 returnstat = pa_gr_uid(context, returnstat, flag);
2269 break;
2270 case CLASS_OBJ:
2271 returnstat = pr_adr_u_int32(context, &value, 1);
2272 if (returnstat != 0)
2273 return (returnstat);
2275 if (!(context->format & PRF_RAWM)) {
2276 uval.uvaltype = PRA_STRING;
2277 uval.string_val = gettext("mask");
2278 returnstat = pa_print(context, &uval, flag);
2279 } else {
2280 uval.uvaltype = PRA_UINT32;
2281 uval.uint32_val = value;
2282 if ((returnstat =
2283 pa_print(context, &uval, flag)) != 0) {
2284 return (returnstat);
2287 break;
2288 case OTHER_OBJ:
2289 returnstat = pr_adr_u_int32(context, &value, 1);
2290 if (returnstat != 0)
2291 return (returnstat);
2293 if (!(context->format & PRF_RAWM)) {
2294 uval.uvaltype = PRA_STRING;
2295 uval.string_val = gettext("other");
2296 returnstat = pa_print(context, &uval, flag);
2297 } else {
2298 uval.uvaltype = PRA_UINT32;
2299 uval.uint32_val = value;
2300 if ((returnstat =
2301 pa_print(context, &uval, flag)) != 0) {
2302 return (returnstat);
2305 break;
2306 default:
2307 returnstat = pr_adr_u_int32(context, &value, 1);
2308 if (returnstat != 0)
2309 return (returnstat);
2311 if (!(context->format & PRF_RAWM)) {
2312 uval.uvaltype = PRA_STRING;
2313 uval.string_val = gettext("unrecognized");
2314 returnstat = pa_print(context, &uval, flag);
2315 } else {
2316 uval.uvaltype = PRA_UINT32;
2317 uval.uint32_val = value;
2318 if ((returnstat =
2319 pa_print(context, &uval, flag)) != 0) {
2320 return (returnstat);
2325 if ((returnstat = close_tag(context, TAG_ACLVAL)) != 0)
2326 return (returnstat);
2328 return (returnstat);
2333 * -----------------------------------------------------------------------
2334 * pa_event_modifier(): Issues pr_adr_u_short to retrieve the next ADR item from
2335 * the input stream pointed to by audit_adr. This is the
2336 * event type, and is displayed in hex;
2337 * return codes : -1 - error
2338 * : 0 - successful
2339 * -----------------------------------------------------------------------
2342 pa_event_modifier(pr_context_t *context, int status, int flag)
2344 int returnstat;
2345 au_emod_t emodifier;
2346 uval_t uval;
2347 char modstring[64];
2349 if (status < 0)
2350 return (status);
2352 if ((returnstat = pr_adr_u_short(context, &emodifier, 1)) != 0)
2353 return (returnstat);
2355 /* For XML, only print when modifier is non-zero */
2356 if (!(context->format & PRF_XMLM) || (emodifier != 0)) {
2357 uval.uvaltype = PRA_STRING;
2359 returnstat = open_tag(context, TAG_EVMOD);
2361 if (returnstat >= 0) {
2362 if (!(context->format & PRF_RAWM)) {
2363 eventmodifier2string(emodifier, modstring,
2364 sizeof (modstring));
2365 uval.string_val = modstring;
2366 returnstat = pa_print(context, &uval, flag);
2367 } else {
2368 uval.string_val = hexconvert((char *)&emodifier,
2369 sizeof (emodifier), sizeof (emodifier));
2370 if (uval.string_val) {
2371 returnstat = pa_print(context, &uval,
2372 flag);
2373 free(uval.string_val);
2377 if (returnstat >= 0)
2378 returnstat = close_tag(context, TAG_EVMOD);
2381 return (returnstat);
2386 * -----------------------------------------------------------------------
2387 * pa_event_type(): Issues pr_adr_u_short to retrieve the next ADR item from
2388 * the input stream pointed to by audit_adr. This is the
2389 * event type, and is displayed in either raw or
2390 * ASCII form as appropriate
2391 * return codes : -1 - error
2392 * : 0 - successful
2393 * -----------------------------------------------------------------------
2396 pa_event_type(pr_context_t *context, int status, int flag)
2398 au_event_t etype;
2399 int returnstat;
2400 au_event_ent_t *p_event = NULL;
2401 uval_t uval;
2403 if (status >= 0) {
2404 if ((returnstat = pr_adr_u_short(context, &etype, 1)) == 0) {
2405 if (!(context->format & PRF_RAWM)) {
2406 uval.uvaltype = PRA_STRING;
2407 if (context->format & PRF_NOCACHE) {
2408 p_event = getauevnum(etype);
2409 } else {
2410 (void) cacheauevent(&p_event, etype);
2412 if (p_event != NULL) {
2413 if (context->format & PRF_SHORTM)
2414 uval.string_val =
2415 p_event->ae_name;
2416 else
2417 uval.string_val =
2418 p_event->ae_desc;
2419 } else {
2420 uval.string_val =
2421 gettext("invalid event number");
2423 returnstat = pa_print(context, &uval, flag);
2424 } else {
2425 uval.uvaltype = PRA_USHORT;
2426 uval.ushort_val = etype;
2427 returnstat = pa_print(context, &uval, flag);
2430 return (returnstat);
2431 } else
2432 return (status);
2438 * Print time from struct timeval to millisecond resolution.
2440 * typedef long time_t; time of day in seconds
2441 * typedef long useconds_t; signed # of microseconds
2443 * struct timeval {
2444 * time_t tv_sec; seconds
2445 * suseconds_t tv_usec; and microseconds
2446 * };
2450 pa_utime32(pr_context_t *context, int status, int flag)
2452 uint32_t scale = 1000; /* usec to msec */
2454 return (do_mtime32(context, status, flag, scale));
2458 * Print time from timestruc_t to millisecond resolution.
2460 * typedef struct timespec timestruct_t;
2461 * struct timespec{
2462 * time_t tv_sec; seconds
2463 * long tv_nsec; and nanoseconds
2464 * };
2467 pa_ntime32(pr_context_t *context, int status, int flag)
2469 uint32_t scale = 1000000; /* nsec to msec */
2471 return (do_mtime32(context, status, flag, scale));
2475 * Format the timezone +/- HH:MM and terminate the string
2476 * Note tm and tv_sec are the same time.
2477 * Too bad strftime won't produce an ISO 8601 time zone numeric
2480 #define MINS (24L * 60)
2481 static void
2482 tzone(struct tm *tm, time_t *tv_sec, char *p)
2484 struct tm *gmt;
2485 int min_off;
2487 gmt = gmtime(tv_sec);
2489 min_off = ((tm->tm_hour - gmt->tm_hour) * 60) +
2490 (tm->tm_min - gmt->tm_min);
2492 if (tm->tm_year < gmt->tm_year) /* cross new year */
2493 min_off -= MINS;
2494 else if (tm->tm_year > gmt->tm_year)
2495 min_off += MINS;
2496 else if (tm->tm_yday < gmt->tm_yday) /* cross dateline */
2497 min_off -= MINS;
2498 else if (tm->tm_yday > gmt->tm_yday)
2499 min_off += MINS;
2501 if (min_off < 0) {
2502 min_off = -min_off;
2503 *p++ = '-';
2504 } else {
2505 *p++ = '+';
2508 *p++ = min_off / 600 + '0'; /* 10s of hours */
2509 min_off = min_off - min_off / 600 * 600;
2510 *p++ = min_off / 60 % 10 + '0'; /* hours */
2511 min_off = min_off - min_off / 60 * 60;
2512 *p++ = ':';
2513 *p++ = min_off / 10 + '0'; /* 10s of minutes */
2514 *p++ = min_off % 10 + '0'; /* minutes */
2515 *p = '\0';
2519 * Format the milliseconds in place in the string.
2520 * Borrowed from strftime.c:itoa()
2522 static void
2523 msec32(uint32_t msec, char *p)
2525 *p++ = msec / 100 + '0';
2526 msec = msec - msec / 100 * 100;
2527 *p++ = msec / 10 + '0';
2528 *p++ = msec % 10 +'0';
2532 * Format time and print relative to scale factor from micro/nano seconds.
2534 static int
2535 do_mtime32(pr_context_t *context, int status, int flag, uint32_t scale)
2537 uint32_t t32;
2538 time_t tv_sec;
2539 struct tm tm;
2540 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2541 int returnstat;
2542 uval_t uval;
2544 if (status < 0)
2545 return (status);
2547 if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2548 return (returnstat);
2550 if ((returnstat = pr_adr_u_int32(context,
2551 (uint32_t *)&tv_sec, 1)) != 0)
2552 return (returnstat);
2553 if ((returnstat = pr_adr_u_int32(context, &t32, 1)) == 0) {
2554 if (!(context->format & PRF_RAWM)) {
2555 (void) localtime_r(&tv_sec, &tm);
2556 (void) strftime(time_created,
2557 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2558 "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2559 msec32(t32/scale,
2560 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2561 tzone(&tm, &tv_sec,
2562 &time_created[
2563 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2564 uval.uvaltype = PRA_STRING;
2565 uval.string_val = time_created;
2566 } else {
2567 uval.uvaltype = PRA_UINT32;
2568 uval.uint32_val = (uint32_t)tv_sec;
2569 (void) pa_print(context, &uval, 0);
2570 if (context->format & PRF_XMLM) {
2571 uval.uvaltype = PRA_CHAR;
2572 uval.char_val = '.';
2573 (void) pa_print(context, &uval, 0);
2575 uval.uvaltype = PRA_UINT32;
2576 uval.uint32_val = t32;
2578 returnstat = pa_print(context, &uval, flag);
2581 if (returnstat == 0)
2582 return (close_tag(context, TAG_ISO));
2583 else
2584 return (returnstat);
2588 * Print time from struct timeval to millisecond resolution.
2590 * typedef long time_t; time of day in seconds
2591 * typedef long useconds_t; signed # of microseconds
2593 * struct timeval {
2594 * time_t tv_sec; seconds
2595 * suseconds_t tv_usec; and microseconds
2596 * };
2600 pa_utime64(pr_context_t *context, int status, int flag)
2602 uint64_t scale = 1000; /* usec to msec */
2604 return (do_mtime64(context, status, flag, scale));
2608 * Print time from timestruc_t to millisecond resolution.
2610 * typedef struct timespec timestruct_t;
2611 * struct timespec{
2612 * time_t tv_sec; seconds
2613 * long tv_nsec; and nanoseconds
2614 * };
2617 pa_ntime64(pr_context_t *context, int status, int flag)
2619 uint64_t scale = 1000000; /* nsec to msec */
2621 return (do_mtime64(context, status, flag, scale));
2625 * Format the milliseconds in place in the string.
2626 * Borrowed from strftime.c:itoa()
2628 static void
2629 msec64(uint64_t msec, char *p)
2631 *p++ = msec / 100 + '0';
2632 msec = msec - msec / 100 * 100;
2633 *p++ = msec / 10 + '0';
2634 *p++ = msec % 10 +'0';
2638 * Format time and print relative to scale factor from micro/nano seconds.
2640 static int
2641 do_mtime64(pr_context_t *context, int status, int flag, uint64_t scale)
2643 uint64_t t64_sec;
2644 uint64_t t64_msec;
2645 time_t tv_sec;
2646 struct tm tm;
2647 char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2648 int returnstat;
2649 uval_t uval;
2651 if (status < 0)
2652 return (status);
2654 if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2655 return (returnstat);
2657 if ((returnstat = pr_adr_u_int64(context, &t64_sec, 1)) != 0)
2658 return (returnstat);
2659 if ((returnstat = pr_adr_u_int64(context, &t64_msec, 1)) == 0) {
2660 if (!(context->format & PRF_RAWM)) {
2661 #ifndef _LP64
2663 * N.B.
2664 * This fails for years from 2038
2665 * The Y2K+38 problem
2667 #endif /* !_LP64 */
2668 tv_sec = (time_t)t64_sec;
2669 (void) localtime_r(&tv_sec, &tm);
2670 (void) strftime(time_created,
2671 sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2672 "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2673 msec64(t64_msec/scale,
2674 &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2675 tzone(&tm, &tv_sec,
2676 &time_created[
2677 sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2678 uval.uvaltype = PRA_STRING;
2679 uval.string_val = time_created;
2680 } else {
2681 uval.uvaltype = PRA_UINT64;
2682 uval.uint64_val = t64_sec;
2683 (void) pa_print(context, &uval, 0);
2684 if (context->format & PRF_XMLM) {
2685 uval.uvaltype = PRA_CHAR;
2686 uval.char_val = '.';
2687 (void) pa_print(context, &uval, 0);
2689 uval.uvaltype = PRA_UINT64;
2690 uval.uint64_val = t64_msec;
2692 returnstat = pa_print(context, &uval, flag);
2695 if (returnstat < 0)
2696 return (returnstat);
2698 return (close_tag(context, TAG_ISO));
2702 * -----------------------------------------------------------------------
2703 * pa_error() : convert the return token error code.
2705 * output : buf string representing return token error code.
2707 * -----------------------------------------------------------------------
2709 void
2710 pa_error(const uchar_t err, char *buf, size_t buflen)
2712 if (err == ADT_SUCCESS) {
2713 (void) strlcpy(buf, gettext("success"), buflen);
2714 } else if ((char)err == ADT_FAILURE) {
2715 (void) strlcpy(buf, gettext("failure"), buflen);
2716 } else {
2717 char *emsg = strerror(err);
2719 if (emsg != NULL) {
2720 (void) strlcpy(buf, gettext("failure: "), buflen);
2721 (void) strlcat(buf, emsg, buflen);
2722 } else {
2723 (void) snprintf(buf, buflen, "%s%d",
2724 gettext("failure: "), err);
2730 * -----------------------------------------------------------------------
2731 * pa_retval() : convert the return token return value code.
2733 * input : err, for kernel success 0, or
2734 * failure errno: 0 > & < sys_nerr.
2735 * for userland success ADT_SUCCESS (0) or
2736 * failure ADT_FAILURE (-1).
2737 * pa_error() above has already converted err.
2739 * : retval, for kernel arbitrary return value for success, or
2740 * failure: -1.
2741 * for userland,
2742 * >= ADT_FAIL_VALUE < ADT_FAIL_PAM, an adt message code;
2743 * >= ADT_FAIL_PAM, a pam_strerror value;
2744 * < ADT_FAIL_VALUE, supposed to be an errno.
2746 * output : buf string representing return token error code.
2748 * -----------------------------------------------------------------------
2750 void
2751 pa_retval(const uchar_t err, const int32_t retval, char *buf, size_t buflen)
2753 struct msg_text *msglist;
2754 char *emsg;
2756 /* success or kernel failure */
2757 if (((char)err == ADT_SUCCESS) ||
2758 (retval < 0)) {
2760 (void) snprintf(buf, buflen, "%d", retval);
2761 return;
2764 /* userland failure */
2765 msglist = &adt_msg_text[ADT_LIST_FAIL_VALUE];
2767 if ((retval + msglist->ml_offset >= msglist->ml_min_index) &&
2768 (retval + msglist->ml_offset <= msglist->ml_max_index)) {
2770 (void) strlcpy(buf,
2771 gettext(msglist->ml_msg_list[retval + msglist->ml_offset]),
2772 buflen);
2773 } else if ((retval >= ADT_FAIL_PAM) &&
2774 (retval < ADT_FAIL_PAM + PAM_TOTAL_ERRNUM)) {
2776 (void) strlcpy(buf, pam_strerror(NULL, retval - ADT_FAIL_PAM),
2777 buflen);
2778 } else if ((emsg = strerror(retval)) != NULL) {
2780 (void) strlcpy(buf, emsg, buflen);
2781 } else {
2783 (void) snprintf(buf, buflen, "%d", retval);
2788 * -----------------------------------------------------------------------
2789 * pa_printstr() : print a given string, translating unprintables
2790 * : as needed.
2792 static int
2793 pa_printstr(pr_context_t *context, char *str)
2795 int err = 0;
2796 int len, printable;
2797 int mbmax = MB_CUR_MAX;
2798 wchar_t wc;
2799 char c;
2801 if (mbmax == 1) {
2802 /* fast path */
2803 while (err == 0 && *str != '\0') {
2804 c = *str++;
2805 printable = isprint((unsigned char)c);
2806 err = pa_putstr(context, printable, &c, 1);
2808 return (err);
2810 while (err == 0 && *str != '\0') {
2811 len = mbtowc(&wc, str, mbmax);
2812 if (len <= 0) {
2813 len = 1;
2814 printable = 0;
2815 } else {
2816 printable = iswprint(wc);
2818 err = pa_putstr(context, printable, str, len);
2819 str += len;
2821 return (err);
2825 * -----------------------------------------------------------------------
2826 * pa_print() : print as one str or formatted for easy reading.
2827 * : flag - indicates whether to output a new line for
2828 * : multi-line output.
2829 * : = 0; no new line
2830 * : = 1; new line if regular output
2831 * output : The audit record information is displayed in the
2832 * type specified by uvaltype and value specified in
2833 * uval. The printing of the delimiter or newline is
2834 * determined by PRF_ONELINE, and the flag value,
2835 * as follows:
2836 * +--------+------+------+-----------------+
2837 * |ONELINE | flag | last | Action |
2838 * +--------+------+------+-----------------+
2839 * | Y | Y | T | print new line |
2840 * | Y | Y | F | print delimiter |
2841 * | Y | N | T | print new line |
2842 * | Y | N | F | print delimiter |
2843 * | N | Y | T | print new line |
2844 * | N | Y | F | print new line |
2845 * | N | N | T | print new line |
2846 * | N | N | F | print delimiter |
2847 * +--------+------+------+-----------------+
2849 * return codes : -1 - error
2850 * 0 - successful
2851 * -----------------------------------------------------------------------
2854 pa_print(pr_context_t *context, uval_t *uval, int flag)
2856 int returnstat = 0;
2857 int last;
2859 switch (uval->uvaltype) {
2860 case PRA_INT32:
2861 returnstat = pr_printf(context, "%d", uval->int32_val);
2862 break;
2863 case PRA_UINT32:
2864 returnstat = pr_printf(context, "%u", uval->uint32_val);
2865 break;
2866 case PRA_INT64:
2867 returnstat = pr_printf(context, "%"PRId64, uval->int64_val);
2868 break;
2869 case PRA_UINT64:
2870 returnstat = pr_printf(context, "%"PRIu64, uval->uint64_val);
2871 break;
2872 case PRA_SHORT:
2873 returnstat = pr_printf(context, "%hd", uval->short_val);
2874 break;
2875 case PRA_USHORT:
2876 returnstat = pr_printf(context, "%hu", uval->ushort_val);
2877 break;
2878 case PRA_CHAR:
2879 returnstat = pr_printf(context, "%c", uval->char_val);
2880 break;
2881 case PRA_BYTE:
2882 returnstat = pr_printf(context, "%d", uval->char_val);
2883 break;
2884 case PRA_STRING:
2885 returnstat = pa_printstr(context, uval->string_val);
2886 break;
2887 case PRA_HEX32:
2888 returnstat = pr_printf(context, "0x%x", uval->int32_val);
2889 break;
2890 case PRA_HEX64:
2891 returnstat = pr_printf(context, "0x%"PRIx64, uval->int64_val);
2892 break;
2893 case PRA_SHEX:
2894 returnstat = pr_printf(context, "0x%hx", uval->short_val);
2895 break;
2896 case PRA_OCT:
2897 returnstat = pr_printf(context, "%ho", uval->ushort_val);
2898 break;
2899 case PRA_LOCT:
2900 returnstat = pr_printf(context, "%o", (int)uval->uint32_val);
2901 break;
2902 default:
2903 (void) fprintf(stderr, gettext("praudit: Unknown type.\n"));
2904 returnstat = -1;
2905 break;
2907 if (returnstat < 0)
2908 return (returnstat);
2910 last = (context->audit_adr->adr_now ==
2911 (context->audit_rec_start + context->audit_rec_len));
2913 if (!(context->format & PRF_XMLM)) {
2914 if (!(context->format & PRF_ONELINE)) {
2915 if ((flag == 1) || last)
2916 returnstat = pr_putchar(context, '\n');
2917 else
2918 returnstat = pr_printf(context, "%s",
2919 context->SEPARATOR);
2920 } else {
2921 if (!last)
2922 returnstat = pr_printf(context, "%s",
2923 context->SEPARATOR);
2924 else
2925 returnstat = pr_putchar(context, '\n');
2928 return (returnstat);
2931 static struct cntrl_mapping {
2932 char from;
2933 char to;
2934 } cntrl_map[] = {
2935 '\0', '0',
2936 '\a', 'a',
2937 '\b', 'b',
2938 '\t', 't',
2939 '\f', 'f',
2940 '\n', 'n',
2941 '\r', 'r',
2942 '\v', 'v'
2945 static int cntrl_map_entries = sizeof (cntrl_map)
2946 / sizeof (struct cntrl_mapping);
2949 * Convert binary data to ASCII for printing.
2951 void
2952 convertascii(char *p, char *c, int size)
2954 int i, j, uc;
2956 for (i = 0; i < size; i++) {
2957 uc = (unsigned char)*(c + i);
2958 if (isascii(uc)) {
2959 if (iscntrl(uc)) {
2960 for (j = 0; j < cntrl_map_entries; j++) {
2961 if (cntrl_map[j].from == uc) {
2962 *p++ = '\\';
2963 *p++ = cntrl_map[j].to;
2964 break;
2967 if (j == cntrl_map_entries) {
2968 *p++ = '^';
2969 *p++ = (char)(uc ^ 0100);
2971 } else {
2972 *p++ = (char)uc;
2974 } else {
2975 p += sprintf(p, "\\%03o", uc);
2978 *p = '\0';
2982 * -----------------------------------------------------------------------
2983 * pa_xgeneric: Process Xobject token and display contents
2984 * This routine will handle many of the attribute
2985 * types introduced in TS 2.x, such as:
2987 * AUT_XCOLORMAP, AUT_XCURSOR, AUT_XFONT,
2988 * AUT_XGC, AUT_XPIXMAP, AUT_XWINDOW
2990 * NOTE: At the time of call, the token id has been retrieved
2992 * return codes : -1 - error
2993 * : 0 - successful
2994 * NOTE: At the time of call, the xatom token id has been retrieved
2996 * Format of xobj
2997 * text token id adr_char
2998 * XID adr_u_int32
2999 * creator uid adr_pw_uid
3000 * -----------------------------------------------------------------------
3003 pa_xgeneric(pr_context_t *context)
3005 int returnstat;
3007 returnstat = process_tag(context, TAG_XID, 0, 0);
3008 return (process_tag(context, TAG_XCUID, returnstat, 1));
3013 * ------------------------------------------------------------------------
3014 * pa_liaison : Issues pr_adr_char to retrieve the next ADR item from the
3015 * input stream pointed to by audit_adr, and prints it
3016 * if status >= 0 either in ASCII or raw form
3017 * return codes : -1 - error
3018 * : 0 - successful
3019 * : 1 - warning, unknown label type
3020 * -----------------------------------------------------------------------
3023 pa_liaison(pr_context_t *context, int status, int flag)
3025 int returnstat;
3026 int32_t li;
3027 uval_t uval;
3029 if (status >= 0) {
3030 if ((returnstat = pr_adr_int32(context, &li, 1)) != 0) {
3031 return (returnstat);
3033 if (!(context->format & PRF_RAWM)) {
3034 uval.uvaltype = PRA_UINT32;
3035 uval.uint32_val = li;
3036 returnstat = pa_print(context, &uval, flag);
3038 /* print in hexadecimal form */
3039 if ((context->format & PRF_RAWM) || (returnstat == 1)) {
3040 uval.uvaltype = PRA_HEX32;
3041 uval.uint32_val = li;
3042 returnstat = pa_print(context, &uval, flag);
3044 return (returnstat);
3045 } else
3046 return (status);
3050 * ------------------------------------------------------------------------
3051 * pa_xid : Issues pr_adr_int32 to retrieve the XID from the input
3052 * stream pointed to by audit_adr, and prints it if
3053 * status >= 0 either in ASCII or raw form
3054 * return codes : -1 - error
3055 * : 0 - successful
3056 * : 1 - warning, unknown label type
3057 * ------------------------------------------------------------------------
3061 pa_xid(pr_context_t *context, int status, int flag)
3063 int returnstat;
3064 int32_t xid;
3065 uval_t uval;
3067 if (status < 0)
3068 return (status);
3070 /* get XID from stream */
3071 if ((returnstat = pr_adr_int32(context, (int32_t *)&xid, 1)) != 0)
3072 return (returnstat);
3074 if (!(context->format & PRF_RAWM)) {
3075 uval.uvaltype = PRA_STRING;
3076 uval.string_val = hexconvert((char *)&xid, sizeof (xid),
3077 sizeof (xid));
3078 if (uval.string_val) {
3079 returnstat = pa_print(context, &uval, flag);
3080 free(uval.string_val);
3082 } else {
3083 uval.uvaltype = PRA_INT32;
3084 uval.int32_val = xid;
3085 returnstat = pa_print(context, &uval, flag);
3088 return (returnstat);
3091 static int
3092 pa_ace_flags(pr_context_t *context, ace_t *ace, int status, int flag)
3094 int returnstat;
3095 uval_t uval;
3097 if (status < 0)
3098 return (status);
3101 * TRANSLATION_NOTE
3102 * ace->a_flags refers to access flags of ZFS/NFSv4 ACL entry.
3104 if ((returnstat = open_tag(context, TAG_ACEFLAGS)) != 0)
3105 return (returnstat);
3106 if (!(context->format & PRF_RAWM)) {
3107 uval.uvaltype = PRA_STRING;
3108 switch (ace->a_flags & ACE_TYPE_FLAGS) {
3109 case ACE_OWNER:
3110 uval.string_val = gettext(OWNERAT_TXT);
3111 break;
3112 case ACE_GROUP | ACE_IDENTIFIER_GROUP:
3113 uval.string_val = gettext(GROUPAT_TXT);
3114 break;
3115 case ACE_IDENTIFIER_GROUP:
3116 uval.string_val = gettext(GROUP_TXT);
3117 break;
3118 case ACE_EVERYONE:
3119 uval.string_val = gettext(EVERYONEAT_TXT);
3120 break;
3121 case 0:
3122 uval.string_val = gettext(USER_TXT);
3123 break;
3124 default:
3125 uval.uvaltype = PRA_USHORT;
3126 uval.uint32_val = ace->a_flags;
3128 } else {
3129 uval.uvaltype = PRA_USHORT;
3130 uval.uint32_val = ace->a_flags;
3132 if ((returnstat = pa_print(context, &uval, flag)) != 0)
3133 return (returnstat);
3134 return (close_tag(context, TAG_ACEFLAGS));
3137 static int
3138 pa_ace_who(pr_context_t *context, ace_t *ace, int status, int flag)
3140 int returnstat;
3142 if (status < 0)
3143 return (status);
3146 * TRANSLATION_NOTE
3147 * ace->a_who refers to user id or group id of ZFS/NFSv4 ACL entry.
3149 if ((returnstat = open_tag(context, TAG_ACEID)) != 0)
3150 return (returnstat);
3151 switch (ace->a_flags & ACE_TYPE_FLAGS) {
3152 case ACE_IDENTIFIER_GROUP: /* group id */
3153 returnstat = pa_print_gid(context, ace->a_who, returnstat,
3154 flag);
3155 break;
3156 default: /* user id */
3157 returnstat = pa_print_uid(context, ace->a_who, returnstat,
3158 flag);
3159 break;
3161 if (returnstat < 0)
3162 return (returnstat);
3163 return (close_tag(context, TAG_ACEID));
3167 * Appends what to str, (re)allocating str if necessary.
3169 #define INITIAL_ALLOC 256
3170 static int
3171 strappend(char **str, char *what, size_t *alloc)
3173 char *s, *newstr;
3174 size_t needed;
3176 s = *str;
3178 if (s == NULL) {
3179 s = malloc(INITIAL_ALLOC);
3180 if (s == NULL) {
3181 *alloc = 0;
3182 return (-1);
3184 *alloc = INITIAL_ALLOC;
3185 s[0] = '\0';
3186 *str = s;
3189 needed = strlen(s) + strlen(what) + 1;
3190 if (*alloc < needed) {
3191 newstr = realloc(s, needed);
3192 if (newstr == NULL)
3193 return (-1);
3194 s = newstr;
3195 *alloc = needed;
3196 *str = s;
3198 (void) strlcat(s, what, *alloc);
3200 return (0);
3203 static int
3204 pa_ace_access_mask(pr_context_t *context, ace_t *ace, int status, int flag)
3206 int returnstat, i;
3207 uval_t uval;
3208 char *permstr = NULL;
3209 size_t permstr_alloc = 0;
3211 if (status < 0)
3212 return (status);
3215 * TRANSLATION_NOTE
3216 * ace->a_access_mask refers to access mask of ZFS/NFSv4 ACL entry.
3218 if ((returnstat = open_tag(context, TAG_ACEMASK)) != 0)
3219 return (returnstat);
3220 if (context->format & PRF_SHORTM &&
3221 ((permstr = malloc(15)) != NULL)) {
3222 for (i = 0; i < 14; i++)
3223 permstr[i] = '-';
3225 if (ace->a_access_mask & ACE_READ_DATA)
3226 permstr[0] = 'r';
3227 if (ace->a_access_mask & ACE_WRITE_DATA)
3228 permstr[1] = 'w';
3229 if (ace->a_access_mask & ACE_EXECUTE)
3230 permstr[2] = 'x';
3231 if (ace->a_access_mask & ACE_APPEND_DATA)
3232 permstr[3] = 'p';
3233 if (ace->a_access_mask & ACE_DELETE)
3234 permstr[4] = 'd';
3235 if (ace->a_access_mask & ACE_DELETE_CHILD)
3236 permstr[5] = 'D';
3237 if (ace->a_access_mask & ACE_READ_ATTRIBUTES)
3238 permstr[6] = 'a';
3239 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES)
3240 permstr[7] = 'A';
3241 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS)
3242 permstr[8] = 'R';
3243 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS)
3244 permstr[9] = 'W';
3245 if (ace->a_access_mask & ACE_READ_ACL)
3246 permstr[10] = 'c';
3247 if (ace->a_access_mask & ACE_WRITE_ACL)
3248 permstr[11] = 'C';
3249 if (ace->a_access_mask & ACE_WRITE_OWNER)
3250 permstr[12] = 'o';
3251 if (ace->a_access_mask & ACE_SYNCHRONIZE)
3252 permstr[13] = 's';
3253 permstr[14] = '\0';
3254 uval.uvaltype = PRA_STRING;
3255 uval.string_val = permstr;
3256 } else if (!(context->format & PRF_RAWM)) {
3259 * Note this differs from acltext.c:ace_perm_txt()
3260 * because we don't know if the acl belongs to a file
3261 * or directory. ace mask value are the same
3262 * nonetheless, see sys/acl.h
3264 if (ace->a_access_mask & ACE_LIST_DIRECTORY) {
3265 returnstat = strappend(&permstr, gettext(READ_DIR_TXT),
3266 &permstr_alloc);
3268 if (ace->a_access_mask & ACE_ADD_FILE) {
3269 returnstat = strappend(&permstr, gettext(ADD_FILE_TXT),
3270 &permstr_alloc);
3272 if (ace->a_access_mask & ACE_ADD_SUBDIRECTORY) {
3273 returnstat = strappend(&permstr, gettext(ADD_DIR_TXT),
3274 &permstr_alloc);
3276 if (ace->a_access_mask & ACE_READ_NAMED_ATTRS) {
3277 returnstat = strappend(&permstr,
3278 gettext(READ_XATTR_TXT), &permstr_alloc);
3280 if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS) {
3281 returnstat = strappend(&permstr,
3282 gettext(WRITE_XATTR_TXT), &permstr_alloc);
3284 if (ace->a_access_mask & ACE_EXECUTE) {
3285 returnstat = strappend(&permstr,
3286 gettext(EXECUTE_TXT), &permstr_alloc);
3288 if (ace->a_access_mask & ACE_DELETE_CHILD) {
3289 returnstat = strappend(&permstr,
3290 gettext(DELETE_CHILD_TXT), &permstr_alloc);
3292 if (ace->a_access_mask & ACE_READ_ATTRIBUTES) {
3293 returnstat = strappend(&permstr,
3294 gettext(READ_ATTRIBUTES_TXT), &permstr_alloc);
3296 if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES) {
3297 returnstat = strappend(&permstr,
3298 gettext(WRITE_ATTRIBUTES_TXT), &permstr_alloc);
3300 if (ace->a_access_mask & ACE_DELETE) {
3301 returnstat = strappend(&permstr, gettext(DELETE_TXT),
3302 &permstr_alloc);
3304 if (ace->a_access_mask & ACE_READ_ACL) {
3305 returnstat = strappend(&permstr, gettext(READ_ACL_TXT),
3306 &permstr_alloc);
3308 if (ace->a_access_mask & ACE_WRITE_ACL) {
3309 returnstat = strappend(&permstr, gettext(WRITE_ACL_TXT),
3310 &permstr_alloc);
3312 if (ace->a_access_mask & ACE_WRITE_OWNER) {
3313 returnstat = strappend(&permstr,
3314 gettext(WRITE_OWNER_TXT), &permstr_alloc);
3316 if (ace->a_access_mask & ACE_SYNCHRONIZE) {
3317 returnstat = strappend(&permstr,
3318 gettext(SYNCHRONIZE_TXT), &permstr_alloc);
3320 if (permstr[strlen(permstr) - 1] == '/')
3321 permstr[strlen(permstr) - 1] = '\0';
3322 uval.uvaltype = PRA_STRING;
3323 uval.string_val = permstr;
3325 if ((permstr == NULL) || (returnstat != 0) ||
3326 (context->format & PRF_RAWM)) {
3327 uval.uvaltype = PRA_UINT32;
3328 uval.uint32_val = ace->a_access_mask;
3330 returnstat = pa_print(context, &uval, flag);
3332 free(permstr);
3333 if (returnstat != 0)
3334 return (returnstat);
3335 return (close_tag(context, TAG_ACEMASK));
3338 static int
3339 pa_ace_type(pr_context_t *context, ace_t *ace, int status, int flag)
3341 int returnstat;
3342 uval_t uval;
3344 if (status < 0)
3345 return (status);
3348 * TRANSLATION_NOTE
3349 * ace->a_type refers to access type of ZFS/NFSv4 ACL entry.
3351 if ((returnstat = open_tag(context, TAG_ACETYPE)) != 0)
3352 return (returnstat);
3353 if (!(context->format & PRF_RAWM)) {
3354 uval.uvaltype = PRA_STRING;
3355 switch (ace->a_type) {
3356 case ACE_ACCESS_ALLOWED_ACE_TYPE:
3357 uval.string_val = gettext(ALLOW_TXT);
3358 break;
3359 case ACE_ACCESS_DENIED_ACE_TYPE:
3360 uval.string_val = gettext(DENY_TXT);
3361 break;
3362 case ACE_SYSTEM_AUDIT_ACE_TYPE:
3363 uval.string_val = gettext(AUDIT_TXT);
3364 break;
3365 case ACE_SYSTEM_ALARM_ACE_TYPE:
3366 uval.string_val = gettext(ALARM_TXT);
3367 break;
3368 default:
3369 uval.string_val = gettext(UNKNOWN_TXT);
3371 } else {
3372 uval.uvaltype = PRA_USHORT;
3373 uval.uint32_val = ace->a_type;
3375 if ((returnstat = pa_print(context, &uval, flag)) != 0)
3376 return (returnstat);
3377 return (close_tag(context, TAG_ACETYPE));
3381 pa_ace(pr_context_t *context, int status, int flag)
3383 int returnstat;
3384 ace_t ace;
3386 if (status < 0)
3387 return (status);
3389 if ((returnstat = pr_adr_u_int32(context, &ace.a_who, 1)) != 0)
3390 return (returnstat);
3391 if ((returnstat = pr_adr_u_int32(context, &ace.a_access_mask, 1)) != 0)
3392 return (returnstat);
3393 if ((returnstat = pr_adr_u_short(context, &ace.a_flags, 1)) != 0)
3394 return (returnstat);
3395 if ((returnstat = pr_adr_u_short(context, &ace.a_type, 1)) != 0)
3396 return (returnstat);
3398 if ((returnstat = pa_ace_flags(context, &ace, returnstat, 0)) != 0)
3399 return (returnstat);
3400 /* pa_ace_who can returns 1 if uid/gid is not found */
3401 if ((returnstat = pa_ace_who(context, &ace, returnstat, 0)) < 0)
3402 return (returnstat);
3403 if ((returnstat = pa_ace_access_mask(context, &ace,
3404 returnstat, 0)) != 0)
3405 return (returnstat);
3406 return (pa_ace_type(context, &ace, returnstat, flag));