Path: blob/master/src/java.security.jgss/share/native/libj2gss/NativeUtil.c
41149 views
/*1* Copyright (c) 2005, 2018, 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>29#include "jni_util.h"3031const int JAVA_DUPLICATE_TOKEN_CODE = 19; /* DUPLICATE_TOKEN */32const int JAVA_OLD_TOKEN_CODE = 20; /* OLD_TOKEN */33const int JAVA_UNSEQ_TOKEN_CODE = 21; /* UNSEQ_TOKEN */34const int JAVA_GAP_TOKEN_CODE = 22; /* GAP_TOKEN */35const int JAVA_ERROR_CODE[] = {362, /* BAD_MECH */373, /* BAD_NAME */384, /* BAD_NAMETYPE */391, /* BAD_BINDINGS */405, /* BAD_STATUS */416, /* BAD_MIC */4213, /* NO_CRED */4312, /* NO_CONTEXT */4410, /* DEFECTIVE_TOKEN */459, /* DEFECTIVE_CREDENTIAL */468, /* CREDENTIAL_EXPIRED */477, /* CONTEXT_EXPIRED */4811, /* FAILURE */4914, /* BAD_QOP */5015, /* UNAUTHORIZED */5116, /* UNAVAILABLE */5217, /* DUPLICATE_ELEMENT */5318, /* NAME_NOT_MN */54};55const char SPNEGO_BYTES[] = {560x2b, 0x06, 0x01, 0x05, 0x05, 0x0257};5859jclass CLS_Object;60jclass CLS_String;61jclass CLS_Oid;62jclass CLS_GSSException;63jclass CLS_GSSNameElement;64jclass CLS_GSSCredElement;65jclass CLS_NativeGSSContext;66jclass CLS_SunNativeProvider;67jmethodID MID_String_ctor;68jmethodID MID_Oid_ctor1;69jmethodID MID_Oid_getDER;70jmethodID MID_MessageProp_getPrivacy;71jmethodID MID_MessageProp_getQOP;72jmethodID MID_MessageProp_setPrivacy;73jmethodID MID_MessageProp_setQOP;74jmethodID MID_MessageProp_setSupplementaryStates;75jmethodID MID_GSSException_ctor3;76jmethodID MID_ChannelBinding_getInitiatorAddr;77jmethodID MID_ChannelBinding_getAcceptorAddr;78jmethodID MID_ChannelBinding_getAppData;79jmethodID MID_InetAddress_getAddr;80jmethodID MID_GSSNameElement_ctor;81jmethodID MID_GSSCredElement_ctor;82jmethodID MID_NativeGSSContext_ctor;83jfieldID FID_GSSLibStub_pMech;84jfieldID FID_NativeGSSContext_pContext;85jfieldID FID_NativeGSSContext_srcName;86jfieldID FID_NativeGSSContext_targetName;87jfieldID FID_NativeGSSContext_isInitiator;88jfieldID FID_NativeGSSContext_isEstablished;89jfieldID FID_NativeGSSContext_delegatedCred;90jfieldID FID_NativeGSSContext_flags;91jfieldID FID_NativeGSSContext_lifetime;92jfieldID FID_NativeGSSContext_actualMech;9394int JGSS_DEBUG;9596JNIEXPORT jint JNICALL97DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) {98JNIEnv *env;99jclass cls;100101if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {102return JNI_EVERSION; /* JNI version not supported */103}104/* Retrieve and store the classes in global ref */105cls = (*env)->FindClass(env, "java/lang/Object");106if (cls == NULL) {107printf("Couldn't find Object class\n");108return JNI_ERR;109}110CLS_Object = (*env)->NewGlobalRef(env, cls);111if (CLS_Object == NULL) {112return JNI_ERR;113}114cls = (*env)->FindClass(env, "java/lang/String");115if (cls == NULL) {116printf("Couldn't find String class\n");117return JNI_ERR;118}119CLS_String = (*env)->NewGlobalRef(env, cls);120if (CLS_String == NULL) {121return JNI_ERR;122}123cls = (*env)->FindClass(env, "org/ietf/jgss/Oid");124if (cls == NULL) {125printf("Couldn't find org.ietf.jgss.Oid class\n");126return JNI_ERR;127}128CLS_Oid = (*env)->NewGlobalRef(env, cls);129if (CLS_Oid == NULL) {130return JNI_ERR;131}132cls = (*env)->FindClass(env, "org/ietf/jgss/GSSException");133if (cls == NULL) {134printf("Couldn't find org.ietf.jgss.GSSException class\n");135return JNI_ERR;136}137CLS_GSSException = (*env)->NewGlobalRef(env, cls);138if (CLS_GSSException == NULL) {139return JNI_ERR;140}141cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSNameElement");142if (cls == NULL) {143printf("Couldn't find sun.security.jgss.wrapper.GSSNameElement class\n");144return JNI_ERR;145}146CLS_GSSNameElement = (*env)->NewGlobalRef(env, cls);147if (CLS_GSSNameElement == NULL) {148return JNI_ERR;149}150cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSCredElement");151if (cls == NULL) {152printf("Couldn't find sun.security.jgss.wrapper.GSSCredElement class\n");153return JNI_ERR;154}155CLS_GSSCredElement = (*env)->NewGlobalRef(env, cls);156if (CLS_GSSCredElement == NULL) {157return JNI_ERR;158}159cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/NativeGSSContext");160if (cls == NULL) {161printf("Couldn't find sun.security.jgss.wrapper.NativeGSSContext class\n");162return JNI_ERR;163}164CLS_NativeGSSContext = (*env)->NewGlobalRef(env, cls);165if (CLS_NativeGSSContext == NULL) {166return JNI_ERR;167}168cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/SunNativeProvider");169if (cls == NULL) {170printf("Couldn't find sun.security.jgss.wrapper.SunNativeProvider class\n");171return JNI_ERR;172}173CLS_SunNativeProvider = (*env)->NewGlobalRef(env, cls);174if (CLS_SunNativeProvider == NULL) {175return JNI_ERR;176}177/* Compute and cache the method ID */178MID_String_ctor = (*env)->GetMethodID(env, CLS_String,179"<init>", "([B)V");180if (MID_String_ctor == NULL) {181printf("Couldn't find String(byte[]) constructor\n");182return JNI_ERR;183}184MID_Oid_ctor1 =185(*env)->GetMethodID(env, CLS_Oid, "<init>", "([B)V");186if (MID_Oid_ctor1 == NULL) {187printf("Couldn't find Oid(byte[]) constructor\n");188return JNI_ERR;189}190MID_Oid_getDER = (*env)->GetMethodID(env, CLS_Oid, "getDER", "()[B");191if (MID_Oid_getDER == NULL) {192printf("Couldn't find Oid.getDER() method\n");193return JNI_ERR;194}195cls = (*env)->FindClass(env, "org/ietf/jgss/MessageProp");196if (cls == NULL) {197printf("Couldn't find org.ietf.jgss.MessageProp class\n");198return JNI_ERR;199}200MID_MessageProp_getPrivacy =201(*env)->GetMethodID(env, cls, "getPrivacy", "()Z");202if (MID_MessageProp_getPrivacy == NULL) {203printf("Couldn't find MessageProp.getPrivacy() method\n");204return JNI_ERR;205}206MID_MessageProp_getQOP = (*env)->GetMethodID(env, cls, "getQOP", "()I");207if (MID_MessageProp_getQOP == NULL) {208printf("Couldn't find MessageProp.getQOP() method\n");209return JNI_ERR;210}211MID_MessageProp_setPrivacy =212(*env)->GetMethodID(env, cls, "setPrivacy", "(Z)V");213if (MID_MessageProp_setPrivacy == NULL) {214printf("Couldn't find MessageProp.setPrivacy(boolean) method\n");215return JNI_ERR;216}217MID_MessageProp_setQOP = (*env)->GetMethodID(env, cls, "setQOP", "(I)V");218if (MID_MessageProp_setQOP == NULL) {219printf("Couldn't find MessageProp.setQOP(int) method\n");220return JNI_ERR;221}222MID_MessageProp_setSupplementaryStates =223(*env)->GetMethodID(env, cls, "setSupplementaryStates",224"(ZZZZILjava/lang/String;)V");225if (MID_MessageProp_setSupplementaryStates == NULL) {226printf("Couldn't find MessageProp.setSupplementaryStates(...) method\n");227return JNI_ERR;228}229MID_GSSException_ctor3 = (*env)->GetMethodID230(env, CLS_GSSException, "<init>", "(IILjava/lang/String;)V");231if (MID_GSSException_ctor3 == NULL) {232printf("Couldn't find GSSException(int, int, String) constructor\n");233return JNI_ERR;234}235cls = (*env)->FindClass(env, "org/ietf/jgss/ChannelBinding");236if (cls == NULL) {237printf("Couldn't find org.ietf.jgss.ChannelBinding class\n");238return JNI_ERR;239}240MID_ChannelBinding_getInitiatorAddr =241(*env)->GetMethodID(env, cls, "getInitiatorAddress",242"()Ljava/net/InetAddress;");243if (MID_ChannelBinding_getInitiatorAddr == NULL) {244printf("Couldn't find ChannelBinding.getInitiatorAddress() method\n");245return JNI_ERR;246}247MID_ChannelBinding_getAcceptorAddr =248(*env)->GetMethodID(env, cls, "getAcceptorAddress",249"()Ljava/net/InetAddress;");250if (MID_ChannelBinding_getAcceptorAddr == NULL) {251printf("Couldn't find ChannelBinding.getAcceptorAddress() method\n");252return JNI_ERR;253}254MID_ChannelBinding_getAppData =255(*env)->GetMethodID(env, cls, "getApplicationData", "()[B");256if (MID_ChannelBinding_getAppData == NULL) {257printf("Couldn't find ChannelBinding.getApplicationData() method\n");258return JNI_ERR;259}260cls = (*env)->FindClass(env, "java/net/InetAddress");261if (cls == NULL) {262printf("Couldn't find java.net.InetAddress class\n");263return JNI_ERR;264}265MID_InetAddress_getAddr = (*env)->GetMethodID(env, cls, "getAddress",266"()[B");267if (MID_InetAddress_getAddr == NULL) {268printf("Couldn't find InetAddress.getAddress() method\n");269return JNI_ERR;270}271MID_GSSNameElement_ctor =272(*env)->GetMethodID(env, CLS_GSSNameElement,273"<init>", "(JLsun/security/jgss/wrapper/GSSLibStub;)V");274if (MID_GSSNameElement_ctor == NULL) {275printf("Couldn't find GSSNameElement(long, GSSLibStub) constructor\n");276return JNI_ERR;277}278MID_GSSCredElement_ctor =279(*env)->GetMethodID(env, CLS_GSSCredElement, "<init>",280"(JLsun/security/jgss/wrapper/GSSNameElement;Lorg/ietf/jgss/Oid;)V");281if (MID_GSSCredElement_ctor == NULL) {282printf("Couldn't find GSSCredElement(long, GSSLibStub) constructor\n");283return JNI_ERR;284}285MID_NativeGSSContext_ctor =286(*env)->GetMethodID(env, CLS_NativeGSSContext, "<init>",287"(JLsun/security/jgss/wrapper/GSSLibStub;)V");288if (MID_NativeGSSContext_ctor == NULL) {289printf("Couldn't find NativeGSSContext(long, GSSLibStub) constructor\n");290return JNI_ERR;291}292/* Compute and cache the field ID */293cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSLibStub");294if (cls == NULL) {295printf("Couldn't find sun.security.jgss.wrapper.GSSLibStub class\n");296return JNI_ERR;297}298FID_GSSLibStub_pMech =299(*env)->GetFieldID(env, cls, "pMech", "J");300if (FID_GSSLibStub_pMech == NULL) {301printf("Couldn't find GSSLibStub.pMech field\n");302return JNI_ERR;303}304FID_NativeGSSContext_pContext =305(*env)->GetFieldID(env, CLS_NativeGSSContext, "pContext", "J");306if (FID_NativeGSSContext_pContext == NULL) {307printf("Couldn't find NativeGSSContext.pContext field\n");308return JNI_ERR;309}310FID_NativeGSSContext_srcName =311(*env)->GetFieldID(env, CLS_NativeGSSContext, "srcName",312"Lsun/security/jgss/wrapper/GSSNameElement;");313if (FID_NativeGSSContext_srcName == NULL) {314printf("Couldn't find NativeGSSContext.srcName field\n");315return JNI_ERR;316}317FID_NativeGSSContext_targetName =318(*env)->GetFieldID(env, CLS_NativeGSSContext, "targetName",319"Lsun/security/jgss/wrapper/GSSNameElement;");320if (FID_NativeGSSContext_targetName == NULL) {321printf("Couldn't find NativeGSSContext.targetName field\n");322return JNI_ERR;323}324FID_NativeGSSContext_isInitiator =325(*env)->GetFieldID(env, CLS_NativeGSSContext, "isInitiator", "Z");326if (FID_NativeGSSContext_isInitiator == NULL) {327printf("Couldn't find NativeGSSContext.isInitiator field\n");328return JNI_ERR;329}330FID_NativeGSSContext_isEstablished =331(*env)->GetFieldID(env, CLS_NativeGSSContext, "isEstablished", "Z");332if (FID_NativeGSSContext_isEstablished == NULL) {333printf("Couldn't find NativeGSSContext.isEstablished field\n");334return JNI_ERR;335}336FID_NativeGSSContext_delegatedCred =337(*env)->GetFieldID(env, CLS_NativeGSSContext, "delegatedCred",338"Lsun/security/jgss/wrapper/GSSCredElement;");339if (FID_NativeGSSContext_delegatedCred == NULL) {340printf("Couldn't find NativeGSSContext.delegatedCred field\n");341return JNI_ERR;342}343FID_NativeGSSContext_flags =344(*env)->GetFieldID(env, CLS_NativeGSSContext, "flags", "I");345if (FID_NativeGSSContext_flags == NULL) {346printf("Couldn't find NativeGSSContext.flags field\n");347return JNI_ERR;348}349FID_NativeGSSContext_lifetime =350(*env)->GetFieldID(env, CLS_NativeGSSContext, "lifetime", "I");351if (FID_NativeGSSContext_lifetime == NULL) {352printf("Couldn't find NativeGSSContext.lifetime field\n");353return JNI_ERR;354}355FID_NativeGSSContext_actualMech =356(*env)->GetFieldID(env, CLS_NativeGSSContext, "actualMech",357"Lorg/ietf/jgss/Oid;");358if (FID_NativeGSSContext_actualMech == NULL) {359printf("Couldn't find NativeGSSContext.actualMech field\n");360return JNI_ERR;361}362return JNI_VERSION_1_2;363}364365JNIEXPORT void JNICALL366DEF_JNI_OnUnload(JavaVM *jvm, void *reserved) {367JNIEnv *env;368369if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {370return;371}372/* Delete the global refs */373(*env)->DeleteGlobalRef(env, CLS_Object);374(*env)->DeleteGlobalRef(env, CLS_String);375(*env)->DeleteGlobalRef(env, CLS_Oid);376(*env)->DeleteGlobalRef(env, CLS_GSSException);377(*env)->DeleteGlobalRef(env, CLS_GSSNameElement);378(*env)->DeleteGlobalRef(env, CLS_GSSCredElement);379(*env)->DeleteGlobalRef(env, CLS_SunNativeProvider);380return;381}382383const OM_uint32 JAVA_MAX = GSS_C_INDEFINITE/2;384385/*386* Utility routine for converting the C unsigned integer time387* to Java signed integer time.388*/389jint getJavaTime(OM_uint32 ctime) {390jint result;391392/* special handle values equals or more than JAVA_MAX */393if (ctime == GSS_C_INDEFINITE) {394result = JAVA_MAX;395} else if (ctime >= JAVA_MAX) {396result = JAVA_MAX-1;397} else {398result = ctime;399}400return result;401}402/*403* Utility routine for converting the Java signed integer time404* to C unsigned integer time.405*/406OM_uint32 getGSSTime(jint jtime) {407OM_uint32 result;408409/* special handle values equal to JAVA_MAX */410if (jtime == (jint)JAVA_MAX) {411result = GSS_C_INDEFINITE;412} else {413result = jtime;414}415return result;416}417/*418* Utility routine for mapping the C error code to the419* Java one. The routine errors really should have420* shared the same values but unfortunately don't.421*/422jint getJavaErrorCode(int cNonCallingErr) {423int cRoutineErr, cSuppStatus;424/* map the routine errors */425cRoutineErr = GSS_ROUTINE_ERROR(cNonCallingErr) >> 16;426if (cRoutineErr != GSS_S_COMPLETE) {427return JAVA_ERROR_CODE[cRoutineErr-1];428}429/* map the supplementary infos */430cSuppStatus = GSS_SUPPLEMENTARY_INFO(cNonCallingErr);431if (cSuppStatus & GSS_S_DUPLICATE_TOKEN) {432return JAVA_DUPLICATE_TOKEN_CODE;433} else if (cSuppStatus & GSS_S_OLD_TOKEN) {434return JAVA_OLD_TOKEN_CODE;435} else if (cSuppStatus & GSS_S_UNSEQ_TOKEN) {436return JAVA_UNSEQ_TOKEN_CODE;437} else if (cSuppStatus & GSS_S_GAP_TOKEN) {438return JAVA_GAP_TOKEN_CODE;439}440return GSS_S_COMPLETE;441}442443444/* Throws a Java Exception by name */445void throwByName(JNIEnv *env, const char *name, const char *msg) {446jclass cls = (*env)->FindClass(env, name);447448if (cls != NULL) {449(*env)->ThrowNew(env, cls, msg);450}451}452453void throwOutOfMemoryError(JNIEnv *env, const char *message) {454throwByName(env, "java/lang/OutOfMemoryError", message);455}456457/*458* Utility routine for creating a java.lang.String object459* using the specified gss_buffer_t structure. The specified460* gss_buffer_t structure is always released.461*/462jstring getJavaString(JNIEnv *env, gss_buffer_t bytes) {463jstring result = NULL;464OM_uint32 minor;465int len;466jbyteArray jbytes;467468if (bytes != NULL) {469/* constructs the String object with new String(byte[])470NOTE: do NOT include the trailing NULL */471len = (int) bytes->length;472jbytes = (*env)->NewByteArray(env, len);473if (jbytes == NULL) {474goto finish;475}476477(*env)->SetByteArrayRegion(env, jbytes, 0, len, (jbyte *) bytes->value);478if ((*env)->ExceptionCheck(env)) {479goto finish;480}481482result = (*env)->NewObject(env, CLS_String, MID_String_ctor,483jbytes);484finish:485(*env)->DeleteLocalRef(env, jbytes);486(*ftab->releaseBuffer)(&minor, bytes);487return result;488} /* else fall through */489return NULL;490}491/*492* Utility routine for generate message for the specified minor493* status code.494*/495jstring getMinorMessage(JNIEnv *env, jobject jstub, OM_uint32 statusValue) {496OM_uint32 messageContext, minor, major;497gss_buffer_desc statusString;498gss_OID mech;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, (int) cbytes->length);638if (result == NULL) {639goto finish;640}641(*env)->SetByteArrayRegion(env, result, 0, (int) 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;662if (jOid != NULL) {663jbytes = (*env)->CallObjectMethod(env, jOid, MID_Oid_getDER);664if ((*env)->ExceptionCheck(env)) {665return GSS_C_NO_OID;666}667cOid = malloc(sizeof(struct gss_OID_desc_struct));668if (cOid == NULL) {669throwOutOfMemoryError(env,NULL);670return GSS_C_NO_OID;671}672cOid->length = (*env)->GetArrayLength(env, jbytes) - 2;673cOid->elements = malloc(cOid->length);674if (cOid->elements == NULL) {675throwOutOfMemoryError(env,NULL);676goto cleanup;677}678(*env)->GetByteArrayRegion(env, jbytes, 2, cOid->length,679cOid->elements);680if ((*env)->ExceptionCheck(env)) {681goto cleanup;682}683return cOid;684} else {685return GSS_C_NO_OID;686}687cleanup:688(*env)->DeleteLocalRef(env, jbytes);689free(cOid->elements);690free(cOid);691return GSS_C_NO_OID;692}693694/*695* Utility routine for releasing the specified gss_OID696* structure.697* NOTE: used in conjunction with newGSSOID(...).698*/699void deleteGSSOID(gss_OID oid) {700if (oid != GSS_C_NO_OID) {701free(oid->elements);702free(oid);703}704}705706/*707* Utility routine for creating a org.ietf.jgss.Oid708* object using the specified gss_OID structure.709*/710jobject getJavaOID(JNIEnv *env, gss_OID cOid) {711int cLen;712char oidHdr[2];713jbyteArray jbytes;714jobject result = NULL;715716if ((cOid == NULL) || (cOid == GSS_C_NO_OID)) {717return NULL;718}719cLen = cOid->length;720oidHdr[0] = 6;721oidHdr[1] = cLen;722jbytes = (*env)->NewByteArray(env, cLen+2);723if (jbytes == NULL) {724return NULL;725}726if (!(*env)->ExceptionCheck(env)) {727(*env)->SetByteArrayRegion(env, jbytes, 0, 2, (jbyte *) oidHdr);728}729if (!(*env)->ExceptionCheck(env)) {730(*env)->SetByteArrayRegion(env, jbytes, 2, cLen, (jbyte *) cOid->elements);731}732if (!(*env)->ExceptionCheck(env)) {733result = (*env)->NewObject(env, CLS_Oid, MID_Oid_ctor1, jbytes);734}735(*env)->DeleteLocalRef(env, jbytes);736return result;737}738/*739* Utility routine for creating a gss_OID_set structure740* using the specified gss_OID.741* NOTE: need to call deleteGSSOIDSet(...) afterwards742* to release the created gss_OID_set structure.743*/744gss_OID_set newGSSOIDSet(gss_OID oid) {745gss_OID_set oidSet;746OM_uint32 minor; // don't care; just so it compiles747748if (oid->length != 6 ||749memcmp(oid->elements, SPNEGO_BYTES, 6) != 0) {750(*ftab->createEmptyOidSet)(&minor, &oidSet);751(*ftab->addOidSetMember)(&minor, oid, &oidSet);752return oidSet;753} else {754// Use all mechs for SPNEGO in order to work with755// various native GSS impls756return (ftab->mechs);757}758}759/*760* Utility routine for releasing a gss_OID_set structure.761* NOTE: used in conjunction with newGSSOIDSet(...).762*/763void deleteGSSOIDSet(gss_OID_set oidSet) {764OM_uint32 minor; /* don't care; just so it compiles */765766if ((oidSet != ftab->mechs) &&767(oidSet != NULL) && (oidSet != GSS_C_NO_OID_SET)) {768(*ftab->releaseOidSet)(&minor, &oidSet);769}770}771/*772* Utility routine for creating a org.ietf.jgss.Oid[]773* using the specified gss_OID_set structure.774*/775jobjectArray getJavaOIDArray(JNIEnv *env, gss_OID_set cOidSet) {776int numOfOids = 0;777jobjectArray jOidSet;778jobject jOid;779int i;780781if (cOidSet != NULL && cOidSet != GSS_C_NO_OID_SET) {782numOfOids = (int) cOidSet->count;783jOidSet = (*env)->NewObjectArray(env, numOfOids, CLS_Oid, NULL);784if ((*env)->ExceptionCheck(env)) {785return NULL;786}787for (i = 0; i < numOfOids; i++) {788jOid = getJavaOID(env, &(cOidSet->elements[i]));789if ((*env)->ExceptionCheck(env)) {790return NULL;791}792(*env)->SetObjectArrayElement(env, jOidSet, i, jOid);793if ((*env)->ExceptionCheck(env)) {794return NULL;795}796(*env)->DeleteLocalRef(env, jOid);797}798return jOidSet;799}800return NULL;801}802803int sameMech(gss_OID mech, gss_OID mech2) {804int result = JNI_FALSE; // default to not equal805806if (mech->length == mech2->length) {807result = (memcmp(mech->elements, mech2->elements, mech->length) == 0);808}809return result;810}811812813