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