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