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