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