/*
 * 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 com.sun.security.auth.module;

import javax.security.auth.x500.X500Principal;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AuthProvider;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.UnrecoverableKeyException;
import java.security.cert.*;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.ResourceBundle;
import javax.security.auth.Destroyable;
import javax.security.auth.DestroyFailedException;
import javax.security.auth.Subject;
import javax.security.auth.x500.*;
import javax.security.auth.Subject;
import javax.security.auth.x500.*;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.ConfirmationCallback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import sun.security.util.AuthResources;
import sun.security.util.Password;

/**
 * Provides a JAAS login module that prompts for a key store alias and
 * populates the subject with the alias's principal and credentials. Stores
 * an <code>X500Principal</code> for the subject distinguished name of the
 * first certificate in the alias's credentials in the subject's principals,
 * the alias's certificate path in the subject's public credentials, and a
 * <code>X500PrivateCredential</code> whose certificate is the first
 * certificate in the alias's certificate path and whose private key is the
 * alias's private key in the subject's private credentials. <p>
 *
 * Recognizes the following options in the configuration file:
 * <dl>
 *
 * <dt> <code>keyStoreURL</code> </dt>
 * <dd> A URL that specifies the location of the key store.  Defaults to
 *      a URL pointing to the .keystore file in the directory specified by the
 *      <code>user.home</code> system property.  The input stream from this
 *      URL is passed to the <code>KeyStore.load</code> method.
 *      "NONE" may be specified if a <code>null</code> stream must be
 *      passed to the <code>KeyStore.load</code> method.
 *      "NONE" should be specified if the KeyStore resides
 *      on a hardware token device, for example.</dd>
 *
 * <dt> <code>keyStoreType</code> </dt>
 * <dd> The key store type.  If not specified, defaults to the result of
 *      calling <code>KeyStore.getDefaultType()</code>.
 *      If the type is "PKCS11", then keyStoreURL must be "NONE"
 *      and privateKeyPasswordURL must not be specified.</dd>
 *
 * <dt> <code>keyStoreProvider</code> </dt>
 * <dd> The key store provider.  If not specified, uses the standard search
 *      order to find the provider. </dd>
 *
 * <dt> <code>keyStoreAlias</code> </dt>
 * <dd> The alias in the key store to login as.  Required when no callback
 *      handler is provided.  No default value. </dd>
 *
 * <dt> <code>keyStorePasswordURL</code> </dt>
 * <dd> A URL that specifies the location of the key store password.  Required
 *      when no callback handler is provided and
 *      <code>protected</code> is false.
 *      No default value. </dd>
 *
 * <dt> <code>privateKeyPasswordURL</code> </dt>
 * <dd> A URL that specifies the location of the specific private key password
 *      needed to access the private key for this alias.
 *      The keystore password
 *      is used if this value is needed and not specified. </dd>
 *
 * <dt> <code>protected</code> </dt>
 * <dd> This value should be set to "true" if the KeyStore
 *      has a separate, protected authentication path
 *      (for example, a dedicated PIN-pad attached to a smart card).
 *      Defaults to "false". If "true" keyStorePasswordURL and
 *      privateKeyPasswordURL must not be specified.</dd>
 *
 * </dl>
 */
public class KeyStoreLoginModule implements LoginModule {

   static final java.util.ResourceBundle rb =
        java.util.ResourceBundle.getBundle("sun.security.util.AuthResources");

    /* -- Fields -- */

    private static final int UNINITIALIZED = 0;
    private static final int INITIALIZED = 1;
    private static final int AUTHENTICATED = 2;
    private static final int LOGGED_IN = 3;

    private static final int PROTECTED_PATH = 0;
    private static final int TOKEN = 1;
    private static final int NORMAL = 2;

    private static final String NONE = "NONE";
    private static final String P11KEYSTORE = "PKCS11";

    private static final TextOutputCallback bannerCallback =
                new TextOutputCallback
                        (TextOutputCallback.INFORMATION,
                        rb.getString("Please enter keystore information"));
    private final ConfirmationCallback confirmationCallback =
                new ConfirmationCallback
                        (ConfirmationCallback.INFORMATION,
                        ConfirmationCallback.OK_CANCEL_OPTION,
                        ConfirmationCallback.OK);

    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map sharedState;
    private Map<String, ?> options;

