| /* | |
| * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| #include "sun_security_jgss_wrapper_GSSLibStub.h" | |
| #include "NativeUtil.h" | |
| #include "NativeFunc.h" | |
| #include "jlong.h" | |
| #include <jni.h> | |
| /* Constants for indicating what type of info is needed for inquiries */ | |
| const int TYPE_CRED_NAME = 10; | |
| const int TYPE_CRED_TIME = 11; | |
| const int TYPE_CRED_USAGE = 12; | |
| static jclass tlsCBCl = NULL; | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: init | |
| * Signature: (Ljava/lang/String;Z)Z | |
| */ | |
| JNIEXPORT jboolean JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_init(JNIEnv *env, | |
| jclass jcls, | |
| jstring jlibName, | |
| jboolean jDebug) { | |
| const char *libName; | |
| int failed; | |
| if (!jDebug) { | |
| JGSS_DEBUG = 0; | |
| } else { | |
| JGSS_DEBUG = 1; | |
| } | |
| if (jlibName == NULL) { | |
| TRACE0("[GSSLibStub_init] GSS lib name is NULL"); | |
| return JNI_FALSE; | |
| } | |
| libName = (*env)->GetStringUTFChars(env, jlibName, NULL); | |
| if (libName == NULL) { | |
| return JNI_FALSE; | |
| } | |
| TRACE1("[GSSLibStub_init] libName=%s", libName); | |
| /* initialize global function table */ | |
| failed = loadNative(libName); | |
| (*env)->ReleaseStringUTFChars(env, jlibName, libName); | |
| if (tlsCBCl == NULL) { | |
| /* initialize TLS Channel Binding class wrapper */ | |
| jclass cl = (*env)->FindClass(env, | |
| "sun/security/jgss/krb5/internal/TlsChannelBindingImpl"); | |
| if (cl == NULL) { /* exception thrown */ | |
| return JNI_FALSE; | |
| } | |
| tlsCBCl = (*env)->NewGlobalRef(env, cl); | |
| } | |
| if (!failed) { | |
| return JNI_TRUE; | |
| } else { | |
| if (JGSS_DEBUG) { | |
| #ifdef WIN32 | |
| #define MAX_MSG_SIZE 256 | |
| static CHAR szMsgBuf[MAX_MSG_SIZE]; | |
| DWORD dwRes; | |
| DWORD dwError = GetLastError(); | |
| dwRes = FormatMessage ( | |
| FORMAT_MESSAGE_FROM_SYSTEM, | |
| NULL, | |
| dwError, | |
| 0, | |
| szMsgBuf, | |
| MAX_MSG_SIZE, | |
| NULL); | |
| if (0 == dwRes) { | |
| TRACE1("GSS-API: Unknown failure %d", dwError); | |
| } else { | |
| TRACE1("GSS-API: %s",szMsgBuf); | |
| } | |
| #else | |
| char* error = dlerror(); | |
| if (error) { | |
| TRACE0(error); | |
| } | |
| #endif | |
| } | |
| return JNI_FALSE; | |
| } | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getMechPtr | |
| * Signature: ([B)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getMechPtr(JNIEnv *env, | |
| jclass jcls, | |
| jbyteArray jbytes) { | |
| gss_OID cOid; | |
| unsigned int i, len; | |
| jbyte* bytes; | |
| int found; | |
| if (jbytes != NULL) { | |
| found = 0; | |
| len = (unsigned int)((*env)->GetArrayLength(env, jbytes) - 2); | |
| bytes = (*env)->GetByteArrayElements(env, jbytes, NULL); | |
| if (bytes == NULL) { | |
| return ptr_to_jlong(NULL); | |
| } | |
| for (i = 0; i < ftab->mechs->count; i++) { | |
| cOid = &(ftab->mechs->elements[i]); | |
| if (len == cOid->length && | |
| (memcmp(cOid->elements, (bytes + 2), len) == 0)) { | |
| // Found a match | |
| found = 1; | |
| break; | |
| } | |
| } | |
| (*env)->ReleaseByteArrayElements(env, jbytes, bytes, 0); | |
| if (found != 1) { | |
| checkStatus(env, NULL, GSS_S_BAD_MECH, 0, "[GSSLibStub_getMechPtr]"); | |
| return ptr_to_jlong(NULL); | |
| } else { | |
| return ptr_to_jlong(cOid); | |
| } | |
| } else { | |
| return ptr_to_jlong(GSS_C_NO_OID); | |
| } | |
| } | |
| /* | |
| * Utility routine which releases the specified gss_channel_bindings_t | |
| * structure. | |
| */ | |
| void deleteGSSCB(gss_channel_bindings_t cb) { | |
| if (cb == GSS_C_NO_CHANNEL_BINDINGS) return; | |
| /* release initiator address */ | |
| if (cb->initiator_addrtype != GSS_C_AF_NULLADDR && | |
| cb->initiator_addrtype != GSS_C_AF_UNSPEC) { | |
| resetGSSBuffer(&(cb->initiator_address)); | |
| } | |
| /* release acceptor address */ | |
| if (cb->acceptor_addrtype != GSS_C_AF_NULLADDR && | |
| cb->acceptor_addrtype != GSS_C_AF_UNSPEC) { | |
| resetGSSBuffer(&(cb->acceptor_address)); | |
| } | |
| /* release application data */ | |
| if (cb->application_data.length != 0) { | |
| resetGSSBuffer(&(cb->application_data)); | |
| } | |
| free(cb); | |
| } | |
| /* | |
| * Utility routine which creates a gss_channel_bindings_t structure | |
| * using the specified org.ietf.jgss.ChannelBinding object. | |
| * NOTE: must call deleteGSSCB() to free up the resources. | |
| */ | |
| gss_channel_bindings_t newGSSCB(JNIEnv *env, jobject jcb) { | |
| gss_channel_bindings_t cb; | |
| jobject jinetAddr; | |
| jbyteArray value; | |
| if (jcb == NULL) { | |
| return GSS_C_NO_CHANNEL_BINDINGS; | |
| } | |
| // initialize cb as zeroes to avoid uninitialized pointer being | |
| // freed when deleteGSSCB is called at cleanup. | |
| cb = calloc(1, sizeof(struct gss_channel_bindings_struct)); | |
| if (cb == NULL) { | |
| gssThrowOutOfMemoryError(env, NULL); | |
| return NULL; | |
| } | |
| // initialize addrtype in CB first | |
| // LDAP TLS Channel Binding requires GSS_C_AF_UNSPEC address type | |
| // for unspecified initiator and acceptor addresses. | |
| // GSS_C_AF_NULLADDR value should be used for unspecified address | |
| // in all other cases. | |
| if ((*env)->IsInstanceOf(env, jcb, tlsCBCl)) { | |
| // TLS Channel Binding requires unspecified addrtype=0 | |
| cb->initiator_addrtype = GSS_C_AF_UNSPEC; | |
| cb->acceptor_addrtype = GSS_C_AF_UNSPEC; | |
| } else { | |
| cb->initiator_addrtype = GSS_C_AF_NULLADDR; | |
| cb->acceptor_addrtype = GSS_C_AF_NULLADDR; | |
| } | |
| /* set up initiator address */ | |
| jinetAddr = (*env)->CallObjectMethod(env, jcb, | |
| MID_ChannelBinding_getInitiatorAddr); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| if (jinetAddr != NULL) { | |
| value = (*env)->CallObjectMethod(env, jinetAddr, | |
| MID_InetAddress_getAddr); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| cb->initiator_addrtype = GSS_C_AF_INET; | |
| initGSSBuffer(env, value, &(cb->initiator_address)); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| } | |
| /* set up acceptor address */ | |
| jinetAddr = (*env)->CallObjectMethod(env, jcb, | |
| MID_ChannelBinding_getAcceptorAddr); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| if (jinetAddr != NULL) { | |
| value = (*env)->CallObjectMethod(env, jinetAddr, | |
| MID_InetAddress_getAddr); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| cb->acceptor_addrtype = GSS_C_AF_INET; | |
| initGSSBuffer(env, value, &(cb->acceptor_address)); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| } | |
| /* set up application data */ | |
| value = (*env)->CallObjectMethod(env, jcb, | |
| MID_ChannelBinding_getAppData); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| initGSSBuffer(env, value, &(cb->application_data)); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto cleanup; | |
| } | |
| return cb; | |
| cleanup: | |
| deleteGSSCB(cb); | |
| return NULL; | |
| } | |
| /* | |
| * Utility routine for storing the supplementary information | |
| * into the specified org.ietf.jgss.MessageProp object. | |
| */ | |
| void setSupplementaryInfo(JNIEnv *env, jobject jstub, jobject jprop, | |
| int suppInfo, int minor) { | |
| jboolean isDuplicate, isOld, isUnseq, hasGap; | |
| jstring minorMsg; | |
| if (suppInfo != GSS_S_COMPLETE) { | |
| isDuplicate = ((suppInfo & GSS_S_DUPLICATE_TOKEN) != 0); | |
| isOld = ((suppInfo & GSS_S_OLD_TOKEN) != 0); | |
| isUnseq = ((suppInfo & GSS_S_UNSEQ_TOKEN) != 0); | |
| hasGap = ((suppInfo & GSS_S_GAP_TOKEN) != 0); | |
| minorMsg = getMinorMessage(env, jstub, minor); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return; | |
| } | |
| (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setSupplementaryStates, | |
| isDuplicate, isOld, isUnseq, hasGap, minor, | |
| minorMsg); | |
| } | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: indicateMechs | |
| * Signature: ()[Lorg/ietf/jgss/Oid; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_indicateMechs(JNIEnv *env, | |
| jclass jcls) | |
| { | |
| if (ftab->mechs != NULL && ftab->mechs != GSS_C_NO_OID_SET) { | |
| return getJavaOIDArray(env, ftab->mechs); | |
| } else return NULL; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: inquireNamesForMech | |
| * Signature: ()[Lorg/ietf/jgss/Oid; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_inquireNamesForMech(JNIEnv *env, | |
| jobject jobj) | |
| { | |
| OM_uint32 minor, major; | |
| gss_OID mech; | |
| gss_OID_set nameTypes; | |
| jobjectArray result; | |
| if (ftab->inquireNamesForMech != NULL) { | |
| mech = (gss_OID)jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech)); | |
| nameTypes = GSS_C_NO_OID_SET; | |
| /* gss_inquire_names_for_mech(...) => N/A */ | |
| major = (*ftab->inquireNamesForMech)(&minor, mech, &nameTypes); | |
| /* release intermediate buffers before checking status */ | |
| result = getJavaOIDArray(env, nameTypes); | |
| deleteGSSOIDSet(nameTypes); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireNamesForMech]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return result; | |
| } | |
| return NULL; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: releaseName | |
| * Signature: (J)V | |
| */ | |
| JNIEXPORT void JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_releaseName(JNIEnv *env, | |
| jobject jobj, | |
| jlong pName) | |
| { | |
| OM_uint32 minor, major; | |
| gss_name_t nameHdl; | |
| nameHdl = (gss_name_t) jlong_to_ptr(pName); | |
| TRACE1("[GSSLibStub_releaseName] %ld", (long) pName); | |
| if (nameHdl != GSS_C_NO_NAME) { | |
| /* gss_release_name(...) => GSS_S_BAD_NAME */ | |
| major = (*ftab->releaseName)(&minor, &nameHdl); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_releaseName]"); | |
| } | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: importName | |
| * Signature: ([BLorg/ietf/jgss/Oid;)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_importName(JNIEnv *env, | |
| jobject jobj, | |
| jbyteArray jnameVal, | |
| jobject jnameType) | |
| { | |
| OM_uint32 minor, major; | |
| gss_buffer_desc nameVal; | |
| gss_OID nameType; | |
| gss_name_t nameHdl; | |
| nameHdl = GSS_C_NO_NAME; | |
| TRACE0("[GSSLibStub_importName]"); | |
| initGSSBuffer(env, jnameVal, &nameVal); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return jlong_zero; | |
| } | |
| nameType = newGSSOID(env, jnameType); | |
| if ((*env)->ExceptionCheck(env)) { | |
| resetGSSBuffer(&nameVal); | |
| return jlong_zero; | |
| } | |
| /* gss_import_name(...) => GSS_S_BAD_NAMETYPE, GSS_S_BAD_NAME, | |
| GSS_S_BAD_MECH */ | |
| major = (*ftab->importName)(&minor, &nameVal, nameType, &nameHdl); | |
| TRACE1("[GSSLibStub_importName] %" PRIuPTR "", (uintptr_t) nameHdl); | |
| /* release intermediate buffers */ | |
| deleteGSSOID(nameType); | |
| resetGSSBuffer(&nameVal); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_importName]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return jlong_zero; | |
| } | |
| return ptr_to_jlong(nameHdl); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: compareName | |
| * Signature: (JJ)Z | |
| */ | |
| JNIEXPORT jboolean JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_compareName(JNIEnv *env, | |
| jobject jobj, | |
| jlong pName1, | |
| jlong pName2) | |
| { | |
| OM_uint32 minor, major; | |
| gss_name_t nameHdl1, nameHdl2; | |
| int isEqual; | |
| isEqual = 0; | |
| nameHdl1 = (gss_name_t) jlong_to_ptr(pName1); | |
| nameHdl2 = (gss_name_t) jlong_to_ptr(pName2); | |
| TRACE2("[GSSLibStub_compareName] %ld %ld", (long)pName1, (long)pName2); | |
| if ((nameHdl1 != GSS_C_NO_NAME) && (nameHdl2 != GSS_C_NO_NAME)) { | |
| /* gss_compare_name(...) => GSS_S_BAD_NAMETYPE, GSS_S_BAD_NAME(!) */ | |
| major = (*ftab->compareName)(&minor, nameHdl1, nameHdl2, &isEqual); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_compareName]"); | |
| } | |
| return (isEqual != 0); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: canonicalizeName | |
| * Signature: (J)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_canonicalizeName(JNIEnv *env, | |
| jobject jobj, | |
| jlong pName) | |
| { | |
| OM_uint32 minor, major; | |
| gss_name_t nameHdl, mnNameHdl; | |
| gss_OID mech; | |
| nameHdl = (gss_name_t) jlong_to_ptr(pName); | |
| TRACE1("[GSSLibStub_canonicalizeName] %ld", (long) pName); | |
| if (nameHdl != GSS_C_NO_NAME) { | |
| mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech)); | |
| mnNameHdl = GSS_C_NO_NAME; | |
| /* gss_canonicalize_name(...) may return GSS_S_BAD_NAMETYPE, | |
| GSS_S_BAD_NAME, GSS_S_BAD_MECH */ | |
| major = (*ftab->canonicalizeName)(&minor, nameHdl, mech, &mnNameHdl); | |
| TRACE1("[GSSLibStub_canonicalizeName] MN=%" PRIuPTR "", (uintptr_t)mnNameHdl); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_canonicalizeName]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return ptr_to_jlong(GSS_C_NO_NAME); | |
| } | |
| return ptr_to_jlong(mnNameHdl); | |
| } | |
| return ptr_to_jlong(GSS_C_NO_NAME); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: exportName | |
| * Signature: (J)[B | |
| */ | |
| JNIEXPORT jbyteArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_exportName(JNIEnv *env, | |
| jobject jobj, | |
| jlong pName) { | |
| OM_uint32 minor, major; | |
| gss_name_t nameHdl, mNameHdl; | |
| gss_buffer_desc outBuf; | |
| jbyteArray jresult; | |
| nameHdl = (gss_name_t) jlong_to_ptr(pName); | |
| TRACE1("[GSSLibStub_exportName] %ld", (long) pName); | |
| /* gss_export_name(...) => GSS_S_NAME_NOT_MN, GSS_S_BAD_NAMETYPE, | |
| GSS_S_BAD_NAME */ | |
| major = (*ftab->exportName)(&minor, nameHdl, &outBuf); | |
| /* canonicalize the internal name to MN and retry */ | |
| if (major == GSS_S_NAME_NOT_MN) { | |
| /* release intermediate buffers before retrying */ | |
| (*ftab->releaseBuffer)(&minor, &outBuf); | |
| TRACE0("[GSSLibStub_exportName] canonicalize and re-try"); | |
| mNameHdl = (gss_name_t)jlong_to_ptr( | |
| Java_sun_security_jgss_wrapper_GSSLibStub_canonicalizeName | |
| (env, jobj, pName)); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| major = (*ftab->exportName)(&minor, mNameHdl, &outBuf); | |
| Java_sun_security_jgss_wrapper_GSSLibStub_releaseName | |
| (env, jobj, ptr_to_jlong(mNameHdl)); | |
| if ((*env)->ExceptionCheck(env)) { | |
| /* release intermediate buffers */ | |
| (*ftab->releaseBuffer)(&minor, &outBuf); | |
| return NULL; | |
| } | |
| } | |
| /* release intermediate buffers before checking status */ | |
| jresult = getJavaBuffer(env, &outBuf); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_exportName]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: displayName | |
| * Signature: (J)[Ljava/lang/Object; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_displayName(JNIEnv *env, | |
| jobject jobj, | |
| jlong pName) { | |
| OM_uint32 minor, major; | |
| gss_name_t nameHdl; | |
| gss_buffer_desc outNameBuf; | |
| gss_OID outNameType; | |
| jstring jname; | |
| jobject jtype; | |
| jobjectArray jresult; | |
| nameHdl = (gss_name_t) jlong_to_ptr(pName); | |
| TRACE1("[GSSLibStub_displayName] %ld", (long) pName); | |
| if (nameHdl == GSS_C_NO_NAME) { | |
| checkStatus(env, jobj, GSS_S_BAD_NAME, 0, "[GSSLibStub_displayName]"); | |
| return NULL; | |
| } | |
| /* gss_display_name(...) => GSS_S_BAD_NAME */ | |
| major = (*ftab->displayName)(&minor, nameHdl, &outNameBuf, &outNameType); | |
| /* release intermediate buffers before checking status */ | |
| jname = getJavaString(env, &outNameBuf); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_displayName]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| jtype = getJavaOID(env, outNameType); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| jresult = (*env)->NewObjectArray(env, 2, CLS_Object, NULL); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| (*env)->SetObjectArrayElement(env, jresult, 0, jname); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| (*env)->SetObjectArrayElement(env, jresult, 1, jtype); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: acquireCred | |
| * Signature: (JII)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_acquireCred(JNIEnv *env, | |
| jobject jobj, | |
| jlong pName, | |
| jint reqTime, | |
| jint usage) | |
| { | |
| OM_uint32 minor, major; | |
| gss_OID mech; | |
| gss_OID_set mechs; | |
| gss_cred_usage_t credUsage; | |
| gss_name_t nameHdl; | |
| gss_cred_id_t credHdl; | |
| credHdl = GSS_C_NO_CREDENTIAL; | |
| TRACE0("[GSSLibStub_acquireCred]"); | |
| mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech)); | |
| mechs = newGSSOIDSet(mech); | |
| credUsage = (gss_cred_usage_t) usage; | |
| nameHdl = (gss_name_t) jlong_to_ptr(pName); | |
| TRACE2("[GSSLibStub_acquireCred] pName=%ld, usage=%d", (long)pName, usage); | |
| /* gss_acquire_cred(...) => GSS_S_BAD_MECH, GSS_S_BAD_NAMETYPE, | |
| GSS_S_BAD_NAME, GSS_S_CREDENTIALS_EXPIRED, GSS_S_NO_CRED */ | |
| major = | |
| (*ftab->acquireCred)(&minor, nameHdl, reqTime, mechs, | |
| credUsage, &credHdl, NULL, NULL); | |
| /* release intermediate buffers */ | |
| deleteGSSOIDSet(mechs); | |
| TRACE1("[GSSLibStub_acquireCred] pCred=%" PRIuPTR "", (uintptr_t) credHdl); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_acquireCred]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return jlong_zero; | |
| } | |
| return ptr_to_jlong(credHdl); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: releaseCred | |
| * Signature: (J)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_releaseCred(JNIEnv *env, | |
| jobject jobj, | |
| jlong pCred) | |
| { | |
| OM_uint32 minor, major; | |
| gss_cred_id_t credHdl; | |
| credHdl = (gss_cred_id_t) jlong_to_ptr(pCred); | |
| TRACE1("[GSSLibStub_releaseCred] %ld", (long int)pCred); | |
| if (credHdl != GSS_C_NO_CREDENTIAL) { | |
| /* gss_release_cred(...) => GSS_S_NO_CRED(!) */ | |
| major = (*ftab->releaseCred)(&minor, &credHdl); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_releaseCred]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return jlong_zero; | |
| } | |
| } | |
| return ptr_to_jlong(credHdl); | |
| } | |
| /* | |
| * Utility routine for obtaining info about a credential. | |
| */ | |
| void inquireCred(JNIEnv *env, jobject jobj, gss_cred_id_t pCred, | |
| jint type, void *result) { | |
| OM_uint32 minor=0, major=0; | |
| OM_uint32 routineErr; | |
| gss_cred_id_t credHdl; | |
| credHdl = pCred; | |
| TRACE1("[gss_inquire_cred] %" PRIuPTR "", (uintptr_t) pCred); | |
| /* gss_inquire_cred(...) => GSS_S_DEFECTIVE_CREDENTIAL(!), | |
| GSS_S_CREDENTIALS_EXPIRED(!), GSS_S_NO_CRED(!) */ | |
| if (type == TYPE_CRED_NAME) { | |
| major = (*ftab->inquireCred)(&minor, credHdl, result, NULL, NULL, NULL); | |
| } else if (type == TYPE_CRED_TIME) { | |
| major = (*ftab->inquireCred)(&minor, credHdl, NULL, result, NULL, NULL); | |
| } else if (type == TYPE_CRED_USAGE) { | |
| major = (*ftab->inquireCred)(&minor, credHdl, NULL, NULL, result, NULL); | |
| } | |
| routineErr = GSS_ROUTINE_ERROR(major); | |
| if (routineErr == GSS_S_CREDENTIALS_EXPIRED) { | |
| /* ignore GSS_S_CREDENTIALS_EXPIRED for query */ | |
| major = GSS_CALLING_ERROR(major) | | |
| GSS_SUPPLEMENTARY_INFO(major); | |
| } else if (routineErr == GSS_S_NO_CRED) { | |
| /* twik since Java API throws BAD_MECH instead of NO_CRED */ | |
| major = GSS_CALLING_ERROR(major) | | |
| GSS_S_BAD_MECH | GSS_SUPPLEMENTARY_INFO(major); | |
| } | |
| checkStatus(env, jobj, major, minor, "[gss_inquire_cred]"); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getCredName | |
| * Signature: (J)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getCredName(JNIEnv *env, | |
| jobject jobj, | |
| jlong pCred) | |
| { | |
| gss_name_t nameHdl; | |
| gss_cred_id_t credHdl; | |
| credHdl = (gss_cred_id_t) jlong_to_ptr(pCred); | |
| TRACE1("[GSSLibStub_getCredName] %ld", (long int)pCred); | |
| nameHdl = GSS_C_NO_NAME; | |
| inquireCred(env, jobj, credHdl, TYPE_CRED_NAME, &nameHdl); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return jlong_zero; | |
| } | |
| TRACE1("[GSSLibStub_getCredName] pName=%" PRIuPTR "", (uintptr_t) nameHdl); | |
| return ptr_to_jlong(nameHdl); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getCredTime | |
| * Signature: (J)I | |
| */ | |
| JNIEXPORT jint JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getCredTime(JNIEnv *env, | |
| jobject jobj, | |
| jlong pCred) | |
| { | |
| gss_cred_id_t credHdl; | |
| OM_uint32 lifetime; | |
| credHdl = (gss_cred_id_t) jlong_to_ptr(pCred); | |
| TRACE1("[GSSLibStub_getCredTime] %ld", (long int)pCred); | |
| lifetime = 0; | |
| inquireCred(env, jobj, credHdl, TYPE_CRED_TIME, &lifetime); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return 0; | |
| } | |
| return getJavaTime(lifetime); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getCredUsage | |
| * Signature: (J)I | |
| */ | |
| JNIEXPORT jint JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getCredUsage(JNIEnv *env, | |
| jobject jobj, | |
| jlong pCred) | |
| { | |
| gss_cred_usage_t usage; | |
| gss_cred_id_t credHdl; | |
| credHdl = (gss_cred_id_t) jlong_to_ptr(pCred); | |
| TRACE1("[GSSLibStub_getCredUsage] %ld", (long int)pCred); | |
| inquireCred(env, jobj, credHdl, TYPE_CRED_USAGE, &usage); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return -1; | |
| } | |
| return (jint) usage; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: importContext | |
| * Signature: ([B)Lsun/security/jgss/wrapper/NativeGSSContext; | |
| */ | |
| JNIEXPORT jobject JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_importContext(JNIEnv *env, | |
| jobject jobj, | |
| jbyteArray jctxtToken) | |
| { | |
| OM_uint32 minor, major; | |
| gss_buffer_desc ctxtToken; | |
| gss_ctx_id_t contextHdl; | |
| gss_OID mech, mech2; | |
| TRACE0("[GSSLibStub_importContext]"); | |
| contextHdl = GSS_C_NO_CONTEXT; | |
| initGSSBuffer(env, jctxtToken, &ctxtToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| /* gss_import_sec_context(...) => GSS_S_NO_CONTEXT, GSS_S_DEFECTIVE_TOKEN, | |
| GSS_S_UNAVAILABLE, GSS_S_UNAUTHORIZED */ | |
| major = (*ftab->importSecContext)(&minor, &ctxtToken, &contextHdl); | |
| TRACE1("[GSSLibStub_importContext] pContext=%" PRIuPTR "", (uintptr_t) contextHdl); | |
| /* release intermediate buffers */ | |
| resetGSSBuffer(&ctxtToken); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_importContext]"); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| /* now that the context has been imported, proceed to find out | |
| its mech */ | |
| major = (*ftab->inquireContext)(&minor, contextHdl, NULL, NULL, | |
| NULL, &mech, NULL, NULL, NULL); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_importContext] getMech"); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| mech2 = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, | |
| FID_GSSLibStub_pMech)); | |
| if (sameMech(mech, mech2) == JNI_TRUE) { | |
| /* mech match - return the context object */ | |
| return (*env)->NewObject(env, CLS_NativeGSSContext, | |
| MID_NativeGSSContext_ctor, | |
| ptr_to_jlong(contextHdl), jobj); | |
| } else { | |
| /* mech mismatch - clean up then return null */ | |
| major = (*ftab->deleteSecContext)(&minor, &contextHdl, GSS_C_NO_BUFFER); | |
| checkStatus(env, jobj, major, minor, | |
| "[GSSLibStub_importContext] cleanup"); | |
| return NULL; | |
| } | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: initContext | |
| * Signature: (JJLorg/ietf/jgss/ChannelBinding;[BLsun/security/jgss/wrapper/NativeGSSContext;)[B | |
| */ | |
| JNIEXPORT jbyteArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_initContext(JNIEnv *env, | |
| jobject jobj, | |
| jlong pCred, | |
| jlong pName, | |
| jobject jcb, | |
| jbyteArray jinToken, | |
| jobject jcontextSpi) | |
| { | |
| OM_uint32 minor, major; | |
| gss_cred_id_t credHdl ; | |
| gss_ctx_id_t contextHdl, contextHdlSave; | |
| gss_name_t targetName; | |
| gss_OID mech; | |
| OM_uint32 flags, aFlags; | |
| OM_uint32 time, aTime; | |
| gss_channel_bindings_t cb; | |
| gss_buffer_desc inToken; | |
| gss_buffer_desc outToken; | |
| jbyteArray jresult; | |
| /* UNCOMMENT after SEAM bug#6287358 is backported to S10 | |
| gss_OID aMech; | |
| jobject jMech; | |
| */ | |
| TRACE0("[GSSLibStub_initContext]"); | |
| credHdl = (gss_cred_id_t) jlong_to_ptr(pCred); | |
| contextHdl = contextHdlSave = (gss_ctx_id_t) jlong_to_ptr( | |
| (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext)); | |
| targetName = (gss_name_t) jlong_to_ptr(pName); | |
| mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech)); | |
| flags = (OM_uint32) (*env)->GetIntField(env, jcontextSpi, | |
| FID_NativeGSSContext_flags); | |
| time = getGSSTime((*env)->GetIntField(env, jcontextSpi, | |
| FID_NativeGSSContext_lifetime)); | |
| cb = newGSSCB(env, jcb); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| initGSSBuffer(env, jinToken, &inToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| deleteGSSCB(cb); | |
| return NULL; | |
| } | |
| TRACE2( "[GSSLibStub_initContext] before: pCred=%" PRIuPTR ", pContext=%" PRIuPTR "", | |
| (uintptr_t)credHdl, (uintptr_t)contextHdl); | |
| /* gss_init_sec_context(...) => GSS_S_CONTINUE_NEEDED(!), | |
| GSS_S_DEFECTIVE_TOKEN, GSS_S_NO_CRED, GSS_S_DEFECTIVE_CREDENTIAL(!), | |
| GSS_S_CREDENTIALS_EXPIRED, GSS_S_BAD_BINDINGS, GSS_S_BAD_MIC, | |
| GSS_S_OLD_TOKEN, GSS_S_DUPLICATE_TOKEN, GSS_S_NO_CONTEXT(!), | |
| GSS_S_BAD_NAMETYPE, GSS_S_BAD_NAME(!), GSS_S_BAD_MECH */ | |
| major = (*ftab->initSecContext)(&minor, credHdl, | |
| &contextHdl, targetName, mech, | |
| flags, time, cb, &inToken, NULL /*aMech*/, | |
| &outToken, &aFlags, &aTime); | |
| TRACE2("[GSSLibStub_initContext] after: pContext=%" PRIuPTR ", outToken len=%ld", | |
| (uintptr_t)contextHdl, (long)outToken.length); | |
| // update context handle with the latest value if changed | |
| // this is to work with both MIT and Solaris. Former deletes half-built | |
| // context if error occurs | |
| if (contextHdl != contextHdlSave) { | |
| (*env)->CallVoidMethod(env, jcontextSpi, MID_NativeGSSContext_setContext, | |
| ptr_to_jlong(contextHdl)); | |
| TRACE1("[GSSLibStub_initContext] set pContext=%" PRIuPTR "", (uintptr_t)contextHdl); | |
| } | |
| if (GSS_ERROR(major) == GSS_S_COMPLETE) { | |
| /* update member values if needed */ | |
| (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_flags, aFlags); | |
| TRACE1("[GSSLibStub_initContext] set flags=0x%x", aFlags); | |
| if (major == GSS_S_COMPLETE) { | |
| (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_lifetime, | |
| getJavaTime(aTime)); | |
| TRACE0("[GSSLibStub_initContext] context established"); | |
| (*env)->SetBooleanField(env, jcontextSpi, | |
| FID_NativeGSSContext_isEstablished, | |
| JNI_TRUE); | |
| /* UNCOMMENT after SEAM bug#6287358 is backported to S10 | |
| jMech = getJavaOID(env, aMech); | |
| (*env)->SetObjectField(env, jcontextSpi, | |
| FID_NativeGSSContext_actualMech, jMech); | |
| */ | |
| } else if (major & GSS_S_CONTINUE_NEEDED) { | |
| TRACE0("[GSSLibStub_initContext] context not established"); | |
| major -= GSS_S_CONTINUE_NEEDED; | |
| } | |
| } | |
| /* release intermediate buffers before checking status */ | |
| deleteGSSCB(cb); | |
| resetGSSBuffer(&inToken); | |
| jresult = getJavaBuffer(env, &outToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_initContext]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: acceptContext | |
| * Signature: (JLorg/ietf/jgss/ChannelBinding;[BLsun/security/jgss/wrapper/NativeGSSContext;)[B | |
| */ | |
| JNIEXPORT jbyteArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_acceptContext(JNIEnv *env, | |
| jobject jobj, | |
| jlong pCred, | |
| jobject jcb, | |
| jbyteArray jinToken, | |
| jobject jcontextSpi) | |
| { | |
| OM_uint32 minor, major; | |
| OM_uint32 minor2, major2; | |
| gss_ctx_id_t contextHdl, contextHdlSave; | |
| gss_cred_id_t credHdl; | |
| gss_buffer_desc inToken; | |
| gss_channel_bindings_t cb; | |
| gss_name_t srcName; | |
| gss_buffer_desc outToken; | |
| gss_OID aMech; | |
| OM_uint32 aFlags; | |
| OM_uint32 aTime; | |
| gss_cred_id_t delCred; | |
| jobject jsrcName = NULL; | |
| jobject jdelCred; | |
| jobject jMech; | |
| jboolean setTarget; | |
| gss_name_t targetName; | |
| jobject jtargetName; | |
| TRACE0("[GSSLibStub_acceptContext]"); | |
| contextHdl = contextHdlSave = (gss_ctx_id_t)jlong_to_ptr( | |
| (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext)); | |
| credHdl = (gss_cred_id_t) jlong_to_ptr(pCred); | |
| initGSSBuffer(env, jinToken, &inToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| cb = newGSSCB(env, jcb); | |
| if ((*env)->ExceptionCheck(env)) { | |
| resetGSSBuffer(&inToken); | |
| return NULL; | |
| } | |
| srcName = targetName = GSS_C_NO_NAME; | |
| delCred = GSS_C_NO_CREDENTIAL; | |
| setTarget = (credHdl == GSS_C_NO_CREDENTIAL); | |
| aFlags = 0; | |
| TRACE2( "[GSSLibStub_acceptContext] before: pCred=%" PRIuPTR ", pContext=%" PRIuPTR "", | |
| (uintptr_t) credHdl, (uintptr_t) contextHdl); | |
| /* gss_accept_sec_context(...) => GSS_S_CONTINUE_NEEDED(!), | |
| GSS_S_DEFECTIVE_TOKEN, GSS_S_DEFECTIVE_CREDENTIAL(!), | |
| GSS_S_NO_CRED, GSS_S_CREDENTIALS_EXPIRED, GSS_S_BAD_BINDINGS, | |
| GSS_S_NO_CONTEXT(!), GSS_S_BAD_MIC, GSS_S_OLD_TOKEN, | |
| GSS_S_DUPLICATE_TOKEN, GSS_S_BAD_MECH */ | |
| major = | |
| (*ftab->acceptSecContext)(&minor, &contextHdl, credHdl, | |
| &inToken, cb, &srcName, &aMech, &outToken, | |
| &aFlags, &aTime, &delCred); | |
| /* release intermediate buffers before checking status */ | |
| deleteGSSCB(cb); | |
| resetGSSBuffer(&inToken); | |
| TRACE3("[GSSLibStub_acceptContext] after: pCred=%" PRIuPTR ", pContext=%" PRIuPTR ", pDelegCred=%" PRIuPTR "", | |
| (uintptr_t)credHdl, (uintptr_t)contextHdl, (uintptr_t) delCred); | |
| // update context handle with the latest value if changed | |
| // this is to work with both MIT and Solaris. Former deletes half-built | |
| // context if error occurs | |
| if (contextHdl != contextHdlSave) { | |
| (*env)->CallVoidMethod(env, jcontextSpi, MID_NativeGSSContext_setContext, | |
| ptr_to_jlong(contextHdl)); | |
| TRACE1("[GSSLibStub_acceptContext] set pContext=%" PRIuPTR "", (uintptr_t)contextHdl); | |
| } | |
| if (GSS_ERROR(major) == GSS_S_COMPLETE) { | |
| /* update member values if needed */ | |
| // WORKAROUND for a Heimdal bug | |
| if (delCred == GSS_C_NO_CREDENTIAL) { | |
| aFlags &= 0xfffffffe; | |
| } | |
| (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_flags, aFlags); | |
| TRACE1("[GSSLibStub_acceptContext] set flags=0x%x", aFlags); | |
| if (setTarget) { | |
| major2 = (*ftab->inquireContext)(&minor2, contextHdl, NULL, | |
| &targetName, NULL, NULL, NULL, | |
| NULL, NULL); | |
| checkStatus(env, jobj, major2, minor2, | |
| "[GSSLibStub_acceptContext] inquire"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| jtargetName = (*env)->NewObject(env, CLS_GSSNameElement, | |
| MID_GSSNameElement_ctor, | |
| ptr_to_jlong(targetName), jobj); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| TRACE1("[GSSLibStub_acceptContext] set targetName=%" PRIuPTR "", | |
| (uintptr_t)targetName); | |
| (*env)->SetObjectField(env, jcontextSpi, FID_NativeGSSContext_targetName, | |
| jtargetName); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| } | |
| if (srcName != GSS_C_NO_NAME) { | |
| jsrcName = (*env)->NewObject(env, CLS_GSSNameElement, | |
| MID_GSSNameElement_ctor, | |
| ptr_to_jlong(srcName), jobj); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| TRACE1("[GSSLibStub_acceptContext] set srcName=%" PRIuPTR "", (uintptr_t)srcName); | |
| (*env)->SetObjectField(env, jcontextSpi, FID_NativeGSSContext_srcName, | |
| jsrcName); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| } | |
| if (major == GSS_S_COMPLETE) { | |
| TRACE0("[GSSLibStub_acceptContext] context established"); | |
| (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_lifetime, | |
| getJavaTime(aTime)); | |
| (*env)->SetBooleanField(env, jcontextSpi, | |
| FID_NativeGSSContext_isEstablished, | |
| JNI_TRUE); | |
| jMech = getJavaOID(env, aMech); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| (*env)->SetObjectField(env, jcontextSpi, | |
| FID_NativeGSSContext_actualMech, jMech); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| if (delCred != GSS_C_NO_CREDENTIAL) { | |
| jdelCred = (*env)->NewObject(env, CLS_GSSCredElement, | |
| MID_GSSCredElement_ctor, | |
| ptr_to_jlong(delCred), jsrcName, jMech); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| (*env)->SetObjectField(env, jcontextSpi, | |
| FID_NativeGSSContext_delegatedCred, | |
| jdelCred); | |
| TRACE1("[GSSLibStub_acceptContext] set delegatedCred=%" PRIuPTR "", | |
| (uintptr_t) delCred); | |
| if ((*env)->ExceptionCheck(env)) { | |
| goto error; | |
| } | |
| } | |
| } else if (major & GSS_S_CONTINUE_NEEDED) { | |
| TRACE0("[GSSLibStub_acceptContext] context not established"); | |
| if (aFlags & GSS_C_PROT_READY_FLAG) { | |
| (*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_lifetime, | |
| getJavaTime(aTime)); | |
| } | |
| major -= GSS_S_CONTINUE_NEEDED; | |
| } | |
| } | |
| return getJavaBuffer(env, &outToken); | |
| error: | |
| (*ftab->releaseBuffer)(&minor, &outToken); | |
| if (srcName != GSS_C_NO_NAME) { | |
| (*ftab->releaseName)(&minor, &srcName); | |
| } | |
| if (targetName != GSS_C_NO_NAME) { | |
| (*ftab->releaseName)(&minor, &targetName); | |
| } | |
| if (delCred != GSS_C_NO_CREDENTIAL) { | |
| (*ftab->releaseCred) (&minor, &delCred); | |
| } | |
| return NULL; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: inquireContext | |
| * Signature: (J)[J | |
| */ | |
| JNIEXPORT jlongArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_inquireContext(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext) | |
| { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| gss_name_t srcName, targetName; | |
| OM_uint32 time; | |
| OM_uint32 flags; | |
| int isInitiator, isEstablished; | |
| #if defined (_WIN32) && defined (_MSC_VER) | |
| _Alignas(8) | |
| #endif | |
| jlong result[6]; | |
| jlongArray jresult; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_inquireContext] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| srcName = targetName = GSS_C_NO_NAME; | |
| time = 0; | |
| flags = isInitiator = isEstablished = 0; | |
| /* gss_inquire_context(...) => GSS_S_NO_CONTEXT(!) */ | |
| major = (*ftab->inquireContext)(&minor, contextHdl, &srcName, | |
| &targetName, &time, NULL, &flags, | |
| &isInitiator, &isEstablished); | |
| /* update member values if needed */ | |
| TRACE2("[GSSLibStub_inquireContext] srcName %" PRIuPTR ", targetName %" PRIuPTR "", | |
| (uintptr_t)srcName, (uintptr_t)targetName); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireContext]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| result[0] = ptr_to_jlong(srcName); | |
| result[1] = ptr_to_jlong(targetName); | |
| result[2] = (jlong) isInitiator; | |
| result[3] = (jlong) isEstablished; | |
| result[4] = (jlong) flags; | |
| result[5] = (jlong) getJavaTime(time); | |
| jresult = (*env)->NewLongArray(env, 6); | |
| if (jresult == NULL) { | |
| return NULL; | |
| } | |
| (*env)->SetLongArrayRegion(env, jresult, 0, 6, result); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getContextMech | |
| * Signature: (J)Lorg/ietf/jgss/Oid; | |
| */ | |
| JNIEXPORT jobject JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getContextMech(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext) | |
| { | |
| OM_uint32 minor, major; | |
| gss_OID mech; | |
| gss_ctx_id_t contextHdl; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_getContextMech] %ld", (long int)pContext); | |
| major = (*ftab->inquireContext)(&minor, contextHdl, NULL, NULL, | |
| NULL, &mech, NULL, NULL, NULL); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_getContextMech]"); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return getJavaOID(env, mech); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getContextName | |
| * Signature: (JZ)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getContextName(JNIEnv *env, | |
| jobject jobj, jlong pContext, jboolean isSrc) | |
| { | |
| OM_uint32 minor, major; | |
| gss_name_t nameHdl; | |
| gss_ctx_id_t contextHdl; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE2("[GSSLibStub_getContextName] %" PRIuPTR ", isSrc=%d", | |
| (uintptr_t)contextHdl, isSrc); | |
| nameHdl = GSS_C_NO_NAME; | |
| if (isSrc == JNI_TRUE) { | |
| major = (*ftab->inquireContext)(&minor, contextHdl, &nameHdl, NULL, | |
| NULL, NULL, NULL, NULL, NULL); | |
| } else { | |
| major = (*ftab->inquireContext)(&minor, contextHdl, NULL, &nameHdl, | |
| NULL, NULL, NULL, NULL, NULL); | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireContextAll]"); | |
| /* return immediately if an exception has occurred */ | |
| if ((*env)->ExceptionCheck(env)) { | |
| return jlong_zero; | |
| } | |
| TRACE1("[GSSLibStub_getContextName] pName=%" PRIuPTR "", (uintptr_t) nameHdl); | |
| return ptr_to_jlong(nameHdl); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getContextTime | |
| * Signature: (J)I | |
| */ | |
| JNIEXPORT jint JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getContextTime(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext) { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| OM_uint32 time; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_getContextTime] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) return 0; | |
| /* gss_context_time(...) => GSS_S_CONTEXT_EXPIRED(!), | |
| GSS_S_NO_CONTEXT(!) */ | |
| major = (*ftab->contextTime)(&minor, contextHdl, &time); | |
| if (GSS_ROUTINE_ERROR(major) == GSS_S_CONTEXT_EXPIRED) { | |
| major = GSS_CALLING_ERROR(major) | GSS_SUPPLEMENTARY_INFO(major); | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_getContextTime]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return 0; | |
| } | |
| return getJavaTime(time); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: deleteContext | |
| * Signature: (J)J | |
| */ | |
| JNIEXPORT jlong JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_deleteContext(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext) | |
| { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_deleteContext] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) return ptr_to_jlong(GSS_C_NO_CONTEXT); | |
| /* gss_delete_sec_context(...) => GSS_S_NO_CONTEXT(!) */ | |
| major = (*ftab->deleteSecContext)(&minor, &contextHdl, GSS_C_NO_BUFFER); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_deleteContext]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return jlong_zero; | |
| } | |
| return (jlong) ptr_to_jlong(contextHdl); | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: wrapSizeLimit | |
| * Signature: (JIII)I | |
| */ | |
| JNIEXPORT jint JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_wrapSizeLimit(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext, | |
| jint reqFlag, | |
| jint jqop, | |
| jint joutSize) | |
| { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| OM_uint32 outSize, maxInSize; | |
| gss_qop_t qop; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_wrapSizeLimit] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) { | |
| // Twik per javadoc | |
| checkStatus(env, jobj, GSS_S_NO_CONTEXT, 0, | |
| "[GSSLibStub_wrapSizeLimit]"); | |
| return 0; | |
| } | |
| qop = (gss_qop_t) jqop; | |
| outSize = (OM_uint32) joutSize; | |
| /* gss_wrap_size_limit(...) => GSS_S_NO_CONTEXT(!), GSS_S_CONTEXT_EXPIRED, | |
| GSS_S_BAD_QOP */ | |
| major = (*ftab->wrapSizeLimit)(&minor, contextHdl, reqFlag, | |
| qop, outSize, &maxInSize); | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_wrapSizeLimit]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return 0; | |
| } | |
| return (jint) maxInSize; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: exportContext | |
| * Signature: (J)[B | |
| */ | |
| JNIEXPORT jbyteArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_exportContext(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext) | |
| { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| gss_buffer_desc interProcToken; | |
| jbyteArray jresult; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_exportContext] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) { | |
| // Twik per javadoc | |
| checkStatus(env, jobj, GSS_S_NO_CONTEXT, 0, "[GSSLibStub_exportContext]"); | |
| return NULL; | |
| } | |
| /* gss_export_sec_context(...) => GSS_S_CONTEXT_EXPIRED, | |
| GSS_S_NO_CONTEXT, GSS_S_UNAVAILABLE */ | |
| major = | |
| (*ftab->exportSecContext)(&minor, &contextHdl, &interProcToken); | |
| /* release intermediate buffers */ | |
| jresult = getJavaBuffer(env, &interProcToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_exportContext]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: getMic | |
| * Signature: (JI[B)[B | |
| */ | |
| JNIEXPORT jbyteArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_getMic(JNIEnv *env, jobject jobj, | |
| jlong pContext, jint jqop, | |
| jbyteArray jmsg) | |
| { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| gss_qop_t qop; | |
| gss_buffer_desc msg; | |
| gss_buffer_desc msgToken; | |
| jbyteArray jresult; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_getMic] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) { | |
| // Twik per javadoc | |
| checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_getMic]"); | |
| return NULL; | |
| } | |
| qop = (gss_qop_t) jqop; | |
| initGSSBuffer(env, jmsg, &msg); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| /* gss_get_mic(...) => GSS_S_CONTEXT_EXPIRED, GSS_S_NO_CONTEXT(!), | |
| GSS_S_BAD_QOP */ | |
| major = | |
| (*ftab->getMic)(&minor, contextHdl, qop, &msg, &msgToken); | |
| /* release intermediate buffers */ | |
| resetGSSBuffer(&msg); | |
| jresult = getJavaBuffer(env, &msgToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_getMic]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: verifyMic | |
| * Signature: (J[B[BLorg/ietf/jgss/MessageProp;)V | |
| */ | |
| JNIEXPORT void JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_verifyMic(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext, | |
| jbyteArray jmsgToken, | |
| jbyteArray jmsg, | |
| jobject jprop) | |
| { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| gss_buffer_desc msg; | |
| gss_buffer_desc msgToken; | |
| gss_qop_t qop; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_verifyMic] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) { | |
| // Twik per javadoc | |
| checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, | |
| "[GSSLibStub_verifyMic]"); | |
| return; | |
| } | |
| qop = (gss_qop_t) (*env)->CallIntMethod(env, jprop, MID_MessageProp_getQOP); | |
| if ((*env)->ExceptionCheck(env)) { return; } | |
| initGSSBuffer(env, jmsg, &msg); | |
| if ((*env)->ExceptionCheck(env)) { return; } | |
| initGSSBuffer(env, jmsgToken, &msgToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| resetGSSBuffer(&msg); | |
| return; | |
| } | |
| /* gss_verify_mic(...) => GSS_S_DEFECTIVE_TOKEN, GSS_S_BAD_MIC, | |
| GSS_S_CONTEXT_EXPIRED, GSS_S_DUPLICATE_TOKEN(!), GSS_S_OLD_TOKEN(!), | |
| GSS_S_UNSEQ_TOKEN(!), GSS_S_GAP_TOKEN(!), GSS_S_NO_CONTEXT(!) */ | |
| major = | |
| (*ftab->verifyMic)(&minor, contextHdl, &msg, &msgToken, &qop); | |
| /* release intermediate buffers */ | |
| resetGSSBuffer(&msg); | |
| resetGSSBuffer(&msgToken); | |
| checkStatus(env, jobj, GSS_ERROR(major), minor, "[GSSLibStub_verifyMic]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return; | |
| } | |
| (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setQOP, qop); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return; | |
| } | |
| setSupplementaryInfo(env, jobj, jprop, GSS_SUPPLEMENTARY_INFO(major), | |
| minor); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return; | |
| } | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: wrap | |
| * Signature: (J[BLorg/ietf/jgss/MessageProp;)[B | |
| */ | |
| JNIEXPORT jbyteArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_wrap(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext, | |
| jbyteArray jmsg, | |
| jobject jprop) | |
| { | |
| OM_uint32 minor, major; | |
| jboolean confFlag; | |
| gss_qop_t qop; | |
| gss_buffer_desc msg; | |
| gss_buffer_desc msgToken; | |
| int confState; | |
| gss_ctx_id_t contextHdl; | |
| jbyteArray jresult; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_wrap] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) { | |
| // Twik per javadoc | |
| checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_wrap]"); | |
| return NULL; | |
| } | |
| confFlag = | |
| (*env)->CallBooleanMethod(env, jprop, MID_MessageProp_getPrivacy); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| qop = (gss_qop_t) | |
| (*env)->CallIntMethod(env, jprop, MID_MessageProp_getQOP); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| initGSSBuffer(env, jmsg, &msg); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| /* gss_wrap(...) => GSS_S_CONTEXT_EXPIRED, GSS_S_NO_CONTEXT(!), | |
| GSS_S_BAD_QOP */ | |
| major = (*ftab->wrap)(&minor, contextHdl, confFlag, qop, &msg, &confState, | |
| &msgToken); | |
| /* release intermediate buffers */ | |
| resetGSSBuffer(&msg); | |
| jresult = getJavaBuffer(env, &msgToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, major, minor, "[GSSLibStub_wrap]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setPrivacy, | |
| (confState? JNI_TRUE:JNI_FALSE)); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } | |
| /* | |
| * Class: sun_security_jgss_wrapper_GSSLibStub | |
| * Method: unwrap | |
| * Signature: (J[BLorg/ietf/jgss/MessageProp;)[B | |
| */ | |
| JNIEXPORT jbyteArray JNICALL | |
| Java_sun_security_jgss_wrapper_GSSLibStub_unwrap(JNIEnv *env, | |
| jobject jobj, | |
| jlong pContext, | |
| jbyteArray jmsgToken, | |
| jobject jprop) | |
| { | |
| OM_uint32 minor, major; | |
| gss_ctx_id_t contextHdl; | |
| gss_buffer_desc msgToken; | |
| gss_buffer_desc msg; | |
| int confState; | |
| gss_qop_t qop; | |
| jbyteArray jresult; | |
| contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); | |
| TRACE1("[GSSLibStub_unwrap] %" PRIuPTR "", (uintptr_t)contextHdl); | |
| if (contextHdl == GSS_C_NO_CONTEXT) { | |
| // Twik per javadoc | |
| checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_unwrap]"); | |
| return NULL; | |
| } | |
| initGSSBuffer(env, jmsgToken, &msgToken); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| confState = 0; | |
| qop = GSS_C_QOP_DEFAULT; | |
| /* gss_unwrap(...) => GSS_S_DEFECTIVE_TOKEN, GSS_S_BAD_MIC, | |
| GSS_S_CONTEXT_EXPIRED, GSS_S_DUPLICATE_TOKEN(!), GSS_S_OLD_TOKEN(!), | |
| GSS_S_UNSEQ_TOKEN(!), GSS_S_GAP_TOKEN(!), GSS_S_NO_CONTEXT(!) */ | |
| major = | |
| (*ftab->unwrap)(&minor, contextHdl, &msgToken, &msg, &confState, &qop); | |
| /* release intermediate buffers */ | |
| resetGSSBuffer(&msgToken); | |
| jresult = getJavaBuffer(env, &msg); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| checkStatus(env, jobj, GSS_ERROR(major), minor, "[GSSLibStub_unwrap]"); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| /* update the message prop with relevant info */ | |
| (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setPrivacy, | |
| (confState != 0)); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| (*env)->CallVoidMethod(env, jprop, MID_MessageProp_setQOP, qop); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| setSupplementaryInfo(env, jobj, jprop, GSS_SUPPLEMENTARY_INFO(major), | |
| minor); | |
| if ((*env)->ExceptionCheck(env)) { | |
| return NULL; | |
| } | |
| return jresult; | |
| } |