1 /*
   2  * Copyright (c) 2005, 2019, 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
  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
 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  */
 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  */
 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  */
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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  */
 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
 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
 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
 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
 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
 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
 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 = NULL;
 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
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 #if defined (_WIN32) && defined (_MSC_VER)
1168   __declspec(align(8))
1169 #endif
1170   jlong result[6];
1171   jlongArray jresult;
1172 
1173   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1174 
1175   TRACE1("[GSSLibStub_inquireContext] %" PRIuPTR "", (uintptr_t)contextHdl);
1176 
1177   srcName = targetName = GSS_C_NO_NAME;
1178   time = 0;
1179   flags = isInitiator = isEstablished = 0;
1180 
1181   /* gss_inquire_context(...) => GSS_S_NO_CONTEXT(!) */
1182   major = (*ftab->inquireContext)(&minor, contextHdl, &srcName,
1183                               &targetName, &time, NULL, &flags,
1184                               &isInitiator, &isEstablished);
1185   /* update member values if needed */
1186   TRACE2("[GSSLibStub_inquireContext] srcName %" PRIuPTR ", targetName %" PRIuPTR "",
1187       (uintptr_t)srcName, (uintptr_t)targetName);
1188 
1189   checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireContext]");
1190   if ((*env)->ExceptionCheck(env)) {
1191     return NULL;
1192   }
1193   result[0] = ptr_to_jlong(srcName);
1194   result[1] = ptr_to_jlong(targetName);
1195   result[2] = (jlong) isInitiator;
1196   result[3] = (jlong) isEstablished;
1197   result[4] = (jlong) flags;
1198   result[5] = (jlong) getJavaTime(time);
1199 
1200   jresult = (*env)->NewLongArray(env, 6);
1201   if (jresult == NULL) {
1202     return NULL;
1203   }
1204   (*env)->SetLongArrayRegion(env, jresult, 0, 6, result);
1205   if ((*env)->ExceptionCheck(env)) {
1206     return NULL;
1207   }
1208   return jresult;
1209 }
1210 
1211 /*
1212  * Class:     sun_security_jgss_wrapper_GSSLibStub
1213  * Method:    getContextMech
1214  * Signature: (J)Lorg/ietf/jgss/Oid;
1215  */
1216 JNIEXPORT jobject JNICALL
1217 Java_sun_security_jgss_wrapper_GSSLibStub_getContextMech(JNIEnv *env,
1218                                                          jobject jobj,
1219                                                          jlong pContext)
1220 {
1221   OM_uint32 minor, major;
1222   gss_OID mech;
1223   gss_ctx_id_t contextHdl;
1224 
1225   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1226 
1227   TRACE1("[GSSLibStub_getContextMech] %ld", (long int)pContext);
1228 
1229   major = (*ftab->inquireContext)(&minor, contextHdl, NULL, NULL,
1230                                 NULL, &mech, NULL,  NULL, NULL);
1231 
1232   checkStatus(env, jobj, major, minor, "[GSSLibStub_getContextMech]");
1233   /* return immediately if an exception has occurred */
1234   if ((*env)->ExceptionCheck(env)) {
1235     return NULL;
1236   }
1237 
1238   return getJavaOID(env, mech);
1239 }
1240 
1241 /*
1242  * Class:     sun_security_jgss_wrapper_GSSLibStub
1243  * Method:    getContextName
1244  * Signature: (JZ)J
1245  */
1246 JNIEXPORT jlong JNICALL
1247 Java_sun_security_jgss_wrapper_GSSLibStub_getContextName(JNIEnv *env,
1248   jobject jobj, jlong pContext, jboolean isSrc)
1249 {
1250   OM_uint32 minor, major;
1251   gss_name_t nameHdl;
1252   gss_ctx_id_t contextHdl;
1253 
1254   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1255 
1256   TRACE2("[GSSLibStub_getContextName] %" PRIuPTR ", isSrc=%d",
1257           (uintptr_t)contextHdl, isSrc);
1258 
1259   nameHdl = GSS_C_NO_NAME;
1260   if (isSrc == JNI_TRUE) {
1261     major = (*ftab->inquireContext)(&minor, contextHdl, &nameHdl, NULL,
1262                                 NULL, NULL, NULL,  NULL, NULL);
1263   } else {
1264     major = (*ftab->inquireContext)(&minor, contextHdl, NULL, &nameHdl,
1265                                 NULL, NULL, NULL,  NULL, NULL);
1266   }
1267 
1268   checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireContextAll]");
1269   /* return immediately if an exception has occurred */
1270   if ((*env)->ExceptionCheck(env)) {
1271     return jlong_zero;
1272   }
1273 
1274   TRACE1("[GSSLibStub_getContextName] pName=%" PRIuPTR "", (uintptr_t) nameHdl);
1275 
1276   return ptr_to_jlong(nameHdl);
1277 }
1278 
1279 /*
1280  * Class:     sun_security_jgss_wrapper_GSSLibStub
1281  * Method:    getContextTime
1282  * Signature: (J)I
1283  */
1284 JNIEXPORT jint JNICALL
1285 Java_sun_security_jgss_wrapper_GSSLibStub_getContextTime(JNIEnv *env,
1286                                                          jobject jobj,
1287                                                          jlong pContext) {
1288   OM_uint32 minor, major;
1289   gss_ctx_id_t contextHdl;
1290   OM_uint32 time;
1291 
1292   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1293 
1294   TRACE1("[GSSLibStub_getContextTime] %" PRIuPTR "", (uintptr_t)contextHdl);
1295 
1296   if (contextHdl == GSS_C_NO_CONTEXT) return 0;
1297 
1298   /* gss_context_time(...) => GSS_S_CONTEXT_EXPIRED(!),
1299      GSS_S_NO_CONTEXT(!) */
1300   major = (*ftab->contextTime)(&minor, contextHdl, &time);
1301   if (GSS_ROUTINE_ERROR(major) == GSS_S_CONTEXT_EXPIRED) {
1302     major = GSS_CALLING_ERROR(major) | GSS_SUPPLEMENTARY_INFO(major);
1303   }
1304   checkStatus(env, jobj, major, minor, "[GSSLibStub_getContextTime]");
1305   if ((*env)->ExceptionCheck(env)) {
1306     return 0;
1307   }
1308   return getJavaTime(time);
1309 }
1310 
1311 /*
1312  * Class:     sun_security_jgss_wrapper_GSSLibStub
1313  * Method:    deleteContext
1314  * Signature: (J)J
1315  */
1316 JNIEXPORT jlong JNICALL
1317 Java_sun_security_jgss_wrapper_GSSLibStub_deleteContext(JNIEnv *env,
1318                                                         jobject jobj,
1319                                                         jlong pContext)
1320 {
1321   OM_uint32 minor, major;
1322   gss_ctx_id_t contextHdl;
1323 
1324   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1325 
1326   TRACE1("[GSSLibStub_deleteContext] %" PRIuPTR "", (uintptr_t)contextHdl);
1327 
1328   if (contextHdl == GSS_C_NO_CONTEXT) return ptr_to_jlong(GSS_C_NO_CONTEXT);
1329 
1330   /* gss_delete_sec_context(...) => GSS_S_NO_CONTEXT(!) */
1331   major = (*ftab->deleteSecContext)(&minor, &contextHdl, GSS_C_NO_BUFFER);
1332 
1333   checkStatus(env, jobj, major, minor, "[GSSLibStub_deleteContext]");
1334   if ((*env)->ExceptionCheck(env)) {
1335     return jlong_zero;
1336   }
1337   return (jlong) ptr_to_jlong(contextHdl);
1338 }
1339 
1340 /*
1341  * Class:     sun_security_jgss_wrapper_GSSLibStub
1342  * Method:    wrapSizeLimit
1343  * Signature: (JIII)I
1344  */
1345 JNIEXPORT jint JNICALL
1346 Java_sun_security_jgss_wrapper_GSSLibStub_wrapSizeLimit(JNIEnv *env,
1347                                                         jobject jobj,
1348                                                         jlong pContext,
1349                                                         jint reqFlag,
1350                                                         jint jqop,
1351                                                         jint joutSize)
1352 {
1353   OM_uint32 minor, major;
1354   gss_ctx_id_t contextHdl;
1355   OM_uint32 outSize, maxInSize;
1356   gss_qop_t qop;
1357 
1358   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1359 
1360   TRACE1("[GSSLibStub_wrapSizeLimit] %" PRIuPTR "", (uintptr_t)contextHdl);
1361 
1362   if (contextHdl == GSS_C_NO_CONTEXT) {
1363     // Twik per javadoc
1364     checkStatus(env, jobj, GSS_S_NO_CONTEXT, 0,
1365         "[GSSLibStub_wrapSizeLimit]");
1366     return 0;
1367   }
1368 
1369   qop = (gss_qop_t) jqop;
1370   outSize = (OM_uint32) joutSize;
1371   /* gss_wrap_size_limit(...) => GSS_S_NO_CONTEXT(!), GSS_S_CONTEXT_EXPIRED,
1372      GSS_S_BAD_QOP */
1373   major = (*ftab->wrapSizeLimit)(&minor, contextHdl, reqFlag,
1374                               qop, outSize, &maxInSize);
1375 
1376   checkStatus(env, jobj, major, minor, "[GSSLibStub_wrapSizeLimit]");
1377   if ((*env)->ExceptionCheck(env)) {
1378     return 0;
1379   }
1380   return (jint) maxInSize;
1381 }
1382 
1383 /*
1384  * Class:     sun_security_jgss_wrapper_GSSLibStub
1385  * Method:    exportContext
1386  * Signature: (J)[B
1387  */
1388 JNIEXPORT jbyteArray JNICALL
1389 Java_sun_security_jgss_wrapper_GSSLibStub_exportContext(JNIEnv *env,
1390                                                         jobject jobj,
1391                                                         jlong pContext)
1392 {
1393   OM_uint32 minor, major;
1394   gss_ctx_id_t contextHdl;
1395   gss_buffer_desc interProcToken;
1396   jbyteArray jresult;
1397 
1398   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1399 
1400   TRACE1("[GSSLibStub_exportContext] %" PRIuPTR "", (uintptr_t)contextHdl);
1401 
1402   if (contextHdl == GSS_C_NO_CONTEXT) {
1403     // Twik per javadoc
1404     checkStatus(env, jobj, GSS_S_NO_CONTEXT, 0, "[GSSLibStub_exportContext]");
1405     return NULL;
1406   }
1407   /* gss_export_sec_context(...) => GSS_S_CONTEXT_EXPIRED,
1408      GSS_S_NO_CONTEXT, GSS_S_UNAVAILABLE */
1409   major =
1410     (*ftab->exportSecContext)(&minor, &contextHdl, &interProcToken);
1411 
1412   /* release intermediate buffers */
1413   jresult = getJavaBuffer(env, &interProcToken);
1414   if ((*env)->ExceptionCheck(env)) {
1415     return NULL;
1416   }
1417   checkStatus(env, jobj, major, minor, "[GSSLibStub_exportContext]");
1418   if ((*env)->ExceptionCheck(env)) {
1419     return NULL;
1420   }
1421 
1422   return jresult;
1423 }
1424 
1425 /*
1426  * Class:     sun_security_jgss_wrapper_GSSLibStub
1427  * Method:    getMic
1428  * Signature: (JI[B)[B
1429  */
1430 JNIEXPORT jbyteArray JNICALL
1431 Java_sun_security_jgss_wrapper_GSSLibStub_getMic(JNIEnv *env, jobject jobj,
1432                                                  jlong pContext, jint jqop,
1433                                                  jbyteArray jmsg)
1434 {
1435   OM_uint32 minor, major;
1436   gss_ctx_id_t contextHdl;
1437   gss_qop_t qop;
1438   gss_buffer_desc msg;
1439   gss_buffer_desc msgToken;
1440   jbyteArray jresult;
1441 
1442   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1443 
1444   TRACE1("[GSSLibStub_getMic] %" PRIuPTR "", (uintptr_t)contextHdl);
1445 
1446   if (contextHdl == GSS_C_NO_CONTEXT) {
1447     // Twik per javadoc
1448     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_getMic]");
1449     return NULL;
1450   }
1451   qop = (gss_qop_t) jqop;
1452   initGSSBuffer(env, jmsg, &msg);
1453   if ((*env)->ExceptionCheck(env)) {
1454     return NULL;
1455   }
1456 
1457   /* gss_get_mic(...) => GSS_S_CONTEXT_EXPIRED, GSS_S_NO_CONTEXT(!),
1458      GSS_S_BAD_QOP */
1459   major =
1460     (*ftab->getMic)(&minor, contextHdl, qop, &msg, &msgToken);
1461 
1462   /* release intermediate buffers */
1463   resetGSSBuffer(&msg);
1464   jresult = getJavaBuffer(env, &msgToken);
1465   if ((*env)->ExceptionCheck(env)) {
1466     return NULL;
1467   }
1468   checkStatus(env, jobj, major, minor, "[GSSLibStub_getMic]");
1469   if ((*env)->ExceptionCheck(env)) {
1470     return NULL;
1471   }
1472 
1473   return jresult;
1474 }
1475 
1476 /*
1477  * Class:     sun_security_jgss_wrapper_GSSLibStub
1478  * Method:    verifyMic
1479  * Signature: (J[B[BLorg/ietf/jgss/MessageProp;)V
1480  */
1481 JNIEXPORT void JNICALL
1482 Java_sun_security_jgss_wrapper_GSSLibStub_verifyMic(JNIEnv *env,
1483                                                     jobject jobj,
1484                                                     jlong pContext,
1485                                                     jbyteArray jmsgToken,
1486                                                     jbyteArray jmsg,
1487                                                     jobject jprop)
1488 {
1489   OM_uint32 minor, major;
1490   gss_ctx_id_t contextHdl;
1491   gss_buffer_desc msg;
1492   gss_buffer_desc msgToken;
1493   gss_qop_t qop;
1494 
1495   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1496 
1497   TRACE1("[GSSLibStub_verifyMic] %" PRIuPTR "", (uintptr_t)contextHdl);
1498 
1499   if (contextHdl == GSS_C_NO_CONTEXT) {
1500     // Twik per javadoc
1501     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0,
1502         "[GSSLibStub_verifyMic]");
1503     return;
1504   }
1505 
1506   qop = (gss_qop_t) (*env)->CallIntMethod(env, jprop, MID_MessageProp_getQOP);
1507   if ((*env)->ExceptionCheck(env)) { return; }
1508 
1509   initGSSBuffer(env, jmsg, &msg);
1510   if ((*env)->ExceptionCheck(env)) { return; }
1511 
1512   initGSSBuffer(env, jmsgToken, &msgToken);
1513   if ((*env)->ExceptionCheck(env)) {
1514     resetGSSBuffer(&msg);
1515     return;
1516   }
1517 
1518   /* gss_verify_mic(...) => GSS_S_DEFECTIVE_TOKEN, GSS_S_BAD_MIC,
1519      GSS_S_CONTEXT_EXPIRED, GSS_S_DUPLICATE_TOKEN(!), GSS_S_OLD_TOKEN(!),
1520      GSS_S_UNSEQ_TOKEN(!), GSS_S_GAP_TOKEN(!), GSS_S_NO_CONTEXT(!) */
1521   major =
1522     (*ftab->verifyMic)(&minor, contextHdl, &msg, &msgToken, &qop);
1523 
1524   /* release intermediate buffers */
1525   resetGSSBuffer(&msg);
1526   resetGSSBuffer(&msgToken);
1527 
1528   checkStatus(env, jobj, GSS_ERROR(major), minor, "[GSSLibStub_verifyMic]");
1529   if ((*env)->ExceptionCheck(env)) {
1530     return;
1531   }
1532 
1533   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setQOP, qop);
1534   if ((*env)->ExceptionCheck(env)) {
1535     return;
1536   }
1537 
1538   setSupplementaryInfo(env, jobj, jprop, GSS_SUPPLEMENTARY_INFO(major),
1539                        minor);
1540   if ((*env)->ExceptionCheck(env)) {
1541     return;
1542   }
1543 }
1544 
1545 /*
1546  * Class:     sun_security_jgss_wrapper_GSSLibStub
1547  * Method:    wrap
1548  * Signature: (J[BLorg/ietf/jgss/MessageProp;)[B
1549  */
1550 JNIEXPORT jbyteArray JNICALL
1551 Java_sun_security_jgss_wrapper_GSSLibStub_wrap(JNIEnv *env,
1552                                                jobject jobj,
1553                                                jlong pContext,
1554                                                jbyteArray jmsg,
1555                                                jobject jprop)
1556 {
1557   OM_uint32 minor, major;
1558   jboolean confFlag;
1559   gss_qop_t qop;
1560   gss_buffer_desc msg;
1561   gss_buffer_desc msgToken;
1562   int confState;
1563   gss_ctx_id_t contextHdl;
1564   jbyteArray jresult;
1565 
1566   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1567 
1568   TRACE1("[GSSLibStub_wrap] %" PRIuPTR "", (uintptr_t)contextHdl);
1569 
1570   if (contextHdl == GSS_C_NO_CONTEXT) {
1571     // Twik per javadoc
1572     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_wrap]");
1573     return NULL;
1574   }
1575 
1576   confFlag =
1577     (*env)->CallBooleanMethod(env, jprop, MID_MessageProp_getPrivacy);
1578   if ((*env)->ExceptionCheck(env)) {
1579     return NULL;
1580   }
1581 
1582   qop = (gss_qop_t)
1583     (*env)->CallIntMethod(env, jprop, MID_MessageProp_getQOP);
1584   if ((*env)->ExceptionCheck(env)) {
1585     return NULL;
1586   }
1587 
1588   initGSSBuffer(env, jmsg, &msg);
1589   if ((*env)->ExceptionCheck(env)) {
1590     return NULL;
1591   }
1592 
1593   /* gss_wrap(...) => GSS_S_CONTEXT_EXPIRED, GSS_S_NO_CONTEXT(!),
1594      GSS_S_BAD_QOP */
1595   major = (*ftab->wrap)(&minor, contextHdl, confFlag, qop, &msg, &confState,
1596                    &msgToken);
1597 
1598   /* release intermediate buffers */
1599   resetGSSBuffer(&msg);
1600   jresult = getJavaBuffer(env, &msgToken);
1601   if ((*env)->ExceptionCheck(env)) {
1602     return NULL;
1603   }
1604 
1605   checkStatus(env, jobj, major, minor, "[GSSLibStub_wrap]");
1606   if ((*env)->ExceptionCheck(env)) {
1607     return NULL;
1608   }
1609 
1610   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setPrivacy,
1611                          (confState? JNI_TRUE:JNI_FALSE));
1612   if ((*env)->ExceptionCheck(env)) {
1613     return NULL;
1614   }
1615   return jresult;
1616 }
1617 
1618 /*
1619  * Class:     sun_security_jgss_wrapper_GSSLibStub
1620  * Method:    unwrap
1621  * Signature: (J[BLorg/ietf/jgss/MessageProp;)[B
1622  */
1623 JNIEXPORT jbyteArray JNICALL
1624 Java_sun_security_jgss_wrapper_GSSLibStub_unwrap(JNIEnv *env,
1625                                                  jobject jobj,
1626                                                  jlong pContext,
1627                                                  jbyteArray jmsgToken,
1628                                                  jobject jprop)
1629 {
1630   OM_uint32 minor, major;
1631   gss_ctx_id_t contextHdl;
1632   gss_buffer_desc msgToken;
1633   gss_buffer_desc msg;
1634   int confState;
1635   gss_qop_t qop;
1636   jbyteArray jresult;
1637 
1638   contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
1639 
1640   TRACE1("[GSSLibStub_unwrap] %" PRIuPTR "", (uintptr_t)contextHdl);
1641 
1642   if (contextHdl == GSS_C_NO_CONTEXT) {
1643     // Twik per javadoc
1644     checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_unwrap]");
1645     return NULL;
1646   }
1647 
1648   initGSSBuffer(env, jmsgToken, &msgToken);
1649   if ((*env)->ExceptionCheck(env)) {
1650     return NULL;
1651   }
1652 
1653   confState = 0;
1654   qop = GSS_C_QOP_DEFAULT;
1655   /* gss_unwrap(...) => GSS_S_DEFECTIVE_TOKEN, GSS_S_BAD_MIC,
1656      GSS_S_CONTEXT_EXPIRED, GSS_S_DUPLICATE_TOKEN(!), GSS_S_OLD_TOKEN(!),
1657      GSS_S_UNSEQ_TOKEN(!), GSS_S_GAP_TOKEN(!), GSS_S_NO_CONTEXT(!) */
1658   major =
1659     (*ftab->unwrap)(&minor, contextHdl, &msgToken, &msg, &confState, &qop);
1660 
1661   /* release intermediate buffers */
1662   resetGSSBuffer(&msgToken);
1663   jresult = getJavaBuffer(env, &msg);
1664   if ((*env)->ExceptionCheck(env)) {
1665     return NULL;
1666   }
1667 
1668   checkStatus(env, jobj, GSS_ERROR(major), minor, "[GSSLibStub_unwrap]");
1669   if ((*env)->ExceptionCheck(env)) {
1670     return NULL;
1671   }
1672 
1673   /* update the message prop with relevant info */
1674   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setPrivacy,
1675                          (confState != 0));
1676   if ((*env)->ExceptionCheck(env)) {
1677     return NULL;
1678   }
1679   (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setQOP, qop);
1680   if ((*env)->ExceptionCheck(env)) {
1681     return NULL;
1682   }
1683   setSupplementaryInfo(env, jobj, jprop, GSS_SUPPLEMENTARY_INFO(major),
1684                          minor);
1685   if ((*env)->ExceptionCheck(env)) {
1686     return NULL;
1687   }
1688 
1689   return jresult;
1690 }