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 } 1400