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