#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#
# auditxml_jni [-d] <xml input file>
# auditxml takes the audit record description (.xml file) and
# generates the files needed for the Java
use auditxml;
use strict;
# <debug set="on"/> or <debug set="off"/> or <debug/>
# if the set attribute is omitted, debug state is toggled
# Override with appDebug, but toggle won't do what you
# want.
my $genNotice = "
DO NOT EDIT. This file is auto generated by the Solaris Audit
system from adt.xml.
";
$genNotice =~ s/^\n//s;
$genNotice =~ s/\n$//s;
getopts('d');
my $uniLabel = "adr";
my $xlateUniLabelInc = 0;
# where everything comes from and where it goes:
my $templatePath = './';
my $javaPath = $templatePath;
my $bsmBuildPath = "../libbsm";
my $jniBuildPath = "$javaPath";
my $buildPathJ = "$jniBuildPath/com/sun/audit";
my $buildPathJNI = "$jniBuildPath/common";
my $auditEventJ = "$buildPathJ/AuditEvent.java";
my $jniC = "$buildPathJNI/adt_jni_event.c";
my $mapFile = "$jniBuildPath/common/mapfile-vers";
my %jniEventTable = ();
my %externalIdNo = ();
my %msg_list = ();
my %eventCode = ();
my $event;
my $super;
} else {
}
# c file table for translation
}
}
exit 0;
sub printJavaFiles {
my $jniFile = shift;
my $javaFile = shift;
my $subclassPath = shift;
my $mapFile = shift;
# warning: time_t is equated to jlong since there is no
# java long is C long long, 64 bits.
# java int is 32 bits.
'ADT_UINT' => ['int', 'jint'],
'ADT_INT' => ['int', 'jint'],
'ADT_INT32' => ['int', 'jint'],
'ADT_UID' => ['int', 'jint'],
'ADT_GID' => ['int', 'jint'],
'ADT_UIDSTAR' => ['int[]', 'jintArray'],
'ADT_GIDSTAR' => ['int[]', 'jintArray'],
'ADT_CHAR' => ['String', 'jchar'],
'ADT_CHARSTAR' => ['String', 'jstring'],
'ADT_CHAR2STAR' => ['String[]', 'jstring'],
'ADT_MSG' => ['int', 'jint'],
'ADT_PID' => ['int', 'jint'],
# ADT_PRIVSTAR omitted -- not implemented and the audit records that
# use it must be coded to emit no java. We'll cross that bridge
# when someone in Java land needs to generate a priv token.
'ADT_LONG' => ['int', 'jint'],
'ADT_TERMIDSTAR' => ['String', 'jstring'], # hostname -> termid
'ADT_ULONG' => ['int', 'jint'],
'ADT_UINT16' => ['int', 'jint'],
'ADT_UINT32' => ['int', 'jint'],
'ADT_UINT32STAR' => ['int[]', 'jintArray'],
# ADT_UINT32ARRAY omitted; no Java implementation yet
'ADT_UINT64' => ['long', 'jlong'],
'ADT_UINT64STAR' => ['long[]', 'jlongArray']
);
# open output files
# write headers
my $notice = $genNotice;
print Cfile <<EOF;
/*
* $notice
*/
#include "../../libbsm/common/adt_xlate.h"
#include <jni.h>
#include "../com/sun/audit/AuditSession.h" /* javah output */
#include "adt_jni.h"
#include <stdlib.h>
#include <string.h>
static char *except_class = "java/lang/Exception";
EOF
print Jfile <<EOF;
/*
* $notice
*/
package com.sun.audit;
public class AuditEvent {
protected AuditSession sh; // associated session object
public AuditEvent(AuditSession auSession)
throws Error
{
sh = auSession;
}
// Manifest values: keep them in sync with generated <bsm/adt_event.h>.
// It is generated by \$SRC/lib/libbsm/auditxml
public static final int ADT_SUCCESS = 0; // generated
public static final int ADT_FAILURE = -1; // generated
// See the subclasses of AuditEvent for mapping message codes
// to events
EOF
my $notice_map = $genNotice;
$notice_map =~ s/\n/\n# /gs;
$notice_map =~ s/\s+\n/\n/gs;
print MapFile <<EOF;
#
# $notice_map
#
\$mapfile_version 2
STUB_OBJECT;
SYMBOL_VERSION SUNWprivate_1.1 {
global:
c2j_pointer;
j2c_pointer;
Java_com_sun_audit_AuditSession_bsmAuditOn;
Java_com_sun_audit_AuditSession_startSession;
Java_com_sun_audit_AuditSession_endSession;
Java_com_sun_audit_AuditSession_dupSession;
Java_com_sun_audit_AuditSession_getSessionId;
Java_com_sun_audit_AuditSession_exportSessionData;
Java_com_sun_audit_AuditSession_sessionAttr;
# One subclass of AuditEvent per audit record...
EOF
my $shortName = uc $listName;
$shortName =~ s/_TEXT//;
my $listValue;
$enumValue++;
}
}
# generate event creation and access functions and event
# generation for both Java and JNI
$putMethod =~ s/_/_1/g;
# the subclass file template isn't used; it may be needed to get
# the right file header stuff in place. The subclassPath is
# the directory that contains 'em.
my $validSfile = 1;
$validSfile = 0;
}
print Sfile <<EOF;
/*
* $notice
*/
package com.sun.audit;
// audit event: $eventId = $eventCode{"AUE_$root"}
public class AuditEvent_$root extends AuditEvent {
EOF
}
} else {
}
my $needCleanupTarget = 0;
my $haveStringDef = 0;
my $haveCDef = 0;
my $haveLengthDef = 0;
my $haveStringArrayDef = 0;
my $cntTermidDef = 0;
my $jniDefine;
my $needLocaleDefined = 0;
my $jniADTalloc;
"\tadt_session_data_t *session;\n";
} else {
"\tadt_session_data_t *session;\n";
}
my $ref2;
my $p_event;
} else {
}
$needLocaleDefined = 1;
$jniStorageList .= <<EOF;
/* $id */
length = (*env)->GetArrayLength(env, $id);
$p_event =
(int *)malloc(length * sizeof (int));
if ($p_event == NULL) {
locale = I18N_SETUP;
local_throw(env, except_class,
$noMemory);
(void) setlocale(LC_MESSAGES, locale);
goto cleanup;
}
(*env)->GetIntArrayRegion(env, $id, 0, length,
(int *)$p_event);
EOF
$haveLengthDef = 1;
}
$needCleanupTarget = 1;
$needLocaleDefined = 1;
$jniStorageList .= <<EOF;
/* $id */
length = (*env)->GetArrayLength(env, $id);
$p_event =
($cType *)malloc(length * sizeof ($cType));
if ($p_event == NULL) {
locale = I18N_SETUP;
local_throw(env, except_class,
$noMemory);
(void) setlocale(LC_MESSAGES, locale);
goto cleanup;
}
(*env)->GetIntArrayRegion(env, $id, 0, length,
(int *)$p_event);
EOF
$jniFreeList .=
$haveLengthDef = 1;
}
$needCleanupTarget = 1;
$needLocaleDefined = 1;
$jniStorageList .= <<EOF;
/* $id */
length = (*env)->GetArrayLength(env, $id);
$p_event =
(long *)malloc(length * sizeof (long long));
if ($p_event == NULL) {
locale = I18N_SETUP;
local_throw(env, except_class,
$noMemory);
(void) setlocale(LC_MESSAGES, locale);
goto cleanup;
}
(*env)->GetLongArrayRegion(env, $id, 0, length,
$p_event);
EOF
$haveLengthDef = 1;
}
$needCleanupTarget = 1;
$jniStorageList .= <<EOF;
/* $id */
c = (char *)(*env)->GetStringUTFChars(env, $id, NULL);
if (c == NULL)
goto cleanup; /* exception thrown */
$p_event = *c;
(*env)->ReleaseStringUTFChars(env, $id, c);
EOF
# no need to free anything
$haveCDef = 1;
}
$needLocaleDefined = 1;
$jniStorageList .= <<EOF;
/* $id */
if ($id != NULL) {
string = (char *)(*env)->GetStringUTFChars(
env, $id, NULL);
if (string == NULL)
goto cleanup; /* exception thrown */
$p_event = strdup(string);
(*env)->ReleaseStringUTFChars(env, $id, string);
if ($p_event == NULL) {
locale = I18N_SETUP;
local_throw(env, except_class,
$noMemory);
(void) setlocale(LC_MESSAGES, locale);
goto cleanup;
}
}
EOF
$haveStringDef = 1;
}
$needCleanupTarget = 1;
$needLocaleDefined = 1;
$jniStorageList .= <<EOF;
/* $id */
length = (*env)->GetArrayLength(env, $id);
$p_event = (char **)malloc(length
* sizeof (char *));
if ($p_event == NULL) {
locale = I18N_SETUP;
local_throw(env, except_class,
$noMemory);
(void) setlocale(LC_MESSAGES, locale);
goto cleanup;
}
p = $p_event;
for (i = 0; i < length; i++) {
jString = (*env)->GetObjectArrayElement(env, $id, i);
string = (char *)(*env)->GetStringUTFChars(
env, jString, NULL);
if (string == NULL)
goto cleanup; /* exception thrown */
*p = strdup(string);
(*env)->ReleaseStringUTFChars(env, jString, string);
if (*p == NULL) {
locale = I18N_SETUP;
local_throw(env, except_class,
$noMemory);
(void) setlocale(LC_MESSAGES, locale);
while (p >= $p_event)
free(*p--);
goto cleanup;
}
p++;
}
EOF
$jniFreeList .=
$haveStringDef = 1;
$jniDefine .= <<EOF;
char *string;
EOF
}
$haveLengthDef = 1;
$jniDefine .= <<EOF;
int length;
EOF
}
$haveStringArrayDef = 1;
$jniDefine .= <<EOF;
int i;
char **p;
jstring jString;
EOF
}
$needCleanupTarget = 1;
$needLocaleDefined = 1;
$jniStorageList .= <<EOF;
/* $id */
hostname$cntTermidDef = (char *)(*env)->GetStringUTFChars(env, $id, NULL);
if (adt_load_hostname((const char *)hostname$cntTermidDef, &termid$cntTermidDef)) {
local_throw(env, except_class,
gettext("hostname lookup failed"));
}
$p_event = termid$cntTermidDef;
(*env)->ReleaseStringUTFChars(env, $id, hostname$cntTermidDef);
EOF
$needCleanupTarget = 1;
} else { # all others are primitive types
if length $nativeParameter < 4; # why?
}
}
$jniDefine .= <<EOF
char *locale;
EOF
}
my $idParameter = $eventId;
$idParameter =~ s/AUE_/ADT_/;
}
{
}
};
$jniPutEvent; };
my @allowed = @$allowedIds;
my $i;
my $idNo = $externalIdNo{$allowed[$i]};
}
}
} else {
}
}
print Sfile <<EOF;
private native void $javaPutEvent(byte[]session, $overrideParameter
int status, int ret_val$nativeParameterList);
public AuditEvent_$root(AuditSession session)
throws Exception
{
super(session);
}
EOF
# generate java native method prototypes
# and the corresponding C method implementation
my $jniMethodName = $root . $id;
my $storage;
} else {
}
} else {
} else {
}
}
' = {}' : '');
' = {}' : '');
' = ""' : '');
' = {}' : '');
' = ""' : '');
} else { # all others are primitive types
$enumUsage = "\n\t// See $jComment in AuditEvent.java for valid values"
if $jComment;
}
print Sfile <<EOF;
$enumUsage
private $storage;$comment
public void $javaMethodName($jParam setTo)
{
$javaStorageName = setTo;
}
EOF
} # end foreach (@entries)
print Sfile <<EOF;
public void putEvent(int status, int ret_val, int eventId)
{
byte[] session = super.sh.getSession();
if ((super.sh.AuditIsOn) && (super.sh.ValidSession))
$javaPutEvent(session, eventId,
status, ret_val$javaParameterList);
}
}
EOF
} else {
print Sfile <<EOF;
public void putEvent(int status, int ret_val)
{
byte[] session = super.sh.getSession();
if ((super.sh.AuditIsOn) && (super.sh.ValidSession))
$javaPutEvent(session, status, ret_val$javaParameterList);
}
}
EOF
}
} # end if ($validSfile);
}
# write trailers
print Jfile <<EOF;
}
EOF
print MapFile <<EOF;
local:
*;
};
EOF
}
sub generateTableC {
my $event = shift;
my $eventId = shift;
my $eventType = shift;
my $eventHeader = shift;
my $omit = shift;
my %tokenType = (
'acl' => 'AUT_ACL',
'arbitrary' => 'AUT_ARBITRARY',
'arg' => 'AUT_ARG',
'attr' => 'AUT_ATTR',
'command' => 'AUT_CMD',
'command_1' => 'ADT_CMD_ALT', # dummy token id
'date' => 'AUT_TEXT',
'exec_args' => 'AUT_EXEC_ARGS',
'exec_env' => 'AUT_EXEC_ENV',
'exit' => 'AUT_EXIT',
'file' => 'AUT_FILE',
'fmri' => 'AUT_FMRI',
'groups' => 'AUT_GROUPS',
# 'header' => 'AUT_HEADER', # not used
'in_addr' => 'AUT_IN_ADDR',
'ipc' => 'AUT_IPC',
'ipc_perm' => 'AUT_IPC_PERM',
'iport' => 'AUT_IPORT',
'label' => 'AUT_LABEL',
'newgroups' => 'AUT_NEWGROUPS',
'opaque' => 'AUT_OPAQUE',
'path' => 'AUT_PATH',
'path_list' => '-AUT_PATH', # dummy token id
'process' => 'AUT_PROCESS',
'priv_effective' => 'ADT_AUT_PRIV_E', # dummy token id
'priv_limit' => 'ADT_AUT_PRIV_L', # dummy token id
'priv_inherit' => 'ADT_AUT_PRIV_I', # dummy token id
'return' => 'AUT_RETURN',
'seq' => 'AUT_SEQ',
'socket' => 'AUT_SOCKET',
'socket-inet' => 'AUT_SOCKET_INET',
'subject' => 'AUT_SUBJECT',
'text' => 'AUT_TEXT',
'tid' => 'AUT_TID',
# 'trailer' => 'AUT_TRAILER', # not used
'uauth' => 'AUT_UAUTH',
'user' => 'AUT_USER',
'zonename' => 'AUT_ZONENAME'
);
return;
}
return;
}
my $entryRef;
my $firstTokenIndex = 0; # djdj not used yet, djdj BUG!
# needs to be used by translate table
my @inputOrder;
}
my $i; # walk down the inputOrder list once
my $k = 1; # discover next in line
my $l = 0; # who should point to next in line
my $j;
if ($k == 1) {
$firstTokenIndex = $j;
} else {
}
$l = $j;
last;
}
}
$k++;
}
}
else { # default order -- input order same as output
my $i;
my $j;
my $j = $i + 1;
}
}
my $sequence = 0;
}
else {
}
}
else {
}
'NULL', '');
}
else {
$dataType =~ s/\s+//g; # remove blanks (char * => char*)
$enumGroup =~ s/^msg\s*//i;
}
my $tsol = 0;
my $token;
my $tokenName;
}
else {
}
}
else {
}
}
else {
print STDERR
}
}
$sequence++;
}
$jniEventTable{$eventId} = [\@jniEntryList, $eventType,
}
sub formatTableEntry {
$omitJNI) = @_;
# does this map belong in the xml source? (at least the defaults?)
# fill in the default value only if it is other than zero.
# base type adt name, default value
'uint_t' => ['ADT_UINT32', ''],
'int' => ['ADT_INT', ''],
'int32_t' => ['ADT_INT32', ''],
'uid_t' => ['ADT_UID', 'AU_NOAUDITID'],
'gid_t' => ['ADT_GID', 'AU_NOAUDITID'],
'uid_t*' => ['ADT_UIDSTAR', ''],
'gid_t*' => ['ADT_GIDSTAR', ''],
'char' => ['ADT_CHAR', ''],
'char*' => ['ADT_CHARSTAR', ''],
'char**' => ['ADT_CHAR2STAR', ''],
'long' => ['ADT_LONG', ''],
'pid_t' => ['ADT_PID', ''],
'priv_set_t*' => ['ADT_PRIVSTAR', ''],
'ulong_t' => ['ADT_ULONG', ''],
'uint16_t', => ['ADT_UINT16', ''],
'uint32_t' => ['ADT_UINT32', ''],
'uint32_t*' => ['ADT_UINT32STAR', ''],
'uint32_t[]' => ['ADT_UINT32ARRAY', ''],
'uint64_t' => ['ADT_UINT64', ''],
'uint64_t*' => ['ADT_UINT64STAR', ''],
'm_label_t*' => ['ADT_MLABELSTAR', ''],
);
my $xlateLabelInc = 0;
# the list handling should be a simple loop with a loop of one
# falling out naturally.
my $dataType;
my $dataSize;
my $entryType = ${$entryDef{$type}}[0];
my $typeCount = 1;
$type =~ s/\[\]//;
}
} else {
}
# "EOL" is where a comma should go unless end of list
} else { # is a list
my $dataType;
my $entryType = ${$entryDef{$dtype}}[0];
$type =~ s/\[\]//;
# nothing to do.
} else {
}
}
}
}
}
sub generateMsgLists {
my $textList = shift;
my $entry;
my @entry;
}
}
[\@entry, [$header, $start, $public, $deprecated]];
}
sub readAuditEventFile {
my $eventListFile = shift;
next if /^\s*#/;
next if /^\s*$/;
next if $value < 6000;
$eventCode{$name} = $value;
}
}