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