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 + -
显示快捷键?