/* * Copyright (c) 1998, 2011, 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 javax.security.auth.login; import javax.security.auth.AuthPermission; import java.io.*; import java.util.*; import java.net.URI; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; import java.security.Security; import java.security.SecurityPermission; import sun.security.jca.GetInstance; /** * A Configuration object is responsible for specifying which LoginModules * should be used for a particular application, and in what order the * LoginModules should be invoked. * *
A login configuration contains the following information.
* Note that this example only represents the default syntax for the
* Configuration
. Subclass implementations of this class
* may implement alternative syntaxes and may retrieve the
* Configuration
from any source such as files, databases,
* or servers.
*
*
* Name { * ModuleClass Flag ModuleOptions; * ModuleClass Flag ModuleOptions; * ModuleClass Flag ModuleOptions; * }; * Name { * ModuleClass Flag ModuleOptions; * ModuleClass Flag ModuleOptions; * }; * other { * ModuleClass Flag ModuleOptions; * ModuleClass Flag ModuleOptions; * }; ** *
Each entry in the Configuration
is indexed via an
* application name, Name, and contains a list of
* LoginModules configured for that application. Each LoginModule
* is specified via its fully qualified class name.
* Authentication proceeds down the module list in the exact order specified.
* If an application does not have specific entry,
* it defaults to the specific entry for "other".
*
*
The Flag value controls the overall behavior as authentication * proceeds down the stack. The following represents a description of the * valid values for Flag and their respective semantics: * *
* 1) Required - The* *LoginModule
is required to succeed. * If it succeeds or fails, authentication still continues * to proceed down theLoginModule
list. * * 2) Requisite - TheLoginModule
is required to succeed. * If it succeeds, authentication continues down the *LoginModule
list. If it fails, * control immediately returns to the application * (authentication does not proceed down the *LoginModule
list). * * 3) Sufficient - TheLoginModule
is not required to * succeed. If it does succeed, control immediately * returns to the application (authentication does not * proceed down theLoginModule
list). * If it fails, authentication continues down the *LoginModule
list. * * 4) Optional - TheLoginModule
is not required to * succeed. If it succeeds or fails, * authentication still continues to proceed down the *LoginModule
list. *
The overall authentication succeeds only if all Required and
* Requisite LoginModules succeed. If a Sufficient
* LoginModule
is configured and succeeds,
* then only the Required and Requisite LoginModules prior to
* that Sufficient LoginModule
need to have succeeded for
* the overall authentication to succeed. If no Required or
* Requisite LoginModules are configured for an application,
* then at least one Sufficient or Optional
* LoginModule
must succeed.
*
*
ModuleOptions is a space separated list of
* LoginModule
-specific values which are passed directly to
* the underlying LoginModules. Options are defined by the
* LoginModule
itself, and control the behavior within it.
* For example, a LoginModule
may define options to support
* debugging/testing capabilities. The correct way to specify options in the
* Configuration
is by using the following key-value pairing:
* debug="true". The key and value should be separated by an
* 'equals' symbol, and the value should be surrounded by double quotes.
* If a String in the form, ${system.property}, occurs in the value,
* it will be expanded to the value of the system property.
* Note that there is no limit to the number of
* options a LoginModule
may define.
*
*
The following represents an example Configuration
entry
* based on the syntax above:
*
*
* Login { * com.sun.security.auth.module.UnixLoginModule required; * com.sun.security.auth.module.Krb5LoginModule optional * useTicketCache="true" * ticketCache="${user.home}${/}tickets"; * }; ** *
This Configuration
specifies that an application named,
* "Login", requires users to first authenticate to the
* com.sun.security.auth.module.UnixLoginModule, which is
* required to succeed. Even if the UnixLoginModule
* authentication fails, the
* com.sun.security.auth.module.Krb5LoginModule
* still gets invoked. This helps hide the source of failure.
* Since the Krb5LoginModule is Optional, the overall
* authentication succeeds only if the UnixLoginModule
* (Required) succeeds.
*
*
Also note that the LoginModule-specific options, * useTicketCache="true" and * ticketCache=${user.home}${/}tickets", * are passed to the Krb5LoginModule. * These options instruct the Krb5LoginModule to * use the ticket cache at the specified location. * The system properties, user.home and / * (file.separator), are expanded to their respective values. * *
There is only one Configuration object installed in the runtime at any
* given time. A Configuration object can be installed by calling the
* setConfiguration
method. The installed Configuration object
* can be obtained by calling the getConfiguration
method.
*
*
If no Configuration object has been installed in the runtime, a call to
* getConfiguration
installs an instance of the default
* Configuration implementation (a default subclass implementation of this
* abstract class).
* The default Configuration implementation can be changed by setting the value
* of the "login.configuration.provider" security property (in the Java
* security properties file) to the fully qualified name of the desired
* Configuration subclass implementation. The Java security properties file
* is located in the file named <JAVA_HOME>/lib/security/java.security.
* <JAVA_HOME> refers to the value of the java.home system property,
* and specifies the directory where the JRE is installed.
*
*
Application code can directly subclass Configuration to provide a custom
* implementation. In addition, an instance of a Configuration object can be
* constructed by invoking one of the
*
* @return the login Configuration. If a Configuration object was set
* via the
*
* @param configuration the new This method traverses the list of registered security providers,
* starting with the most preferred Provider.
* A new Configuration object encapsulating the
* ConfigurationSpi implementation from the first
* Provider that supports the specified type is returned.
*
* Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param type the specified Configuration type. See the Configuration
* section in the
* Java Cryptography Architecture Standard Algorithm Name
* Documentation for a list of standard Configuration types.
*
* @param params parameters for the Configuration, which may be null.
*
* @return the new Configuration object.
*
* @exception SecurityException if the caller does not have permission
* to get a Configuration instance for the specified type.
*
* @exception NullPointerException if the specified type is null.
*
* @exception IllegalArgumentException if the specified parameters
* are not understood by the ConfigurationSpi implementation
* from the selected Provider.
*
* @exception NoSuchAlgorithmException if no Provider supports a
* ConfigurationSpi implementation for the specified type.
*
* @see Provider
* @since 1.6
*/
public static Configuration getInstance(String type,
Configuration.Parameters params)
throws NoSuchAlgorithmException {
checkPermission(type);
try {
GetInstance.Instance instance = GetInstance.getInstance
("Configuration",
ConfigurationSpi.class,
type,
params);
return new ConfigDelegate((ConfigurationSpi)instance.impl,
instance.provider,
type,
params);
} catch (NoSuchAlgorithmException nsae) {
return handleException (nsae);
}
}
/**
* Returns a Configuration object of the specified type.
*
* A new Configuration object encapsulating the
* ConfigurationSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the provider list.
*
* Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param type the specified Configuration type. See the Configuration
* section in the
* Java Cryptography Architecture Standard Algorithm Name
* Documentation for a list of standard Configuration types.
*
* @param params parameters for the Configuration, which may be null.
*
* @param provider the provider.
*
* @return the new Configuration object.
*
* @exception SecurityException if the caller does not have permission
* to get a Configuration instance for the specified type.
*
* @exception NullPointerException if the specified type is null.
*
* @exception IllegalArgumentException if the specified provider
* is null or empty,
* or if the specified parameters are not understood by
* the ConfigurationSpi implementation from the specified provider.
*
* @exception NoSuchProviderException if the specified provider is not
* registered in the security provider list.
*
* @exception NoSuchAlgorithmException if the specified provider does not
* support a ConfigurationSpi implementation for the specified
* type.
*
* @see Provider
* @since 1.6
*/
public static Configuration getInstance(String type,
Configuration.Parameters params,
String provider)
throws NoSuchProviderException, NoSuchAlgorithmException {
if (provider == null || provider.length() == 0) {
throw new IllegalArgumentException("missing provider");
}
checkPermission(type);
try {
GetInstance.Instance instance = GetInstance.getInstance
("Configuration",
ConfigurationSpi.class,
type,
params,
provider);
return new ConfigDelegate((ConfigurationSpi)instance.impl,
instance.provider,
type,
params);
} catch (NoSuchAlgorithmException nsae) {
return handleException (nsae);
}
}
/**
* Returns a Configuration object of the specified type.
*
* A new Configuration object encapsulating the
* ConfigurationSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param type the specified Configuration type. See the Configuration
* section in the
* Java Cryptography Architecture Standard Algorithm Name
* Documentation for a list of standard Configuration types.
*
* @param params parameters for the Configuration, which may be null.
*
* @param provider the Provider.
*
* @return the new Configuration object.
*
* @exception SecurityException if the caller does not have permission
* to get a Configuration instance for the specified type.
*
* @exception NullPointerException if the specified type is null.
*
* @exception IllegalArgumentException if the specified Provider is null,
* or if the specified parameters are not understood by
* the ConfigurationSpi implementation from the specified Provider.
*
* @exception NoSuchAlgorithmException if the specified Provider does not
* support a ConfigurationSpi implementation for the specified
* type.
*
* @see Provider
* @since 1.6
*/
public static Configuration getInstance(String type,
Configuration.Parameters params,
Provider provider)
throws NoSuchAlgorithmException {
if (provider == null) {
throw new IllegalArgumentException("missing provider");
}
checkPermission(type);
try {
GetInstance.Instance instance = GetInstance.getInstance
("Configuration",
ConfigurationSpi.class,
type,
params,
provider);
return new ConfigDelegate((ConfigurationSpi)instance.impl,
instance.provider,
type,
params);
} catch (NoSuchAlgorithmException nsae) {
return handleException (nsae);
}
}
private static Configuration handleException(NoSuchAlgorithmException nsae)
throws NoSuchAlgorithmException {
Throwable cause = nsae.getCause();
if (cause instanceof IllegalArgumentException) {
throw (IllegalArgumentException)cause;
}
throw nsae;
}
/**
* Return the Provider of this Configuration.
*
* This Configuration instance will only have a Provider if it
* was obtained via a call to This Configuration instance will only have a type if it
* was obtained via a call to This Configuration instance will only have parameters if it
* was obtained via a call to
*
* @param name the name used to index the Configuration.
*
* @return an array of AppConfigurationEntries for the specified name
* from this Configuration, or null if there are no entries
* for the specified name
*/
public abstract AppConfigurationEntry[] getAppConfigurationEntry
(String name);
/**
* Refresh and reload the Configuration.
*
* This method causes this Configuration object to refresh/reload its
* contents in an implementation-dependent manner.
* For example, if this Configuration object stores its entries in a file,
* calling The default implementation of this method does nothing.
* This method should be overridden if a refresh operation is supported
* by the implementation.
*
* @exception SecurityException if the caller does not have permission
* to refresh its Configuration.
*/
public void refresh() { }
/**
* This subclass is returned by the getInstance calls. All Configuration
* calls are delegated to the underlying ConfigurationSpi.
*/
private static class ConfigDelegate extends Configuration {
private ConfigurationSpi spi;
private Provider p;
private String type;
private Configuration.Parameters params;
private ConfigDelegate(ConfigurationSpi spi, Provider p,
String type, Configuration.Parameters params) {
this.spi = spi;
this.p = p;
this.type = type;
this.params = params;
}
public String getType() { return type; }
public Configuration.Parameters getParameters() { return params; }
public Provider getProvider() { return p; }
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return spi.engineGetAppConfigurationEntry(name);
}
public void refresh() {
spi.engineRefresh();
}
}
/**
* This represents a marker interface for Configuration parameters.
*
* @since 1.6
*/
public static interface Parameters { }
}
getInstance
factory methods
* with a standard type. The default policy type is "JavaLoginConfig".
* See the Configuration section in the
* Java Cryptography Architecture Standard Algorithm Name Documentation
* for a list of standard Configuration types.
*
* @see javax.security.auth.login.LoginContext
*/
public abstract class Configuration {
private static Configuration configuration;
private static ClassLoader contextClassLoader;
static {
contextClassLoader = AccessController.doPrivileged
(new PrivilegedActionConfiguration.setConfiguration
method,
* then that object is returned. Otherwise, a default
* Configuration object is returned.
*
* @exception SecurityException if the caller does not have permission
* to retrieve the Configuration.
*
* @see #setConfiguration
*/
public static Configuration getConfiguration() {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new AuthPermission("getLoginConfiguration"));
synchronized (Configuration.class) {
if (configuration == null) {
String config_class = null;
config_class = AccessController.doPrivileged
(new PrivilegedActionConfiguration
.
*
* Configuration
*
* @exception SecurityException if the current thread does not have
* Permission to set the Configuration
.
*
* @see #getConfiguration
*/
public static void setConfiguration(Configuration configuration) {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new AuthPermission("setLoginConfiguration"));
Configuration.configuration = configuration;
}
/**
* Returns a Configuration object of the specified type.
*
* Configuration.getInstance
.
* Otherwise this method returns null.
*
* @return the Provider of this Configuration, or null.
*
* @since 1.6
*/
public Provider getProvider() {
return null;
}
/**
* Return the type of this Configuration.
*
* Configuration.getInstance
.
* Otherwise this method returns null.
*
* @return the type of this Configuration, or null.
*
* @since 1.6
*/
public String getType() {
return null;
}
/**
* Return Configuration parameters.
*
* Configuration.getInstance
.
* Otherwise this method returns null.
*
* @return Configuration parameters, or null.
*
* @since 1.6
*/
public Configuration.Parameters getParameters() {
return null;
}
/**
* Retrieve the AppConfigurationEntries for the specified name
* from this Configuration.
*
* refresh
may cause the file to be re-read.
*
*