267 lines · 9.6 KB · Java
RawDownload
/* * Copyright (c) 2005, 2010, 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. */ package sun.security.jgss.wrapper; import org.ietf.jgss.*;import java.security.Provider;import java.security.Security;import java.io.IOException;import java.io.UnsupportedEncodingException;import sun.security.jgss.GSSUtil;import sun.security.util.ObjectIdentifier;import sun.security.util.DerInputStream;import sun.security.util.DerOutputStream;import sun.security.jgss.GSSUtil;import sun.security.jgss.GSSExceptionImpl;import sun.security.jgss.spi.GSSNameSpi; /** * This class is essentially a wrapper class for the gss_name_t * structure of the native GSS library. * @author Valerie Peng * @since 1.6 */ public class GSSNameElement implements GSSNameSpi {     long pName = 0; // Pointer to the gss_name_t structure    private String printableName;    private Oid printableType;    private GSSLibStub cStub;     static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();     private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) {        if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {            Oid[] supportedNTs = null;            try {                supportedNTs = stub.inquireNamesForMech();            } catch (GSSException ge) {                if (ge.getMajor() == GSSException.BAD_MECH &&                    GSSUtil.isSpNegoMech(stub.getMech())) {                    // Workaround known Heimdal issue and retry with KRB5                    try {                        stub = GSSLibStub.getInstance                            (GSSUtil.GSS_KRB5_MECH_OID);                        supportedNTs = stub.inquireNamesForMech();                    } catch (GSSException ge2) {                        // Should never happen                        SunNativeProvider.debug("Name type list unavailable: " +                            ge2.getMajorString());                    }                } else {                    SunNativeProvider.debug("Name type list unavailable: " +                        ge.getMajorString());                }            }            if (supportedNTs != null) {                for (int i = 0; i < supportedNTs.length; i++) {                    if (supportedNTs[i].equals(nameType)) return nameType;                }                // Special handling the specified name type                SunNativeProvider.debug("Override " + nameType +                    " with mechanism default(null)");                return null; // Use mechanism specific default            }        }        return nameType;    }     private GSSNameElement() {        printableName = "<DEFAULT ACCEPTOR>";    }     GSSNameElement(long pNativeName, GSSLibStub stub) throws GSSException {        assert(stub != null);        if (pNativeName == 0) {            throw new GSSException(GSSException.BAD_NAME);        }        // Note: pNativeName is assumed to be a MN.        pName = pNativeName;        cStub = stub;        setPrintables();    }     GSSNameElement(byte[] nameBytes, Oid nameType, GSSLibStub stub)        throws GSSException {        assert(stub != null);        if (nameBytes == null) {            throw new GSSException(GSSException.BAD_NAME);        }        cStub = stub;        byte[] name = nameBytes;         if (nameType != null) {            // Special handling the specified name type if            // necessary            nameType = getNativeNameType(nameType, stub);             if (GSSName.NT_EXPORT_NAME.equals(nameType)) {                // Need to add back the mech Oid portion (stripped                // off by GSSNameImpl class prior to calling this                // method) for "NT_EXPORT_NAME"                byte[] mechBytes = null;                DerOutputStream dout = new DerOutputStream();                Oid mech = cStub.getMech();                try {                    dout.putOID(new ObjectIdentifier(mech.toString()));                } catch (IOException e) {                    throw new GSSExceptionImpl(GSSException.FAILURE, e);                }                mechBytes = dout.toByteArray();                name = new byte[2 + 2 + mechBytes.length + 4 + nameBytes.length];                int pos = 0;                name[pos++] = 0x04;                name[pos++] = 0x01;                name[pos++] = (byte) (mechBytes.length>>>8);                name[pos++] = (byte) mechBytes.length;                System.arraycopy(mechBytes, 0, name, pos, mechBytes.length);                pos += mechBytes.length;                name[pos++] = (byte) (nameBytes.length>>>24);                name[pos++] = (byte) (nameBytes.length>>>16);                name[pos++] = (byte) (nameBytes.length>>>8);                name[pos++] = (byte) nameBytes.length;                System.arraycopy(nameBytes, 0, name, pos, nameBytes.length);            }        }        pName = cStub.importName(name, nameType);        setPrintables();         SunNativeProvider.debug("Imported " + printableName + " w/ type " +                                printableType);    }     private void setPrintables() throws GSSException {        Object[] printables = null;        printables = cStub.displayName(pName);        assert((printables != null) && (printables.length == 2));        printableName = (String) printables[0];        assert(printableName != null);        printableType = (Oid) printables[1];        if (printableType == null) {            printableType = GSSName.NT_USER_NAME;        }    }     // Need to be public for GSSUtil.getSubject()    public String getKrbName() throws GSSException {        long mName = 0;        GSSLibStub stub = cStub;        if (!GSSUtil.isKerberosMech(cStub.getMech())) {            stub = GSSLibStub.getInstance(GSSUtil.GSS_KRB5_MECH_OID);        }        mName = stub.canonicalizeName(pName);        Object[] printables2 = stub.displayName(mName);        stub.releaseName(mName);        SunNativeProvider.debug("Got kerberized name: " + printables2[0]);        return (String) printables2[0];    }     public Provider getProvider() {        return SunNativeProvider.INSTANCE;    }     public boolean equals(GSSNameSpi other) throws GSSException {        if (!(other instanceof GSSNameElement)) {            return false;        }        return cStub.compareName(pName, ((GSSNameElement)other).pName);    }     public boolean equals(Object other) {        if (!(other instanceof GSSNameElement)) {            return false;        }        try {            return equals((GSSNameElement) other);        } catch (GSSException ex) {            return false;        }    }     public int hashCode() {        return new Long(pName).hashCode();    }     public byte[] export() throws GSSException {        byte[] nameVal = cStub.exportName(pName);         // Need to strip off the mech Oid portion of the exported        // bytes since GSSNameImpl class will subsequently add it.        int pos = 0;        if ((nameVal[pos++] != 0x04) ||            (nameVal[pos++] != 0x01))            throw new GSSException(GSSException.BAD_NAME);         int mechOidLen  = (((0xFF & nameVal[pos++]) << 8) |                           (0xFF & nameVal[pos++]));        ObjectIdentifier temp = null;        try {            DerInputStream din = new DerInputStream(nameVal, pos,                                                    mechOidLen);            temp = new ObjectIdentifier(din);        } catch (IOException e) {            throw new GSSExceptionImpl(GSSException.BAD_NAME, e);        }        Oid mech2 = new Oid(temp.toString());        assert(mech2.equals(getMechanism()));        pos += mechOidLen;        int mechPortionLen = (((0xFF & nameVal[pos++]) << 24) |                              ((0xFF & nameVal[pos++]) << 16) |                              ((0xFF & nameVal[pos++]) << 8) |                              (0xFF & nameVal[pos++]));        byte[] mechPortion = new byte[mechPortionLen];        System.arraycopy(nameVal, pos, mechPortion, 0, mechPortionLen);        return mechPortion;    }     public Oid getMechanism() {        return cStub.getMech();    }     public String toString() {        return printableName;    }     public Oid getStringNameType() {        return printableType;    }     public boolean isAnonymousName() {        return (GSSName.NT_ANONYMOUS.equals(printableType));    }     public void dispose() {        if (pName != 0) {            cStub.releaseName(pName);            pName = 0;        }    }     protected void finalize() throws Throwable {        dispose();    }}