/*
 * Copyright (c) 2000, 2013, 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.*;
import com.sun.security.jgss.*;
import sun.security.jgss.spnego.SpNegoCredElement;

public class GSSCredentialImpl implements ExtendedGSSCredential {

    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);
    }

    // Wrap a mech cred into a GSS 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);
        // More mechs that can use this cred, say, SPNEGO
        if (!GSSUtil.isSpNegoMech(mechElement.getMechanism())) {
            key = new SearchKey(GSSUtil.GSS_SPNEGO_MECH_OID, usage);
            hashtable.put(key, new SpNegoCredElement(mechElement));
        }
    }

    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 GSSCredential impersonate(GSSName name) throws GSSException {
        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }
        Oid mech = tempCred.getMechanism();
        GSSNameSpi nameElement = (name == null ? null :
                                  ((GSSNameImpl)name).getElement(mech));
        GSSCredentialSpi cred = tempCred.impersonate(nameElement);
        return (cred == null ?
            null : new GSSCredentialImpl(gssManager, cred));
    }

    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) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        // NOTE: The specification does not define the criteria to compare
        // credentials.
        /*
         * XXX
         * Decide on a criteria for equals first then do this.
         */
        return 1;
    }

    /**
     * Returns the specified mechanism's credential-element.
     *
     * @param mechOid - the oid for mechanism to retrieve
     * @param throwExcep - boolean indicating if the function is
     *    to throw exception or return null when element is not
     *    found.
     * @return mechanism credential object
     * @exception GSSException of invalid mechanism
     */
    public GSSCredentialSpi getElement(Oid mechOid, boolean initiate)
        throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        SearchKey key;
        GSSCredentialSpi element;

        if (mechOid == null) {
            /*
             * First see if the default mechanism satisfies the
             * desired usage.
             */
            mechOid = ProviderList.DEFAULT_MECH_OID;
            key = new SearchKey(mechOid,
                                 initiate? INITIATE_ONLY : ACCEPT_ONLY);
            element = hashtable.get(key);
            if (element == null) {
                key = new SearchKey(mechOid, INITIATE_AND_ACCEPT);
                element = hashtable.get(key);
                if (element == null) {
                    /*
                     * Now just return any element that satisfies the
                     * desired usage.
                     */
                    Object[] elements = hashtable.entrySet().toArray();
                    for (int i = 0; i < elements.length; i++) {
                        element = (GSSCredentialSpi)
                            ((Map.Entry)elements[i]).getValue();
                        if (element.isInitiatorCredential() == initiate)
                            break;
                    } // for loop
                }
            }
        } else {

            if (initiate)
                key = new SearchKey(mechOid, INITIATE_ONLY);
            else
                key = new SearchKey(mechOid, ACCEPT_ONLY);

            element = hashtable.get(key);

            if (element == null) {
                key = new SearchKey(mechOid, INITIATE_AND_ACCEPT);
                element = hashtable.get(key);
            }
        }

        if (element == null)
            throw new GSSExceptionImpl(GSSException.NO_CRED,
                                       "No credential found for: " +
                                       getElementStr(mechOid,
                                       initiate? INITIATE_ONLY : ACCEPT_ONLY));
        return element;
    }

    Set<GSSCredentialSpi> getElements() {
        HashSet<GSSCredentialSpi> retVal =
                        new HashSet<GSSCredentialSpi>(hashtable.size());
        Enumeration<GSSCredentialSpi> values = hashtable.elements();
        while (values.hasMoreElements()) {
            GSSCredentialSpi o = values.nextElement();
            retVal.add(o);
        }
        return retVal;
    }

    private static String getElementStr(Oid mechOid, int usage) {
        String displayString = mechOid.toString();
        if (usage == GSSCredential.INITIATE_ONLY) {
            displayString =
                displayString.concat(" usage: Initiate");
        } else if (usage == GSSCredential.ACCEPT_ONLY) {
            displayString =
                displayString.concat(" usage: Accept");
        } else {
            displayString =
                displayString.concat(" usage: Initiate and Accept");
        }
        return displayString;
    }

    public String toString() {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        GSSCredentialSpi element = null;
        StringBuffer buffer = new StringBuffer("[GSSCredential: ");
        Object[] elements = hashtable.entrySet().toArray();
        for (int i = 0; i < elements.length; i++) {
            try {
                buffer.append('\n');
                element = (GSSCredentialSpi)
                    ((Map.Entry)elements[i]).getValue();
                buffer.append(element.getName());
                buffer.append(' ');
                buffer.append(element.getMechanism());
                buffer.append(element.isInitiatorCredential() ?
                              " Initiate" : "");
                buffer.append(element.isAcceptorCredential() ?
                              " Accept" : "");
                buffer.append(" [");
                buffer.append(element.getClass());
                buffer.append(']');
            } catch (GSSException e) {
                // skip to next element
            }
        }
        buffer.append(']');
        return buffer.toString();
    }

    static class SearchKey {
        private Oid mechOid = null;
        private int usage = GSSCredential.INITIATE_AND_ACCEPT;
        public SearchKey(Oid mechOid, int usage) {

            this.mechOid = mechOid;
            this.usage = usage;
        }
        public Oid getMech() {
            return mechOid;
        }
        public int getUsage() {
            return usage;
        }
        public boolean equals(Object other) {
            if (! (other instanceof SearchKey))
                return false;
            SearchKey that = (SearchKey) other;
            return ((this.mechOid.equals(that.mechOid)) &&
                    (this.usage == that.usage));
        }
        public int hashCode() {
            return mechOid.hashCode();
        }
    }

}
