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