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