1 /*
2  * Copyright (c) 2005, 2018, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #include "sun_security_jgss_wrapper_GSSLibStub.h"
27 #include "NativeUtil.h"
28 #include "NativeFunc.h"
29 #include "jlong.h"
30 #include <jni.h>
31 
32 /* Constants for indicating what type of info is needed for inquiries */
33 const int TYPE_CRED_NAME = 10;
34 const int TYPE_CRED_TIME = 11;
35 const int TYPE_CRED_USAGE = 12;
36 
37 /*
38  * Class:     sun_security_jgss_wrapper_GSSLibStub
39  * Method:    init
40  * Signature: (Ljava/lang/String;Z)Z
41  */
42 JNIEXPORT jboolean JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_init(JNIEnv * env,jclass jcls,jstring jlibName,jboolean jDebug)43 Java_sun_security_jgss_wrapper_GSSLibStub_init(JNIEnv *env,
44                                                jclass jcls,
45                                                jstring jlibName,
46                                                jboolean jDebug) {
47     const char *libName;
48     int failed;
49     char *error = NULL;
50 
51     if (!jDebug) {
52       JGSS_DEBUG = 0;
53     } else {
54       JGSS_DEBUG = 1;
55     }
56 
57     if (jlibName == NULL) {
58         TRACE0("[GSSLibStub_init] GSS lib name is NULL");
59         return JNI_FALSE;
60     }
61 
62     libName = (*env)->GetStringUTFChars(env, jlibName, NULL);
63     if (libName == NULL) {
64         return JNI_FALSE;
65     }
66     TRACE1("[GSSLibStub_init] libName=%s", libName);
67 
68     /* initialize global function table */
69     failed = loadNative(libName);
70     (*env)->ReleaseStringUTFChars(env, jlibName, libName);
71 
72     if (!failed) {
73         return JNI_TRUE;
74     } else {
75         if (JGSS_DEBUG) {
76 #ifdef WIN32
77             #define MAX_MSG_SIZE 256
78             static CHAR szMsgBuf[MAX_MSG_SIZE];
79             DWORD dwRes;
80             DWORD dwError = GetLastError();
81             dwRes = FormatMessage (
82                     FORMAT_MESSAGE_FROM_SYSTEM,
83                     NULL,
84                     dwError,
85                     0,
86                     szMsgBuf,
87                     MAX_MSG_SIZE,
88                     NULL);
89             if (0 == dwRes) {
90                 printf("GSS-API: Unknown failure %d\n", dwError);
91             } else {
92                 printf("GSS-API: %s\n",szMsgBuf);
93             }
94 #else
95             char* error = dlerror();
96             if (error) {
97                 TRACE0(error);
98             }
99 #endif
100         }
101         return JNI_FALSE;
102     }
103 }
104 
105 /*
106  * Class:     sun_security_jgss_wrapper_GSSLibStub
107  * Method:    getMechPtr
108  * Signature: ([B)J
109  */
110 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getMechPtr(JNIEnv * env,jclass jcls,jbyteArray jbytes)111 Java_sun_security_jgss_wrapper_GSSLibStub_getMechPtr(JNIEnv *env,
112                                                      jclass jcls,
113                                                      jbyteArray jbytes) {
114   gss_OID cOid;
115   unsigned int i, len;
116   jbyte* bytes;
117   int found;
118 
119   if (jbytes != NULL) {
120     found = 0;
121     len = (unsigned int)((*env)->GetArrayLength(env, jbytes) - 2);
122     bytes = (*env)->GetByteArrayElements(env, jbytes, NULL);
123     if (bytes == NULL) {
124       return ptr_to_jlong(NULL);
125     }
126     for (i = 0; i < ftab->mechs->count; i++) {
127       cOid = &(ftab->mechs->elements[i]);
128       if (len == cOid->length &&
129           (memcmp(cOid->elements, (bytes + 2), len) == 0)) {
130         // Found a match
131         found = 1;
132         break;
133       }
134     }
135     (*env)->ReleaseByteArrayElements(env, jbytes, bytes, 0);
136 
137     if (found != 1) {
138       checkStatus(env, NULL, GSS_S_BAD_MECH, 0, "[GSSLibStub_getMechPtr]");
139       return ptr_to_jlong(NULL);
140     } else {
141       return ptr_to_jlong(cOid);
142     }
143   } else {
144     return ptr_to_jlong(GSS_C_NO_OID);
145   }
146 }
147 
148 /*
149  * Utility routine which releases the specified gss_channel_bindings_t
150  * structure.
151  */
deleteGSSCB(gss_channel_bindings_t cb)152 void deleteGSSCB(gss_channel_bindings_t cb) {
153 
154   if (cb == GSS_C_NO_CHANNEL_BINDINGS) return;
155 
156   /* release initiator address */
157   if (cb->initiator_addrtype != GSS_C_AF_NULLADDR) {
158     resetGSSBuffer(&(cb->initiator_address));
159   }
160   /* release acceptor address */
161   if (cb->acceptor_addrtype != GSS_C_AF_NULLADDR) {
162     resetGSSBuffer(&(cb->acceptor_address));
163   }
164   /* release application data */
165   if (cb->application_data.length != 0) {
166     resetGSSBuffer(&(cb->application_data));
167   }
168   free(cb);
169 }
170 
171 /*
172  * Utility routine which creates a gss_channel_bindings_t structure
173  * using the specified org.ietf.jgss.ChannelBinding object.
174  * NOTE: must call deleteGSSCB() to free up the resources.
175  */
newGSSCB(JNIEnv * env,jobject jcb)176 gss_channel_bindings_t newGSSCB(JNIEnv *env, jobject jcb) {
177   gss_channel_bindings_t cb;
178   jobject jinetAddr;
179   jbyteArray value;
180 
181   if (jcb == NULL) {
182     return GSS_C_NO_CHANNEL_BINDINGS;
183   }
184 
185   cb = malloc(sizeof(struct gss_channel_bindings_struct));
186   if (cb == NULL) {
187     throwOutOfMemoryError(env,NULL);
188     return NULL;
189   }
190 
191   // initialize addrtype in CB first
192   cb->initiator_addrtype = GSS_C_AF_NULLADDR;
193   cb->acceptor_addrtype = GSS_C_AF_NULLADDR;
194 
195   // addresses needs to be initialized to empty
196   memset(&cb->initiator_address, 0, sizeof(cb->initiator_address));
197   memset(&cb->acceptor_address, 0, sizeof(cb->acceptor_address));
198 
199   /* set up initiator address */
200   jinetAddr = (*env)->CallObjectMethod(env, jcb,
201       MID_ChannelBinding_getInitiatorAddr);
202   if ((*env)->ExceptionCheck(env)) {
203     goto cleanup;
204   }
205   if (jinetAddr != NULL) {
206     value = (*env)->CallObjectMethod(env, jinetAddr,
207                                      MID_InetAddress_getAddr);
208     if ((*env)->ExceptionCheck(env)) {
209       goto cleanup;
210     }
211     cb->initiator_addrtype = GSS_C_AF_INET;
212     initGSSBuffer(env, value, &(cb->initiator_address));
213     if ((*env)->ExceptionCheck(env)) {
214       goto cleanup;
215     }
216   }
217   /* set up acceptor address */
218   jinetAddr = (*env)->CallObjectMethod(env, jcb,
219       MID_ChannelBinding_getAcceptorAddr);
220   if ((*env)->ExceptionCheck(env)) {
221     goto cleanup;
222   }
223   if (jinetAddr != NULL) {
224     value = (*env)->CallObjectMethod(env, jinetAddr,
225                                      MID_InetAddress_getAddr);
226     if ((*env)->ExceptionCheck(env)) {
227       goto cleanup;
228     }
229     cb->acceptor_addrtype = GSS_C_AF_INET;
230     initGSSBuffer(env, value, &(cb->acceptor_address));
231     if ((*env)->ExceptionCheck(env)) {
232       goto cleanup;
233     }
234   }
235   /* set up application data */
236   value = (*env)->CallObjectMethod(env, jcb,
237                                    MID_ChannelBinding_getAppData);
238   if ((*env)->ExceptionCheck(env)) {
239     goto cleanup;
240   }
241   initGSSBuffer(env, value, &(cb->application_data));
242   if ((*env)->ExceptionCheck(env)) {
243     goto cleanup;
244   }
245   return cb;
246 cleanup:
247   deleteGSSCB(cb);
248   return NULL;
249 }
250 
251 /*
252  * Utility routine for storing the supplementary information
253  * into the specified org.ietf.jgss.MessageProp object.
254  */
setSupplementaryInfo(JNIEnv * env,jobject jstub,jobject jprop,int suppInfo,int minor)255 void setSupplementaryInfo(JNIEnv *env, jobject jstub, jobject jprop,
256                           int suppInfo, int minor) {
257   jboolean isDuplicate, isOld, isUnseq, hasGap;
258   jstring minorMsg;
259 
260   if (suppInfo != GSS_S_COMPLETE) {
261     isDuplicate = ((suppInfo & GSS_S_DUPLICATE_TOKEN) != 0);
262     isOld = ((suppInfo & GSS_S_OLD_TOKEN) != 0);
263     isUnseq = ((suppInfo & GSS_S_UNSEQ_TOKEN) != 0);
264     hasGap = ((suppInfo & GSS_S_GAP_TOKEN) != 0);
265     minorMsg = getMinorMessage(env, jstub, minor);
266     if ((*env)->ExceptionCheck(env)) {
267       return;
268     }
269     (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setSupplementaryStates,
270                            isDuplicate, isOld, isUnseq, hasGap, minor,
271                            minorMsg);
272   }
273 }
274 
275 /*
276  * Class:     sun_security_jgss_wrapper_GSSLibStub
277  * Method:    indicateMechs
278  * Signature: ()[Lorg/ietf/jgss/Oid;
279  */
280 JNIEXPORT jobjectArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_indicateMechs(JNIEnv * env,jclass jcls)281 Java_sun_security_jgss_wrapper_GSSLibStub_indicateMechs(JNIEnv *env,
282                                                         jclass jcls)
283 {
284   if (ftab->mechs != NULL && ftab->mechs != GSS_C_NO_OID_SET) {
285     return getJavaOIDArray(env, ftab->mechs);
286   } else return NULL;
287 }
288 
289 /*
290  * Class:     sun_security_jgss_wrapper_GSSLibStub
291  * Method:    inquireNamesForMech
292  * Signature: ()[Lorg/ietf/jgss/Oid;
293  */
294 JNIEXPORT jobjectArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_inquireNamesForMech(JNIEnv * env,jobject jobj)295 Java_sun_security_jgss_wrapper_GSSLibStub_inquireNamesForMech(JNIEnv *env,
296                                                               jobject jobj)
297 {
298   OM_uint32 minor, major;
299   gss_OID mech;
300   gss_OID_set nameTypes;
301   jobjectArray result;
302 
303   if (ftab->inquireNamesForMech != NULL) {
304     mech = (gss_OID)jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
305     nameTypes = GSS_C_NO_OID_SET;
306 
307     /* gss_inquire_names_for_mech(...) => N/A */
308     major = (*ftab->inquireNamesForMech)(&minor, mech, &nameTypes);
309 
310     /* release intermediate buffers before checking status */
311     result = getJavaOIDArray(env, nameTypes);
312     deleteGSSOIDSet(nameTypes);
313     if ((*env)->ExceptionCheck(env)) {
314       return NULL;
315     }
316 
317     checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireNamesForMech]");
318     if ((*env)->ExceptionCheck(env)) {
319       return NULL;
320     }
321     return result;
322   }
323   return NULL;
324 }
325 
326 /*
327  * Class:     sun_security_jgss_wrapper_GSSLibStub
328  * Method:    releaseName
329  * Signature: (J)V
330  */
331 JNIEXPORT void JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_releaseName(JNIEnv * env,jobject jobj,jlong pName)332 Java_sun_security_jgss_wrapper_GSSLibStub_releaseName(JNIEnv *env,
333                                                       jobject jobj,
334                                                       jlong pName)
335 {
336   OM_uint32 minor, major;
337   gss_name_t nameHdl;
338 
339   nameHdl = (gss_name_t) jlong_to_ptr(pName);
340 
341   TRACE1("[GSSLibStub_releaseName] %ld", (long) pName);
342 
343   if (nameHdl != GSS_C_NO_NAME) {
344     /* gss_release_name(...) => GSS_S_BAD_NAME */
345     major = (*ftab->releaseName)(&minor, &nameHdl);
346     checkStatus(env, jobj, major, minor, "[GSSLibStub_releaseName]");
347   }
348 }
349 
350 /*
351  * Class:     sun_security_jgss_wrapper_GSSLibStub
352  * Method:    importName
353  * Signature: ([BLorg/ietf/jgss/Oid;)J
354  */
355 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_importName(JNIEnv * env,jobject jobj,jbyteArray jnameVal,jobject jnameType)356 Java_sun_security_jgss_wrapper_GSSLibStub_importName(JNIEnv *env,
357                                                      jobject jobj,
358                                                      jbyteArray jnameVal,
359                                                      jobject jnameType)
360 {
361   OM_uint32 minor, major;
362   gss_buffer_desc nameVal;
363   gss_OID nameType;
364   gss_name_t nameHdl;
365   nameHdl = GSS_C_NO_NAME;
366 
367   TRACE0("[GSSLibStub_importName]");
368 
369   initGSSBuffer(env, jnameVal, &nameVal);
370   if ((*env)->ExceptionCheck(env)) {
371       return jlong_zero;
372   }
373 
374   nameType = newGSSOID(env, jnameType);
375   if ((*env)->ExceptionCheck(env)) {
376     resetGSSBuffer(&nameVal);
377     return jlong_zero;
378   }
379 
380   /* gss_import_name(...) => GSS_S_BAD_NAMETYPE, GSS_S_BAD_NAME,
381      GSS_S_BAD_MECH */
382   major = (*ftab->importName)(&minor, &nameVal, nameType, &nameHdl);
383 
384   TRACE1("[GSSLibStub_importName] %" PRIuPTR  "", (uintptr_t) nameHdl);
385 
386   /* release intermediate buffers */
387   deleteGSSOID(nameType);
388   resetGSSBuffer(&nameVal);
389 
390   checkStatus(env, jobj, major, minor, "[GSSLibStub_importName]");
391   if ((*env)->ExceptionCheck(env)) {
392     return jlong_zero;
393   }
394   return ptr_to_jlong(nameHdl);
395 }
396 
397 
398 /*
399  * Class:     sun_security_jgss_wrapper_GSSLibStub
400  * Method:    compareName
401  * Signature: (JJ)Z
402  */
403 JNIEXPORT jboolean JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_compareName(JNIEnv * env,jobject jobj,jlong pName1,jlong pName2)404 Java_sun_security_jgss_wrapper_GSSLibStub_compareName(JNIEnv *env,
405                                                       jobject jobj,
406                                                       jlong pName1,
407                                                       jlong pName2)
408 {
409   OM_uint32 minor, major;
410   gss_name_t nameHdl1, nameHdl2;
411   int isEqual;
412 
413   isEqual = 0;
414   nameHdl1 = (gss_name_t) jlong_to_ptr(pName1);
415   nameHdl2 = (gss_name_t) jlong_to_ptr(pName2);
416 
417   TRACE2("[GSSLibStub_compareName] %ld %ld", (long)pName1, (long)pName2);
418 
419   if ((nameHdl1 != GSS_C_NO_NAME) && (nameHdl2 != GSS_C_NO_NAME)) {
420 
421     /* gss_compare_name(...) => GSS_S_BAD_NAMETYPE, GSS_S_BAD_NAME(!) */
422     major = (*ftab->compareName)(&minor, nameHdl1, nameHdl2, &isEqual);
423 
424     checkStatus(env, jobj, major, minor, "[GSSLibStub_compareName]");
425   }
426   return (isEqual != 0);
427 }
428 
429 /*
430  * Class:     sun_security_jgss_wrapper_GSSLibStub
431  * Method:    canonicalizeName
432  * Signature: (J)J
433  */
434 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_canonicalizeName(JNIEnv * env,jobject jobj,jlong pName)435 Java_sun_security_jgss_wrapper_GSSLibStub_canonicalizeName(JNIEnv *env,
436                                                            jobject jobj,
437                                                            jlong pName)
438 {
439   OM_uint32 minor, major;
440   gss_name_t nameHdl, mnNameHdl;
441   gss_OID mech;
442 
443   nameHdl = (gss_name_t) jlong_to_ptr(pName);
444 
445   TRACE1("[GSSLibStub_canonicalizeName] %ld", (long) pName);
446 
447   if (nameHdl != GSS_C_NO_NAME) {
448     mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
449     mnNameHdl = GSS_C_NO_NAME;
450 
451     /* gss_canonicalize_name(...) may return GSS_S_BAD_NAMETYPE,
452        GSS_S_BAD_NAME, GSS_S_BAD_MECH */
453     major = (*ftab->canonicalizeName)(&minor, nameHdl, mech, &mnNameHdl);
454 
455     TRACE1("[GSSLibStub_canonicalizeName] MN=%" PRIuPTR "", (uintptr_t)mnNameHdl);
456 
457     checkStatus(env, jobj, major, minor, "[GSSLibStub_canonicalizeName]");
458     if ((*env)->ExceptionCheck(env)) {
459       return ptr_to_jlong(GSS_C_NO_NAME);
460     }
461     return ptr_to_jlong(mnNameHdl);
462   }
463   return ptr_to_jlong(GSS_C_NO_NAME);
464 }
465 
466 /*
467  * Class:     sun_security_jgss_wrapper_GSSLibStub
468  * Method:    exportName
469  * Signature: (J)[B
470  */
471 JNIEXPORT jbyteArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_exportName(JNIEnv * env,jobject jobj,jlong pName)472 Java_sun_security_jgss_wrapper_GSSLibStub_exportName(JNIEnv *env,
473                                                      jobject jobj,
474                                                      jlong pName) {
475   OM_uint32 minor, major;
476   gss_name_t nameHdl, mNameHdl;
477   gss_buffer_desc outBuf;
478   jbyteArray jresult;
479 
480   nameHdl = (gss_name_t) jlong_to_ptr(pName);
481 
482   TRACE1("[GSSLibStub_exportName] %ld", (long) pName);
483 
484   /* gss_export_name(...) => GSS_S_NAME_NOT_MN, GSS_S_BAD_NAMETYPE,
485      GSS_S_BAD_NAME */
486   major = (*ftab->exportName)(&minor, nameHdl, &outBuf);
487 
488   /* canonicalize the internal name to MN and retry */
489   if (major == GSS_S_NAME_NOT_MN) {
490     /* release intermediate buffers before retrying */
491     (*ftab->releaseBuffer)(&minor, &outBuf);
492 
493     TRACE0("[GSSLibStub_exportName] canonicalize and re-try");
494 
495     mNameHdl = (gss_name_t)jlong_to_ptr(
496         Java_sun_security_jgss_wrapper_GSSLibStub_canonicalizeName
497                                         (env, jobj, pName));
498     if ((*env)->ExceptionCheck(env)) {
499         return NULL;
500     }
501 
502     major = (*ftab->exportName)(&minor, mNameHdl, &outBuf);
503     Java_sun_security_jgss_wrapper_GSSLibStub_releaseName
504                                         (env, jobj, ptr_to_jlong(mNameHdl));
505     if ((*env)->ExceptionCheck(env)) {
506       /* release intermediate buffers */
507       (*ftab->releaseBuffer)(&minor, &outBuf);
508       return NULL;
509     }
510   }
511 
512   /* release intermediate buffers before checking status */
513   jresult = getJavaBuffer(env, &outBuf);
514   if ((*env)->ExceptionCheck(env)) {
515     return NULL;
516   }
517 
518   checkStatus(env, jobj, major, minor, "[GSSLibStub_exportName]");
519   if ((*env)->ExceptionCheck(env)) {
520     return NULL;
521   }
522   return jresult;
523 }
524 
525 /*
526  * Class:     sun_security_jgss_wrapper_GSSLibStub
527  * Method:    displayName
528  * Signature: (J)[Ljava/lang/Object;
529  */
530 JNIEXPORT jobjectArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_displayName(JNIEnv * env,jobject jobj,jlong pName)531 Java_sun_security_jgss_wrapper_GSSLibStub_displayName(JNIEnv *env,
532                                                       jobject jobj,
533                                                       jlong pName) {
534   OM_uint32 minor, major;
535   gss_name_t nameHdl;
536   gss_buffer_desc outNameBuf;
537   gss_OID outNameType;
538   jstring jname;
539   jobject jtype;
540   jobjectArray jresult;
541 
542   nameHdl = (gss_name_t) jlong_to_ptr(pName);
543 
544   TRACE1("[GSSLibStub_displayName] %ld", (long) pName);
545 
546   if (nameHdl == GSS_C_NO_NAME) {
547     checkStatus(env, jobj, GSS_S_BAD_NAME, 0, "[GSSLibStub_displayName]");
548     return NULL;
549   }
550 
551   /* gss_display_name(...) => GSS_S_BAD_NAME */
552   major = (*ftab->displayName)(&minor, nameHdl, &outNameBuf, &outNameType);
553 
554   /* release intermediate buffers before checking status */
555   jname = getJavaString(env, &outNameBuf);
556   if ((*env)->ExceptionCheck(env)) {
557     return NULL;
558   }
559 
560   checkStatus(env, jobj, major, minor, "[GSSLibStub_displayName]");
561   if ((*env)->ExceptionCheck(env)) {
562     return NULL;
563   }
564 
565   jtype = getJavaOID(env, outNameType);
566   if ((*env)->ExceptionCheck(env)) {
567     return NULL;
568   }
569 
570   jresult = (*env)->NewObjectArray(env, 2, CLS_Object, NULL);
571   /* return immediately if an exception has occurred */
572   if ((*env)->ExceptionCheck(env)) {
573     return NULL;
574   }
575 
576   (*env)->SetObjectArrayElement(env, jresult, 0, jname);
577   if ((*env)->ExceptionCheck(env)) {
578     return NULL;
579   }
580   (*env)->SetObjectArrayElement(env, jresult, 1, jtype);
581   if ((*env)->ExceptionCheck(env)) {
582     return NULL;
583   }
584 
585   return jresult;
586 }
587 
588 /*
589  * Class:     sun_security_jgss_wrapper_GSSLibStub
590  * Method:    acquireCred
591  * Signature: (JII)J
592  */
593 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_acquireCred(JNIEnv * env,jobject jobj,jlong pName,jint reqTime,jint usage)594 Java_sun_security_jgss_wrapper_GSSLibStub_acquireCred(JNIEnv *env,
595                                                       jobject jobj,
596                                                       jlong pName,
597                                                       jint reqTime,
598                                                       jint usage)
599 {
600   OM_uint32 minor, major;
601   gss_OID mech;
602   gss_OID_set mechs;
603   gss_cred_usage_t credUsage;
604   gss_name_t nameHdl;
605   gss_cred_id_t credHdl;
606   credHdl = GSS_C_NO_CREDENTIAL;
607 
608   TRACE0("[GSSLibStub_acquireCred]");
609 
610   mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
611   mechs = newGSSOIDSet(mech);
612   credUsage = (gss_cred_usage_t) usage;
613   nameHdl = (gss_name_t) jlong_to_ptr(pName);
614 
615   TRACE2("[GSSLibStub_acquireCred] pName=%ld, usage=%d", (long)pName, usage);
616 
617   /* gss_acquire_cred(...) => GSS_S_BAD_MECH, GSS_S_BAD_NAMETYPE,
618      GSS_S_BAD_NAME, GSS_S_CREDENTIALS_EXPIRED, GSS_S_NO_CRED */
619   major =
620     (*ftab->acquireCred)(&minor, nameHdl, reqTime, mechs,
621                      credUsage, &credHdl, NULL, NULL);
622   /* release intermediate buffers */
623   deleteGSSOIDSet(mechs);
624 
625   TRACE1("[GSSLibStub_acquireCred] pCred=%" PRIuPTR "", (uintptr_t) credHdl);
626 
627   checkStatus(env, jobj, major, minor, "[GSSLibStub_acquireCred]");
628   if ((*env)->ExceptionCheck(env)) {
629     return jlong_zero;
630   }
631   return ptr_to_jlong(credHdl);
632 }
633 
634 /*
635  * Class:     sun_security_jgss_wrapper_GSSLibStub
636  * Method:    releaseCred
637  * Signature: (J)J
638  */
639 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_releaseCred(JNIEnv * env,jobject jobj,jlong pCred)640 Java_sun_security_jgss_wrapper_GSSLibStub_releaseCred(JNIEnv *env,
641                                                       jobject jobj,
642                                                       jlong pCred)
643 {
644   OM_uint32 minor, major;
645   gss_cred_id_t credHdl;
646 
647   credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
648 
649   TRACE1("[GSSLibStub_releaseCred] %ld", (long int)pCred);
650 
651   if (credHdl != GSS_C_NO_CREDENTIAL) {
652     /* gss_release_cred(...) => GSS_S_NO_CRED(!) */
653     major = (*ftab->releaseCred)(&minor, &credHdl);
654 
655     checkStatus(env, jobj, major, minor, "[GSSLibStub_releaseCred]");
656     if ((*env)->ExceptionCheck(env)) {
657       return jlong_zero;
658     }
659   }
660   return ptr_to_jlong(credHdl);
661 }
662 
663 /*
664  * Utility routine for obtaining info about a credential.
665  */
inquireCred(JNIEnv * env,jobject jobj,gss_cred_id_t pCred,jint type,void * result)666 void inquireCred(JNIEnv *env, jobject jobj, gss_cred_id_t pCred,
667                  jint type, void *result) {
668   OM_uint32 minor=0, major=0;
669   OM_uint32 routineErr;
670   gss_cred_id_t credHdl;
671 
672   credHdl = pCred;
673 
674   TRACE1("[gss_inquire_cred] %" PRIuPTR "", (uintptr_t) pCred);
675 
676   /* gss_inquire_cred(...) => GSS_S_DEFECTIVE_CREDENTIAL(!),
677      GSS_S_CREDENTIALS_EXPIRED(!), GSS_S_NO_CRED(!) */
678   if (type == TYPE_CRED_NAME) {
679     major = (*ftab->inquireCred)(&minor, credHdl, result, NULL, NULL, NULL);
680   } else if (type == TYPE_CRED_TIME) {
681     major = (*ftab->inquireCred)(&minor, credHdl, NULL, result, NULL, NULL);
682   } else if (type == TYPE_CRED_USAGE) {
683     major = (*ftab->inquireCred)(&minor, credHdl, NULL, NULL, result, NULL);
684   }
685 
686   routineErr = GSS_ROUTINE_ERROR(major);
687   if (routineErr == GSS_S_CREDENTIALS_EXPIRED) {
688     /* ignore GSS_S_CREDENTIALS_EXPIRED for query  */
689     major = GSS_CALLING_ERROR(major) |
690       GSS_SUPPLEMENTARY_INFO(major);
691   } else if (routineErr == GSS_S_NO_CRED) {
692     /* twik since Java API throws BAD_MECH instead of NO_CRED */
693     major = GSS_CALLING_ERROR(major) |
694       GSS_S_BAD_MECH  | GSS_SUPPLEMENTARY_INFO(major);
695   }
696   checkStatus(env, jobj, major, minor, "[gss_inquire_cred]");
697 }
698 
699 /*
700  * Class:     sun_security_jgss_wrapper_GSSLibStub
701  * Method:    getCredName
702  * Signature: (J)J
703  */
704 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getCredName(JNIEnv * env,jobject jobj,jlong pCred)705 Java_sun_security_jgss_wrapper_GSSLibStub_getCredName(JNIEnv *env,
706                                                       jobject jobj,
707                                                       jlong pCred)
708 {
709   gss_name_t nameHdl;
710   gss_cred_id_t credHdl;
711 
712   credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
713 
714   TRACE1("[GSSLibStub_getCredName] %ld", (long int)pCred);
715 
716   nameHdl = GSS_C_NO_NAME;
717   inquireCred(env, jobj, credHdl, TYPE_CRED_NAME, &nameHdl);
718   /* return immediately if an exception has occurred */
719   if ((*env)->ExceptionCheck(env)) {
720     return jlong_zero;
721   }
722 
723   TRACE1("[GSSLibStub_getCredName] pName=%" PRIuPTR "", (uintptr_t) nameHdl);
724   return ptr_to_jlong(nameHdl);
725 }
726 
727 /*
728  * Class:     sun_security_jgss_wrapper_GSSLibStub
729  * Method:    getCredTime
730  * Signature: (J)I
731  */
732 JNIEXPORT jint JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getCredTime(JNIEnv * env,jobject jobj,jlong pCred)733 Java_sun_security_jgss_wrapper_GSSLibStub_getCredTime(JNIEnv *env,
734                                                       jobject jobj,
735                                                       jlong pCred)
736 {
737   gss_cred_id_t credHdl;
738   OM_uint32 lifetime;
739 
740   credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
741 
742   TRACE1("[GSSLibStub_getCredTime] %ld", (long int)pCred);
743 
744   lifetime = 0;
745   inquireCred(env, jobj, credHdl, TYPE_CRED_TIME, &lifetime);
746   /* return immediately if an exception has occurred */
747   if ((*env)->ExceptionCheck(env)) {
748     return 0;
749   }
750   return getJavaTime(lifetime);
751 }
752 
753 /*
754  * Class:     sun_security_jgss_wrapper_GSSLibStub
755  * Method:    getCredUsage
756  * Signature: (J)I
757  */
758 JNIEXPORT jint JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getCredUsage(JNIEnv * env,jobject jobj,jlong pCred)759 Java_sun_security_jgss_wrapper_GSSLibStub_getCredUsage(JNIEnv *env,
760                                                        jobject jobj,
761                                                        jlong pCred)
762 {
763   gss_cred_usage_t usage;
764   gss_cred_id_t credHdl;
765 
766   credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
767 
768   TRACE1("[GSSLibStub_getCredUsage] %ld", (long int)pCred);
769 
770   inquireCred(env, jobj, credHdl, TYPE_CRED_USAGE, &usage);
771   /* return immediately if an exception has occurred */
772   if ((*env)->ExceptionCheck(env)) {
773     return -1;
774   }
775   return (jint) usage;
776 }
777 /*
778  * Class:     sun_security_jgss_wrapper_GSSLibStub
779  * Method:    importContext
780  * Signature: ([B)Lsun/security/jgss/wrapper/NativeGSSContext;
781  */
782 JNIEXPORT jobject JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_importContext(JNIEnv * env,jobject jobj,jbyteArray jctxtToken)783 Java_sun_security_jgss_wrapper_GSSLibStub_importContext(JNIEnv *env,
784                                                         jobject jobj,
785                                                         jbyteArray jctxtToken)
786 {
787   OM_uint32 minor, major;
788   gss_buffer_desc ctxtToken;
789   gss_ctx_id_t contextHdl;
790   gss_OID mech, mech2;
791 
792   TRACE0("[GSSLibStub_importContext]");
793 
794   contextHdl = GSS_C_NO_CONTEXT;
795   initGSSBuffer(env, jctxtToken, &ctxtToken);
796   if ((*env)->ExceptionCheck(env)) {
797     return NULL;
798   }
799 
800   /* gss_import_sec_context(...) => GSS_S_NO_CONTEXT, GSS_S_DEFECTIVE_TOKEN,
801      GSS_S_UNAVAILABLE, GSS_S_UNAUTHORIZED */
802   major = (*ftab->importSecContext)(&minor, &ctxtToken, &contextHdl);
803 
804   TRACE1("[GSSLibStub_importContext] pContext=%" PRIuPTR "", (uintptr_t) contextHdl);
805 
806   /* release intermediate buffers */
807   resetGSSBuffer(&ctxtToken);
808 
809   checkStatus(env, jobj, major, minor, "[GSSLibStub_importContext]");
810   /* return immediately if an exception has occurred */
811   if ((*env)->ExceptionCheck(env)) {
812     return NULL;
813   }
814 
815   /* now that the context has been imported, proceed to find out
816      its mech */
817   major = (*ftab->inquireContext)(&minor, contextHdl, NULL, NULL,
818                               NULL, &mech, NULL, NULL, NULL);
819 
820   checkStatus(env, jobj, major, minor, "[GSSLibStub_importContext] getMech");
821   /* return immediately if an exception has occurred */
822   if ((*env)->ExceptionCheck(env)) {
823     return NULL;
824   }
825 
826   mech2 = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj,
827       FID_GSSLibStub_pMech));
828 
829   if (sameMech(mech, mech2) == JNI_TRUE) {
830     /* mech match - return the context object */
831     return (*env)->NewObject(env, CLS_NativeGSSContext,
832                                  MID_NativeGSSContext_ctor,
833                                  ptr_to_jlong(contextHdl), jobj);
834   } else {
835     /* mech mismatch - clean up then return null */
836     major = (*ftab->deleteSecContext)(&minor, &contextHdl, GSS_C_NO_BUFFER);
837     checkStatus(env, jobj, major, minor,
838         "[GSSLibStub_importContext] cleanup");
839     return NULL;
840   }
841 }
842 
843 /*
844  * Class:     sun_security_jgss_wrapper_GSSLibStub
845  * Method:    initContext
846  * Signature: (JJLorg/ietf/jgss/ChannelBinding;[BLsun/security/jgss/wrapper/NativeGSSContext;)[B
847  */
848 JNIEXPORT jbyteArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_initContext(JNIEnv * env,jobject jobj,jlong pCred,jlong pName,jobject jcb,jbyteArray jinToken,jobject jcontextSpi)849 Java_sun_security_jgss_wrapper_GSSLibStub_initContext(JNIEnv *env,
850                                                       jobject jobj,
851                                                       jlong pCred,
852                                                       jlong pName,
853                                                       jobject jcb,
854                                                       jbyteArray jinToken,
855                                                       jobject jcontextSpi)
856 {
857   OM_uint32 minor, major;
858   gss_cred_id_t credHdl ;
859   gss_ctx_id_t contextHdl, contextHdlSave;
860   gss_name_t targetName;
861   gss_OID mech;
862   OM_uint32 flags, aFlags;
863   OM_uint32 time, aTime;
864   gss_channel_bindings_t cb;
865   gss_buffer_desc inToken;
866   gss_buffer_desc outToken;
867   jbyteArray jresult;
868 /* UNCOMMENT after SEAM bug#6287358 is backported to S10
869   gss_OID aMech;
870   jobject jMech;
871 */
872 
873   TRACE0("[GSSLibStub_initContext]");
874 
875   credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
876   contextHdl = contextHdlSave = (gss_ctx_id_t) jlong_to_ptr(
877     (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext));
878   targetName = (gss_name_t) jlong_to_ptr(pName);
879   mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
880   flags = (OM_uint32) (*env)->GetIntField(env, jcontextSpi,
881                                           FID_NativeGSSContext_flags);
882   time = getGSSTime((*env)->GetIntField(env, jcontextSpi,
883                                         FID_NativeGSSContext_lifetime));
884   cb = newGSSCB(env, jcb);
885   if ((*env)->ExceptionCheck(env)) {
886     return NULL;
887   }
888 
889   initGSSBuffer(env, jinToken, &inToken);
890   if ((*env)->ExceptionCheck(env)) {
891     deleteGSSCB(cb);
892     return NULL;
893   }
894 
895   TRACE2( "[GSSLibStub_initContext] before: pCred=%" PRIuPTR ", pContext=%" PRIuPTR "",
896           (uintptr_t)credHdl, (uintptr_t)contextHdl);
897 
898   /* gss_init_sec_context(...) => GSS_S_CONTINUE_NEEDED(!),
899      GSS_S_DEFECTIVE_TOKEN, GSS_S_NO_CRED, GSS_S_DEFECTIVE_CREDENTIAL(!),
900      GSS_S_CREDENTIALS_EXPIRED, GSS_S_BAD_BINDINGS, GSS_S_BAD_MIC,
901      GSS_S_OLD_TOKEN, GSS_S_DUPLICATE_TOKEN, GSS_S_NO_CONTEXT(!),
902      GSS_S_BAD_NAMETYPE, GSS_S_BAD_NAME(!), GSS_S_BAD_MECH */
903   major = (*ftab->initSecContext)(&minor, credHdl,
904                                  &contextHdl, targetName, mech,
905                                  flags, time, cb, &inToken, NULL /*aMech*/,
906                                  &outToken, &aFlags, &aTime);
907 
908   TRACE2("[GSSLibStub_initContext] after: pContext=%" PRIuPTR ", outToken len=%ld",
909             (uintptr_t)contextHdl, (long)outToken.length);
910 
911   // update context handle with the latest value if changed
912   // this is to work with both MIT and Solaris. Former deletes half-built
913   // context if error occurs
914   if (contextHdl != contextHdlSave) {
915     (*env)->SetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext,
916                          ptr_to_jlong(contextHdl));
917     TRACE1("[GSSLibStub_initContext] set pContext=%" PRIuPTR "", (uintptr_t)contextHdl);
918   }
919 
920   if (GSS_ERROR(major) == GSS_S_COMPLETE) {
921     /* update member values if needed */
922     (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_flags, aFlags);
923     TRACE1("[GSSLibStub_initContext] set flags=0x%x", aFlags);
924 
925     if (major == GSS_S_COMPLETE) {
926       (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_lifetime,
927                           getJavaTime(aTime));
928       TRACE0("[GSSLibStub_initContext] context established");
929 
930       (*env)->SetBooleanField(env, jcontextSpi,
931                               FID_NativeGSSContext_isEstablished,
932                               JNI_TRUE);
933 
934 /* UNCOMMENT after SEAM bug#6287358 is backported to S10
935       jMech = getJavaOID(env, aMech);
936       (*env)->SetObjectField(env, jcontextSpi,
937                              FID_NativeGSSContext_actualMech, jMech);
938 */
939     } else if (major & GSS_S_CONTINUE_NEEDED) {
940       TRACE0("[GSSLibStub_initContext] context not established");
941       major -= GSS_S_CONTINUE_NEEDED;
942     }
943   }
944 
945   /* release intermediate buffers before checking status */
946   deleteGSSCB(cb);
947   resetGSSBuffer(&inToken);
948   jresult = getJavaBuffer(env, &outToken);
949   if ((*env)->ExceptionCheck(env)) {
950     return NULL;
951   }
952 
953   checkStatus(env, jobj, major, minor, "[GSSLibStub_initContext]");
954   if ((*env)->ExceptionCheck(env)) {
955     return NULL;
956   }
957   return jresult;
958 }
959 
960 /*
961  * Class:     sun_security_jgss_wrapper_GSSLibStub
962  * Method:    acceptContext
963  * Signature: (JLorg/ietf/jgss/ChannelBinding;[BLsun/security/jgss/wrapper/NativeGSSContext;)[B
964  */
965 JNIEXPORT jbyteArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_acceptContext(JNIEnv * env,jobject jobj,jlong pCred,jobject jcb,jbyteArray jinToken,jobject jcontextSpi)966 Java_sun_security_jgss_wrapper_GSSLibStub_acceptContext(JNIEnv *env,
967                                                         jobject jobj,
968                                                         jlong pCred,
969                                                         jobject jcb,
970                                                         jbyteArray jinToken,
971                                                         jobject jcontextSpi)
972 {
973   OM_uint32 minor, major;
974   OM_uint32 minor2, major2;
975   gss_ctx_id_t contextHdl, contextHdlSave;
976   gss_cred_id_t credHdl;
977   gss_buffer_desc inToken;
978   gss_channel_bindings_t cb;
979   gss_name_t srcName;
980   gss_buffer_desc outToken;
981   gss_OID aMech;
982   OM_uint32 aFlags;
983   OM_uint32 aTime;
984   gss_cred_id_t delCred;
985   jobject jsrcName=GSS_C_NO_NAME;
986   jobject jdelCred;
987   jobject jMech;
988   jboolean setTarget;
989   gss_name_t targetName;
990   jobject jtargetName;
991 
992   TRACE0("[GSSLibStub_acceptContext]");
993 
994   contextHdl = contextHdlSave = (gss_ctx_id_t)jlong_to_ptr(
995     (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext));
996   credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
997   initGSSBuffer(env, jinToken, &inToken);
998   if ((*env)->ExceptionCheck(env)) {
999     return NULL;
1000   }
1001   cb = newGSSCB(env, jcb);
1002   if ((*env)->ExceptionCheck(env)) {
1003     resetGSSBuffer(&inToken);
1004     return NULL;
1005   }
1006   srcName = targetName = GSS_C_NO_NAME;
1007   delCred = GSS_C_NO_CREDENTIAL;
1008   setTarget = (credHdl == GSS_C_NO_CREDENTIAL);
1009   aFlags = 0;
1010 
1011   TRACE2( "[GSSLibStub_acceptContext] before: pCred=%" PRIuPTR ", pContext=%" PRIuPTR "",
1012           (uintptr_t) credHdl, (uintptr_t) contextHdl);
1013 
1014   /* gss_accept_sec_context(...) => GSS_S_CONTINUE_NEEDED(!),
1015      GSS_S_DEFECTIVE_TOKEN, GSS_S_DEFECTIVE_CREDENTIAL(!),
1016      GSS_S_NO_CRED, GSS_S_CREDENTIALS_EXPIRED, GSS_S_BAD_BINDINGS,
1017      GSS_S_NO_CONTEXT(!), GSS_S_BAD_MIC, GSS_S_OLD_TOKEN,
1018      GSS_S_DUPLICATE_TOKEN, GSS_S_BAD_MECH */
1019   major =
1020     (*ftab->acceptSecContext)(&minor, &contextHdl, credHdl,
1021                            &inToken, cb, &srcName, &aMech, &outToken,
1022                            &aFlags, &aTime, &delCred);
1023   /* release intermediate buffers before checking status */
1024 
1025   deleteGSSCB(cb);
1026   resetGSSBuffer(&inToken);
1027 
1028   TRACE3("[GSSLibStub_acceptContext] after: pCred=%" PRIuPTR ", pContext=%" PRIuPTR ", pDelegCred=%" PRIuPTR "",
1029         (uintptr_t)credHdl, (uintptr_t)contextHdl, (uintptr_t) delCred);
1030 
1031   // update context handle with the latest value if changed
1032   // this is to work with both MIT and Solaris. Former deletes half-built
1033   // context if error occurs
1034   if (contextHdl != contextHdlSave) {
1035     (*env)->SetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext,
1036                          ptr_to_jlong(contextHdl));
1037     TRACE1("[GSSLibStub_acceptContext] set pContext=%" PRIuPTR "", (uintptr_t)contextHdl);
1038   }
1039 
1040   if (GSS_ERROR(major) == GSS_S_COMPLETE) {
1041     /* update member values if needed */
1042     // WORKAROUND for a Heimdal bug
1043     if (delCred == GSS_C_NO_CREDENTIAL) {
1044         aFlags &= 0xfffffffe;
1045     }
1046     (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_flags, aFlags);
1047     TRACE1("[GSSLibStub_acceptContext] set flags=0x%x", aFlags);
1048 
1049     if (setTarget) {
1050       major2 = (*ftab->inquireContext)(&minor2, contextHdl, NULL,
1051                               &targetName, NULL, NULL, NULL,
1052                               NULL, NULL);
1053       checkStatus(env, jobj, major2, minor2,
1054                     "[GSSLibStub_acceptContext] inquire");
1055       if ((*env)->ExceptionCheck(env)) {
1056          goto error;
1057       }
1058 
1059       jtargetName = (*env)->NewObject(env, CLS_GSSNameElement,
1060                                 MID_GSSNameElement_ctor,
1061                                 ptr_to_jlong(targetName), jobj);
1062       if ((*env)->ExceptionCheck(env)) {
1063         goto error;
1064       }
1065 
1066       TRACE1("[GSSLibStub_acceptContext] set targetName=%" PRIuPTR "",
1067               (uintptr_t)targetName);
1068 
1069       (*env)->SetObjectField(env, jcontextSpi, FID_NativeGSSContext_targetName,
1070                              jtargetName);
1071       if ((*env)->ExceptionCheck(env)) {
1072         goto error;
1073       }
1074     }
1075     if (srcName != GSS_C_NO_NAME) {
1076       jsrcName = (*env)->NewObject(env, CLS_GSSNameElement,
1077                                    MID_GSSNameElement_ctor,
1078                                    ptr_to_jlong(srcName), jobj);
1079       if ((*env)->ExceptionCheck(env)) {
1080         goto error;
1081       }
1082 
1083       TRACE1("[GSSLibStub_acceptContext] set srcName=%" PRIuPTR "", (uintptr_t)srcName);
1084 
1085       (*env)->SetObjectField(env, jcontextSpi, FID_NativeGSSContext_srcName,
1086                              jsrcName);
1087       if ((*env)->ExceptionCheck(env)) {
1088         goto error;
1089       }
1090     }
1091     if (major == GSS_S_COMPLETE) {
1092       TRACE0("[GSSLibStub_acceptContext] context established");
1093 
1094       (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_lifetime,
1095                           getJavaTime(aTime));
1096       (*env)->SetBooleanField(env, jcontextSpi,
1097                               FID_NativeGSSContext_isEstablished,
1098                               JNI_TRUE);
1099       jMech = getJavaOID(env, aMech);
1100       if ((*env)->ExceptionCheck(env)) {
1101         goto error;
1102       }
1103       (*env)->SetObjectField(env, jcontextSpi,
1104                              FID_NativeGSSContext_actualMech, jMech);
1105       if ((*env)->ExceptionCheck(env)) {
1106         goto error;
1107       }
1108       if (delCred != GSS_C_NO_CREDENTIAL) {
1109         jdelCred = (*env)->NewObject(env, CLS_GSSCredElement,
1110                                      MID_GSSCredElement_ctor,
1111                                      ptr_to_jlong(delCred), jsrcName, jMech);
1112         if ((*env)->ExceptionCheck(env)) {
1113           goto error;
1114         }
1115         (*env)->SetObjectField(env, jcontextSpi,
1116                                FID_NativeGSSContext_delegatedCred,
1117                                jdelCred);
1118         TRACE1("[GSSLibStub_acceptContext] set delegatedCred=%" PRIuPTR "",
1119                 (uintptr_t) delCred);
1120 
1121         if ((*env)->ExceptionCheck(env)) {
1122           goto error;
1123         }
1124       }
1125     } else if (major & GSS_S_CONTINUE_NEEDED) {
1126       TRACE0("[GSSLibStub_acceptContext] context not established");
1127 
1128       if (aFlags & GSS_C_PROT_READY_FLAG) {
1129         (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_lifetime,
1130                             getJavaTime(aTime));
1131       }
1132       major -= GSS_S_CONTINUE_NEEDED;
1133     }
1134   }
1135   return getJavaBuffer(env, &outToken);
1136 
1137 error:
1138   (*ftab->releaseBuffer)(&minor, &outToken);
1139   if (srcName != GSS_C_NO_NAME) {
1140     (*ftab->releaseName)(&minor, &srcName);
1141   }
1142   if (targetName != GSS_C_NO_NAME) {
1143     (*ftab->releaseName)(&minor, &targetName);
1144   }
1145   if (delCred != GSS_C_NO_CREDENTIAL) {
1146     (*ftab->releaseCred) (&minor, &delCred);
1147   }
1148   return NULL;
1149 }
1150 
1151 /*
1152  * Class:     sun_security_jgss_wrapper_GSSLibStub
1153  * Method:    inquireContext
1154  * Signature: (J)[J
1155  */
1156 JNIEXPORT jlongArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_inquireContext(JNIEnv * env,jobject jobj,jlong pContext)1157 Java_sun_security_jgss_wrapper_GSSLibStub_inquireContext(JNIEnv *env,
1158                                                          jobject jobj,
1159                                                          jlong pContext)
1160 {
1161   OM_uint32 minor, major;
1162   gss_ctx_id_t contextHdl;
1163   gss_name_t srcName, targetName;
1164   OM_uint32 time;
1165   OM_uint32 flags;
1166   int isInitiator, isEstablished;
1167   jlong result[6];
1168   jlongArray jresult;
1169 
1170   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1171 
1172   TRACE1("[GSSLibStub_inquireContext] %" PRIuPTR "", (uintptr_t)contextHdl);
1173 
1174   srcName = targetName = GSS_C_NO_NAME;
1175   time = 0;
1176   flags = isInitiator = isEstablished = 0;
1177 
1178   /* gss_inquire_context(...) => GSS_S_NO_CONTEXT(!) */
1179   major = (*ftab->inquireContext)(&minor, contextHdl, &srcName,
1180                               &targetName, &time, NULL, &flags,
1181                               &isInitiator, &isEstablished);
1182   /* update member values if needed */
1183   TRACE2("[GSSLibStub_inquireContext] srcName %" PRIuPTR ", targetName %" PRIuPTR "",
1184       (uintptr_t)srcName, (uintptr_t)targetName);
1185 
1186   checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireContext]");
1187   if ((*env)->ExceptionCheck(env)) {
1188     return NULL;
1189   }
1190   result[0] = ptr_to_jlong(srcName);
1191   result[1] = ptr_to_jlong(targetName);
1192   result[2] = (jlong) isInitiator;
1193   result[3] = (jlong) isEstablished;
1194   result[4] = (jlong) flags;
1195   result[5] = (jlong) getJavaTime(time);
1196 
1197   jresult = (*env)->NewLongArray(env, 6);
1198   if (jresult == NULL) {
1199     return NULL;
1200   }
1201   (*env)->SetLongArrayRegion(env, jresult, 0, 6, result);
1202   if ((*env)->ExceptionCheck(env)) {
1203     return NULL;
1204   }
1205   return jresult;
1206 }
1207 
1208 /*
1209  * Class:     sun_security_jgss_wrapper_GSSLibStub
1210  * Method:    getContextMech
1211  * Signature: (J)Lorg/ietf/jgss/Oid;
1212  */
1213 JNIEXPORT jobject JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getContextMech(JNIEnv * env,jobject jobj,jlong pContext)1214 Java_sun_security_jgss_wrapper_GSSLibStub_getContextMech(JNIEnv *env,
1215                                                          jobject jobj,
1216                                                          jlong pContext)
1217 {
1218   OM_uint32 minor, major;
1219   gss_OID mech;
1220   gss_ctx_id_t contextHdl;
1221 
1222   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1223 
1224   TRACE1("[GSSLibStub_getContextMech] %ld", (long int)pContext);
1225 
1226   major = (*ftab->inquireContext)(&minor, contextHdl, NULL, NULL,
1227                                 NULL, &mech, NULL,  NULL, NULL);
1228 
1229   checkStatus(env, jobj, major, minor, "[GSSLibStub_getContextMech]");
1230   /* return immediately if an exception has occurred */
1231   if ((*env)->ExceptionCheck(env)) {
1232     return NULL;
1233   }
1234 
1235   return getJavaOID(env, mech);
1236 }
1237 
1238 /*
1239  * Class:     sun_security_jgss_wrapper_GSSLibStub
1240  * Method:    getContextName
1241  * Signature: (JZ)J
1242  */
1243 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getContextName(JNIEnv * env,jobject jobj,jlong pContext,jboolean isSrc)1244 Java_sun_security_jgss_wrapper_GSSLibStub_getContextName(JNIEnv *env,
1245   jobject jobj, jlong pContext, jboolean isSrc)
1246 {
1247   OM_uint32 minor, major;
1248   gss_name_t nameHdl;
1249   gss_ctx_id_t contextHdl;
1250 
1251   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1252 
1253   TRACE2("[GSSLibStub_getContextName] %" PRIuPTR ", isSrc=%d",
1254           (uintptr_t)contextHdl, isSrc);
1255 
1256   nameHdl = GSS_C_NO_NAME;
1257   if (isSrc == JNI_TRUE) {
1258     major = (*ftab->inquireContext)(&minor, contextHdl, &nameHdl, NULL,
1259                                 NULL, NULL, NULL,  NULL, NULL);
1260   } else {
1261     major = (*ftab->inquireContext)(&minor, contextHdl, NULL, &nameHdl,
1262                                 NULL, NULL, NULL,  NULL, NULL);
1263   }
1264 
1265   checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireContextAll]");
1266   /* return immediately if an exception has occurred */
1267   if ((*env)->ExceptionCheck(env)) {
1268     return jlong_zero;
1269   }
1270 
1271   TRACE1("[GSSLibStub_getContextName] pName=%" PRIuPTR "", (uintptr_t) nameHdl);
1272 
1273   return ptr_to_jlong(nameHdl);
1274 }
1275 
1276 /*
1277  * Class:     sun_security_jgss_wrapper_GSSLibStub
1278  * Method:    getContextTime
1279  * Signature: (J)I
1280  */
1281 JNIEXPORT jint JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getContextTime(JNIEnv * env,jobject jobj,jlong pContext)1282 Java_sun_security_jgss_wrapper_GSSLibStub_getContextTime(JNIEnv *env,
1283                                                          jobject jobj,
1284                                                          jlong pContext) {
1285   OM_uint32 minor, major;
1286   gss_ctx_id_t contextHdl;
1287   OM_uint32 time;
1288 
1289   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1290 
1291   TRACE1("[GSSLibStub_getContextTime] %" PRIuPTR "", (uintptr_t)contextHdl);
1292 
1293   if (contextHdl == GSS_C_NO_CONTEXT) return 0;
1294 
1295   /* gss_context_time(...) => GSS_S_CONTEXT_EXPIRED(!),
1296      GSS_S_NO_CONTEXT(!) */
1297   major = (*ftab->contextTime)(&minor, contextHdl, &time);
1298   if (GSS_ROUTINE_ERROR(major) == GSS_S_CONTEXT_EXPIRED) {
1299     major = GSS_CALLING_ERROR(major) | GSS_SUPPLEMENTARY_INFO(major);
1300   }
1301   checkStatus(env, jobj, major, minor, "[GSSLibStub_getContextTime]");
1302   if ((*env)->ExceptionCheck(env)) {
1303     return 0;
1304   }
1305   return getJavaTime(time);
1306 }
1307 
1308 /*
1309  * Class:     sun_security_jgss_wrapper_GSSLibStub
1310  * Method:    deleteContext
1311  * Signature: (J)J
1312  */
1313 JNIEXPORT jlong JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_deleteContext(JNIEnv * env,jobject jobj,jlong pContext)1314 Java_sun_security_jgss_wrapper_GSSLibStub_deleteContext(JNIEnv *env,
1315                                                         jobject jobj,
1316                                                         jlong pContext)
1317 {
1318   OM_uint32 minor, major;
1319   gss_ctx_id_t contextHdl;
1320 
1321   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1322 
1323   TRACE1("[GSSLibStub_deleteContext] %" PRIuPTR "", (uintptr_t)contextHdl);
1324 
1325   if (contextHdl == GSS_C_NO_CONTEXT) return ptr_to_jlong(GSS_C_NO_CONTEXT);
1326 
1327   /* gss_delete_sec_context(...) => GSS_S_NO_CONTEXT(!) */
1328   major = (*ftab->deleteSecContext)(&minor, &contextHdl, GSS_C_NO_BUFFER);
1329 
1330   checkStatus(env, jobj, major, minor, "[GSSLibStub_deleteContext]");
1331   if ((*env)->ExceptionCheck(env)) {
1332     return jlong_zero;
1333   }
1334   return (jlong) ptr_to_jlong(contextHdl);
1335 }
1336 
1337 /*
1338  * Class:     sun_security_jgss_wrapper_GSSLibStub
1339  * Method:    wrapSizeLimit
1340  * Signature: (JIII)I
1341  */
1342 JNIEXPORT jint JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_wrapSizeLimit(JNIEnv * env,jobject jobj,jlong pContext,jint reqFlag,jint jqop,jint joutSize)1343 Java_sun_security_jgss_wrapper_GSSLibStub_wrapSizeLimit(JNIEnv *env,
1344                                                         jobject jobj,
1345                                                         jlong pContext,
1346                                                         jint reqFlag,
1347                                                         jint jqop,
1348                                                         jint joutSize)
1349 {
1350   OM_uint32 minor, major;
1351   gss_ctx_id_t contextHdl;
1352   OM_uint32 outSize, maxInSize;
1353   gss_qop_t qop;
1354 
1355   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1356 
1357   TRACE1("[GSSLibStub_wrapSizeLimit] %" PRIuPTR "", (uintptr_t)contextHdl);
1358 
1359   if (contextHdl == GSS_C_NO_CONTEXT) {
1360     // Twik per javadoc
1361     checkStatus(env, jobj, GSS_S_NO_CONTEXT, 0,
1362         "[GSSLibStub_wrapSizeLimit]");
1363     return 0;
1364   }
1365 
1366   qop = (gss_qop_t) jqop;
1367   outSize = (OM_uint32) joutSize;
1368   /* gss_wrap_size_limit(...) => GSS_S_NO_CONTEXT(!), GSS_S_CONTEXT_EXPIRED,
1369      GSS_S_BAD_QOP */
1370   major = (*ftab->wrapSizeLimit)(&minor, contextHdl, reqFlag,
1371                               qop, outSize, &maxInSize);
1372 
1373   checkStatus(env, jobj, major, minor, "[GSSLibStub_wrapSizeLimit]");
1374   if ((*env)->ExceptionCheck(env)) {
1375     return 0;
1376   }
1377   return (jint) maxInSize;
1378 }
1379 
1380 /*
1381  * Class:     sun_security_jgss_wrapper_GSSLibStub
1382  * Method:    exportContext
1383  * Signature: (J)[B
1384  */
1385 JNIEXPORT jbyteArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_exportContext(JNIEnv * env,jobject jobj,jlong pContext)1386 Java_sun_security_jgss_wrapper_GSSLibStub_exportContext(JNIEnv *env,
1387                                                         jobject jobj,
1388                                                         jlong pContext)
1389 {
1390   OM_uint32 minor, major;
1391   gss_ctx_id_t contextHdl;
1392   gss_buffer_desc interProcToken;
1393   jbyteArray jresult;
1394 
1395   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1396 
1397   TRACE1("[GSSLibStub_exportContext] %" PRIuPTR "", (uintptr_t)contextHdl);
1398 
1399   if (contextHdl == GSS_C_NO_CONTEXT) {
1400     // Twik per javadoc
1401     checkStatus(env, jobj, GSS_S_NO_CONTEXT, 0, "[GSSLibStub_exportContext]");
1402     return NULL;
1403   }
1404   /* gss_export_sec_context(...) => GSS_S_CONTEXT_EXPIRED,
1405      GSS_S_NO_CONTEXT, GSS_S_UNAVAILABLE */
1406   major =
1407     (*ftab->exportSecContext)(&minor, &contextHdl, &interProcToken);
1408 
1409   /* release intermediate buffers */
1410   jresult = getJavaBuffer(env, &interProcToken);
1411   if ((*env)->ExceptionCheck(env)) {
1412     return NULL;
1413   }
1414   checkStatus(env, jobj, major, minor, "[GSSLibStub_exportContext]");
1415   if ((*env)->ExceptionCheck(env)) {
1416     return NULL;
1417   }
1418 
1419   return jresult;
1420 }
1421 
1422 /*
1423  * Class:     sun_security_jgss_wrapper_GSSLibStub
1424  * Method:    getMic
1425  * Signature: (JI[B)[B
1426  */
1427 JNIEXPORT jbyteArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_getMic(JNIEnv * env,jobject jobj,jlong pContext,jint jqop,jbyteArray jmsg)1428 Java_sun_security_jgss_wrapper_GSSLibStub_getMic(JNIEnv *env, jobject jobj,
1429                                                  jlong pContext, jint jqop,
1430                                                  jbyteArray jmsg)
1431 {
1432   OM_uint32 minor, major;
1433   gss_ctx_id_t contextHdl;
1434   gss_qop_t qop;
1435   gss_buffer_desc msg;
1436   gss_buffer_desc msgToken;
1437   jbyteArray jresult;
1438 
1439   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1440 
1441   TRACE1("[GSSLibStub_getMic] %" PRIuPTR "", (uintptr_t)contextHdl);
1442 
1443   if (contextHdl == GSS_C_NO_CONTEXT) {
1444     // Twik per javadoc
1445     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_getMic]");
1446     return NULL;
1447   }
1448   qop = (gss_qop_t) jqop;
1449   initGSSBuffer(env, jmsg, &msg);
1450   if ((*env)->ExceptionCheck(env)) {
1451     return NULL;
1452   }
1453 
1454   /* gss_get_mic(...) => GSS_S_CONTEXT_EXPIRED, GSS_S_NO_CONTEXT(!),
1455      GSS_S_BAD_QOP */
1456   major =
1457     (*ftab->getMic)(&minor, contextHdl, qop, &msg, &msgToken);
1458 
1459   /* release intermediate buffers */
1460   resetGSSBuffer(&msg);
1461   jresult = getJavaBuffer(env, &msgToken);
1462   if ((*env)->ExceptionCheck(env)) {
1463     return NULL;
1464   }
1465   checkStatus(env, jobj, major, minor, "[GSSLibStub_getMic]");
1466   if ((*env)->ExceptionCheck(env)) {
1467     return NULL;
1468   }
1469 
1470   return jresult;
1471 }
1472 
1473 /*
1474  * Class:     sun_security_jgss_wrapper_GSSLibStub
1475  * Method:    verifyMic
1476  * Signature: (J[B[BLorg/ietf/jgss/MessageProp;)V
1477  */
1478 JNIEXPORT void JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_verifyMic(JNIEnv * env,jobject jobj,jlong pContext,jbyteArray jmsgToken,jbyteArray jmsg,jobject jprop)1479 Java_sun_security_jgss_wrapper_GSSLibStub_verifyMic(JNIEnv *env,
1480                                                     jobject jobj,
1481                                                     jlong pContext,
1482                                                     jbyteArray jmsgToken,
1483                                                     jbyteArray jmsg,
1484                                                     jobject jprop)
1485 {
1486   OM_uint32 minor, major;
1487   gss_ctx_id_t contextHdl;
1488   gss_buffer_desc msg;
1489   gss_buffer_desc msgToken;
1490   gss_qop_t qop;
1491 
1492   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1493 
1494   TRACE1("[GSSLibStub_verifyMic] %" PRIuPTR "", (uintptr_t)contextHdl);
1495 
1496   if (contextHdl == GSS_C_NO_CONTEXT) {
1497     // Twik per javadoc
1498     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0,
1499         "[GSSLibStub_verifyMic]");
1500     return;
1501   }
1502 
1503   qop = (gss_qop_t) (*env)->CallIntMethod(env, jprop, MID_MessageProp_getQOP);
1504   if ((*env)->ExceptionCheck(env)) { return; }
1505 
1506   initGSSBuffer(env, jmsg, &msg);
1507   if ((*env)->ExceptionCheck(env)) { return; }
1508 
1509   initGSSBuffer(env, jmsgToken, &msgToken);
1510   if ((*env)->ExceptionCheck(env)) {
1511     resetGSSBuffer(&msg);
1512     return;
1513   }
1514 
1515   /* gss_verify_mic(...) => GSS_S_DEFECTIVE_TOKEN, GSS_S_BAD_MIC,
1516      GSS_S_CONTEXT_EXPIRED, GSS_S_DUPLICATE_TOKEN(!), GSS_S_OLD_TOKEN(!),
1517      GSS_S_UNSEQ_TOKEN(!), GSS_S_GAP_TOKEN(!), GSS_S_NO_CONTEXT(!) */
1518   major =
1519     (*ftab->verifyMic)(&minor, contextHdl, &msg, &msgToken, &qop);
1520 
1521   /* release intermediate buffers */
1522   resetGSSBuffer(&msg);
1523   resetGSSBuffer(&msgToken);
1524 
1525   checkStatus(env, jobj, GSS_ERROR(major), minor, "[GSSLibStub_verifyMic]");
1526   if ((*env)->ExceptionCheck(env)) {
1527     return;
1528   }
1529 
1530   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setQOP, qop);
1531   if ((*env)->ExceptionCheck(env)) {
1532     return;
1533   }
1534 
1535   setSupplementaryInfo(env, jobj, jprop, GSS_SUPPLEMENTARY_INFO(major),
1536                        minor);
1537   if ((*env)->ExceptionCheck(env)) {
1538     return;
1539   }
1540 }
1541 
1542 /*
1543  * Class:     sun_security_jgss_wrapper_GSSLibStub
1544  * Method:    wrap
1545  * Signature: (J[BLorg/ietf/jgss/MessageProp;)[B
1546  */
1547 JNIEXPORT jbyteArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_wrap(JNIEnv * env,jobject jobj,jlong pContext,jbyteArray jmsg,jobject jprop)1548 Java_sun_security_jgss_wrapper_GSSLibStub_wrap(JNIEnv *env,
1549                                                jobject jobj,
1550                                                jlong pContext,
1551                                                jbyteArray jmsg,
1552                                                jobject jprop)
1553 {
1554   OM_uint32 minor, major;
1555   jboolean confFlag;
1556   gss_qop_t qop;
1557   gss_buffer_desc msg;
1558   gss_buffer_desc msgToken;
1559   int confState;
1560   gss_ctx_id_t contextHdl;
1561   jbyteArray jresult;
1562 
1563   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1564 
1565   TRACE1("[GSSLibStub_wrap] %" PRIuPTR "", (uintptr_t)contextHdl);
1566 
1567   if (contextHdl == GSS_C_NO_CONTEXT) {
1568     // Twik per javadoc
1569     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_wrap]");
1570     return NULL;
1571   }
1572 
1573   confFlag =
1574     (*env)->CallBooleanMethod(env, jprop, MID_MessageProp_getPrivacy);
1575   if ((*env)->ExceptionCheck(env)) {
1576     return NULL;
1577   }
1578 
1579   qop = (gss_qop_t)
1580     (*env)->CallIntMethod(env, jprop, MID_MessageProp_getQOP);
1581   if ((*env)->ExceptionCheck(env)) {
1582     return NULL;
1583   }
1584 
1585   initGSSBuffer(env, jmsg, &msg);
1586   if ((*env)->ExceptionCheck(env)) {
1587     return NULL;
1588   }
1589 
1590   /* gss_wrap(...) => GSS_S_CONTEXT_EXPIRED, GSS_S_NO_CONTEXT(!),
1591      GSS_S_BAD_QOP */
1592   major = (*ftab->wrap)(&minor, contextHdl, confFlag, qop, &msg, &confState,
1593                    &msgToken);
1594 
1595   /* release intermediate buffers */
1596   resetGSSBuffer(&msg);
1597   jresult = getJavaBuffer(env, &msgToken);
1598   if ((*env)->ExceptionCheck(env)) {
1599     return NULL;
1600   }
1601 
1602   checkStatus(env, jobj, major, minor, "[GSSLibStub_wrap]");
1603   if ((*env)->ExceptionCheck(env)) {
1604     return NULL;
1605   }
1606 
1607   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setPrivacy,
1608                          (confState? JNI_TRUE:JNI_FALSE));
1609   if ((*env)->ExceptionCheck(env)) {
1610     return NULL;
1611   }
1612   return jresult;
1613 }
1614 
1615 /*
1616  * Class:     sun_security_jgss_wrapper_GSSLibStub
1617  * Method:    unwrap
1618  * Signature: (J[BLorg/ietf/jgss/MessageProp;)[B
1619  */
1620 JNIEXPORT jbyteArray JNICALL
Java_sun_security_jgss_wrapper_GSSLibStub_unwrap(JNIEnv * env,jobject jobj,jlong pContext,jbyteArray jmsgToken,jobject jprop)1621 Java_sun_security_jgss_wrapper_GSSLibStub_unwrap(JNIEnv *env,
1622                                                  jobject jobj,
1623                                                  jlong pContext,
1624                                                  jbyteArray jmsgToken,
1625                                                  jobject jprop)
1626 {
1627   OM_uint32 minor, major;
1628   gss_ctx_id_t contextHdl;
1629   gss_buffer_desc msgToken;
1630   gss_buffer_desc msg;
1631   int confState;
1632   gss_qop_t qop;
1633   jbyteArray jresult;
1634 
1635   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1636 
1637   TRACE1("[GSSLibStub_unwrap] %" PRIuPTR "", (uintptr_t)contextHdl);
1638 
1639   if (contextHdl == GSS_C_NO_CONTEXT) {
1640     // Twik per javadoc
1641     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_unwrap]");
1642     return NULL;
1643   }
1644 
1645   initGSSBuffer(env, jmsgToken, &msgToken);
1646   if ((*env)->ExceptionCheck(env)) {
1647     return NULL;
1648   }
1649 
1650   confState = 0;
1651   qop = GSS_C_QOP_DEFAULT;
1652   /* gss_unwrap(...) => GSS_S_DEFECTIVE_TOKEN, GSS_S_BAD_MIC,
1653      GSS_S_CONTEXT_EXPIRED, GSS_S_DUPLICATE_TOKEN(!), GSS_S_OLD_TOKEN(!),
1654      GSS_S_UNSEQ_TOKEN(!), GSS_S_GAP_TOKEN(!), GSS_S_NO_CONTEXT(!) */
1655   major =
1656     (*ftab->unwrap)(&minor, contextHdl, &msgToken, &msg, &confState, &qop);
1657 
1658   /* release intermediate buffers */
1659   resetGSSBuffer(&msgToken);
1660   jresult = getJavaBuffer(env, &msg);
1661   if ((*env)->ExceptionCheck(env)) {
1662     return NULL;
1663   }
1664 
1665   checkStatus(env, jobj, GSS_ERROR(major), minor, "[GSSLibStub_unwrap]");
1666   if ((*env)->ExceptionCheck(env)) {
1667     return NULL;
1668   }
1669 
1670   /* update the message prop with relevant info */
1671   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setPrivacy,
1672                          (confState != 0));
1673   if ((*env)->ExceptionCheck(env)) {
1674     return NULL;
1675   }
1676   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setQOP, qop);
1677   if ((*env)->ExceptionCheck(env)) {
1678     return NULL;
1679   }
1680   setSupplementaryInfo(env, jobj, jprop, GSS_SUPPLEMENTARY_INFO(major),
1681                          minor);
1682   if ((*env)->ExceptionCheck(env)) {
1683     return NULL;
1684   }
1685 
1686   return jresult;
1687 }
1688