keystoreloginmodule.java
来自「JAVA 所有包」· Java 代码 · 共 897 行 · 第 1/2 页
JAVA
897 行
/* * @(#)KeyStoreLoginModule.java 1.19 05/11/17 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */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 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."); } try { InputStream in = new URL(keyStorePasswordURL).openStream(); keyStorePassword = Password.readPassword(in); in.close(); } catch (IOException e) { LoginException le = new LoginException ("Problem accessing keystore password \"" + keyStorePasswordURL + "\""); le.initCause(e); throw le; } } private void checkKeyPass() throws LoginException { if (privateKeyPasswordURL == null) { privateKeyPassword = keyStorePassword; } else { try { InputStream in = new URL(privateKeyPasswordURL).openStream(); privateKeyPassword = Password.readPassword(in); in.close(); } catch (IOException e) { LoginException le = new LoginException ("Problem accessing private key password \"" + privateKeyPasswordURL + "\""); le.initCause(e); 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"); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?