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