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