systoken.c revision 1780:baba427bca27
1251886Speter/*
2251886Speter * CDDL HEADER START
3251886Speter *
4251886Speter * The contents of this file are subject to the terms of the
5299742Sdim * Common Development and Distribution License (the "License").
6251886Speter * You may not use this file except in compliance with the License.
7291804Sbdrewery *
8251886Speter * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9251886Speter * 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 2006 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
55static FILE	*dbfp;			/* debug file */
56#endif
57
58static void	anchor_path(char *);
59static size_t	collapse_path(char *, size_t);
60static void	get_bytes_to_string(parse_context_t *, size_t *, char **,
61		    size_t);
62static void	skip_bytes(parse_context_t *);
63static void	skip_string(parse_context_t *);
64static 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
82int
83parse_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 */
112int
113file_token(parse_context_t *ctx)
114{
115
116	return (-1);
117}
118
119/* ARGSUSED */
120int
121file64_token(parse_context_t *ctx)
122{
123	return (-1);
124}
125
126static void
127common_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 */
138int
139header_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
148int
149header32_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
164int
165header64_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
180int
181header64_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
199int
200trailer_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 */
224int
225arbitrary_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 */
262int
263opaque_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 */
277int
278return_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 */
297int
298return_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 */
317int
318sequence_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 */
330int
331text_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 */
381int
382tid_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 */
407int
408ip_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 */
422int
423ip_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 */
445int
446ip_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 */
463int
464iport_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 */
478int
479group_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 */
493int
494newgroup_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 */
513int
514argument32_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 */
530int
531argument64_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
539int
540acl_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 */
558int
559attribute_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 */
577int
578attribute32_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 */
596int
597attribute64_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 */
622int
623cmd_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 */
649int
650exit_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 */
668int
669exec_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 */
688int
689exec_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 */
703int
704liaison_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 */
716int
717path_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 */
748int
749path_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 */
795int
796s5_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
806static void
807common_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 */
834int
835process32_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 */
860int
861process32_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 */
887int
888process64_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 */
914int
915process64_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 */
936int
937s5_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 */
953int
954socket_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 */
966int
967socket_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
982static void
983common_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 */
1009int
1010subject32_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 */
1036int
1037subject32_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 */
1063int
1064subject64_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 */
1090int
1091subject64_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
1106int
1107xatom_token(parse_context_t *ctx)
1108{
1109	skip_bytes(ctx);
1110
1111	return (0);
1112}
1113
1114
1115int
1116xselect_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 */
1129static void
1130anchor_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 */
1146static size_t
1147collapse_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
1214static void
1215skip_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
1223static void
1224skip_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
1241static void
1242get_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 */
1271int
1272host_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 */
1285int
1286useofauth_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 */
1300int
1301zonename_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/*
1312 * Format of fmri token:
1313 *	fmri token id		adr_char
1314 *	fmri			adr_string
1315 */
1316int
1317fmri_token(parse_context_t *ctx)
1318{
1319	skip_bytes(ctx);
1320
1321	return (0);
1322}
1323
1324int
1325xcolormap_token(parse_context_t *ctx)
1326{
1327	return (xgeneric(ctx));
1328}
1329
1330int
1331xcursor_token(parse_context_t *ctx)
1332{
1333	return (xgeneric(ctx));
1334}
1335
1336int
1337xfont_token(parse_context_t *ctx)
1338{
1339	return (xgeneric(ctx));
1340}
1341
1342int
1343xgc_token(parse_context_t *ctx)
1344{
1345	return (xgeneric(ctx));
1346}
1347
1348int
1349xpixmap_token(parse_context_t *ctx)
1350{
1351	return (xgeneric(ctx));
1352}
1353
1354int
1355xwindow_token(parse_context_t *ctx)
1356{
1357	return (xgeneric(ctx));
1358}
1359/*
1360 * Format of xgeneric token:
1361 *	XID			adr_int32
1362 *	creator UID		adr_int32
1363 *
1364 * Includes:  xcolormap, xcursor, xfont, xgc, xpixmap, and xwindow
1365 */
1366static int
1367xgeneric(parse_context_t *ctx)
1368{
1369	ctx->adr.adr_now += 2 * sizeof (int32_t);
1370
1371	return (0);
1372}
1373/*
1374 * Format of xproperty token:
1375 *	XID			adr_int32
1376 *	creator UID		adr_int32
1377 *	atom string		adr_string
1378 */
1379int
1380xproperty_token(parse_context_t *ctx)
1381{
1382	ctx->adr.adr_now += 2 * sizeof (int32_t);
1383
1384	return (0);
1385}
1386/*
1387 * Format of xclient token:
1388 * 	xclient id		adr_int32
1389 */
1390int
1391xclient_token(parse_context_t *ctx)
1392{
1393	ctx->adr.adr_now += sizeof (int32_t);
1394
1395	return (0);
1396}
1397
1398/*
1399 * -----------------------------------------------------------------------
1400 * privilege_token()	: Process privilege token and display contents
1401 *
1402 * Format of privilege token:
1403 *	privilege token id	adr_char
1404 *	privilege type		adr_string
1405 *	privilege		adr_string
1406 * -----------------------------------------------------------------------
1407 */
1408
1409int
1410privilege_token(parse_context_t *ctx)
1411{
1412	skip_bytes(ctx);
1413	skip_bytes(ctx);
1414
1415	return (0);
1416}
1417
1418
1419/*
1420 * Format of slabel token:
1421 *	label ID                1 byte
1422 *	compartment length      1 byte
1423 *	classification          2 bytes
1424 *	compartment words       <compartment length> * 4 bytes
1425 */
1426int
1427slabel_token(parse_context_t *ctx)
1428{
1429	char	c;
1430
1431	ctx->adr.adr_now += sizeof (char);	/* label ID */
1432	adrm_char(&(ctx->adr), &c, 1);
1433
1434	ctx->adr.adr_now += sizeof (ushort_t);	/* classification */
1435	ctx->adr.adr_now += 4 * c;		/* compartments */
1436
1437	return (0);
1438}
1439
1440/*
1441 * Format of useofpriv token:
1442 *	priv_type			adr_char
1443 *	priv_set_t			adr_short
1444 *	priv_set			adr_char*(sizeof (priv_set_t))
1445 */
1446int
1447useofpriv_token(parse_context_t *ctx)
1448{
1449	ctx->adr.adr_now += sizeof (char); /* success / fail */
1450	skip_bytes(ctx);
1451
1452	return (0);
1453}
1454