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 2009 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 'tid' => 'AUT_TID', 791 'ipc' => 'AUT_IPC', 792 'ipc_perm' => 'AUT_IPC_PERM', 793 'iport' => 'AUT_IPORT', 794 'label' => 'AUT_LABEL', 795 'newgroups' => 'AUT_NEWGROUPS', 796 'opaque' => 'AUT_OPAQUE', 797 'path' => 'AUT_PATH', 798 'path_list' => '-AUT_PATH', # dummy token id 799 'process' => 'AUT_PROCESS', 800 'priv_effective' => 'ADT_AUT_PRIV_E', # dummy token id 801 'priv_limit' => 'ADT_AUT_PRIV_L', # dummy token id 802 'priv_inherit' => 'ADT_AUT_PRIV_I', # dummy token id 803 'return' => 'AUT_RETURN', 804 'seq' => 'AUT_SEQ', 805 'socket' => 'AUT_SOCKET', 806 'socket-inet' => 'AUT_SOCKET_INET', 807 'subject' => 'AUT_SUBJECT', 808 'text' => 'AUT_TEXT', 809 # 'trailer' => 'AUT_TRAILER', # not used 810 'uauth' => 'AUT_UAUTH', 811 'zonename' => 'AUT_ZONENAME' 812 ); 813 814 my @xlateEntryList = (); 815 my @jniEntryList = (); 816 817 my $external = $event->getExternal(); 818 my $internal = $event->getInternal(); 819 820 unless ($external) { 821 print STDERR "No external object captured for event $eventId\n"; 822 return; 823 } 824 unless ($internal) { 825 print STDERR "No internal object captured for event $eventId\n"; 826 return; 827 } 828 my @entryRef = $internal->getEntries(); 829 my $entryRef; 830 my @tokenOrder = (); 831 my $firstTokenIndex = 0; # djdj not used yet, djdj BUG! 832 # needs to be used by translate table 833 834 if ($internal->isReorder()) { # prescan the entry list to get the token order 835 my @inputOrder; 836 foreach $entryRef (@entryRef) { 837 my ($intEntry, $entry) = @$entryRef; 838 push (@inputOrder, $intEntry->getAttr('order')); 839 } 840 841 my $i; # walk down the inputOrder list once 842 my $k = 1; # discover next in line 843 my $l = 0; # who should point to next in line 844 for ($i = 0; $i <= $#inputOrder; $i++) { 845 my $j; 846 for ($j = 0; $j <= $#inputOrder; $j++) { 847 if ($k == $inputOrder[$j]) { 848 if ($k == 1) { 849 $firstTokenIndex = $j; 850 } else { 851 $tokenOrder[$l] = "&(selfReference[$j])"; 852 } 853 $l = $j; 854 last; 855 } 856 } 857 $k++; 858 } 859 $tokenOrder[$l] = 'NULL'; 860 } 861 else { # default order -- input order same as output 862 my $i; 863 my $j; 864 for ($i = 0; $i < $#entryRef; $i++) { 865 my $j = $i + 1; 866 $tokenOrder[$i] = "&(selfReference[$j])"; 867 } 868 $tokenOrder[$#entryRef] = 'NULL'; 869 } 870 871 my $sequence = 0; 872 foreach $entryRef (@entryRef) { 873 my ($intEntry, $entry) = @$entryRef; 874 my $entryId = $entry->getAttr('id'); 875 876 my ($extEntry, $unusedEntry, $tokenId) = 877 $external->getEntry($entryId); 878 my $opt = $extEntry->getAttr('opt'); 879 880 if ($opt eq 'none') { 881 if (defined ($doc->getToken($tokenId))) { 882 if (defined ($tokenType{$tokenId})) { 883 $tokenId = $tokenType{$tokenId}; 884 } 885 else { 886 print STDERR "token id $tokenId not implemented\n"; 887 } 888 } 889 else { 890 print STDERR "token = $tokenId is undefined\n"; 891 $tokenId = 'error'; 892 } 893 my ($xlate, $jni) = 894 formatTableEntry ('', $tokenId, $eventId, '', 0, 0, $tokenOrder[$sequence], 895 'NULL', ''); 896 push (@xlateEntryList, $xlate); 897 push (@jniEntryList, @$jni); 898 } 899 else { 900 my $dataType = $extEntry->getAttr('type'); 901 $dataType =~ s/\s+//g; # remove blanks (char * => char*) 902 903 my $enumGroup = ''; 904 if ($dataType =~ /^msg/i) { 905 $enumGroup = $dataType; 906 $enumGroup =~ s/^msg\s*//i; 907 $enumGroup = 'adt_' . $enumGroup; 908 } 909 my $required = ($opt eq 'required') ? 1 : 0; 910 my $tsol = 0; 911 my $tokenId = $intEntry->getAttr('token'); 912 my $token; 913 my $tokenName; 914 my $tokenFormat = $intEntry->getAttr('format'); 915 if (defined ($tokenFormat)) { 916 $tokenFormat = "\"$tokenFormat\""; 917 } 918 else { 919 $tokenFormat = 'NULL'; 920 } 921 922 if (defined ($token = $doc->getToken($tokenId))) { 923 $tsol = (lc $token->getUsage() eq 'tsol') ? 1 : 0; 924 if (defined ($tokenType{$tokenId})) { 925 $tokenName = $tokenType{$tokenId}; 926 } 927 else { 928 print STDERR "token id $tokenId not implemented\n"; 929 } 930 } 931 else { 932 print STDERR 933 "$tokenId is an unimplemented token ($entryId in $eventId)\n"; 934 $tokenName = 'AUT_TEXT'; 935 } 936 my ($xlate, $jni) = 937 formatTableEntry($entryId, $tokenName, $eventId, $dataType, $required, 938 $tsol, $tokenOrder[$sequence], $tokenFormat, 939 $enumGroup, (uc $omit eq 'JNI')); 940 push (@xlateEntryList, $xlate); 941 push (@jniEntryList, @$jni); 942 } 943 $sequence++; 944 } 945 $jniEventTable{$eventId} = [\@jniEntryList, $eventType, 946 $external->getAllowedTypes(), $eventHeader] 947 unless (uc $omit eq 'JNI') || ($omit eq 'always'); 948} 949 950sub formatTableEntry { 951 my ($id, $token, $eventId, $type, $required, $tsol, $sequence, $format, $enumGroup, 952 $omitJNI) = @_; 953 954 955 # does this map belong in the xml source? (at least the defaults?) 956 # fill in the default value only if it is other than zero. 957 # base type adt name, default value 958 my %entryDef = ( 'au_asid_t' => ['ADT_UINT32', ''], 959 'uint_t' => ['ADT_UINT32', ''], 960 'int' => ['ADT_INT', ''], 961 'int32_t' => ['ADT_INT32', ''], 962 'uid_t' => ['ADT_UID', 'AU_NOAUDITID'], 963 'gid_t' => ['ADT_GID', 'AU_NOAUDITID'], 964 'uid_t*' => ['ADT_UIDSTAR', ''], 965 'gid_t*' => ['ADT_GIDSTAR', ''], 966 'char' => ['ADT_CHAR', ''], 967 'char*' => ['ADT_CHARSTAR', ''], 968 'char**' => ['ADT_CHAR2STAR', ''], 969 'long' => ['ADT_LONG', ''], 970 'pid_t' => ['ADT_PID', ''], 971 'priv_set_t*' => ['ADT_PRIVSTAR', ''], 972 'ulong_t' => ['ADT_ULONG', ''], 973 'uint16_t', => ['ADT_UINT16', ''], 974 'uint32_t' => ['ADT_UINT32', ''], 975 'uint32_t*' => ['ADT_UINT32STAR', ''], 976 'uint32_t[]' => ['ADT_UINT32ARRAY', ''], 977 'uint64_t' => ['ADT_UINT64', ''], 978 'uint64_t*' => ['ADT_UINT64STAR', ''], 979 'm_label_t*' => ['ADT_MLABELSTAR', ''], 980 ); 981 my $xlateLabel = $uniLabel.$xlateUniLabelInc; 982 my $xlateLabelInc = 0; 983 my $xlateLine = ''; 984 my @jniLine = (); 985 986 # the list handling should be a simple loop with a loop of one 987 # falling out naturally. 988 989 unless ($type =~ /,/) { # if list, then generate sequence of entries 990 my $dataType; 991 my $dataSize; 992 my $xlateLabelRef = ''; 993 994 my $arraySize = ''; 995 $arraySize = $1 if ($type =~ s/\[(\d+)\]/[]/); 996 997 my $entryType = ${$entryDef{$type}}[0]; 998 999 my @xlateType = (); # for adt_xlate.c 1000 my $typeCount = 1; 1001 1002 if ($entryType) { 1003 $dataType = $entryType; 1004 $type =~ s/([^*]+)\s*(\*+)/$1 $2/; 1005 $type =~ s/\[\]//; 1006 $dataSize = "sizeof ($type)"; 1007 if ($arraySize) { 1008 $dataSize = "$arraySize * " . $dataSize; 1009 } 1010 $xlateLine = "{{$dataType, $dataSize}}"; 1011 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1012 } elsif ($type eq '') { 1013 $xlateLabelRef = 'NULL'; 1014 } elsif ($type =~ /^msg/i) { 1015 $type =~ s/^msg//i; 1016 $dataType = 'ADT_MSG'; 1017 my $dataEnum = 'ADT_LIST_' . uc $type; 1018 $xlateLine = "{{$dataType, $dataEnum}}"; 1019 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1020 } elsif ($type =~ /time_t/i) { 1021 $dataType = 'ADT_DATE'; 1022 $dataSize = "sizeof (time_t)"; 1023 $xlateLine = "{{$dataType, $dataSize}}"; 1024 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1025 } elsif ($type =~ /termid/i) { 1026 $dataType = 'ADT_TERMIDSTAR'; 1027 $dataSize = "sizeof (au_tid_addr_t *)"; 1028 $xlateLine = "{{$dataType, $dataSize}}"; 1029 push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); 1030 } elsif ($omitJNI) { 1031 $xlateLabelRef = 'NULL'; 1032 } else { 1033 print STDERR "$type is not an implemented data type\n"; 1034 $xlateLabelRef = 'NULL'; 1035 } 1036 $xlateLabelRef = '&' . $xlateLabel . '[0]' 1037 unless $xlateLabelRef eq 'NULL'; 1038 1039 # "EOL" is where a comma should go unless end of list 1040 $xlateLine = "{$token,\t1,\t$xlateLabelRef,\t$sequence,\n" . 1041 "\t\t0,\t$required,\t$tsol,\t$format}EOL"; 1042 1043 } else { # is a list 1044 my @type = split(/,/, $type); 1045 my @arraySize = (); 1046 my @id = split(/,/, $id); 1047 my @jniId = @id; 1048 my $dataType; 1049 my $typeCount = ($#type + 1); 1050 my @xlateType = (); 1051 my @default = (); 1052 1053 foreach my $dtype (@type) { 1054 my $jniId = shift @jniId; 1055 my $id = shift @id; 1056 my $arraySize = ''; 1057 $arraySize = $1 if ($dtype =~ s/\[(\d+)\]/[]/); 1058 1059 my $entryType = ${$entryDef{$dtype}}[0]; 1060 if ($entryType) { 1061 my $type = $dtype; 1062 $type =~ s/([^*]+)\s*(\*+)/$1 $2/; 1063 $type =~ s/\[\]//; 1064 1065 my $sizeString = "sizeof"; 1066 $sizeString = "$arraySize * " . $sizeString if $arraySize; 1067 push (@xlateType, "\{$entryType, $sizeString ($type)\}"); 1068 push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]); 1069 } elsif ($type =~ /^msg/i) { 1070 $type =~ s/^msg//i; 1071 $dataType = 'ADT_MSG'; 1072 my $dataEnum = 'ADT_LIST_' . uc $type; 1073 push (@xlateType, "\{$dataType, $dataEnum\}};"); 1074 push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]); 1075 } elsif ($type =~ /time_t/i) { 1076 $dataType = 'ADT_DATE'; 1077 push (@xlateType, "\{$entryType, sizeof ($type)\}"); 1078 push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]); 1079 } elsif ($type =~ /termid/i) { 1080 $dataType = 'ADT_TERMIDSTAR'; 1081 push (@xlateType, "\{$dataType, sizeof (au_tid_addr_t *)\}"); 1082 push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]); 1083 } elsif ($omitJNI) { 1084 # nothing to do. 1085 } else { 1086 print STDERR "$dtype is not an implemented data type\n"; 1087 } 1088 if (${$entryDef{$dtype}}[1]) { 1089 push (@default, $id, ${$entryDef{$dtype}}[1]); 1090 } 1091 } 1092 my $xlateArray = "\[$typeCount\] =\t{" . join(",\n\t\t\t\t", @xlateType) . "};"; 1093 1094 $xlateLine = 1095 "{$token,\t$typeCount,\t&$xlateLabel\[0\],\t$sequence,\n" . 1096 "\t\t0,\t$required,\t$tsol,\t$format}EOL"; 1097 } 1098 $xlateUniLabelInc++ if $xlateLabelInc; 1099 return ($xlateLine, \@jniLine); 1100} 1101 1102sub generateMsgLists { 1103 my $textList = shift; 1104 1105 my $textName = $textList->getId(); 1106 my $header = $textList->getHeader(); 1107 my $start = $textList->getMsgStart(); 1108 my $public = $textList->getMsgPublic(); 1109 my $deprecated = $textList->getDeprecated(); 1110 1111 print "$textName starts at $start\n" if $debug; 1112 1113 my $entry; 1114 my @entry; 1115 while ($entry = $textList->getNextMsg()) { 1116 if ($debug) { 1117 my ($id, $text) = split(/\s*::\s*/, $entry); 1118 print " $id = $text\n"; 1119 } 1120 unshift (@entry, $entry); 1121 } 1122 $msg_list{$textName} = 1123 [\@entry, [$header, $start, $public, $deprecated]]; 1124} 1125sub readAuditEventFile { 1126 my $eventListFile = shift; 1127 1128 open(Event, $eventListFile) 1129 or die "can't open $eventListFile: $!\n"; 1130 while(<Event>) { 1131 next if /^\s*#/; 1132 next if /^\s*$/; 1133 my ($value, $name) = split(/\s*:\s*/); 1134 next if $value < 6000; 1135 $eventCode{$name} = $value; 1136 } 1137 close Event; 1138} 1139