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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Token processing for sysupd; each token function does one
31  * or more operations.  All of them bump the buffer pointer
32  * to the next token; some of them extract one or more data
33  * from the token.
34  */
35 
36 #define	DEBUG	0
37 #if DEBUG
38 #define	DPRINT(x) {fprintf x; }
39 #else
40 #define	DPRINT(x)
41 #endif
42 
43 #include <locale.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <sys/types.h>
48 #include <bsm/libbsm.h>
49 #include "toktable.h"	/* ../praudit */
50 #include "sysplugin.h"
51 #include "systoken.h"
52 #include <audit_plugin.h>
53 
54 #if DEBUG
55 static FILE	*dbfp;			/* debug file */
56 #endif
57 
58 static void	anchor_path(char *);
59 static size_t	collapse_path(char *, size_t);
60 static void	get_bytes_to_string(parse_context_t *, size_t *, char **,
61 		    size_t);
62 static void	skip_bytes(parse_context_t *);
63 static void	skip_string(parse_context_t *);
64 static int	xgeneric(parse_context_t *);
65 
66 /*
67  * Process a token in a record to (1) extract data of interest if any
68  * and (2) point to the next token.
69  *
70  * returns 0 if ok.  + or - values are of debug value:
71  *
72  *	returns -1 if the parsing of the token failed.
73  *
74  *	returns +<previous id> if the token is not found.  This value
75  *	is used to help determine where in the record the problem
76  *	occurred.  The common failure case is that the parsing of
77  *	token M is incorrect and the buffer pointer ends up pointing
78  *	to garbage.  The positive error value of M *may* be the id of
79  *	the incorrectly parsed token.
80  */
81 
82 int
83 parse_token(parse_context_t *ctx)
84 {
85 	char		tokenid;
86 	static char	prev_tokenid = -1;
87 	int		rc;
88 
89 #if DEBUG
90 	static boolean_t	first = 1;
91 
92 	if (first) {
93 		dbfp = __auditd_debug_file_open();
94 		first = 0;
95 	}
96 #endif
97 
98 	adrm_char(&(ctx->adr), &tokenid, 1);
99 
100 	if ((tokenid > 0) && (tokentable[tokenid].func != NOFUNC)) {
101 		rc = (*tokentable[tokenid].func)(ctx);
102 		prev_tokenid = tokenid;
103 		return (rc);
104 	}
105 	/* here if token id is not in table */
106 	return (prev_tokenid);
107 }
108 
109 /* There should not be any file tokens in the middle of a record */
110 
111 /* ARGSUSED */
112 int
113 file_token(parse_context_t *ctx)
114 {
115 
116 	return (-1);
117 }
118 
119 /* ARGSUSED */
120 int
121 file64_token(parse_context_t *ctx)
122 {
123 	return (-1);
124 }
125 
126 static void
127 common_header(parse_context_t *ctx)
128 {
129 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_reclen), 1);
130 	ctx->adr.adr_now += sizeof (char);		/* version number */
131 	adrm_short(&(ctx->adr), &(ctx->out.sf_eventid), 1);
132 	ctx->adr.adr_now += sizeof (short);		/* modifier */
133 }
134 
135 /*
136  * 32bit header
137  */
138 int
139 header_token(parse_context_t *ctx)
140 {
141 	common_header(ctx);
142 	ctx->adr.adr_now += 2 * sizeof (int32_t);	/* time */
143 
144 	return (0);
145 }
146 
147 
148 int
149 header32_ex_token(parse_context_t *ctx)
150 {
151 	int32_t	type;
152 
153 	common_header(ctx);
154 
155 	adrm_int32(&(ctx->adr), &type, 1);		/* tid type */
156 	ctx->adr.adr_now += type * sizeof (char);	/* ip address */
157 
158 	ctx->adr.adr_now += 2 * sizeof (int32_t);	/* time */
159 
160 	return (0);
161 }
162 
163 
164 int
165 header64_ex_token(parse_context_t *ctx)
166 {
167 	int32_t	type;
168 
169 	common_header(ctx);
170 
171 	adrm_int32(&(ctx->adr), &type, 1);		/* tid type */
172 	ctx->adr.adr_now += type * sizeof (char);	/* ip address */
173 
174 	ctx->adr.adr_now += 2 * sizeof (int64_t);	/* time */
175 
176 	return (0);
177 }
178 
179 
180 int
181 header64_token(parse_context_t *ctx)
182 {
183 	common_header(ctx);
184 
185 	ctx->adr.adr_now += 2 * sizeof (int64_t);	/* time */
186 
187 	return (0);
188 }
189 
190 
191 /*
192  * ======================================================
193  *  The following token processing routines return
194  *  0: if parsed ok
195  * -1: can't parse and can't determine location of next token
196  * ======================================================
197  */
198 
199 int
200 trailer_token(parse_context_t *ctx)
201 {
202 	short	magic_number;
203 	uint32_t bytes;
204 
205 	adrm_u_short(&(ctx->adr), (ushort_t *)&magic_number, 1);
206 	if (magic_number != AUT_TRAILER_MAGIC)
207 		return (-1);
208 
209 	adrm_u_int32(&(ctx->adr), &bytes, 1);
210 
211 	return (0);
212 }
213 
214 
215 /*
216  * Format of arbitrary data token:
217  *	arbitrary data token id	&(ctx->adr) char
218  * 	how to print		adr_char
219  *	basic unit		adr_char
220  *	unit count		adr_char, specifying number of units of
221  *	data items		depends on basic unit
222  *
223  */
224 int
225 arbitrary_data_token(parse_context_t *ctx)
226 {
227 	char	basic_unit, unit_count;
228 
229 	ctx->adr.adr_now += sizeof (char); /* how to print */
230 
231 	adrm_char(&(ctx->adr), &basic_unit, 1);
232 	adrm_char(&(ctx->adr), &unit_count, 1);
233 
234 	switch (basic_unit) {
235 	case AUR_CHAR: /* same as AUR_BYTE */
236 		ctx->adr.adr_now += unit_count * sizeof (char);
237 		break;
238 	case AUR_SHORT:
239 		ctx->adr.adr_now += unit_count * sizeof (short);
240 		break;
241 	case AUR_INT32:	/* same as AUR_INT */
242 		ctx->adr.adr_now += unit_count * sizeof (int32_t);
243 		break;
244 	case AUR_INT64:
245 		ctx->adr.adr_now += unit_count * sizeof (int64_t);
246 		break;
247 	default:
248 		return (-1);
249 		break;
250 	}
251 	return (0);
252 }
253 
254 
255 /*
256  * Format of opaque token:
257  *	opaque token id		adr_char
258  *	size			adr_short
259  *	data			adr_char, size times
260  *
261  */
262 int
263 opaque_token(parse_context_t *ctx)
264 {
265 	skip_bytes(ctx);
266 	return (0);
267 }
268 
269 
270 /*
271  * Format of return32 value token:
272  * 	return value token id	adr_char
273  *	error number		adr_char
274  *	return value		adr_u_int32
275  *
276  */
277 int
278 return_value32_token(parse_context_t *ctx)
279 {
280 	char		errnum;
281 
282 	adrm_char(&(ctx->adr), &errnum, 1);	/* pass / fail */
283 	ctx->adr.adr_now += sizeof (int32_t);	/* error code */
284 
285 	ctx->out.sf_pass = (errnum == 0) ? 1 : -1;
286 
287 	return (0);
288 }
289 
290 /*
291  * Format of return64 value token:
292  * 	return value token id	adr_char
293  *	error number		adr_char
294  *	return value		adr_u_int64
295  *
296  */
297 int
298 return_value64_token(parse_context_t *ctx)
299 {
300 	char		errnum;
301 
302 	adrm_char(&(ctx->adr), &errnum, 1);	/* pass / fail */
303 	ctx->adr.adr_now += sizeof (int64_t);	/* error code */
304 
305 	ctx->out.sf_pass = (errnum == 0) ? 1 : -1;
306 
307 	return (0);
308 }
309 
310 
311 /*
312  * Format of sequence token:
313  *	sequence token id	adr_char
314  *	audit_count		int32_t
315  *
316  */
317 int
318 sequence_token(parse_context_t *ctx)
319 {
320 	adrm_int32(&(ctx->adr), &(ctx->out.sf_sequence), 1);
321 	return (0);
322 }
323 
324 
325 /*
326  * Format of text token:
327  *	text token id		adr_char
328  * 	text			adr_string
329  */
330 int
331 text_token(parse_context_t *ctx)
332 {
333 	ushort_t	len;
334 	size_t		separator_sz = 0;
335 	char		*bp;	/* pointer to output string */
336 
337 	adrm_u_short(&(ctx->adr), &len, 1);
338 
339 	if (ctx->out.sf_textlen > 0)
340 		separator_sz = sizeof (AU_TEXT_NAME) - 1;
341 
342 	DPRINT((dbfp, "text_token: start length=%d, add length=%d+%d\n",
343 	    ctx->out.sf_textlen, (size_t)len, separator_sz));
344 
345 	ctx->out.sf_text = realloc(ctx->out.sf_text,
346 	    ctx->out.sf_textlen + (size_t)len + separator_sz);
347 
348 	if (ctx->out.sf_text == NULL)
349 		return (-1);
350 
351 	bp = ctx->out.sf_text;
352 
353 	if (ctx->out.sf_textlen != 0) {	/* concatenation? */
354 		bp += ctx->out.sf_textlen;
355 		bp += strlcpy(bp, AU_TEXT_NAME, separator_sz + 1);
356 		ctx->out.sf_textlen += separator_sz;
357 		DPRINT((dbfp, "text_token: l is %d\n%s\n", ctx->out.sf_textlen,
358 		    ctx->out.sf_text));
359 	}
360 	adrm_char(&(ctx->adr), bp, len);
361 	len--;		/* includes EOS */
362 	*(bp + len) = '\0';
363 
364 	ctx->out.sf_textlen += len;
365 	DPRINT((dbfp, "text_token: l=%d\n%s\n", ctx->out.sf_textlen,
366 	    ctx->out.sf_text));
367 
368 	return (0);
369 }
370 
371 /*
372  * Format of tid token:
373  *	ip token id	adr_char
374  *	terminal type	adr_char
375  *  terminal type = AU_IPADR:
376  *	remote port:	ushort
377  *	local port:	ushort
378  *	IP type:	int32 -- AU_IPv4 or AU_IPv6
379  *	address:	int32 if IPv4, else 4 * int32
380  */
381 int
382 tid_token(parse_context_t *ctx)
383 {
384 	uchar_t		type;
385 	int32_t		ip_length;
386 
387 	adrm_char(&(ctx->adr), (char *)&type, 1);
388 
389 	switch (type) {
390 	default:
391 		return (-1);	/* other than IP type is not implemented */
392 	case AU_IPADR:
393 		ctx->adr.adr_now += 2 * sizeof (ushort_t);
394 		adrm_int32(&(ctx->adr), &ip_length, 1);
395 		ctx->adr.adr_now += ip_length;
396 		break;
397 	}
398 	return (0);
399 }
400 
401 /*
402  * Format of ip_addr token:
403  *	ip token id	adr_char
404  *	address		adr_int32
405  *
406  */
407 int
408 ip_addr_token(parse_context_t *ctx)
409 {
410 	ctx->adr.adr_now += sizeof (int32_t);
411 
412 	return (0);
413 }
414 
415 /*
416  * Format of ip_addr_ex token:
417  *	ip token id	adr_char
418  *	ip type		adr_int32
419  *	address		4*adr_int32
420  *
421  */
422 int
423 ip_addr_ex_token(parse_context_t *ctx)
424 {
425 	ctx->adr.adr_now += 5 * sizeof (int32_t);
426 
427 	return (0);
428 }
429 
430 /*
431  * Format of ip token:
432  *	ip header token id	adr_char
433  *	version			adr_char
434  *	type of service		adr_char
435  *	length			adr_short
436  *	id			adr_u_short
437  *	offset			adr_u_short
438  *	ttl			adr_char
439  *	protocol		adr_char
440  *	checksum		adr_u_short
441  *	source address		adr_int32
442  *	destination address	adr_int32
443  *
444  */
445 int
446 ip_token(parse_context_t *ctx)
447 {
448 	ctx->adr.adr_now +=	(2 * sizeof (char)) +
449 				(3 * sizeof (short)) +
450 				(2 * sizeof (char)) +
451 				sizeof (short) +
452 				(2 * sizeof (int32_t));
453 	return (0);
454 }
455 
456 
457 /*
458  * Format of iport token:
459  *	ip port address token id	adr_char
460  *	port address			adr_short
461  *
462  */
463 int
464 iport_token(parse_context_t *ctx)
465 {
466 	ctx->adr.adr_now += sizeof (short);
467 
468 	return (0);
469 }
470 
471 
472 /*
473  * Format of groups token:
474  *	group token id		adr_char
475  *	group list		adr_int32, 16 times
476  *
477  */
478 int
479 group_token(parse_context_t *ctx)
480 {
481 	ctx->adr.adr_now += 16 * sizeof (int32_t);
482 
483 	return (0);
484 }
485 
486 /*
487  * Format of newgroups token:
488  *	group token id		adr_char
489  *	number of groups	adr_short
490  *	group list		adr_int32, "number" times
491  *
492  */
493 int
494 newgroup_token(parse_context_t *ctx)
495 {
496 	short int   number;
497 
498 	adrm_short(&(ctx->adr), &number, 1);
499 
500 	ctx->adr.adr_now += number * sizeof (int32_t);
501 
502 	return (0);
503 }
504 
505 /*
506  * Format of argument32 token:
507  *	argument token id	adr_char
508  *	argument number		adr_char
509  *	argument value		adr_int32
510  *	argument description	adr_string
511  *
512  */
513 int
514 argument32_token(parse_context_t *ctx)
515 {
516 	ctx->adr.adr_now += sizeof (char) + sizeof (int32_t);
517 	skip_bytes(ctx);
518 
519 	return (0);
520 }
521 
522 /*
523  * Format of argument64 token:
524  *	argument token id	adr_char
525  *	argument number		adr_char
526  *	argument value		adr_int64
527  *	argument description	adr_string
528  *
529  */
530 int
531 argument64_token(parse_context_t *ctx)
532 {
533 	ctx->adr.adr_now += sizeof (char) + sizeof (int64_t);
534 	skip_bytes(ctx);
535 
536 	return (0);
537 }
538 
539 int
540 acl_token(parse_context_t *ctx)
541 {
542 	ctx->adr.adr_now += 3 * sizeof (int32_t);
543 
544 	return (0);
545 }
546 
547 /*
548  * Format of attribute token: (old pre SunOS 5.7 format)
549  *	attribute token id	adr_char
550  * 	mode			adr_int32 (printed in octal)
551  *	uid			adr_int32
552  *	gid			adr_int32
553  *	file system id		adr_int32
554  *	node id			adr_int32
555  *	device			adr_int32
556  *
557  */
558 int
559 attribute_token(parse_context_t *ctx)
560 {
561 	ctx->adr.adr_now += 6 * sizeof (int32_t);
562 
563 	return (0);
564 }
565 
566 /*
567  * Format of attribute32 token:
568  *	attribute token id	adr_char
569  * 	mode			adr_int32 (printed in octal)
570  *	uid			adr_int32
571  *	gid			adr_int32
572  *	file system id		adr_int32
573  *	node id			adr_int64
574  *	device			adr_int32
575  *
576  */
577 int
578 attribute32_token(parse_context_t *ctx)
579 {
580 	ctx->adr.adr_now += (5 * sizeof (int32_t)) + sizeof (int64_t);
581 
582 	return (0);
583 }
584 
585 /*
586  * Format of attribute64 token:
587  *	attribute token id	adr_char
588  * 	mode			adr_int32 (printed in octal)
589  *	uid			adr_int32
590  *	gid			adr_int32
591  *	file system id		adr_int32
592  *	node id			adr_int64
593  *	device			adr_int64
594  *
595  */
596 int
597 attribute64_token(parse_context_t *ctx)
598 {
599 	ctx->adr.adr_now += (4 * sizeof (int32_t)) + (2 * sizeof (int64_t));
600 
601 	return (0);
602 }
603 
604 
605 /*
606  * Format of command token:
607  *	attribute token id	adr_char
608  *	argc			adr_short
609  *	argv len		adr_short	variable amount of argv len
610  *	argv text		argv len	and text
611  *	.
612  *	.
613  *	.
614  *	envp count		adr_short	variable amount of envp len
615  *	envp len		adr_short	and text
616  *	envp text		envp		len
617  *	.
618  *	.
619  *	.
620  *
621  */
622 int
623 cmd_token(parse_context_t *ctx)
624 {
625 	short	cnt;
626 	short	i;
627 
628 	adrm_short(&(ctx->adr), &cnt, 1);
629 
630 	for (i = 0; i < cnt; i++)
631 		skip_bytes(ctx);
632 
633 	adrm_short(&(ctx->adr), &cnt, 1);
634 
635 	for (i = 0; i < cnt; i++)
636 		skip_bytes(ctx);
637 
638 	return (0);
639 }
640 
641 
642 /*
643  * Format of exit token:
644  *	attribute token id	adr_char
645  *	return value		adr_int32
646  *	errno			adr_int32
647  *
648  */
649 int
650 exit_token(parse_context_t *ctx)
651 {
652 	int32_t	retval;
653 
654 	adrm_int32(&(ctx->adr), &retval, 1);
655 	ctx->adr.adr_now += sizeof (int32_t);
656 
657 	ctx->out.sf_pass = (retval == 0) ? 1 : -1;
658 	return (0);
659 }
660 
661 /*
662  * Format of exec_args token:
663  *	attribute token id	adr_char
664  *	count value		adr_int32
665  *	strings			null terminated strings
666  *
667  */
668 int
669 exec_args_token(parse_context_t *ctx)
670 {
671 	int count, i;
672 
673 	adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
674 	for (i = 1; i <= count; i++) {
675 		skip_string(ctx);
676 	}
677 
678 	return (0);
679 }
680 
681 /*
682  * Format of exec_env token:
683  *	attribute token id	adr_char
684  *	count value		adr_int32
685  *	strings			null terminated strings
686  *
687  */
688 int
689 exec_env_token(parse_context_t *ctx)
690 {
691 	int count, i;
692 
693 	adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
694 	for (i = 1; i <= count; i++)
695 		skip_string(ctx);
696 
697 	return (0);
698 }
699 
700 /*
701  * Format of liaison token:
702  */
703 int
704 liaison_token(parse_context_t *ctx)
705 {
706 	ctx->adr.adr_now += sizeof (int32_t);
707 
708 	return (0);
709 }
710 
711 
712 /*
713  * Format of path token:
714  *	path				adr_string
715  */
716 int
717 path_token(parse_context_t *ctx)
718 {
719 	get_bytes_to_string(ctx, &(ctx->out.sf_pathlen), &(ctx->out.sf_path),
720 	    0);
721 	if (ctx->out.sf_path == NULL)
722 		return (-1);
723 	/*
724 	 * anchor the path because collapse_path needs it
725 	 */
726 	if (*(ctx->out.sf_path) != '/') {
727 		anchor_path(ctx->out.sf_path);
728 		ctx->out.sf_pathlen++;
729 	}
730 	ctx->out.sf_pathlen = collapse_path(ctx->out.sf_path,
731 	    ctx->out.sf_pathlen);
732 
733 	return (0);
734 }
735 
736 /*
737  * path attr token / AUT_XATPATH
738  *
739  * Format of path attr token:
740  *	token id		adr_char
741  *	string count		adr_int32
742  *	strings			adr_string
743  *
744  * the sequence of strings is converted to a single string with
745  * a blank separator replacing the EOS for all but the last
746  * string.
747  */
748 int
749 path_attr_token(parse_context_t *ctx)
750 {
751 	int	count, i;
752 	int	last_len;
753 	size_t	offset;
754 	char	*p;
755 
756 	adrm_int32(&(ctx->adr), &count, 1);
757 
758 	offset = ctx->out.sf_atpathlen;
759 	p = ctx->adr.adr_now;
760 	for (i = 0; i <= count; i++) {
761 		last_len = strlen(p);
762 		ctx->out.sf_atpathlen += last_len + 1;
763 		p += last_len + 1;
764 	}
765 	ctx->out.sf_atpath = realloc(ctx->out.sf_atpath, ctx->out.sf_atpathlen);
766 	ctx->out.sf_atpath += offset;
767 	p = ctx->out.sf_atpath;		/* save for fix up, below */
768 	(void) memcpy(ctx->out.sf_atpath, ctx->adr.adr_now,
769 		ctx->out.sf_atpathlen - offset);
770 	ctx->out.sf_atpathlen--;
771 
772 	/* fix up: replace each eos except the last with ' ' */
773 
774 	for (i = 0; i < count; i++) {
775 		while (*p++ != '\0');
776 		*(p - 1) = ' ';
777 	}
778 	return (0);
779 }
780 
781 
782 /*
783  * Format of System V IPC permission token:
784  *	System V IPC permission token id	adr_char
785  * 	uid					adr_int32
786  *	gid					adr_int32
787  *	cuid					adr_int32
788  *	cgid					adr_int32
789  *	mode					adr_int32
790  *	seq					adr_int32
791  *	key					adr_int32
792  *	label					adr_opaque, sizeof (bslabel_t)
793  *							    bytes
794  */
795 int
796 s5_IPC_perm_token(parse_context_t *ctx)
797 {
798 	ctx->adr.adr_now += (7 * sizeof (int32_t));
799 
800 #if TSOL
801 	ctx->adr.adr_now += sizeof (bslabel_t);
802 #endif
803 	return (0);
804 }
805 
806 static void
807 common_process(parse_context_t *ctx)
808 {
809 	int32_t	ruid, rgid, egid, pid;
810 	uint32_t asid;
811 
812 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_pauid), 1);
813 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_peuid), 1);
814 	adrm_int32(&(ctx->adr), &egid, 1);
815 	adrm_int32(&(ctx->adr), &ruid, 1);
816 	adrm_int32(&(ctx->adr), &rgid, 1);
817 	adrm_int32(&(ctx->adr), &pid, 1);
818 	adrm_u_int32(&(ctx->adr), &asid, 1);
819 }
820 
821 /*
822  * Format of process32 token:
823  *	process token id	adr_char
824  *	auid			adr_int32
825  *	euid			adr_int32
826  *	egid 			adr_int32
827  * 	ruid			adr_int32
828  *	rgid			adr_int32
829  * 	pid			adr_int32
830  * 	sid			adr_int32
831  * 	termid			adr_int32*2
832  *
833  */
834 int
835 process32_token(parse_context_t *ctx)
836 {
837 	int32_t port, machine;
838 
839 	common_process(ctx);
840 
841 	adrm_int32(&(ctx->adr), &port, 1);
842 	adrm_int32(&(ctx->adr), &machine, 1);
843 
844 	return (0);
845 }
846 
847 /*
848  * Format of process32_ex token:
849  *	process token id	adr_char
850  *	auid			adr_int32
851  *	euid			adr_int32
852  *	egid 			adr_int32
853  * 	ruid			adr_int32
854  *	rgid			adr_int32
855  * 	pid			adr_int32
856  * 	sid			adr_int32
857  * 	termid			adr_int32*6
858  *
859  */
860 int
861 process32_ex_token(parse_context_t *ctx)
862 {
863 	int32_t port, type, addr[4];
864 
865 	common_process(ctx);
866 
867 	adrm_int32(&(ctx->adr), &port, 1);
868 	adrm_int32(&(ctx->adr), &type, 1);
869 	adrm_int32(&(ctx->adr), &addr[0], 4);
870 
871 	return (0);
872 }
873 
874 /*
875  * Format of process64 token:
876  *	process token id	adr_char
877  *	auid			adr_int32
878  *	euid			adr_int32
879  *	egid 			adr_int32
880  * 	ruid			adr_int32
881  *	rgid			adr_int32
882  * 	pid			adr_int32
883  * 	sid			adr_int32
884  * 	termid			adr_int64+adr_int32
885  *
886  */
887 int
888 process64_token(parse_context_t *ctx)
889 {
890 	int64_t port;
891 	int32_t machine;
892 
893 	common_process(ctx);
894 
895 	adrm_int64(&(ctx->adr), &port, 1);
896 	adrm_int32(&(ctx->adr), &machine, 1);
897 
898 	return (0);
899 }
900 
901 /*
902  * Format of process64 token:
903  *	process token id	adr_char
904  *	auid			adr_int32
905  *	euid			adr_int32
906  *	egid 			adr_int32
907  * 	ruid			adr_int32
908  *	rgid			adr_int32
909  * 	pid			adr_int32
910  * 	sid			adr_int32
911  * 	termid			adr_int64+5*adr_int32
912  *
913  */
914 int
915 process64_ex_token(parse_context_t *ctx)
916 {
917 	int64_t port;
918 	int32_t type, addr[4];
919 
920 	common_process(ctx);
921 
922 	adrm_int64(&(ctx->adr), &port, 1);
923 	adrm_int32(&(ctx->adr), &type, 1);
924 	adrm_int32(&(ctx->adr), &addr[0], 4);
925 
926 	return (0);
927 }
928 
929 /*
930  * Format of System V IPC token:
931  *	System V IPC token id	adr_char
932  *	System V IPC type	adr_char
933  *	object id		adr_int32
934  *
935  */
936 int
937 s5_IPC_token(parse_context_t *ctx)
938 {
939 	ctx->adr.adr_now += sizeof (char);
940 	ctx->adr.adr_now += sizeof (int32_t);
941 
942 	return (0);
943 }
944 
945 
946 /*
947  * Format of socket token:
948  *	socket_type		adrm_short
949  *	remote_port		adrm_short
950  *	remote_inaddr		adrm_int32
951  *
952  */
953 int
954 socket_token(parse_context_t *ctx)
955 {
956 	ctx->adr.adr_now += (2 * sizeof (short)) + sizeof (int32_t);
957 
958 	return (0);
959 }
960 
961 
962 /*
963  * Format of socket token:
964  *
965  */
966 int
967 socket_ex_token(parse_context_t *ctx)
968 {
969 	short	ip_size;
970 
971 	ctx->adr.adr_now += (2 * sizeof (short));
972 	adrm_short(&(ctx->adr), &ip_size, 1);
973 
974 	ctx->adr.adr_now +=	sizeof (short) +
975 				(ip_size * sizeof (char)) +
976 				sizeof (short) +
977 				(ip_size * sizeof (char));
978 	return (0);
979 }
980 
981 
982 static void
983 common_subject(parse_context_t *ctx)
984 {
985 	int32_t	ruid, rgid, pid;
986 
987 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_auid), 1);
988 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_euid), 1);
989 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_egid), 1);
990 	adrm_int32(&(ctx->adr), &ruid, 1);
991 	adrm_int32(&(ctx->adr), &rgid, 1);
992 	adrm_int32(&(ctx->adr), &pid, 1);
993 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_asid), 1);
994 }
995 
996 /*
997  * Format of subject32 token:
998  *	subject token id	adr_char
999  *	auid			adr_int32
1000  *	euid			adr_int32
1001  *	egid 			adr_int32
1002  * 	ruid			adr_int32
1003  *	rgid			adr_int32
1004  * 	pid			adr_int32
1005  * 	sid			adr_int32
1006  * 	termid			adr_int32*2
1007  *
1008  */
1009 int
1010 subject32_token(parse_context_t *ctx)
1011 {
1012 	int32_t port;	/* not used in output */
1013 
1014 	common_subject(ctx);
1015 
1016 	adrm_int32(&(ctx->adr), &port, 1);
1017 	ctx->out.sf_tid.at_type = AU_IPv4;
1018 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 1);
1019 
1020 	return (0);
1021 }
1022 
1023 /*
1024  * Format of subject32_ex token:
1025  *	subject token id	adr_char
1026  *	auid			adr_int32
1027  *	euid			adr_int32
1028  *	egid 			adr_int32
1029  * 	ruid			adr_int32
1030  *	rgid			adr_int32
1031  * 	pid			adr_int32
1032  * 	sid			adr_int32
1033  * 	termid_addr		adr_int32*6
1034  *
1035  */
1036 int
1037 subject32_ex_token(parse_context_t *ctx)
1038 {
1039 	int32_t port;	/* not used in output */
1040 
1041 	common_subject(ctx);
1042 
1043 	adrm_int32(&(ctx->adr), &port, 1);
1044 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
1045 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 4);
1046 
1047 	return (0);
1048 }
1049 
1050 /*
1051  * Format of subject64 token:
1052  *	subject token id	adr_char
1053  *	auid			adr_int32
1054  *	euid			adr_int32
1055  *	egid 			adr_int32
1056  * 	ruid			adr_int32
1057  *	rgid			adr_int32
1058  * 	pid			adr_int32
1059  * 	sid			adr_int32
1060  * 	termid			adr_int64+adr_int32
1061  *
1062  */
1063 int
1064 subject64_token(parse_context_t *ctx)
1065 {
1066 	int64_t port;
1067 
1068 	common_subject(ctx);
1069 
1070 	adrm_int64(&(ctx->adr), &port, 1);
1071 	ctx->out.sf_tid.at_type = AU_IPv4;
1072 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 1);
1073 
1074 	return (0);
1075 }
1076 
1077 /*
1078  * Format of subject64 token:
1079  *	subject token id	adr_char
1080  *	auid			adr_int32
1081  *	euid			adr_int32
1082  *	egid 			adr_int32
1083  * 	ruid			adr_int32
1084  *	rgid			adr_int32
1085  * 	pid			adr_int32
1086  * 	sid			adr_int32
1087  * 	termid			adr_int64+5*adr_int32
1088  *
1089  */
1090 int
1091 subject64_ex_token(parse_context_t *ctx)
1092 {
1093 	int64_t port;
1094 
1095 	common_subject(ctx);
1096 
1097 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_asid), 1);
1098 	adrm_int64(&(ctx->adr), &port, 1);
1099 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
1100 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 4);
1101 
1102 	return (0);
1103 }
1104 
1105 
1106 int
1107 xatom_token(parse_context_t *ctx)
1108 {
1109 	skip_bytes(ctx);
1110 
1111 	return (0);
1112 }
1113 
1114 
1115 int
1116 xselect_token(parse_context_t *ctx)
1117 {
1118 	skip_bytes(ctx);
1119 	skip_bytes(ctx);
1120 	skip_bytes(ctx);
1121 
1122 	return (0);
1123 }
1124 
1125 /*
1126  * anchor a path name with a slash
1127  * assume we have enough space
1128  */
1129 static void
1130 anchor_path(char *path)
1131 {
1132 
1133 	(void) memmove((void *)(path + 1), (void *)path, strlen(path) + 1);
1134 	*path = '/';
1135 }
1136 
1137 
1138 /*
1139  * copy path to collapsed path.
1140  * collapsed path does not contain:
1141  *	successive slashes
1142  *	instances of dot-slash
1143  *	instances of dot-dot-slash
1144  * passed path must be anchored with a '/'
1145  */
1146 static size_t
1147 collapse_path(char *s, size_t ls)
1148 {
1149 	int	id;	/* index of where we are in destination string */
1150 	int	is;	/* index of where we are in source string */
1151 	int	slashseen;	/* have we seen a slash */
1152 
1153 	ls++; /* source length including '\0' */
1154 
1155 	slashseen = 0;
1156 	for (is = 0, id = 0; is < ls; is++) {
1157 		if (s[is] == '\0') {
1158 			if (id > 1 && s[id-1] == '/') {
1159 				--id;
1160 			}
1161 			s[id++] = '\0';
1162 			break;
1163 		}
1164 		/* previous character was a / */
1165 		if (slashseen) {
1166 			if (s[is] == '/')
1167 				continue;	/* another slash, ignore it */
1168 		} else if (s[is] == '/') {
1169 			/* we see a /, just copy it and try again */
1170 			slashseen = 1;
1171 			s[id++] = '/';
1172 			continue;
1173 		}
1174 		/* /./ seen */
1175 		if (s[is] == '.' && s[is+1] == '/') {
1176 			is += 1;
1177 			continue;
1178 		}
1179 		/* XXX/. seen */
1180 		if (s[is] == '.' && s[is+1] == '\0') {
1181 			if (id > 1)
1182 				id--;
1183 			continue;
1184 		}
1185 		/* XXX/.. seen */
1186 		if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '\0') {
1187 			is += 1;
1188 			if (id > 0)
1189 				id--;
1190 			while (id > 0 && s[--id] != '/');
1191 			id++;
1192 			continue;
1193 		}
1194 		/* XXX/../ seen */
1195 		if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '/') {
1196 			is += 2;
1197 			if (id > 0)
1198 				id--;
1199 			while (id > 0 && s[--id] != '/');
1200 			id++;
1201 			continue;
1202 		}
1203 		while (is < ls && (s[id++] = s[is++]) != '/');
1204 		is--;
1205 	}
1206 	return ((size_t)id - 1);
1207 }
1208 
1209 /*
1210  * for tokens with sub-fields that include a length, this
1211  * skips the sub-field.
1212  */
1213 
1214 static void
1215 skip_bytes(parse_context_t *ctx)
1216 {
1217 	ushort_t	c;
1218 
1219 	adrm_u_short(&(ctx->adr), &c, 1);
1220 	ctx->adr.adr_now += c;
1221 }
1222 
1223 static void
1224 skip_string(parse_context_t *ctx)
1225 {
1226 	char	c;
1227 
1228 	do {
1229 		adrm_char(&(ctx->adr), &c, 1);
1230 	} while (c != (char)0);
1231 }
1232 
1233 /*
1234  * add a byte to specified length so there can be a prefix of
1235  * '/' added (if needed for paths).  Another is added for '\0'
1236  *
1237  * if offset is zero, new data overwrites old, if any.  Otherwise
1238  * new data is appended to the end.
1239  */
1240 
1241 static void
1242 get_bytes_to_string(parse_context_t *ctx, size_t *l, char **p,
1243     size_t offset)
1244 {
1245 	ushort_t	len;
1246 	char		*bp;
1247 
1248 	adrm_u_short(&(ctx->adr), &len, 1);
1249 
1250 	len++;	/* in case need to add '/' prefix */
1251 	*p = realloc(*p, 1 + (size_t)len + offset);
1252 	if (*p == NULL) {
1253 		perror("audit_sysudp.so");
1254 		return;
1255 	}
1256 	if (offset > 0)
1257 		offset--;	/* overwrite end of string */
1258 
1259 	*l = (size_t)len - 2 + offset;
1260 
1261 	bp = *p + offset;
1262 	adrm_char(&(ctx->adr), bp, len - 1);
1263 	*(bp + len - 1) = '\0';
1264 }
1265 
1266 
1267 /*
1268  * Format of host token:
1269  *	host  		adr_uint32
1270  */
1271 int
1272 host_token(parse_context_t *ctx)
1273 {
1274 	ctx->adr.adr_now += sizeof (int32_t);
1275 
1276 	return (0);
1277 }
1278 
1279 /*
1280  * Format of useofauth token:
1281  *	uauth token id		adr_char
1282  * 	uauth			adr_string
1283  *
1284  */
1285 int
1286 useofauth_token(parse_context_t *ctx)
1287 {
1288 	get_bytes_to_string(ctx, &(ctx->out.sf_uauthlen),
1289 	    &(ctx->out.sf_uauth), 0);
1290 
1291 	return (0);
1292 }
1293 
1294 /*
1295  * Format of zonename token:
1296  *	zonename token id		adr_char
1297  * 	zonename			adr_string
1298  *
1299  */
1300 int
1301 zonename_token(parse_context_t *ctx)
1302 {
1303 	get_bytes_to_string(ctx,
1304 	    &(ctx->out.sf_zonelen),
1305 	    &(ctx->out.sf_zonename),
1306 	    0);
1307 
1308 	return (0);
1309 }
1310 
1311 int
1312 xcolormap_token(parse_context_t *ctx)
1313 {
1314 	return (xgeneric(ctx));
1315 }
1316 
1317 int
1318 xcursor_token(parse_context_t *ctx)
1319 {
1320 	return (xgeneric(ctx));
1321 }
1322 
1323 int
1324 xfont_token(parse_context_t *ctx)
1325 {
1326 	return (xgeneric(ctx));
1327 }
1328 
1329 int
1330 xgc_token(parse_context_t *ctx)
1331 {
1332 	return (xgeneric(ctx));
1333 }
1334 
1335 int
1336 xpixmap_token(parse_context_t *ctx)
1337 {
1338 	return (xgeneric(ctx));
1339 }
1340 
1341 int
1342 xwindow_token(parse_context_t *ctx)
1343 {
1344 	return (xgeneric(ctx));
1345 }
1346 /*
1347  * Format of xgeneric token:
1348  *	XID			adr_int32
1349  *	creator UID		adr_int32
1350  *
1351  * Includes:  xcolormap, xcursor, xfont, xgc, xpixmap, and xwindow
1352  */
1353 static int
1354 xgeneric(parse_context_t *ctx)
1355 {
1356 	ctx->adr.adr_now += 2 * sizeof (int32_t);
1357 
1358 	return (0);
1359 }
1360 /*
1361  * Format of xproperty token:
1362  *	XID			adr_int32
1363  *	creator UID		adr_int32
1364  *	atom string		adr_string
1365  */
1366 int
1367 xproperty_token(parse_context_t *ctx)
1368 {
1369 	ctx->adr.adr_now += 2 * sizeof (int32_t);
1370 
1371 	return (0);
1372 }
1373 /*
1374  * Format of xclient token:
1375  * 	xclient id		adr_int32
1376  */
1377 int
1378 xclient_token(parse_context_t *ctx)
1379 {
1380 	ctx->adr.adr_now += sizeof (int32_t);
1381 
1382 	return (0);
1383 }
1384 /*
1385  * Format of clearance token:
1386  *	clearance		adr_char*(sizeof (bclear_t))
1387  *
1388  * ifdef TSOL because of bclear_t
1389  */
1390 #ifndef	TSOL
1391 /* ARGSUSED */
1392 #endif	/* !TSOL */
1393 int
1394 clearance_token(parse_context_t *ctx)
1395 {
1396 #ifdef	TSOL
1397 
1398 	ctx->adr.adr_now += sizeof (bclear_t);
1399 
1400 	return (0);
1401 #else	/* !TSOL */
1402 	return (-1);
1403 #endif	/* TSOL */
1404 }
1405 /*
1406  * Format of ilabel token:
1407  *	ilabel			adr_char*(sizeof (bilabel_t))
1408  */
1409 #ifndef	TSOL
1410 /* ARGSUSED */
1411 #endif	/* !TSOL */
1412 int
1413 ilabel_token(parse_context_t *ctx)
1414 {
1415 #ifdef	TSOL
1416 
1417 	ctx->adr.adr_now += sizeof (bilabel_t);
1418 
1419 	return (0);
1420 #else	/* !TSOL */
1421 	return (-1);
1422 #endif	/* TSOL */
1423 }
1424 
1425 /*
1426  * -----------------------------------------------------------------------
1427  * privilege_token()	: Process privilege token and display contents
1428  *
1429  * Format of privilege token:
1430  *	privilege token id	adr_char
1431  *	privilege type		adr_string
1432  *	privilege		adr_string
1433  * -----------------------------------------------------------------------
1434  */
1435 
1436 int
1437 privilege_token(parse_context_t *ctx)
1438 {
1439 	skip_bytes(ctx);
1440 	skip_bytes(ctx);
1441 
1442 	return (0);
1443 }
1444 
1445 
1446 /*
1447  * Format of slabel token:
1448  *	slabel			adr_char*(sizeof (bslabel_t))
1449  */
1450 #ifndef	TSOL
1451 /* ARGSUSED */
1452 #endif	/* !TSOL */
1453 int
1454 slabel_token(parse_context_t *ctx)
1455 {
1456 #ifdef	TSOL
1457 
1458 	ctx->adr.adr_now += sizeof (bslabel_t);
1459 
1460 	return (0);
1461 #else	/* !TSOL */
1462 	return (-1);
1463 #endif	/* TSOL */
1464 }
1465 
1466 /*
1467  * Format of useofpriv token:
1468  *	priv_type			adr_char
1469  *	priv_set_t			adr_short
1470  *	priv_set			adr_char*(sizeof (priv_set_t))
1471  */
1472 int
1473 useofpriv_token(parse_context_t *ctx)
1474 {
1475 	ctx->adr.adr_now += sizeof (char); /* success / fail */
1476 	skip_bytes(ctx);
1477 
1478 	return (0);
1479 }
1480