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 2009 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 30 #include <bsm/adt.h> 31 #include <bsm/adt_event.h> 32 #include <bsm/audit.h> 33 34 #include <adt_xlate.h> 35 #include <alloca.h> 36 #include <assert.h> 37 #include <netdb.h> 38 #include <priv.h> 39 #include <string.h> 40 #include <strings.h> 41 #include <stdlib.h> 42 #include <time.h> 43 #include <unistd.h> 44 45 #include <sys/priv_names.h> 46 #include <sys/socket.h> 47 #include <sys/types.h> 48 #include <sys/vnode.h> 49 50 #include <tsol/label.h> 51 52 #ifdef C2_DEBUG 53 #define DPRINTF(x) {printf x; } 54 #define DFLUSH fflush(stdout); 55 56 /* 0x + Classification + Compartments + end of string */ 57 #define HEX_SIZE 2 + 2*2 + 2*32 + 1 58 59 static char * 60 dprt_label(m_label_t *label) 61 { 62 static char hex[HEX_SIZE]; 63 char *direct = NULL; 64 65 if (label_to_str(label, &direct, M_INTERNAL, DEF_NAMES) != 0) { 66 adt_write_syslog("label_to_str(M_INTERNAL)", errno); 67 return ("hex label failed"); 68 } 69 (void) strlcpy(hex, direct, sizeof (hex)); 70 free(direct); 71 return (hex); 72 } 73 #else /* !C2_DEBUG */ 74 #define DPRINTF(x) 75 #define DFLUSH 76 #endif /* C2_DEBUG */ 77 78 static adt_token_func_t adt_getTokenFunction(char); 79 80 static char *empty = ""; 81 82 /* 83 * call adt_token_open() first and adt_token_close() last. 84 * 85 * au_open is sort of broken; it returns a -1 when out of memory that 86 * you're supposed to ignore; au_write and au_close return without 87 * doing anything when a -1 is passed. This code sort of follows the 88 * au_open model except that it calls syslog to indicate underlying 89 * brokenness. Other than that, -1 is ignored. 90 */ 91 92 void 93 adt_token_open(struct adt_event_state *event) 94 { 95 static int have_syslogged = 0; 96 97 event->ae_event_handle = au_open(); 98 if (event->ae_event_handle < 0) { 99 if (!have_syslogged) { 100 adt_write_syslog("au_open failed", ENOMEM); 101 have_syslogged = 1; 102 } 103 } else { 104 have_syslogged = 0; 105 } 106 } 107 108 /* 109 * call generate_token for each token in the order you want the tokens 110 * generated. 111 */ 112 113 void 114 adt_generate_token(struct entry *p_entry, void *p_data, 115 struct adt_event_state *event) 116 { 117 adt_token_func_t p_func; 118 119 assert((p_entry != NULL) && (p_data != NULL) && (event != NULL)); 120 121 p_func = adt_getTokenFunction(p_entry->en_token_id); 122 assert(p_func != NULL); 123 124 DPRINTF(("p_entry=%08X, p_data=%08X, offset=%X, msgFmt=%X\n", 125 p_entry, p_data, p_entry->en_offset, p_entry->en_msg_format)); 126 DFLUSH 127 128 (*p_func)(p_entry->en_type_def, 129 (char *)p_data + p_entry->en_offset, p_entry->en_required, event, 130 p_entry->en_msg_format); 131 } 132 133 /* call this last */ 134 135 int 136 adt_token_close(struct adt_event_state *event) 137 { 138 int rc; 139 140 rc = au_close(event->ae_event_handle, AU_TO_WRITE, 141 event->ae_internal_id); 142 if (rc < 0) 143 adt_write_syslog("au_close failed", errno); 144 return (rc); 145 } 146 147 /* 148 * one function per token -- see the jump table at the end of file 149 */ 150 151 /* ARGSUSED */ 152 static void 153 adt_to_return(datadef *def, void *p_data, int required, 154 struct adt_event_state *event, char *notUsed) 155 { 156 157 #ifdef _LP64 158 (void) au_write(event->ae_event_handle, 159 au_to_return64((int64_t)event->ae_rc, event->ae_type)); 160 #else 161 (void) au_write(event->ae_event_handle, 162 au_to_return32((int32_t)event->ae_rc, event->ae_type)); 163 #endif 164 } 165 166 /* 167 * AUT_CMD 168 * 169 * the command line is described with argc and argv and the environment 170 * with envp. The envp list is NULL terminated and has no separate 171 * counter; envp will be a NULL list unless the AUDIT_ARGE policy is 172 * set. 173 */ 174 175 /* ARGSUSED */ 176 static void 177 adt_to_cmd(datadef *def, void *p_data, int required, 178 struct adt_event_state *event, char *notUsed) 179 { 180 struct adt_internal_state *sp = event->ae_session; 181 int argc; 182 char **argv; 183 char **envp = NULL; 184 185 argc = ((union convert *)p_data)->tint; 186 p_data = adt_adjust_address(p_data, sizeof (int), sizeof (char **)); 187 argv = ((union convert *)p_data)->tchar2star; 188 p_data = adt_adjust_address(p_data, sizeof (char **), sizeof (char **)); 189 190 if (sp->as_kernel_audit_policy & AUDIT_ARGE) 191 envp = ((union convert *)p_data)->tchar2star; 192 193 (void) au_write(event->ae_event_handle, 194 au_to_cmd(argc, argv, envp)); 195 } 196 197 /* 198 * special case of AUT_CMD with 1 argument that is 199 * a string showing the whole command and no envp 200 */ 201 /* ARGSUSED */ 202 static void 203 adt_to_cmd1(datadef *def, void *p_data, int required, 204 struct adt_event_state *event, char *notUsed) 205 { 206 char *string; 207 208 string = ((union convert *)p_data)->tcharstar; 209 210 if (string == NULL) { 211 if (required) { 212 string = empty; 213 } else { 214 return; 215 } 216 } 217 /* argc is hardcoded as 1 */ 218 (void) au_write(event->ae_event_handle, au_to_cmd(1, &string, 219 NULL)); 220 } 221 222 /* 223 * adt_to_tid -- generic address (ip is only one defined at present) 224 * input: 225 * terminal type: ADT_IPv4, ADT_IPv6... 226 * case: ADT_IPv4 or ADT_IPv6... 227 * ip type 228 * remote port 229 * local port 230 * address 231 * case: not defined... 232 */ 233 /* ARGSUSED */ 234 static void 235 adt_to_tid(datadef *def, void *p_data, int required, 236 struct adt_event_state *event, char *notUsed) 237 { 238 au_generic_tid_t tid; 239 uint32_t type; 240 au_ip_t *ip; 241 242 type = ((union convert *)p_data)->tuint32; 243 244 switch (type) { 245 case ADT_IPv4: 246 case ADT_IPv6: 247 p_data = adt_adjust_address(p_data, sizeof (uint32_t), 248 sizeof (uint32_t)); 249 250 tid.gt_type = AU_IPADR; 251 ip = &(tid.gt_adr.at_ip); 252 253 ip->at_type = (type == ADT_IPv4) ? 254 AU_IPv4 : AU_IPv6; 255 256 ip->at_r_port = ((union convert *)p_data)->tuint16; 257 p_data = adt_adjust_address(p_data, sizeof (uint16_t), 258 sizeof (uint16_t)); 259 260 ip->at_l_port = ((union convert *)p_data)->tuint16; 261 262 /* arg3 is for the array element, not the array size */ 263 p_data = adt_adjust_address(p_data, sizeof (uint16_t), 264 sizeof (uint32_t)); 265 266 (void) memcpy(ip->at_addr, p_data, ip->at_type); 267 break; 268 default: 269 adt_write_syslog("Invalid terminal id type", EINVAL); 270 return; 271 } 272 (void) au_write(event->ae_event_handle, au_to_tid(&tid)); 273 } 274 275 /* 276 * au_to_frmi takes a char * that is the fmri. 277 */ 278 /* ARGSUSED */ 279 static void 280 adt_to_frmi(datadef *def, void *p_data, int required, 281 struct adt_event_state *event, char *notUsed) 282 { 283 char *fmri; 284 285 DPRINTF((" adt_to_fmri dd_datatype=%d\n", def->dd_datatype)); 286 287 fmri = ((union convert *)p_data)->tcharstar; 288 289 if (fmri == NULL) { 290 if (required) { 291 fmri = empty; 292 } else { 293 return; 294 } 295 } 296 DPRINTF((" fmri=%s\n", fmri)); 297 (void) au_write(event->ae_event_handle, au_to_fmri(fmri)); 298 } 299 300 /* 301 * au_to_label takes an m_label_t * that is the label. 302 */ 303 /* ARGSUSED */ 304 static void 305 adt_to_label(datadef *def, void *p_data, int required, 306 struct adt_event_state *event, char *notUsed) 307 { 308 m_label_t *label; 309 310 DPRINTF((" adt_to_label dd_datatype=%d\n", def->dd_datatype)); 311 312 label = ((union convert *)p_data)->tm_label; 313 314 if (label != NULL) { 315 DPRINTF((" label=%s\n", dprt_label(label))); 316 DFLUSH 317 (void) au_write(event->ae_event_handle, au_to_label(label)); 318 } else { 319 DPRINTF((" Null label\n")); 320 if (required) 321 adt_write_syslog("adt_to_label no required label", 0); 322 } 323 } 324 325 /* 326 * au_to_newgroups takes a length and an array of gids 327 * as input. The input to adt_to_newgroups is a length 328 * and a pointer to an array of gids. 329 */ 330 331 /* ARGSUSED */ 332 static void 333 adt_to_newgroups(datadef *def, void *p_data, int required, 334 struct adt_event_state *event, char *notUsed) 335 { 336 int n; 337 gid_t *groups; 338 339 n = ((union convert *)p_data)->tint; 340 if (n < 1) { 341 if (required) { 342 n = 0; /* in case negative n was passed */ 343 } else { 344 return; 345 } 346 } 347 p_data = adt_adjust_address(p_data, sizeof (int), sizeof (int32_t *)); 348 349 groups = ((union convert *)p_data)->tgidstar; 350 351 (void) au_write(event->ae_event_handle, au_to_newgroups(n, groups)); 352 } 353 354 /* ARGSUSED */ 355 static void 356 adt_to_path(datadef *def, void *p_data, int required, 357 struct adt_event_state *event, char *notUsed) 358 { 359 char *path; 360 361 path = ((union convert *)p_data)->tcharstar; 362 363 if (path != NULL) { 364 DPRINTF((" path=%s\n", path)); 365 (void) au_write(event->ae_event_handle, au_to_path(path)); 366 } else { 367 DPRINTF((" Null path\n")); 368 if (required) { 369 (void) au_write(event->ae_event_handle, 370 au_to_path(empty)); 371 } 372 } 373 } 374 375 /* 376 * dummy token id: AUT_PATHLIST 377 */ 378 379 /* ARGSUSED */ 380 static void 381 adt_to_pathlist(datadef *def, void *p_data, int required, 382 struct adt_event_state *event, char *notUsed) 383 { 384 char *path; 385 char *working_buf; 386 char *pathlist; 387 char *last_str; 388 389 pathlist = ((union convert *)p_data)->tcharstar; 390 391 if (pathlist != NULL) { 392 working_buf = strdup(pathlist); 393 if (working_buf == NULL) { 394 adt_write_syslog("audit failure", errno); 395 if (required) { 396 (void) au_write(event->ae_event_handle, 397 au_to_path(empty)); 398 } 399 return; 400 } 401 for (path = strtok_r(working_buf, " ", &last_str); 402 path; path = strtok_r(NULL, " ", &last_str)) { 403 DPRINTF((" path=%s\n", path)); 404 (void) au_write(event->ae_event_handle, 405 au_to_path(path)); 406 } 407 } else { 408 DPRINTF((" Null path list\n")); 409 if (required) 410 (void) au_write(event->ae_event_handle, 411 au_to_path(empty)); 412 } 413 } 414 415 /* 416 * AUT_PRIV 417 */ 418 419 /* ARGSUSED */ 420 static void 421 adt_to_priv(datadef *def, void *p_data, int required, 422 struct adt_event_state *event, const char *priv_type) 423 { 424 priv_set_t *privilege; 425 426 privilege = ((union convert *)p_data)->tprivstar; 427 428 if (privilege != NULL) { 429 (void) au_write(event->ae_event_handle, 430 au_to_privset(priv_type, privilege)); 431 } else { 432 if (required) { 433 DPRINTF((" Null privilege\n")); 434 (void) au_write(event->ae_event_handle, 435 au_to_privset(empty, NULL)); 436 } 437 } 438 } 439 440 /* 441 * -AUT_PRIV_L AUT_PRIV for a limit set 442 */ 443 444 /* ARGSUSED */ 445 static void 446 adt_to_priv_limit(datadef *def, void *p_data, int required, 447 struct adt_event_state *event, char *notUsed) 448 { 449 adt_to_priv(def, p_data, required, event, PRIV_LIMIT); 450 } 451 452 /* 453 * -AUT_PRIV_I AUT_PRIV for an inherit set 454 */ 455 456 /* ARGSUSED */ 457 static void 458 adt_to_priv_inherit(datadef *def, void *p_data, int required, 459 struct adt_event_state *event, char *notUsed) 460 { 461 adt_to_priv(def, p_data, required, event, PRIV_INHERITABLE); 462 } 463 464 /* ARGSUSED */ 465 static void 466 adt_to_priv_effective(datadef *def, void *p_data, int required, 467 struct adt_event_state *event, char *notUsed) 468 { 469 adt_to_priv(def, p_data, required, event, PRIV_EFFECTIVE); 470 } 471 472 static void 473 getCharacteristics(struct auditpinfo_addr *info, pid_t *pid) 474 { 475 int rc; 476 477 if (*pid == 0) { /* getpinfo for this pid */ 478 info->ap_pid = getpid(); 479 } else { 480 info->ap_pid = *pid; 481 } 482 483 rc = auditon(A_GETPINFO_ADDR, (caddr_t)info, 484 sizeof (struct auditpinfo_addr)); 485 if (rc == -1) { 486 info->ap_auid = AU_NOAUDITID; 487 info->ap_asid = 0; 488 (void) memset((void *)&(info->ap_termid), 0, 489 sizeof (au_tid_addr_t)); 490 info->ap_termid.at_type = AU_IPv4; 491 } 492 } 493 494 /* 495 * AUT_PROCESS 496 * 497 */ 498 499 /* ARGSUSED */ 500 static void 501 adt_to_process(datadef *def, void *p_data, int required, 502 struct adt_event_state *event, char *notUsed) 503 { 504 au_id_t auid; 505 uid_t euid; 506 gid_t egid; 507 uid_t ruid; 508 gid_t rgid; 509 pid_t pid; 510 au_asid_t sid; 511 au_tid_addr_t *tid; 512 struct auditpinfo_addr info; 513 514 auid = ((union convert *)p_data)->tuid; 515 p_data = adt_adjust_address(p_data, sizeof (uid_t), sizeof (uid_t)); 516 euid = ((union convert *)p_data)->tuid; 517 p_data = adt_adjust_address(p_data, sizeof (uid_t), sizeof (gid_t)); 518 egid = ((union convert *)p_data)->tgid; 519 p_data = adt_adjust_address(p_data, sizeof (gid_t), sizeof (uid_t)); 520 ruid = ((union convert *)p_data)->tuid; 521 p_data = adt_adjust_address(p_data, sizeof (uid_t), sizeof (gid_t)); 522 rgid = ((union convert *)p_data)->tgid; 523 p_data = adt_adjust_address(p_data, sizeof (gid_t), sizeof (pid_t)); 524 pid = ((union convert *)p_data)->tpid; 525 p_data = adt_adjust_address(p_data, sizeof (pid_t), sizeof (uint32_t)); 526 sid = ((union convert *)p_data)->tuint32; 527 p_data = adt_adjust_address(p_data, sizeof (uint32_t), 528 sizeof (au_tid_addr_t *)); 529 tid = ((union convert *)p_data)->ttermid; 530 531 getCharacteristics(&info, &pid); 532 533 if (auid == AU_NOAUDITID) 534 auid = info.ap_auid; 535 536 if (euid == AU_NOAUDITID) 537 euid = geteuid(); 538 539 if (egid == AU_NOAUDITID) 540 egid = getegid(); 541 542 if (ruid == AU_NOAUDITID) 543 ruid = getuid(); 544 545 if (rgid == AU_NOAUDITID) 546 rgid = getgid(); 547 548 if (tid == NULL) 549 tid = &(info.ap_termid); 550 551 if (sid == 0) 552 sid = info.ap_asid; 553 554 if (pid == 0) 555 pid = info.ap_pid; 556 557 (void) au_write(event->ae_event_handle, 558 au_to_process_ex(auid, euid, egid, ruid, rgid, pid, sid, tid)); 559 } 560 561 /* 562 * Generate subject information. 563 * If labels are present, generate the subject label token. 564 * If the group audit policy is set, generate the subject group token. 565 * 566 * The required flag does not apply here. 567 * 568 * Non-attributable records are indicated by an auid of AU_NOAUDITID; 569 * no subject token or group token is generated for a non-attributable 570 * record. 571 */ 572 573 /* ARGSUSED */ 574 static void 575 adt_to_subject(datadef *def, void *p_data, int required, 576 struct adt_event_state *event, char *notUsed) 577 { 578 struct adt_internal_state *sp = event->ae_session; 579 580 if (sp->as_info.ai_auid == AU_NOAUDITID) 581 return; 582 583 assert(sp->as_have_user_data == ADT_HAVE_ALL); 584 585 (void) au_write(event->ae_event_handle, 586 au_to_subject_ex(sp->as_info.ai_auid, 587 sp->as_euid, sp->as_egid, sp->as_ruid, sp->as_rgid, 588 sp->as_pid, sp->as_info.ai_asid, 589 &(sp->as_info.ai_termid))); 590 if (is_system_labeled()) { 591 (void) au_write(event->ae_event_handle, 592 au_to_label(sp->as_label)); 593 } 594 /* 595 * Add optional tokens if in the process model. 596 * In a session model, the groups list is undefined and label 597 * is in the state. 598 */ 599 if (sp->as_session_model == ADT_PROCESS_MODEL) { 600 if (sp->as_kernel_audit_policy & AUDIT_GROUP) { 601 int group_count; 602 int maxgrp = getgroups(0, NULL); 603 gid_t *grouplist = alloca(maxgrp * sizeof (gid_t)); 604 605 if ((group_count = getgroups(maxgrp, grouplist)) > 0) { 606 (void) au_write(event->ae_event_handle, 607 au_to_newgroups(group_count, grouplist)); 608 } 609 } 610 } 611 } 612 613 /* 614 * adt_to_text() 615 * 616 * The format string, normally null, is sort of a wrapper around 617 * the input. adt_write_text() is a wrapper around au_write that 618 * handles the format string 619 * 620 */ 621 #define TEXT_LENGTH 49 622 623 static void 624 adt_write_text(int handle, char *main_text, const char *format) 625 { 626 char buffer[TEXT_LENGTH * 2 + 1]; 627 628 if (format == NULL) { 629 (void) au_write(handle, au_to_text(main_text)); 630 } else { 631 (void) snprintf(buffer, TEXT_LENGTH * 2, format, main_text); 632 (void) au_write(handle, au_to_text(buffer)); 633 } 634 } 635 636 static void 637 adt_to_text(datadef *def, void *p_data, int required, 638 struct adt_event_state *event, char *format) 639 { 640 static int have_syslogged = 0; 641 char *string; 642 char **string_list; 643 char buffer[TEXT_LENGTH + 1]; 644 time_t date; 645 struct tm tm; 646 uint32_t *int_list; 647 int written, available; 648 int i, arrayCount; 649 struct msg_text *list; 650 int list_index; 651 652 DPRINTF((" adt_to_text dd_datatype=%d\n", def->dd_datatype)); 653 switch (def->dd_datatype) { 654 case ADT_DATE: 655 /* 656 * Consider creating a separate token type for dates 657 * -- store as longs and format them in praudit. 658 * For now, a date is input as a time_t and output as 659 * a text token. If we do this, we need to consider 660 * carrying timezone info so that praudit can 661 * represent times in an unambiguous manner. 662 */ 663 date = ((union convert *)p_data)->tlong; 664 if (strftime(buffer, sizeof (buffer), "%x", 665 localtime_r(&date, &tm)) > TEXT_LENGTH) { 666 if (required) { 667 (void) strncpy(buffer, "invalid date", 668 TEXT_LENGTH); 669 } else { 670 break; 671 } 672 } 673 DPRINTF((" text=%s\n", buffer)); 674 adt_write_text(event->ae_event_handle, buffer, format); 675 break; 676 /* 677 * The "input size" is overloaded to mean the list number 678 * and the msg_selector indexes the desired string in 679 * that list 680 */ 681 case ADT_MSG: 682 list = &adt_msg_text[(enum adt_msg_list)def->dd_input_size]; 683 list_index = ((union convert *)p_data)->msg_selector; 684 685 if ((list_index + list->ml_offset < list->ml_min_index) || 686 (list_index + list->ml_offset > list->ml_max_index)) { 687 string = "Invalid message index"; 688 } else { 689 string = list->ml_msg_list[list_index + 690 list->ml_offset]; 691 } 692 693 if (string == NULL) { /* null is valid; means skip */ 694 if (required) { 695 string = empty; 696 } else { 697 break; 698 } 699 } 700 DPRINTF((" text=%s\n", string)); 701 adt_write_text(event->ae_event_handle, string, format); 702 break; 703 case ADT_UID: 704 case ADT_GID: 705 case ADT_UINT: 706 case ADT_UINT32: 707 (void) snprintf(buffer, TEXT_LENGTH, "%u", 708 ((union convert *)p_data)->tuint); 709 710 DPRINTF((" text=%s\n", buffer)); 711 adt_write_text(event->ae_event_handle, buffer, format); 712 break; 713 case ADT_INT: 714 case ADT_INT32: 715 (void) snprintf(buffer, TEXT_LENGTH, "%d", 716 ((union convert *)p_data)->tint); 717 718 DPRINTF((" text=%s\n", buffer)); 719 adt_write_text(event->ae_event_handle, buffer, format); 720 break; 721 case ADT_LONG: 722 (void) snprintf(buffer, TEXT_LENGTH, "%ld", 723 ((union convert *)p_data)->tlong); 724 725 DPRINTF((" text=%s\n", buffer)); 726 adt_write_text(event->ae_event_handle, buffer, format); 727 break; 728 case ADT_UIDSTAR: 729 case ADT_GIDSTAR: 730 case ADT_UINT32STAR: 731 int_list = ((union convert *)p_data)->tuint32star; 732 p_data = adt_adjust_address(p_data, sizeof (int *), 733 sizeof (int)); 734 arrayCount = ((union convert *)p_data)->tint; 735 736 string = buffer; 737 available = TEXT_LENGTH; /* space available in buffer */ 738 739 if (arrayCount < 0) 740 arrayCount = 0; 741 742 if ((arrayCount > 0) && (int_list != NULL)) { 743 for (; arrayCount > 0; arrayCount--) { 744 written = snprintf(string, available, 745 "%d ", *int_list++); 746 if (written < 1) 747 break; 748 string += written; 749 available -= written; 750 } 751 } else if (required) { 752 string = empty; 753 } else { 754 break; 755 } 756 757 adt_write_text(event->ae_event_handle, buffer, format); 758 break; 759 case ADT_ULONG: 760 (void) snprintf(buffer, TEXT_LENGTH, "%lu", 761 ((union convert *)p_data)->tulong); 762 763 DPRINTF((" text=%s\n", buffer)); 764 adt_write_text(event->ae_event_handle, buffer, format); 765 break; 766 case ADT_UINT64: 767 (void) snprintf(buffer, TEXT_LENGTH, "%llu", 768 ((union convert *)p_data)->tuint64); 769 770 DPRINTF((" text=%s\n", buffer)); 771 adt_write_text(event->ae_event_handle, buffer, format); 772 break; 773 case ADT_CHARSTAR: 774 string = ((union convert *)p_data)->tcharstar; 775 776 if (string == NULL) { 777 if (required) { 778 string = empty; 779 } else { 780 break; 781 } 782 } 783 DPRINTF((" text=%s\n", string)); 784 adt_write_text(event->ae_event_handle, string, format); 785 break; 786 case ADT_CHAR2STAR: 787 string_list = ((union convert *)p_data)->tchar2star; 788 p_data = adt_adjust_address(p_data, sizeof (char **), 789 sizeof (int)); 790 arrayCount = ((union convert *)p_data)->tint; 791 792 if (arrayCount < 0) 793 arrayCount = 0; 794 795 if ((arrayCount > 0) && (string_list != NULL)) { 796 for (i = 0; i < arrayCount; i++) { 797 string = string_list[i]; 798 if (string != NULL) 799 adt_write_text(event->ae_event_handle, 800 string, format); 801 } 802 } else if (required) { 803 adt_write_text(event->ae_event_handle, empty, format); 804 } else { 805 break; 806 } 807 break; 808 default: 809 if (!have_syslogged) { /* don't flood the log */ 810 adt_write_syslog("unsupported data conversion", 811 ENOTSUP); 812 have_syslogged = 1; 813 } 814 break; 815 } 816 DFLUSH 817 } 818 819 /* 820 * AUT_UAUTH 821 */ 822 823 /* ARGSUSED */ 824 static void 825 adt_to_uauth(datadef *def, void *p_data, int required, 826 struct adt_event_state *event, char *format) 827 { 828 char *string; 829 830 DPRINTF((" adt_to_uauth dd_datatype=%d\n", def->dd_datatype)); 831 832 string = ((union convert *)p_data)->tcharstar; 833 834 if (string == NULL) { 835 if (required) { 836 string = empty; 837 } else { 838 return; 839 } 840 } 841 DPRINTF((" text=%s\n", string)); 842 (void) au_write(event->ae_event_handle, au_to_uauth(string)); 843 } 844 845 /* 846 * AUT_ZONENAME 847 */ 848 849 /* ARGSUSED */ 850 static void 851 adt_to_zonename(datadef *def, void *p_data, int required, 852 struct adt_event_state *event, char *notUsed) 853 { 854 char *name; 855 856 name = ((union convert *)p_data)->tcharstar; 857 858 if (name != NULL) { 859 DPRINTF((" name=%s\n", name)); 860 (void) au_write(event->ae_event_handle, au_to_zonename(name)); 861 } else { 862 DPRINTF((" Null name\n")); 863 if (required) { 864 (void) au_write(event->ae_event_handle, 865 au_to_zonename(empty)); 866 } 867 } 868 } 869 870 /* 871 * ADT_IN_PEER dummy token 872 */ 873 874 /* ARGSUSED */ 875 static void 876 adt_to_in_peer(datadef *def, void *p_data, int required, 877 struct adt_event_state *event, char *notUsed) 878 { 879 int sock; 880 struct sockaddr_in6 peer; 881 int peerlen = sizeof (peer); 882 883 DPRINTF((" adt_to_in_peer dd_datatype=%d\n", def->dd_datatype)); 884 885 sock = ((union convert *)p_data)->tfd; 886 887 if (sock < 0) { 888 DPRINTF((" Socket fd %d\n", sock)); 889 if (required) { 890 adt_write_syslog("adt_to_in_peer no required socket", 891 0); 892 } 893 return; 894 } 895 if (getpeername(sock, (struct sockaddr *)&peer, (socklen_t *)&peerlen) 896 < 0) { 897 898 adt_write_syslog("adt_to_in_addr getpeername", errno); 899 return; 900 } 901 if (peer.sin6_family == AF_INET6) { 902 (void) au_write(event->ae_event_handle, 903 au_to_in_addr_ex(&(peer.sin6_addr))); 904 (void) au_write(event->ae_event_handle, 905 au_to_iport((ushort_t)peer.sin6_port)); 906 } else { 907 (void) au_write(event->ae_event_handle, 908 au_to_in_addr(&(((struct sockaddr_in *)&peer)->sin_addr))); 909 (void) au_write(event->ae_event_handle, 910 au_to_iport( 911 (ushort_t)(((struct sockaddr_in *)&peer)->sin_port))); 912 } 913 } 914 915 /* 916 * ADT_IN_REMOTE dummy token 917 * 918 * Similar to ADT_IN_PEER except the input is 919 * an IP address type (ADT_IPv4 | ADT_IPv6) and an address V4/V6 920 */ 921 922 /* ARGSUSED */ 923 static void 924 adt_to_in_remote(datadef *def, void *p_data, int required, 925 struct adt_event_state *event, char *notUsed) 926 { 927 int32_t type; 928 929 DPRINTF((" adt_to_in_remote dd_datatype=%d\n", def->dd_datatype)); 930 931 type = ((union convert *)p_data)->tuint32; 932 933 if (type == 0) { 934 if (required == 0) { 935 return; 936 } 937 /* required and not specified */ 938 adt_write_syslog("adt_to_in_remote required address not " 939 "specified", 0); 940 type = ADT_IPv4; 941 } 942 p_data = adt_adjust_address(p_data, sizeof (int32_t), 943 sizeof (uint32_t)); 944 945 switch (type) { 946 case ADT_IPv4: 947 (void) au_write(event->ae_event_handle, au_to_in_addr( 948 (struct in_addr *)&(((union convert *)p_data)->tuint32))); 949 break; 950 case ADT_IPv6: 951 (void) au_write(event->ae_event_handle, au_to_in_addr_ex( 952 (struct in6_addr *)&(((union convert *)p_data)->tuint32))); 953 break; 954 default: 955 adt_write_syslog("adt_to_in_remote invalid type", EINVAL); 956 return; 957 } 958 } 959 960 /* 961 * adt_to_iport takes a uint16_t IP port. 962 */ 963 964 /* ARGSUSED */ 965 static void 966 adt_to_iport(datadef *def, void *p_data, int required, 967 struct adt_event_state *event, char *notUsed) 968 { 969 ushort_t port; 970 971 DPRINTF((" adt_to_iport dd_datatype=%d\n", def->dd_datatype)); 972 973 port = ((union convert *)p_data)->tuint16; 974 975 if (port == 0) { 976 if (required == 0) { 977 return; 978 } 979 /* required and not specified */ 980 adt_write_syslog("adt_to_iport no required port", 0); 981 } 982 (void) au_write(event->ae_event_handle, au_to_iport(port)); 983 984 } 985 986 987 /* 988 * This is a compact table that defines only the tokens that are 989 * actually generated in the adt.xml file. It can't be a pure 990 * indexed table because the adt.xml language defines internal extension 991 * tokens for some processing. VIZ. ADT_CMD_ALT, ADT_AUT_PRIV_* (see 992 * adt_xlate.h), and the -AUT_PATH value. 993 */ 994 995 #define MAX_TOKEN_JMP 20 996 997 static struct token_jmp token_table[MAX_TOKEN_JMP] = 998 { 999 {AUT_CMD, adt_to_cmd}, 1000 {ADT_CMD_ALT, adt_to_cmd1}, 1001 {AUT_FMRI, adt_to_frmi}, 1002 {ADT_IN_PEER, adt_to_in_peer}, 1003 {ADT_IN_REMOTE, adt_to_in_remote}, 1004 {AUT_IPORT, adt_to_iport}, 1005 {AUT_LABEL, adt_to_label}, 1006 {AUT_NEWGROUPS, adt_to_newgroups}, 1007 {AUT_PATH, adt_to_path}, 1008 {-AUT_PATH, adt_to_pathlist}, /* private extension of token values */ 1009 {ADT_AUT_PRIV_L, adt_to_priv_limit}, 1010 {ADT_AUT_PRIV_I, adt_to_priv_inherit}, 1011 {ADT_AUT_PRIV_E, adt_to_priv_effective}, 1012 {AUT_PROCESS, adt_to_process}, 1013 {AUT_RETURN, adt_to_return}, 1014 {AUT_SUBJECT, adt_to_subject}, 1015 {AUT_TEXT, adt_to_text}, 1016 {AUT_TID, adt_to_tid}, 1017 {AUT_UAUTH, adt_to_uauth}, 1018 {AUT_ZONENAME, adt_to_zonename} 1019 }; 1020 1021 /* 1022 * {AUT_ACL, adt_to_acl}, not used 1023 * {AUT_ARBITRARY, adt_to_arbitrary}, AUT_ARBITRARY is undefined 1024 * {AUT_ARG, adt_to_arg}, not used 1025 * {AUT_ATTR, adt_to_attr}, not used in mountd 1026 * {AUT_XATOM, adt_to_atom}, not used 1027 * {AUT_EXEC_ARGS, adt_to_exec_args}, not used 1028 * {AUT_EXEC_ENV, adt_to_exec_env}, not used 1029 * {AUT_EXIT, adt_to_exit}, obsolete 1030 * {AUT_FILE, adt_to_file}, AUT_FILE is undefined 1031 * {AUT_XCOLORMAP, adt_to_colormap}, not used 1032 * {AUT_XCURSOR, adt_to_cursor}, not used 1033 * {AUT_XFONT, adt_to_font}, not used 1034 * {AUT_XGC, adt_to_gc}, not used 1035 * {AUT_GROUPS, adt_to_groups}, obsolete 1036 * {AUT_HEADER, adt_to_header}, generated by au_close 1037 * {AUT_IP, adt_to_ip}, not used 1038 * {AUT_IPC, adt_to_ipc}, not used 1039 * {AUT_IPC_PERM, adt_to_ipc_perm}, not used 1040 * {AUT_OPAQUE, adt_to_opaque}, not used 1041 * {AUT_XPIXMAP, adt_to_pixmap}, not used 1042 * {AUT_XPROPERTY, adt_to_property}, not used 1043 * {AUT_SEQ, adt_to_seq}, not used 1044 * {AUT_SOCKET, adt_to_socket}, not used 1045 * {AUT_SOCKET_INET, adt_to_socket_inet}, AUT_SOCKET_INET is undefined 1046 * {AUT_TRAILER, adt_to_trailer}, generated by au_close 1047 * {AUT_XCLIENT, adt_to_xclient} not used 1048 */ 1049 1050 /* find function to generate token */ 1051 1052 static adt_token_func_t 1053 adt_getTokenFunction(char token_id) 1054 { 1055 int i; 1056 struct token_jmp *p_jmp = token_table; 1057 1058 for (i = 0; i < MAX_TOKEN_JMP; i++) { 1059 if (token_id == p_jmp->jmp_id) { 1060 return (p_jmp->jmp_to); 1061 } 1062 p_jmp++; 1063 } 1064 errno = EINVAL; 1065 return (NULL); 1066 } 1067 1068 /* 1069 * adjustAddress -- given the address of data, its size, and the type of 1070 * the next data field, calculate the offset to the next piece of data. 1071 * Depending on the caller, "current" and "next" mean the current pointer 1072 * and the next pointer or the last pointer and the current pointer. 1073 */ 1074 void * 1075 adt_adjust_address(void *current_address, size_t current_size, 1076 size_t next_size) 1077 { 1078 ptrdiff_t adjustment; 1079 ptrdiff_t remainder; 1080 1081 adjustment = (size_t)current_address + current_size; 1082 1083 if (next_size) { 1084 remainder = adjustment % next_size; 1085 if (remainder != 0) 1086 adjustment += next_size - remainder; 1087 } 1088 return ((char *)adjustment); 1089 } 1090