    private char[] keyStorePassword;
    private char[] privateKeyPassword;
    private KeyStore keyStore;

    private String keyStoreURL;
    private String keyStoreType;
    private String keyStoreProvider;
    private String keyStoreAlias;
    private String keyStorePasswordURL;
    private String privateKeyPasswordURL;
    private boolean debug;
    private javax.security.auth.x500.X500Principal principal;
    private Certificate[] fromKeyStore;
    private java.security.cert.CertPath certP = null;
    private X500PrivateCredential privateCredential;
    private int status = UNINITIALIZED;
    private boolean nullStream = false;
    private boolean token = false;
    private boolean protectedPath = false;

    /* -- Methods -- */

    /**
     * Initialize this <code>LoginModule</code>.
     *
     * <p>
     *
     * @param subject the <code>Subject</code> to be authenticated. <p>
     *
     * @param callbackHandler a <code>CallbackHandler</code> for communicating
     *                  with the end user (prompting for usernames and
     *                  passwords, for example),
     *                  which may be <code>null</code>. <p>
     *
     * @param sharedState shared <code>LoginModule</code> state. <p>
     *
     * @param options options specified in the login
     *                  <code>Configuration</code> for this particular
     *                  <code>LoginModule</code>.
     */

    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
                           Map<String,?> sharedState,
                           Map<String,?> options)
    {
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        this.options = options;

        processOptions();
        status = INITIALIZED;
    }

    private void processOptions() {
        keyStoreURL = (String) options.get("keyStoreURL");
        if (keyStoreURL == null) {
            keyStoreURL =
                "file:" +
                System.getProperty("user.home").replace(
                    File.separatorChar, '/') +
                '/' + ".keystore";
        } else if (NONE.equals(keyStoreURL)) {
            nullStream = true;
        }
        keyStoreType = (String) options.get("keyStoreType");
        if (keyStoreType == null) {
            keyStoreType = KeyStore.getDefaultType();
        }
        if (P11KEYSTORE.equalsIgnoreCase(keyStoreType)) {
            token = true;
        }

        keyStoreProvider = (String) options.get("keyStoreProvider");

        keyStoreAlias = (String) options.get("keyStoreAlias");

        keyStorePasswordURL = (String) options.get("keyStorePasswordURL");

        privateKeyPasswordURL = (String) options.get("privateKeyPasswordURL");

        protectedPath = "true".equalsIgnoreCase((String)options.get
                                        ("protected"));

        debug = "true".equalsIgnoreCase((String) options.get("debug"));
        if (debug) {
            debugPrint(null);
            debugPrint("keyStoreURL=" + keyStoreURL);
            debugPrint("keyStoreType=" + keyStoreType);
            debugPrint("keyStoreProvider=" + keyStoreProvider);
            debugPrint("keyStoreAlias=" + keyStoreAlias);
            debugPrint("keyStorePasswordURL=" + keyStorePasswordURL);
            debugPrint("privateKeyPasswordURL=" + privateKeyPasswordURL);
            debugPrint("protectedPath=" + protectedPath);
            debugPrint(null);
        }
    }

    /**
     * Authenticate the user.
     *
     * <p> Get the Keystore alias and relevant passwords.
     * Retrieve the alias's principal and credentials from the Keystore.
     *
     * <p>
     *
     * @exception FailedLoginException if the authentication fails. <p>
     *
     * @return true in all cases (this <code>LoginModule</code>
     *          should not be ignored).
     */

    public boolean login() throws LoginException {
        switch (status) {
        case UNINITIALIZED:
        default:
            throw new LoginException("The login module is not initialized");
        case INITIALIZED:
        case AUTHENTICATED:

            if (token && !nullStream) {
                throw new LoginException
                        ("if keyStoreType is " + P11KEYSTORE +
                        " then keyStoreURL must be " + NONE);
            }

            if (token && privateKeyPasswordURL != null) {
                throw new LoginException
                        ("if keyStoreType is " + P11KEYSTORE +
                        " then privateKeyPasswordURL must not be specified");
            }

            if (protectedPath &&
                (keyStorePasswordURL != null ||
                        privateKeyPasswordURL != null)) {
                throw new LoginException
                        ("if protected is true then keyStorePasswordURL and " +
                        "privateKeyPasswordURL must not be specified");
            }

            // get relevant alias and password info

            if (protectedPath) {
                getAliasAndPasswords(PROTECTED_PATH);
            } else if (token) {
                getAliasAndPasswords(TOKEN);
            } else {
                getAliasAndPasswords(NORMAL);
            }

            // log into KeyStore to retrieve data,
            // then clear passwords

            try {
                getKeyStoreInfo();
            } finally {
                if (privateKeyPassword != null &&
                    privateKeyPassword != keyStorePassword) {
                    Arrays.fill(privateKeyPassword, '\0');
                    privateKeyPassword = null;
                }
                if (keyStorePassword != null) {
                    Arrays.fill(keyStorePassword, '\0');
                    keyStorePassword = null;
                }
            }
            status = AUTHENTICATED;
            return true;
        case LOGGED_IN:
            return true;
        }
    }

    /** Get the alias and passwords to use for looking up in the KeyStore. */
    private void getAliasAndPasswords(int env) throws LoginException {
        if (callbackHandler == null) {

            // No callback handler - check for alias and password options

            switch (env) {
            case PROTECTED_PATH:
                checkAlias();
                break;
            case TOKEN:
                checkAlias();
                checkStorePass();
                break;
            case NORMAL:
                checkAlias();
                checkStorePass();
                checkKeyPass();
                break;
            }

        } else {

            // Callback handler available - prompt for alias and passwords

            NameCallback aliasCallback;
            if (keyStoreAlias == null || keyStoreAlias.length() == 0) {
                aliasCallback = new NameCallback(
                                        rb.getString("Keystore alias: "));
            } else {
                aliasCallback =
                    new NameCallback(rb.getString("Keystore alias: "),
                                     keyStoreAlias);
            }

            PasswordCallback storePassCallback = null;
            PasswordCallback keyPassCallback = null;

            switch (env) {
            case PROTECTED_PATH:
                break;
            case NORMAL:
                keyPassCallback = new PasswordCallback
                    (rb.getString("Private key password (optional): "), false);
                // fall thru
            case TOKEN:
                storePassCallback = new PasswordCallback
                    (rb.getString("Keystore password: "), false);
                break;
            }
            prompt(aliasCallback, storePassCallback, keyPassCallback);
        }

        if (debug) {
            debugPrint("alias=" + keyStoreAlias);
        }
    }

    private void checkAlias() throws LoginException {
        if (keyStoreAlias == null) {
            throw new LoginException
                ("Need to specify an alias option to use " +
                "KeyStoreLoginModule non-interactively.");
        }
    }

    private void checkStorePass() throws LoginException {
        if (keyStorePasswordURL == null) {
            throw new LoginException
                ("Need to specify keyStorePasswordURL option to use " +
                "KeyStoreLoginModule non-interactively.");
        }
        InputStream in = null;
        try {
            in = new URL(keyStorePasswordURL).openStream();
            keyStorePassword = Password.readPassword(in);
        } catch (IOException e) {
            LoginException le = new LoginException
                ("Problem accessing keystore password \"" +
                keyStorePasswordURL + "\"");
            le.initCause(e);
            throw le;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {
                    LoginException le = new LoginException(
                        "Problem closing the keystore password stream");
                    le.initCause(ioe);
                    throw le;
                }
            }
        }
    }

    private void checkKeyPass() throws LoginException {
        if (privateKeyPasswordURL == null) {
            privateKeyPassword = keyStorePassword;
        } else {
            InputStream in = null;
            try {
                in = new URL(privateKeyPasswordURL).openStream();
                privateKeyPassword = Password.readPassword(in);
            } catch (IOException e) {
                LoginException le = new LoginException
                        ("Problem accessing private key password \"" +
                        privateKeyPasswordURL + "\"");
                le.initCause(e);
                throw le;
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException ioe) {
                        LoginException le = new LoginException(
                            "Problem closing the private key password stream");
                        le.initCause(ioe);
                        throw le;
                    }
                }
            }
        }
    }

    private void prompt(NameCallback aliasCallback,
                        PasswordCallback storePassCallback,
                        PasswordCallback keyPassCallback)
                throws LoginException {

        if (storePassCallback == null) {

            // only prompt for alias

            try {
                callbackHandler.handle(
                    new Callback[] {
                        bannerCallback, aliasCallback, confirmationCallback
                    });
            } catch (IOException e) {
                LoginException le = new LoginException
                        ("Problem retrieving keystore alias");
                le.initCause(e);
                throw le;
            } catch (UnsupportedCallbackException e) {
                throw new LoginException(
                    "Error: " + e.getCallback().toString() +
                    " is not available to retrieve authentication " +
                    " information from the user");
            }

            int confirmationResult = confirmationCallback.getSelectedIndex();

            if (confirmationResult == ConfirmationCallback.CANCEL) {
                throw new LoginException("Login cancelled");
            }

            saveAlias(aliasCallback);

        } else if (keyPassCallback == null) {

            // prompt for alias and key store password

            try {
                callbackHandler.handle(
                    new Callback[] {
                        bannerCallback, aliasCallback,
                        storePassCallback, confirmationCallback
                    });
            } catch (IOException e) {
                LoginException le = new LoginException
                        ("Problem retrieving keystore alias and password");
                le.initCause(e);
                throw le;
            } catch (UnsupportedCallbackException e) {
                throw new LoginException(
                    "Error: " + e.getCallback().toString() +
                    " is not available to retrieve authentication " +
                    " information from the user");
            }

            int confirmationResult = confirmationCallback.getSelectedIndex();

            if (confirmationResult == ConfirmationCallback.CANCEL) {
                throw new LoginException("Login cancelled");
            }

            saveAlias(aliasCallback);
            saveStorePass(storePassCallback);

        } else {

            // prompt for alias, key store password, and key password

            try {
                callbackHandler.handle(
                    new Callback[] {
                        bannerCallback, aliasCallback,
                        storePassCallback, keyPassCallback,
                        confirmationCallback
                    });
            } catch (IOException e) {
                LoginException le = new LoginException
                        ("Problem retrieving keystore alias and passwords");
                le.initCause(e);
                throw le;
            } catch (UnsupportedCallbackException e) {
                throw new LoginException(
                    "Error: " + e.getCallback().toString() +
                    " is not available to retrieve authentication " +
                    " information from the user");
            }

            int confirmationResult = confirmationCallback.getSelectedIndex();

            if (confirmationResult == ConfirmationCallback.CANCEL) {
                throw new LoginException("Login cancelled");
            }

            saveAlias(aliasCallback);
            saveStorePass(storePassCallback);
            saveKeyPass(keyPassCallback);
        }
    }

    private void saveAlias(NameCallback cb) {
        keyStoreAlias = cb.getName();
    }

    private void saveStorePass(PasswordCallback c) {
        keyStorePassword = c.getPassword();
        if (keyStorePassword == null) {
            /* Treat a NULL password as an empty password */
            keyStorePassword = new char[0];
        }
        c.clearPassword();
    }

    private void saveKeyPass(PasswordCallback c) {
        privateKeyPassword = c.getPassword();
        if (privateKeyPassword == null || privateKeyPassword.length == 0) {
            /*
             * Use keystore password if no private key password is
             * specified.
             */
            privateKeyPassword = keyStorePassword;
        }
        c.clearPassword();
    }

    /** Get the credentials from the KeyStore. */
    private void getKeyStoreInfo() throws LoginException {

        /* Get KeyStore instance */
        try {
            if (keyStoreProvider == null) {
                keyStore = KeyStore.getInstance(keyStoreType);
            } else {
                keyStore =
                    KeyStore.getInstance(keyStoreType, keyStoreProvider);
            }
        } catch (KeyStoreException e) {
            LoginException le = new LoginException
                ("The specified keystore type was not available");
            le.initCause(e);
            throw le;
        } catch (NoSuchProviderException e) {
            LoginException le = new LoginException
                ("The specified keystore provider was not available");
            le.initCause(e);
            throw le;
        }

        /* Load KeyStore contents from file */
        InputStream in = null;
        try {
            if (nullStream) {
                // if using protected auth path, keyStorePassword will be null
                keyStore.load(null, keyStorePassword);
            } else {
                in = new URL(keyStoreURL).openStream();
                keyStore.load(in, keyStorePassword);
            }
        } catch (MalformedURLException e) {
            LoginException le = new LoginException
                                ("Incorrect keyStoreURL option");
            le.initCause(e);
            throw le;
        } catch (GeneralSecurityException e) {
            LoginException le = new LoginException
                                ("Error initializing keystore");
            le.initCause(e);
            throw le;
        } catch (IOException e) {
            LoginException le = new LoginException
                                ("Error initializing keystore");
            le.initCause(e);
            throw le;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {
                    LoginException le = new LoginException
                                ("Error initializing keystore");
                    le.initCause(ioe);
                    throw le;
                }
            }
        }

        /* Get certificate chain and create a certificate path */
        try {
            fromKeyStore =
                keyStore.getCertificateChain(keyStoreAlias);
            if (fromKeyStore == null
                || fromKeyStore.length == 0
                || !(fromKeyStore[0] instanceof X509Certificate))
            {
                throw new FailedLoginException(
                    "Unable to find X.509 certificate chain in keystore");
            } else {
                LinkedList<Certificate> certList =
                                new LinkedList<Certificate>();
                for (int i=0; i < fromKeyStore.length; i++) {
                    certList.add(fromKeyStore[i]);
                }
                CertificateFactory certF=
                    CertificateFactory.getInstance("X.509");
                certP =
                    certF.generateCertPath(certList);
            }
        } catch (KeyStoreException e) {
            LoginException le = new LoginException("Error using keystore");
            le.initCause(e);
            throw le;
        } catch (CertificateException ce) {
            LoginException le = new LoginException
                ("Error: X.509 Certificate type unavailable");
            le.initCause(ce);
            throw le;
        }

        /* Get principal and keys */
        try {
            X509Certificate certificate = (X509Certificate)fromKeyStore[0];
            principal = new javax.security.auth.x500.X500Principal
                (certificate.getSubjectDN().getName());

            // if token, privateKeyPassword will be null
            Key privateKey = keyStore.getKey(keyStoreAlias, privateKeyPassword);
            if (privateKey == null
                || !(privateKey instanceof PrivateKey))
            {
                throw new FailedLoginException(
                    "Unable to recover key from keystore");
            }

            privateCredential = new X500PrivateCredential(
                certificate, (PrivateKey) privateKey, keyStoreAlias);
        } catch (KeyStoreException e) {
            LoginException le = new LoginException("Error using keystore");
            le.initCause(e);
            throw le;
        } catch (NoSuchAlgorithmException e) {
            LoginException le = new LoginException("Error using keystore");
            le.initCause(e);
            throw le;
        } catch (UnrecoverableKeyException e) {
            FailedLoginException fle = new FailedLoginException
                                ("Unable to recover key from keystore");
            fle.initCause(e);
            throw fle;
        }
        if (debug) {
            debugPrint("principal=" + principal +
                       "\n certificate="
                       + privateCredential.getCertificate() +
                       "\n alias =" + privateCredential.getAlias());
        }
    }

    /**
     * Abstract method to commit the authentication process (phase 2).
     *
     * <p> This method is called if the LoginContext's
     * overall authentication succeeded
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * succeeded).
     *
     * <p> If this LoginModule's own authentication attempt
     * succeeded (checked by retrieving the private state saved by the
     * <code>login</code> method), then this method associates a
     * <code>X500Principal</code> for the subject distinguished name of the
     * first certificate in the alias's credentials in the subject's
     * principals,the alias's certificate path in the subject's public
     * credentials, and a<code>X500PrivateCredential</code> whose certificate
     * is the first  certificate in the alias's certificate path and whose
     * private key is the alias's private key in the subject's private
     * credentials.  If this LoginModule's own
     * authentication attempted failed, then this method removes
     * any state that was originally saved.
     *
     * <p>
     *
     * @exception LoginException if the commit fails
     *
     * @return true if this LoginModule's own login and commit
     *          attempts succeeded, or false otherwise.
     */

    public boolean commit() throws LoginException {
        switch (status) {
        case UNINITIALIZED:
        default:
            throw new LoginException("The login module is not initialized");
        case INITIALIZED:
            logoutInternal();
            throw new LoginException("Authentication failed");
        case AUTHENTICATED:
            if (commitInternal()) {
                return true;
            } else {
                logoutInternal();
                throw new LoginException("Unable to retrieve certificates");
            }
        case LOGGED_IN:
            return true;
        }
    }

    private boolean commitInternal() throws LoginException {
        /* If the subject is not readonly add to the principal and credentials
         * set; otherwise just return true
         */
        if (subject.isReadOnly()) {
            throw new LoginException ("Subject is set readonly");
        } else {
            subject.getPrincipals().add(principal);
            subject.getPublicCredentials().add(certP);
            subject.getPrivateCredentials().add(privateCredential);
            status = LOGGED_IN;
            return true;
        }
    }

    /**
     * <p> This method is called if the LoginContext's
     * overall authentication failed.
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * did not succeed).
     *
     * <p> If this LoginModule's own authentication attempt
     * succeeded (checked by retrieving the private state saved by the
     * <code>login</code> and <code>commit</code> methods),
     * then this method cleans up any state that was originally saved.
     *
     * <p> If the loaded KeyStore's provider extends
     * <code>java.security.AuthProvider</code>,
     * then the provider's <code>logout</code> method is invoked.
     *
     * <p>
     *
     * @exception LoginException if the abort fails.
     *
     * @return false if this LoginModule's own login and/or commit attempts
     *          failed, and true otherwise.
     */

    public boolean abort() throws LoginException {
        switch (status) {
        case UNINITIALIZED:
        default:
            return false;
        case INITIALIZED:
            return false;
        case AUTHENTICATED:
            logoutInternal();
            return true;
        case LOGGED_IN:
            logoutInternal();
            return true;
        }
    }
    /**
     * Logout a user.
     *
     * <p> This method removes the Principals, public credentials and the
     * private credentials that were added by the <code>commit</code> method.
     *
     * <p> If the loaded KeyStore's provider extends
     * <code>java.security.AuthProvider</code>,
     * then the provider's <code>logout</code> method is invoked.
     *
     * <p>
     *
     * @exception LoginException if the logout fails.
     *
     * @return true in all cases since this <code>LoginModule</code>
     *          should not be ignored.
     */

    public boolean logout() throws LoginException {
        if (debug)
            debugPrint("Entering logout " + status);
        switch (status) {
        case UNINITIALIZED:
            throw new LoginException
                ("The login module is not initialized");
        case INITIALIZED:
        case AUTHENTICATED:
        default:
           // impossible for LoginModule to be in AUTHENTICATED
           // state
           // assert status != AUTHENTICATED;
            return false;
        case LOGGED_IN:
            logoutInternal();
            return true;
        }
    }

    private void logoutInternal() throws LoginException {
        if (debug) {
            debugPrint("Entering logoutInternal");
        }

        // assumption is that KeyStore.load did a login -
        // perform explicit logout if possible
        LoginException logoutException = null;
        Provider provider = keyStore.getProvider();
        if (provider instanceof AuthProvider) {
            AuthProvider ap = (AuthProvider)provider;
            try {
                ap.logout();
                if (debug) {
                    debugPrint("logged out of KeyStore AuthProvider");
                }
            } catch (LoginException le) {
                // save but continue below
                logoutException = le;
            }
        }

        if (subject.isReadOnly()) {
            // attempt to destroy the private credential
            // even if the Subject is read-only
            principal = null;
            certP = null;
            status = INITIALIZED;
            // destroy the private credential
            Iterator<Object> it = subject.getPrivateCredentials().iterator();
            while (it.hasNext()) {
                Object obj = it.next();
                if (privateCredential.equals(obj)) {
                    privateCredential = null;
                    try {
                        ((Destroyable)obj).destroy();
                        if (debug)
                            debugPrint("Destroyed private credential, " +
                                       obj.getClass().getName());
                        break;
                    } catch (DestroyFailedException dfe) {
                        LoginException le = new LoginException
                            ("Unable to destroy private credential, "
                             + obj.getClass().getName());
                        le.initCause(dfe);
                        throw le;
                    }
                }
            }

            // throw an exception because we can not remove
            // the principal and public credential from this
            // read-only Subject
            throw new LoginException
                ("Unable to remove Principal ("
                 + "X500Principal "
                 + ") and public credential (certificatepath) "
                 + "from read-only Subject");
        }
        if (principal != null) {
            subject.getPrincipals().remove(principal);
            principal = null;
        }
        if (certP != null) {
            subject.getPublicCredentials().remove(certP);
            certP = null;
        }
        if (privateCredential != null) {
            subject.getPrivateCredentials().remove(privateCredential);
            privateCredential = null;
        }

        // throw pending logout exception if there is one
        if (logoutException != null) {
            throw logoutException;
        }
        status = INITIALIZED;
    }

    private void debugPrint(String message) {
        // we should switch to logging API
        if (message == null) {
            System.err.println();
        } else {
            System.err.println("Debug KeyStoreLoginModule: " + message);
        }
    }
}
