xref: /freebsd/contrib/openbsm/libbsm/bsm_token.c (revision d056fa046c6a91b90cd98165face0e42a33a5173)
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#48 $
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 	/* 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  */
289 token_t *
290 au_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  */
308 token_t *
309 au_to_groups(int *groups)
310 {
311 
312 	return (au_to_newgroups(BSM_MAX_GROUPS, groups));
313 }
314 
315 /*
316  * token ID                1 byte
317  * number groups           2 bytes
318  * group list              count * 4 bytes
319  */
320 token_t *
321 au_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  */
344 token_t *
345 au_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  */
365 token_t *
366 au_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  */
387 token_t *
388 au_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  */
411 token_t *
412 au_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  */
438 token_t *
439 au_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  */
491 token_t *
492 au_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  */
512 token_t *
513 au_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  */
536 token_t *
537 au_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  */
568 token_t *
569 au_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  */
594 token_t *
595 au_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  */
628 token_t *
629 au_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 
653 token_t *
654 au_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 
663 token_t *
664 au_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  */
687 token_t *
688 au_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 
727 token_t *
728 au_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 
736 token_t *
737 au_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  */
750 token_t *
751 au_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 
767 token_t *
768 au_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 
784 token_t *
785 au_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  */
795 token_t *
796 au_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  */
816 token_t *
817 au_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  */
841 token_t *
842 au_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 
873 token_t *
874 au_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 
899 token_t *
900 au_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  */
919 token_t *
920 au_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 
944 token_t *
945 au_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 
953 token_t *
954 au_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  */
976 token_t *
977 au_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 
1016 token_t *
1017 au_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 
1025 token_t *
1026 au_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  */
1039 token_t *
1040 au_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  */
1057 token_t *
1058 au_to_exec_args(const char **args)
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 = *args;
1067 
1068 	while (nextarg != NULL) {
1069 		int nextlen;
1070 
1071 		nextlen = strlen(nextarg);
1072 		totlen += nextlen + 1;
1073 		count++;
1074 		nextarg = *(args + 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 = *(args + 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  */
1098 token_t *
1099 au_to_exec_env(const char **env)
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 = *env;
1108 
1109 	while (nextenv != NULL) {
1110 		int nextlen;
1111 
1112 		nextlen = strlen(nextenv);
1113 		totlen += nextlen + 1;
1114 		count++;
1115 		nextenv = *(env + 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 = *(env + 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  */
1143 token_t *
1144 au_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, HEADER_VERSION);
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)
1171 token_t *
1172 au_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 
1181 token_t *
1182 au_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 
1190 token_t *
1191 au_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  */
1203 token_t *
1204 au_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