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