669 lines · 22.7 KB · Java
RawDownload
/* * Copyright (c) 2000, 2006, 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; import org.ietf.jgss.*;import sun.security.jgss.spi.*;import java.util.*; public class GSSCredentialImpl implements GSSCredential {     private GSSManagerImpl gssManager = null;    private boolean destroyed = false;     /*     * We store all elements in a hashtable, using <oid, usage> as the     * key. This makes it easy to locate the specific kind of credential we     * need. The implementation needs to be optimized for the case where     * there is just one element (tempCred).     */    private Hashtable<SearchKey, GSSCredentialSpi> hashtable = null;     // XXX Optimization for single mech usage    private GSSCredentialSpi tempCred = null;     GSSCredentialImpl(GSSManagerImpl gssManager, int usage)        throws GSSException {        this(gssManager, null, GSSCredential.DEFAULT_LIFETIME,             (Oid[]) null, usage);    }     GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name,                             int lifetime, Oid mech, int usage)        throws GSSException {        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;         init(gssManager);        add(name, lifetime, lifetime, mech, usage);    }     GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name,                      int lifetime, Oid mechs[], int usage)        throws GSSException {        init(gssManager);        boolean defaultList = false;        if (mechs == null) {            mechs = gssManager.getMechs();            defaultList = true;        }         for (int i = 0; i < mechs.length; i++) {            try {                add(name, lifetime, lifetime, mechs[i], usage);            } catch (GSSException e) {                if (defaultList) {                    // Try the next mechanism                    GSSUtil.debug("Ignore " + e + " while acquring cred for "                        + mechs[i]);                    //e.printStackTrace();                } else throw e; // else try the next mechanism            }        }        if ((hashtable.size() == 0) || (usage != getUsage()))            throw new GSSException(GSSException.NO_CRED);    }     public GSSCredentialImpl(GSSManagerImpl gssManager,                      GSSCredentialSpi mechElement) throws GSSException {         init(gssManager);        int usage = GSSCredential.ACCEPT_ONLY;        if (mechElement.isInitiatorCredential()) {            if (mechElement.isAcceptorCredential()) {                usage = GSSCredential.INITIATE_AND_ACCEPT;            } else {                usage = GSSCredential.INITIATE_ONLY;            }        }        SearchKey key = new SearchKey(mechElement.getMechanism(),                                        usage);        tempCred = mechElement;        hashtable.put(key, tempCred);    }     void init(GSSManagerImpl gssManager) {        this.gssManager = gssManager;        hashtable = new Hashtable<SearchKey, GSSCredentialSpi>(                                                gssManager.getMechs().length);    }     public void dispose() throws GSSException {        if (!destroyed) {            GSSCredentialSpi element;            Enumeration<GSSCredentialSpi> values = hashtable.elements();            while (values.hasMoreElements()) {                element = values.nextElement();                element.dispose();            }            destroyed = true;        }    }     public GSSName getName() throws GSSException {        if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }        return GSSNameImpl.wrapElement(gssManager, tempCred.getName());    }     public GSSName getName(Oid mech) throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }         SearchKey key = null;        GSSCredentialSpi element = null;         if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;         key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);        element = hashtable.get(key);         if (element == null) {            key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);            element = hashtable.get(key);        }         if (element == null) {            key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);            element = hashtable.get(key);        }         if (element == null) {            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);        }         return GSSNameImpl.wrapElement(gssManager, element.getName());     }     /**     * Returns the remaining lifetime of this credential. The remaining     * lifetime is defined as the minimum lifetime, either for initiate or     * for accept, across all elements contained in it. Not terribly     * useful, but required by GSS-API.     */    public int getRemainingLifetime() throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }         SearchKey tempKey;        GSSCredentialSpi tempCred;        int tempLife = 0, tempInitLife = 0, tempAcceptLife = 0;        int min = INDEFINITE_LIFETIME;         for (Enumeration<SearchKey> e = hashtable.keys();                                        e.hasMoreElements(); ) {            tempKey = e.nextElement();            tempCred = hashtable.get(tempKey);            if (tempKey.getUsage() == INITIATE_ONLY)                tempLife = tempCred.getInitLifetime();            else if (tempKey.getUsage() == ACCEPT_ONLY)                tempLife = tempCred.getAcceptLifetime();            else {                tempInitLife = tempCred.getInitLifetime();                tempAcceptLife = tempCred.getAcceptLifetime();                tempLife = (tempInitLife < tempAcceptLife ?                            tempInitLife:                            tempAcceptLife);            }            if (min > tempLife)                min = tempLife;        }         return min;    }     public int getRemainingInitLifetime(Oid mech) throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }         GSSCredentialSpi element = null;        SearchKey key = null;        boolean found = false;        int max = 0;         if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;         key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);        element = hashtable.get(key);         if (element != null) {            found = true;            if (max < element.getInitLifetime())                max = element.getInitLifetime();        }         key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);        element = hashtable.get(key);         if (element != null) {            found = true;            if (max < element.getInitLifetime())                max = element.getInitLifetime();        }         if (!found) {            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);        }         return max;     }     public int getRemainingAcceptLifetime(Oid mech) throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }         GSSCredentialSpi element = null;        SearchKey key = null;        boolean found = false;        int max = 0;         if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;         key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);        element = hashtable.get(key);         if (element != null) {            found = true;            if (max < element.getAcceptLifetime())                max = element.getAcceptLifetime();        }         key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);        element = hashtable.get(key);         if (element != null) {            found = true;            if (max < element.getAcceptLifetime())                max = element.getAcceptLifetime();        }         if (!found) {            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);        }         return max;     }     /**     * Returns the usage mode for this credential. Returns     * INITIATE_AND_ACCEPT if any one element contained in it supports     * INITIATE_AND_ACCEPT or if two different elements exist where one     * support INITIATE_ONLY and the other supports ACCEPT_ONLY.     */    public int getUsage() throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }         SearchKey tempKey;        boolean initiate = false;        boolean accept = false;         for (Enumeration<SearchKey> e = hashtable.keys();                                        e.hasMoreElements(); ) {            tempKey = e.nextElement();            if (tempKey.getUsage() == INITIATE_ONLY)                initiate = true;            else if (tempKey.getUsage() == ACCEPT_ONLY)                accept = true;            else                return INITIATE_AND_ACCEPT;        }        if (initiate) {            if (accept)                return INITIATE_AND_ACCEPT;            else                return INITIATE_ONLY;        } else            return ACCEPT_ONLY;    }     public int getUsage(Oid mech) throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }         GSSCredentialSpi element = null;        SearchKey key = null;        boolean initiate = false;        boolean accept = false;         if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;         key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);        element = hashtable.get(key);         if (element != null) {            initiate = true;        }         key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);        element = hashtable.get(key);         if (element != null) {            accept = true;        }         key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);        element = hashtable.get(key);         if (element != null) {            initiate = true;            accept = true;        }         if (initiate && accept)            return GSSCredential.INITIATE_AND_ACCEPT;        else if (initiate)            return GSSCredential.INITIATE_ONLY;        else if (accept)            return GSSCredential.ACCEPT_ONLY;        else {            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);        }    }     public Oid[] getMechs() throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }        Vector<Oid> result = new Vector<Oid>(hashtable.size());         for (Enumeration<SearchKey> e = hashtable.keys();                                                e.hasMoreElements(); ) {            SearchKey tempKey = e.nextElement();            result.addElement(tempKey.getMech());        }        return result.toArray(new Oid[0]);    }     public void add(GSSName name, int initLifetime, int acceptLifetime,                    Oid mech, int usage) throws GSSException {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;         SearchKey key = new SearchKey(mech, usage);        if (hashtable.containsKey(key)) {            throw new GSSExceptionImpl(GSSException.DUPLICATE_ELEMENT,                                       "Duplicate element found: " +                                       getElementStr(mech, usage));        }         // XXX If not instance of GSSNameImpl then throw exception        // Application mixing GSS implementations        GSSNameSpi nameElement = (name == null ? null :                                  ((GSSNameImpl)name).getElement(mech));         tempCred = gssManager.getCredentialElement(nameElement,                                                   initLifetime,                                                   acceptLifetime,                                                   mech,                                                   usage);        /*         * Not all mechanisms support the concept of one credential element         * that can be used for both initiating and accepting a context. In         * the event that an application requests usage INITIATE_AND_ACCEPT         * for a credential from such a mechanism, the GSS framework will         * need to obtain two different credential elements from the         * mechanism, one that will have usage INITIATE_ONLY and another         * that will have usage ACCEPT_ONLY. The mechanism will help the         * GSS-API realize this by returning a credential element with         * usage INITIATE_ONLY or ACCEPT_ONLY prompting it to make another         * call to getCredentialElement, this time with the other usage         * mode.         */         if (tempCred != null) {            if (usage == GSSCredential.INITIATE_AND_ACCEPT &&                (!tempCred.isAcceptorCredential() ||                !tempCred.isInitiatorCredential())) {                 int currentUsage;                int desiredUsage;                 if (!tempCred.isInitiatorCredential()) {                    currentUsage = GSSCredential.ACCEPT_ONLY;                    desiredUsage = GSSCredential.INITIATE_ONLY;                } else {                    currentUsage = GSSCredential.INITIATE_ONLY;                    desiredUsage = GSSCredential.ACCEPT_ONLY;                }                 key = new SearchKey(mech, currentUsage);                hashtable.put(key, tempCred);                 tempCred = gssManager.getCredentialElement(nameElement,                                                        initLifetime,                                                        acceptLifetime,                                                        mech,                                                        desiredUsage);                 key = new SearchKey(mech, desiredUsage);                hashtable.put(key, tempCred);            } else {                hashtable.put(key, tempCred);            }        }    }     public boolean equals(Object another) {         if (destroyed) {            throw new IllegalStateException("This credential is " +                                        "no longer valid");        }         if (this == another) {            return true;        }         if (!(another instanceof GSSCredentialImpl)) {            return false;        }         // NOTE: The specification does not define the criteria to compare        // credentials.        /*         * XXX         * The RFC says: "Tests if this GSSCredential refers to the same         * entity as the supplied object.  The two credentials must be         * acquired over the same mechanisms and must refer to the same         * principal.  Returns "true" if the two GSSCredentials refer to         * the same entity; "false" otherwise."         *         * Well, when do two credentials refer to the same principal? Do         * they need to have one GSSName in common for the different         * GSSName's that the credential elements return? Or do all         * GSSName's have to be in common when the names are exported with         * their respective mechanisms for the credential elements?         */        return false;     }     /**     * Returns a hashcode value for this GSSCredential.     *     * @return a hashCode value     */    public int hashCode() {         if (destroyed) {

Lines 1–500 of 669.