xref: /freebsd/contrib/openbsm/libbsm/bsm_token.c (revision 87569f75a91f298c52a71823c04d41cf53c88889)
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#43 $
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  */
101 token_t *
102 au_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 
126 token_t *
127 au_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 
151 token_t *
152 au_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  */
168 token_t *
169 au_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 
213 token_t *
214 au_to_attr64(struct vnode_au_info *vni)
215 {
216 
217 	errno = ENOTSUP;
218 	return (NULL);
219 }
220 
221 token_t *
222 au_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  */
236 token_t *
237 au_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 		datasize = AUR_BYTE_SIZE;
247 		break;
248 
249 	case AUR_SHORT:
250 		datasize = AUR_SHORT_SIZE;
251 		break;
252 
253 	case AUR_LONG:
254 		datasize = AUR_LONG_SIZE;
255 		break;
256 
257 	default:
258 		errno = EINVAL;
259  		return (NULL);
260 	}
261 
262 	totdata = datasize * unit_count;
263 
264 	GET_TOKEN_AREA(t, dptr, totdata + 4 * sizeof(u_char));
265 	if (t == NULL)
266 		return (NULL);
267 
268 	ADD_U_CHAR(dptr, AUT_DATA);
269 	ADD_U_CHAR(dptr, unit_print);
270 	ADD_U_CHAR(dptr, unit_type);
271 	ADD_U_CHAR(dptr, unit_count);
272 	ADD_MEM(dptr, p, totdata);
273 
274 	return (t);
275 }
276 
277 
278 /*
279  * token ID                1 byte
280  * status		   4 bytes
281  * return value            4 bytes
282  */
283 token_t *
284 au_to_exit(int retval, int err)
285 {
286 	token_t *t;
287 	u_char *dptr = NULL;
288 
289 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t));
290 	if (t == NULL)
291 		return (NULL);
292 
293 	ADD_U_CHAR(dptr, AUT_EXIT);
294 	ADD_U_INT32(dptr, err);
295 	ADD_U_INT32(dptr, retval);
296 
297 	return (t);
298 }
299 
300 /*
301  */
302 token_t *
303 au_to_groups(int *groups)
304 {
305 
306 	return (au_to_newgroups(BSM_MAX_GROUPS, groups));
307 }
308 
309 /*
310  * token ID                1 byte
311  * number groups           2 bytes
312  * group list              count * 4 bytes
313  */
314 token_t *
315 au_to_newgroups(u_int16_t n, gid_t *groups)
316 {
317 	token_t *t;
318 	u_char *dptr = NULL;
319 	int i;
320 
321 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
322 	    n * sizeof(u_int32_t));
323 	if (t == NULL)
324 		return (NULL);
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  */
338 token_t *
339 au_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(u_int32_t));
345 	if (t == NULL)
346 		return (NULL);
347 
348 	ADD_U_CHAR(dptr, AUT_IN_ADDR);
349 	ADD_U_INT32(dptr, internet_addr->s_addr);
350 
351 	return (t);
352 }
353 
354 /*
355  * token ID                1 byte
356  * address type/length     4 bytes
357  * Address                16 bytes
358  */
359 token_t *
360 au_to_in_addr_ex(struct in6_addr *internet_addr)
361 {
362 	token_t *t;
363 	u_char *dptr = NULL;
364 	u_int32_t type = AF_INET6;
365 
366 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(u_int32_t));
367 	if (t == NULL)
368 		return (NULL);
369 
370 	ADD_U_CHAR(dptr, AUT_IN_ADDR_EX);
371 	ADD_U_INT32(dptr, type);
372 	ADD_MEM(dptr, internet_addr, sizeof(*internet_addr));
373 
374 	return (t);
375 }
376 
377 /*
378  * token ID                1 byte
379  * ip header		   20 bytes
380  */
381 token_t *
382 au_to_ip(struct ip *ip)
383 {
384 	token_t *t;
385 	u_char *dptr = NULL;
386 
387 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(struct ip));
388 	if (t == NULL)
389 		return (NULL);
390 
391 	ADD_U_CHAR(dptr, AUT_IP);
392 	/*
393 	 * XXXRW: Any byte order work needed on the IP header before writing?
394 	 */
395 	ADD_MEM(dptr, ip, sizeof(struct ip));
396 
397 	return (t);
398 }
399 
400 /*
401  * token ID                1 byte
402  * object ID type          1 byte
403  * object ID               4 bytes
404  */
405 token_t *
406 au_to_ipc(char type, int id)
407 {
408 	token_t *t;
409 	u_char *dptr = NULL;
410 
411 	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
412 	if (t == NULL)
413 		return (NULL);
414 
415 	ADD_U_CHAR(dptr, AUT_IPC);
416 	ADD_U_CHAR(dptr, type);
417 	ADD_U_INT32(dptr, id);
418 
419 	return (t);
420 }
421 
422 /*
423  * token ID                1 byte
424  * owner user ID           4 bytes
425  * owner group ID          4 bytes
426  * creator user ID         4 bytes
427  * creator group ID        4 bytes
428  * access mode             4 bytes
429  * slot sequence #         4 bytes
430  * key                     4 bytes
431  */
432 token_t *
433 au_to_ipc_perm(struct ipc_perm *perm)
434 {
435 	token_t *t;
436 	u_char *dptr = NULL;
437 	u_int16_t pad0 = 0;
438 
439 	GET_TOKEN_AREA(t, dptr, 12 * sizeof(u_int16_t) + sizeof(u_int32_t));
440 	if (t == NULL)
441 		return (NULL);
442 
443 	ADD_U_CHAR(dptr, AUT_IPC_PERM);
444 
445 	/*
446 	 * Darwin defines the sizes for ipc_perm members
447 	 * as 2 bytes; BSM defines 4 so pad with 0
448 	 */
449 	ADD_U_INT16(dptr, pad0);
450 	ADD_U_INT16(dptr, perm->uid);
451 
452 	ADD_U_INT16(dptr, pad0);
453 	ADD_U_INT16(dptr, perm->gid);
454 
455 	ADD_U_INT16(dptr, pad0);
456 	ADD_U_INT16(dptr, perm->cuid);
457 
458 	ADD_U_INT16(dptr, pad0);
459 	ADD_U_INT16(dptr, perm->cgid);
460 
461 	ADD_U_INT16(dptr, pad0);
462 	ADD_U_INT16(dptr, perm->mode);
463 
464 	ADD_U_INT16(dptr, pad0);
465 
466 #ifdef HAVE_IPC_PERM___SEQ
467 	ADD_U_INT16(dptr, perm->__seq);
468 #else
469 	ADD_U_INT16(dptr, perm->seq);
470 #endif
471 
472 #ifdef HAVE_IPC_PERM___KEY
473 	ADD_U_INT32(dptr, perm->__key);
474 #else
475 	ADD_U_INT32(dptr, perm->key);
476 #endif
477 
478 	return (t);
479 }
480 
481 /*
482  * token ID                1 byte
483  * port IP address         2 bytes
484  */
485 token_t *
486 au_to_iport(u_int16_t iport)
487 {
488 	token_t *t;
489 	u_char *dptr = NULL;
490 
491 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t));
492 	if (t == NULL)
493 		return (NULL);
494 
495 	ADD_U_CHAR(dptr, AUT_IPORT);
496 	ADD_U_INT16(dptr, iport);
497 
498 	return (t);
499 }
500 
501 /*
502  * token ID                1 byte
503  * size                    2 bytes
504  * data                    size bytes
505  */
506 token_t *
507 au_to_opaque(char *data, u_int16_t bytes)
508 {
509 	token_t *t;
510 	u_char *dptr = NULL;
511 
512 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + bytes);
513 	if (t == NULL)
514 		return (NULL);
515 
516 	ADD_U_CHAR(dptr, AUT_OPAQUE);
517 	ADD_U_INT16(dptr, bytes);
518 	ADD_MEM(dptr, data, bytes);
519 
520 	return (t);
521 }
522 
523 /*
524  * token ID                1 byte
525  * seconds of time         4 bytes
526  * milliseconds of time    4 bytes
527  * file name len           2 bytes
528  * file pathname           N bytes + 1 terminating NULL byte
529  */
530 token_t *
531 #if defined(KERNEL) || defined(_KERNEL)
532 au_to_file(char *file, struct timeval tm)
533 #else
534 au_to_file(char *file)
535 #endif
536 {
537 	token_t *t;
538 	u_char *dptr = NULL;
539 	u_int16_t filelen;
540 	u_int32_t timems;
541 #if !defined(KERNEL) && !defined(_KERNEL)
542 	struct timeval tm;
543 	struct timezone tzp;
544 
545 	if (gettimeofday(&tm, &tzp) == -1)
546 		return (NULL);
547 #endif
548 
549 	filelen = strlen(file);
550 	filelen += 1;
551 
552 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t) +
553 	    sizeof(u_int16_t) + filelen);
554 	if (t == NULL)
555 		return (NULL);
556 
557 	timems = tm.tv_usec/1000;
558 
559 	ADD_U_CHAR(dptr, AUT_OTHER_FILE32);
560 	ADD_U_INT32(dptr, tm.tv_sec);
561 	ADD_U_INT32(dptr, timems);	/* We need time in ms. */
562 	ADD_U_INT16(dptr, filelen);
563 	ADD_STRING(dptr, file, filelen);
564 
565 	return (t);
566 }
567 
568 /*
569  * token ID                1 byte
570  * text length             2 bytes
571  * text                    N bytes + 1 terminating NULL byte
572  */
573 token_t *
574 au_to_text(char *text)
575 {
576 	token_t *t;
577 	u_char *dptr = NULL;
578 	u_int16_t textlen;
579 
580 	textlen = strlen(text);
581 	textlen += 1;
582 
583 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
584 	if (t == NULL)
585 		return (NULL);
586 
587 	ADD_U_CHAR(dptr, AUT_TEXT);
588 	ADD_U_INT16(dptr, textlen);
589 	ADD_STRING(dptr, text, textlen);
590 
591 	return (t);
592 }
593 
594 /*
595  * token ID                1 byte
596  * path length             2 bytes
597  * path                    N bytes + 1 terminating NULL byte
598  */
599 token_t *
600 au_to_path(char *text)
601 {
602 	token_t *t;
603 	u_char *dptr = NULL;
604 	u_int16_t textlen;
605 
606 	textlen = strlen(text);
607 	textlen += 1;
608 
609 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
610 	if (t == NULL)
611 		return (NULL);
612 
613 	ADD_U_CHAR(dptr, AUT_PATH);
614 	ADD_U_INT16(dptr, textlen);
615 	ADD_STRING(dptr, text, textlen);
616 
617 	return (t);
618 }
619 
620 /*
621  * token ID                1 byte
622  * audit ID                4 bytes
623  * effective user ID       4 bytes
624  * effective group ID      4 bytes
625  * real user ID            4 bytes
626  * real group ID           4 bytes
627  * process ID              4 bytes
628  * session ID              4 bytes
629  * terminal ID
630  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
631  *   machine address       4 bytes
632  */
633 token_t *
634 au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
635     pid_t pid, au_asid_t sid, au_tid_t *tid)
636 {
637 	token_t *t;
638 	u_char *dptr = NULL;
639 
640 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
641 	if (t == NULL)
642 		return (NULL);
643 
644 	ADD_U_CHAR(dptr, AUT_PROCESS32);
645 	ADD_U_INT32(dptr, auid);
646 	ADD_U_INT32(dptr, euid);
647 	ADD_U_INT32(dptr, egid);
648 	ADD_U_INT32(dptr, ruid);
649 	ADD_U_INT32(dptr, rgid);
650 	ADD_U_INT32(dptr, pid);
651 	ADD_U_INT32(dptr, sid);
652 	ADD_U_INT32(dptr, tid->port);
653 	ADD_U_INT32(dptr, tid->machine);
654 
655 	return (t);
656 }
657 
658 token_t *
659 au_to_process64(__unused au_id_t auid, __unused uid_t euid,
660     __unused gid_t egid, __unused uid_t ruid, __unused gid_t rgid,
661     __unused pid_t pid, __unused au_asid_t sid, __unused au_tid_t *tid)
662 {
663 
664 	errno = ENOTSUP;
665 	return (NULL);
666 }
667 
668 token_t *
669 au_to_process(__unused au_id_t auid, __unused uid_t euid,
670     __unused gid_t egid, __unused uid_t ruid, __unused gid_t rgid,
671     __unused pid_t pid, __unused au_asid_t sid, __unused au_tid_t *tid)
672 {
673 
674 	return (au_to_process32(auid, euid, egid, ruid, rgid, pid, sid,
675 	    tid));
676 }
677 
678 /*
679  * token ID                1 byte
680  * audit ID                4 bytes
681  * effective user ID       4 bytes
682  * effective group ID      4 bytes
683  * real user ID            4 bytes
684  * real group ID           4 bytes
685  * process ID              4 bytes
686  * session ID              4 bytes
687  * terminal ID
688  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
689  *   address type-len      4 bytes
690  *   machine address      16 bytes
691  */
692 token_t *
693 au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
694     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
695 {
696 	token_t *t;
697 	u_char *dptr = NULL;
698 
699 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 * sizeof(u_int32_t));
700 	if (t == NULL)
701 		return (NULL);
702 
703 	ADD_U_CHAR(dptr, AUT_PROCESS32_EX);
704 	ADD_U_INT32(dptr, auid);
705 	ADD_U_INT32(dptr, euid);
706 	ADD_U_INT32(dptr, egid);
707 	ADD_U_INT32(dptr, ruid);
708 	ADD_U_INT32(dptr, rgid);
709 	ADD_U_INT32(dptr, pid);
710 	ADD_U_INT32(dptr, sid);
711 	ADD_U_INT32(dptr, tid->at_port);
712 	ADD_U_INT32(dptr, tid->at_type);
713 	ADD_U_INT32(dptr, tid->at_addr[0]);
714 	ADD_U_INT32(dptr, tid->at_addr[1]);
715 	ADD_U_INT32(dptr, tid->at_addr[2]);
716 	ADD_U_INT32(dptr, tid->at_addr[3]);
717 
718 	return (t);
719 }
720 
721 token_t *
722 au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
723     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
724 {
725 
726 	errno = ENOTSUP;
727 	return (NULL);
728 }
729 
730 token_t *
731 au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
732     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
733 {
734 
735 	return (au_to_process32_ex(auid, euid, egid, ruid, rgid, pid, sid,
736 	    tid));
737 }
738 
739 /*
740  * token ID                1 byte
741  * error status            1 byte
742  * return value            4 bytes/8 bytes (32-bit/64-bit value)
743  */
744 token_t *
745 au_to_return32(char status, u_int32_t ret)
746 {
747 	token_t *t;
748 	u_char *dptr = NULL;
749 
750 	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
751 	if (t == NULL)
752 		return (NULL);
753 
754 	ADD_U_CHAR(dptr, AUT_RETURN32);
755 	ADD_U_CHAR(dptr, status);
756 	ADD_U_INT32(dptr, ret);
757 
758 	return (t);
759 }
760 
761 token_t *
762 au_to_return64(char status, u_int64_t ret)
763 {
764 	token_t *t;
765 	u_char *dptr = NULL;
766 
767 	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t));
768 	if (t == NULL)
769 		return (NULL);
770 
771 	ADD_U_CHAR(dptr, AUT_RETURN64);
772 	ADD_U_CHAR(dptr, status);
773 	ADD_U_INT64(dptr, ret);
774 
775 	return (t);
776 }
777 
778 token_t *
779 au_to_return(char status, u_int32_t ret)
780 {
781 
782 	return (au_to_return32(status, ret));
783 }
784 
785 /*
786  * token ID                1 byte
787  * sequence number         4 bytes
788  */
789 token_t *
790 au_to_seq(long audit_count)
791 {
792 	token_t *t;
793 	u_char *dptr = NULL;
794 
795 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t));
796 	if (t == NULL)
797 		return (NULL);
798 
799 	ADD_U_CHAR(dptr, AUT_SEQ);
800 	ADD_U_INT32(dptr, audit_count);
801 
802 	return (t);
803 }
804 
805 /*
806  * token ID                1 byte
807  * socket family           2 bytes
808  * path                    104 bytes
809  */
810 token_t *
811 au_to_sock_unix(struct sockaddr_un *so)
812 {
813 	token_t *t;
814 	u_char *dptr;
815 
816 	GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + strlen(so->sun_path) + 1);
817 	if (t == NULL)
818 		return (NULL);
819 
820 	ADD_U_CHAR(dptr, AU_SOCK_UNIX_TOKEN);
821 	/* BSM token has two bytes for family */
822 	ADD_U_CHAR(dptr, 0);
823 	ADD_U_CHAR(dptr, so->sun_family);
824 	ADD_STRING(dptr, so->sun_path, strlen(so->sun_path) + 1);
825 
826 	return (t);
827 }
828 
829 /*
830  * token ID                1 byte
831  * socket family           2 bytes
832  * local port              2 bytes
833  * socket address          4 bytes
834  */
835 token_t *
836 au_to_sock_inet32(struct sockaddr_in *so)
837 {
838 	token_t *t;
839 	u_char *dptr = NULL;
840 
841 	GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
842 	    sizeof(u_int32_t));
843 	if (t == NULL)
844 		return (NULL);
845 
846 	ADD_U_CHAR(dptr, AUT_SOCKINET32);
847 	/*
848 	 * In Darwin, sin_family is one octet, but BSM defines the token
849  	 * to store two. So we copy in a 0 first.
850  	 */
851 	ADD_U_CHAR(dptr, 0);
852 	ADD_U_CHAR(dptr, so->sin_family);
853 	ADD_U_INT16(dptr, so->sin_port);
854 	ADD_U_INT32(dptr, so->sin_addr.s_addr);
855 
856 	return (t);
857 
858 }
859 
860 token_t *
861 au_to_sock_inet128(struct sockaddr_in6 *so)
862 {
863 	token_t *t;
864 	u_char *dptr = NULL;
865 
866 	GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
867 	    4 * sizeof(u_int32_t));
868 	if (t == NULL)
869 		return (NULL);
870 
871 	ADD_U_CHAR(dptr, AUT_SOCKINET128);
872 	/*
873 	 * In Darwin, sin6_family is one octet, but BSM defines the token
874  	 * to store two. So we copy in a 0 first.
875  	 */
876 	ADD_U_CHAR(dptr, 0);
877 	ADD_U_CHAR(dptr, so->sin6_family);
878 
879 	ADD_U_INT16(dptr, so->sin6_port);
880 	ADD_MEM(dptr, &so->sin6_addr, sizeof(so->sin6_addr));
881 
882 	return (t);
883 
884 }
885 
886 token_t *
887 au_to_sock_inet(struct sockaddr_in *so)
888 {
889 
890 	return (au_to_sock_inet32(so));
891 }
892 
893 /*
894  * token ID                1 byte
895  * audit ID                4 bytes
896  * effective user ID       4 bytes
897  * effective group ID      4 bytes
898  * real user ID            4 bytes
899  * real group ID           4 bytes
900  * process ID              4 bytes
901  * session ID              4 bytes
902  * terminal ID
903  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
904  *   machine address       4 bytes
905  */
906 token_t *
907 au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
908     pid_t pid, au_asid_t sid, au_tid_t *tid)
909 {
910 	token_t *t;
911 	u_char *dptr = NULL;
912 
913 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
914 	if (t == NULL)
915 		return (NULL);
916 
917 	ADD_U_CHAR(dptr, AUT_SUBJECT32);
918 	ADD_U_INT32(dptr, auid);
919 	ADD_U_INT32(dptr, euid);
920 	ADD_U_INT32(dptr, egid);
921 	ADD_U_INT32(dptr, ruid);
922 	ADD_U_INT32(dptr, rgid);
923 	ADD_U_INT32(dptr, pid);
924 	ADD_U_INT32(dptr, sid);
925 	ADD_U_INT32(dptr, tid->port);
926 	ADD_U_INT32(dptr, tid->machine);
927 
928 	return (t);
929 }
930 
931 token_t *
932 au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
933     pid_t pid, au_asid_t sid, au_tid_t *tid)
934 {
935 
936 	errno = ENOTSUP;
937 	return (NULL);
938 }
939 
940 token_t *
941 au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
942     pid_t pid, au_asid_t sid, au_tid_t *tid)
943 {
944 
945 	return (au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
946 	    tid));
947 }
948 
949 /*
950  * token ID                1 byte
951  * audit ID                4 bytes
952  * effective user ID       4 bytes
953  * effective group ID      4 bytes
954  * real user ID            4 bytes
955  * real group ID           4 bytes
956  * process ID              4 bytes
957  * session ID              4 bytes
958  * terminal ID
959  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
960  *   address type/length   4 bytes
961  *   machine address      16 bytes
962  */
963 token_t *
964 au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
965     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
966 {
967 	token_t *t;
968 	u_char *dptr = NULL;
969 
970 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 * sizeof(u_int32_t));
971 	if (t == NULL)
972 		return (NULL);
973 
974 	ADD_U_CHAR(dptr, AUT_SUBJECT32_EX);
975 	ADD_U_INT32(dptr, auid);
976 	ADD_U_INT32(dptr, euid);
977 	ADD_U_INT32(dptr, egid);
978 	ADD_U_INT32(dptr, ruid);
979 	ADD_U_INT32(dptr, rgid);
980 	ADD_U_INT32(dptr, pid);
981 	ADD_U_INT32(dptr, sid);
982 	ADD_U_INT32(dptr, tid->at_port);
983 	ADD_U_INT32(dptr, tid->at_type);
984 	ADD_U_INT32(dptr, tid->at_addr[0]);
985 	ADD_U_INT32(dptr, tid->at_addr[1]);
986 	ADD_U_INT32(dptr, tid->at_addr[2]);
987 	ADD_U_INT32(dptr, tid->at_addr[3]);
988 
989 	return (t);
990 }
991 
992 token_t *
993 au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
994     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
995 {
996 
997 	errno = ENOTSUP;
998 	return (NULL);
999 }
1000 
1001 token_t *
1002 au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
1003     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
1004 {
1005 
1006 	return (au_to_subject32_ex(auid, euid, egid, ruid, rgid, pid, sid,
1007 	    tid));
1008 }
1009 
1010 #if !defined(_KERNEL) && !defined(KERNEL) && defined(HAVE_AUDIT_SYSCALLS)
1011 /*
1012  * Collects audit information for the current process
1013  * and creates a subject token from it
1014  */
1015 token_t *
1016 au_to_me(void)
1017 {
1018 	auditinfo_t auinfo;
1019 
1020 	if (getaudit(&auinfo) != 0)
1021 		return (NULL);
1022 
1023 	return (au_to_subject32(auinfo.ai_auid, geteuid(), getegid(),
1024 	    getuid(), getgid(), getpid(), auinfo.ai_asid, &auinfo.ai_termid));
1025 }
1026 #endif
1027 
1028 /*
1029  * token ID				1 byte
1030  * count				4 bytes
1031  * text					count null-terminated strings
1032  */
1033 token_t *
1034 au_to_exec_args(const char **args)
1035 {
1036 	token_t *t;
1037 	u_char *dptr = NULL;
1038 	const char *nextarg;
1039 	int i, count = 0;
1040 	size_t totlen = 0;
1041 
1042 	nextarg = *args;
1043 
1044 	while (nextarg != NULL) {
1045 		int nextlen;
1046 
1047 		nextlen = strlen(nextarg);
1048 		totlen += nextlen + 1;
1049 		count++;
1050 		nextarg = *(args + count);
1051 	}
1052 
1053 	totlen += count * sizeof(char);	/* nul terminations. */
1054 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
1055 	if (t == NULL)
1056 		return (NULL);
1057 
1058 	ADD_U_CHAR(dptr, AUT_EXEC_ARGS);
1059 	ADD_U_INT32(dptr, count);
1060 
1061 	for (i = 0; i < count; i++) {
1062 		nextarg = *(args + i);
1063 		ADD_MEM(dptr, nextarg, strlen(nextarg) + 1);
1064 	}
1065 
1066 	return (t);
1067 }
1068 
1069 /*
1070  * token ID				1 byte
1071  * count				4 bytes
1072  * text					count null-terminated strings
1073  */
1074 token_t *
1075 au_to_exec_env(const char **env)
1076 {
1077 	token_t *t;
1078 	u_char *dptr = NULL;
1079 	int i, count = 0;
1080 	size_t totlen = 0;
1081 	const char *nextenv;
1082 
1083 	nextenv = *env;
1084 
1085 	while (nextenv != NULL) {
1086 		int nextlen;
1087 
1088 		nextlen = strlen(nextenv);
1089 		totlen += nextlen + 1;
1090 		count++;
1091 		nextenv = *(env + count);
1092 	}
1093 
1094 	totlen += sizeof(char) * count;
1095 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
1096 	if (t == NULL)
1097 		return (NULL);
1098 
1099 	ADD_U_CHAR(dptr, AUT_EXEC_ENV);
1100 	ADD_U_INT32(dptr, count);
1101 
1102 	for (i = 0; i < count; i++) {
1103 		nextenv = *(env + i);
1104 		ADD_MEM(dptr, nextenv, strlen(nextenv) + 1);
1105 	}
1106 
1107 	return (t);
1108 }
1109 
1110 /*
1111  * token ID                1 byte
1112  * record byte count       4 bytes
1113  * version #               1 byte    [2]
1114  * event type              2 bytes
1115  * event modifier          2 bytes
1116  * seconds of time         4 bytes/8 bytes (32-bit/64-bit value)
1117  * milliseconds of time    4 bytes/8 bytes (32-bit/64-bit value)
1118  */
1119 token_t *
1120 #if defined(KERNEL) || defined(_KERNEL)
1121 au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod,
1122     struct timeval tm)
1123 #else
1124 au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod)
1125 #endif
1126 {
1127 	token_t *t;
1128 	u_char *dptr = NULL;
1129 	u_int32_t timems;
1130 #if !defined(KERNEL) && !defined(_KERNEL)
1131 	struct timeval tm;
1132 	struct timezone tzp;
1133 
1134 	if (gettimeofday(&tm, &tzp) == -1)
1135 		return (NULL);
1136 #endif
1137 
1138 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
1139 	    sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
1140 	if (t == NULL)
1141 		return (NULL);
1142 
1143 	ADD_U_CHAR(dptr, AUT_HEADER32);
1144 	ADD_U_INT32(dptr, rec_size);
1145 	ADD_U_CHAR(dptr, HEADER_VERSION);
1146 	ADD_U_INT16(dptr, e_type);
1147 	ADD_U_INT16(dptr, e_mod);
1148 
1149 	timems = tm.tv_usec/1000;
1150 	/* Add the timestamp */
1151 	ADD_U_INT32(dptr, tm.tv_sec);
1152 	ADD_U_INT32(dptr, timems);	/* We need time in ms. */
1153 
1154 	return (t);
1155 }
1156 
1157 token_t *
1158 au_to_header64(__unused int rec_size, __unused au_event_t e_type,
1159     __unused au_emod_t e_mod)
1160 {
1161 
1162 	errno = ENOTSUP;
1163 	return (NULL);
1164 }
1165 
1166 token_t *
1167 au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod)
1168 {
1169 
1170 	return (au_to_header32(rec_size, e_type, e_mod));
1171 }
1172 
1173 /*
1174  * token ID                1 byte
1175  * trailer magic number    2 bytes
1176  * record byte count       4 bytes
1177  */
1178 token_t *
1179 au_to_trailer(int rec_size)
1180 {
1181 	token_t *t;
1182 	u_char *dptr = NULL;
1183 	u_int16_t magic = TRAILER_PAD_MAGIC;
1184 
1185 	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
1186 	    sizeof(u_int32_t));
1187 	if (t == NULL)
1188 		return (NULL);
1189 
1190 	ADD_U_CHAR(dptr, AUT_TRAILER);
1191 	ADD_U_INT16(dptr, magic);
1192 	ADD_U_INT32(dptr, rec_size);
1193 
1194 	return (t);
1195 }
1196