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