1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * adt_jni.c 23 * 24 * JNI wrapper for adt interface within libbsm 25 * 26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 * 29 */ 30 31 #include <bsm/adt.h> 32 #include "adt_jni.h" 33 #include <jni.h> 34 #include "../com/sun/audit/AuditSession.h" /* javah output */ 35 #include <assert.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <netdb.h> 39 40 /* 41 * local_throw -- throw an exception. 42 * "why" string must be i18n'd before calling here. 43 * 44 */ 45 46 void 47 local_throw(JNIEnv *env, const char *exception, const char *why) { 48 jobject jexception; 49 jclass exceptionclass; 50 jmethodID jexceptionnew; 51 52 jbyteArray jbarray; 53 54 jstring jmsg; 55 jclass strclass; 56 jmethodID jstrnew; 57 58 /* Get a String class and "new" method */ 59 strclass = (*env)->FindClass(env, "java/lang/String"); 60 jstrnew = (*env)->GetMethodID(env, strclass, "<init>", "([B)V"); 61 62 /* Create a Byte Array from message "why" */ 63 jbarray = (*env)->NewByteArray(env, (jsize)(strlen(why))); 64 (*env)->SetByteArrayRegion(env, jbarray, (jsize)0, 65 (jsize)(strlen(why)), (jbyte*) why); 66 67 /* Create string from byte array */ 68 jmsg = (*env)->NewObject(env, strclass, jstrnew, jbarray); 69 exceptionclass = (*env)->FindClass(env, exception); 70 jexceptionnew = (*env)->GetMethodID(env, exceptionclass, 71 "<init>", "(Ljava/lang/String;)V"); 72 73 jexception = (*env)->NewObject(env, exceptionclass, jexceptionnew, 74 jmsg); 75 (*env)->Throw(env, jexception); 76 } 77 78 /* 79 * i18n the strerror return. Input is errno. 80 * 81 */ 82 83 static char * 84 errno_to_i18n(int error_code) { 85 char *locale; 86 char *local_text; 87 88 locale = I18N_SETUP; 89 local_text = strerror(error_code); 90 (void) setlocale(LC_MESSAGES, locale); 91 return (local_text); 92 } 93 94 /* 95 * j2c_pointer 96 * 97 * convert java byte array into a C pointer 98 */ 99 int 100 j2c_pointer(JNIEnv *env, jbyteArray jpointer, caddr_t *cpointer) { 101 union { 102 caddr_t ptr; 103 jbyte buf[sizeof (uint64_t)]; 104 } u; 105 size_t jpointer_length; 106 char *locale; 107 108 (void) memset(u.buf, 0, sizeof (uint64_t)); 109 110 assert(jpointer != NULL); 111 112 jpointer_length = (*env)->GetArrayLength(env, jpointer); 113 if (jpointer_length != sizeof (uint64_t)) { 114 locale = I18N_SETUP; 115 local_throw(env, "java/lang/Error", 116 gettext("Bad session handle")); 117 (void) setlocale(LC_MESSAGES, locale); 118 return (-1); 119 } 120 (*env)->GetByteArrayRegion(env, jpointer, 0, jpointer_length, 121 &(u.buf[0])); 122 *cpointer = (caddr_t)u.ptr; 123 124 return (0); 125 } 126 127 /* 128 * c2j_pointer 129 * 130 * convert a C pointer into a java byte array 131 */ 132 void 133 c2j_pointer(JNIEnv *env, caddr_t cpointer, jbyteArray *jpointer) { 134 union { 135 caddr_t ptr; 136 jbyte buf[sizeof (uint64_t)]; 137 } u; 138 139 (void) memset(u.buf, 0, sizeof (uint64_t)); 140 u.ptr = cpointer; 141 142 *jpointer = (*env)->NewByteArray(env, sizeof (uint64_t)); 143 144 (*env)->SetByteArrayRegion(env, *jpointer, 0, sizeof (uint64_t), 145 &(u.buf[0])); 146 } 147 148 /* 149 * adt_start_session wrapper 150 * 151 */ 152 /*ARGSUSED*/ 153 JNIEXPORT jbyteArray JNICALL 154 Java_com_sun_audit_AuditSession_startSession(JNIEnv *env, jobject cls, 155 jbyteArray jimport, jlong flags) { 156 jbyteArray jstate; 157 adt_session_data_t *state; 158 jbyte *import; 159 size_t import_size; 160 int rc; 161 162 if (jimport == NULL) { 163 import = NULL; 164 } else { 165 import_size = (*env)->GetArrayLength(env, jimport); 166 import = (jbyte *)malloc(import_size * sizeof (jbyte)); 167 if (import == NULL) { 168 local_throw(env, "java/lang/Error", 169 errno_to_i18n(errno)); 170 return (NULL); 171 } 172 (*env)->GetByteArrayRegion(env, jimport, 0, import_size, 173 import); 174 } 175 rc = adt_start_session(&state, (adt_export_data_t *)import, flags); 176 177 if (import != NULL) 178 free(import); 179 180 if (rc) { 181 local_throw(env, "java/lang/Error", errno_to_i18n(errno)); 182 return (NULL); 183 } 184 c2j_pointer(env, (caddr_t)state, &jstate); 185 186 return (jstate); 187 } 188 189 /* 190 * adt_end_session wrapper 191 */ 192 193 /* ARGSUSED */ 194 JNIEXPORT void JNICALL 195 Java_com_sun_audit_AuditSession_endSession(JNIEnv *env, jobject cls, 196 jbyteArray jstate) { 197 adt_session_data_t *state; 198 char *locale; 199 200 if (j2c_pointer(env, jstate, (caddr_t *)&state)) 201 return; 202 203 if (state == NULL) 204 return; /* invalid session, nothing to free */ 205 206 /* presently, no errors defined, but what the heck? */ 207 if (adt_end_session(state)) { 208 locale = I18N_SETUP; 209 local_throw(env, "java/lang/Error", 210 gettext("Bad session handle")); 211 (void) setlocale(LC_MESSAGES, locale); 212 } 213 } 214 215 /* 216 * adt_dup_session wrapper 217 */ 218 219 /* ARGSUSED */ 220 JNIEXPORT jbyteArray JNICALL 221 Java_com_sun_audit_AuditSession_dupSession(JNIEnv *env, jobject cls, 222 jbyteArray jsource) { 223 jbyteArray jdest; 224 adt_session_data_t *source, *dest; 225 char *locale; 226 227 if (j2c_pointer(env, jsource, (caddr_t *)&source)) 228 return (NULL); 229 230 if (adt_dup_session(source, &dest)) { 231 locale = I18N_SETUP; 232 local_throw(env, "java/lang/Error", 233 gettext("Out of memory")); 234 (void) setlocale(LC_MESSAGES, locale); 235 } 236 237 c2j_pointer(env, (caddr_t)dest, &jdest); 238 239 return (jdest); 240 } 241 242 /* 243 * adt_get_session_id wrapper 244 * 245 */ 246 247 /* ARGSUSED */ 248 JNIEXPORT jstring JNICALL 249 Java_com_sun_audit_AuditSession_getSessionId(JNIEnv *env, jobject cls, 250 jbyteArray jstate) { 251 adt_session_data_t *state; 252 char *session_id; 253 jstring return_val; 254 255 if (j2c_pointer(env, jstate, (caddr_t *)&state)) 256 return (NULL); 257 258 if (adt_get_session_id(state, &session_id)) { 259 return_val = (*env)->NewStringUTF(env, session_id); 260 free(session_id); 261 return (return_val); 262 } else 263 return (NULL); 264 } 265 266 /* 267 * adt_get_session_id wrapper 268 */ 269 270 /* ARGSUSED */ 271 JNIEXPORT jbyteArray JNICALL 272 Java_com_sun_audit_AuditSession_exportSessionData 273 (JNIEnv *env, jobject cls, jbyteArray jstate) { 274 adt_session_data_t *state; 275 size_t length; 276 jbyte *buffer; 277 jbyteArray jbuf; 278 279 if (j2c_pointer(env, jstate, (caddr_t *)&state)) 280 return (NULL); 281 282 length = adt_export_session_data(state, (adt_export_data_t **)&buffer); 283 284 if ((jbuf = (*env)->NewByteArray(env, length)) == NULL) { 285 free(buffer); 286 return (NULL); 287 } 288 (*env)->SetByteArrayRegion(env, jbuf, 0, length, buffer); 289 free(buffer); 290 291 return (jbuf); 292 } 293 294 /* ARGSUSED */ 295 JNIEXPORT void JNICALL 296 Java_com_sun_audit_AuditSession_sessionAttr(JNIEnv *env, jobject cls, 297 jbyteArray jstate, 298 jint euid, jint egid, jint ruid, jint rgid, 299 jstring jhostname, jint context) { 300 adt_session_data_t *state; 301 const char *hostname; 302 adt_termid_t *termid; 303 304 if (j2c_pointer(env, jstate, (caddr_t *)&state)) 305 return; /* j2c_pointer threw exception */ 306 307 if (state == NULL) 308 return; /* invalid session */ 309 310 hostname = (*env)->GetStringUTFChars(env, jhostname, NULL); 311 312 if (adt_load_hostname(hostname, &termid)) { 313 local_throw(env, "java/lang/Error", errno_to_i18n(errno)); 314 } else if (adt_set_user(state, euid, egid, ruid, rgid, termid, 315 context)) { 316 free(termid); 317 local_throw(env, "java/lang/Error", errno_to_i18n(errno)); 318 } 319 (*env)->ReleaseStringUTFChars(env, jhostname, hostname); 320 free(termid); 321 } 322 323 /* ARGSUSED */ 324 JNIEXPORT jboolean JNICALL 325 Java_com_sun_audit_AuditSession_bsmAuditOn(JNIEnv *env, jobject cls) { 326 int condition; 327 328 if (auditon(A_GETCOND, (caddr_t)&condition, sizeof (condition))) 329 return (0); 330 331 return (1); 332 } 333