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