]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/openbsm/libbsm/bsm_token.c
Merge OpenBSM alpha 4 from OpenBSM vendor branch to head, both
[FreeBSD/FreeBSD.git] / contrib / openbsm / libbsm / bsm_token.c
1 /*-
2  * Copyright (c) 2004-2008 Apple Inc.
3  * Copyright (c) 2005 SPARTA, Inc.
4  * All rights reserved.
5  *
6  * This code was developed in part by Robert N. M. Watson, Senior Principal
7  * Scientist, SPARTA, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1.  Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  * 2.  Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
18  *     its contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
25  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_token.c#85 $
34  */
35
36 #include <sys/types.h>
37
38 #include <config/config.h>
39 #if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BE32ENC)
40 #include <sys/endian.h>
41 #else /* !HAVE_SYS_ENDIAN_H || !HAVE_BE32ENC */
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 || !HAVE_BE32ENC */
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  */
100 token_t *
101 au_to_arg32(char n, const 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 token_t *
125 au_to_arg64(char n, const char *text, u_int64_t v)
126 {
127         token_t *t;
128         u_char *dptr = NULL;
129         u_int16_t textlen;
130
131         textlen = strlen(text);
132         textlen += 1;
133
134         GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t) +
135             sizeof(u_int16_t) + textlen);
136         if (t == NULL)
137                 return (NULL);
138
139         ADD_U_CHAR(dptr, AUT_ARG64);
140         ADD_U_CHAR(dptr, n);
141         ADD_U_INT64(dptr, v);
142         ADD_U_INT16(dptr, textlen);
143         ADD_STRING(dptr, text, textlen);
144
145         return (t);
146 }
147
148 token_t *
149 au_to_arg(char n, const char *text, u_int32_t v)
150 {
151
152         return (au_to_arg32(n, text, v));
153 }
154
155 #if defined(_KERNEL) || defined(KERNEL)
156 /*
157  * token ID                1 byte
158  * file access mode        4 bytes
159  * owner user ID           4 bytes
160  * owner group ID          4 bytes
161  * file system ID          4 bytes
162  * node ID                 8 bytes
163  * device                  4 bytes/8 bytes (32-bit/64-bit)
164  */
165 token_t *
166 au_to_attr32(struct vnode_au_info *vni)
167 {
168         token_t *t;
169         u_char *dptr = NULL;
170         u_int16_t pad0_16 = 0;
171         u_int16_t pad0_32 = 0;
172
173         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
174             3 * sizeof(u_int32_t) + sizeof(u_int64_t) + sizeof(u_int32_t));
175         if (t == NULL)
176                 return (NULL);
177
178         ADD_U_CHAR(dptr, AUT_ATTR32);
179
180         /*
181          * BSD defines the size for the file mode as 2 bytes; BSM defines 4
182          * so pad with 0.
183          *
184          * XXXRW: Possibly should be conditionally compiled.
185          *
186          * XXXRW: Should any conversions take place on the mode?
187          */
188         ADD_U_INT16(dptr, pad0_16);
189         ADD_U_INT16(dptr, vni->vn_mode);
190
191         ADD_U_INT32(dptr, vni->vn_uid);
192         ADD_U_INT32(dptr, vni->vn_gid);
193         ADD_U_INT32(dptr, vni->vn_fsid);
194
195         /*
196          * Some systems use 32-bit file ID's, others use 64-bit file IDs.
197          * Attempt to handle both, and let the compiler sort it out.  If we
198          * could pick this out at compile-time, it would be better, so as to
199          * avoid the else case below.
200          */
201         if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
202                 ADD_U_INT32(dptr, pad0_32);
203                 ADD_U_INT32(dptr, vni->vn_fileid);
204         } else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
205                 ADD_U_INT64(dptr, vni->vn_fileid);
206         else
207                 ADD_U_INT64(dptr, 0LL);
208
209         ADD_U_INT32(dptr, vni->vn_dev);
210
211         return (t);
212 }
213
214 token_t *
215 au_to_attr64(struct vnode_au_info *vni)
216 {
217         token_t *t;
218         u_char *dptr = NULL;
219         u_int16_t pad0_16 = 0;
220         u_int16_t pad0_32 = 0;
221
222         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
223             3 * sizeof(u_int32_t) + sizeof(u_int64_t) * 2);
224         if (t == NULL)
225                 return (NULL);
226
227         ADD_U_CHAR(dptr, AUT_ATTR64);
228
229         /*
230          * BSD defines the size for the file mode as 2 bytes; BSM defines 4
231          * so pad with 0.
232          *
233          * XXXRW: Possibly should be conditionally compiled.
234          *
235          * XXXRW: Should any conversions take place on the mode?
236          */
237         ADD_U_INT16(dptr, pad0_16);
238         ADD_U_INT16(dptr, vni->vn_mode);
239
240         ADD_U_INT32(dptr, vni->vn_uid);
241         ADD_U_INT32(dptr, vni->vn_gid);
242         ADD_U_INT32(dptr, vni->vn_fsid);
243
244         /*
245          * Some systems use 32-bit file ID's, other's use 64-bit file IDs.
246          * Attempt to handle both, and let the compiler sort it out.  If we
247          * could pick this out at compile-time, it would be better, so as to
248          * avoid the else case below.
249          */
250         if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
251                 ADD_U_INT32(dptr, pad0_32);
252                 ADD_U_INT32(dptr, vni->vn_fileid);
253         } else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
254                 ADD_U_INT64(dptr, vni->vn_fileid);
255         else
256                 ADD_U_INT64(dptr, 0LL);
257
258         ADD_U_INT64(dptr, vni->vn_dev);
259
260         return (t);
261 }
262
263 token_t *
264 au_to_attr(struct vnode_au_info *vni)
265 {
266
267         return (au_to_attr32(vni));
268 }
269 #endif /* !(defined(_KERNEL) || defined(KERNEL) */
270
271 /*
272  * token ID                1 byte
273  * how to print            1 byte
274  * basic unit              1 byte
275  * unit count              1 byte
276  * data items              (depends on basic unit)
277  */
278 token_t *
279 au_to_data(char unit_print, char unit_type, char unit_count, const char *p)
280 {
281         token_t *t;
282         u_char *dptr = NULL;
283         size_t datasize, totdata;
284
285         /* Determine the size of the basic unit. */
286         switch (unit_type) {
287         case AUR_BYTE:
288         /* case AUR_CHAR: */
289                 datasize = AUR_BYTE_SIZE;
290                 break;
291
292         case AUR_SHORT:
293                 datasize = AUR_SHORT_SIZE;
294                 break;
295
296         case AUR_INT32:
297         /* case AUR_INT: */
298                 datasize = AUR_INT32_SIZE;
299                 break;
300
301         case AUR_INT64:
302                 datasize = AUR_INT64_SIZE;
303                 break;
304
305         default:
306                 errno = EINVAL;
307                 return (NULL);
308         }
309
310         totdata = datasize * unit_count;
311
312         GET_TOKEN_AREA(t, dptr, 4 * sizeof(u_char) + totdata);
313         if (t == NULL)
314                 return (NULL);
315
316         /*
317          * XXXRW: We should be byte-swapping each data item for multi-byte
318          * types.
319          */
320         ADD_U_CHAR(dptr, AUT_DATA);
321         ADD_U_CHAR(dptr, unit_print);
322         ADD_U_CHAR(dptr, unit_type);
323         ADD_U_CHAR(dptr, unit_count);
324         ADD_MEM(dptr, p, totdata);
325
326         return (t);
327 }
328
329
330 /*
331  * token ID                1 byte
332  * status                  4 bytes
333  * return value            4 bytes
334  */
335 token_t *
336 au_to_exit(int retval, int err)
337 {
338         token_t *t;
339         u_char *dptr = NULL;
340
341         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t));
342         if (t == NULL)
343                 return (NULL);
344
345         ADD_U_CHAR(dptr, AUT_EXIT);
346         ADD_U_INT32(dptr, err);
347         ADD_U_INT32(dptr, retval);
348
349         return (t);
350 }
351
352 /*
353  */
354 token_t *
355 au_to_groups(int *groups)
356 {
357
358         return (au_to_newgroups(AUDIT_MAX_GROUPS, (gid_t *)groups));
359 }
360
361 /*
362  * token ID                1 byte
363  * number groups           2 bytes
364  * group list              count * 4 bytes
365  */
366 token_t *
367 au_to_newgroups(u_int16_t n, gid_t *groups)
368 {
369         token_t *t;
370         u_char *dptr = NULL;
371         int i;
372
373         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
374             n * sizeof(u_int32_t));
375         if (t == NULL)
376                 return (NULL);
377
378         ADD_U_CHAR(dptr, AUT_NEWGROUPS);
379         ADD_U_INT16(dptr, n);
380         for (i = 0; i < n; i++)
381                 ADD_U_INT32(dptr, groups[i]);
382
383         return (t);
384 }
385
386 /*
387  * token ID                1 byte
388  * internet address        4 bytes
389  */
390 token_t *
391 au_to_in_addr(struct in_addr *internet_addr)
392 {
393         token_t *t;
394         u_char *dptr = NULL;
395
396         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(uint32_t));
397         if (t == NULL)
398                 return (NULL);
399
400         ADD_U_CHAR(dptr, AUT_IN_ADDR);
401         ADD_MEM(dptr, &internet_addr->s_addr, sizeof(uint32_t));
402
403         return (t);
404 }
405
406 /*
407  * token ID                1 byte
408  * address type/length     4 bytes
409  * address                16 bytes
410  */
411 token_t *
412 au_to_in_addr_ex(struct in6_addr *internet_addr)
413 {
414         token_t *t;
415         u_char *dptr = NULL;
416         u_int32_t type = AU_IPv6;
417
418         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(uint32_t));
419         if (t == NULL)
420                 return (NULL);
421
422         ADD_U_CHAR(dptr, AUT_IN_ADDR_EX);
423         ADD_U_INT32(dptr, type);
424         ADD_MEM(dptr, internet_addr, 4 * sizeof(uint32_t));
425
426         return (t);
427 }
428
429 /*
430  * token ID                1 byte
431  * ip header               20 bytes
432  *
433  * The IP header should be submitted in network byte order.
434  */
435 token_t *
436 au_to_ip(struct ip *ip)
437 {
438         token_t *t;
439         u_char *dptr = NULL;
440
441         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(struct ip));
442         if (t == NULL)
443                 return (NULL);
444
445         ADD_U_CHAR(dptr, AUT_IP);
446         ADD_MEM(dptr, ip, sizeof(struct ip));
447
448         return (t);
449 }
450
451 /*
452  * token ID                1 byte
453  * object ID type          1 byte
454  * object ID               4 bytes
455  */
456 token_t *
457 au_to_ipc(char type, int id)
458 {
459         token_t *t;
460         u_char *dptr = NULL;
461
462         GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
463         if (t == NULL)
464                 return (NULL);
465
466         ADD_U_CHAR(dptr, AUT_IPC);
467         ADD_U_CHAR(dptr, type);
468         ADD_U_INT32(dptr, id);
469
470         return (t);
471 }
472
473 /*
474  * token ID                1 byte
475  * owner user ID           4 bytes
476  * owner group ID          4 bytes
477  * creator user ID         4 bytes
478  * creator group ID        4 bytes
479  * access mode             4 bytes
480  * slot sequence #         4 bytes
481  * key                     4 bytes
482  */
483 token_t *
484 au_to_ipc_perm(struct ipc_perm *perm)
485 {
486         token_t *t;
487         u_char *dptr = NULL;
488         u_int16_t pad0 = 0;
489
490         GET_TOKEN_AREA(t, dptr, 12 * sizeof(u_int16_t) + sizeof(u_int32_t));
491         if (t == NULL)
492                 return (NULL);
493
494         ADD_U_CHAR(dptr, AUT_IPC_PERM);
495
496         /*
497          * Systems vary significantly in what types they use in struct
498          * ipc_perm; at least a few still use 16-bit uid's and gid's, so
499          * allow for that, as BSM define 32-bit values here.
500          * Some systems define the sizes for ipc_perm members as 2 bytes;
501          * BSM defines 4 so pad with 0.
502          *
503          * XXXRW: Possibly shoulid be conditionally compiled, and more cases
504          * need to be handled.
505          */
506         if (sizeof(perm->uid) != sizeof(u_int32_t)) {
507                 ADD_U_INT16(dptr, pad0);
508                 ADD_U_INT16(dptr, perm->uid);
509                 ADD_U_INT16(dptr, pad0);
510                 ADD_U_INT16(dptr, perm->gid);
511                 ADD_U_INT16(dptr, pad0);
512                 ADD_U_INT16(dptr, perm->cuid);
513                 ADD_U_INT16(dptr, pad0);
514                 ADD_U_INT16(dptr, perm->cgid);
515         } else {
516                 ADD_U_INT32(dptr, perm->uid);
517                 ADD_U_INT32(dptr, perm->gid);
518                 ADD_U_INT32(dptr, perm->cuid);
519                 ADD_U_INT32(dptr, perm->cgid);
520         }
521
522         ADD_U_INT16(dptr, pad0);
523         ADD_U_INT16(dptr, perm->mode);
524
525         ADD_U_INT16(dptr, pad0);
526
527 #ifdef HAVE_IPC_PERM___SEQ
528         ADD_U_INT16(dptr, perm->__seq);
529 #else   /* HAVE_IPC_PERM___SEQ */
530 #ifdef  HAVE_IPC_PERM__SEQ
531         ADD_U_INT16(dptr, perm->_seq);
532 #else   /* HAVE_IPC_PERM__SEQ */
533         ADD_U_INT16(dptr, perm->seq);
534 #endif  /* HAVE_IPC_PERM__SEQ */
535 #endif  /* HAVE_IPC_PERM___SEQ */
536
537 #ifdef HAVE_IPC_PERM___KEY
538         ADD_U_INT32(dptr, perm->__key);
539 #else   /* HAVE_IPC_PERM___KEY */
540 #ifdef  HAVE_IPC_PERM__KEY
541         ADD_U_INT32(dptr, perm->_key);
542 #else   /* HAVE_IPC_PERM__KEY */
543         ADD_U_INT32(dptr, perm->key);
544 #endif  /* HAVE_IPC_PERM__KEY */
545 #endif  /* HAVE_IPC_PERM___KEY */
546
547         return (t);
548 }
549
550 /*
551  * token ID                1 byte
552  * port IP address         2 bytes
553  */
554 token_t *
555 au_to_iport(u_int16_t iport)
556 {
557         token_t *t;
558         u_char *dptr = NULL;
559
560         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t));
561         if (t == NULL)
562                 return (NULL);
563
564         ADD_U_CHAR(dptr, AUT_IPORT);
565         ADD_U_INT16(dptr, iport);
566
567         return (t);
568 }
569
570 /*
571  * token ID                1 byte
572  * size                    2 bytes
573  * data                    size bytes
574  */
575 token_t *
576 au_to_opaque(const char *data, u_int16_t bytes)
577 {
578         token_t *t;
579         u_char *dptr = NULL;
580
581         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + bytes);
582         if (t == NULL)
583                 return (NULL);
584
585         ADD_U_CHAR(dptr, AUT_OPAQUE);
586         ADD_U_INT16(dptr, bytes);
587         ADD_MEM(dptr, data, bytes);
588
589         return (t);
590 }
591
592 /*
593  * token ID                1 byte
594  * seconds of time         4 bytes
595  * milliseconds of time    4 bytes
596  * file name len           2 bytes
597  * file pathname           N bytes + 1 terminating NULL byte
598  */
599 token_t *
600 au_to_file(const char *file, struct timeval tm)
601 {
602         token_t *t;
603         u_char *dptr = NULL;
604         u_int16_t filelen;
605         u_int32_t timems;
606
607         filelen = strlen(file);
608         filelen += 1;
609
610         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t) +
611             sizeof(u_int16_t) + filelen);
612         if (t == NULL)
613                 return (NULL);
614
615         timems = tm.tv_usec/1000;
616
617         ADD_U_CHAR(dptr, AUT_OTHER_FILE32);
618         ADD_U_INT32(dptr, tm.tv_sec);
619         ADD_U_INT32(dptr, timems);      /* We need time in ms. */
620         ADD_U_INT16(dptr, filelen);
621         ADD_STRING(dptr, file, filelen);
622
623         return (t);
624 }
625
626 /*
627  * token ID                1 byte
628  * text length             2 bytes
629  * text                    N bytes + 1 terminating NULL byte
630  */
631 token_t *
632 au_to_text(const char *text)
633 {
634         token_t *t;
635         u_char *dptr = NULL;
636         u_int16_t textlen;
637
638         textlen = strlen(text);
639         textlen += 1;
640
641         /* XXXRW: Should validate length against token size limit. */
642
643         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
644         if (t == NULL)
645                 return (NULL);
646
647         ADD_U_CHAR(dptr, AUT_TEXT);
648         ADD_U_INT16(dptr, textlen);
649         ADD_STRING(dptr, text, textlen);
650
651         return (t);
652 }
653
654 /*
655  * token ID                1 byte
656  * path length             2 bytes
657  * path                    N bytes + 1 terminating NULL byte
658  */
659 token_t *
660 au_to_path(const char *text)
661 {
662         token_t *t;
663         u_char *dptr = NULL;
664         u_int16_t textlen;
665
666         textlen = strlen(text);
667         textlen += 1;
668
669         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
670         if (t == NULL)
671                 return (NULL);
672
673         ADD_U_CHAR(dptr, AUT_PATH);
674         ADD_U_INT16(dptr, textlen);
675         ADD_STRING(dptr, text, textlen);
676
677         return (t);
678 }
679
680 /*
681  * token ID                1 byte
682  * audit ID                4 bytes
683  * effective user ID       4 bytes
684  * effective group ID      4 bytes
685  * real user ID            4 bytes
686  * real group ID           4 bytes
687  * process ID              4 bytes
688  * session ID              4 bytes
689  * terminal ID
690  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
691  *   machine address       4 bytes
692  */
693 token_t *
694 au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
695     pid_t pid, au_asid_t sid, au_tid_t *tid)
696 {
697         token_t *t;
698         u_char *dptr = NULL;
699
700         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
701         if (t == NULL)
702                 return (NULL);
703
704         ADD_U_CHAR(dptr, AUT_PROCESS32);
705         ADD_U_INT32(dptr, auid);
706         ADD_U_INT32(dptr, euid);
707         ADD_U_INT32(dptr, egid);
708         ADD_U_INT32(dptr, ruid);
709         ADD_U_INT32(dptr, rgid);
710         ADD_U_INT32(dptr, pid);
711         ADD_U_INT32(dptr, sid);
712         ADD_U_INT32(dptr, tid->port);
713
714         /*
715          * Note: Solaris will write out IPv6 addresses here as a 32-bit
716          * address type and 16 bytes of address, but for IPv4 addresses it
717          * simply writes the 4-byte address directly.  We support only IPv4
718          * addresses for process32 tokens.
719          */
720         ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
721
722         return (t);
723 }
724
725 token_t *
726 au_to_process64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
727     pid_t pid, au_asid_t sid, au_tid_t *tid)
728 {
729         token_t *t;
730         u_char *dptr = NULL;
731
732         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 8 * sizeof(u_int32_t) +
733             sizeof(u_int64_t));
734         if (t == NULL)
735                 return (NULL);
736
737         ADD_U_CHAR(dptr, AUT_PROCESS64);
738         ADD_U_INT32(dptr, auid);
739         ADD_U_INT32(dptr, euid);
740         ADD_U_INT32(dptr, egid);
741         ADD_U_INT32(dptr, ruid);
742         ADD_U_INT32(dptr, rgid);
743         ADD_U_INT32(dptr, pid);
744         ADD_U_INT32(dptr, sid);
745         ADD_U_INT64(dptr, tid->port);
746
747         /*
748          * Note: Solaris will write out IPv6 addresses here as a 32-bit
749          * address type and 16 bytes of address, but for IPv4 addresses it
750          * simply writes the 4-byte address directly.  We support only IPv4
751          * addresses for process64 tokens.
752          */
753         ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
754
755         return (t);
756 }
757
758 token_t *
759 au_to_process(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
760     pid_t pid, au_asid_t sid, au_tid_t *tid)
761 {
762
763         return (au_to_process32(auid, euid, egid, ruid, rgid, pid, sid,
764             tid));
765 }
766
767 /*
768  * token ID                1 byte
769  * audit ID                4 bytes
770  * effective user ID       4 bytes
771  * effective group ID      4 bytes
772  * real user ID            4 bytes
773  * real group ID           4 bytes
774  * process ID              4 bytes
775  * session ID              4 bytes
776  * terminal ID
777  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
778  *   address type-len      4 bytes
779  *   machine address      16 bytes
780  */
781 token_t *
782 au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
783     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
784 {
785         token_t *t;
786         u_char *dptr = NULL;
787
788         if (tid->at_type == AU_IPv4)
789                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
790                     10 * sizeof(u_int32_t));
791         else if (tid->at_type == AU_IPv6)
792                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
793                     13 * sizeof(u_int32_t));
794         else {
795                 errno = EINVAL;
796                 return (NULL);
797         }
798         if (t == NULL)
799                 return (NULL);
800
801         ADD_U_CHAR(dptr, AUT_PROCESS32_EX);
802         ADD_U_INT32(dptr, auid);
803         ADD_U_INT32(dptr, euid);
804         ADD_U_INT32(dptr, egid);
805         ADD_U_INT32(dptr, ruid);
806         ADD_U_INT32(dptr, rgid);
807         ADD_U_INT32(dptr, pid);
808         ADD_U_INT32(dptr, sid);
809         ADD_U_INT32(dptr, tid->at_port);
810         ADD_U_INT32(dptr, tid->at_type);
811         ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
812         if (tid->at_type == AU_IPv6) {
813                 ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t));
814                 ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t));
815                 ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t));
816         }
817
818         return (t);
819 }
820
821 token_t *
822 au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
823     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
824 {
825         token_t *t;
826         u_char *dptr = NULL;
827
828         if (tid->at_type == AU_IPv4)
829                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
830                     7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
831                     2 * sizeof(u_int32_t));
832         else if (tid->at_type == AU_IPv6)
833                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
834                     7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
835                     5 * sizeof(u_int32_t));
836         else {
837                 errno = EINVAL;
838                 return (NULL);
839         }
840         if (t == NULL)
841                 return (NULL);
842
843         ADD_U_CHAR(dptr, AUT_PROCESS64_EX);
844         ADD_U_INT32(dptr, auid);
845         ADD_U_INT32(dptr, euid);
846         ADD_U_INT32(dptr, egid);
847         ADD_U_INT32(dptr, ruid);
848         ADD_U_INT32(dptr, rgid);
849         ADD_U_INT32(dptr, pid);
850         ADD_U_INT32(dptr, sid);
851         ADD_U_INT64(dptr, tid->at_port);
852         ADD_U_INT32(dptr, tid->at_type);
853         ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
854         if (tid->at_type == AU_IPv6) {
855                 ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t));
856                 ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t));
857                 ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t));
858         }
859
860         return (t);
861 }
862
863 token_t *
864 au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
865     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
866 {
867
868         return (au_to_process32_ex(auid, euid, egid, ruid, rgid, pid, sid,
869             tid));
870 }
871
872 /*
873  * token ID                1 byte
874  * error status            1 byte
875  * return value            4 bytes/8 bytes (32-bit/64-bit value)
876  */
877 token_t *
878 au_to_return32(char status, u_int32_t ret)
879 {
880         token_t *t;
881         u_char *dptr = NULL;
882
883         GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
884         if (t == NULL)
885                 return (NULL);
886
887         ADD_U_CHAR(dptr, AUT_RETURN32);
888         ADD_U_CHAR(dptr, status);
889         ADD_U_INT32(dptr, ret);
890
891         return (t);
892 }
893
894 token_t *
895 au_to_return64(char status, u_int64_t ret)
896 {
897         token_t *t;
898         u_char *dptr = NULL;
899
900         GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t));
901         if (t == NULL)
902                 return (NULL);
903
904         ADD_U_CHAR(dptr, AUT_RETURN64);
905         ADD_U_CHAR(dptr, status);
906         ADD_U_INT64(dptr, ret);
907
908         return (t);
909 }
910
911 token_t *
912 au_to_return(char status, u_int32_t ret)
913 {
914
915         return (au_to_return32(status, ret));
916 }
917
918 /*
919  * token ID                1 byte
920  * sequence number         4 bytes
921  */
922 token_t *
923 au_to_seq(long audit_count)
924 {
925         token_t *t;
926         u_char *dptr = NULL;
927
928         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t));
929         if (t == NULL)
930                 return (NULL);
931
932         ADD_U_CHAR(dptr, AUT_SEQ);
933         ADD_U_INT32(dptr, audit_count);
934
935         return (t);
936 }
937
938 /*
939  * token ID                1 byte
940  * socket domain           2 bytes
941  * socket type             2 bytes
942  * address type            2 byte
943  * local port              2 bytes
944  * local address           4 bytes/16 bytes (IPv4/IPv6 address)
945  * remote port             2 bytes
946  * remote address          4 bytes/16 bytes (IPv4/IPv6 address)
947  */
948 token_t *
949 au_to_socket_ex(u_short so_domain, u_short so_type,
950     struct sockaddr *sa_local, struct sockaddr *sa_remote)
951 {
952         token_t *t;
953         u_char *dptr = NULL;
954         struct sockaddr_in *sin;
955         struct sockaddr_in6 *sin6;
956
957         if (so_domain == AF_INET)
958                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
959                     5 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
960         else if (so_domain == AF_INET6)
961                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
962                     5 * sizeof(u_int16_t) + 16 * sizeof(u_int32_t));
963         else {
964                 errno = EINVAL;
965                 return (NULL);
966         }
967
968         ADD_U_CHAR(dptr, AUT_SOCKET_EX);
969         ADD_U_INT16(dptr, so_domain);   /* XXXRW: explicitly convert? */
970         ADD_U_INT16(dptr, so_type);     /* XXXRW: explicitly convert? */
971         if (so_domain == AF_INET) {
972                 ADD_U_INT16(dptr, AU_IPv4);
973                 sin = (struct sockaddr_in *)sa_local;
974                 ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t));
975                 ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t));
976                 sin = (struct sockaddr_in *)sa_remote;
977                 ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t));
978                 ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t));
979         } else {
980                 ADD_U_INT16(dptr, AU_IPv6);
981                 sin6 = (struct sockaddr_in6 *)sa_local;
982                 ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t));
983                 ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t));
984                 sin6 = (struct sockaddr_in6 *)sa_remote;
985                 ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t));
986                 ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t));
987         }
988
989         return (t);
990 }
991
992 /*
993  * token ID                1 byte
994  * socket family           2 bytes
995  * path                    104 bytes
996  */
997 token_t *
998 au_to_sock_unix(struct sockaddr_un *so)
999 {
1000         token_t *t;
1001         u_char *dptr;
1002
1003         GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + strlen(so->sun_path) + 1);
1004         if (t == NULL)
1005                 return (NULL);
1006
1007         ADD_U_CHAR(dptr, AUT_SOCKUNIX);
1008         /* BSM token has two bytes for family */
1009         ADD_U_CHAR(dptr, 0);
1010         ADD_U_CHAR(dptr, so->sun_family);
1011         ADD_STRING(dptr, so->sun_path, strlen(so->sun_path) + 1);
1012
1013         return (t);
1014 }
1015
1016 /*
1017  * token ID                1 byte
1018  * socket family           2 bytes
1019  * local port              2 bytes
1020  * socket address          4 bytes
1021  */
1022 token_t *
1023 au_to_sock_inet32(struct sockaddr_in *so)
1024 {
1025         token_t *t;
1026         u_char *dptr = NULL;
1027         uint16_t family;
1028
1029         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(uint16_t) +
1030             sizeof(uint32_t));
1031         if (t == NULL)
1032                 return (NULL);
1033
1034         ADD_U_CHAR(dptr, AUT_SOCKINET32);
1035         /*
1036          * BSM defines the family field as 16 bits, but many operating
1037          * systems have an 8-bit sin_family field.  Extend to 16 bits before
1038          * writing into the token.  Assume that both the port and the address
1039          * in the sockaddr_in are already in network byte order, but family
1040          * is in local byte order.
1041          *
1042          * XXXRW: Should a name space conversion be taking place on the value
1043          * of sin_family?
1044          */
1045         family = so->sin_family;
1046         ADD_U_INT16(dptr, family);
1047         ADD_MEM(dptr, &so->sin_port, sizeof(uint16_t));
1048         ADD_MEM(dptr, &so->sin_addr.s_addr, sizeof(uint32_t));
1049
1050         return (t);
1051 }
1052
1053 token_t *
1054 au_to_sock_inet128(struct sockaddr_in6 *so)
1055 {
1056         token_t *t;
1057         u_char *dptr = NULL;
1058
1059         GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
1060             4 * sizeof(u_int32_t));
1061         if (t == NULL)
1062                 return (NULL);
1063
1064         ADD_U_CHAR(dptr, AUT_SOCKINET128);
1065         /*
1066          * In BSD, sin6_family is one octet, but BSM defines the token to
1067          * store two. So we copy in a 0 first.  XXXRW: Possibly should be
1068          * conditionally compiled.
1069          */
1070         ADD_U_CHAR(dptr, 0);
1071         ADD_U_CHAR(dptr, so->sin6_family);
1072
1073         ADD_U_INT16(dptr, so->sin6_port);
1074         ADD_MEM(dptr, &so->sin6_addr, 4 * sizeof(uint32_t));
1075
1076         return (t);
1077 }
1078
1079 token_t *
1080 au_to_sock_inet(struct sockaddr_in *so)
1081 {
1082
1083         return (au_to_sock_inet32(so));
1084 }
1085
1086 /*
1087  * token ID                1 byte
1088  * audit ID                4 bytes
1089  * effective user ID       4 bytes
1090  * effective group ID      4 bytes
1091  * real user ID            4 bytes
1092  * real group ID           4 bytes
1093  * process ID              4 bytes
1094  * session ID              4 bytes
1095  * terminal ID
1096  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
1097  *   machine address       4 bytes
1098  */
1099 token_t *
1100 au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
1101     pid_t pid, au_asid_t sid, au_tid_t *tid)
1102 {
1103         token_t *t;
1104         u_char *dptr = NULL;
1105
1106         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
1107         if (t == NULL)
1108                 return (NULL);
1109
1110         ADD_U_CHAR(dptr, AUT_SUBJECT32);
1111         ADD_U_INT32(dptr, auid);
1112         ADD_U_INT32(dptr, euid);
1113         ADD_U_INT32(dptr, egid);
1114         ADD_U_INT32(dptr, ruid);
1115         ADD_U_INT32(dptr, rgid);
1116         ADD_U_INT32(dptr, pid);
1117         ADD_U_INT32(dptr, sid);
1118         ADD_U_INT32(dptr, tid->port);
1119         ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
1120
1121         return (t);
1122 }
1123
1124 token_t *
1125 au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
1126     pid_t pid, au_asid_t sid, au_tid_t *tid)
1127 {
1128         token_t *t;
1129         u_char *dptr = NULL;
1130
1131         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) +
1132             sizeof(u_int64_t) + sizeof(u_int32_t));
1133         if (t == NULL)
1134                 return (NULL);
1135
1136         ADD_U_CHAR(dptr, AUT_SUBJECT64);
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->port);
1145         ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
1146
1147         return (t);
1148 }
1149
1150 token_t *
1151 au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
1152     pid_t pid, au_asid_t sid, au_tid_t *tid)
1153 {
1154
1155         return (au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
1156             tid));
1157 }
1158
1159 /*
1160  * token ID                1 byte
1161  * audit ID                4 bytes
1162  * effective user ID       4 bytes
1163  * effective group ID      4 bytes
1164  * real user ID            4 bytes
1165  * real group ID           4 bytes
1166  * process ID              4 bytes
1167  * session ID              4 bytes
1168  * terminal ID
1169  *   port ID               4 bytes/8 bytes (32-bit/64-bit value)
1170  *   address type/length   4 bytes
1171  *   machine address      16 bytes
1172  */
1173 token_t *
1174 au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
1175     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
1176 {
1177         token_t *t;
1178         u_char *dptr = NULL;
1179
1180         if (tid->at_type == AU_IPv4)
1181                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 10 *
1182                     sizeof(u_int32_t));
1183         else if (tid->at_type == AU_IPv6)
1184                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 *
1185                     sizeof(u_int32_t));
1186         else {
1187                 errno = EINVAL;
1188                 return (NULL);
1189         }
1190         if (t == NULL)
1191                 return (NULL);
1192
1193         ADD_U_CHAR(dptr, AUT_SUBJECT32_EX);
1194         ADD_U_INT32(dptr, auid);
1195         ADD_U_INT32(dptr, euid);
1196         ADD_U_INT32(dptr, egid);
1197         ADD_U_INT32(dptr, ruid);
1198         ADD_U_INT32(dptr, rgid);
1199         ADD_U_INT32(dptr, pid);
1200         ADD_U_INT32(dptr, sid);
1201         ADD_U_INT32(dptr, tid->at_port);
1202         ADD_U_INT32(dptr, tid->at_type);
1203         if (tid->at_type == AU_IPv6)
1204                 ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
1205         else
1206                 ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
1207
1208         return (t);
1209 }
1210
1211 token_t *
1212 au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
1213     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
1214 {
1215         token_t *t;
1216         u_char *dptr = NULL;
1217
1218         if (tid->at_type == AU_IPv4)
1219                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
1220                     7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
1221                     2 * sizeof(u_int32_t));
1222         else if (tid->at_type == AU_IPv6)
1223                 GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
1224                     7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
1225                     5 * sizeof(u_int32_t));
1226         else {
1227                 errno = EINVAL;
1228                 return (NULL);
1229         }
1230         if (t == NULL)
1231                 return (NULL);
1232
1233         ADD_U_CHAR(dptr, AUT_SUBJECT64_EX);
1234         ADD_U_INT32(dptr, auid);
1235         ADD_U_INT32(dptr, euid);
1236         ADD_U_INT32(dptr, egid);
1237         ADD_U_INT32(dptr, ruid);
1238         ADD_U_INT32(dptr, rgid);
1239         ADD_U_INT32(dptr, pid);
1240         ADD_U_INT32(dptr, sid);
1241         ADD_U_INT64(dptr, tid->at_port);
1242         ADD_U_INT32(dptr, tid->at_type);
1243         if (tid->at_type == AU_IPv6)
1244                 ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
1245         else
1246                 ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
1247
1248         return (t);
1249 }
1250
1251 token_t *
1252 au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
1253     gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
1254 {
1255
1256         return (au_to_subject32_ex(auid, euid, egid, ruid, rgid, pid, sid,
1257             tid));
1258 }
1259
1260 #if !defined(_KERNEL) && !defined(KERNEL) && defined(HAVE_AUDIT_SYSCALLS)
1261 /*
1262  * Collects audit information for the current process and creates a subject
1263  * token from it.
1264  */
1265 token_t *
1266 au_to_me(void)
1267 {
1268         auditinfo_t auinfo;
1269
1270         if (getaudit(&auinfo) != 0)
1271                 return (NULL);
1272
1273         return (au_to_subject32(auinfo.ai_auid, geteuid(), getegid(),
1274             getuid(), getgid(), getpid(), auinfo.ai_asid, &auinfo.ai_termid));
1275 }
1276 #endif
1277
1278 /*
1279  * token ID                             1 byte
1280  * count                                4 bytes
1281  * text                                 count null-terminated strings
1282  */
1283 token_t *
1284 au_to_exec_args(char **argv)
1285 {
1286         token_t *t;
1287         u_char *dptr = NULL;
1288         const char *nextarg;
1289         int i, count = 0;
1290         size_t totlen = 0;
1291
1292         nextarg = *argv;
1293
1294         while (nextarg != NULL) {
1295                 int nextlen;
1296
1297                 nextlen = strlen(nextarg);
1298                 totlen += nextlen + 1;
1299                 count++;
1300                 nextarg = *(argv + count);
1301         }
1302
1303         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
1304         if (t == NULL)
1305                 return (NULL);
1306
1307         ADD_U_CHAR(dptr, AUT_EXEC_ARGS);
1308         ADD_U_INT32(dptr, count);
1309
1310         for (i = 0; i < count; i++) {
1311                 nextarg = *(argv + i);
1312                 ADD_MEM(dptr, nextarg, strlen(nextarg) + 1);
1313         }
1314
1315         return (t);
1316 }
1317
1318 /*
1319  * token ID                             1 byte
1320  * count                                4 bytes
1321  * text                                 count null-terminated strings
1322  */
1323 token_t *
1324 au_to_exec_env(char **envp)
1325 {
1326         token_t *t;
1327         u_char *dptr = NULL;
1328         int i, count = 0;
1329         size_t totlen = 0;
1330         const char *nextenv;
1331
1332         nextenv = *envp;
1333
1334         while (nextenv != NULL) {
1335                 int nextlen;
1336
1337                 nextlen = strlen(nextenv);
1338                 totlen += nextlen + 1;
1339                 count++;
1340                 nextenv = *(envp + count);
1341         }
1342
1343         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
1344         if (t == NULL)
1345                 return (NULL);
1346
1347         ADD_U_CHAR(dptr, AUT_EXEC_ENV);
1348         ADD_U_INT32(dptr, count);
1349
1350         for (i = 0; i < count; i++) {
1351                 nextenv = *(envp + i);
1352                 ADD_MEM(dptr, nextenv, strlen(nextenv) + 1);
1353         }
1354
1355         return (t);
1356 }
1357
1358 /*
1359  * token ID                1 byte
1360  * zonename length         2 bytes
1361  * zonename                N bytes + 1 terminating NULL byte
1362  */
1363 token_t *
1364 au_to_zonename(const char *zonename)
1365 {
1366         u_char *dptr = NULL;
1367         u_int16_t textlen;
1368         token_t *t;
1369
1370         textlen = strlen(zonename) + 1;
1371         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
1372         if (t == NULL)
1373                 return (NULL);
1374
1375         ADD_U_CHAR(dptr, AUT_ZONENAME);
1376         ADD_U_INT16(dptr, textlen);
1377         ADD_STRING(dptr, zonename, textlen);
1378         return (t);
1379 }
1380
1381 /*
1382  * token ID                1 byte
1383  * record byte count       4 bytes
1384  * version #               1 byte    [2]
1385  * event type              2 bytes
1386  * event modifier          2 bytes
1387  * seconds of time         4 bytes/8 bytes (32-bit/64-bit value)
1388  * milliseconds of time    4 bytes/8 bytes (32-bit/64-bit value)
1389  */
1390 token_t *
1391 au_to_header32_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
1392     struct timeval tm)
1393 {
1394         token_t *t;
1395         u_char *dptr = NULL;
1396         u_int32_t timems;
1397
1398         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
1399             sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
1400         if (t == NULL)
1401                 return (NULL);
1402
1403         ADD_U_CHAR(dptr, AUT_HEADER32);
1404         ADD_U_INT32(dptr, rec_size);
1405         ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
1406         ADD_U_INT16(dptr, e_type);
1407         ADD_U_INT16(dptr, e_mod);
1408
1409         timems = tm.tv_usec/1000;
1410         /* Add the timestamp */
1411         ADD_U_INT32(dptr, tm.tv_sec);
1412         ADD_U_INT32(dptr, timems);      /* We need time in ms. */
1413
1414         return (t);
1415 }
1416
1417 /*
1418  * token ID                1 byte
1419  * record byte count       4 bytes
1420  * version #               1 byte    [2]
1421  * event type              2 bytes
1422  * event modifier          2 bytes
1423  * address type/length     4 bytes
1424  * machine address         4 bytes/16 bytes (IPv4/IPv6 address)
1425  * seconds of time         4 bytes/8 bytes (32-bit/64-bit value)
1426  * milliseconds of time    4 bytes/8 bytes (32-bit/64-bit value)
1427  */
1428 token_t *
1429 au_to_header32_ex_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
1430     struct timeval tm, struct auditinfo_addr *aia)
1431 {
1432         token_t *t;
1433         u_char *dptr = NULL;
1434         u_int32_t timems;
1435         au_tid_addr_t *tid;
1436
1437         tid = &aia->ai_termid;
1438         if (tid->at_type != AU_IPv4 && tid->at_type != AU_IPv6)
1439                 return (NULL);
1440         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
1441             sizeof(u_char) + 2 * sizeof(u_int16_t) + 3 *
1442             sizeof(u_int32_t) + tid->at_type);
1443         if (t == NULL) 
1444                 return (NULL);
1445
1446         ADD_U_CHAR(dptr, AUT_HEADER32_EX);
1447         ADD_U_INT32(dptr, rec_size);
1448         ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
1449         ADD_U_INT16(dptr, e_type);
1450         ADD_U_INT16(dptr, e_mod);
1451
1452         ADD_U_INT32(dptr, tid->at_type);
1453         if (tid->at_type == AU_IPv6)
1454                 ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
1455         else
1456                 ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
1457         timems = tm.tv_usec/1000;
1458         /* Add the timestamp */
1459         ADD_U_INT32(dptr, tm.tv_sec);
1460         ADD_U_INT32(dptr, timems);      /* We need time in ms. */
1461
1462         return (t);   
1463 }
1464
1465 token_t *
1466 au_to_header64_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
1467     struct timeval tm)
1468 {
1469         token_t *t;
1470         u_char *dptr = NULL;
1471         u_int32_t timems;
1472
1473         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
1474             sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int64_t));
1475         if (t == NULL)
1476                 return (NULL);
1477
1478         ADD_U_CHAR(dptr, AUT_HEADER64);
1479         ADD_U_INT32(dptr, rec_size);
1480         ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
1481         ADD_U_INT16(dptr, e_type);
1482         ADD_U_INT16(dptr, e_mod);
1483
1484         timems = tm.tv_usec/1000;
1485         /* Add the timestamp */
1486         ADD_U_INT64(dptr, tm.tv_sec);
1487         ADD_U_INT64(dptr, timems);      /* We need time in ms. */
1488
1489         return (t);
1490 }
1491
1492 #if !defined(KERNEL) && !defined(_KERNEL)
1493 #ifdef HAVE_AUDIT_SYSCALLS
1494 token_t *
1495 au_to_header32_ex(int rec_size, au_event_t e_type, au_emod_t e_mod)
1496 {
1497         struct timeval tm;
1498         struct auditinfo_addr aia;
1499
1500         if (gettimeofday(&tm, NULL) == -1)
1501                 return (NULL);
1502         if (auditon(A_GETKAUDIT, &aia, sizeof(aia)) < 0) {
1503                 if (errno != ENOSYS)
1504                         return (NULL);
1505                 return (au_to_header32_tm(rec_size, e_type, e_mod, tm));
1506         }
1507         return (au_to_header32_ex_tm(rec_size, e_type, e_mod, tm, &aia));
1508 }
1509 #endif /* HAVE_AUDIT_SYSCALLS */
1510
1511 token_t *
1512 au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod)
1513 {
1514         struct timeval tm;
1515
1516         if (gettimeofday(&tm, NULL) == -1)
1517                 return (NULL);
1518         return (au_to_header32_tm(rec_size, e_type, e_mod, tm));
1519 }
1520
1521 token_t *
1522 au_to_header64(__unused int rec_size, __unused au_event_t e_type,
1523     __unused au_emod_t e_mod)
1524 {
1525         struct timeval tm;
1526
1527         if (gettimeofday(&tm, NULL) == -1)
1528                 return (NULL);
1529         return (au_to_header64_tm(rec_size, e_type, e_mod, tm));
1530 }
1531
1532 token_t *
1533 au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod)
1534 {
1535
1536         return (au_to_header32(rec_size, e_type, e_mod));
1537 }
1538
1539 #ifdef HAVE_AUDIT_SYSCALLS
1540 token_t *
1541 au_to_header_ex(int rec_size, au_event_t e_type, au_emod_t e_mod)
1542 {
1543
1544         return (au_to_header32_ex(rec_size, e_type, e_mod));
1545 }
1546 #endif /* HAVE_AUDIT_SYSCALLS */
1547 #endif /* !defined(KERNEL) && !defined(_KERNEL) */
1548
1549 /*
1550  * token ID                1 byte
1551  * trailer magic number    2 bytes
1552  * record byte count       4 bytes
1553  */
1554 token_t *
1555 au_to_trailer(int rec_size)
1556 {
1557         token_t *t;
1558         u_char *dptr = NULL;
1559         u_int16_t magic = AUT_TRAILER_MAGIC;
1560
1561         GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
1562             sizeof(u_int32_t));
1563         if (t == NULL)
1564                 return (NULL);
1565
1566         ADD_U_CHAR(dptr, AUT_TRAILER);
1567         ADD_U_INT16(dptr, magic);
1568         ADD_U_INT32(dptr, rec_size);
1569
1570         return (t);
1571 }