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