1#!/usr/perl5/bin/perl -w 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# 23# Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26 27# auditxml_jni [-d] <xml input file> 28 29# auditxml takes the audit record description (.xml file) and 30# generates the files needed for the Java 31 32use auditxml; 33use Getopt::Std; 34use vars qw($opt_d); 35use strict; 36 37 38our $debug = 0; # normal use is to set via the file being parsed. 39 # <debug set="on"/> or <debug set="off"/> or <debug/> 40 # if the set attribute is omitted, debug state is toggled 41 # Override with appDebug, but toggle won't do what you 42 # want. 43my $appDebug = 0; # used after return from "new auditxml"; 44 45my $genNotice = " 46DO NOT EDIT. This file is auto generated by the Solaris Audit 47system from adt.xml. 48 49See http://opensolaris.org/os/project/audit/ 50"; 51 52# trim leading/trailing newlines 53$genNotice =~ s/^\n//s; 54$genNotice =~ s/\n$//s; 55my $prog = $0; $prog =~ s|.*/||g; 56my $usage = "usage: $prog [-d] file.xml\n"; 57 58getopts('d'); 59 60$appDebug = $opt_d; 61 62my $uniLabel = "adr"; 63my $xlateUniLabelInc = 0; 64 65die $usage if ($#ARGV < 0); 66 67# where everything comes from and where it goes: 68 69my $templatePath = './'; 70my $javaPath = $templatePath; 71my $bsmBuildPath = "../libbsm"; 72 73my $jniBuildPath = "$javaPath"; 74 75my $buildPathJ = "$jniBuildPath/com/sun/audit"; 76my $buildPathJNI = "$jniBuildPath/common"; 77 78my $auditEventJ = "$buildPathJ/AuditEvent.java"; 79my $jniC = "$buildPathJNI/adt_jni_event.c"; 80my $mapFile = "$jniBuildPath/common/mapfile-vers"; 81 82my $doc = new auditxml ($ARGV[0]); # input XML file 83 84$debug = $appDebug; 85 86my %jniEventTable = (); 87my %externalIdNo = (); 88my %msg_list = (); 89my %eventCode = (); 90 91readAuditEventFile("$bsmBuildPath/audit_event.txt"); 92 93my $event; 94while ($event = $doc->getNextEvent()) { 95 my $eventId = $event->getId(); 96 my $idNo = $event->getIdNo(); 97 $externalIdNo{$eventId} = $idNo; 98 my $super; 99 my $omit = $event->getOmit(); 100 my $eventType = ''; 101 if ($super = $event->getSuperClass()) { 102 $event = $super; 103 $eventType = 'instance'; 104 } else { 105 $eventType = $event->getType(); 106 } 107 108 # c file table for translation 109 generateTableC($event, $eventId, $eventType, undef, $omit); 110} 111 112while (my $textList = $doc->getNextMsgId()) { 113 generateMsgLists($textList); # enum -> text mappings 114} 115 116printJavaFiles($jniC, $auditEventJ, $buildPathJ, $mapFile); 117 118exit 0; 119 120 121 122sub printJavaFiles { 123 my $jniFile = shift; 124 my $javaFile = shift; 125 my $subclassPath = shift; 126 my $mapFile = shift; 127 128 # warning: time_t is equated to jlong since there is no 129 # way to use sys/types.h in Java code. 130 # java long is C long long, 64 bits. 131 # java int is 32 bits. 132 133 my %java_jni = ('ADT_DATE' => ['long', 'jlong'], 134 'ADT_UINT' => ['int', 'jint'], 135 'ADT_INT' => ['int', 'jint'], 136 'ADT_INT32' => ['int', 'jint'], 137 'ADT_UID' => ['int', 'jint'], 138 'ADT_GID' => ['int', 'jint'], 139 'ADT_UIDSTAR' => ['int[]', 'jintArray'], 140 'ADT_GIDSTAR' => ['int[]', 'jintArray'], 141 'ADT_CHAR' => ['String', 'jchar'], 142 'ADT_CHARSTAR' => ['String', 'jstring'], 143 'ADT_CHAR2STAR' => ['String[]', 'jstring'], 144 'ADT_MSG' => ['int', 'jint'], 145 'ADT_PID' => ['int', 'jint'], 146# ADT_PRIVSTAR omitted -- not implemented and the audit records that 147# use it must be coded to emit no java. We'll cross that bridge 148# when someone in Java land needs to generate a priv token. 149 'ADT_LONG' => ['int', 'jint'], 150 'ADT_TERMIDSTAR' => ['String', 'jstring'], # hostname -> termid 151 'ADT_ULONG' => ['int', 'jint'], 152 'ADT_UINT16' => ['int', 'jint'], 153 'ADT_UINT32' => ['int', 'jint'], 154 'ADT_UINT32STAR' => ['int[]', 'jintArray'], 155# ADT_UINT32ARRAY omitted; no Java implementation yet 156 'ADT_UINT64' => ['long', 'jlong'], 157 'ADT_UINT64STAR' => ['long[]', 'jlongArray'] 158 ); 159 my $noMemory = 'gettext("Out of memory")'; 160 161 # open output files 162 open (Cfile, ">$jniFile") or 163 die "can't open output file ($jniFile): $!\n"; 164 open (Jfile, ">$javaFile") or 165 die "can't open output file ($javaFile): $!\n"; 166 open (MapFile, ">$mapFile") or 167 die "can't open output file ($mapFile): $!\n"; 168 169 # write headers 170 my $notice = $genNotice; 171 $notice =~ s/\n/\n * /gs; 172 $notice =~ s/\s+\n/\n/gs; 173 print Cfile <<EOF; 174/* 175 * $notice 176 */ 177 178#include "../../libbsm/common/adt_xlate.h" 179#include <jni.h> 180#include "../com/sun/audit/AuditSession.h" /* javah output */ 181#include "adt_jni.h" 182#include <stdlib.h> 183#include <string.h> 184 185static char *except_class = "java/lang/Exception"; 186 187EOF 188 print Jfile <<EOF; 189/* 190 * $notice 191 */ 192 193package com.sun.audit; 194 195public class AuditEvent { 196 protected AuditSession sh; // associated session object 197 198 public AuditEvent(AuditSession auSession) 199 throws Error 200 { 201 202 sh = auSession; 203 } 204 205 // Manifest values: keep them in sync with generated <bsm/adt_event.h>. 206 // It is generated by \$SRC/lib/libbsm/auditxml 207 208 public static final int ADT_SUCCESS = 0; // generated 209 public static final int ADT_FAILURE = -1; // generated 210 211 // See the subclasses of AuditEvent for mapping message codes 212 // to events 213EOF 214 215 my $notice_map = $genNotice; 216 $notice_map =~ s/\n/\n# /gs; 217 $notice_map =~ s/\s+\n/\n/gs; 218 print MapFile <<EOF; 219# 220# $notice_map 221# 222 223SUNWprivate_1.1 { 224 global: 225 c2j_pointer; 226 j2c_pointer; 227 Java_com_sun_audit_AuditSession_bsmAuditOn; 228 Java_com_sun_audit_AuditSession_startSession; 229 Java_com_sun_audit_AuditSession_endSession; 230 Java_com_sun_audit_AuditSession_dupSession; 231 Java_com_sun_audit_AuditSession_getSessionId; 232 Java_com_sun_audit_AuditSession_exportSessionData; 233 Java_com_sun_audit_AuditSession_sessionAttr; 234 235# One subclass of AuditEvent per audit record... 236EOF 237 238 # generate java final int classes to line up with string/enums 239 240 foreach my $listName (sort keys %msg_list) { 241 my $shortName = uc $listName; 242 $shortName =~ s/_TEXT//; 243 my ($listRef, $headref) = @{$msg_list{$listName}}; 244 my @listValue = @$listRef; 245 my ($header, $enumValue, $public, $deprecated) = @$headref; 246 my $listValue; 247 248 print Jfile "\n\t// adt_$listName" . "\n\n"; 249 print Jfile "\tpublic static final int ADT_$shortName", 250 " = $enumValue;\n" if $enumValue; 251 252 next unless ($#listValue >= 0); 253 print Jfile "\t// Deprecated message list\n" if $deprecated; 254 foreach $listValue (@listValue) { 255 my ($id, $text) = split(/\s*::\s*/, $listValue); 256 print Jfile "\t// $text\n"; 257 print Jfile "\tpublic static final int ADT_$shortName"; 258 print Jfile "_$id = $enumValue;\n"; 259 $enumValue++; 260 } 261 } 262 263 # generate event creation and access functions and event 264 # generation for both Java and JNI 265 # com.sun.audit.AuditEvent_xxx.java 266 foreach my $eventId (sort keys %jniEventTable) { 267 my ($ref1, $eventType, $allowedIds, $header) = @{$jniEventTable{$eventId}}; 268 $eventCode{$eventId} = -1 if ($eventType eq 'generic'); 269 my @entries = @$ref1; 270 my $entries = $#entries; 271 my $root = $eventId; 272 $root =~ s/AUE_//; 273 my $javaPutEvent = 'putEvent'; 274 my $putMethod = "_$root"; 275 $putMethod =~ s/_/_1/g; 276 277 my $jniPutEvent = "Java_com_sun_audit_AuditEvent$putMethod" . "_$javaPutEvent"; 278 279 # the subclass file template isn't used; it may be needed to get 280 # the right file header stuff in place. The subclassPath is 281 # the directory that contains 'em. 282 283 my $validSfile = 1; 284 unless (open(Sfile, ">$subclassPath/AuditEvent_$root.java")) { 285 print STDERR "can't open class file AuditEvent_$root.java: $!\n"; 286 $validSfile = 0; 287 } 288 if ($eventCode{"AUE_$root"}) { 289 if ($validSfile) { 290 print Sfile <<EOF; 291/* 292 * $notice 293 */ 294 295package com.sun.audit; 296 297// audit event: $eventId = $eventCode{"AUE_$root"} 298 299public class AuditEvent_$root extends AuditEvent { 300 301EOF 302 } 303 } else { 304 print STDERR "no event code for $eventId. Is audit_event current?\n"; 305 } 306 my $nativeParameterList = ''; 307 my $jniParameterList = ''; 308 my $specParameterList = ''; 309 my $jniStorageList = ''; 310 my $needCleanupTarget = 0; 311 my $jniFreeList = ''; 312 313 my $haveStringDef = 0; 314 my $haveCDef = 0; 315 my $haveLengthDef = 0; 316 my $haveStringArrayDef = 0; 317 my $cntTermidDef = 0; 318 my $jniDefine; 319 my $needLocaleDefined = 0; 320 my $jniADTalloc; 321 if (defined $header && ($header > 0) ) { 322 $jniDefine = "union union_of_events *event;\n" . 323 "\tadt_session_data_t *session;\n"; 324 $jniADTalloc = '(union union_of_events *)adt_alloc_event'; 325 } else { 326 $jniDefine = "adt_event_data_t *event;\n" . 327 "\tadt_session_data_t *session;\n"; 328 $jniADTalloc = 'adt_alloc_event'; 329 } 330 my $ref2; 331 foreach $ref2 (@entries) { 332 my ($id, $type) = @$ref2; 333 my $jniRoot = $root . $id; 334 $jniRoot =~ s/_/_1/g; # escape unicode "_" 335 336 my $p_event; 337 if (defined $header && ($header > 0) ) { 338 $p_event = "event->d$header.adt_$root.$id"; 339 } else { 340 $p_event = "event->adt_$root.$id"; 341 } 342 343 if ($type eq 'ADT_UINT32STAR') { # int array 344 $needLocaleDefined = 1; 345 346 347 $jniStorageList .= <<EOF; 348 /* $id */ 349 length = (*env)->GetArrayLength(env, $id); 350 $p_event = 351 (int *)malloc(length * sizeof (int)); 352 if ($p_event == NULL) { 353 locale = I18N_SETUP; 354 local_throw(env, except_class, 355 $noMemory); 356 (void) setlocale(LC_MESSAGES, locale); 357 goto cleanup; 358 } 359 (*env)->GetIntArrayRegion(env, $id, 0, length, 360 (int *)$p_event); 361EOF 362 363 364 $jniFreeList .= "\n\tif ($p_event != NULL)\n" . 365 "\t\tfree($p_event);\n"; 366 unless ($haveLengthDef) { 367 $haveLengthDef = 1; 368 $jniDefine .= "\tint\t\t\tlength;\n"; 369 } 370 $nativeParameterList .= ",\n\t int[]\t$id"; 371 $jniParameterList .= ",\n jintArray\t$id"; 372 $specParameterList .= ", jintArray"; 373 $needCleanupTarget = 1; 374 } elsif (($type eq 'ADT_UIDSTAR') || 375 ($type eq 'ADT_GIDSTAR')) { # gid_t array 376 my $cType = 'uid_t'; 377 $cType = 'gid_t' if ($type eq 'ADT_GIDSTAR'); 378 $needLocaleDefined = 1; 379 380 381 $jniStorageList .= <<EOF; 382 /* $id */ 383 length = (*env)->GetArrayLength(env, $id); 384 $p_event = 385 ($cType *)malloc(length * sizeof ($cType)); 386 if ($p_event == NULL) { 387 locale = I18N_SETUP; 388 local_throw(env, except_class, 389 $noMemory); 390 (void) setlocale(LC_MESSAGES, locale); 391 goto cleanup; 392 } 393 (*env)->GetIntArrayRegion(env, $id, 0, length, 394 (int *)$p_event); 395EOF 396 397 398 $jniFreeList .= 399 "\n\tif ($p_event != NULL)\n" . 400 "\t\tfree($p_event);\n"; 401 unless ($haveLengthDef) { 402 $haveLengthDef = 1; 403 $jniDefine .= "\tint\t\t\tlength;\n"; 404 } 405 $nativeParameterList .= ",\n\t int[]\t$id"; 406 $jniParameterList .= ",\n jintArray\t$id"; 407 $specParameterList .= ", jintArray"; 408 $needCleanupTarget = 1; 409 } elsif ($type eq 'ADT_UINT64STAR') { # long array 410 $needLocaleDefined = 1; 411 $jniStorageList .= <<EOF; 412 /* $id */ 413 length = (*env)->GetArrayLength(env, $id); 414 $p_event = 415 (long *)malloc(length * sizeof (long long)); 416 if ($p_event == NULL) { 417 locale = I18N_SETUP; 418 local_throw(env, except_class, 419 $noMemory); 420 (void) setlocale(LC_MESSAGES, locale); 421 goto cleanup; 422 } 423 (*env)->GetLongArrayRegion(env, $id, 0, length, 424 $p_event); 425EOF 426 $jniFreeList .= "\n\tif ($p_event != NULL)\n" . 427 "\t\tfree($p_event);\n"; 428 unless ($haveLengthDef) { 429 $haveLengthDef = 1; 430 $jniDefine .= "\tint\t\t\tlength;\n"; 431 } 432 $nativeParameterList .= ",\n\t long[]\t$id"; 433 $jniParameterList .= ",\n jlongArray\t$id"; 434 $specParameterList .= ", jlongArray"; 435 $needCleanupTarget = 1; 436 } elsif ($type eq 'ADT_CHAR') { # string in Java, char in C 437 $jniStorageList .= <<EOF; 438 439 /* $id */ 440 c = (char *)(*env)->GetStringUTFChars(env, $id, NULL); 441 if (c == NULL) 442 goto cleanup; /* exception thrown */ 443 $p_event = *c; 444 (*env)->ReleaseStringUTFChars(env, $id, c); 445EOF 446 # no need to free anything 447 unless ($haveCDef) { 448 $haveCDef = 1; 449 $jniDefine .= "\tchar\t\t\t*c\n"; 450 } 451 $nativeParameterList .= ",\n\t String\t$id"; 452 $jniParameterList .= ",\n jstring\t$id"; 453 $specParameterList .= ", jstring"; 454 } elsif ($type eq 'ADT_CHARSTAR') { 455 $needLocaleDefined = 1; 456 $jniStorageList .= <<EOF; 457 /* $id */ 458 if ($id != NULL) { 459 string = (char *)(*env)->GetStringUTFChars( 460 env, $id, NULL); 461 if (string == NULL) 462 goto cleanup; /* exception thrown */ 463 $p_event = strdup(string); 464 (*env)->ReleaseStringUTFChars(env, $id, string); 465 if ($p_event == NULL) { 466 locale = I18N_SETUP; 467 local_throw(env, except_class, 468 $noMemory); 469 (void) setlocale(LC_MESSAGES, locale); 470 goto cleanup; 471 } 472 } 473EOF 474 $jniFreeList .= "\n\tif ($p_event != NULL)\n" . 475 "\t\tfree($p_event);\n"; 476 unless ($haveStringDef) { 477 $haveStringDef = 1; 478 $jniDefine .= "\tchar\t\t\t*string;\n"; 479 } 480 $nativeParameterList .= ",\n\t String\t$id"; 481 $jniParameterList .= ",\n jstring\t$id"; 482 $specParameterList .= ", jstring"; 483 $needCleanupTarget = 1; 484 } elsif ($type eq 'ADT_CHAR2STAR') { # array of string 485 $needLocaleDefined = 1; 486 $jniStorageList .= <<EOF; 487 /* $id */ 488 length = (*env)->GetArrayLength(env, $id); 489 $p_event = (char **)malloc(length 490 * sizeof (char *)); 491 if ($p_event == NULL) { 492 locale = I18N_SETUP; 493 local_throw(env, except_class, 494 $noMemory); 495 (void) setlocale(LC_MESSAGES, locale); 496 goto cleanup; 497 } 498 p = $p_event; 499 for (i = 0; i < length; i++) { 500 jString = (*env)->GetObjectArrayElement(env, $id, i); 501 string = (char *)(*env)->GetStringUTFChars( 502 env, jString, NULL); 503 if (string == NULL) 504 goto cleanup; /* exception thrown */ 505 *p = strdup(string); 506 (*env)->ReleaseStringUTFChars(env, jString, string); 507 if (*p == NULL) { 508 locale = I18N_SETUP; 509 local_throw(env, except_class, 510 $noMemory); 511 (void) setlocale(LC_MESSAGES, locale); 512 while (p >= $p_event) 513 free(*p--); 514 goto cleanup; 515 } 516 p++; 517 } 518EOF 519 $jniFreeList .= 520 "\n\tif ($p_event != NULL)\n" . 521 "\t\tfree($p_event);\n"; 522 unless ($haveStringArrayDef) { 523 unless ($haveStringDef) { 524 $haveStringDef = 1; 525 $jniDefine .= <<EOF; 526 char *string; 527EOF 528 } 529 unless ($haveLengthDef) { 530 $haveLengthDef = 1; 531 $jniDefine .= <<EOF; 532 int length; 533EOF 534 } 535 $haveStringArrayDef = 1; 536 $jniDefine .= <<EOF; 537 int i; 538 char **p; 539 jstring jString; 540EOF 541 } 542 $nativeParameterList .= ",\n\t String[]\t$id"; 543 $jniParameterList .= ",\n jstring\t$id"; 544 $specParameterList .= ", jstring"; 545 $needCleanupTarget = 1; 546 } elsif ($type eq 'ADT_TERMIDSTAR') { 547 $needLocaleDefined = 1; 548 549 $jniStorageList .= <<EOF; 550 /* $id */ 551 hostname$cntTermidDef = (char *)(*env)->GetStringUTFChars(env, $id, NULL); 552 553 if (adt_load_hostname((const char *)hostname$cntTermidDef, &termid$cntTermidDef)) { 554 local_throw(env, except_class, 555 gettext("hostname lookup failed")); 556 } 557 $p_event = termid$cntTermidDef; 558 559 (*env)->ReleaseStringUTFChars(env, $id, hostname$cntTermidDef); 560EOF 561 562 $jniFreeList .= "\n\tif (hostname$cntTermidDef != NULL)\n" . 563 "\t\tfree(hostname$cntTermidDef);\n"; 564 $jniFreeList .= "\n\tif (termid$cntTermidDef != NULL)\n" . 565 "\t\tfree(termid$cntTermidDef);\n"; 566 567 $jniDefine .= "\tchar\t\t\t*hostname$cntTermidDef;\n"; 568 $jniDefine .= "\tadt_termid_t\t\t*termid$cntTermidDef;\n"; #djdj 569 570 $cntTermidDef++; 571 572 my ($nativeParameter, $jniParameter) = @{$java_jni{$type}}; 573 $nativeParameterList .= ",\n\t $nativeParameter\t$id"; 574 $jniParameterList .= ",\n $jniParameter\t$id"; 575 $specParameterList .= ", $jniParameter"; 576 $needCleanupTarget = 1; 577 } else { # all others are primitive types 578 $jniStorageList .= "\n\t$p_event = $id;\n"; 579 my ($nativeParameter, $jniParameter) = @{$java_jni{$type}}; 580 $nativeParameter = "$nativeParameter\t" 581 if length $nativeParameter < 4; # why? 582 $nativeParameterList .= ",\n\t $nativeParameter\t$id"; 583 $jniParameterList .= ",\n $jniParameter\t$id"; 584 $specParameterList .= ", $jniParameter"; 585 } 586 } 587 if ($needLocaleDefined) { 588 $jniDefine .= <<EOF 589 char *locale; 590EOF 591 } 592 my $genericOverride = ''; 593 my $idParameter = $eventId; 594 $idParameter =~ s/AUE_/ADT_/; 595 if ($eventType eq 'generic') { 596 $genericOverride = ', jint eventId'; 597 $idParameter = 'eventId'; 598 } 599 $jniFreeList = "\tcleanup:\n" . $jniFreeList if $needCleanupTarget; 600 601 print Cfile qq{/* ARGSUSED */ 602JNIEXPORT void JNICALL 603$jniPutEvent( 604 JNIEnv *env, 605 jobject self, 606 jbyteArray jsession$genericOverride, 607 jint status, 608 jint ret_val$jniParameterList) 609{ 610 $jniDefine 611 (void) j2c_pointer(env, jsession, (char **)&session); 612 613 event = $jniADTalloc(session, $idParameter); 614 615$jniStorageList 616 (void) adt_put_event((adt_event_data_t *)event, status, ret_val); 617 618$jniFreeList 619 adt_free_event((adt_event_data_t *)event); 620} 621}; 622 print MapFile qq{ 623 $jniPutEvent; }; 624 my $overrideParameter = ''; 625 if ($eventType eq 'generic') { 626 $overrideParameter = 'int eventId,'; 627 my @allowed = @$allowedIds; 628 if (@allowed) { 629 my $i; 630 if ($validSfile) { 631 print Sfile "\t// Allowed values for eventId in putEvent:\n"; 632 for ($i = 0; $i <= $#allowed; $i++) { 633 my $idNo = $externalIdNo{$allowed[$i]}; 634 $allowed[$i] =~ s/AUE_/ADT_/; 635 print Sfile "\tstatic final int $allowed[$i] = ", 636 "$idNo;\n"; 637 } 638 print Sfile "\n"; 639 } 640 } else { 641 print STDERR "Generic event with no allowed instances: $eventId\n"; 642 } 643 } 644 if ($validSfile) { 645 print Sfile <<EOF; 646 private native void $javaPutEvent(byte[]session, $overrideParameter 647 int status, int ret_val$nativeParameterList); 648 649 public AuditEvent_$root(AuditSession session) 650 throws Exception 651 { 652 super(session); 653 } 654 655EOF 656 my $javaParameterList = ''; 657 foreach $ref2 (@entries) { 658 my ($id, $type, $format, $jComment, $required) = @$ref2; 659 660 # generate java native method prototypes 661 # and the corresponding C method implementation 662 663 my $javaMethodName = "$id"; 664 my $javaStorageName = $javaMethodName . '_val'; 665 my $jniMethodName = $root . $id; 666 my $storage; 667 my $enumUsage = ''; 668 my $jParam = @{$java_jni{$type}}[0]; 669 my $comment = ''; 670 if ($required) { 671 if ($format ne 'NULL') { 672 $comment = "\t// (required) formatted: $format"; 673 } else { 674 $comment = "\t// required"; 675 } 676 } else { 677 if ($format ne 'NULL') { 678 $comment = "\t// (optional) formatted: $format"; 679 } else { 680 $comment = "\t// optional"; 681 } 682 } 683 if (($type eq 'ADT_UINT32STAR') || 684 ($type eq 'ADT_UIDSTAR') || 685 ($type eq 'ADT_GIDSTAR')) { # int array 686 $storage = "int[] $javaStorageName" . ($required ? 687 ' = {}' : ''); 688 $javaParameterList .= ",\n\t\t\t $javaStorageName"; 689 } elsif ($type eq 'ADT_UINT64STAR') { # long array 690 $storage = "long[] $javaStorageName" . ($required ? 691 ' = {}' : ''); 692 $javaParameterList .= ",\n\t\t\t $javaStorageName"; 693 } elsif (($type eq 'ADT_CHARSTAR') || 694 ($type eq 'ADT_CHAR')) { # string 695 $storage = "String $javaStorageName" . ($required ? 696 ' = ""' : ''); 697 $javaParameterList .= ",\n\t\t\t $javaStorageName"; 698 } elsif ($type eq 'ADT_CHAR2STAR') { # array of string 699 $storage = "String[] $javaStorageName" . ($required ? 700 ' = {}' : ''); 701 $javaParameterList .= ",\n\t\t\t $javaStorageName"; 702 } elsif ($type eq 'ADT_TERMIDSTAR') { # array of string 703 $storage = "String $javaStorageName" . ($required ? 704 ' = ""' : ''); 705 $javaParameterList .= ",\n\t\t\t $javaStorageName"; 706 } else { # all others are primitive types 707 $storage = "$jParam $javaStorageName = 0"; 708 $javaParameterList .= ",\n\t\t\t $javaStorageName"; 709 $enumUsage = "\n\t// See $jComment in AuditEvent.java for valid values" 710 if $jComment; 711 } 712 print Sfile <<EOF; 713$enumUsage 714 private $storage;$comment 715 public void $javaMethodName($jParam setTo) 716 { 717 $javaStorageName = setTo; 718 } 719EOF 720 } # end foreach (@entries) 721 if ($eventType eq 'generic') { 722 print Sfile <<EOF; 723 724 public void putEvent(int status, int ret_val, int eventId) 725 { 726 byte[] session = super.sh.getSession(); 727 728 if ((super.sh.AuditIsOn) && (super.sh.ValidSession)) 729 $javaPutEvent(session, eventId, 730 status, ret_val$javaParameterList); 731 } 732} 733EOF 734 } else { 735 print Sfile <<EOF; 736 737 public void putEvent(int status, int ret_val) 738 { 739 byte[] session = super.sh.getSession(); 740 741 if ((super.sh.AuditIsOn) && (super.sh.ValidSession)) 742 $javaPutEvent(session, status, ret_val$javaParameterList); 743 } 744} 745EOF 746 } 747 close Sfile; 748 } # end if ($validSfile); 749 } 750 751 # write trailers 752 print Jfile <<EOF; 753 754} 755EOF 756 print MapFile <<EOF; 757 758 local: 759 *; 760}; 761EOF 762 close Cfile; 763 close Jfile; 764 close MapFile; 765} 766 767sub generateTableC { 768 my $event = shift; 769 my $eventId = shift; 770 my $eventType = shift; 771 my $eventHeader = shift; 772 my $omit = shift; 773 774 my %tokenType = ( 775 'acl' => 'AUT_ACL', 776 'arbitrary' => 'AUT_ARBITRARY', 777 'arg' => 'AUT_ARG', 778 'attr' => 'AUT_ATTR', 779 'command' => 'AUT_CMD', 780 'command_1' => 'ADT_CMD_ALT', # dummy token id 781 'date' => 'AUT_TEXT', 782 'exec_args' => 'AUT_EXEC_ARGS', 783 'exec_env' => 'AUT_EXEC_ENV', 784 'exit' => 'AUT_EXIT', 785 'file' => 'AUT_FILE', 786 'fmri' => 'AUT_FMRI', 787 'groups' => 'AUT_GROUPS', 788 # 'header' => 'AUT_HEADER', # not used 789 'in_addr' => 'AUT_IN_ADDR', 790 'ipc' => 'AUT_IPC', 791 'ipc_perm' => 'AUT_IPC_PERM', 792 'iport' => 'AUT_IPORT', 793 'label' => 'AUT_LABEL', 794 'newgroups' => 'AUT_NEWGROUPS', 795 'opaque' => 'AUT_OPAQUE', 796 'path' => 'AUT_PATH', 797 'path_list' => '-AUT_PATH', # dummy token id 798 'process' => 'AUT_PROCESS', 799 'priv_effective' => 'ADT_AUT_PRIV_E', # dummy token id 800 'priv_limit' => 'ADT_AUT_PRIV_L', # dummy token id 801 'priv_inherit' => 'ADT_AUT_PRIV_I', # dummy token id 802 'return' => 'AUT_RETURN', 803 'seq' => 'AUT_SEQ', 804 'socket' => 'AUT_SOCKET', 805 'socket-inet' => 'AUT_SOCKET_INET', 806 'subject' => 'AUT_SUBJECT', 807 'text' => 'AUT_TEXT', 808 'tid' => 'AUT_TID', 809 # 'trailer' => 'AUT_TRAILER', # not used 810 'uauth' => 'AUT_UAUTH', 811 'user' => 'AUT_USER', 812 'zonename' => 'AUT_ZONENAME' 813 ); 814 815 my @xlateEntryList = (); 816 my @jniEntryList = (); 817 818 my $external = $event->getExternal(); 819 my $internal = $event->getInternal(); 820 821 unless ($external) { 822 print STDERR "No external object captured for event $eventId\n"; 823 return; 824 } 825 unless ($internal) { 826 print STDERR "No internal object captured for event $eventId\n"; 827 return; 828 } 829 my @entryRef = $internal->getEntries(); 830 my $entryRef; 831 my @tokenOrder = (); 832 my $firstTokenIndex = 0; # djdj not used yet, djdj BUG! 833 # needs to be used by translate table 834 835 if ($internal->isReorder()) { # prescan the entry list to get the token order 836 my @inputOrder; 837 foreach $entryRef (@entryRef) { 838 my ($intEntry, $entry) = @$entryRef; 839 push (@inputOrder, $intEntry->getAttr('order')); 840 } 841 842 my $i; # walk down the inputOrder list once 843 my $k = 1; # discover next in line 844 my $l = 0; # who should point to next in line 845 for ($i = 0; $i <= $#inputOrder; $i++) { 846 my $j; 847 for ($j = 0; $j <= $#inputOrder; $j++) { 848 if ($k == $inputOrder[$j]) { 849 if ($k == 1) { 850 $firstTokenIndex = $j; 851 } else { 852 $tokenOrder[$l] = "&(selfReference[$j])"; 853 } 854 $l = $j; 855 last; 856 } 857 } 858 $k++; 859 } 860 $tokenOrder[$l] = 'NULL'; 861 } 862 else { # default order -- input order same as output 863 my $i; 864 my $j; 865 for ($i = 0; $i < $#entryRef; $i++) { 866 my $j = $i + 1; 867 $tokenOrder[$i] = "&(selfReference[$j])"; 868 } 869 $tokenOrder[$#entryRef] = 'NULL'; 870 } 871 872 my $sequence = 0; 873 foreach $entryRef (@entryRef) { 874 my ($intEntry, $entry) = @$entryRef; 875 my $entryId = $entry->getAttr('id'); 876 877 my ($extEntry, $unusedEntry, $tokenId) = 878 $external->getEntry($entryId); 879 my $opt = $extEntry->getAttr('opt'); 880 881 if ($opt eq 'none') { 882 if (defined ($doc->getToken($tokenId))) { 883 if (defined ($tokenType{$tokenId})) { 884 $tokenId = $tokenType{$tokenId}; 885 } 886 else { 887 print STDERR "token id $tokenId not implemented\n"; 888 } 889 } 890 else { 891 print STDERR "token = $tokenId is undefined\n"; 892 $tokenId = 'error'; 893 } 894 my ($xlate, $jni) = 895 formatTableEntry ('', $tokenId, $eventId, '', 0, 0, $tokenOrder[$sequence], 896 'NULL', ''); 897 push (@xlateEntryList, $xlate); 898 push (@jniEntryList, @$jni); 899 } 900 else { 901 my $dataType = $extEntry->getAttr('type'); 902 $dataType =~ s/\s+//g; # remove blanks (char * => char*) 903 904 my $enumGroup = ''; 905 if ($dataType =~ /^msg/i) { 906 $enumGroup = $dataType; 907 $enumGroup =~ s/^msg\s*//i; 908 $enumGroup = 'adt_' . $enumGroup; 909 } 910 my $required = ($opt eq 'required') ? 1 : 0; 911 my $tsol = 0; 912 my $tokenId = $intEntry->getAttr('token'); 913 my $token; 914 my $tokenName; 915 my $tokenFormat = $intEntry->getAttr('format'); 916 if (defined ($tokenFormat)) { 917 $tokenFormat = "\"$tokenFormat\""; 918 } 919 else { 920 $tokenFormat = 'NULL'; 921 } 922 923 if (defined ($token = $doc->getToken($tokenId))) { 924 $tsol = (lc $token->getUsage() eq 'tsol') ? 1 : 0; 925 if (defined ($tokenType{$tokenId})) { 926 $tokenName = $tokenType{$tokenId}; 927 } 928 else { 929 print STDERR "token id $tokenId not implemented\n"; 930 } 931 } 932 else { 933 print STDERR 934 "$tokenId is an unimplemented token ($entryId in $eventId)\n"; 935 $tokenName = 'AUT_TEXT'; 936 } 937 my ($xlate, $jni) = 938 formatTableEntry($entryId, $tokenName, $eventId, $dataType, $required, 939 $tsol, $tokenOrder[$sequence], $tokenFormat, 940 $enumGroup, (uc $omit eq 'JNI')); 941 push (@xlateEntryList, $xlate); 942 push (@jniEntryList, @$jni); 943 } 944 $sequence++; 945 } 946 $jniEventTable{$eventId} = [\@jniEntryList, $eventType, 947 $external->getAllowedTypes(), $eventHeader] 948 unless (uc $omit eq 'JNI') || ($omit eq 'always'); 949} 950 951sub formatTableEntry { 952 my ($id, $token, $eventId, $type, $required, $tsol, $sequence, $format, $enumGroup, 953 $omitJNI) = @_; 954 955 956 # does this map belong in the xml source? (at least the defaults?) 957 # fill in the default value only if it is other than zero. 958 # base type adt name, default value 959 my %entryDef = ( 'au_asid_t' => ['ADT_UINT32', ''], 960 'uint_t' => ['ADT_UINT32', ''], 961 'int' => ['ADT_INT', ''], 962 'int32_t' => ['ADT_INT32', ''], 963 'uid_t' => ['ADT_UID', 'AU_NOAUDITID'], 964 'gid_t' => ['ADT_GID', 'AU_NOAUDITID'], 965 'uid_t*' => ['ADT_UIDSTAR', ''], 966 'gid_t*' => ['ADT_GIDSTAR', ''], 967 'char' => ['ADT_CHAR', ''], 968 'char*' => ['ADT_CHARSTAR', ''], 969 'char**' => ['ADT_CHAR2STAR', ''], 970 'long' => ['ADT_LONG', ''], 971 'pid_t' => ['ADT_PID', ''], 972 'priv_set_t*' => ['ADT_PRIVSTAR', ''], 973 'ulong_t' => ['ADT_ULONG', ''], 974 'uint16_t', => ['ADT_UINT16', ''], 975 'uint32_t' => ['ADT_UINT32', ''], 976 'uint32_t*' => ['ADT_UINT32STAR', ''], 977 'uint32_t[]' => ['ADT_UINT32ARRAY', ''], 978 'uint64_t' => ['ADT_UINT64', ''], 979 'uint64_t*' => ['ADT_UINT64STAR', ''], 980 'm_label_t*' => ['ADT_MLABELSTAR', ''], 981 ); 982 my $xlateLabel = $uniLabel.$xlateUniLabelInc; 983 my $xlateLabelInc = 0; 984 my $xlateLine = ''; 985 my @jniLine = (); 986 987 # the list handling should be a simple loop with a loop of one 988 # falling out naturally. 989 990 unless ($type =~ /,/) { # if list, then generate sequence of entries 991 my $dataType; 992 my $dataSize; 993 my $xlateLabelRef = ''; 994 995 my $arraySize = ''; 996 $arraySize = $1 if ($type =~ s/\[(\d+)\]/[]/); 997 998 my $entryType = ${$entryDef{$type}}[0]; 999 1000 my @xlateType = (); # for adt_xlate.c 1001 my $typeCount = 1; 1002 1003 if ($entryType) { 1004 $dataType = $entryType; 1005 $type =~ s/([^*]+)\s*(\*+)/$1 $2/; 1006 $type =~ s/\[\]//; 1007 $dataSize = "sizeof ($type)"; 1008 if ($arraySize) { 1009 $dataSize = "$arraySize * " . $dataSize; 1010 } 1011 $xlateLine = "{{$dataType, $dataSize}}"; 1012 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1013 } elsif ($type eq '') { 1014 $xlateLabelRef = 'NULL'; 1015 } elsif ($type =~ /^msg/i) { 1016 $type =~ s/^msg//i; 1017 $dataType = 'ADT_MSG'; 1018 my $dataEnum = 'ADT_LIST_' . uc $type; 1019 $xlateLine = "{{$dataType, $dataEnum}}"; 1020 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1021 } elsif ($type =~ /time_t/i) { 1022 $dataType = 'ADT_DATE'; 1023 $dataSize = "sizeof (time_t)"; 1024 $xlateLine = "{{$dataType, $dataSize}}"; 1025 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1026 } elsif ($type =~ /termid/i) { 1027 $dataType = 'ADT_TERMIDSTAR'; 1028 $dataSize = "sizeof (au_tid_addr_t *)"; 1029 $xlateLine = "{{$dataType, $dataSize}}"; 1030 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1031 } elsif ($omitJNI) { 1032 $xlateLabelRef = 'NULL'; 1033 } else { 1034 print STDERR "$type is not an implemented data type\n"; 1035 $xlateLabelRef = 'NULL'; 1036 } 1037 $xlateLabelRef = '&' . $xlateLabel . '[0]' 1038 unless $xlateLabelRef eq 'NULL'; 1039 1040 # "EOL" is where a comma should go unless end of list 1041 $xlateLine = "{$token,\t1,\t$xlateLabelRef,\t$sequence,\n" . 1042 "\t\t0,\t$required,\t$tsol,\t$format}EOL"; 1043 1044 } else { # is a list 1045 my @type = split(/,/, $type); 1046 my @arraySize = (); 1047 my @id = split(/,/, $id); 1048 my @jniId = @id; 1049 my $dataType; 1050 my $typeCount = ($#type + 1); 1051 my @xlateType = (); 1052 my @default = (); 1053 1054 foreach my $dtype (@type) { 1055 my $jniId = shift @jniId; 1056 my $id = shift @id; 1057 my $arraySize = ''; 1058 $arraySize = $1 if ($dtype =~ s/\[(\d+)\]/[]/); 1059 1060 my $entryType = ${$entryDef{$dtype}}[0]; 1061 if ($entryType) { 1062 my $type = $dtype; 1063 $type =~ s/([^*]+)\s*(\*+)/$1 $2/; 1064 $type =~ s/\[\]//; 1065 1066 my $sizeString = "sizeof"; 1067 $sizeString = "$arraySize * " . $sizeString if $arraySize; 1068 push (@xlateType, "\{$entryType, $sizeString ($type)\}"); 1069 push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]); 1070 } elsif ($type =~ /^msg/i) { 1071 $type =~ s/^msg//i; 1072 $dataType = 'ADT_MSG'; 1073 my $dataEnum = 'ADT_LIST_' . uc $type; 1074 push (@xlateType, "\{$dataType, $dataEnum\}};"); 1075 push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]); 1076 } elsif ($type =~ /time_t/i) { 1077 $dataType = 'ADT_DATE'; 1078 push (@xlateType, "\{$entryType, sizeof ($type)\}"); 1079 push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]); 1080 } elsif ($type =~ /termid/i) { 1081 $dataType = 'ADT_TERMIDSTAR'; 1082 push (@xlateType, "\{$dataType, sizeof (au_tid_addr_t *)\}"); 1083 push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]); 1084 } elsif ($omitJNI) { 1085 # nothing to do. 1086 } else { 1087 print STDERR "$dtype is not an implemented data type\n"; 1088 } 1089 if (${$entryDef{$dtype}}[1]) { 1090 push (@default, $id, ${$entryDef{$dtype}}[1]); 1091 } 1092 } 1093 my $xlateArray = "\[$typeCount\] =\t{" . join(",\n\t\t\t\t", @xlateType) . "};"; 1094 1095 $xlateLine = 1096 "{$token,\t$typeCount,\t&$xlateLabel\[0\],\t$sequence,\n" . 1097 "\t\t0,\t$required,\t$tsol,\t$format}EOL"; 1098 } 1099 $xlateUniLabelInc++ if $xlateLabelInc; 1100 return ($xlateLine, \@jniLine); 1101} 1102 1103sub generateMsgLists { 1104 my $textList = shift; 1105 1106 my $textName = $textList->getId(); 1107 my $header = $textList->getHeader(); 1108 my $start = $textList->getMsgStart(); 1109 my $public = $textList->getMsgPublic(); 1110 my $deprecated = $textList->getDeprecated(); 1111 1112 print "$textName starts at $start\n" if $debug; 1113 1114 my $entry; 1115 my @entry; 1116 while ($entry = $textList->getNextMsg()) { 1117 if ($debug) { 1118 my ($id, $text) = split(/\s*::\s*/, $entry); 1119 print " $id = $text\n"; 1120 } 1121 unshift (@entry, $entry); 1122 } 1123 $msg_list{$textName} = 1124 [\@entry, [$header, $start, $public, $deprecated]]; 1125} 1126sub readAuditEventFile { 1127 my $eventListFile = shift; 1128 1129 open(Event, $eventListFile) 1130 or die "can't open $eventListFile: $!\n"; 1131 while(<Event>) { 1132 next if /^\s*#/; 1133 next if /^\s*$/; 1134 my ($value, $name) = split(/\s*:\s*/); 1135 next if $value < 6000; 1136 $eventCode{$name} = $value; 1137 } 1138 close Event; 1139} 1140