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