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