blob: 3243c5d483aa5f531bb6a5f1e9eee15dc7445d67 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include "NativeUtil.h"
27#include "NativeFunc.h"
28
29const int JAVA_DUPLICATE_TOKEN_CODE = 19; /* DUPLICATE_TOKEN */
30const int JAVA_OLD_TOKEN_CODE = 20; /* OLD_TOKEN */
31const int JAVA_UNSEQ_TOKEN_CODE = 21; /* UNSEQ_TOKEN */
32const int JAVA_GAP_TOKEN_CODE = 22; /* GAP_TOKEN */
33const int JAVA_ERROR_CODE[] = {
34 2, /* BAD_MECH */
35 3, /* BAD_NAME */
36 4, /* BAD_NAMETYPE */
37 1, /* BAD_BINDINGS */
38 5, /* BAD_STATUS */
39 6, /* BAD_MIC */
40 13, /* NO_CRED */
41 12, /* NO_CONTEXT */
42 10, /* DEFECTIVE_TOKEN */
43 9, /* DEFECTIVE_CREDENTIAL */
44 8, /* CREDENTIAL_EXPIRED */
45 7, /* CONTEXT_EXPIRED */
46 11, /* FAILURE */
47 14, /* BAD_QOP */
48 15, /* UNAUTHORIZED */
49 16, /* UNAVAILABLE */
50 17, /* DUPLICATE_ELEMENT */
51 18, /* NAME_NOT_MN */
52};
53const char SPNEGO_BYTES[] = {
54 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
55};
56
57jclass CLS_Object;
58jclass CLS_String;
59jclass CLS_Oid;
60jclass CLS_GSSException;
61jclass CLS_GSSNameElement;
62jclass CLS_GSSCredElement;
63jclass CLS_NativeGSSContext;
64jclass CLS_SunNativeProvider;
65jmethodID MID_String_ctor;
66jmethodID MID_Oid_ctor1;
67jmethodID MID_Oid_getDER;
68jmethodID MID_MessageProp_getPrivacy;
69jmethodID MID_MessageProp_getQOP;
70jmethodID MID_MessageProp_setPrivacy;
71jmethodID MID_MessageProp_setQOP;
72jmethodID MID_MessageProp_setSupplementaryStates;
73jmethodID MID_GSSException_ctor3;
74jmethodID MID_ChannelBinding_getInitiatorAddr;
75jmethodID MID_ChannelBinding_getAcceptorAddr;
76jmethodID MID_ChannelBinding_getAppData;
77jmethodID MID_InetAddress_getAddr;
78jmethodID MID_GSSNameElement_ctor;
79jmethodID MID_GSSCredElement_ctor;
80jmethodID MID_NativeGSSContext_ctor;
81jmethodID MID_SunNativeProvider_debug;
82jfieldID FID_GSSLibStub_pMech;
83jfieldID FID_NativeGSSContext_pContext;
84jfieldID FID_NativeGSSContext_srcName;
85jfieldID FID_NativeGSSContext_targetName;
86jfieldID FID_NativeGSSContext_isInitiator;
87jfieldID FID_NativeGSSContext_isEstablished;
88jfieldID FID_NativeGSSContext_delegatedCred;
89jfieldID FID_NativeGSSContext_flags;
90jfieldID FID_NativeGSSContext_lifetime;
91jfieldID FID_NativeGSSContext_actualMech;
92char debugBuf[256];
93
94JNIEXPORT jint JNICALL
95JNI_OnLoad(JavaVM *jvm, void *reserved) {
96 JNIEnv *env;
97 jclass cls;
98
99 if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
100 return JNI_EVERSION; /* JNI version not supported */
101 }
102 /* Retrieve and store the classes in global ref */
103 cls = (*env)->FindClass(env, "java/lang/Object");
104 if (cls == NULL) {
105 printf("Couldn't find Object class\n");
106 return JNI_ERR;
107 }
108 CLS_Object = (*env)->NewGlobalRef(env, cls);
109 if (CLS_Object == NULL) {
110 return JNI_ERR;
111 }
112 cls = (*env)->FindClass(env, "java/lang/String");
113 if (cls == NULL) {
114 printf("Couldn't find String class\n");
115 return JNI_ERR;
116 }
117 CLS_String = (*env)->NewGlobalRef(env, cls);
118 if (CLS_String == NULL) {
119 return JNI_ERR;
120 }
121 cls = (*env)->FindClass(env, "org/ietf/jgss/Oid");
122 if (cls == NULL) {
123 printf("Couldn't find org.ietf.jgss.Oid class\n");
124 return JNI_ERR;
125 }
126 CLS_Oid = (*env)->NewGlobalRef(env, cls);
127 if (CLS_Oid == NULL) {
128 return JNI_ERR;
129 }
130 cls = (*env)->FindClass(env, "org/ietf/jgss/GSSException");
131 if (cls == NULL) {
132 printf("Couldn't find org.ietf.jgss.GSSException class\n");
133 return JNI_ERR;
134 }
135 CLS_GSSException = (*env)->NewGlobalRef(env, cls);
136 if (CLS_GSSException == NULL) {
137 return JNI_ERR;
138 }
139 cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSNameElement");
140 if (cls == NULL) {
141 printf("Couldn't find sun.security.jgss.wrapper.GSSNameElement class\n");
142 return JNI_ERR;
143 }
144 CLS_GSSNameElement = (*env)->NewGlobalRef(env, cls);
145 if (CLS_GSSException == NULL) {
146 return JNI_ERR;
147 }
148 cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSCredElement");
149 if (cls == NULL) {
150 printf("Couldn't find sun.security.jgss.wrapper.GSSCredElement class\n");
151 return JNI_ERR;
152 }
153 CLS_GSSCredElement = (*env)->NewGlobalRef(env, cls);
154 if (CLS_GSSCredElement == NULL) {
155 return JNI_ERR;
156 }
157 cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/NativeGSSContext");
158 if (cls == NULL) {
159 printf("Couldn't find sun.security.jgss.wrapper.NativeGSSContext class\n");
160 return JNI_ERR;
161 }
162 CLS_NativeGSSContext = (*env)->NewGlobalRef(env, cls);
163 if (CLS_NativeGSSContext == NULL) {
164 return JNI_ERR;
165 }
166 cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/SunNativeProvider");
167 if (cls == NULL) {
168 printf("Couldn't find sun.security.jgss.wrapper.SunNativeProvider class\n");
169 return JNI_ERR;
170 }
171 CLS_SunNativeProvider = (*env)->NewGlobalRef(env, cls);
172 if (CLS_SunNativeProvider == NULL) {
173 return JNI_ERR;
174 }
175 /* Compute and cache the method ID */
176 MID_String_ctor = (*env)->GetMethodID(env, CLS_String,
177 "<init>", "([B)V");
178 if (MID_String_ctor == NULL) {
179 printf("Couldn't find String(byte[]) constructor\n");
180 return JNI_ERR;
181 }
182 MID_Oid_ctor1 =
183 (*env)->GetMethodID(env, CLS_Oid, "<init>", "([B)V");
184 if (MID_Oid_ctor1 == NULL) {
185 printf("Couldn't find Oid(byte[]) constructor\n");
186 return JNI_ERR;
187 }
188 MID_Oid_getDER = (*env)->GetMethodID(env, CLS_Oid, "getDER", "()[B");
189 if (MID_Oid_getDER == NULL) {
190 printf("Couldn't find Oid.getDER() method\n");
191 return JNI_ERR;
192 }
193 cls = (*env)->FindClass(env, "org/ietf/jgss/MessageProp");
194 if (cls == NULL) {
195 printf("Couldn't find org.ietf.jgss.MessageProp class\n");
196 return JNI_ERR;
197 }
198 MID_MessageProp_getPrivacy =
199 (*env)->GetMethodID(env, cls, "getPrivacy", "()Z");
200 if (MID_MessageProp_getPrivacy == NULL) {
201 printf("Couldn't find MessageProp.getPrivacy() method\n");
202 return JNI_ERR;
203 }
204 MID_MessageProp_getQOP = (*env)->GetMethodID(env, cls, "getQOP", "()I");
205 if (MID_MessageProp_getQOP == NULL) {
206 printf("Couldn't find MessageProp.getQOP() method\n");
207 return JNI_ERR;
208 }
209 MID_MessageProp_setPrivacy =
210 (*env)->GetMethodID(env, cls, "setPrivacy", "(Z)V");
211 if (MID_MessageProp_setPrivacy == NULL) {
212 printf("Couldn't find MessageProp.setPrivacy(boolean) method\n");
213 return JNI_ERR;
214 }
215 MID_MessageProp_setQOP = (*env)->GetMethodID(env, cls, "setQOP", "(I)V");
216 if (MID_MessageProp_setQOP == NULL) {
217 printf("Couldn't find MessageProp.setQOP(int) method\n");
218 return JNI_ERR;
219 }
220 MID_MessageProp_setSupplementaryStates =
221 (*env)->GetMethodID(env, cls, "setSupplementaryStates",
222 "(ZZZZILjava/lang/String;)V");
223 if (MID_MessageProp_setSupplementaryStates == NULL) {
224 printf("Couldn't find MessageProp.setSupplementaryStates(...) method\n");
225 return JNI_ERR;
226 }
227 MID_GSSException_ctor3 = (*env)->GetMethodID
228 (env, CLS_GSSException, "<init>", "(IILjava/lang/String;)V");
229 if (MID_GSSException_ctor3 == NULL) {
230 printf("Couldn't find GSSException(int, int, String) constructor\n");
231 return JNI_ERR;
232 }
233 cls = (*env)->FindClass(env, "org/ietf/jgss/ChannelBinding");
234 if (cls == NULL) {
235 printf("Couldn't find org.ietf.jgss.ChannelBinding class\n");
236 return JNI_ERR;
237 }
238 MID_ChannelBinding_getInitiatorAddr =
239 (*env)->GetMethodID(env, cls, "getInitiatorAddress",
240 "()Ljava/net/InetAddress;");
241 if (MID_ChannelBinding_getInitiatorAddr == NULL) {
242 printf("Couldn't find ChannelBinding.getInitiatorAddress() method\n");
243 return JNI_ERR;
244 }
245 MID_ChannelBinding_getAcceptorAddr =
246 (*env)->GetMethodID(env, cls, "getAcceptorAddress",
247 "()Ljava/net/InetAddress;");
248 if (MID_ChannelBinding_getAcceptorAddr == NULL) {
249 printf("Couldn't find ChannelBinding.getAcceptorAddress() method\n");
250 return JNI_ERR;
251 }
252 MID_ChannelBinding_getAppData =
253 (*env)->GetMethodID(env, cls, "getApplicationData", "()[B");
254 if (MID_ChannelBinding_getAppData == NULL) {
255 printf("Couldn't find ChannelBinding.getApplicationData() method\n");
256 return JNI_ERR;
257 }
258 cls = (*env)->FindClass(env, "java/net/InetAddress");
259 if (cls == NULL) {
260 printf("Couldn't find java.net.InetAddress class\n");
261 return JNI_ERR;
262 }
263 MID_InetAddress_getAddr = (*env)->GetMethodID(env, cls, "getAddress",
264 "()[B");
265 if (MID_InetAddress_getAddr == NULL) {
266 printf("Couldn't find InetAddress.getAddress() method\n");
267 return JNI_ERR;
268 }
269 MID_GSSNameElement_ctor =
270 (*env)->GetMethodID(env, CLS_GSSNameElement,
271 "<init>", "(JLsun/security/jgss/wrapper/GSSLibStub;)V");
272 if (MID_GSSNameElement_ctor == NULL) {
273 printf("Couldn't find GSSNameElement(long, GSSLibStub) constructor\n");
274 return JNI_ERR;
275 }
276 MID_GSSCredElement_ctor =
277 (*env)->GetMethodID(env, CLS_GSSCredElement, "<init>",
278 "(JLsun/security/jgss/wrapper/GSSNameElement;Lorg/ietf/jgss/Oid;)V");
279 if (MID_GSSCredElement_ctor == NULL) {
280 printf("Couldn't find GSSCredElement(long, GSSLibStub) constructor\n");
281 return JNI_ERR;
282 }
283 MID_NativeGSSContext_ctor =
284 (*env)->GetMethodID(env, CLS_NativeGSSContext, "<init>",
285 "(JLsun/security/jgss/wrapper/GSSLibStub;)V");
286 if (MID_NativeGSSContext_ctor == NULL) {
287 printf("Couldn't find NativeGSSContext(long, GSSLibStub) constructor\n");
288 return JNI_ERR;
289 }
290 MID_SunNativeProvider_debug =
291 (*env)->GetStaticMethodID(env, CLS_SunNativeProvider, "debug",
292 "(Ljava/lang/String;)V");
293 if (MID_SunNativeProvider_debug == NULL) {
294 printf("Couldn't find SunNativeProvider.debug(String) method\n");
295 return JNI_ERR;
296 }
297 /* Compute and cache the field ID */
298 cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSLibStub");
299 if (cls == NULL) {
300 printf("Couldn't find sun.security.jgss.wrapper.GSSLibStub class\n");
301 return JNI_ERR;
302 }
303 FID_GSSLibStub_pMech =
304 (*env)->GetFieldID(env, cls, "pMech", "J");
305 if (FID_GSSLibStub_pMech == NULL) {
306 printf("Couldn't find GSSLibStub.pMech field\n");
307 return JNI_ERR;
308 }
309 FID_NativeGSSContext_pContext =
310 (*env)->GetFieldID(env, CLS_NativeGSSContext, "pContext", "J");
311 if (FID_NativeGSSContext_pContext == NULL) {
312 printf("Couldn't find NativeGSSContext.pContext field\n");
313 return JNI_ERR;
314 }
315 FID_NativeGSSContext_srcName =
316 (*env)->GetFieldID(env, CLS_NativeGSSContext, "srcName",
317 "Lsun/security/jgss/wrapper/GSSNameElement;");
318 if (FID_NativeGSSContext_srcName == NULL) {
319 printf("Couldn't find NativeGSSContext.srcName field\n");
320 return JNI_ERR;
321 }
322 FID_NativeGSSContext_targetName =
323 (*env)->GetFieldID(env, CLS_NativeGSSContext, "targetName",
324 "Lsun/security/jgss/wrapper/GSSNameElement;");
325 if (FID_NativeGSSContext_targetName == NULL) {
326 printf("Couldn't find NativeGSSContext.targetName field\n");
327 return JNI_ERR;
328 }
329 FID_NativeGSSContext_isInitiator =
330 (*env)->GetFieldID(env, CLS_NativeGSSContext, "isInitiator", "Z");
331 if (FID_NativeGSSContext_isInitiator == NULL) {
332 printf("Couldn't find NativeGSSContext.isInitiator field\n");
333 return JNI_ERR;
334 }
335 FID_NativeGSSContext_isEstablished =
336 (*env)->GetFieldID(env, CLS_NativeGSSContext, "isEstablished", "Z");
337 if (FID_NativeGSSContext_isEstablished == NULL) {
338 printf("Couldn't find NativeGSSContext.isEstablished field\n");
339 return JNI_ERR;
340 }
341 FID_NativeGSSContext_delegatedCred =
342 (*env)->GetFieldID(env, CLS_NativeGSSContext, "delegatedCred",
343 "Lsun/security/jgss/wrapper/GSSCredElement;");
344 if (FID_NativeGSSContext_delegatedCred == NULL) {
345 printf("Couldn't find NativeGSSContext.delegatedCred field\n");
346 return JNI_ERR;
347 }
348 FID_NativeGSSContext_flags =
349 (*env)->GetFieldID(env, CLS_NativeGSSContext, "flags", "I");
350 if (FID_NativeGSSContext_flags == NULL) {
351 printf("Couldn't find NativeGSSContext.flags field\n");
352 return JNI_ERR;
353 }
354 FID_NativeGSSContext_lifetime =
355 (*env)->GetFieldID(env, CLS_NativeGSSContext, "lifetime", "I");
356 if (FID_NativeGSSContext_lifetime == NULL) {
357 printf("Couldn't find NativeGSSContext.lifetime field\n");
358 return JNI_ERR;
359 }
360 FID_NativeGSSContext_actualMech =
361 (*env)->GetFieldID(env, CLS_NativeGSSContext, "actualMech",
362 "Lorg/ietf/jgss/Oid;");
363 if (FID_NativeGSSContext_actualMech == NULL) {
364 printf("Couldn't find NativeGSSContext.actualMech field\n");
365 return JNI_ERR;
366 }
367 return JNI_VERSION_1_2;
368}
369
370JNIEXPORT void JNICALL
371JNI_OnUnload(JavaVM *jvm, void *reserved) {
372 JNIEnv *env;
373
374 if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
375 return;
376 }
377 /* Delete the global refs */
378 (*env)->DeleteGlobalRef(env, CLS_Object);
379 (*env)->DeleteGlobalRef(env, CLS_String);
380 (*env)->DeleteGlobalRef(env, CLS_Oid);
381 (*env)->DeleteGlobalRef(env, CLS_GSSException);
382 (*env)->DeleteGlobalRef(env, CLS_GSSNameElement);
383 (*env)->DeleteGlobalRef(env, CLS_GSSCredElement);
384 (*env)->DeleteGlobalRef(env, CLS_SunNativeProvider);
385 return;
386}
387
388const OM_uint32 JAVA_MAX = GSS_C_INDEFINITE/2;
389
390/*
391 * Utility routine for converting the C unsigned integer time
392 * to Java signed integer time.
393 */
394jint getJavaTime(OM_uint32 ctime) {
395 jint result;
396
397 /* special handle values equals or more than JAVA_MAX */
398 if (ctime == GSS_C_INDEFINITE) {
399 result = JAVA_MAX;
400 } else if (ctime >= JAVA_MAX) {
401 result = JAVA_MAX-1;
402 } else {
403 result = ctime;
404 }
405 return result;
406}
407/*
408 * Utility routine for converting the Java signed integer time
409 * to C unsigned integer time.
410 */
411OM_uint32 getGSSTime(jint jtime) {
412 OM_uint32 result;
413
414 /* special handle values equal to JAVA_MAX */
415 if (jtime == JAVA_MAX) {
416 result = GSS_C_INDEFINITE;
417 } else {
418 result = jtime;
419 }
420 return result;
421}
422/*
423 * Utility routine for mapping the C error code to the
424 * Java one. The routine errors really should have
425 * shared the same values but unfortunately don't.
426 */
427jint getJavaErrorCode(int cNonCallingErr) {
428 int cRoutineErr, cSuppStatus;
429 /* map the routine errors */
430 cRoutineErr = GSS_ROUTINE_ERROR(cNonCallingErr) >> 16;
431 if (cRoutineErr != GSS_S_COMPLETE) {
432 return JAVA_ERROR_CODE[cRoutineErr-1];
433 }
434 /* map the supplementary infos */
435 cSuppStatus = GSS_SUPPLEMENTARY_INFO(cNonCallingErr);
436 if (cSuppStatus & GSS_S_DUPLICATE_TOKEN) {
437 return JAVA_DUPLICATE_TOKEN_CODE;
438 } else if (cSuppStatus & GSS_S_OLD_TOKEN) {
439 return JAVA_OLD_TOKEN_CODE;
440 } else if (cSuppStatus & GSS_S_UNSEQ_TOKEN) {
441 return JAVA_UNSEQ_TOKEN_CODE;
442 } else if (cSuppStatus & GSS_S_GAP_TOKEN) {
443 return JAVA_GAP_TOKEN_CODE;
444 }
445 return GSS_S_COMPLETE;
446}
447/*
448 * Utility routine for creating a java.lang.String object
449 * using the specified gss_buffer_t structure. After the,
450 * String object is created, the specified gss_buffer_t
451 * structure is released.
452 */
453jstring getJavaString(JNIEnv *env, gss_buffer_t bytes) {
454 jstring result;
455 OM_uint32 minor;
456 int len;
457 jbyteArray jbytes;
458
459 if (bytes != NULL) {
460 /* constructs the String object with new String(byte[])
461 NOTE: do NOT include the trailing NULL */
462 len = bytes->length;
463 jbytes = (*env)->NewByteArray(env, len);
464 (*env)->SetByteArrayRegion(env, jbytes, 0, len, (jbyte *) bytes->value);
465 result = (*env)->NewObject(env, CLS_String, MID_String_ctor,
466 jbytes);
467 (*env)->DeleteLocalRef(env, jbytes);
468 (*ftab->releaseBuffer)(&minor, bytes);
469 return result;
470 } /* else fall through */
471 return NULL;
472}
473/*
474 * Utility routine for generate message for the specified minor
475 * status code.
476 */
477jstring getMinorMessage(JNIEnv *env, jobject jstub, OM_uint32 statusValue) {
478 OM_uint32 messageContext, minor, major;
479 gss_buffer_desc statusString;
480 gss_OID mech;
481 jstring msg;
482
483 messageContext = 0;
484 if (jstub != NULL) {
485 mech = (gss_OID) (*env)->GetLongField(env, jstub, FID_GSSLibStub_pMech);
486 } else {
487 mech = GSS_C_NO_OID;
488 }
489 /* gss_display_status(...) => GSS_S_BAD_MECH, GSS_S_BAD_STATUS */
490 major = (*ftab->displayStatus)(&minor, statusValue, GSS_C_MECH_CODE, mech,
491 &messageContext, &statusString);
492 /* release intermediate buffers */
493 msg = getJavaString(env, &statusString);
494 (*ftab->releaseBuffer)(&minor, &statusString);
495 return msg;
496}
497/*
498 * Utility routine checking the specified major and minor
499 * status codes. GSSExceptions will be thrown if they are
500 * not GSS_S_COMPLETE (i.e. 0).
501 */
502void checkStatus(JNIEnv *env, jobject jstub, OM_uint32 major,
503 OM_uint32 minor, char* methodName) {
504 int callingErr, routineErr, supplementaryInfo;
505 jint jmajor, jminor;
506 char* msg;
507 jstring jmsg;
508 jthrowable gssEx;
509
510 if (major == GSS_S_COMPLETE) return;
511
512 callingErr = GSS_CALLING_ERROR(major);
513 routineErr = GSS_ROUTINE_ERROR(major);
514 supplementaryInfo = GSS_SUPPLEMENTARY_INFO(major);
515
516 sprintf(debugBuf, "%s Status major/minor = %x/%d", methodName, major, minor);
517 debug(env, debugBuf);
518 sprintf(debugBuf, "%s Status c/r/s = %d/%d/%d ", methodName, callingErr>>24,
519 routineErr>>16, supplementaryInfo);
520 debug(env, debugBuf);
521
522 jmajor = getJavaErrorCode(routineErr | supplementaryInfo);
523 jminor = minor;
524 if (jmajor != GSS_S_COMPLETE) {
525 jmsg = NULL;
526 if (minor != 0) {
527 jmsg = getMinorMessage(env, jstub, minor);
528 }
529 gssEx = (*env)->NewObject(env, CLS_GSSException,
530 MID_GSSException_ctor3,
531 jmajor, jminor, jmsg);
532 (*env)->Throw(env, gssEx);
533 } else {
534 /* Error in calling the GSS api */
535 if (callingErr == GSS_S_CALL_INACCESSIBLE_READ) {
536 msg = "A required input parameter cannot be read";
537 } else if (callingErr == GSS_S_CALL_INACCESSIBLE_WRITE) {
538 msg = "A required output parameter cannot be write";
539 } else {
540 msg = "A parameter was malformed";
541 }
542 jmajor = 13; /* use GSSException.FAILURE for now */
543 jmsg = (*env)->NewStringUTF(env, msg);
544 gssEx = (*env)->NewObject(env, CLS_GSSException,
545 MID_GSSException_ctor3,
546 jmajor, jminor, jmsg);
547 (*env)->Throw(env, gssEx);
548 }
549}
550/*
551 * Utility routine for initializing gss_buffer_t structure
552 * with the byte[] in the specified jbyteArray object.
553 * NOTE: need to call resetGSSBuffer(...) to free up
554 * the resources.
555 */
556void initGSSBuffer(JNIEnv *env, jbyteArray jbytes,
557 gss_buffer_t cbytes) {
558 if (jbytes != NULL) {
559 cbytes->length = (*env)->GetArrayLength(env, jbytes);
560 cbytes->value = (*env)->GetByteArrayElements(env, jbytes, NULL);
561 } else {
562 cbytes->length = 0;
563 cbytes->value = NULL;
564 }
565}
566/*
567 * Utility routine for unpinning/releasing the byte[]
568 * associated with the specified jbyteArray object.
569 * NOTE: used in conjunction with initGSSBuffer(...).
570 */
571void resetGSSBuffer(JNIEnv *env, jbyteArray jbytes,
572 gss_buffer_t cbytes) {
573 if ((cbytes != NULL) && (cbytes != GSS_C_NO_BUFFER) &&
574 (cbytes->length != 0)) {
575 (*env)->ReleaseByteArrayElements(env, jbytes, cbytes->value,
576 JNI_ABORT);
577 }
578}
579/*
580 * Utility routine for creating a jbyteArray object using
581 * the byte[] value in specified gss_buffer_t structure.
582 * NOTE: the specified gss_buffer_t structure will be
583 * released in this routine.
584 */
585jbyteArray getJavaBuffer(JNIEnv *env, gss_buffer_t cbytes) {
586 jbyteArray result;
587 OM_uint32 minor; // don't care, just so it compiles
588
589 if ((cbytes != NULL) && (cbytes != GSS_C_NO_BUFFER) &&
590 (cbytes->length != 0)) {
591 result = (*env)->NewByteArray(env, cbytes->length);
592 (*env)->SetByteArrayRegion(env, result, 0, cbytes->length,
593 cbytes->value);
594 (*ftab->releaseBuffer)(&minor, cbytes);
595 return result;
596 }
597 return NULL;
598}
599
600/*
601 * Utility routine for creating a non-mech gss_OID using
602 * the specified org.ietf.jgss.Oid object.
603 * NOTE: need to call deleteGSSOID(...) afterwards to
604 * release the created gss_OID structure.
605 */
606gss_OID newGSSOID(JNIEnv *env, jobject jOid) {
607 jbyteArray jbytes;
608 gss_OID cOid;
609 jthrowable gssEx;
610 if (jOid != NULL) {
611 jbytes = (*env)->CallObjectMethod(env, jOid, MID_Oid_getDER);
612 if ((*env)->ExceptionCheck(env)) {
613 gssEx = (*env)->ExceptionOccurred(env);
614 (*env)->Throw(env, gssEx);
615 }
616 cOid = malloc(sizeof(struct gss_OID_desc_struct));
617 cOid->length = (*env)->GetArrayLength(env, jbytes) - 2;
618 cOid->elements = malloc(cOid->length);
619 (*env)->GetByteArrayRegion(env, jbytes, 2, cOid->length,
620 cOid->elements);
621 (*env)->DeleteLocalRef(env, jbytes);
622 return cOid;
623 } else {
624 return GSS_C_NO_OID;
625 }
626}
627/*
628 * Utility routine for releasing the specified gss_OID
629 * structure.
630 * NOTE: used in conjunction with newGSSOID(...).
631 */
632void deleteGSSOID(gss_OID oid) {
633 if (oid != GSS_C_NO_OID) {
634 free(oid->elements);
635 free(oid);
636 }
637}
638/*
639 * Utility routine for creating a org.ietf.jgss.Oid
640 * object using the specified gss_OID structure.
641 */
642jobject getJavaOID(JNIEnv *env, gss_OID cOid) {
643 int cLen;
644 char oidHdr[2];
645 jbyteArray jbytes;
646 jobject result;
647
648 if ((cOid == NULL) || (cOid == GSS_C_NO_OID)) {
649 return NULL;
650 }
651 cLen = cOid->length;
652 oidHdr[0] = 6;
653 oidHdr[1] = cLen;
654 jbytes = (*env)->NewByteArray(env, cLen+2);
655 (*env)->SetByteArrayRegion(env, jbytes, 0, 2, (jbyte *) oidHdr);
656 (*env)->SetByteArrayRegion(env, jbytes, 2, cLen, (jbyte *) cOid->elements);
657
658 result = (*env)->NewObject(env, CLS_Oid, MID_Oid_ctor1, jbytes);
659 if ((*env)->ExceptionCheck(env)) {
660 (*env)->Throw(env, (*env)->ExceptionOccurred(env));
661 }
662 (*env)->DeleteLocalRef(env, jbytes);
663 return result;
664}
665/*
666 * Utility routine for creating a gss_OID_set structure
667 * using the specified gss_OID.
668 * NOTE: need to call deleteGSSOIDSet(...) afterwards
669 * to release the created gss_OID_set structure.
670 */
671gss_OID_set newGSSOIDSet(JNIEnv *env, gss_OID oid) {
672 gss_OID_set oidSet;
673 OM_uint32 minor; // don't care; just so it compiles
674
675 if (oid->length != 6 ||
676 memcmp(oid->elements, SPNEGO_BYTES, 6) != 0) {
677 (*ftab->createEmptyOidSet)(&minor, &oidSet);
678 (*ftab->addOidSetMember)(&minor, oid, &oidSet);
679 return oidSet;
680 } else {
681 // Use all mechs for SPNEGO in order to work with
682 // various native GSS impls
683 return (ftab->mechs);
684 }
685}
686/*
687 * Utility routine for releasing a gss_OID_set structure.
688 * NOTE: used in conjunction with newGSSOIDSet(...).
689 */
690void deleteGSSOIDSet(gss_OID_set oidSet) {
691 OM_uint32 minor; /* don't care; just so it compiles */
692
693 if ((oidSet != ftab->mechs) &&
694 (oidSet != NULL) && (oidSet != GSS_C_NO_OID_SET)) {
695 (*ftab->releaseOidSet)(&minor, &oidSet);
696 }
697}
698/*
699 * Utility routine for creating a org.ietf.jgss.Oid[]
700 * using the specified gss_OID_set structure.
701 */
702jobjectArray getJavaOIDArray(JNIEnv *env, gss_OID_set cOidSet) {
703 int numOfOids = 0;
704 jobjectArray jOidSet;
705 jobject jOid;
706 int i;
707 jthrowable gssEx;
708
709 if (cOidSet != NULL && cOidSet != GSS_C_NO_OID_SET) {
710 numOfOids = cOidSet->count;
711 jOidSet = (*env)->NewObjectArray(env, numOfOids, CLS_Oid, NULL);
712 if (jOidSet != NULL) {
713 for (i = 0; i < numOfOids; i++) {
714 jOid = getJavaOID(env, &(cOidSet->elements[i]));
715 (*env)->SetObjectArrayElement(env, jOidSet, i, jOid);
716 (*env)->DeleteLocalRef(env, jOid);
717 }
718 }
719 return jOidSet;
720 }
721 return NULL;
722}
723
724void debug(JNIEnv *env, char *msg) {
725 jstring jmsg = (*env)->NewStringUTF(env, msg);
726 (*env)->CallStaticVoidMethod(env, CLS_SunNativeProvider,
727 MID_SunNativeProvider_debug, jmsg);
728 (*env)->DeleteLocalRef(env, jmsg);
729}
730
731int sameMech(JNIEnv *env, gss_OID mech, gss_OID mech2) {
732 int result = JNI_FALSE; // default to not equal
733
734 if (mech->length == mech2->length) {
735 result = (memcmp(mech->elements, mech2->elements, mech->length) == 0);
736 }
737 return result;
738}