10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2425Sgww * Common Development and Distribution License (the "License"). 6*2425Sgww * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 220Sstevel@tonic-gate * adt_jni.c 230Sstevel@tonic-gate * 240Sstevel@tonic-gate * JNI wrapper for adt interface within libbsm 250Sstevel@tonic-gate * 26*2425Sgww * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 270Sstevel@tonic-gate * Use is subject to license terms. 280Sstevel@tonic-gate * 290Sstevel@tonic-gate */ 300Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <bsm/adt.h> 330Sstevel@tonic-gate #include "adt_jni.h" 340Sstevel@tonic-gate #include <jni.h> 350Sstevel@tonic-gate #include "../com/sun/audit/AuditSession.h" /* javah output */ 360Sstevel@tonic-gate #include <assert.h> 370Sstevel@tonic-gate #include <stdlib.h> 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate #include <netdb.h> 400Sstevel@tonic-gate 410Sstevel@tonic-gate /* 420Sstevel@tonic-gate * local_throw -- throw an exception. 430Sstevel@tonic-gate * "why" string must be i18n'd before calling here. 440Sstevel@tonic-gate * 450Sstevel@tonic-gate */ 460Sstevel@tonic-gate 470Sstevel@tonic-gate void 480Sstevel@tonic-gate local_throw(JNIEnv *env, const char *exception, const char *why) { 490Sstevel@tonic-gate jobject jexception; 500Sstevel@tonic-gate jclass exceptionclass; 510Sstevel@tonic-gate jmethodID jexceptionnew; 520Sstevel@tonic-gate 530Sstevel@tonic-gate jbyteArray jbarray; 540Sstevel@tonic-gate 550Sstevel@tonic-gate jstring jmsg; 560Sstevel@tonic-gate jclass strclass; 570Sstevel@tonic-gate jmethodID jstrnew; 580Sstevel@tonic-gate 590Sstevel@tonic-gate /* Get a String class and "new" method */ 600Sstevel@tonic-gate strclass = (*env)->FindClass(env, "java/lang/String"); 610Sstevel@tonic-gate jstrnew = (*env)->GetMethodID(env, strclass, "<init>", "([B)V"); 620Sstevel@tonic-gate 630Sstevel@tonic-gate /* Create a Byte Array from message "why" */ 640Sstevel@tonic-gate jbarray = (*env)->NewByteArray(env, (jsize)(strlen(why))); 650Sstevel@tonic-gate (*env)->SetByteArrayRegion(env, jbarray, (jsize)0, 660Sstevel@tonic-gate (jsize)(strlen(why)), (jbyte*) why); 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* Create string from byte array */ 690Sstevel@tonic-gate jmsg = (*env)->NewObject(env, strclass, jstrnew, jbarray); 700Sstevel@tonic-gate exceptionclass = (*env)->FindClass(env, exception); 710Sstevel@tonic-gate jexceptionnew = (*env)->GetMethodID(env, exceptionclass, 720Sstevel@tonic-gate "<init>", "(Ljava/lang/String;)V"); 730Sstevel@tonic-gate 740Sstevel@tonic-gate jexception = (*env)->NewObject(env, exceptionclass, jexceptionnew, 750Sstevel@tonic-gate jmsg); 760Sstevel@tonic-gate (*env)->Throw(env, jexception); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 790Sstevel@tonic-gate /* 800Sstevel@tonic-gate * i18n the strerror return. Input is errno. 810Sstevel@tonic-gate * 820Sstevel@tonic-gate */ 830Sstevel@tonic-gate 840Sstevel@tonic-gate static char * 850Sstevel@tonic-gate errno_to_i18n(int error_code) { 860Sstevel@tonic-gate char *locale; 870Sstevel@tonic-gate char *local_text; 880Sstevel@tonic-gate 890Sstevel@tonic-gate locale = I18N_SETUP; 900Sstevel@tonic-gate local_text = strerror(error_code); 910Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, locale); 920Sstevel@tonic-gate return (local_text); 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * j2c_pointer 970Sstevel@tonic-gate * 980Sstevel@tonic-gate * convert java byte array into a C pointer 990Sstevel@tonic-gate */ 1000Sstevel@tonic-gate int 1010Sstevel@tonic-gate j2c_pointer(JNIEnv *env, jbyteArray jpointer, caddr_t *cpointer) { 1020Sstevel@tonic-gate union { 1030Sstevel@tonic-gate caddr_t ptr; 1040Sstevel@tonic-gate jbyte buf[sizeof (uint64_t)]; 1050Sstevel@tonic-gate } u; 1060Sstevel@tonic-gate size_t jpointer_length; 1070Sstevel@tonic-gate char *locale; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate (void) memset(u.buf, 0, sizeof (uint64_t)); 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate assert(jpointer != NULL); 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate jpointer_length = (*env)->GetArrayLength(env, jpointer); 1140Sstevel@tonic-gate if (jpointer_length != sizeof (uint64_t)) { 1150Sstevel@tonic-gate locale = I18N_SETUP; 1160Sstevel@tonic-gate local_throw(env, "java/lang/Error", 1170Sstevel@tonic-gate gettext("Bad session handle")); 1180Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, locale); 1190Sstevel@tonic-gate return (-1); 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate (*env)->GetByteArrayRegion(env, jpointer, 0, jpointer_length, 1220Sstevel@tonic-gate &(u.buf[0])); 1230Sstevel@tonic-gate *cpointer = (caddr_t)u.ptr; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate return (0); 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * c2j_pointer 1300Sstevel@tonic-gate * 1310Sstevel@tonic-gate * convert a C pointer into a java byte array 1320Sstevel@tonic-gate */ 1330Sstevel@tonic-gate void 1340Sstevel@tonic-gate c2j_pointer(JNIEnv *env, caddr_t cpointer, jbyteArray *jpointer) { 1350Sstevel@tonic-gate union { 1360Sstevel@tonic-gate caddr_t ptr; 1370Sstevel@tonic-gate jbyte buf[sizeof (uint64_t)]; 1380Sstevel@tonic-gate } u; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate (void) memset(u.buf, 0, sizeof (uint64_t)); 1410Sstevel@tonic-gate u.ptr = cpointer; 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate *jpointer = (*env)->NewByteArray(env, sizeof (uint64_t)); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate (*env)->SetByteArrayRegion(env, *jpointer, 0, sizeof (uint64_t), 1460Sstevel@tonic-gate &(u.buf[0])); 1470Sstevel@tonic-gate } 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * adt_start_session wrapper 1510Sstevel@tonic-gate * 1520Sstevel@tonic-gate */ 1530Sstevel@tonic-gate /*ARGSUSED*/ 1540Sstevel@tonic-gate JNIEXPORT jbyteArray JNICALL 1550Sstevel@tonic-gate Java_com_sun_audit_AuditSession_startSession(JNIEnv *env, jobject cls, 1560Sstevel@tonic-gate jbyteArray jimport, jlong flags) { 1570Sstevel@tonic-gate jbyteArray jstate; 1580Sstevel@tonic-gate adt_session_data_t *state; 1590Sstevel@tonic-gate jbyte *import; 1600Sstevel@tonic-gate size_t import_size; 1610Sstevel@tonic-gate int rc; 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate if (jimport == NULL) { 1640Sstevel@tonic-gate import = NULL; 1650Sstevel@tonic-gate } else { 1660Sstevel@tonic-gate import_size = (*env)->GetArrayLength(env, jimport); 1670Sstevel@tonic-gate import = (jbyte *)malloc(import_size * sizeof (jbyte)); 1680Sstevel@tonic-gate if (import == NULL) { 1690Sstevel@tonic-gate local_throw(env, "java/lang/Error", 1700Sstevel@tonic-gate errno_to_i18n(errno)); 1710Sstevel@tonic-gate return (NULL); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate (*env)->GetByteArrayRegion(env, jimport, 0, import_size, 1740Sstevel@tonic-gate import); 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate rc = adt_start_session(&state, (adt_export_data_t *)import, flags); 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate if (import != NULL) 1790Sstevel@tonic-gate free(import); 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate if (rc) { 1820Sstevel@tonic-gate local_throw(env, "java/lang/Error", errno_to_i18n(errno)); 1830Sstevel@tonic-gate return (NULL); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate c2j_pointer(env, (caddr_t)state, &jstate); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate return (jstate); 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate /* 1910Sstevel@tonic-gate * adt_end_session wrapper 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* ARGSUSED */ 1950Sstevel@tonic-gate JNIEXPORT void JNICALL 1960Sstevel@tonic-gate Java_com_sun_audit_AuditSession_endSession(JNIEnv *env, jobject cls, 1970Sstevel@tonic-gate jbyteArray jstate) { 1980Sstevel@tonic-gate adt_session_data_t *state; 1990Sstevel@tonic-gate char *locale; 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate if (j2c_pointer(env, jstate, (caddr_t *)&state)) 2020Sstevel@tonic-gate return; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate if (state == NULL) 2050Sstevel@tonic-gate return; /* invalid session, nothing to free */ 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate /* presently, no errors defined, but what the heck? */ 2080Sstevel@tonic-gate if (adt_end_session(state)) { 2090Sstevel@tonic-gate locale = I18N_SETUP; 2100Sstevel@tonic-gate local_throw(env, "java/lang/Error", 2110Sstevel@tonic-gate gettext("Bad session handle")); 2120Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, locale); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate /* 2170Sstevel@tonic-gate * adt_dup_session wrapper 2180Sstevel@tonic-gate */ 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* ARGSUSED */ 2210Sstevel@tonic-gate JNIEXPORT jbyteArray JNICALL 2220Sstevel@tonic-gate Java_com_sun_audit_AuditSession_dupSession(JNIEnv *env, jobject cls, 2230Sstevel@tonic-gate jbyteArray jsource) { 2240Sstevel@tonic-gate jbyteArray jdest; 2250Sstevel@tonic-gate adt_session_data_t *source, *dest; 2260Sstevel@tonic-gate char *locale; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate if (j2c_pointer(env, jsource, (caddr_t *)&source)) 2290Sstevel@tonic-gate return (NULL); 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate if (adt_dup_session(source, &dest)) { 2320Sstevel@tonic-gate locale = I18N_SETUP; 2330Sstevel@tonic-gate local_throw(env, "java/lang/Error", 2340Sstevel@tonic-gate gettext("Out of memory")); 2350Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, locale); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate c2j_pointer(env, (caddr_t)dest, &jdest); 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate return (jdest); 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate /* 2440Sstevel@tonic-gate * adt_get_session_id wrapper 2450Sstevel@tonic-gate * 2460Sstevel@tonic-gate */ 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate /* ARGSUSED */ 2490Sstevel@tonic-gate JNIEXPORT jstring JNICALL 2500Sstevel@tonic-gate Java_com_sun_audit_AuditSession_getSessionId(JNIEnv *env, jobject cls, 2510Sstevel@tonic-gate jbyteArray jstate) { 2520Sstevel@tonic-gate adt_session_data_t *state; 2530Sstevel@tonic-gate char *session_id; 2540Sstevel@tonic-gate jstring return_val; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate if (j2c_pointer(env, jstate, (caddr_t *)&state)) 2570Sstevel@tonic-gate return (NULL); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate if (adt_get_session_id(state, &session_id)) { 2600Sstevel@tonic-gate return_val = (*env)->NewStringUTF(env, session_id); 2610Sstevel@tonic-gate free(session_id); 2620Sstevel@tonic-gate return (return_val); 2630Sstevel@tonic-gate } else 2640Sstevel@tonic-gate return (NULL); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate /* 2680Sstevel@tonic-gate * adt_get_session_id wrapper 2690Sstevel@tonic-gate */ 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* ARGSUSED */ 2720Sstevel@tonic-gate JNIEXPORT jbyteArray JNICALL 2730Sstevel@tonic-gate Java_com_sun_audit_AuditSession_exportSessionData 2740Sstevel@tonic-gate (JNIEnv *env, jobject cls, jbyteArray jstate) { 2750Sstevel@tonic-gate adt_session_data_t *state; 2760Sstevel@tonic-gate size_t length; 2770Sstevel@tonic-gate jbyte *buffer; 2780Sstevel@tonic-gate jbyteArray jbuf; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if (j2c_pointer(env, jstate, (caddr_t *)&state)) 2810Sstevel@tonic-gate return (NULL); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate length = adt_export_session_data(state, (adt_export_data_t **)&buffer); 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if ((jbuf = (*env)->NewByteArray(env, length)) == NULL) { 2860Sstevel@tonic-gate free(buffer); 2870Sstevel@tonic-gate return (NULL); 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate (*env)->SetByteArrayRegion(env, jbuf, 0, length, buffer); 2900Sstevel@tonic-gate free(buffer); 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate return (jbuf); 2930Sstevel@tonic-gate } 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate /* ARGSUSED */ 2960Sstevel@tonic-gate JNIEXPORT void JNICALL 2970Sstevel@tonic-gate Java_com_sun_audit_AuditSession_sessionAttr(JNIEnv *env, jobject cls, 2980Sstevel@tonic-gate jbyteArray jstate, 2990Sstevel@tonic-gate jint euid, jint egid, jint ruid, jint rgid, 3000Sstevel@tonic-gate jstring jhostname, jint context) { 3010Sstevel@tonic-gate adt_session_data_t *state; 3020Sstevel@tonic-gate const char *hostname; 3030Sstevel@tonic-gate adt_termid_t *termid; 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate if (j2c_pointer(env, jstate, (caddr_t *)&state)) 3060Sstevel@tonic-gate return; /* j2c_pointer threw exception */ 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate if (state == NULL) 3090Sstevel@tonic-gate return; /* invalid session */ 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate hostname = (*env)->GetStringUTFChars(env, jhostname, NULL); 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate if (adt_load_hostname(hostname, &termid)) 3140Sstevel@tonic-gate local_throw(env, "java/lang/Error", errno_to_i18n(errno)); 3150Sstevel@tonic-gate else if (adt_set_user(state, euid, egid, ruid, rgid, 3160Sstevel@tonic-gate termid, context)) 3170Sstevel@tonic-gate local_throw(env, "java/lang/Error", errno_to_i18n(errno)); 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate (*env)->ReleaseStringUTFChars(env, jhostname, hostname); 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate /* ARGSUSED */ 3230Sstevel@tonic-gate JNIEXPORT jboolean JNICALL 3240Sstevel@tonic-gate Java_com_sun_audit_AuditSession_bsmAuditOn(JNIEnv *env, jobject cls) { 3250Sstevel@tonic-gate int condition; 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate if (auditon(A_GETCOND, (caddr_t)&condition, sizeof (condition))) 3280Sstevel@tonic-gate return (0); 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate return (1); 3310Sstevel@tonic-gate } 332