1/*-
2 * Copyright (c) 2004-2009 Apple Inc.
3 * Copyright (c) 2005 SPARTA, Inc.
4 * All rights reserved.
5 *
6 * This code was developed in part by Robert N. M. Watson, Senior Principal
7 * Scientist, SPARTA, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1.  Redistributions of source code must retain the above copyright
13 *     notice, this list of conditions and the following disclaimer.
14 * 2.  Redistributions in binary form must reproduce the above copyright
15 *     notice, this list of conditions and the following disclaimer in the
16 *     documentation and/or other materials provided with the distribution.
17 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
18 *     its contributors may be used to endorse or promote products derived
19 *     from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_token.c#99 $
34 */
35
36#include <sys/types.h>
37
38#include <config/config.h>
39
40#ifdef USE_ENDIAN_H
41#include <endian.h>
42#endif
43#ifdef USE_SYS_ENDIAN_H
44#include <sys/endian.h>
45#endif
46#ifdef USE_MACHINE_ENDIAN_H
47#include <machine/endian.h>
48#endif
49#ifdef USE_COMPAT_ENDIAN_H
50#include <compat/endian.h>
51#endif
52#ifdef USE_COMPAT_ENDIAN_ENC_H
53#include <compat/endian_enc.h>
54#endif
55
56#ifdef HAVE_FULL_QUEUE_H
57#include <sys/queue.h>
58#else /* !HAVE_FULL_QUEUE_H */
59#include <compat/queue.h>
60#endif /* !HAVE_FULL_QUEUE_H */
61
62#include <sys/socket.h>
63#include <sys/time.h>
64#include <sys/un.h>
65
66#include <sys/ipc.h>
67
68#include <netinet/in.h>
69#include <netinet/in_systm.h>
70#include <netinet/ip.h>
71
72#include <assert.h>
73#include <errno.h>
74#include <string.h>
75#include <stdlib.h>
76#include <unistd.h>
77
78#include <bsm/audit_internal.h>
79#include <bsm/libbsm.h>
80
81#define	GET_TOKEN_AREA(t, dptr, length) do {				\
82	(t) = malloc(sizeof(token_t));					\
83	if ((t) != NULL) {						\
84		(t)->len = (length);					\
85		(dptr) = (t->t_data) = calloc((length), sizeof(u_char)); \
86		if ((dptr) == NULL) {					\
87			free(t);					\
88			(t) = NULL;					\
89		}							\
90	} else								\
91		(dptr) = NULL;						\
92	assert((t) == NULL || (dptr) != NULL);				\
93} while (0)
94
95/*
96 * token ID                1 byte
97 * success/failure         1 byte
98 * privstrlen              2 bytes
99 * privstr                 N bytes + 1 (\0 byte)
100 */
101token_t *
102au_to_upriv(char sorf, char *priv)
103{
104	u_int16_t textlen;
105	u_char *dptr;
106	token_t *t;
107
108	textlen = strlen(priv) + 1;
109	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_char) +
110	    sizeof(u_int16_t) + textlen);
111	if (t == NULL)
112		return (NULL);
113	ADD_U_CHAR(dptr, AUT_UPRIV);
114	ADD_U_CHAR(dptr, sorf);
115	ADD_U_INT16(dptr, textlen);
116	ADD_STRING(dptr, priv, textlen);
117	return (t);
118}
119
120/*
121 * token ID		1 byte
122 * privtstrlen		2 bytes
123 * privtstr		N bytes + 1
124 * privstrlen		2 bytes
125 * privstr		N bytes + 1
126 */
127token_t *
128au_to_privset(char *privtypestr, char *privstr)
129{
130	u_int16_t	 type_len, priv_len;
131	u_char		*dptr;
132	token_t		*t;
133
134	type_len = strlen(privtypestr) + 1;
135	priv_len = strlen(privstr) + 1;
136	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
137	    sizeof(u_int16_t) + type_len + priv_len);
138	if (t == NULL)
139		return (NULL);
140	ADD_U_CHAR(dptr, AUT_PRIV);
141	ADD_U_INT16(dptr, type_len);
142	ADD_STRING(dptr, privtypestr, type_len);
143	ADD_U_INT16(dptr, priv_len);
144	ADD_STRING(dptr, privstr, priv_len);
145	return (t);
146}
147
148/*
149 * token ID                1 byte
150 * argument #              1 byte
151 * argument value          4 bytes/8 bytes (32-bit/64-bit value)
152 * text length             2 bytes
153 * text                    N bytes + 1 terminating NULL byte
154 */
155token_t *
156au_to_arg32(char n, const char *text, u_int32_t v)
157{
158	token_t *t;
159	u_char *dptr = NULL;
160	u_int16_t textlen;
161
162	textlen = strlen(text);
163	textlen += 1;
164
165	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t) +
166	    sizeof(u_int16_t) + textlen);
167	if (t == NULL)
168		return (NULL);
169
170	ADD_U_CHAR(dptr, AUT_ARG32);
171	ADD_U_CHAR(dptr, n);
172	ADD_U_INT32(dptr, v);
173	ADD_U_INT16(dptr, textlen);
174	ADD_STRING(dptr, text, textlen);
175
176	return (t);
177}
178
179token_t *
180au_to_arg64(char n, const char *text, u_int64_t v)
181{
182	token_t *t;
183	u_char *dptr = NULL;
184	u_int16_t textlen;
185
186	textlen = strlen(text);
187	textlen += 1;
188
189	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t) +
190	    sizeof(u_int16_t) + textlen);
191	if (t == NULL)
192		return (NULL);
193
194	ADD_U_CHAR(dptr, AUT_ARG64);
195	ADD_U_CHAR(dptr, n);
196	ADD_U_INT64(dptr, v);
197	ADD_U_INT16(dptr, textlen);
198	ADD_STRING(dptr, text, textlen);
199
200	return (t);
201}
202
203token_t *
204au_to_arg(char n, const char *text, u_int32_t v)
205{
206
207	return (au_to_arg32(n, text, v));
208}
209
210#if defined(_KERNEL) || defined(KERNEL)
211/*
212 * token ID                1 byte
213 * file access mode        4 bytes
214 * owner user ID           4 bytes
215 * owner group ID          4 bytes
216 * file system ID          4 bytes
217 * node ID                 8 bytes
218 * device                  4 bytes/8 bytes (32-bit/64-bit)
219 */
220token_t *
221au_to_attr32(struct vnode_au_info *vni)
222{
223	token_t *t;
224	u_char *dptr = NULL;
225	u_int16_t pad0_16 = 0;
226	u_int32_t pad0_32 = 0;
227
228	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
229	    3 * sizeof(u_int32_t) + sizeof(u_int64_t) + sizeof(u_int32_t));
230	if (t == NULL)
231		return (NULL);
232
233	ADD_U_CHAR(dptr, AUT_ATTR32);
234
235	/*
236	 * BSD defines the size for the file mode as 2 bytes; BSM defines 4
237	 * so pad with 0.
238	 *
239	 * XXXRW: Possibly should be conditionally compiled.
240	 *
241	 * XXXRW: Should any conversions take place on the mode?
242	 */
243	ADD_U_INT16(dptr, pad0_16);
244	ADD_U_INT16(dptr, vni->vn_mode);
245
246	ADD_U_INT32(dptr, vni->vn_uid);
247	ADD_U_INT32(dptr, vni->vn_gid);
248	ADD_U_INT32(dptr, vni->vn_fsid);
249
250	/*
251	 * Some systems use 32-bit file ID's, others use 64-bit file IDs.
252	 * Attempt to handle both, and let the compiler sort it out.  If we
253	 * could pick this out at compile-time, it would be better, so as to
254	 * avoid the else case below.
255	 */
256	if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
257		ADD_U_INT32(dptr, pad0_32);
258		ADD_U_INT32(dptr, vni->vn_fileid);
259	} else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
260		ADD_U_INT64(dptr, vni->vn_fileid);
261	else
262		ADD_U_INT64(dptr, 0LL);
263
264	ADD_U_INT32(dptr, vni->vn_dev);
265
266	return (t);
267}
268
269token_t *
270au_to_attr64(struct vnode_au_info *vni)
271{
272	token_t *t;
273	u_char *dptr = NULL;
274	u_int16_t pad0_16 = 0;
275	u_int32_t pad0_32 = 0;
276
277	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
278	    3 * sizeof(u_int32_t) + sizeof(u_int64_t) * 2);
279	if (t == NULL)
280		return (NULL);
281
282	ADD_U_CHAR(dptr, AUT_ATTR64);
283
284	/*
285	 * BSD defines the size for the file mode as 2 bytes; BSM defines 4
286	 * so pad with 0.
287	 *
288	 * XXXRW: Possibly should be conditionally compiled.
289	 *
290	 * XXXRW: Should any conversions take place on the mode?
291	 */
292	ADD_U_INT16(dptr, pad0_16);
293	ADD_U_INT16(dptr, vni->vn_mode);
294
295	ADD_U_INT32(dptr, vni->vn_uid);
296	ADD_U_INT32(dptr, vni->vn_gid);
297	ADD_U_INT32(dptr, vni->vn_fsid);
298
299	/*
300	 * Some systems use 32-bit file ID's, other's use 64-bit file IDs.
301	 * Attempt to handle both, and let the compiler sort it out.  If we
302	 * could pick this out at compile-time, it would be better, so as to
303	 * avoid the else case below.
304	 */
305	if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
306		ADD_U_INT32(dptr, pad0_32);
307		ADD_U_INT32(dptr, vni->vn_fileid);
308	} else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
309		ADD_U_INT64(dptr, vni->vn_fileid);
310	else
311		ADD_U_INT64(dptr, 0LL);
312
313	ADD_U_INT64(dptr, vni->vn_dev);
314
315	return (t);
316}
317
318token_t *
319au_to_attr(struct vnode_au_info *vni)
320{
321
322	return (au_to_attr32(vni));
323}
324#endif /* !(defined(_KERNEL) || defined(KERNEL) */
325
326/*
327 * token ID                1 byte
328 * how to print            1 byte
329 * basic unit              1 byte
330 * unit count              1 byte
331 * data items              (depends on basic unit)
332 */
333token_t *
334au_to_data(char unit_print, char unit_type, char unit_count, const char *p)
335{
336	token_t *t;
337	u_char *dptr = NULL;
338	size_t datasize, totdata;
339
340	/* Determine the size of the basic unit. */
341	switch (unit_type) {
342	case AUR_BYTE:
343	/* case AUR_CHAR: */
344		datasize = AUR_BYTE_SIZE;
345		break;
346
347	case AUR_SHORT:
348		datasize = AUR_SHORT_SIZE;
349		break;
350
351	case AUR_INT32:
352	/* case AUR_INT: */
353		datasize = AUR_INT32_SIZE;
354		break;
355
356	case AUR_INT64:
357		datasize = AUR_INT64_SIZE;
358		break;
359
360	default:
361		errno = EINVAL;
362		return (NULL);
363	}
364
365	totdata = datasize * unit_count;
366
367	GET_TOKEN_AREA(t, dptr, 4 * sizeof(u_char) + totdata);
368	if (t == NULL)
369		return (NULL);
370
371	/*
372	 * XXXRW: We should be byte-swapping each data item for multi-byte
373	 * types.
374	 */
375	ADD_U_CHAR(dptr, AUT_DATA);
376	ADD_U_CHAR(dptr, unit_print);
377	ADD_U_CHAR(dptr, unit_type);
378	ADD_U_CHAR(dptr, unit_count);
379	ADD_MEM(dptr, p, totdata);
380
381	return (t);
382}
383
384
385/*
386 * token ID                1 byte
387 * status		   4 bytes
388 * return value            4 bytes
389 */
390token_t *
391au_to_exit(int retval, int err)
392{
393	token_t *t;
394	u_char *dptr = NULL;
395
396	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t));
397	if (t == NULL)
398		return (NULL);
399
400	ADD_U_CHAR(dptr, AUT_EXIT);
401	ADD_U_INT32(dptr, err);
402	ADD_U_INT32(dptr, retval);
403
404	return (t);
405}
406
407/*
408 */
409token_t *
410au_to_groups(int *groups)
411{
412
413	return (au_to_newgroups(AUDIT_MAX_GROUPS, (gid_t *)groups));
414}
415
416/*
417 * token ID                1 byte
418 * number groups           2 bytes
419 * group list              count * 4 bytes
420 */
421token_t *
422au_to_newgroups(u_int16_t n, gid_t *groups)
423{
424	token_t *t;
425	u_char *dptr = NULL;
426	int i;
427
428	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
429	    n * sizeof(u_int32_t));
430	if (t == NULL)
431		return (NULL);
432
433	ADD_U_CHAR(dptr, AUT_NEWGROUPS);
434	ADD_U_INT16(dptr, n);
435	for (i = 0; i < n; i++)
436		ADD_U_INT32(dptr, groups[i]);
437
438	return (t);
439}
440
441/*
442 * token ID                1 byte
443 * internet address        4 bytes
444 */
445token_t *
446au_to_in_addr(struct in_addr *internet_addr)
447{
448	token_t *t;
449	u_char *dptr = NULL;
450
451	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(uint32_t));
452	if (t == NULL)
453		return (NULL);
454
455	ADD_U_CHAR(dptr, AUT_IN_ADDR);
456	ADD_MEM(dptr, &internet_addr->s_addr, sizeof(uint32_t));
457
458	return (t);
459}
460
461/*
462 * token ID                1 byte
463 * address type/length     4 bytes
464 * address                16 bytes
465 */
466token_t *
467au_to_in_addr_ex(struct in6_addr *internet_addr)
468{
469	token_t *t;
470	u_char *dptr = NULL;
471	u_int32_t type = AU_IPv6;
472
473	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(uint32_t));
474	if (t == NULL)
475		return (NULL);
476
477	ADD_U_CHAR(dptr, AUT_IN_ADDR_EX);
478	ADD_U_INT32(dptr, type);
479	ADD_MEM(dptr, internet_addr, 4 * sizeof(uint32_t));
480
481	return (t);
482}
483
484/*
485 * token ID                1 byte
486 * ip header		   20 bytes
487 *
488 * The IP header should be submitted in network byte order.
489 */
490token_t *
491au_to_ip(struct ip *ip)
492{
493	token_t *t;
494	u_char *dptr = NULL;
495
496	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(struct ip));
497	if (t == NULL)
498		return (NULL);
499
500	ADD_U_CHAR(dptr, AUT_IP);
501	ADD_MEM(dptr, ip, sizeof(struct ip));
502
503	return (t);
504}
505
506/*
507 * token ID                1 byte
508 * object ID type          1 byte
509 * object ID               4 bytes
510 */
511token_t *
512au_to_ipc(char type, int id)
513{
514	token_t *t;
515	u_char *dptr = NULL;
516
517	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
518	if (t == NULL)
519		return (NULL);
520
521	ADD_U_CHAR(dptr, AUT_IPC);
522	ADD_U_CHAR(dptr, type);
523	ADD_U_INT32(dptr, id);
524
525	return (t);
526}
527
528/*
529 * token ID                1 byte
530 * owner user ID           4 bytes
531 * owner group ID          4 bytes
532 * creator user ID         4 bytes
533 * creator group ID        4 bytes
534 * access mode             4 bytes
535 * slot sequence #         4 bytes
536 * key                     4 bytes
537 */
538token_t *
539au_to_ipc_perm(struct ipc_perm *perm)
540{
541	token_t *t;
542	u_char *dptr = NULL;
543	u_int16_t pad0 = 0;
544
545	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 12 * sizeof(u_int16_t) +
546	    sizeof(u_int32_t));
547	if (t == NULL)
548		return (NULL);
549
550	ADD_U_CHAR(dptr, AUT_IPC_PERM);
551
552	/*
553	 * Systems vary significantly in what types they use in struct
554	 * ipc_perm; at least a few still use 16-bit uid's and gid's, so
555	 * allow for that, as BSM define 32-bit values here.
556	 * Some systems define the sizes for ipc_perm members as 2 bytes;
557	 * BSM defines 4 so pad with 0.
558	 *
559	 * XXXRW: Possibly shoulid be conditionally compiled, and more cases
560	 * need to be handled.
561	 */
562	if (sizeof(perm->uid) != sizeof(u_int32_t)) {
563		ADD_U_INT16(dptr, pad0);
564		ADD_U_INT16(dptr, perm->uid);
565		ADD_U_INT16(dptr, pad0);
566		ADD_U_INT16(dptr, perm->gid);
567		ADD_U_INT16(dptr, pad0);
568		ADD_U_INT16(dptr, perm->cuid);
569		ADD_U_INT16(dptr, pad0);
570		ADD_U_INT16(dptr, perm->cgid);
571	} else {
572		ADD_U_INT32(dptr, perm->uid);
573		ADD_U_INT32(dptr, perm->gid);
574		ADD_U_INT32(dptr, perm->cuid);
575		ADD_U_INT32(dptr, perm->cgid);
576	}
577
578	ADD_U_INT16(dptr, pad0);
579	ADD_U_INT16(dptr, perm->mode);
580
581	ADD_U_INT16(dptr, pad0);
582
583#ifdef HAVE_IPC_PERM___SEQ
584	ADD_U_INT16(dptr, perm->__seq);
585#else	/* HAVE_IPC_PERM___SEQ */
586#ifdef  HAVE_IPC_PERM__SEQ
587	ADD_U_INT16(dptr, perm->_seq);
588#else	/* HAVE_IPC_PERM__SEQ */
589	ADD_U_INT16(dptr, perm->seq);
590#endif	/* HAVE_IPC_PERM__SEQ */
591#endif	/* HAVE_IPC_PERM___SEQ */
592
593#ifdef HAVE_IPC_PERM___KEY
594	ADD_U_INT32(dptr, perm->__key);
595#else	/* HAVE_IPC_PERM___KEY */
596#ifdef  HAVE_IPC_PERM__KEY
597	ADD_U_INT32(dptr, perm->_key);
598#else	/* HAVE_IPC_PERM__KEY */
599	ADD_U_INT32(dptr, perm->key);
600#endif	/* HAVE_IPC_PERM__KEY */
601#endif	/* HAVE_IPC_PERM___KEY */
602
603	return (t);
604}
605
606/*
607 * token ID                1 byte
608 * port IP address         2 bytes
609 */
610token_t *
611au_to_iport(u_int16_t iport)
612{
613	token_t *t;
614	u_char *dptr = NULL;
615
616	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t));
617	if (t == NULL)
618		return (NULL);
619
620	ADD_U_CHAR(dptr, AUT_IPORT);
621	ADD_U_INT16(dptr, iport);
622
623	return (t);
624}
625
626/*
627 * token ID                1 byte
628 * size                    2 bytes
629 * data                    size bytes
630 */
631token_t *
632au_to_opaque(const char *data, u_int16_t bytes)
633{
634	token_t *t;
635	u_char *dptr = NULL;
636
637	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + bytes);
638	if (t == NULL)
639		return (NULL);
640
641	ADD_U_CHAR(dptr, AUT_OPAQUE);
642	ADD_U_INT16(dptr, bytes);
643	ADD_MEM(dptr, data, bytes);
644
645	return (t);
646}
647
648/*
649 * token ID                1 byte
650 * seconds of time         4 bytes
651 * milliseconds of time    4 bytes
652 * file name len           2 bytes
653 * file pathname           N bytes + 1 terminating NULL byte
654 */
655token_t *
656au_to_file(const char *file, struct timeval tm)
657{
658	token_t *t;
659	u_char *dptr = NULL;
660	u_int16_t filelen;
661	u_int32_t timems;
662
663	filelen = strlen(file);
664	filelen += 1;
665
666	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t) +
667	    sizeof(u_int16_t) + filelen);
668	if (t == NULL)
669		return (NULL);
670
671	timems = tm.tv_usec/1000;
672
673	ADD_U_CHAR(dptr, AUT_OTHER_FILE32);
674	ADD_U_INT32(dptr, tm.tv_sec);
675	ADD_U_INT32(dptr, timems);	/* We need time in ms. */
676	ADD_U_INT16(dptr, filelen);
677	ADD_STRING(dptr, file, filelen);
678
679	return (t);
680}
681
682/*
683 * token ID                1 byte
684 * text length             2 bytes
685 * text                    N bytes + 1 terminating NULL byte
686 */
687token_t *
688au_to_text(const char *text)
689{
690	token_t *t;
691	u_char *dptr = NULL;
692	u_int16_t textlen;
693
694	textlen = strlen(text);
695	textlen += 1;
696
697	/* XXXRW: Should validate length against token size limit. */
698
699	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
700	if (t == NULL)
701		return (NULL);
702
703	ADD_U_CHAR(dptr, AUT_TEXT);
704	ADD_U_INT16(dptr, textlen);
705	ADD_STRING(dptr, text, textlen);
706
707	return (t);
708}
709
710/*
711 * token ID                1 byte
712 * path length             2 bytes
713 * path                    N bytes + 1 terminating NULL byte
714 */
715token_t *
716au_to_path(const char *text)
717{
718	token_t *t;
719	u_char *dptr = NULL;
720	u_int16_t textlen;
721
722	textlen = strlen(text);
723	textlen += 1;
724
725	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
726	if (t == NULL)
727		return (NULL);
728
729	ADD_U_CHAR(dptr, AUT_PATH);
730	ADD_U_INT16(dptr, textlen);
731	ADD_STRING(dptr, text, textlen);
732
733	return (t);
734}
735
736/*
737 * token ID                1 byte
738 * audit ID                4 bytes
739 * effective user ID       4 bytes
740 * effective group ID      4 bytes
741 * real user ID            4 bytes
742 * real group ID           4 bytes
743 * process ID              4 bytes
744 * session ID              4 bytes
745 * terminal ID
746 *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
747 *   machine address       4 bytes
748 */
749token_t *
750au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
751    pid_t pid, au_asid_t sid, au_tid_t *tid)
752{
753	token_t *t;
754	u_char *dptr = NULL;
755
756	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
757	if (t == NULL)
758		return (NULL);
759
760	ADD_U_CHAR(dptr, AUT_PROCESS32);
761	ADD_U_INT32(dptr, auid);
762	ADD_U_INT32(dptr, euid);
763	ADD_U_INT32(dptr, egid);
764	ADD_U_INT32(dptr, ruid);
765	ADD_U_INT32(dptr, rgid);
766	ADD_U_INT32(dptr, pid);
767	ADD_U_INT32(dptr, sid);
768	ADD_U_INT32(dptr, tid->port);
769
770	/*
771	 * Note: Solaris will write out IPv6 addresses here as a 32-bit
772	 * address type and 16 bytes of address, but for IPv4 addresses it
773	 * simply writes the 4-byte address directly.  We support only IPv4
774	 * addresses for process32 tokens.
775	 */
776	ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
777
778	return (t);
779}
780
781token_t *
782au_to_process64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
783    pid_t pid, au_asid_t sid, au_tid_t *tid)
784{
785	token_t *t;
786	u_char *dptr = NULL;
787
788	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 8 * sizeof(u_int32_t) +
789	    sizeof(u_int64_t));
790	if (t == NULL)
791		return (NULL);
792
793	ADD_U_CHAR(dptr, AUT_PROCESS64);
794	ADD_U_INT32(dptr, auid);
795	ADD_U_INT32(dptr, euid);
796	ADD_U_INT32(dptr, egid);
797	ADD_U_INT32(dptr, ruid);
798	ADD_U_INT32(dptr, rgid);
799	ADD_U_INT32(dptr, pid);
800	ADD_U_INT32(dptr, sid);
801	ADD_U_INT64(dptr, tid->port);
802
803	/*
804	 * Note: Solaris will write out IPv6 addresses here as a 32-bit
805	 * address type and 16 bytes of address, but for IPv4 addresses it
806	 * simply writes the 4-byte address directly.  We support only IPv4
807	 * addresses for process64 tokens.
808	 */
809	ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
810
811	return (t);
812}
813
814token_t *
815au_to_process(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
816    pid_t pid, au_asid_t sid, au_tid_t *tid)
817{
818
819	return (au_to_process32(auid, euid, egid, ruid, rgid, pid, sid,
820	    tid));
821}
822
823/*
824 * token ID                1 byte
825 * audit ID                4 bytes
826 * effective user ID       4 bytes
827 * effective group ID      4 bytes
828 * real user ID            4 bytes
829 * real group ID           4 bytes
830 * process ID              4 bytes
831 * session ID              4 bytes
832 * terminal ID
833 *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
834 *   address type-len      4 bytes
835 *   machine address      16 bytes
836 */
837token_t *
838au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
839    gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
840{
841	token_t *t;
842	u_char *dptr = NULL;
843
844	if (tid->at_type == AU_IPv4)
845		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
846		    10 * sizeof(u_int32_t));
847	else if (tid->at_type == AU_IPv6)
848		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
849		    13 * sizeof(u_int32_t));
850	else {
851		errno = EINVAL;
852		return (NULL);
853	}
854	if (t == NULL)
855		return (NULL);
856
857	ADD_U_CHAR(dptr, AUT_PROCESS32_EX);
858	ADD_U_INT32(dptr, auid);
859	ADD_U_INT32(dptr, euid);
860	ADD_U_INT32(dptr, egid);
861	ADD_U_INT32(dptr, ruid);
862	ADD_U_INT32(dptr, rgid);
863	ADD_U_INT32(dptr, pid);
864	ADD_U_INT32(dptr, sid);
865	ADD_U_INT32(dptr, tid->at_port);
866	ADD_U_INT32(dptr, tid->at_type);
867	ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
868	if (tid->at_type == AU_IPv6) {
869		ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t));
870		ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t));
871		ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t));
872	}
873
874	return (t);
875}
876
877token_t *
878au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
879    gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
880{
881	token_t *t;
882	u_char *dptr = NULL;
883
884	if (tid->at_type == AU_IPv4)
885		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
886		    7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
887		    2 * sizeof(u_int32_t));
888	else if (tid->at_type == AU_IPv6)
889		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
890		    7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
891		    5 * sizeof(u_int32_t));
892	else {
893		errno = EINVAL;
894		return (NULL);
895	}
896	if (t == NULL)
897		return (NULL);
898
899	ADD_U_CHAR(dptr, AUT_PROCESS64_EX);
900	ADD_U_INT32(dptr, auid);
901	ADD_U_INT32(dptr, euid);
902	ADD_U_INT32(dptr, egid);
903	ADD_U_INT32(dptr, ruid);
904	ADD_U_INT32(dptr, rgid);
905	ADD_U_INT32(dptr, pid);
906	ADD_U_INT32(dptr, sid);
907	ADD_U_INT64(dptr, tid->at_port);
908	ADD_U_INT32(dptr, tid->at_type);
909	ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
910	if (tid->at_type == AU_IPv6) {
911		ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t));
912		ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t));
913		ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t));
914	}
915
916	return (t);
917}
918
919token_t *
920au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
921    gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
922{
923
924	return (au_to_process32_ex(auid, euid, egid, ruid, rgid, pid, sid,
925	    tid));
926}
927
928/*
929 * token ID                1 byte
930 * error status            1 byte
931 * return value            4 bytes/8 bytes (32-bit/64-bit value)
932 */
933token_t *
934au_to_return32(char status, u_int32_t ret)
935{
936	token_t *t;
937	u_char *dptr = NULL;
938
939	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
940	if (t == NULL)
941		return (NULL);
942
943	ADD_U_CHAR(dptr, AUT_RETURN32);
944	ADD_U_CHAR(dptr, status);
945	ADD_U_INT32(dptr, ret);
946
947	return (t);
948}
949
950token_t *
951au_to_return64(char status, u_int64_t ret)
952{
953	token_t *t;
954	u_char *dptr = NULL;
955
956	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t));
957	if (t == NULL)
958		return (NULL);
959
960	ADD_U_CHAR(dptr, AUT_RETURN64);
961	ADD_U_CHAR(dptr, status);
962	ADD_U_INT64(dptr, ret);
963
964	return (t);
965}
966
967token_t *
968au_to_return(char status, u_int32_t ret)
969{
970
971	return (au_to_return32(status, ret));
972}
973
974/*
975 * token ID                1 byte
976 * sequence number         4 bytes
977 */
978token_t *
979au_to_seq(long audit_count)
980{
981	token_t *t;
982	u_char *dptr = NULL;
983
984	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t));
985	if (t == NULL)
986		return (NULL);
987
988	ADD_U_CHAR(dptr, AUT_SEQ);
989	ADD_U_INT32(dptr, audit_count);
990
991	return (t);
992}
993
994/*
995 * token ID                1 byte
996 * socket domain           2 bytes
997 * socket type             2 bytes
998 * address type            2 byte
999 * local port              2 bytes
1000 * local address           4 bytes/16 bytes (IPv4/IPv6 address)
1001 * remote port             2 bytes
1002 * remote address          4 bytes/16 bytes (IPv4/IPv6 address)
1003 *
1004 * Domain and type arguments to this routine are assumed to already have been
1005 * converted to the BSM constant space, so we don't do that here.
1006 */
1007token_t *
1008au_to_socket_ex(u_short so_domain, u_short so_type,
1009    struct sockaddr *sa_local, struct sockaddr *sa_remote)
1010{
1011	token_t *t;
1012	u_char *dptr = NULL;
1013	struct sockaddr_in *sin;
1014	struct sockaddr_in6 *sin6;
1015
1016	if (so_domain == AF_INET)
1017		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
1018		    5 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
1019	else if (so_domain == AF_INET6)
1020		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
1021		    5 * sizeof(u_int16_t) + 8 * sizeof(u_int32_t));
1022	else {
1023		errno = EINVAL;
1024		return (NULL);
1025	}
1026	if (t == NULL)
1027		return (NULL);
1028
1029	ADD_U_CHAR(dptr, AUT_SOCKET_EX);
1030	ADD_U_INT16(dptr, au_domain_to_bsm(so_domain));
1031	ADD_U_INT16(dptr, au_socket_type_to_bsm(so_type));
1032	if (so_domain == AF_INET) {
1033		ADD_U_INT16(dptr, AU_IPv4);
1034		sin = (struct sockaddr_in *)sa_local;
1035		ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t));
1036		ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t));
1037		sin = (struct sockaddr_in *)sa_remote;
1038		ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t));
1039		ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t));
1040	} else {
1041		ADD_U_INT16(dptr, AU_IPv6);
1042		sin6 = (struct sockaddr_in6 *)sa_local;
1043		ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t));
1044		ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t));
1045		sin6 = (struct sockaddr_in6 *)sa_remote;
1046		ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t));
1047		ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t));
1048	}
1049
1050	return (t);
1051}
1052
1053/*
1054 * token ID                1 byte
1055 * socket family           2 bytes
1056 * path                    (up to) 104 bytes + NULL  (NULL terminated string)
1057 */
1058token_t *
1059au_to_sock_unix(struct sockaddr_un *so)
1060{
1061	token_t *t;
1062	u_char *dptr;
1063
1064	GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + strlen(so->sun_path) + 1);
1065	if (t == NULL)
1066		return (NULL);
1067
1068	ADD_U_CHAR(dptr, AUT_SOCKUNIX);
1069	/* BSM token has two bytes for family */
1070	ADD_U_CHAR(dptr, 0);
1071	ADD_U_CHAR(dptr, so->sun_family);
1072	ADD_STRING(dptr, so->sun_path, strlen(so->sun_path) + 1);
1073
1074	return (t);
1075}
1076
1077/*
1078 * token ID                1 byte
1079 * socket family           2 bytes
1080 * local port              2 bytes
1081 * socket address          4 bytes
1082 */
1083token_t *
1084au_to_sock_inet32(struct sockaddr_in *so)
1085{
1086	token_t *t;
1087	u_char *dptr = NULL;
1088	uint16_t family;
1089
1090	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(uint16_t) +
1091	    sizeof(uint32_t));
1092	if (t == NULL)
1093		return (NULL);
1094
1095	ADD_U_CHAR(dptr, AUT_SOCKINET32);
1096	/*
1097	 * BSM defines the family field as 16 bits, but many operating
1098	 * systems have an 8-bit sin_family field.  Extend to 16 bits before
1099	 * writing into the token.  Assume that both the port and the address
1100	 * in the sockaddr_in are already in network byte order, but family
1101	 * is in local byte order.
1102	 *
1103	 * XXXRW: Should a name space conversion be taking place on the value
1104	 * of sin_family?
1105	 */
1106	family = so->sin_family;
1107	ADD_U_INT16(dptr, family);
1108	ADD_MEM(dptr, &so->sin_port, sizeof(uint16_t));
1109	ADD_MEM(dptr, &so->sin_addr.s_addr, sizeof(uint32_t));
1110
1111	return (t);
1112}
1113
1114token_t *
1115au_to_sock_inet128(struct sockaddr_in6 *so)
1116{
1117	token_t *t;
1118	u_char *dptr = NULL;
1119
1120	GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
1121	    4 * sizeof(u_int32_t));
1122	if (t == NULL)
1123		return (NULL);
1124
1125	ADD_U_CHAR(dptr, AUT_SOCKINET128);
1126	/*
1127	 * In BSD, sin6_family is one octet, but BSM defines the token to
1128	 * store two. So we copy in a 0 first.  XXXRW: Possibly should be
1129	 * conditionally compiled.
1130	 */
1131	ADD_U_CHAR(dptr, 0);
1132	ADD_U_CHAR(dptr, so->sin6_family);
1133
1134	ADD_U_INT16(dptr, so->sin6_port);
1135	ADD_MEM(dptr, &so->sin6_addr, 4 * sizeof(uint32_t));
1136
1137	return (t);
1138}
1139
1140token_t *
1141au_to_sock_inet(struct sockaddr_in *so)
1142{
1143
1144	return (au_to_sock_inet32(so));
1145}
1146
1147/*
1148 * token ID                1 byte
1149 * audit ID                4 bytes
1150 * effective user ID       4 bytes
1151 * effective group ID      4 bytes
1152 * real user ID            4 bytes
1153 * real group ID           4 bytes
1154 * process ID              4 bytes
1155 * session ID              4 bytes
1156 * terminal ID
1157 *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
1158 *   machine address       4 bytes
1159 */
1160token_t *
1161au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
1162    pid_t pid, au_asid_t sid, au_tid_t *tid)
1163{
1164	token_t *t;
1165	u_char *dptr = NULL;
1166
1167	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
1168	if (t == NULL)
1169		return (NULL);
1170
1171	ADD_U_CHAR(dptr, AUT_SUBJECT32);
1172	ADD_U_INT32(dptr, auid);
1173	ADD_U_INT32(dptr, euid);
1174	ADD_U_INT32(dptr, egid);
1175	ADD_U_INT32(dptr, ruid);
1176	ADD_U_INT32(dptr, rgid);
1177	ADD_U_INT32(dptr, pid);
1178	ADD_U_INT32(dptr, sid);
1179	ADD_U_INT32(dptr, tid->port);
1180	ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
1181
1182	return (t);
1183}
1184
1185token_t *
1186au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
1187    pid_t pid, au_asid_t sid, au_tid_t *tid)
1188{
1189	token_t *t;
1190	u_char *dptr = NULL;
1191
1192	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) +
1193	    sizeof(u_int64_t) + sizeof(u_int32_t));
1194	if (t == NULL)
1195		return (NULL);
1196
1197	ADD_U_CHAR(dptr, AUT_SUBJECT64);
1198	ADD_U_INT32(dptr, auid);
1199	ADD_U_INT32(dptr, euid);
1200	ADD_U_INT32(dptr, egid);
1201	ADD_U_INT32(dptr, ruid);
1202	ADD_U_INT32(dptr, rgid);
1203	ADD_U_INT32(dptr, pid);
1204	ADD_U_INT32(dptr, sid);
1205	ADD_U_INT64(dptr, tid->port);
1206	ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
1207
1208	return (t);
1209}
1210
1211token_t *
1212au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
1213    pid_t pid, au_asid_t sid, au_tid_t *tid)
1214{
1215
1216	return (au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
1217	    tid));
1218}
1219
1220/*
1221 * token ID                1 byte
1222 * audit ID                4 bytes
1223 * effective user ID       4 bytes
1224 * effective group ID      4 bytes
1225 * real user ID            4 bytes
1226 * real group ID           4 bytes
1227 * process ID              4 bytes
1228 * session ID              4 bytes
1229 * terminal ID
1230 *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
1231 *   address type/length   4 bytes
1232 *   machine address      16 bytes
1233 */
1234token_t *
1235au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
1236    gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
1237{
1238	token_t *t;
1239	u_char *dptr = NULL;
1240
1241	if (tid->at_type == AU_IPv4)
1242		GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 10 *
1243		    sizeof(u_int32_t));
1244	else if (tid->at_type == AU_IPv6)
1245		GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 *
1246		    sizeof(u_int32_t));
1247	else {
1248		errno = EINVAL;
1249		return (NULL);
1250	}
1251	if (t == NULL)
1252		return (NULL);
1253
1254	ADD_U_CHAR(dptr, AUT_SUBJECT32_EX);
1255	ADD_U_INT32(dptr, auid);
1256	ADD_U_INT32(dptr, euid);
1257	ADD_U_INT32(dptr, egid);
1258	ADD_U_INT32(dptr, ruid);
1259	ADD_U_INT32(dptr, rgid);
1260	ADD_U_INT32(dptr, pid);
1261	ADD_U_INT32(dptr, sid);
1262	ADD_U_INT32(dptr, tid->at_port);
1263	ADD_U_INT32(dptr, tid->at_type);
1264	if (tid->at_type == AU_IPv6)
1265		ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
1266	else
1267		ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
1268
1269	return (t);
1270}
1271
1272token_t *
1273au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
1274    gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
1275{
1276	token_t *t;
1277	u_char *dptr = NULL;
1278
1279	if (tid->at_type == AU_IPv4)
1280		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
1281		    7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
1282		    2 * sizeof(u_int32_t));
1283	else if (tid->at_type == AU_IPv6)
1284		GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
1285		    7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
1286		    5 * sizeof(u_int32_t));
1287	else {
1288		errno = EINVAL;
1289		return (NULL);
1290	}
1291	if (t == NULL)
1292		return (NULL);
1293
1294	ADD_U_CHAR(dptr, AUT_SUBJECT64_EX);
1295	ADD_U_INT32(dptr, auid);
1296	ADD_U_INT32(dptr, euid);
1297	ADD_U_INT32(dptr, egid);
1298	ADD_U_INT32(dptr, ruid);
1299	ADD_U_INT32(dptr, rgid);
1300	ADD_U_INT32(dptr, pid);
1301	ADD_U_INT32(dptr, sid);
1302	ADD_U_INT64(dptr, tid->at_port);
1303	ADD_U_INT32(dptr, tid->at_type);
1304	if (tid->at_type == AU_IPv6)
1305		ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
1306	else
1307		ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
1308
1309	return (t);
1310}
1311
1312token_t *
1313au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
1314    gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
1315{
1316
1317	return (au_to_subject32_ex(auid, euid, egid, ruid, rgid, pid, sid,
1318	    tid));
1319}
1320
1321#if !defined(_KERNEL) && !defined(KERNEL) && defined(HAVE_AUDIT_SYSCALLS)
1322/*
1323 * Collects audit information for the current process and creates a subject
1324 * token from it.
1325 */
1326token_t *
1327au_to_me(void)
1328{
1329	auditinfo_t auinfo;
1330	auditinfo_addr_t aia;
1331
1332	/*
1333	 * Try to use getaudit_addr(2) first.  If this kernel does not support
1334	 * it, then fall back on to getaudit(2).
1335	 */
1336	if (getaudit_addr(&aia, sizeof(aia)) != 0) {
1337		if (errno == ENOSYS) {
1338			if (getaudit(&auinfo) != 0)
1339				return (NULL);
1340			return (au_to_subject32(auinfo.ai_auid, geteuid(),
1341				getegid(), getuid(), getgid(), getpid(),
1342				auinfo.ai_asid, &auinfo.ai_termid));
1343		} else {
1344			/* getaudit_addr(2) failed for some other reason. */
1345			return (NULL);
1346		}
1347	}
1348
1349	return (au_to_subject32_ex(aia.ai_auid, geteuid(), getegid(), getuid(),
1350		getgid(), getpid(), aia.ai_asid, &aia.ai_termid));
1351}
1352#endif
1353
1354/*
1355 * token ID				1 byte
1356 * count				4 bytes
1357 * text					count null-terminated strings
1358 */
1359token_t *
1360au_to_exec_args(char **argv)
1361{
1362	token_t *t;
1363	u_char *dptr = NULL;
1364	const char *nextarg;
1365	int i, count = 0;
1366	size_t totlen = 0;
1367
1368	nextarg = *argv;
1369
1370	while (nextarg != NULL) {
1371		int nextlen;
1372
1373		nextlen = strlen(nextarg);
1374		totlen += nextlen + 1;
1375		count++;
1376		nextarg = *(argv + count);
1377	}
1378
1379	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
1380	if (t == NULL)
1381		return (NULL);
1382
1383	ADD_U_CHAR(dptr, AUT_EXEC_ARGS);
1384	ADD_U_INT32(dptr, count);
1385
1386	for (i = 0; i < count; i++) {
1387		nextarg = *(argv + i);
1388		ADD_MEM(dptr, nextarg, strlen(nextarg) + 1);
1389	}
1390
1391	return (t);
1392}
1393
1394/*
1395 * token ID				1 byte
1396 * count				4 bytes
1397 * text					count null-terminated strings
1398 */
1399token_t *
1400au_to_exec_env(char **envp)
1401{
1402	token_t *t;
1403	u_char *dptr = NULL;
1404	int i, count = 0;
1405	size_t totlen = 0;
1406	const char *nextenv;
1407
1408	nextenv = *envp;
1409
1410	while (nextenv != NULL) {
1411		int nextlen;
1412
1413		nextlen = strlen(nextenv);
1414		totlen += nextlen + 1;
1415		count++;
1416		nextenv = *(envp + count);
1417	}
1418
1419	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
1420	if (t == NULL)
1421		return (NULL);
1422
1423	ADD_U_CHAR(dptr, AUT_EXEC_ENV);
1424	ADD_U_INT32(dptr, count);
1425
1426	for (i = 0; i < count; i++) {
1427		nextenv = *(envp + i);
1428		ADD_MEM(dptr, nextenv, strlen(nextenv) + 1);
1429	}
1430
1431	return (t);
1432}
1433
1434/*
1435 * token ID                1 byte
1436 * zonename length         2 bytes
1437 * zonename                N bytes + 1 terminating NULL byte
1438 */
1439token_t *
1440au_to_zonename(const char *zonename)
1441{
1442	u_char *dptr = NULL;
1443	u_int16_t textlen;
1444	token_t *t;
1445
1446	textlen = strlen(zonename) + 1;
1447	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
1448	if (t == NULL)
1449		return (NULL);
1450
1451	ADD_U_CHAR(dptr, AUT_ZONENAME);
1452	ADD_U_INT16(dptr, textlen);
1453	ADD_STRING(dptr, zonename, textlen);
1454	return (t);
1455}
1456
1457/*
1458 * token ID                1 byte
1459 * record byte count       4 bytes
1460 * version #               1 byte    [2]
1461 * event type              2 bytes
1462 * event modifier          2 bytes
1463 * seconds of time         4 bytes/8 bytes (32-bit/64-bit value)
1464 * milliseconds of time    4 bytes/8 bytes (32-bit/64-bit value)
1465 */
1466token_t *
1467au_to_header32_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
1468    struct timeval tm)
1469{
1470	token_t *t;
1471	u_char *dptr = NULL;
1472	u_int32_t timems;
1473
1474	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
1475	    sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
1476	if (t == NULL)
1477		return (NULL);
1478
1479	ADD_U_CHAR(dptr, AUT_HEADER32);
1480	ADD_U_INT32(dptr, rec_size);
1481	ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
1482	ADD_U_INT16(dptr, e_type);
1483	ADD_U_INT16(dptr, e_mod);
1484
1485	timems = tm.tv_usec/1000;
1486	/* Add the timestamp */
1487	ADD_U_INT32(dptr, tm.tv_sec);
1488	ADD_U_INT32(dptr, timems);	/* We need time in ms. */
1489
1490	return (t);
1491}
1492
1493/*
1494 * token ID                1 byte
1495 * record byte count       4 bytes
1496 * version #               1 byte    [2]
1497 * event type              2 bytes
1498 * event modifier          2 bytes
1499 * address type/length     4 bytes
1500 * machine address         4 bytes/16 bytes (IPv4/IPv6 address)
1501 * seconds of time         4 bytes/8 bytes (32-bit/64-bit value)
1502 * milliseconds of time    4 bytes/8 bytes (32-bit/64-bit value)
1503 */
1504token_t *
1505au_to_header32_ex_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
1506    struct timeval tm, struct auditinfo_addr *aia)
1507{
1508	token_t *t;
1509	u_char *dptr = NULL;
1510	u_int32_t timems;
1511	au_tid_addr_t *tid;
1512
1513	tid = &aia->ai_termid;
1514	if (tid->at_type != AU_IPv4 && tid->at_type != AU_IPv6)
1515		return (NULL);
1516	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
1517	    sizeof(u_char) + 2 * sizeof(u_int16_t) + 3 *
1518	    sizeof(u_int32_t) + tid->at_type);
1519	if (t == NULL)
1520		return (NULL);
1521
1522	ADD_U_CHAR(dptr, AUT_HEADER32_EX);
1523	ADD_U_INT32(dptr, rec_size);
1524	ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
1525	ADD_U_INT16(dptr, e_type);
1526	ADD_U_INT16(dptr, e_mod);
1527
1528	ADD_U_INT32(dptr, tid->at_type);
1529	if (tid->at_type == AU_IPv6)
1530		ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
1531	else
1532		ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
1533	timems = tm.tv_usec/1000;
1534	/* Add the timestamp */
1535	ADD_U_INT32(dptr, tm.tv_sec);
1536	ADD_U_INT32(dptr, timems);      /* We need time in ms. */
1537
1538	return (t);
1539}
1540
1541token_t *
1542au_to_header64_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
1543    struct timeval tm)
1544{
1545	token_t *t;
1546	u_char *dptr = NULL;
1547	u_int32_t timems;
1548
1549	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
1550	    sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int64_t));
1551	if (t == NULL)
1552		return (NULL);
1553
1554	ADD_U_CHAR(dptr, AUT_HEADER64);
1555	ADD_U_INT32(dptr, rec_size);
1556	ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
1557	ADD_U_INT16(dptr, e_type);
1558	ADD_U_INT16(dptr, e_mod);
1559
1560	timems = tm.tv_usec/1000;
1561	/* Add the timestamp */
1562	ADD_U_INT64(dptr, tm.tv_sec);
1563	ADD_U_INT64(dptr, timems);	/* We need time in ms. */
1564
1565	return (t);
1566}
1567
1568#if !defined(KERNEL) && !defined(_KERNEL)
1569#ifdef HAVE_AUDIT_SYSCALLS
1570token_t *
1571au_to_header32_ex(int rec_size, au_event_t e_type, au_emod_t e_mod)
1572{
1573	struct timeval tm;
1574	struct auditinfo_addr aia;
1575
1576	if (gettimeofday(&tm, NULL) == -1)
1577		return (NULL);
1578	if (audit_get_kaudit(&aia, sizeof(aia)) != 0) {
1579		if (errno != ENOSYS)
1580			return (NULL);
1581		return (au_to_header32_tm(rec_size, e_type, e_mod, tm));
1582	}
1583	return (au_to_header32_ex_tm(rec_size, e_type, e_mod, tm, &aia));
1584}
1585#endif /* HAVE_AUDIT_SYSCALLS */
1586
1587token_t *
1588au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod)
1589{
1590	struct timeval tm;
1591
1592	if (gettimeofday(&tm, NULL) == -1)
1593		return (NULL);
1594	return (au_to_header32_tm(rec_size, e_type, e_mod, tm));
1595}
1596
1597token_t *
1598au_to_header64(__unused int rec_size, __unused au_event_t e_type,
1599    __unused au_emod_t e_mod)
1600{
1601	struct timeval tm;
1602
1603	if (gettimeofday(&tm, NULL) == -1)
1604		return (NULL);
1605	return (au_to_header64_tm(rec_size, e_type, e_mod, tm));
1606}
1607
1608token_t *
1609au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod)
1610{
1611
1612	return (au_to_header32(rec_size, e_type, e_mod));
1613}
1614
1615#ifdef HAVE_AUDIT_SYSCALLS
1616token_t *
1617au_to_header_ex(int rec_size, au_event_t e_type, au_emod_t e_mod)
1618{
1619
1620	return (au_to_header32_ex(rec_size, e_type, e_mod));
1621}
1622#endif /* HAVE_AUDIT_SYSCALLS */
1623#endif /* !defined(KERNEL) && !defined(_KERNEL) */
1624
1625/*
1626 * token ID                1 byte
1627 * trailer magic number    2 bytes
1628 * record byte count       4 bytes
1629 */
1630token_t *
1631au_to_trailer(int rec_size)
1632{
1633	token_t *t;
1634	u_char *dptr = NULL;
1635	u_int16_t magic = AUT_TRAILER_MAGIC;
1636
1637	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
1638	    sizeof(u_int32_t));
1639	if (t == NULL)
1640		return (NULL);
1641
1642	ADD_U_CHAR(dptr, AUT_TRAILER);
1643	ADD_U_INT16(dptr, magic);
1644	ADD_U_INT32(dptr, rec_size);
1645
1646	return (t);
1647}
1648