xref: /titanic_52/usr/src/lib/auditd_plugins/syslog/systoken.c (revision a93a1f58a8763fa69172980b98e3d24720c1136e)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Token processing for sysupd; each token function does one
30  * or more operations.  All of them bump the buffer pointer
31  * to the next token; some of them extract one or more data
32  * from the token.
33  */
34 
35 #define	DEBUG	0
36 #if DEBUG
37 #define	DPRINT(x) {fprintf x; }
38 #else
39 #define	DPRINT(x)
40 #endif
41 
42 #include <locale.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <sys/types.h>
47 #include <bsm/libbsm.h>
48 #include <sys/tsol/label.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)) + (3 * sizeof (short)) +
449 	    (2 * sizeof (char)) + sizeof (short) + (2 * sizeof (int32_t));
450 	return (0);
451 }
452 
453 
454 /*
455  * Format of iport token:
456  *	ip port address token id	adr_char
457  *	port address			adr_short
458  *
459  */
460 int
461 iport_token(parse_context_t *ctx)
462 {
463 	ctx->adr.adr_now += sizeof (short);
464 
465 	return (0);
466 }
467 
468 
469 /*
470  * Format of groups token:
471  *	group token id		adr_char
472  *	group list		adr_int32, 16 times
473  *
474  */
475 int
476 group_token(parse_context_t *ctx)
477 {
478 	ctx->adr.adr_now += 16 * sizeof (int32_t);
479 
480 	return (0);
481 }
482 
483 /*
484  * Format of newgroups token:
485  *	group token id		adr_char
486  *	number of groups	adr_short
487  *	group list		adr_int32, "number" times
488  *
489  */
490 int
491 newgroup_token(parse_context_t *ctx)
492 {
493 	short int   number;
494 
495 	adrm_short(&(ctx->adr), &number, 1);
496 
497 	ctx->adr.adr_now += number * sizeof (int32_t);
498 
499 	return (0);
500 }
501 
502 /*
503  * Format of argument32 token:
504  *	argument token id	adr_char
505  *	argument number		adr_char
506  *	argument value		adr_int32
507  *	argument description	adr_string
508  *
509  */
510 int
511 argument32_token(parse_context_t *ctx)
512 {
513 	ctx->adr.adr_now += sizeof (char) + sizeof (int32_t);
514 	skip_bytes(ctx);
515 
516 	return (0);
517 }
518 
519 /*
520  * Format of argument64 token:
521  *	argument token id	adr_char
522  *	argument number		adr_char
523  *	argument value		adr_int64
524  *	argument description	adr_string
525  *
526  */
527 int
528 argument64_token(parse_context_t *ctx)
529 {
530 	ctx->adr.adr_now += sizeof (char) + sizeof (int64_t);
531 	skip_bytes(ctx);
532 
533 	return (0);
534 }
535 
536 int
537 acl_token(parse_context_t *ctx)
538 {
539 	ctx->adr.adr_now += 3 * sizeof (int32_t);
540 
541 	return (0);
542 }
543 
544 /*
545  * Format of attribute token: (old pre SunOS 5.7 format)
546  *	attribute token id	adr_char
547  * 	mode			adr_int32 (printed in octal)
548  *	uid			adr_int32
549  *	gid			adr_int32
550  *	file system id		adr_int32
551  *	node id			adr_int32
552  *	device			adr_int32
553  *
554  */
555 int
556 attribute_token(parse_context_t *ctx)
557 {
558 	ctx->adr.adr_now += 6 * sizeof (int32_t);
559 
560 	return (0);
561 }
562 
563 /*
564  * Format of attribute32 token:
565  *	attribute token id	adr_char
566  * 	mode			adr_int32 (printed in octal)
567  *	uid			adr_int32
568  *	gid			adr_int32
569  *	file system id		adr_int32
570  *	node id			adr_int64
571  *	device			adr_int32
572  *
573  */
574 int
575 attribute32_token(parse_context_t *ctx)
576 {
577 	ctx->adr.adr_now += (5 * sizeof (int32_t)) + sizeof (int64_t);
578 
579 	return (0);
580 }
581 
582 /*
583  * Format of attribute64 token:
584  *	attribute token id	adr_char
585  * 	mode			adr_int32 (printed in octal)
586  *	uid			adr_int32
587  *	gid			adr_int32
588  *	file system id		adr_int32
589  *	node id			adr_int64
590  *	device			adr_int64
591  *
592  */
593 int
594 attribute64_token(parse_context_t *ctx)
595 {
596 	ctx->adr.adr_now += (4 * sizeof (int32_t)) + (2 * sizeof (int64_t));
597 
598 	return (0);
599 }
600 
601 
602 /*
603  * Format of command token:
604  *	attribute token id	adr_char
605  *	argc			adr_short
606  *	argv len		adr_short	variable amount of argv len
607  *	argv text		argv len	and text
608  *	.
609  *	.
610  *	.
611  *	envp count		adr_short	variable amount of envp len
612  *	envp len		adr_short	and text
613  *	envp text		envp		len
614  *	.
615  *	.
616  *	.
617  *
618  */
619 int
620 cmd_token(parse_context_t *ctx)
621 {
622 	short	cnt;
623 	short	i;
624 
625 	adrm_short(&(ctx->adr), &cnt, 1);
626 
627 	for (i = 0; i < cnt; i++)
628 		skip_bytes(ctx);
629 
630 	adrm_short(&(ctx->adr), &cnt, 1);
631 
632 	for (i = 0; i < cnt; i++)
633 		skip_bytes(ctx);
634 
635 	return (0);
636 }
637 
638 
639 /*
640  * Format of exit token:
641  *	attribute token id	adr_char
642  *	return value		adr_int32
643  *	errno			adr_int32
644  *
645  */
646 int
647 exit_token(parse_context_t *ctx)
648 {
649 	int32_t	retval;
650 
651 	adrm_int32(&(ctx->adr), &retval, 1);
652 	ctx->adr.adr_now += sizeof (int32_t);
653 
654 	ctx->out.sf_pass = (retval == 0) ? 1 : -1;
655 	return (0);
656 }
657 
658 /*
659  * Format of exec_args token:
660  *	attribute token id	adr_char
661  *	count value		adr_int32
662  *	strings			null terminated strings
663  *
664  */
665 int
666 exec_args_token(parse_context_t *ctx)
667 {
668 	int count, i;
669 
670 	adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
671 	for (i = 1; i <= count; i++) {
672 		skip_string(ctx);
673 	}
674 
675 	return (0);
676 }
677 
678 /*
679  * Format of exec_env token:
680  *	attribute token id	adr_char
681  *	count value		adr_int32
682  *	strings			null terminated strings
683  *
684  */
685 int
686 exec_env_token(parse_context_t *ctx)
687 {
688 	int count, i;
689 
690 	adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
691 	for (i = 1; i <= count; i++)
692 		skip_string(ctx);
693 
694 	return (0);
695 }
696 
697 /*
698  * Format of liaison token:
699  */
700 int
701 liaison_token(parse_context_t *ctx)
702 {
703 	ctx->adr.adr_now += sizeof (int32_t);
704 
705 	return (0);
706 }
707 
708 
709 /*
710  * Format of path token:
711  *	path				adr_string
712  */
713 int
714 path_token(parse_context_t *ctx)
715 {
716 	get_bytes_to_string(ctx, &(ctx->out.sf_pathlen), &(ctx->out.sf_path),
717 	    0);
718 	if (ctx->out.sf_path == NULL)
719 		return (-1);
720 	/*
721 	 * anchor the path because collapse_path needs it
722 	 */
723 	if (*(ctx->out.sf_path) != '/') {
724 		anchor_path(ctx->out.sf_path);
725 		ctx->out.sf_pathlen++;
726 	}
727 	ctx->out.sf_pathlen = collapse_path(ctx->out.sf_path,
728 	    ctx->out.sf_pathlen);
729 
730 	return (0);
731 }
732 
733 /*
734  * path attr token / AUT_XATPATH
735  *
736  * Format of path attr token:
737  *	token id		adr_char
738  *	string count		adr_int32
739  *	strings			adr_string
740  *
741  * the sequence of strings is converted to a single string with
742  * a blank separator replacing the EOS for all but the last
743  * string.
744  */
745 int
746 path_attr_token(parse_context_t *ctx)
747 {
748 	int	count, i;
749 	int	last_len;
750 	size_t	offset;
751 	char	*p;
752 
753 	adrm_int32(&(ctx->adr), &count, 1);
754 
755 	offset = ctx->out.sf_atpathlen;
756 	p = ctx->adr.adr_now;
757 	for (i = 0; i <= count; i++) {
758 		last_len = strlen(p);
759 		ctx->out.sf_atpathlen += last_len + 1;
760 		p += last_len + 1;
761 	}
762 	ctx->out.sf_atpath = realloc(ctx->out.sf_atpath, ctx->out.sf_atpathlen);
763 	ctx->out.sf_atpath += offset;
764 	p = ctx->out.sf_atpath;		/* save for fix up, below */
765 	(void) memcpy(ctx->out.sf_atpath, ctx->adr.adr_now,
766 	    ctx->out.sf_atpathlen - offset);
767 	ctx->out.sf_atpathlen--;
768 
769 	/* fix up: replace each eos except the last with ' ' */
770 
771 	for (i = 0; i < count; i++) {
772 		while (*p++ != '\0')
773 			;
774 		*(p - 1) = ' ';
775 	}
776 	return (0);
777 }
778 
779 
780 /*
781  * Format of System V IPC permission token:
782  *	System V IPC permission token id	adr_char
783  * 	uid					adr_int32
784  *	gid					adr_int32
785  *	cuid					adr_int32
786  *	cgid					adr_int32
787  *	mode					adr_int32
788  *	seq					adr_int32
789  *	key					adr_int32
790  */
791 int
792 s5_IPC_perm_token(parse_context_t *ctx)
793 {
794 	ctx->adr.adr_now += (7 * sizeof (int32_t));
795 	return (0);
796 }
797 
798 static void
799 common_process(parse_context_t *ctx)
800 {
801 	int32_t	ruid, rgid, egid, pid;
802 	uint32_t asid;
803 
804 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_pauid), 1);
805 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_peuid), 1);
806 	adrm_int32(&(ctx->adr), &egid, 1);
807 	adrm_int32(&(ctx->adr), &ruid, 1);
808 	adrm_int32(&(ctx->adr), &rgid, 1);
809 	adrm_int32(&(ctx->adr), &pid, 1);
810 	adrm_u_int32(&(ctx->adr), &asid, 1);
811 }
812 
813 /*
814  * Format of process32 token:
815  *	process token id	adr_char
816  *	auid			adr_int32
817  *	euid			adr_int32
818  *	egid 			adr_int32
819  * 	ruid			adr_int32
820  *	rgid			adr_int32
821  * 	pid			adr_int32
822  * 	sid			adr_int32
823  * 	termid			adr_int32*2
824  *
825  */
826 int
827 process32_token(parse_context_t *ctx)
828 {
829 	int32_t port, machine;
830 
831 	common_process(ctx);
832 
833 	adrm_int32(&(ctx->adr), &port, 1);
834 	adrm_int32(&(ctx->adr), &machine, 1);
835 
836 	return (0);
837 }
838 
839 /*
840  * Format of process32_ex token:
841  *	process token id	adr_char
842  *	auid			adr_int32
843  *	euid			adr_int32
844  *	egid 			adr_int32
845  * 	ruid			adr_int32
846  *	rgid			adr_int32
847  * 	pid			adr_int32
848  * 	sid			adr_int32
849  * 	termid			adr_int32*6
850  *
851  */
852 int
853 process32_ex_token(parse_context_t *ctx)
854 {
855 	int32_t port, type, addr[4];
856 
857 	common_process(ctx);
858 
859 	adrm_int32(&(ctx->adr), &port, 1);
860 	adrm_int32(&(ctx->adr), &type, 1);
861 	adrm_int32(&(ctx->adr), &addr[0], 4);
862 
863 	return (0);
864 }
865 
866 /*
867  * Format of process64 token:
868  *	process token id	adr_char
869  *	auid			adr_int32
870  *	euid			adr_int32
871  *	egid 			adr_int32
872  * 	ruid			adr_int32
873  *	rgid			adr_int32
874  * 	pid			adr_int32
875  * 	sid			adr_int32
876  * 	termid			adr_int64+adr_int32
877  *
878  */
879 int
880 process64_token(parse_context_t *ctx)
881 {
882 	int64_t port;
883 	int32_t machine;
884 
885 	common_process(ctx);
886 
887 	adrm_int64(&(ctx->adr), &port, 1);
888 	adrm_int32(&(ctx->adr), &machine, 1);
889 
890 	return (0);
891 }
892 
893 /*
894  * Format of process64 token:
895  *	process token id	adr_char
896  *	auid			adr_int32
897  *	euid			adr_int32
898  *	egid 			adr_int32
899  * 	ruid			adr_int32
900  *	rgid			adr_int32
901  * 	pid			adr_int32
902  * 	sid			adr_int32
903  * 	termid			adr_int64+5*adr_int32
904  *
905  */
906 int
907 process64_ex_token(parse_context_t *ctx)
908 {
909 	int64_t port;
910 	int32_t type, addr[4];
911 
912 	common_process(ctx);
913 
914 	adrm_int64(&(ctx->adr), &port, 1);
915 	adrm_int32(&(ctx->adr), &type, 1);
916 	adrm_int32(&(ctx->adr), &addr[0], 4);
917 
918 	return (0);
919 }
920 
921 /*
922  * Format of System V IPC token:
923  *	System V IPC token id	adr_char
924  *	System V IPC type	adr_char
925  *	object id		adr_int32
926  *
927  */
928 int
929 s5_IPC_token(parse_context_t *ctx)
930 {
931 	ctx->adr.adr_now += sizeof (char);
932 	ctx->adr.adr_now += sizeof (int32_t);
933 
934 	return (0);
935 }
936 
937 
938 /*
939  * Format of socket token:
940  *	socket_type		adrm_short
941  *	remote_port		adrm_short
942  *	remote_inaddr		adrm_int32
943  *
944  */
945 int
946 socket_token(parse_context_t *ctx)
947 {
948 	ctx->adr.adr_now += (2 * sizeof (short)) + sizeof (int32_t);
949 
950 	return (0);
951 }
952 
953 
954 /*
955  * Format of socket token:
956  *
957  */
958 int
959 socket_ex_token(parse_context_t *ctx)
960 {
961 	short	ip_size;
962 
963 	ctx->adr.adr_now += (2 * sizeof (short));
964 	adrm_short(&(ctx->adr), &ip_size, 1);
965 
966 	ctx->adr.adr_now += sizeof (short) + (ip_size * sizeof (char)) +
967 	    sizeof (short) + (ip_size * sizeof (char));
968 	return (0);
969 }
970 
971 
972 static void
973 common_subject(parse_context_t *ctx)
974 {
975 	int32_t	ruid, rgid, pid;
976 
977 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_auid), 1);
978 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_euid), 1);
979 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_egid), 1);
980 	adrm_int32(&(ctx->adr), &ruid, 1);
981 	adrm_int32(&(ctx->adr), &rgid, 1);
982 	adrm_int32(&(ctx->adr), &pid, 1);
983 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_asid), 1);
984 }
985 
986 /*
987  * Format of subject32 token:
988  *	subject token id	adr_char
989  *	auid			adr_int32
990  *	euid			adr_int32
991  *	egid 			adr_int32
992  * 	ruid			adr_int32
993  *	rgid			adr_int32
994  * 	pid			adr_int32
995  * 	sid			adr_int32
996  * 	termid			adr_int32*2
997  *
998  */
999 int
1000 subject32_token(parse_context_t *ctx)
1001 {
1002 	int32_t port;	/* not used in output */
1003 
1004 	common_subject(ctx);
1005 
1006 	adrm_int32(&(ctx->adr), &port, 1);
1007 	ctx->out.sf_tid.at_type = AU_IPv4;
1008 	adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]), 4);
1009 
1010 	return (0);
1011 }
1012 
1013 /*
1014  * Format of subject32_ex token:
1015  *	subject token id	adr_char
1016  *	auid			adr_int32
1017  *	euid			adr_int32
1018  *	egid 			adr_int32
1019  * 	ruid			adr_int32
1020  *	rgid			adr_int32
1021  * 	pid			adr_int32
1022  * 	sid			adr_int32
1023  * 	termid_addr		adr_int32*6
1024  *
1025  */
1026 int
1027 subject32_ex_token(parse_context_t *ctx)
1028 {
1029 	int32_t port;	/* not used in output */
1030 
1031 	common_subject(ctx);
1032 
1033 	adrm_int32(&(ctx->adr), &port, 1);
1034 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
1035 	adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]), 16);
1036 
1037 	return (0);
1038 }
1039 
1040 /*
1041  * Format of subject64 token:
1042  *	subject token id	adr_char
1043  *	auid			adr_int32
1044  *	euid			adr_int32
1045  *	egid 			adr_int32
1046  * 	ruid			adr_int32
1047  *	rgid			adr_int32
1048  * 	pid			adr_int32
1049  * 	sid			adr_int32
1050  * 	termid			adr_int64+adr_int32
1051  *
1052  */
1053 int
1054 subject64_token(parse_context_t *ctx)
1055 {
1056 	int64_t port;
1057 
1058 	common_subject(ctx);
1059 
1060 	adrm_int64(&(ctx->adr), &port, 1);
1061 	ctx->out.sf_tid.at_type = AU_IPv4;
1062 	adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]), 4);
1063 
1064 	return (0);
1065 }
1066 
1067 /*
1068  * Format of subject64 token:
1069  *	subject token id	adr_char
1070  *	auid			adr_int32
1071  *	euid			adr_int32
1072  *	egid 			adr_int32
1073  * 	ruid			adr_int32
1074  *	rgid			adr_int32
1075  * 	pid			adr_int32
1076  * 	sid			adr_int32
1077  * 	termid			adr_int64+5*adr_int32
1078  *
1079  */
1080 int
1081 subject64_ex_token(parse_context_t *ctx)
1082 {
1083 	int64_t port;
1084 
1085 	common_subject(ctx);
1086 
1087 	adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_asid), 1);
1088 	adrm_int64(&(ctx->adr), &port, 1);
1089 	adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
1090 	adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]), 16);
1091 
1092 	return (0);
1093 }
1094 
1095 
1096 int
1097 xatom_token(parse_context_t *ctx)
1098 {
1099 	skip_bytes(ctx);
1100 
1101 	return (0);
1102 }
1103 
1104 
1105 int
1106 xselect_token(parse_context_t *ctx)
1107 {
1108 	skip_bytes(ctx);
1109 	skip_bytes(ctx);
1110 	skip_bytes(ctx);
1111 
1112 	return (0);
1113 }
1114 
1115 /*
1116  * anchor a path name with a slash
1117  * assume we have enough space
1118  */
1119 static void
1120 anchor_path(char *path)
1121 {
1122 
1123 	(void) memmove((void *)(path + 1), (void *)path, strlen(path) + 1);
1124 	*path = '/';
1125 }
1126 
1127 
1128 /*
1129  * copy path to collapsed path.
1130  * collapsed path does not contain:
1131  *	successive slashes
1132  *	instances of dot-slash
1133  *	instances of dot-dot-slash
1134  * passed path must be anchored with a '/'
1135  */
1136 static size_t
1137 collapse_path(char *s, size_t ls)
1138 {
1139 	int	id;	/* index of where we are in destination string */
1140 	int	is;	/* index of where we are in source string */
1141 	int	slashseen;	/* have we seen a slash */
1142 
1143 	ls++; /* source length including '\0' */
1144 
1145 	slashseen = 0;
1146 	for (is = 0, id = 0; is < ls; is++) {
1147 		if (s[is] == '\0') {
1148 			if (id > 1 && s[id-1] == '/') {
1149 				--id;
1150 			}
1151 			s[id++] = '\0';
1152 			break;
1153 		}
1154 		/* previous character was a / */
1155 		if (slashseen) {
1156 			if (s[is] == '/')
1157 				continue;	/* another slash, ignore it */
1158 		} else if (s[is] == '/') {
1159 			/* we see a /, just copy it and try again */
1160 			slashseen = 1;
1161 			s[id++] = '/';
1162 			continue;
1163 		}
1164 		/* /./ seen */
1165 		if (s[is] == '.' && s[is+1] == '/') {
1166 			is += 1;
1167 			continue;
1168 		}
1169 		/* XXX/. seen */
1170 		if (s[is] == '.' && s[is+1] == '\0') {
1171 			if (id > 1)
1172 				id--;
1173 			continue;
1174 		}
1175 		/* XXX/.. seen */
1176 		if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '\0') {
1177 			is += 1;
1178 			if (id > 0)
1179 				id--;
1180 			while (id > 0 && s[--id] != '/')
1181 				;
1182 			id++;
1183 			continue;
1184 		}
1185 		/* XXX/../ seen */
1186 		if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '/') {
1187 			is += 2;
1188 			if (id > 0)
1189 				id--;
1190 			while (id > 0 && s[--id] != '/')
1191 				;
1192 			id++;
1193 			continue;
1194 		}
1195 		while (is < ls && (s[id++] = s[is++]) != '/')
1196 			;
1197 		is--;
1198 	}
1199 	return ((size_t)id - 1);
1200 }
1201 
1202 /*
1203  * for tokens with sub-fields that include a length, this
1204  * skips the sub-field.
1205  */
1206 
1207 static void
1208 skip_bytes(parse_context_t *ctx)
1209 {
1210 	ushort_t	c;
1211 
1212 	adrm_u_short(&(ctx->adr), &c, 1);
1213 	ctx->adr.adr_now += c;
1214 }
1215 
1216 static void
1217 skip_string(parse_context_t *ctx)
1218 {
1219 	char	c;
1220 
1221 	do {
1222 		adrm_char(&(ctx->adr), &c, 1);
1223 	} while (c != (char)0);
1224 }
1225 
1226 /*
1227  * add a byte to specified length so there can be a prefix of
1228  * '/' added (if needed for paths).  Another is added for '\0'
1229  *
1230  * if offset is zero, new data overwrites old, if any.  Otherwise
1231  * new data is appended to the end.
1232  */
1233 
1234 static void
1235 get_bytes_to_string(parse_context_t *ctx, size_t *l, char **p,
1236     size_t offset)
1237 {
1238 	ushort_t	len;
1239 	char		*bp;
1240 
1241 	adrm_u_short(&(ctx->adr), &len, 1);
1242 
1243 	len++;	/* in case need to add '/' prefix */
1244 	*p = realloc(*p, 1 + (size_t)len + offset);
1245 	if (*p == NULL) {
1246 		perror("audit_sysudp.so");
1247 		return;
1248 	}
1249 	if (offset > 0)
1250 		offset--;	/* overwrite end of string */
1251 
1252 	*l = (size_t)len - 2 + offset;
1253 
1254 	bp = *p + offset;
1255 	adrm_char(&(ctx->adr), bp, len - 1);
1256 	*(bp + len - 1) = '\0';
1257 }
1258 
1259 
1260 /*
1261  * Format of host token:
1262  *	host  		adr_uint32
1263  */
1264 int
1265 host_token(parse_context_t *ctx)
1266 {
1267 	ctx->adr.adr_now += sizeof (int32_t);
1268 
1269 	return (0);
1270 }
1271 
1272 /*
1273  * Format of useofauth token:
1274  *	uauth token id		adr_char
1275  * 	uauth			adr_string
1276  *
1277  */
1278 int
1279 useofauth_token(parse_context_t *ctx)
1280 {
1281 	get_bytes_to_string(ctx, &(ctx->out.sf_uauthlen),
1282 	    &(ctx->out.sf_uauth), 0);
1283 
1284 	return (0);
1285 }
1286 
1287 /*
1288  * Format of zonename token:
1289  *	zonename token id		adr_char
1290  * 	zonename			adr_string
1291  *
1292  */
1293 int
1294 zonename_token(parse_context_t *ctx)
1295 {
1296 	get_bytes_to_string(ctx,
1297 	    &(ctx->out.sf_zonelen),
1298 	    &(ctx->out.sf_zonename),
1299 	    0);
1300 
1301 	return (0);
1302 }
1303 
1304 /*
1305  * Format of fmri token:
1306  *	fmri token id		adr_char
1307  *	fmri			adr_string
1308  */
1309 int
1310 fmri_token(parse_context_t *ctx)
1311 {
1312 	skip_bytes(ctx);
1313 
1314 	return (0);
1315 }
1316 
1317 int
1318 xcolormap_token(parse_context_t *ctx)
1319 {
1320 	return (xgeneric(ctx));
1321 }
1322 
1323 int
1324 xcursor_token(parse_context_t *ctx)
1325 {
1326 	return (xgeneric(ctx));
1327 }
1328 
1329 int
1330 xfont_token(parse_context_t *ctx)
1331 {
1332 	return (xgeneric(ctx));
1333 }
1334 
1335 int
1336 xgc_token(parse_context_t *ctx)
1337 {
1338 	return (xgeneric(ctx));
1339 }
1340 
1341 int
1342 xpixmap_token(parse_context_t *ctx)
1343 {
1344 	return (xgeneric(ctx));
1345 }
1346 
1347 int
1348 xwindow_token(parse_context_t *ctx)
1349 {
1350 	return (xgeneric(ctx));
1351 }
1352 /*
1353  * Format of xgeneric token:
1354  *	XID			adr_int32
1355  *	creator UID		adr_int32
1356  *
1357  * Includes:  xcolormap, xcursor, xfont, xgc, xpixmap, and xwindow
1358  */
1359 static int
1360 xgeneric(parse_context_t *ctx)
1361 {
1362 	ctx->adr.adr_now += 2 * sizeof (int32_t);
1363 
1364 	return (0);
1365 }
1366 /*
1367  * Format of xproperty token:
1368  *	XID			adr_int32
1369  *	creator UID		adr_int32
1370  *	atom string		adr_string
1371  */
1372 int
1373 xproperty_token(parse_context_t *ctx)
1374 {
1375 	ctx->adr.adr_now += 2 * sizeof (int32_t);
1376 
1377 	return (0);
1378 }
1379 /*
1380  * Format of xclient token:
1381  * 	xclient id		adr_int32
1382  */
1383 int
1384 xclient_token(parse_context_t *ctx)
1385 {
1386 	ctx->adr.adr_now += sizeof (int32_t);
1387 
1388 	return (0);
1389 }
1390 
1391 /*
1392  * -----------------------------------------------------------------------
1393  * privilege_token()	: Process privilege token and display contents
1394  *
1395  * Format of privilege token:
1396  *	privilege token id	adr_char
1397  *	privilege type		adr_string
1398  *	privilege		adr_string
1399  * -----------------------------------------------------------------------
1400  */
1401 
1402 int
1403 privilege_token(parse_context_t *ctx)
1404 {
1405 	skip_bytes(ctx);
1406 	skip_bytes(ctx);
1407 
1408 	return (0);
1409 }
1410 
1411 
1412 /*
1413  * Format of label token:
1414  *	label ID                1 byte
1415  *	compartment length      1 byte
1416  *	classification          2 bytes
1417  *	compartment words       <compartment length> * 4 bytes
1418  */
1419 int
1420 label_token(parse_context_t *ctx)
1421 {
1422 	char	c;
1423 
1424 	ctx->adr.adr_now += sizeof (char);	/* label ID */
1425 	adrm_char(&(ctx->adr), &c, 1);
1426 
1427 	ctx->adr.adr_now += sizeof (ushort_t);	/* classification */
1428 	ctx->adr.adr_now += 4 * c;		/* compartments */
1429 
1430 	return (0);
1431 }
1432 
1433 /*
1434  * Format of useofpriv token:
1435  *	priv_type			adr_char
1436  *	priv_set_t			adr_short
1437  *	priv_set			adr_char*(sizeof (priv_set_t))
1438  */
1439 int
1440 useofpriv_token(parse_context_t *ctx)
1441 {
1442 	ctx->adr.adr_now += sizeof (char); /* success / fail */
1443 	skip_bytes(ctx);
1444 
1445 	return (0);
1446 }
1447