2N/A#!/usr/perl5/bin/perl -w
2N/A#
2N/A# CDDL HEADER START
2N/A#
2N/A# The contents of this file are subject to the terms of the
2N/A# Common Development and Distribution License (the "License").
2N/A# You may not use this file except in compliance with the License.
2N/A#
2N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A# or http://www.opensolaris.org/os/licensing.
2N/A# See the License for the specific language governing permissions
2N/A# and limitations under the License.
2N/A#
2N/A# When distributing Covered Code, include this CDDL HEADER in each
2N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A# If applicable, add the following below this CDDL HEADER, with the
2N/A# fields enclosed by brackets "[]" replaced with your own identifying
2N/A# information: Portions Copyright [yyyy] [name of copyright owner]
2N/A#
2N/A# CDDL HEADER END
2N/A#
2N/A#
2N/A# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A#
2N/A
2N/A# auditxml_jni [-d] <xml input file>
2N/A
2N/A# auditxml takes the audit record description (.xml file) and
2N/A# generates the files needed for the Java
2N/A
2N/Ause auditxml;
2N/Ause Getopt::Std;
2N/Ause vars qw($opt_d);
2N/Ause strict;
2N/A
2N/A
2N/Aour $debug = 0; # normal use is to set via the file being parsed.
2N/A # <debug set="on"/> or <debug set="off"/> or <debug/>
2N/A # if the set attribute is omitted, debug state is toggled
2N/A # Override with appDebug, but toggle won't do what you
2N/A # want.
2N/Amy $appDebug = 0; # used after return from "new auditxml";
2N/A
2N/Amy $genNotice = "
2N/ADO NOT EDIT. This file is auto generated by the Solaris Audit
2N/Asystem from adt.xml.
2N/A
2N/ASee http://opensolaris.org/os/project/audit/
2N/A";
2N/A
2N/A# trim leading/trailing newlines
2N/A$genNotice =~ s/^\n//s;
2N/A$genNotice =~ s/\n$//s;
2N/Amy $prog = $0; $prog =~ s|.*/||g;
2N/Amy $usage = "usage: $prog [-d] file.xml\n";
2N/A
2N/Agetopts('d');
2N/A
2N/A$appDebug = $opt_d;
2N/A
2N/Amy $uniLabel = "adr";
2N/Amy $xlateUniLabelInc = 0;
2N/A
2N/Adie $usage if ($#ARGV < 0);
2N/A
2N/A# where everything comes from and where it goes:
2N/A
2N/Amy $templatePath = './';
2N/Amy $javaPath = $templatePath;
2N/Amy $bsmBuildPath = "../libbsm";
2N/A
2N/Amy $jniBuildPath = "$javaPath";
2N/A
2N/Amy $buildPathJ = "$jniBuildPath/com/sun/audit";
2N/Amy $buildPathJNI = "$jniBuildPath/common";
2N/A
2N/Amy $auditEventJ = "$buildPathJ/AuditEvent.java";
2N/Amy $jniC = "$buildPathJNI/adt_jni_event.c";
2N/Amy $mapFile = "$jniBuildPath/common/mapfile-vers";
2N/A
2N/Amy $doc = new auditxml ($ARGV[0]); # input XML file
2N/A
2N/A$debug = $appDebug;
2N/A
2N/Amy %jniEventTable = ();
2N/Amy %externalIdNo = ();
2N/Amy %msg_list = ();
2N/Amy %eventCode = ();
2N/A
2N/AreadAuditEventFile("$bsmBuildPath/audit_event.txt");
2N/A
2N/Amy $event;
2N/Awhile ($event = $doc->getNextEvent()) {
2N/A my $eventId = $event->getId();
2N/A my $idNo = $event->getIdNo();
2N/A $externalIdNo{$eventId} = $idNo;
2N/A my $super;
2N/A my $omit = $event->getOmit();
2N/A my $eventType = '';
2N/A if ($super = $event->getSuperClass()) {
2N/A $event = $super;
2N/A $eventType = 'instance';
2N/A } else {
2N/A $eventType = $event->getType();
2N/A }
2N/A
2N/A # c file table for translation
2N/A generateTableC($event, $eventId, $eventType, undef, $omit);
2N/A}
2N/A
2N/Awhile (my $textList = $doc->getNextMsgId()) {
2N/A generateMsgLists($textList); # enum -> text mappings
2N/A}
2N/A
2N/AprintJavaFiles($jniC, $auditEventJ, $buildPathJ, $mapFile);
2N/A
2N/Aexit 0;
2N/A
2N/A
2N/A
2N/Asub printJavaFiles {
2N/A my $jniFile = shift;
2N/A my $javaFile = shift;
2N/A my $subclassPath = shift;
2N/A my $mapFile = shift;
2N/A
2N/A # warning: time_t is equated to jlong since there is no
2N/A # way to use sys/types.h in Java code.
2N/A # java long is C long long, 64 bits.
2N/A # java int is 32 bits.
2N/A
2N/A my %java_jni = ('ADT_DATE' => ['long', 'jlong'],
2N/A 'ADT_UINT' => ['int', 'jint'],
2N/A 'ADT_INT' => ['int', 'jint'],
2N/A 'ADT_INT32' => ['int', 'jint'],
2N/A 'ADT_UID' => ['int', 'jint'],
2N/A 'ADT_GID' => ['int', 'jint'],
2N/A 'ADT_UIDSTAR' => ['int[]', 'jintArray'],
2N/A 'ADT_GIDSTAR' => ['int[]', 'jintArray'],
2N/A 'ADT_CHAR' => ['String', 'jchar'],
2N/A 'ADT_CHARSTAR' => ['String', 'jstring'],
2N/A 'ADT_CHAR2STAR' => ['String[]', 'jstring'],
2N/A 'ADT_MSG' => ['int', 'jint'],
2N/A 'ADT_PID' => ['int', 'jint'],
2N/A# ADT_PRIVSTAR omitted -- not implemented and the audit records that
2N/A# use it must be coded to emit no java. We'll cross that bridge
2N/A# when someone in Java land needs to generate a priv token.
2N/A 'ADT_LONG' => ['int', 'jint'],
2N/A 'ADT_TERMIDSTAR' => ['String', 'jstring'], # hostname -> termid
2N/A 'ADT_ULONG' => ['int', 'jint'],
2N/A 'ADT_UINT16' => ['int', 'jint'],
2N/A 'ADT_UINT32' => ['int', 'jint'],
2N/A 'ADT_UINT32STAR' => ['int[]', 'jintArray'],
2N/A# ADT_UINT32ARRAY omitted; no Java implementation yet
2N/A 'ADT_UINT64' => ['long', 'jlong'],
2N/A 'ADT_UINT64STAR' => ['long[]', 'jlongArray']
2N/A );
2N/A my $noMemory = 'gettext("Out of memory")';
2N/A
2N/A # open output files
2N/A open (Cfile, ">$jniFile") or
2N/A die "can't open output file ($jniFile): $!\n";
2N/A open (Jfile, ">$javaFile") or
2N/A die "can't open output file ($javaFile): $!\n";
2N/A open (MapFile, ">$mapFile") or
2N/A die "can't open output file ($mapFile): $!\n";
2N/A
2N/A # write headers
2N/A my $notice = $genNotice;
2N/A $notice =~ s/\n/\n * /gs;
2N/A $notice =~ s/\s+\n/\n/gs;
2N/A print Cfile <<EOF;
2N/A/*
2N/A * $notice
2N/A */
2N/A
2N/A#include "../../libbsm/common/adt_xlate.h"
2N/A#include <jni.h>
2N/A#include "../com/sun/audit/AuditSession.h" /* javah output */
2N/A#include "adt_jni.h"
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A
2N/Astatic char *except_class = "java/lang/Exception";
2N/A
2N/AEOF
2N/A print Jfile <<EOF;
2N/A/*
2N/A * $notice
2N/A */
2N/A
2N/Apackage com.sun.audit;
2N/A
2N/Apublic class AuditEvent {
2N/A protected AuditSession sh; // associated session object
2N/A
2N/A public AuditEvent(AuditSession auSession)
2N/A throws Error
2N/A {
2N/A
2N/A sh = auSession;
2N/A }
2N/A
2N/A // Manifest values: keep them in sync with generated <bsm/adt_event.h>.
2N/A // It is generated by \$SRC/lib/libbsm/auditxml
2N/A
2N/A public static final int ADT_SUCCESS = 0; // generated
2N/A public static final int ADT_FAILURE = -1; // generated
2N/A
2N/A // See the subclasses of AuditEvent for mapping message codes
2N/A // to events
2N/AEOF
2N/A
2N/A my $notice_map = $genNotice;
2N/A $notice_map =~ s/\n/\n# /gs;
2N/A $notice_map =~ s/\s+\n/\n/gs;
2N/A print MapFile <<EOF;
2N/A#
2N/A# $notice_map
2N/A#
2N/A
2N/A\$mapfile_version 2
2N/A
2N/ASTUB_OBJECT;
2N/A
2N/ASYMBOL_VERSION SUNWprivate_1.1 {
2N/A global:
2N/A c2j_pointer;
2N/A j2c_pointer;
2N/A Java_com_sun_audit_AuditSession_bsmAuditOn;
2N/A Java_com_sun_audit_AuditSession_startSession;
2N/A Java_com_sun_audit_AuditSession_endSession;
2N/A Java_com_sun_audit_AuditSession_dupSession;
2N/A Java_com_sun_audit_AuditSession_getSessionId;
2N/A Java_com_sun_audit_AuditSession_exportSessionData;
2N/A Java_com_sun_audit_AuditSession_sessionAttr;
2N/A
2N/A# One subclass of AuditEvent per audit record...
2N/AEOF
2N/A
2N/A # generate java final int classes to line up with string/enums
2N/A
2N/A foreach my $listName (sort keys %msg_list) {
2N/A my $shortName = uc $listName;
2N/A $shortName =~ s/_TEXT//;
2N/A my ($listRef, $headref) = @{$msg_list{$listName}};
2N/A my @listValue = @$listRef;
2N/A my ($header, $enumValue, $public, $deprecated) = @$headref;
2N/A my $listValue;
2N/A
2N/A print Jfile "\n\t// adt_$listName" . "\n\n";
2N/A print Jfile "\tpublic static final int ADT_$shortName",
2N/A " = $enumValue;\n" if $enumValue;
2N/A
2N/A next unless ($#listValue >= 0);
2N/A print Jfile "\t// Deprecated message list\n" if $deprecated;
2N/A foreach $listValue (@listValue) {
2N/A my ($id, $text) = split(/\s*::\s*/, $listValue);
2N/A print Jfile "\t// $text\n";
2N/A print Jfile "\tpublic static final int ADT_$shortName";
2N/A print Jfile "_$id = $enumValue;\n";
2N/A $enumValue++;
2N/A }
2N/A }
2N/A
2N/A # generate event creation and access functions and event
2N/A # generation for both Java and JNI
2N/A # com.sun.audit.AuditEvent_xxx.java
2N/A foreach my $eventId (sort keys %jniEventTable) {
2N/A my ($ref1, $eventType, $allowedIds, $header) = @{$jniEventTable{$eventId}};
2N/A $eventCode{$eventId} = -1 if ($eventType eq 'generic');
2N/A my @entries = @$ref1;
2N/A my $entries = $#entries;
2N/A my $root = $eventId;
2N/A $root =~ s/AUE_//;
2N/A my $javaPutEvent = 'putEvent';
2N/A my $putMethod = "_$root";
2N/A $putMethod =~ s/_/_1/g;
2N/A
2N/A my $jniPutEvent = "Java_com_sun_audit_AuditEvent$putMethod" . "_$javaPutEvent";
2N/A
2N/A # the subclass file template isn't used; it may be needed to get
2N/A # the right file header stuff in place. The subclassPath is
2N/A # the directory that contains 'em.
2N/A
2N/A my $validSfile = 1;
2N/A unless (open(Sfile, ">$subclassPath/AuditEvent_$root.java")) {
2N/A print STDERR "can't open class file AuditEvent_$root.java: $!\n";
2N/A $validSfile = 0;
2N/A }
2N/A if ($eventCode{"AUE_$root"}) {
2N/A if ($validSfile) {
2N/A print Sfile <<EOF;
2N/A/*
2N/A * $notice
2N/A */
2N/A
2N/Apackage com.sun.audit;
2N/A
2N/A// audit event: $eventId = $eventCode{"AUE_$root"}
2N/A
2N/Apublic class AuditEvent_$root extends AuditEvent {
2N/A
2N/AEOF
2N/A }
2N/A } else {
2N/A print STDERR "no event code for $eventId. Is audit_event current?\n";
2N/A }
2N/A my $nativeParameterList = '';
2N/A my $jniParameterList = '';
2N/A my $specParameterList = '';
2N/A my $jniStorageList = '';
2N/A my $needCleanupTarget = 0;
2N/A my $jniFreeList = '';
2N/A
2N/A my $haveStringDef = 0;
2N/A my $haveCDef = 0;
2N/A my $haveLengthDef = 0;
2N/A my $haveStringArrayDef = 0;
2N/A my $cntTermidDef = 0;
2N/A my $jniDefine;
2N/A my $needLocaleDefined = 0;
2N/A my $jniADTalloc;
2N/A if (defined $header && ($header > 0) ) {
2N/A $jniDefine = "union union_of_events *event;\n" .
2N/A "\tadt_session_data_t *session;\n";
2N/A $jniADTalloc = '(union union_of_events *)adt_alloc_event';
2N/A } else {
2N/A $jniDefine = "adt_event_data_t *event;\n" .
2N/A "\tadt_session_data_t *session;\n";
2N/A $jniADTalloc = 'adt_alloc_event';
2N/A }
2N/A my $ref2;
2N/A foreach $ref2 (@entries) {
2N/A my ($id, $type) = @$ref2;
2N/A my $jniRoot = $root . $id;
2N/A $jniRoot =~ s/_/_1/g; # escape unicode "_"
2N/A
2N/A my $p_event;
2N/A if (defined $header && ($header > 0) ) {
2N/A $p_event = "event->d$header.adt_$root.$id";
2N/A } else {
2N/A $p_event = "event->adt_$root.$id";
2N/A }
2N/A
2N/A if ($type eq 'ADT_UINT32STAR') { # int array
2N/A $needLocaleDefined = 1;
2N/A
2N/A
2N/A $jniStorageList .= <<EOF;
2N/A /* $id */
2N/A length = (*env)->GetArrayLength(env, $id);
2N/A $p_event =
2N/A (int *)malloc(length * sizeof (int));
2N/A if ($p_event == NULL) {
2N/A locale = I18N_SETUP;
2N/A local_throw(env, except_class,
2N/A $noMemory);
2N/A (void) setlocale(LC_MESSAGES, locale);
2N/A goto cleanup;
2N/A }
2N/A (*env)->GetIntArrayRegion(env, $id, 0, length,
2N/A (int *)$p_event);
2N/AEOF
2N/A
2N/A
2N/A $jniFreeList .= "\n\tif ($p_event != NULL)\n" .
2N/A "\t\tfree($p_event);\n";
2N/A unless ($haveLengthDef) {
2N/A $haveLengthDef = 1;
2N/A $jniDefine .= "\tint\t\t\tlength;\n";
2N/A }
2N/A $nativeParameterList .= ",\n\t int[]\t$id";
2N/A $jniParameterList .= ",\n jintArray\t$id";
2N/A $specParameterList .= ", jintArray";
2N/A $needCleanupTarget = 1;
2N/A } elsif (($type eq 'ADT_UIDSTAR') ||
2N/A ($type eq 'ADT_GIDSTAR')) { # gid_t array
2N/A my $cType = 'uid_t';
2N/A $cType = 'gid_t' if ($type eq 'ADT_GIDSTAR');
2N/A $needLocaleDefined = 1;
2N/A
2N/A
2N/A $jniStorageList .= <<EOF;
2N/A /* $id */
2N/A length = (*env)->GetArrayLength(env, $id);
2N/A $p_event =
2N/A ($cType *)malloc(length * sizeof ($cType));
2N/A if ($p_event == NULL) {
2N/A locale = I18N_SETUP;
2N/A local_throw(env, except_class,
2N/A $noMemory);
2N/A (void) setlocale(LC_MESSAGES, locale);
2N/A goto cleanup;
2N/A }
2N/A (*env)->GetIntArrayRegion(env, $id, 0, length,
2N/A (int *)$p_event);
2N/AEOF
2N/A
2N/A
2N/A $jniFreeList .=
2N/A "\n\tif ($p_event != NULL)\n" .
2N/A "\t\tfree($p_event);\n";
2N/A unless ($haveLengthDef) {
2N/A $haveLengthDef = 1;
2N/A $jniDefine .= "\tint\t\t\tlength;\n";
2N/A }
2N/A $nativeParameterList .= ",\n\t int[]\t$id";
2N/A $jniParameterList .= ",\n jintArray\t$id";
2N/A $specParameterList .= ", jintArray";
2N/A $needCleanupTarget = 1;
2N/A } elsif ($type eq 'ADT_UINT64STAR') { # long array
2N/A $needLocaleDefined = 1;
2N/A $jniStorageList .= <<EOF;
2N/A /* $id */
2N/A length = (*env)->GetArrayLength(env, $id);
2N/A $p_event =
2N/A (long *)malloc(length * sizeof (long long));
2N/A if ($p_event == NULL) {
2N/A locale = I18N_SETUP;
2N/A local_throw(env, except_class,
2N/A $noMemory);
2N/A (void) setlocale(LC_MESSAGES, locale);
2N/A goto cleanup;
2N/A }
2N/A (*env)->GetLongArrayRegion(env, $id, 0, length,
2N/A $p_event);
2N/AEOF
2N/A $jniFreeList .= "\n\tif ($p_event != NULL)\n" .
2N/A "\t\tfree($p_event);\n";
2N/A unless ($haveLengthDef) {
2N/A $haveLengthDef = 1;
2N/A $jniDefine .= "\tint\t\t\tlength;\n";
2N/A }
2N/A $nativeParameterList .= ",\n\t long[]\t$id";
2N/A $jniParameterList .= ",\n jlongArray\t$id";
2N/A $specParameterList .= ", jlongArray";
2N/A $needCleanupTarget = 1;
2N/A } elsif ($type eq 'ADT_CHAR') { # string in Java, char in C
2N/A $jniStorageList .= <<EOF;
2N/A
2N/A /* $id */
2N/A c = (char *)(*env)->GetStringUTFChars(env, $id, NULL);
2N/A if (c == NULL)
2N/A goto cleanup; /* exception thrown */
2N/A $p_event = *c;
2N/A (*env)->ReleaseStringUTFChars(env, $id, c);
2N/AEOF
2N/A # no need to free anything
2N/A unless ($haveCDef) {
2N/A $haveCDef = 1;
2N/A $jniDefine .= "\tchar\t\t\t*c\n";
2N/A }
2N/A $nativeParameterList .= ",\n\t String\t$id";
2N/A $jniParameterList .= ",\n jstring\t$id";
2N/A $specParameterList .= ", jstring";
2N/A } elsif ($type eq 'ADT_CHARSTAR') {
2N/A $needLocaleDefined = 1;
2N/A $jniStorageList .= <<EOF;
2N/A /* $id */
2N/A if ($id != NULL) {
2N/A string = (char *)(*env)->GetStringUTFChars(
2N/A env, $id, NULL);
2N/A if (string == NULL)
2N/A goto cleanup; /* exception thrown */
2N/A $p_event = strdup(string);
2N/A (*env)->ReleaseStringUTFChars(env, $id, string);
2N/A if ($p_event == NULL) {
2N/A locale = I18N_SETUP;
2N/A local_throw(env, except_class,
2N/A $noMemory);
2N/A (void) setlocale(LC_MESSAGES, locale);
2N/A goto cleanup;
2N/A }
2N/A }
2N/AEOF
2N/A $jniFreeList .= "\n\tif ($p_event != NULL)\n" .
2N/A "\t\tfree($p_event);\n";
2N/A unless ($haveStringDef) {
2N/A $haveStringDef = 1;
2N/A $jniDefine .= "\tchar\t\t\t*string;\n";
2N/A }
2N/A $nativeParameterList .= ",\n\t String\t$id";
2N/A $jniParameterList .= ",\n jstring\t$id";
2N/A $specParameterList .= ", jstring";
2N/A $needCleanupTarget = 1;
2N/A } elsif ($type eq 'ADT_CHAR2STAR') { # array of string
2N/A $needLocaleDefined = 1;
2N/A $jniStorageList .= <<EOF;
2N/A /* $id */
2N/A length = (*env)->GetArrayLength(env, $id);
2N/A $p_event = (char **)malloc(length
2N/A * sizeof (char *));
2N/A if ($p_event == NULL) {
2N/A locale = I18N_SETUP;
2N/A local_throw(env, except_class,
2N/A $noMemory);
2N/A (void) setlocale(LC_MESSAGES, locale);
2N/A goto cleanup;
2N/A }
2N/A p = $p_event;
2N/A for (i = 0; i < length; i++) {
2N/A jString = (*env)->GetObjectArrayElement(env, $id, i);
2N/A string = (char *)(*env)->GetStringUTFChars(
2N/A env, jString, NULL);
2N/A if (string == NULL)
2N/A goto cleanup; /* exception thrown */
2N/A *p = strdup(string);
2N/A (*env)->ReleaseStringUTFChars(env, jString, string);
2N/A if (*p == NULL) {
2N/A locale = I18N_SETUP;
2N/A local_throw(env, except_class,
2N/A $noMemory);
2N/A (void) setlocale(LC_MESSAGES, locale);
2N/A while (p >= $p_event)
2N/A free(*p--);
2N/A goto cleanup;
2N/A }
2N/A p++;
2N/A }
2N/AEOF
2N/A $jniFreeList .=
2N/A "\n\tif ($p_event != NULL)\n" .
2N/A "\t\tfree($p_event);\n";
2N/A unless ($haveStringArrayDef) {
2N/A unless ($haveStringDef) {
2N/A $haveStringDef = 1;
2N/A $jniDefine .= <<EOF;
2N/A char *string;
2N/AEOF
2N/A }
2N/A unless ($haveLengthDef) {
2N/A $haveLengthDef = 1;
2N/A $jniDefine .= <<EOF;
2N/A int length;
2N/AEOF
2N/A }
2N/A $haveStringArrayDef = 1;
2N/A $jniDefine .= <<EOF;
2N/A int i;
2N/A char **p;
2N/A jstring jString;
2N/AEOF
2N/A }
2N/A $nativeParameterList .= ",\n\t String[]\t$id";
2N/A $jniParameterList .= ",\n jstring\t$id";
2N/A $specParameterList .= ", jstring";
2N/A $needCleanupTarget = 1;
2N/A } elsif ($type eq 'ADT_TERMIDSTAR') {
2N/A $needLocaleDefined = 1;
2N/A
2N/A $jniStorageList .= <<EOF;
2N/A /* $id */
2N/A hostname$cntTermidDef = (char *)(*env)->GetStringUTFChars(env, $id, NULL);
2N/A
2N/A if (adt_load_hostname((const char *)hostname$cntTermidDef, &termid$cntTermidDef)) {
2N/A local_throw(env, except_class,
2N/A gettext("hostname lookup failed"));
2N/A }
2N/A $p_event = termid$cntTermidDef;
2N/A
2N/A (*env)->ReleaseStringUTFChars(env, $id, hostname$cntTermidDef);
2N/AEOF
2N/A
2N/A $jniFreeList .= "\n\tif (hostname$cntTermidDef != NULL)\n" .
2N/A "\t\tfree(hostname$cntTermidDef);\n";
2N/A $jniFreeList .= "\n\tif (termid$cntTermidDef != NULL)\n" .
2N/A "\t\tfree(termid$cntTermidDef);\n";
2N/A
2N/A $jniDefine .= "\tchar\t\t\t*hostname$cntTermidDef;\n";
2N/A $jniDefine .= "\tadt_termid_t\t\t*termid$cntTermidDef;\n"; #djdj
2N/A
2N/A $cntTermidDef++;
2N/A
2N/A my ($nativeParameter, $jniParameter) = @{$java_jni{$type}};
2N/A $nativeParameterList .= ",\n\t $nativeParameter\t$id";
2N/A $jniParameterList .= ",\n $jniParameter\t$id";
2N/A $specParameterList .= ", $jniParameter";
2N/A $needCleanupTarget = 1;
2N/A } else { # all others are primitive types
2N/A $jniStorageList .= "\n\t$p_event = $id;\n";
2N/A my ($nativeParameter, $jniParameter) = @{$java_jni{$type}};
2N/A $nativeParameter = "$nativeParameter\t"
2N/A if length $nativeParameter < 4; # why?
2N/A $nativeParameterList .= ",\n\t $nativeParameter\t$id";
2N/A $jniParameterList .= ",\n $jniParameter\t$id";
2N/A $specParameterList .= ", $jniParameter";
2N/A }
2N/A }
2N/A if ($needLocaleDefined) {
2N/A $jniDefine .= <<EOF
2N/A char *locale;
2N/AEOF
2N/A }
2N/A my $genericOverride = '';
2N/A my $idParameter = $eventId;
2N/A $idParameter =~ s/AUE_/ADT_/;
2N/A if ($eventType eq 'generic') {
2N/A $genericOverride = ', jint eventId';
2N/A $idParameter = 'eventId';
2N/A }
2N/A $jniFreeList = "\tcleanup:\n" . $jniFreeList if $needCleanupTarget;
2N/A
2N/A print Cfile qq{/* ARGSUSED */
2N/AJNIEXPORT void JNICALL
2N/A$jniPutEvent(
2N/A JNIEnv *env,
2N/A jobject self,
2N/A jbyteArray jsession$genericOverride,
2N/A jint status,
2N/A jint ret_val$jniParameterList)
2N/A{
2N/A $jniDefine
2N/A (void) j2c_pointer(env, jsession, (char **)&session);
2N/A
2N/A event = $jniADTalloc(session, $idParameter);
2N/A
2N/A$jniStorageList
2N/A (void) adt_put_event((adt_event_data_t *)event, status, ret_val);
2N/A
2N/A$jniFreeList
2N/A adt_free_event((adt_event_data_t *)event);
2N/A}
2N/A};
2N/A print MapFile qq{
2N/A $jniPutEvent; };
2N/A my $overrideParameter = '';
2N/A if ($eventType eq 'generic') {
2N/A $overrideParameter = 'int eventId,';
2N/A my @allowed = @$allowedIds;
2N/A if (@allowed) {
2N/A my $i;
2N/A if ($validSfile) {
2N/A print Sfile "\t// Allowed values for eventId in putEvent:\n";
2N/A for ($i = 0; $i <= $#allowed; $i++) {
2N/A my $idNo = $externalIdNo{$allowed[$i]};
2N/A $allowed[$i] =~ s/AUE_/ADT_/;
2N/A print Sfile "\tstatic final int $allowed[$i] = ",
2N/A "$idNo;\n";
2N/A }
2N/A print Sfile "\n";
2N/A }
2N/A } else {
2N/A print STDERR "Generic event with no allowed instances: $eventId\n";
2N/A }
2N/A }
2N/A if ($validSfile) {
2N/A print Sfile <<EOF;
2N/A private native void $javaPutEvent(byte[]session, $overrideParameter
2N/A int status, int ret_val$nativeParameterList);
2N/A
2N/A public AuditEvent_$root(AuditSession session)
2N/A throws Exception
2N/A {
2N/A super(session);
2N/A }
2N/A
2N/AEOF
2N/A my $javaParameterList = '';
2N/A foreach $ref2 (@entries) {
2N/A my ($id, $type, $format, $jComment, $required) = @$ref2;
2N/A
2N/A # generate java native method prototypes
2N/A # and the corresponding C method implementation
2N/A
2N/A my $javaMethodName = "$id";
2N/A my $javaStorageName = $javaMethodName . '_val';
2N/A my $jniMethodName = $root . $id;
2N/A my $storage;
2N/A my $enumUsage = '';
2N/A my $jParam = @{$java_jni{$type}}[0];
2N/A my $comment = '';
2N/A if ($required) {
2N/A if ($format ne 'NULL') {
2N/A $comment = "\t// (required) formatted: $format";
2N/A } else {
2N/A $comment = "\t// required";
2N/A }
2N/A } else {
2N/A if ($format ne 'NULL') {
2N/A $comment = "\t// (optional) formatted: $format";
2N/A } else {
2N/A $comment = "\t// optional";
2N/A }
2N/A }
2N/A if (($type eq 'ADT_UINT32STAR') ||
2N/A ($type eq 'ADT_UIDSTAR') ||
2N/A ($type eq 'ADT_GIDSTAR')) { # int array
2N/A $storage = "int[] $javaStorageName" . ($required ?
2N/A ' = {}' : '');
2N/A $javaParameterList .= ",\n\t\t\t $javaStorageName";
2N/A } elsif ($type eq 'ADT_UINT64STAR') { # long array
2N/A $storage = "long[] $javaStorageName" . ($required ?
2N/A ' = {}' : '');
2N/A $javaParameterList .= ",\n\t\t\t $javaStorageName";
2N/A } elsif (($type eq 'ADT_CHARSTAR') ||
2N/A ($type eq 'ADT_CHAR')) { # string
2N/A $storage = "String $javaStorageName" . ($required ?
2N/A ' = ""' : '');
2N/A $javaParameterList .= ",\n\t\t\t $javaStorageName";
2N/A } elsif ($type eq 'ADT_CHAR2STAR') { # array of string
2N/A $storage = "String[] $javaStorageName" . ($required ?
2N/A ' = {}' : '');
2N/A $javaParameterList .= ",\n\t\t\t $javaStorageName";
2N/A } elsif ($type eq 'ADT_TERMIDSTAR') { # array of string
2N/A $storage = "String $javaStorageName" . ($required ?
2N/A ' = ""' : '');
2N/A $javaParameterList .= ",\n\t\t\t $javaStorageName";
2N/A } else { # all others are primitive types
2N/A $storage = "$jParam $javaStorageName = 0";
2N/A $javaParameterList .= ",\n\t\t\t $javaStorageName";
2N/A $enumUsage = "\n\t// See $jComment in AuditEvent.java for valid values"
2N/A if $jComment;
2N/A }
2N/A print Sfile <<EOF;
2N/A$enumUsage
2N/A private $storage;$comment
2N/A public void $javaMethodName($jParam setTo)
2N/A {
2N/A $javaStorageName = setTo;
2N/A }
2N/AEOF
2N/A } # end foreach (@entries)
2N/A if ($eventType eq 'generic') {
2N/A print Sfile <<EOF;
2N/A
2N/A public void putEvent(int status, int ret_val, int eventId)
2N/A {
2N/A byte[] session = super.sh.getSession();
2N/A
2N/A if ((super.sh.AuditIsOn) && (super.sh.ValidSession))
2N/A $javaPutEvent(session, eventId,
2N/A status, ret_val$javaParameterList);
2N/A }
2N/A}
2N/AEOF
2N/A } else {
2N/A print Sfile <<EOF;
2N/A
2N/A public void putEvent(int status, int ret_val)
2N/A {
2N/A byte[] session = super.sh.getSession();
2N/A
2N/A if ((super.sh.AuditIsOn) && (super.sh.ValidSession))
2N/A $javaPutEvent(session, status, ret_val$javaParameterList);
2N/A }
2N/A}
2N/AEOF
2N/A }
2N/A close Sfile;
2N/A } # end if ($validSfile);
2N/A }
2N/A
2N/A # write trailers
2N/A print Jfile <<EOF;
2N/A
2N/A}
2N/AEOF
2N/A print MapFile <<EOF;
2N/A
2N/A local:
2N/A *;
2N/A};
2N/AEOF
2N/A close Cfile;
2N/A close Jfile;
2N/A close MapFile;
2N/A}
2N/A
2N/Asub generateTableC {
2N/A my $event = shift;
2N/A my $eventId = shift;
2N/A my $eventType = shift;
2N/A my $eventHeader = shift;
2N/A my $omit = shift;
2N/A
2N/A my %tokenType = (
2N/A 'acl' => 'AUT_ACL',
2N/A 'arbitrary' => 'AUT_ARBITRARY',
2N/A 'arg' => 'AUT_ARG',
2N/A 'attr' => 'AUT_ATTR',
2N/A 'command' => 'AUT_CMD',
2N/A 'command_1' => 'ADT_CMD_ALT', # dummy token id
2N/A 'date' => 'AUT_TEXT',
2N/A 'exec_args' => 'AUT_EXEC_ARGS',
2N/A 'exec_env' => 'AUT_EXEC_ENV',
2N/A 'exit' => 'AUT_EXIT',
2N/A 'file' => 'AUT_FILE',
2N/A 'fmri' => 'AUT_FMRI',
2N/A 'groups' => 'AUT_GROUPS',
2N/A # 'header' => 'AUT_HEADER', # not used
2N/A 'in_addr' => 'AUT_IN_ADDR',
2N/A 'ipc' => 'AUT_IPC',
2N/A 'ipc_perm' => 'AUT_IPC_PERM',
2N/A 'iport' => 'AUT_IPORT',
2N/A 'label' => 'AUT_LABEL',
2N/A 'newgroups' => 'AUT_NEWGROUPS',
2N/A 'opaque' => 'AUT_OPAQUE',
2N/A 'path' => 'AUT_PATH',
2N/A 'path_list' => '-AUT_PATH', # dummy token id
2N/A 'process' => 'AUT_PROCESS',
2N/A 'priv_effective' => 'ADT_AUT_PRIV_E', # dummy token id
2N/A 'priv_limit' => 'ADT_AUT_PRIV_L', # dummy token id
2N/A 'priv_inherit' => 'ADT_AUT_PRIV_I', # dummy token id
2N/A 'return' => 'AUT_RETURN',
2N/A 'seq' => 'AUT_SEQ',
2N/A 'socket' => 'AUT_SOCKET',
2N/A 'socket-inet' => 'AUT_SOCKET_INET',
2N/A 'subject' => 'AUT_SUBJECT',
2N/A 'text' => 'AUT_TEXT',
2N/A 'tid' => 'AUT_TID',
2N/A # 'trailer' => 'AUT_TRAILER', # not used
2N/A 'uauth' => 'AUT_UAUTH',
2N/A 'user' => 'AUT_USER',
2N/A 'zonename' => 'AUT_ZONENAME'
2N/A );
2N/A
2N/A my @xlateEntryList = ();
2N/A my @jniEntryList = ();
2N/A
2N/A my $external = $event->getExternal();
2N/A my $internal = $event->getInternal();
2N/A
2N/A unless ($external) {
2N/A print STDERR "No external object captured for event $eventId\n";
2N/A return;
2N/A }
2N/A unless ($internal) {
2N/A print STDERR "No internal object captured for event $eventId\n";
2N/A return;
2N/A }
2N/A my @entryRef = $internal->getEntries();
2N/A my $entryRef;
2N/A my @tokenOrder = ();
2N/A my $firstTokenIndex = 0; # djdj not used yet, djdj BUG!
2N/A # needs to be used by translate table
2N/A
2N/A if ($internal->isReorder()) { # prescan the entry list to get the token order
2N/A my @inputOrder;
2N/A foreach $entryRef (@entryRef) {
2N/A my ($intEntry, $entry) = @$entryRef;
2N/A push (@inputOrder, $intEntry->getAttr('order'));
2N/A }
2N/A
2N/A my $i; # walk down the inputOrder list once
2N/A my $k = 1; # discover next in line
2N/A my $l = 0; # who should point to next in line
2N/A for ($i = 0; $i <= $#inputOrder; $i++) {
2N/A my $j;
2N/A for ($j = 0; $j <= $#inputOrder; $j++) {
2N/A if ($k == $inputOrder[$j]) {
2N/A if ($k == 1) {
2N/A $firstTokenIndex = $j;
2N/A } else {
2N/A $tokenOrder[$l] = "&(selfReference[$j])";
2N/A }
2N/A $l = $j;
2N/A last;
2N/A }
2N/A }
2N/A $k++;
2N/A }
2N/A $tokenOrder[$l] = 'NULL';
2N/A }
2N/A else { # default order -- input order same as output
2N/A my $i;
2N/A my $j;
2N/A for ($i = 0; $i < $#entryRef; $i++) {
2N/A my $j = $i + 1;
2N/A $tokenOrder[$i] = "&(selfReference[$j])";
2N/A }
2N/A $tokenOrder[$#entryRef] = 'NULL';
2N/A }
2N/A
2N/A my $sequence = 0;
2N/A foreach $entryRef (@entryRef) {
2N/A my ($intEntry, $entry) = @$entryRef;
2N/A my $entryId = $entry->getAttr('id');
2N/A
2N/A my ($extEntry, $unusedEntry, $tokenId) =
2N/A $external->getEntry($entryId);
2N/A my $opt = $extEntry->getAttr('opt');
2N/A
2N/A if ($opt eq 'none') {
2N/A if (defined ($doc->getToken($tokenId))) {
2N/A if (defined ($tokenType{$tokenId})) {
2N/A $tokenId = $tokenType{$tokenId};
2N/A }
2N/A else {
2N/A print STDERR "token id $tokenId not implemented\n";
2N/A }
2N/A }
2N/A else {
2N/A print STDERR "token = $tokenId is undefined\n";
2N/A $tokenId = 'error';
2N/A }
2N/A my ($xlate, $jni) =
2N/A formatTableEntry ('', $tokenId, $eventId, '', 0, 0, $tokenOrder[$sequence],
2N/A 'NULL', '');
2N/A push (@xlateEntryList, $xlate);
2N/A push (@jniEntryList, @$jni);
2N/A }
2N/A else {
2N/A my $dataType = $extEntry->getAttr('type');
2N/A $dataType =~ s/\s+//g; # remove blanks (char * => char*)
2N/A
2N/A my $enumGroup = '';
2N/A if ($dataType =~ /^msg/i) {
2N/A $enumGroup = $dataType;
2N/A $enumGroup =~ s/^msg\s*//i;
2N/A $enumGroup = 'adt_' . $enumGroup;
2N/A }
2N/A my $required = ($opt eq 'required') ? 1 : 0;
2N/A my $tsol = 0;
2N/A my $tokenId = $intEntry->getAttr('token');
2N/A my $token;
2N/A my $tokenName;
2N/A my $tokenFormat = $intEntry->getAttr('format');
2N/A if (defined ($tokenFormat)) {
2N/A $tokenFormat = "\"$tokenFormat\"";
2N/A }
2N/A else {
2N/A $tokenFormat = 'NULL';
2N/A }
2N/A
2N/A if (defined ($token = $doc->getToken($tokenId))) {
2N/A $tsol = (lc $token->getUsage() eq 'tsol') ? 1 : 0;
2N/A if (defined ($tokenType{$tokenId})) {
2N/A $tokenName = $tokenType{$tokenId};
2N/A }
2N/A else {
2N/A print STDERR "token id $tokenId not implemented\n";
2N/A }
2N/A }
2N/A else {
2N/A print STDERR
2N/A "$tokenId is an unimplemented token ($entryId in $eventId)\n";
2N/A $tokenName = 'AUT_TEXT';
2N/A }
2N/A my ($xlate, $jni) =
2N/A formatTableEntry($entryId, $tokenName, $eventId, $dataType, $required,
2N/A $tsol, $tokenOrder[$sequence], $tokenFormat,
2N/A $enumGroup, (uc $omit eq 'JNI'));
2N/A push (@xlateEntryList, $xlate);
2N/A push (@jniEntryList, @$jni);
2N/A }
2N/A $sequence++;
2N/A }
2N/A $jniEventTable{$eventId} = [\@jniEntryList, $eventType,
2N/A $external->getAllowedTypes(), $eventHeader]
2N/A unless (uc $omit eq 'JNI') || ($omit eq 'always');
2N/A}
2N/A
2N/Asub formatTableEntry {
2N/A my ($id, $token, $eventId, $type, $required, $tsol, $sequence, $format, $enumGroup,
2N/A $omitJNI) = @_;
2N/A
2N/A
2N/A # does this map belong in the xml source? (at least the defaults?)
2N/A # fill in the default value only if it is other than zero.
2N/A # base type adt name, default value
2N/A my %entryDef = ( 'au_asid_t' => ['ADT_UINT32', ''],
2N/A 'uint_t' => ['ADT_UINT32', ''],
2N/A 'int' => ['ADT_INT', ''],
2N/A 'int32_t' => ['ADT_INT32', ''],
2N/A 'uid_t' => ['ADT_UID', 'AU_NOAUDITID'],
2N/A 'gid_t' => ['ADT_GID', 'AU_NOAUDITID'],
2N/A 'uid_t*' => ['ADT_UIDSTAR', ''],
2N/A 'gid_t*' => ['ADT_GIDSTAR', ''],
2N/A 'char' => ['ADT_CHAR', ''],
2N/A 'char*' => ['ADT_CHARSTAR', ''],
2N/A 'char**' => ['ADT_CHAR2STAR', ''],
2N/A 'long' => ['ADT_LONG', ''],
2N/A 'pid_t' => ['ADT_PID', ''],
2N/A 'priv_set_t*' => ['ADT_PRIVSTAR', ''],
2N/A 'ulong_t' => ['ADT_ULONG', ''],
2N/A 'uint16_t', => ['ADT_UINT16', ''],
2N/A 'uint32_t' => ['ADT_UINT32', ''],
2N/A 'uint32_t*' => ['ADT_UINT32STAR', ''],
2N/A 'uint32_t[]' => ['ADT_UINT32ARRAY', ''],
2N/A 'uint64_t' => ['ADT_UINT64', ''],
2N/A 'uint64_t*' => ['ADT_UINT64STAR', ''],
2N/A 'm_label_t*' => ['ADT_MLABELSTAR', ''],
2N/A );
2N/A my $xlateLabel = $uniLabel.$xlateUniLabelInc;
2N/A my $xlateLabelInc = 0;
2N/A my $xlateLine = '';
2N/A my @jniLine = ();
2N/A
2N/A # the list handling should be a simple loop with a loop of one
2N/A # falling out naturally.
2N/A
2N/A unless ($type =~ /,/) { # if list, then generate sequence of entries
2N/A my $dataType;
2N/A my $dataSize;
2N/A my $xlateLabelRef = '';
2N/A
2N/A my $arraySize = '';
2N/A $arraySize = $1 if ($type =~ s/\[(\d+)\]/[]/);
2N/A
2N/A my $entryType = ${$entryDef{$type}}[0];
2N/A
2N/A my @xlateType = (); # for adt_xlate.c
2N/A my $typeCount = 1;
2N/A
2N/A if ($entryType) {
2N/A $dataType = $entryType;
2N/A $type =~ s/([^*]+)\s*(\*+)/$1 $2/;
2N/A $type =~ s/\[\]//;
2N/A $dataSize = "sizeof ($type)";
2N/A if ($arraySize) {
2N/A $dataSize = "$arraySize * " . $dataSize;
2N/A }
2N/A $xlateLine = "{{$dataType, $dataSize}}";
2N/A push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
2N/A } elsif ($type eq '') {
2N/A $xlateLabelRef = 'NULL';
2N/A } elsif ($type =~ /^msg/i) {
2N/A $type =~ s/^msg//i;
2N/A $dataType = 'ADT_MSG';
2N/A my $dataEnum = 'ADT_LIST_' . uc $type;
2N/A $xlateLine = "{{$dataType, $dataEnum}}";
2N/A push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
2N/A } elsif ($type =~ /time_t/i) {
2N/A $dataType = 'ADT_DATE';
2N/A $dataSize = "sizeof (time_t)";
2N/A $xlateLine = "{{$dataType, $dataSize}}";
2N/A push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
2N/A } elsif ($type =~ /termid/i) {
2N/A $dataType = 'ADT_TERMIDSTAR';
2N/A $dataSize = "sizeof (au_tid_addr_t *)";
2N/A $xlateLine = "{{$dataType, $dataSize}}";
2N/A push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
2N/A } elsif ($omitJNI) {
2N/A $xlateLabelRef = 'NULL';
2N/A } else {
2N/A print STDERR "$type is not an implemented data type\n";
2N/A $xlateLabelRef = 'NULL';
2N/A }
2N/A $xlateLabelRef = '&' . $xlateLabel . '[0]'
2N/A unless $xlateLabelRef eq 'NULL';
2N/A
2N/A # "EOL" is where a comma should go unless end of list
2N/A $xlateLine = "{$token,\t1,\t$xlateLabelRef,\t$sequence,\n" .
2N/A "\t\t0,\t$required,\t$tsol,\t$format}EOL";
2N/A
2N/A } else { # is a list
2N/A my @type = split(/,/, $type);
2N/A my @arraySize = ();
2N/A my @id = split(/,/, $id);
2N/A my @jniId = @id;
2N/A my $dataType;
2N/A my $typeCount = ($#type + 1);
2N/A my @xlateType = ();
2N/A my @default = ();
2N/A
2N/A foreach my $dtype (@type) {
2N/A my $jniId = shift @jniId;
2N/A my $id = shift @id;
2N/A my $arraySize = '';
2N/A $arraySize = $1 if ($dtype =~ s/\[(\d+)\]/[]/);
2N/A
2N/A my $entryType = ${$entryDef{$dtype}}[0];
2N/A if ($entryType) {
2N/A my $type = $dtype;
2N/A $type =~ s/([^*]+)\s*(\*+)/$1 $2/;
2N/A $type =~ s/\[\]//;
2N/A
2N/A my $sizeString = "sizeof";
2N/A $sizeString = "$arraySize * " . $sizeString if $arraySize;
2N/A push (@xlateType, "\{$entryType, $sizeString ($type)\}");
2N/A push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]);
2N/A } elsif ($type =~ /^msg/i) {
2N/A $type =~ s/^msg//i;
2N/A $dataType = 'ADT_MSG';
2N/A my $dataEnum = 'ADT_LIST_' . uc $type;
2N/A push (@xlateType, "\{$dataType, $dataEnum\}};");
2N/A push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]);
2N/A } elsif ($type =~ /time_t/i) {
2N/A $dataType = 'ADT_DATE';
2N/A push (@xlateType, "\{$entryType, sizeof ($type)\}");
2N/A push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]);
2N/A } elsif ($type =~ /termid/i) {
2N/A $dataType = 'ADT_TERMIDSTAR';
2N/A push (@xlateType, "\{$dataType, sizeof (au_tid_addr_t *)\}");
2N/A push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]);
2N/A } elsif ($omitJNI) {
2N/A # nothing to do.
2N/A } else {
2N/A print STDERR "$dtype is not an implemented data type\n";
2N/A }
2N/A if (${$entryDef{$dtype}}[1]) {
2N/A push (@default, $id, ${$entryDef{$dtype}}[1]);
2N/A }
2N/A }
2N/A my $xlateArray = "\[$typeCount\] =\t{" . join(",\n\t\t\t\t", @xlateType) . "};";
2N/A
2N/A $xlateLine =
2N/A "{$token,\t$typeCount,\t&$xlateLabel\[0\],\t$sequence,\n" .
2N/A "\t\t0,\t$required,\t$tsol,\t$format}EOL";
2N/A }
2N/A $xlateUniLabelInc++ if $xlateLabelInc;
2N/A return ($xlateLine, \@jniLine);
2N/A}
2N/A
2N/Asub generateMsgLists {
2N/A my $textList = shift;
2N/A
2N/A my $textName = $textList->getId();
2N/A my $header = $textList->getHeader();
2N/A my $start = $textList->getMsgStart();
2N/A my $public = $textList->getMsgPublic();
2N/A my $deprecated = $textList->getDeprecated();
2N/A
2N/A print "$textName starts at $start\n" if $debug;
2N/A
2N/A my $entry;
2N/A my @entry;
2N/A while ($entry = $textList->getNextMsg()) {
2N/A if ($debug) {
2N/A my ($id, $text) = split(/\s*::\s*/, $entry);
2N/A print " $id = $text\n";
2N/A }
2N/A unshift (@entry, $entry);
2N/A }
2N/A $msg_list{$textName} =
2N/A [\@entry, [$header, $start, $public, $deprecated]];
2N/A}
2N/Asub readAuditEventFile {
2N/A my $eventListFile = shift;
2N/A
2N/A open(Event, $eventListFile)
2N/A or die "can't open $eventListFile: $!\n";
2N/A while(<Event>) {
2N/A next if /^\s*#/;
2N/A next if /^\s*$/;
2N/A my ($value, $name) = split(/\s*:\s*/);
2N/A next if $value < 6000;
2N/A $eventCode{$name} = $value;
2N/A }
2N/A close Event;
2N/A}