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
local_throw(JNIEnv * env,const char * exception,const char * why)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 *
errno_to_i18n(int error_code)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
j2c_pointer(JNIEnv * env,jbyteArray jpointer,caddr_t * cpointer)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
c2j_pointer(JNIEnv * env,caddr_t cpointer,jbyteArray * jpointer)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
Java_com_sun_audit_AuditSession_startSession(JNIEnv * env,jobject cls,jbyteArray jimport,jlong flags)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
Java_com_sun_audit_AuditSession_endSession(JNIEnv * env,jobject cls,jbyteArray jstate)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
Java_com_sun_audit_AuditSession_dupSession(JNIEnv * env,jobject cls,jbyteArray jsource)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
Java_com_sun_audit_AuditSession_getSessionId(JNIEnv * env,jobject cls,jbyteArray jstate)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
Java_com_sun_audit_AuditSession_exportSessionData(JNIEnv * env,jobject cls,jbyteArray jstate)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
Java_com_sun_audit_AuditSession_sessionAttr(JNIEnv * env,jobject cls,jbyteArray jstate,jint euid,jint egid,jint ruid,jint rgid,jstring jhostname,jint context)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
Java_com_sun_audit_AuditSession_bsmAuditOn(JNIEnv * env,jobject cls)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