Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/security/jgss/wrapper/NativeUtil.c
38918 views
/*1* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "NativeUtil.h"26#include "NativeFunc.h"27#include "jlong.h"28#include <jni.h>2930const int JAVA_DUPLICATE_TOKEN_CODE = 19; /* DUPLICATE_TOKEN */31const int JAVA_OLD_TOKEN_CODE = 20; /* OLD_TOKEN */32const int JAVA_UNSEQ_TOKEN_CODE = 21; /* UNSEQ_TOKEN */33const int JAVA_GAP_TOKEN_CODE = 22; /* GAP_TOKEN */34const int JAVA_ERROR_CODE[] = {352, /* BAD_MECH */363, /* BAD_NAME */374, /* BAD_NAMETYPE */381, /* BAD_BINDINGS */395, /* BAD_STATUS */406, /* BAD_MIC */4113, /* NO_CRED */4212, /* NO_CONTEXT */4310, /* DEFECTIVE_TOKEN */449, /* DEFECTIVE_CREDENTIAL */458, /* CREDENTIAL_EXPIRED */467, /* CONTEXT_EXPIRED */4711, /* FAILURE */4814, /* BAD_QOP */4915, /* UNAUTHORIZED */5016, /* UNAVAILABLE */5117, /* DUPLICATE_ELEMENT */5218, /* NAME_NOT_MN */53};54const char SPNEGO_BYTES[] = {550x2b, 0x06, 0x01, 0x05, 0x05, 0x0256};5758jclass CLS_Object;59jclass CLS_String;60jclass CLS_Oid;61jclass CLS_GSSException;62jclass CLS_GSSNameElement;63jclass CLS_GSSCredElement;64jclass CLS_NativeGSSContext;65jclass CLS_SunNativeProvider;66jmethodID MID_String_ctor;67jmethodID MID_Oid_ctor1;68jmethodID MID_Oid_getDER;69jmethodID MID_MessageProp_getPrivacy;70jmethodID MID_MessageProp_getQOP;71jmethodID MID_MessageProp_setPrivacy;72jmethodID MID_MessageProp_setQOP;73jmethodID MID_MessageProp_setSupplementaryStates;74jmethodID MID_GSSException_ctor3;75jmethodID MID_ChannelBinding_getInitiatorAddr;76jmethodID MID_ChannelBinding_getAcceptorAddr;77jmethodID MID_ChannelBinding_getAppData;78jmethodID MID_InetAddress_getAddr;79jmethodID MID_GSSNameElement_ctor;80jmethodID MID_GSSCredElement_ctor;81jmethodID MID_NativeGSSContext_ctor;82jfieldID FID_GSSLibStub_pMech;83jfieldID FID_NativeGSSContext_pContext;84jfieldID FID_NativeGSSContext_srcName;85jfieldID FID_NativeGSSContext_targetName;86jfieldID FID_NativeGSSContext_isInitiator;87jfieldID FID_NativeGSSContext_isEstablished;88jfieldID FID_NativeGSSContext_delegatedCred;89jfieldID FID_NativeGSSContext_flags;90jfieldID FID_NativeGSSContext_lifetime;91jfieldID FID_NativeGSSContext_actualMech;9293int JGSS_DEBUG;9495JNIEXPORT jint JNICALL96JNI_OnLoad(JavaVM *jvm, void *reserved) {97JNIEnv *env;98jclass cls;99100if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {101return JNI_EVERSION; /* JNI version not supported */102}103/* Retrieve and store the classes in global ref */104cls = (*env)->FindClass(env, "java/lang/Object");105if (cls == NULL) {106printf("Couldn't find Object class\n");107return JNI_ERR;108}109CLS_Object = (*env)->NewGlobalRef(env, cls);110if (CLS_Object == NULL) {111return JNI_ERR;112}113cls = (*env)->FindClass(env, "java/lang/String");114if (cls == NULL) {115printf("Couldn't find String class\n");116return JNI_ERR;117}118CLS_String = (*env)->NewGlobalRef(env, cls);119if (CLS_String == NULL) {120return JNI_ERR;121}122cls = (*env)->FindClass(env, "org/ietf/jgss/Oid");123if (cls == NULL) {124printf("Couldn't find org.ietf.jgss.Oid class\n");125return JNI_ERR;126}127CLS_Oid = (*env)->NewGlobalRef(env, cls);128if (CLS_Oid == NULL) {129return JNI_ERR;130}131cls = (*env)->FindClass(env, "org/ietf/jgss/GSSException");132if (cls == NULL) {133printf("Couldn't find org.ietf.jgss.GSSException class\n");134return JNI_ERR;135}136CLS_GSSException = (*env)->NewGlobalRef(env, cls);137if (CLS_GSSException == NULL) {138return JNI_ERR;139}140cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSNameElement");141if (cls == NULL) {142printf("Couldn't find sun.security.jgss.wrapper.GSSNameElement class\n");143return JNI_ERR;144}145CLS_GSSNameElement = (*env)->NewGlobalRef(env, cls);146if (CLS_GSSException == NULL) {147return JNI_ERR;148}149cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSCredElement");150if (cls == NULL) {151printf("Couldn't find sun.security.jgss.wrapper.GSSCredElement class\n");152return JNI_ERR;153}154CLS_GSSCredElement = (*env)->NewGlobalRef(env, cls);155if (CLS_GSSCredElement == NULL) {156return JNI_ERR;157}158cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/NativeGSSContext");159if (cls == NULL) {160printf("Couldn't find sun.security.jgss.wrapper.NativeGSSContext class\n");161return JNI_ERR;162}163CLS_NativeGSSContext = (*env)->NewGlobalRef(env, cls);164if (CLS_NativeGSSContext == NULL) {165return JNI_ERR;166}167cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/SunNativeProvider");168if (cls == NULL) {169printf("Couldn't find sun.security.jgss.wrapper.SunNativeProvider class\n");170return JNI_ERR;171}172CLS_SunNativeProvider = (*env)->NewGlobalRef(env, cls);173if (CLS_SunNativeProvider == NULL) {174return JNI_ERR;175}176/* Compute and cache the method ID */177MID_String_ctor = (*env)->GetMethodID(env, CLS_String,178"<init>", "([B)V");179if (MID_String_ctor == NULL) {180printf("Couldn't find String(byte[]) constructor\n");181return JNI_ERR;182}183MID_Oid_ctor1 =184(*env)->GetMethodID(env, CLS_Oid, "<init>", "([B)V");185if (MID_Oid_ctor1 == NULL) {186printf("Couldn't find Oid(byte[]) constructor\n");187return JNI_ERR;188}189MID_Oid_getDER = (*env)->GetMethodID(env, CLS_Oid, "getDER", "()[B");190if (MID_Oid_getDER == NULL) {191printf("Couldn't find Oid.getDER() method\n");192return JNI_ERR;193}194cls = (*env)->FindClass(env, "org/ietf/jgss/MessageProp");195if (cls == NULL) {196printf("Couldn't find org.ietf.jgss.MessageProp class\n");197return JNI_ERR;198}199MID_MessageProp_getPrivacy =200(*env)->GetMethodID(env, cls, "getPrivacy", "()Z");201if (MID_MessageProp_getPrivacy == NULL) {202printf("Couldn't find MessageProp.getPrivacy() method\n");203return JNI_ERR;204}205MID_MessageProp_getQOP = (*env)->GetMethodID(env, cls, "getQOP", "()I");206if (MID_MessageProp_getQOP == NULL) {207printf("Couldn't find MessageProp.getQOP() method\n");208return JNI_ERR;209}210MID_MessageProp_setPrivacy =211(*env)->GetMethodID(env, cls, "setPrivacy", "(Z)V");212if (MID_MessageProp_setPrivacy == NULL) {213printf("Couldn't find MessageProp.setPrivacy(boolean) method\n");214return JNI_ERR;215}216MID_MessageProp_setQOP = (*env)->GetMethodID(env, cls, "setQOP", "(I)V");217if (MID_MessageProp_setQOP == NULL) {218printf("Couldn't find MessageProp.setQOP(int) method\n");219return JNI_ERR;220}221MID_MessageProp_setSupplementaryStates =222(*env)->GetMethodID(env, cls, "setSupplementaryStates",223"(ZZZZILjava/lang/String;)V");224if (MID_MessageProp_setSupplementaryStates == NULL) {225printf("Couldn't find MessageProp.setSupplementaryStates(...) method\n");226return JNI_ERR;227}228MID_GSSException_ctor3 = (*env)->GetMethodID229(env, CLS_GSSException, "<init>", "(IILjava/lang/String;)V");230if (MID_GSSException_ctor3 == NULL) {231printf("Couldn't find GSSException(int, int, String) constructor\n");232return JNI_ERR;233}234cls = (*env)->FindClass(env, "org/ietf/jgss/ChannelBinding");235if (cls == NULL) {236printf("Couldn't find org.ietf.jgss.ChannelBinding class\n");237return JNI_ERR;238}239MID_ChannelBinding_getInitiatorAddr =240(*env)->GetMethodID(env, cls, "getInitiatorAddress",241"()Ljava/net/InetAddress;");242if (MID_ChannelBinding_getInitiatorAddr == NULL) {243printf("Couldn't find ChannelBinding.getInitiatorAddress() method\n");244return JNI_ERR;245}246MID_ChannelBinding_getAcceptorAddr =247(*env)->GetMethodID(env, cls, "getAcceptorAddress",248"()Ljava/net/InetAddress;");249if (MID_ChannelBinding_getAcceptorAddr == NULL) {250printf("Couldn't find ChannelBinding.getAcceptorAddress() method\n");251return JNI_ERR;252}253MID_ChannelBinding_getAppData =254(*env)->GetMethodID(env, cls, "getApplicationData", "()[B");255if (MID_ChannelBinding_getAppData == NULL) {256printf("Couldn't find ChannelBinding.getApplicationData() method\n");257return JNI_ERR;258}259cls = (*env)->FindClass(env, "java/net/InetAddress");260if (cls == NULL) {261printf("Couldn't find java.net.InetAddress class\n");262return JNI_ERR;263}264MID_InetAddress_getAddr = (*env)->GetMethodID(env, cls, "getAddress",265"()[B");266if (MID_InetAddress_getAddr == NULL) {267printf("Couldn't find InetAddress.getAddress() method\n");268return JNI_ERR;269}270MID_GSSNameElement_ctor =271(*env)->GetMethodID(env, CLS_GSSNameElement,272"<init>", "(JLsun/security/jgss/wrapper/GSSLibStub;)V");273if (MID_GSSNameElement_ctor == NULL) {274printf("Couldn't find GSSNameElement(long, GSSLibStub) constructor\n");275return JNI_ERR;276}277MID_GSSCredElement_ctor =278(*env)->GetMethodID(env, CLS_GSSCredElement, "<init>",279"(JLsun/security/jgss/wrapper/GSSNameElement;Lorg/ietf/jgss/Oid;)V");280if (MID_GSSCredElement_ctor == NULL) {281printf("Couldn't find GSSCredElement(long, GSSLibStub) constructor\n");282return JNI_ERR;283}284MID_NativeGSSContext_ctor =285(*env)->GetMethodID(env, CLS_NativeGSSContext, "<init>",286"(JLsun/security/jgss/wrapper/GSSLibStub;)V");287if (MID_NativeGSSContext_ctor == NULL) {288printf("Couldn't find NativeGSSContext(long, GSSLibStub) constructor\n");289return JNI_ERR;290}291/* Compute and cache the field ID */292cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSLibStub");293if (cls == NULL) {294printf("Couldn't find sun.security.jgss.wrapper.GSSLibStub class\n");295return JNI_ERR;296}297FID_GSSLibStub_pMech =298(*env)->GetFieldID(env, cls, "pMech", "J");299if (FID_GSSLibStub_pMech == NULL) {300printf("Couldn't find GSSLibStub.pMech field\n");301return JNI_ERR;302}303FID_NativeGSSContext_pContext =304(*env)->GetFieldID(env, CLS_NativeGSSContext, "pContext", "J");305if (FID_NativeGSSContext_pContext == NULL) {306printf("Couldn't find NativeGSSContext.pContext field\n");307return JNI_ERR;308}309FID_NativeGSSContext_srcName =310(*env)->GetFieldID(env, CLS_NativeGSSContext, "srcName",311"Lsun/security/jgss/wrapper/GSSNameElement;");312if (FID_NativeGSSContext_srcName == NULL) {313printf("Couldn't find NativeGSSContext.srcName field\n");314return JNI_ERR;315}316FID_NativeGSSContext_targetName =317(*env)->GetFieldID(env, CLS_NativeGSSContext, "targetName",318"Lsun/security/jgss/wrapper/GSSNameElement;");319if (FID_NativeGSSContext_targetName == NULL) {320printf("Couldn't find NativeGSSContext.targetName field\n");321return JNI_ERR;322}323FID_NativeGSSContext_isInitiator =324(*env)->GetFieldID(env, CLS_NativeGSSContext, "isInitiator", "Z");325if (FID_NativeGSSContext_isInitiator == NULL) {326printf("Couldn't find NativeGSSContext.isInitiator field\n");327return JNI_ERR;328}329FID_NativeGSSContext_isEstablished =330(*env)->GetFieldID(env, CLS_NativeGSSContext, "isEstablished", "Z");331if (FID_NativeGSSContext_isEstablished == NULL) {332printf("Couldn't find NativeGSSContext.isEstablished field\n");333return JNI_ERR;334}335FID_NativeGSSContext_delegatedCred =336(*env)->GetFieldID(env, CLS_NativeGSSContext, "delegatedCred",337"Lsun/security/jgss/wrapper/GSSCredElement;");338if (FID_NativeGSSContext_delegatedCred == NULL) {339printf("Couldn't find NativeGSSContext.delegatedCred field\n");340return JNI_ERR;341}342FID_NativeGSSContext_flags =343(*env)->GetFieldID(env, CLS_NativeGSSContext, "flags", "I");344if (FID_NativeGSSContext_flags == NULL) {345printf("Couldn't find NativeGSSContext.flags field\n");346return JNI_ERR;347}348FID_NativeGSSContext_lifetime =349(*env)->GetFieldID(env, CLS_NativeGSSContext, "lifetime", "I");350if (FID_NativeGSSContext_lifetime == NULL) {351printf("Couldn't find NativeGSSContext.lifetime field\n");352return JNI_ERR;353}354FID_NativeGSSContext_actualMech =355(*env)->GetFieldID(env, CLS_NativeGSSContext, "actualMech",356"Lorg/ietf/jgss/Oid;");357if (FID_NativeGSSContext_actualMech == NULL) {358printf("Couldn't find NativeGSSContext.actualMech field\n");359return JNI_ERR;360}361return JNI_VERSION_1_2;362}363364JNIEXPORT void JNICALL365JNI_OnUnload(JavaVM *jvm, void *reserved) {366JNIEnv *env;367368if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {369return;370}371/* Delete the global refs */372(*env)->DeleteGlobalRef(env, CLS_Object);373(*env)->DeleteGlobalRef(env, CLS_String);374(*env)->DeleteGlobalRef(env, CLS_Oid);375(*env)->DeleteGlobalRef(env, CLS_GSSException);376(*env)->DeleteGlobalRef(env, CLS_GSSNameElement);377(*env)->DeleteGlobalRef(env, CLS_GSSCredElement);378(*env)->DeleteGlobalRef(env, CLS_SunNativeProvider);379return;380}381382const OM_uint32 JAVA_MAX = GSS_C_INDEFINITE/2;383384/*385* Utility routine for converting the C unsigned integer time386* to Java signed integer time.387*/388jint getJavaTime(OM_uint32 ctime) {389jint result;390391/* special handle values equals or more than JAVA_MAX */392if (ctime == GSS_C_INDEFINITE) {393result = JAVA_MAX;394} else if (ctime >= JAVA_MAX) {395result = JAVA_MAX-1;396} else {397result = ctime;398}399return result;400}401/*402* Utility routine for converting the Java signed integer time403* to C unsigned integer time.404*/405OM_uint32 getGSSTime(jint jtime) {406OM_uint32 result;407408/* special handle values equal to JAVA_MAX */409if (jtime == (jint)JAVA_MAX) {410result = GSS_C_INDEFINITE;411} else {412result = jtime;413}414return result;415}416/*417* Utility routine for mapping the C error code to the418* Java one. The routine errors really should have419* shared the same values but unfortunately don't.420*/421jint getJavaErrorCode(int cNonCallingErr) {422int cRoutineErr, cSuppStatus;423/* map the routine errors */424cRoutineErr = GSS_ROUTINE_ERROR(cNonCallingErr) >> 16;425if (cRoutineErr != GSS_S_COMPLETE) {426return JAVA_ERROR_CODE[cRoutineErr-1];427}428/* map the supplementary infos */429cSuppStatus = GSS_SUPPLEMENTARY_INFO(cNonCallingErr);430if (cSuppStatus & GSS_S_DUPLICATE_TOKEN) {431return JAVA_DUPLICATE_TOKEN_CODE;432} else if (cSuppStatus & GSS_S_OLD_TOKEN) {433return JAVA_OLD_TOKEN_CODE;434} else if (cSuppStatus & GSS_S_UNSEQ_TOKEN) {435return JAVA_UNSEQ_TOKEN_CODE;436} else if (cSuppStatus & GSS_S_GAP_TOKEN) {437return JAVA_GAP_TOKEN_CODE;438}439return GSS_S_COMPLETE;440}441442443/* Throws a Java Exception by name */444void throwByName(JNIEnv *env, const char *name, const char *msg) {445jclass cls = (*env)->FindClass(env, name);446447if (cls != NULL) {448(*env)->ThrowNew(env, cls, msg);449}450}451452void throwOutOfMemoryError(JNIEnv *env, const char *message) {453throwByName(env, "java/lang/OutOfMemoryError", message);454}455456/*457* Utility routine for creating a java.lang.String object458* using the specified gss_buffer_t structure. The specified459* gss_buffer_t structure is always released.460*/461jstring getJavaString(JNIEnv *env, gss_buffer_t bytes) {462jstring result = NULL;463OM_uint32 minor;464int len;465jbyteArray jbytes;466467if (bytes != NULL) {468/* constructs the String object with new String(byte[])469NOTE: do NOT include the trailing NULL */470len = bytes->length;471jbytes = (*env)->NewByteArray(env, len);472if (jbytes == NULL) {473goto finish;474}475476(*env)->SetByteArrayRegion(env, jbytes, 0, len, (jbyte *) bytes->value);477if ((*env)->ExceptionCheck(env)) {478goto finish;479}480481result = (*env)->NewObject(env, CLS_String, MID_String_ctor,482jbytes);483finish:484(*env)->DeleteLocalRef(env, jbytes);485(*ftab->releaseBuffer)(&minor, bytes);486return result;487} /* else fall through */488return NULL;489}490/*491* Utility routine for generate message for the specified minor492* status code.493*/494jstring getMinorMessage(JNIEnv *env, jobject jstub, OM_uint32 statusValue) {495OM_uint32 messageContext, minor, major;496gss_buffer_desc statusString;497gss_OID mech;498jstring msg;499500messageContext = 0;501if (jstub != NULL) {502mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jstub, FID_GSSLibStub_pMech));503} else {504mech = GSS_C_NO_OID;505}506507/* gss_display_status(...) => GSS_S_BAD_MECH, GSS_S_BAD_STATUS */508// TBD: check messageContext value and repeat the call if necessary509major = (*ftab->displayStatus)(&minor, statusValue, GSS_C_MECH_CODE, mech,510&messageContext, &statusString);511512return getJavaString(env, &statusString);513}514515/*516* Utility routine checking the specified major and minor517* status codes. GSSExceptions will be thrown if they are518* not GSS_S_COMPLETE (i.e. 0).519*/520void checkStatus(JNIEnv *env, jobject jstub, OM_uint32 major,521OM_uint32 minor, char* methodName) {522int callingErr, routineErr, supplementaryInfo;523jint jmajor, jminor;524char* msg;525jstring jmsg;526jthrowable gssEx;527528if (major == GSS_S_COMPLETE) return;529530callingErr = GSS_CALLING_ERROR(major);531routineErr = GSS_ROUTINE_ERROR(major);532supplementaryInfo = GSS_SUPPLEMENTARY_INFO(major);533534TRACE3("%s Status major/minor = %x/%d", methodName, major, minor);535TRACE3("c/r/s = %d/%d/%d ", callingErr>>24, routineErr>>16,536supplementaryInfo);537538jmajor = getJavaErrorCode(routineErr | supplementaryInfo);539jminor = minor;540if (jmajor != GSS_S_COMPLETE) {541jmsg = NULL;542if (minor != 0) {543jmsg = getMinorMessage(env, jstub, minor);544if ((*env)->ExceptionCheck(env)) {545return;546}547}548549gssEx = (*env)->NewObject(env, CLS_GSSException,550MID_GSSException_ctor3,551jmajor, jminor, jmsg);552if (gssEx != NULL) {553(*env)->Throw(env, gssEx);554}555} else {556/* Error in calling the GSS api */557if (callingErr == GSS_S_CALL_INACCESSIBLE_READ) {558msg = "A required input parameter cannot be read";559} else if (callingErr == GSS_S_CALL_INACCESSIBLE_WRITE) {560msg = "A required output parameter cannot be write";561} else {562msg = "A parameter was malformed";563}564jmajor = 13; /* use GSSException.FAILURE for now */565jmsg = (*env)->NewStringUTF(env, msg);566if (jmsg == NULL) {567return;568}569gssEx = (*env)->NewObject(env, CLS_GSSException,570MID_GSSException_ctor3,571jmajor, jminor, jmsg);572if (gssEx != NULL) {573(*env)->Throw(env, gssEx);574}575}576}577578/*579* Utility routine for initializing gss_buffer_t structure580* with the byte[] in the specified jbyteArray object.581* NOTE: must call resetGSSBuffer() to free up the resources582* inside the gss_buffer_t structure.583*/584void initGSSBuffer(JNIEnv *env, jbyteArray jbytes,585gss_buffer_t cbytes) {586587int len;588void* value;589590if (jbytes != NULL) {591len = (*env)->GetArrayLength(env, jbytes);592value = malloc(len);593if (value == NULL) {594throwOutOfMemoryError(env, NULL);595return;596} else {597(*env)->GetByteArrayRegion(env, jbytes, 0, len, value);598if ((*env)->ExceptionCheck(env)) {599free(value);600return;601} else {602cbytes->length = len;603cbytes->value = value;604}605}606} else {607cbytes->length = 0;608cbytes->value = NULL;609}610}611612/*613* Utility routine for freeing the bytes malloc'ed614* in initGSSBuffer() method.615* NOTE: used in conjunction with initGSSBuffer(...).616*/617void resetGSSBuffer(gss_buffer_t cbytes) {618if ((cbytes != NULL) && (cbytes != GSS_C_NO_BUFFER)) {619free(cbytes->value);620cbytes->length = 0;621cbytes->value = NULL;622}623}624625/*626* Utility routine for creating a jbyteArray object using627* the byte[] value in specified gss_buffer_t structure.628* NOTE: the specified gss_buffer_t structure is always629* released.630*/631jbyteArray getJavaBuffer(JNIEnv *env, gss_buffer_t cbytes) {632jbyteArray result = NULL;633OM_uint32 minor; // don't care, just so it compiles634635if (cbytes != NULL) {636if ((cbytes != GSS_C_NO_BUFFER) && (cbytes->length != 0)) {637result = (*env)->NewByteArray(env, cbytes->length);638if (result == NULL) {639goto finish;640}641(*env)->SetByteArrayRegion(env, result, 0, cbytes->length,642cbytes->value);643if ((*env)->ExceptionCheck(env)) {644result = NULL;645}646}647finish:648(*ftab->releaseBuffer)(&minor, cbytes);649return result;650}651return NULL;652}653654/*655* Utility routine for creating a non-mech gss_OID using656* the specified org.ietf.jgss.Oid object.657* NOTE: must call deleteGSSOID(...) to free up the gss_OID.658*/659gss_OID newGSSOID(JNIEnv *env, jobject jOid) {660jbyteArray jbytes;661gss_OID cOid;662jthrowable gssEx;663if (jOid != NULL) {664jbytes = (*env)->CallObjectMethod(env, jOid, MID_Oid_getDER);665if ((*env)->ExceptionCheck(env)) {666return GSS_C_NO_OID;667}668cOid = malloc(sizeof(struct gss_OID_desc_struct));669if (cOid == NULL) {670throwOutOfMemoryError(env,NULL);671return GSS_C_NO_OID;672}673cOid->length = (*env)->GetArrayLength(env, jbytes) - 2;674cOid->elements = malloc(cOid->length);675if (cOid->elements == NULL) {676throwOutOfMemoryError(env,NULL);677goto cleanup;678}679(*env)->GetByteArrayRegion(env, jbytes, 2, cOid->length,680cOid->elements);681if ((*env)->ExceptionCheck(env)) {682goto cleanup;683}684return cOid;685} else {686return GSS_C_NO_OID;687}688cleanup:689(*env)->DeleteLocalRef(env, jbytes);690free(cOid->elements);691free(cOid);692return GSS_C_NO_OID;693}694695/*696* Utility routine for releasing the specified gss_OID697* structure.698* NOTE: used in conjunction with newGSSOID(...).699*/700void deleteGSSOID(gss_OID oid) {701if (oid != GSS_C_NO_OID) {702free(oid->elements);703free(oid);704}705}706707/*708* Utility routine for creating a org.ietf.jgss.Oid709* object using the specified gss_OID structure.710*/711jobject getJavaOID(JNIEnv *env, gss_OID cOid) {712int cLen;713char oidHdr[2];714jbyteArray jbytes;715jobject result = NULL;716717if ((cOid == NULL) || (cOid == GSS_C_NO_OID)) {718return NULL;719}720cLen = cOid->length;721oidHdr[0] = 6;722oidHdr[1] = cLen;723jbytes = (*env)->NewByteArray(env, cLen+2);724if (jbytes == NULL) {725return NULL;726}727(*env)->SetByteArrayRegion(env, jbytes, 0, 2, (jbyte *) oidHdr);728if ((*env)->ExceptionCheck(env)) {729return NULL;730}731(*env)->SetByteArrayRegion(env, jbytes, 2, cLen, (jbyte *) cOid->elements);732if ((*env)->ExceptionCheck(env)) {733return NULL;734}735result = (*env)->NewObject(env, CLS_Oid, MID_Oid_ctor1, jbytes);736if ((*env)->ExceptionCheck(env)) {737return NULL;738}739(*env)->DeleteLocalRef(env, jbytes);740return result;741}742/*743* Utility routine for creating a gss_OID_set structure744* using the specified gss_OID.745* NOTE: need to call deleteGSSOIDSet(...) afterwards746* to release the created gss_OID_set structure.747*/748gss_OID_set newGSSOIDSet(gss_OID oid) {749gss_OID_set oidSet;750OM_uint32 minor; // don't care; just so it compiles751752if (oid->length != 6 ||753memcmp(oid->elements, SPNEGO_BYTES, 6) != 0) {754(*ftab->createEmptyOidSet)(&minor, &oidSet);755(*ftab->addOidSetMember)(&minor, oid, &oidSet);756return oidSet;757} else {758// Use all mechs for SPNEGO in order to work with759// various native GSS impls760return (ftab->mechs);761}762}763/*764* Utility routine for releasing a gss_OID_set structure.765* NOTE: used in conjunction with newGSSOIDSet(...).766*/767void deleteGSSOIDSet(gss_OID_set oidSet) {768OM_uint32 minor; /* don't care; just so it compiles */769770if ((oidSet != ftab->mechs) &&771(oidSet != NULL) && (oidSet != GSS_C_NO_OID_SET)) {772(*ftab->releaseOidSet)(&minor, &oidSet);773}774}775/*776* Utility routine for creating a org.ietf.jgss.Oid[]777* using the specified gss_OID_set structure.778*/779jobjectArray getJavaOIDArray(JNIEnv *env, gss_OID_set cOidSet) {780int numOfOids = 0;781jobjectArray jOidSet;782jobject jOid;783int i;784jthrowable gssEx;785786if (cOidSet != NULL && cOidSet != GSS_C_NO_OID_SET) {787numOfOids = cOidSet->count;788jOidSet = (*env)->NewObjectArray(env, numOfOids, CLS_Oid, NULL);789if ((*env)->ExceptionCheck(env)) {790return NULL;791}792for (i = 0; i < numOfOids; i++) {793jOid = getJavaOID(env, &(cOidSet->elements[i]));794if ((*env)->ExceptionCheck(env)) {795return NULL;796}797(*env)->SetObjectArrayElement(env, jOidSet, i, jOid);798if ((*env)->ExceptionCheck(env)) {799return NULL;800}801(*env)->DeleteLocalRef(env, jOid);802}803return jOidSet;804}805return NULL;806}807808int sameMech(gss_OID mech, gss_OID mech2) {809int result = JNI_FALSE; // default to not equal810811if (mech->length == mech2->length) {812result = (memcmp(mech->elements, mech2->elements, mech->length) == 0);813}814return result;815}816817818