1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * adt_token.c 23 * 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 * 27 * This file does not provide any user callable functions. See adt.c 28 */ 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <bsm/adt.h> 32 #include <bsm/adt_event.h> 33 #include <bsm/audit.h> 34 #include <adt_xlate.h> 35 #include <assert.h> 36 #include <netdb.h> 37 #include <priv.h> 38 #include <string.h> 39 #include <strings.h> 40 #include <sys/priv_names.h> 41 #include <sys/types.h> 42 #include <sys/vnode.h> 43 #include <tsol/label.h> 44 #include <time.h> 45 #include <unistd.h> 46 47 #ifdef C2_DEBUG 48 #define DPRINTF(x) {printf x; } 49 #define DFLUSH fflush(stdout); 50 #else 51 #define DPRINTF(x) 52 #define DFLUSH 53 #endif 54 55 static adt_token_func_t adt_getTokenFunction(char); 56 57 static char *empty = ""; 58 59 /* 60 * call adt_token_open() first and adt_token_close() last. 61 * 62 * au_open is sort of broken; it returns a -1 when out of memory that 63 * you're supposed to ignore; au_write and au_close return without 64 * doing anything when a -1 is passed. This code sort of follows the 65 * au_open model except that it calls syslog to indicate underlying 66 * brokenness. Other than that, -1 is ignored. 67 */ 68 69 void 70 adt_token_open(struct adt_event_state *event) 71 { 72 static int have_syslogged = 0; 73 74 event->ae_event_handle = au_open(); 75 if (event->ae_event_handle < 0) { 76 if (!have_syslogged) { 77 adt_write_syslog("au_open failed", ENOMEM); 78 have_syslogged = 1; 79 } 80 } 81 else 82 have_syslogged = 0; 83 } 84 85 /* 86 * call generate_token for each token in the order you want the tokens 87 * generated. 88 */ 89 90 void 91 adt_generate_token(struct entry *p_entry, void *p_data, 92 struct adt_event_state *event) 93 { 94 adt_token_func_t p_func; 95 96 assert((p_entry != NULL) && (p_data != NULL) && (event != NULL)); 97 98 p_func = adt_getTokenFunction(p_entry->en_token_id); 99 assert(p_func != NULL); 100 101 DPRINTF(("p_entry=%08X, p_data=%08X, offset=%X, msgFmt=%X\n", 102 p_entry, p_data, p_entry->en_offset, p_entry->en_msg_format)); 103 DFLUSH 104 105 (*p_func)(p_entry->en_type_def, 106 (char *)p_data + p_entry->en_offset, p_entry->en_required, event, 107 p_entry->en_msg_format); 108 } 109 110 /* call this last */ 111 112 void 113 adt_token_close(struct adt_event_state *event) 114 { 115 int rc; 116 117 rc = au_close(event->ae_event_handle, AU_TO_WRITE, 118 event->ae_internal_id); 119 if (rc < 0) 120 adt_write_syslog("au_close failed", errno); 121 } 122 123 /* 124 * one function per token -- see the jump table at the end of file 125 */ 126 127 /* ARGSUSED */ 128 static void 129 adt_to_return(datadef *def, void *p_data, int required, 130 struct adt_event_state *event, char *notUsed) 131 { 132 133 #ifdef _LP64 134 (void) au_write(event->ae_event_handle, 135 au_to_return64((int64_t)event->ae_rc, event->ae_type)); 136 #else 137 (void) au_write(event->ae_event_handle, 138 au_to_return32((int32_t)event->ae_rc, event->ae_type)); 139 #endif 140 } 141 142 /* 143 * AUT_CMD 144 * 145 * the command line is described with argc and argv and the environment 146 * with envp. The envp list is NULL terminated and has no separate 147 * counter; envp will be a NULL list unless the AUDIT_ARGE policy is 148 * set. 149 */ 150 151 /* ARGSUSED */ 152 static void 153 adt_to_cmd(datadef *def, void *p_data, int required, 154 struct adt_event_state *event, char *notUsed) 155 { 156 struct adt_internal_state *sp = event->ae_session; 157 int argc; 158 char **argv; 159 char **envp = NULL; 160 161 argc = ((union convert *)p_data)->tint; 162 p_data = adt_adjust_address(p_data, sizeof (int), sizeof (char **)); 163 argv = ((union convert *)p_data)->tchar2star; 164 p_data = adt_adjust_address(p_data, sizeof (char **), sizeof (char **)); 165 166 if (sp->as_kernel_audit_policy & AUDIT_ARGE) 167 envp = ((union convert *)p_data)->tchar2star; 168 169 (void) au_write(event->ae_event_handle, 170 au_to_cmd(argc, argv, envp)); 171 } 172 173 /* 174 * special case of AUT_CMD with 1 argument that is 175 * a string showing the whole command and no envp 176 */ 177 /* ARGSUSED */ 178 static void 179 adt_to_cmd1(datadef *def, void *p_data, int required, 180 struct adt_event_state *event, char *notUsed) 181 { 182 char *string; 183 184 string = ((union convert *)p_data)->tcharstar; 185 186 if (string == NULL) { 187 if (required) 188 string = empty; 189 else 190 return; 191 } 192 /* argc is hardcoded as 1 */ 193 (void) au_write(event->ae_event_handle, au_to_cmd(1, &string, 194 NULL)); 195 } 196 197 /* 198 * adt_to_tid -- generic address (ip is only one defined at present) 199 * input: 200 * terminal type: ADT_IPv4, ADT_IPv6... 201 * case: ADT_IPv4 or ADT_IPv6... 202 * ip type 203 * remote port 204 * local port 205 * address 206 * case: not defined... 207 */ 208 /* ARGSUSED */ 209 static void 210 adt_to_tid(datadef *def, void *p_data, int required, 211 struct adt_event_state *event, char *notUsed) 212 { 213 au_generic_tid_t tid; 214 uint32_t type; 215 au_ip_t *ip; 216 217 type = ((union convert *)p_data)->tuint32; 218 219 switch (type) { 220 case ADT_IPv4: 221 case ADT_IPv6: 222 p_data = adt_adjust_address(p_data, sizeof (uint32_t), 223 sizeof (uint32_t)); 224 225 tid.gt_type = AU_IPADR; 226 ip = &(tid.gt_adr.at_ip); 227 228 ip->at_type = (type == ADT_IPv4) ? 229 AU_IPv4 : AU_IPv6; 230 231 ip->at_r_port = ((union convert *)p_data)->tuint16; 232 p_data = adt_adjust_address(p_data, sizeof (uint16_t), 233 sizeof (uint16_t)); 234 235 ip->at_l_port = ((union convert *)p_data)->tuint16; 236 237 /* arg3 is for the array element, not the array size */ 238 p_data = adt_adjust_address(p_data, sizeof (uint16_t), 239 sizeof (uint32_t)); 240 241 (void) memcpy(ip->at_addr, p_data, ip->at_type); 242 break; 243 default: 244 adt_write_syslog("Invalid terminal id type", EINVAL); 245 return; 246 } 247 (void) au_write(event->ae_event_handle, au_to_tid(&tid)); 248 } 249 250 /* 251 * au_to_frmi takes a char * that is the fmri. 252 */ 253 /* ARGSUSED */ 254 static void 255 adt_to_frmi(datadef *def, void *p_data, int required, 256 struct adt_event_state *event, char *notUsed) 257 { 258 char *fmri; 259 260 DPRINTF((" adt_to_fmri dd_datatype=%d\n", def->dd_datatype)); 261 262 fmri = ((union convert *)p_data)->tcharstar; 263 264 if (fmri == NULL) { 265 if (required) 266 fmri = empty; 267 else 268 return; 269 } 270 DPRINTF((" fmri=%s\n", fmri)); 271 (void) au_write(event->ae_event_handle, au_to_fmri(fmri)); 272 } 273 274 /* 275 * au_to_newgroups takes a length and an array of gids 276 * as input. The input to adt_to_newgroups is a length 277 * and a pointer to an array of gids. 278 */ 279 280 /* ARGSUSED */ 281 static void 282 adt_to_newgroups(datadef *def, void *p_data, int required, 283 struct adt_event_state *event, char *notUsed) 284 { 285 int n; 286 gid_t *groups; 287 288 n = ((union convert *)p_data)->tint; 289 if (n < 1) { 290 if (required) { 291 n = 0; /* in case negative n was passed */ 292 } else 293 return; 294 } 295 p_data = adt_adjust_address(p_data, sizeof (int), sizeof (int32_t *)); 296 297 groups = ((union convert *)p_data)->tgidstar; 298 299 (void) au_write(event->ae_event_handle, au_to_newgroups(n, groups)); 300 } 301 302 /* ARGSUSED */ 303 static void 304 adt_to_path(datadef *def, void *p_data, int required, 305 struct adt_event_state *event, char *notUsed) 306 { 307 char *path; 308 309 path = ((union convert *)p_data)->tcharstar; 310 311 if (path != NULL) { 312 DPRINTF((" path=%s\n", path)); 313 (void) au_write(event->ae_event_handle, au_to_path(path)); 314 } else { 315 DPRINTF((" Null path\n")); 316 if (required) 317 (void) au_write(event->ae_event_handle, 318 au_to_path(empty)); 319 } 320 } 321 322 /* 323 * dummy token id: AUT_PATHLIST 324 */ 325 326 /* ARGSUSED */ 327 static void 328 adt_to_pathlist(datadef *def, void *p_data, int required, 329 struct adt_event_state *event, char *notUsed) 330 { 331 char *path; 332 char *working_buf; 333 char *pathlist; 334 char *last_str; 335 336 pathlist = ((union convert *)p_data)->tcharstar; 337 338 if (pathlist != NULL) { 339 working_buf = strdup(pathlist); 340 if (working_buf == NULL) { 341 adt_write_syslog("audit failure", errno); 342 if (required) 343 (void) au_write(event->ae_event_handle, 344 au_to_path(empty)); 345 return; 346 } 347 for (path = strtok_r(working_buf, " ", &last_str); 348 path; path = strtok_r(NULL, " ", &last_str)) { 349 DPRINTF((" path=%s\n", path)); 350 (void) au_write(event->ae_event_handle, 351 au_to_path(path)); 352 } 353 } else { 354 DPRINTF((" Null path list\n")); 355 if (required) 356 (void) au_write(event->ae_event_handle, 357 au_to_path(empty)); 358 } 359 } 360 361 /* 362 * AUT_PRIV 363 */ 364 365 /* ARGSUSED */ 366 static void 367 adt_to_priv(datadef *def, void *p_data, int required, 368 struct adt_event_state *event, const char *priv_type) 369 { 370 priv_set_t *privilege; 371 372 privilege = ((union convert *)p_data)->tprivstar; 373 374 if (privilege != NULL) { 375 (void) au_write(event->ae_event_handle, 376 au_to_privset(priv_type, privilege)); 377 } else { 378 if (required) { 379 DPRINTF((" Null privilege\n")); 380 (void) au_write(event->ae_event_handle, 381 au_to_privset(empty, NULL)); 382 } 383 } 384 } 385 386 /* 387 * -AUT_PRIV_L AUT_PRIV for a limit set 388 */ 389 390 /* ARGSUSED */ 391 static void 392 adt_to_priv_limit(datadef *def, void *p_data, int required, 393 struct adt_event_state *event, char *notUsed) 394 { 395 adt_to_priv(def, p_data, required, event, PRIV_LIMIT); 396 } 397 398 /* 399 * -AUT_PRIV_I AUT_PRIV for an inherit set 400 */ 401 402 /* ARGSUSED */ 403 static void 404 adt_to_priv_inherit(datadef *def, void *p_data, int required, 405 struct adt_event_state *event, char *notUsed) 406 { 407 adt_to_priv(def, p_data, required, event, PRIV_INHERITABLE); 408 } 409 410 /* ARGSUSED */ 411 static void 412 adt_to_priv_effective(datadef *def, void *p_data, int required, 413 struct adt_event_state *event, char *notUsed) 414 { 415 adt_to_priv(def, p_data, required, event, PRIV_EFFECTIVE); 416 } 417 418 static void 419 getCharacteristics(struct auditpinfo_addr *info, pid_t *pid) 420 { 421 int rc; 422 423 if (*pid == 0) /* getpinfo for this pid */ 424 info->ap_pid = getpid(); 425 else 426 info->ap_pid = *pid; 427 428 rc = auditon(A_GETPINFO_ADDR, (caddr_t)info, 429 sizeof (struct auditpinfo_addr)); 430 if (rc == -1) { 431 info->ap_auid = AU_NOAUDITID; 432 info->ap_asid = 0; 433 (void) memset((void *)&(info->ap_termid), 0, 434 sizeof (au_tid_addr_t)); 435 info->ap_termid.at_type = AU_IPv4; 436 } 437 } 438 439 /* 440 * AUT_PROCESS 441 * 442 */ 443 444 /* ARGSUSED */ 445 static void 446 adt_to_process(datadef *def, void *p_data, int required, 447 struct adt_event_state *event, char *notUsed) 448 { 449 au_id_t auid; 450 uid_t euid; 451 gid_t egid; 452 uid_t ruid; 453 gid_t rgid; 454 pid_t pid; 455 au_asid_t sid; 456 au_tid_addr_t *tid; 457 struct auditpinfo_addr info; 458 459 auid = ((union convert *)p_data)->tuid; 460 p_data = adt_adjust_address(p_data, sizeof (uid_t), sizeof (uid_t)); 461 euid = ((union convert *)p_data)->tuid; 462 p_data = adt_adjust_address(p_data, sizeof (uid_t), sizeof (gid_t)); 463 egid = ((union convert *)p_data)->tgid; 464 p_data = adt_adjust_address(p_data, sizeof (gid_t), sizeof (uid_t)); 465 ruid = ((union convert *)p_data)->tuid; 466 p_data = adt_adjust_address(p_data, sizeof (uid_t), sizeof (gid_t)); 467 rgid = ((union convert *)p_data)->tgid; 468 p_data = adt_adjust_address(p_data, sizeof (gid_t), sizeof (pid_t)); 469 pid = ((union convert *)p_data)->tpid; 470 p_data = adt_adjust_address(p_data, sizeof (pid_t), sizeof (uint32_t)); 471 sid = ((union convert *)p_data)->tuint32; 472 p_data = adt_adjust_address(p_data, sizeof (uint32_t), 473 sizeof (au_tid_addr_t *)); 474 tid = ((union convert *)p_data)->ttermid; 475 476 getCharacteristics(&info, &pid); 477 478 if (auid == AU_NOAUDITID) 479 auid = info.ap_auid; 480 481 if (euid == AU_NOAUDITID) 482 euid = geteuid(); 483 484 if (egid == AU_NOAUDITID) 485 egid = getegid(); 486 487 if (ruid == AU_NOAUDITID) 488 ruid = getuid(); 489 490 if (rgid == AU_NOAUDITID) 491 rgid = getgid(); 492 493 if (tid == NULL) 494 tid = &(info.ap_termid); 495 496 if (sid == 0) 497 sid = info.ap_asid; 498 499 if (pid == 0) 500 pid = info.ap_pid; 501 502 (void) au_write(event->ae_event_handle, 503 au_to_process_ex(auid, euid, egid, ruid, rgid, pid, sid, tid)); 504 } 505 506 /* 507 * generate a subject token and, depending on audit policy, a 508 * group token. For TSOL, this is probably the right place 509 * to generate a label token. Alternatively, a TSOL token could 510 * be defined in adt.xml with 'opt="none". 511 * 512 * The required flag does not apply here. 513 * 514 * Non-attributable records are indicated by an auid of AU_NOAUDITID; 515 * no subject token or group token is generated for a non-attributable 516 * record. 517 */ 518 519 /* ARGSUSED */ 520 static void 521 adt_to_subject(datadef *def, void *p_data, int required, 522 struct adt_event_state *event, char *notUsed) 523 { 524 struct adt_internal_state *sp = event->ae_session; 525 526 if (sp->as_info.ai_auid == AU_NOAUDITID) 527 return; 528 529 assert(sp->as_have_user_data == ADT_HAVE_ALL); 530 531 (void) au_write(event->ae_event_handle, 532 au_to_subject_ex(sp->as_info.ai_auid, 533 sp->as_euid, sp->as_egid, sp->as_ruid, sp->as_rgid, 534 getpid(), sp->as_info.ai_asid, 535 &(sp->as_info.ai_termid))); 536 /* 537 * If AUDIT_GROUP is set, a groups token must be output. 538 * In a session model, the groups list is undefined, so output an 539 * empty list. In a process model, ship it! 540 */ 541 if (sp->as_kernel_audit_policy & AUDIT_GROUP) { 542 int group_count; 543 gid_t grouplist[NGROUPS_MAX]; 544 545 (void) memset(grouplist, 0, sizeof (grouplist)); 546 if (sp->as_session_model == ADT_PROCESS_MODEL) { 547 if ((group_count = getgroups(NGROUPS_UMAX, 548 grouplist))) { 549 (void) au_write(event->ae_event_handle, 550 au_to_newgroups(group_count, grouplist)); 551 } 552 } else { /* consider deleting this null output */ 553 (void) au_write(event->ae_event_handle, 554 au_to_newgroups(0, grouplist)); 555 } 556 } 557 558 if (is_system_labeled()) 559 (void) au_write(event->ae_event_handle, au_to_mylabel()); 560 } 561 562 /* 563 * adt_to_text() 564 * 565 * The format string, normally null, is sort of a wrapper around 566 * the input. adt_write_text() is a wrapper around au_write that 567 * handles the format string 568 * 569 */ 570 #define TEXT_LENGTH 49 571 572 static void 573 adt_write_text(int handle, char *main_text, const char *format) 574 { 575 char buffer[TEXT_LENGTH * 2 + 1]; 576 577 if (format == NULL) 578 (void) au_write(handle, au_to_text(main_text)); 579 else { 580 (void) snprintf(buffer, TEXT_LENGTH * 2, format, main_text); 581 (void) au_write(handle, au_to_text(buffer)); 582 } 583 } 584 585 static void 586 adt_to_text(datadef *def, void *p_data, int required, 587 struct adt_event_state *event, char *format) 588 { 589 static int have_syslogged = 0; 590 char *string; 591 char **string_list; 592 char buffer[TEXT_LENGTH + 1]; 593 time_t date; 594 struct tm tm; 595 uint32_t *int_list; 596 int written, available; 597 int i, arrayCount; 598 struct msg_text *list; 599 int list_index; 600 601 DPRINTF((" adt_to_text dd_datatype=%d\n", def->dd_datatype)); 602 switch (def->dd_datatype) { 603 case ADT_DATE: 604 /* 605 * Consider creating a separate token type for dates 606 * -- store as longs and format them in praudit. 607 * For now, a date is input as a time_t and output as 608 * a text token. If we do this, we need to consider 609 * carrying timezone info so that praudit can 610 * represent times in an unambiguous manner. 611 */ 612 date = ((union convert *)p_data)->tlong; 613 if (strftime(buffer, sizeof (buffer), "%x", 614 localtime_r(&date, &tm)) > TEXT_LENGTH) { 615 if (required) 616 (void) strncpy(buffer, "invalid date", 617 TEXT_LENGTH); 618 else 619 break; 620 } 621 DPRINTF((" text=%s\n", buffer)); 622 adt_write_text(event->ae_event_handle, buffer, format); 623 break; 624 /* 625 * The "input size" is overloaded to mean the list number 626 * and the msg_selector indexes the desired string in 627 * that list 628 */ 629 case ADT_MSG: 630 list = &adt_msg_text[(enum adt_login_text)def->dd_input_size]; 631 list_index = ((union convert *)p_data)->msg_selector; 632 633 if ((list_index < list->ml_min_index) | 634 (list_index > list->ml_max_index)) 635 string = "Invalid message index"; 636 else 637 string = list->ml_msg_list[list_index + 638 list->ml_offset]; 639 640 if (string == NULL) { /* null is valid; means skip */ 641 if (required) { 642 string = empty; 643 } else 644 break; 645 } 646 DPRINTF((" text=%s\n", string)); 647 adt_write_text(event->ae_event_handle, string, format); 648 break; 649 case ADT_UID: 650 case ADT_GID: 651 case ADT_UINT: 652 (void) snprintf(buffer, TEXT_LENGTH, "%d", 653 ((union convert *)p_data)->tuint); 654 655 DPRINTF((" text=%s\n", buffer)); 656 adt_write_text(event->ae_event_handle, buffer, format); 657 break; 658 case ADT_UIDSTAR: 659 case ADT_GIDSTAR: 660 case ADT_UINT32STAR: 661 int_list = ((union convert *)p_data)->tuint32star; 662 p_data = adt_adjust_address(p_data, sizeof (int *), 663 sizeof (int)); 664 arrayCount = ((union convert *)p_data)->tint; 665 666 string = buffer; 667 available = TEXT_LENGTH; /* space available in buffer */ 668 669 if (arrayCount < 0) 670 arrayCount = 0; 671 672 if ((arrayCount > 0) && (int_list != NULL)) { 673 for (; arrayCount > 0; arrayCount--) { 674 written = snprintf(string, available, 675 "%d ", *int_list++); 676 if (written < 1) 677 break; 678 string += written; 679 available -= written; 680 } 681 } else if (required) 682 string = empty; 683 else 684 break; 685 686 adt_write_text(event->ae_event_handle, buffer, format); 687 break; 688 case ADT_ULONG: 689 (void) snprintf(buffer, TEXT_LENGTH, "%ld", 690 ((union convert *)p_data)->tulong); 691 692 DPRINTF((" text=%s\n", buffer)); 693 adt_write_text(event->ae_event_handle, buffer, format); 694 break; 695 case ADT_CHARSTAR: 696 string = ((union convert *)p_data)->tcharstar; 697 698 if (string == NULL) { 699 if (required) 700 string = empty; 701 else 702 break; 703 } 704 DPRINTF((" text=%s\n", string)); 705 adt_write_text(event->ae_event_handle, string, format); 706 break; 707 case ADT_CHAR2STAR: 708 string_list = ((union convert *)p_data)->tchar2star; 709 p_data = adt_adjust_address(p_data, sizeof (char **), 710 sizeof (int)); 711 arrayCount = ((union convert *)p_data)->tint; 712 713 if (arrayCount < 0) 714 arrayCount = 0; 715 716 if ((arrayCount > 0) && (string_list != NULL)) { 717 for (i = 0; i < arrayCount; i++) { 718 string = string_list[i]; 719 if (string != NULL) 720 adt_write_text(event->ae_event_handle, 721 string, format); 722 } 723 } else if (required) 724 adt_write_text(event->ae_event_handle, empty, format); 725 else 726 break; 727 break; 728 default: 729 if (!have_syslogged) { /* don't flood the log */ 730 adt_write_syslog("unsupported data conversion", 731 ENOTSUP); 732 have_syslogged = 1; 733 } 734 break; 735 } 736 DFLUSH 737 } 738 739 /* ARGSUSED */ 740 static void 741 adt_to_uauth(datadef *def, void *p_data, int required, 742 struct adt_event_state *event, char *format) 743 { 744 char *string; 745 746 DPRINTF((" adt_to_uauth dd_datatype=%d\n", def->dd_datatype)); 747 748 string = ((union convert *)p_data)->tcharstar; 749 750 if (string == NULL) { 751 if (required) 752 string = empty; 753 else 754 return; 755 } 756 DPRINTF((" text=%s\n", string)); 757 (void) au_write(event->ae_event_handle, au_to_uauth(string)); 758 } 759 760 /* ARGSUSED */ 761 static void 762 adt_to_zonename(datadef *def, void *p_data, int required, 763 struct adt_event_state *event, char *notUsed) 764 { 765 char *name; 766 767 name = ((union convert *)p_data)->tcharstar; 768 769 if (name != NULL) { 770 DPRINTF((" name=%s\n", name)); 771 (void) au_write(event->ae_event_handle, au_to_zonename(name)); 772 } else { 773 DPRINTF((" Null name\n")); 774 if (required) 775 (void) au_write(event->ae_event_handle, 776 au_to_zonename(empty)); 777 } 778 } 779 780 781 /* 782 * no function for header -- the header is generated by au_close() 783 * 784 * no function for trailer -- the trailer is generated by au_close() 785 */ 786 787 #define MAX_TOKEN_JMP 16 788 789 static struct token_jmp token_table[MAX_TOKEN_JMP] = 790 { 791 {AUT_CMD, adt_to_cmd}, 792 {ADT_CMD_ALT, adt_to_cmd1}, 793 {ADT_AUT_PRIV_L, adt_to_priv_limit}, 794 {ADT_AUT_PRIV_I, adt_to_priv_inherit}, 795 {ADT_AUT_PRIV_E, adt_to_priv_effective}, 796 {AUT_NEWGROUPS, adt_to_newgroups}, 797 {AUT_FMRI, adt_to_frmi}, 798 {AUT_PATH, adt_to_path}, 799 {-AUT_PATH, adt_to_pathlist}, /* private extension of token values */ 800 {AUT_PROCESS, adt_to_process}, 801 {AUT_RETURN, adt_to_return}, 802 {AUT_SUBJECT, adt_to_subject}, 803 {AUT_TEXT, adt_to_text}, 804 {AUT_TID, adt_to_tid}, 805 {AUT_UAUTH, adt_to_uauth}, 806 {AUT_ZONENAME, adt_to_zonename} 807 }; 808 /* 809 * {AUT_ARG, adt_to_arg}, not used 810 * {AUT_ACL, adt_to_acl}, not used 811 * {AUT_ARBITRARY, adt_to_arbitrary}, AUT_ARBITRARY is undefined 812 * {AUT_ATTR, adt_to_attr}, not used in mountd 813 * {AUT_EXEC_ARGS, adt_to_exec_args}, not used 814 * {AUT_EXEC_ENV, adt_to_exec_env}, not used 815 * {AUT_EXIT, adt_to_exit}, obsolete 816 * {AUT_FILE, adt_to_file}, AUT_FILE is undefined 817 * {AUT_GROUPS, adt_to_groups}, obsolete 818 * {AUT_HEADER, adt_to_header} not used 819 * {AUT_IN_ADDR, adt_to_in_addr}, not used 820 * {AUT_IP, adt_to_ip}, not used 821 * {AUT_IPC, adt_to_ipc}, not used 822 * {AUT_IPC_PERM, adt_to_ipc_perm}, not used 823 * {AUT_OPAQUE, adt_to_opaque}, not used 824 * {AUT_SEQ, adt_to_seq}, not used 825 * {AUT_SOCKET, adt_to_socket}, not used 826 * {AUT_SOCKET_INET, adt_to_socket_inet}, AUT_SOCKET_INET is undefined 827 * {AUT_TRAILER, adt_to_trailer} not used 828 */ 829 830 /* find function to generate token */ 831 832 static adt_token_func_t 833 adt_getTokenFunction(char token_id) 834 { 835 int i; 836 struct token_jmp *p_jmp = token_table; 837 838 for (i = 0; i < MAX_TOKEN_JMP; i++) { 839 if (token_id == p_jmp->jmp_id) { 840 return (p_jmp->jmp_to); 841 } 842 p_jmp++; 843 } 844 errno = EINVAL; 845 return (NULL); 846 } 847 848 /* 849 * adjustAddress -- given the address of data, its size, and the type of 850 * the next data field, calculate the offset to the next piece of data. 851 * Depending on the caller, "current" and "next" mean the current pointer 852 * and the next pointer or the last pointer and the current pointer. 853 */ 854 void * 855 adt_adjust_address(void *current_address, size_t current_size, 856 size_t next_size) 857 { 858 ptrdiff_t adjustment; 859 ptrdiff_t remainder; 860 861 adjustment = (size_t)current_address + current_size; 862 863 if (next_size) { 864 remainder = adjustment % next_size; 865 if (remainder != 0) 866 adjustment += next_size - remainder; 867 } 868 return ((char *)adjustment); 869 } 870