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