| /* | |
| * Copyright (c) 1998, 2025, 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 java.security.NoSuchAlgorithmException; | |
| import java.security.NoSuchProviderException; | |
| import java.security.Provider; | |
| import java.security.Security; | |
| import java.util.Objects; | |
| 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. | |
| * | |
| * <p> A login configuration contains the following information. | |
| * Note that this example only represents the default syntax for the | |
| * {@code Configuration}. Subclass implementations of this class | |
| * may implement alternative syntaxes and may retrieve the | |
| * {@code Configuration} from any source such as files, databases, | |
| * or servers. | |
| * | |
| * <pre> | |
| * Name { | |
| * ModuleClass Flag ModuleOptions; | |
| * ModuleClass Flag ModuleOptions; | |
| * ModuleClass Flag ModuleOptions; | |
| * }; | |
| * Name { | |
| * ModuleClass Flag ModuleOptions; | |
| * ModuleClass Flag ModuleOptions; | |
| * }; | |
| * other { | |
| * ModuleClass Flag ModuleOptions; | |
| * ModuleClass Flag ModuleOptions; | |
| * }; | |
| * </pre> | |
| * | |
| * <p> Each entry in the {@code Configuration} is indexed via an | |
| * application name, <i>Name</i>, and contains a list of | |
| * LoginModules configured for that application. Each {@code 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 a specific entry, | |
| * it defaults to the specific entry for "<i>other</i>". | |
| * | |
| * <p> The <i>Flag</i> value controls the overall behavior as authentication | |
| * proceeds down the stack. The following represents a description of the | |
| * valid values for <i>Flag</i> and their respective semantics: | |
| * | |
| * <pre> | |
| * 1) Required - The {@code LoginModule} is required to succeed. | |
| * If it succeeds or fails, authentication still continues | |
| * to proceed down the {@code LoginModule} list. | |
| * | |
| * 2) Requisite - The {@code LoginModule} is required to succeed. | |
| * If it succeeds, authentication continues down the | |
| * {@code LoginModule} list. If it fails, | |
| * control immediately returns to the application | |
| * (authentication does not proceed down the | |
| * {@code LoginModule} list). | |
| * | |
| * 3) Sufficient - The {@code LoginModule} is not required to | |
| * succeed. If it does succeed, control immediately | |
| * returns to the application (authentication does not | |
| * proceed down the {@code LoginModule} list). | |
| * If it fails, authentication continues down the | |
| * {@code LoginModule} list. | |
| * | |
| * 4) Optional - The {@code LoginModule} is not required to | |
| * succeed. If it succeeds or fails, | |
| * authentication still continues to proceed down the | |
| * {@code LoginModule} list. | |
| * </pre> | |
| * | |
| * <p> The overall authentication succeeds only if all <i>Required</i> and | |
| * <i>Requisite</i> LoginModules succeed. If a <i>Sufficient</i> | |
| * {@code LoginModule} is configured and succeeds, | |
| * then only the <i>Required</i> and <i>Requisite</i> LoginModules prior to | |
| * that <i>Sufficient</i> {@code LoginModule} need to have succeeded for | |
| * the overall authentication to succeed. If no <i>Required</i> or | |
| * <i>Requisite</i> LoginModules are configured for an application, | |
| * then at least one <i>Sufficient</i> or <i>Optional</i> | |
| * {@code LoginModule} must succeed. | |
| * | |
| * <p> <i>ModuleOptions</i> is a space separated list of | |
| * {@code LoginModule}-specific values which are passed directly to | |
| * the underlying LoginModules. Options are defined by the | |
| * {@code LoginModule} itself, and control the behavior within it. | |
| * For example, a {@code LoginModule} may define options to support | |
| * debugging/testing capabilities. The correct way to specify options in the | |
| * {@code Configuration} is by using the following key-value pairing: | |
| * <i>debug="true"</i>. 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 {@code LoginModule} may define. | |
| * | |
| * <p> The following represents an example {@code Configuration} entry | |
| * based on the syntax above: | |
| * | |
| * <pre> | |
| * Login { | |
| * com.sun.security.auth.module.UnixLoginModule required; | |
| * com.sun.security.auth.module.Krb5LoginModule optional | |
| * useTicketCache="true" | |
| * ticketCache="${user.home}${/}tickets"; | |
| * }; | |
| * </pre> | |
| * | |
| * <p> This {@code Configuration} specifies that an application named, | |
| * "Login", requires users to first authenticate to the | |
| * <i>com.sun.security.auth.module.UnixLoginModule</i>, which is | |
| * required to succeed. Even if the <i>UnixLoginModule</i> | |
| * authentication fails, the | |
| * <i>com.sun.security.auth.module.Krb5LoginModule</i> | |
| * still gets invoked. This helps hide the source of failure. | |
| * Since the <i>Krb5LoginModule</i> is <i>Optional</i>, the overall | |
| * authentication succeeds only if the <i>UnixLoginModule</i> | |
| * (<i>Required</i>) succeeds. | |
| * | |
| * <p> Also note that the LoginModule-specific options, | |
| * <i>useTicketCache="true"</i> and | |
| * <i>ticketCache=${user.home}${/}tickets"</i>, | |
| * are passed to the <i>Krb5LoginModule</i>. | |
| * These options instruct the <i>Krb5LoginModule</i> to | |
| * use the ticket cache at the specified location. | |
| * The system properties, <i>user.home</i> and <i>/</i> | |
| * (file.separator), are expanded to their respective values. | |
| * | |
| * <p> There is only one Configuration object installed in the runtime at any | |
| * given time. A Configuration object can be installed by calling the | |
| * {@code setConfiguration} method. The installed Configuration object | |
| * can be obtained by calling the {@code getConfiguration} method. | |
| * | |
| * <p> If no Configuration object has been installed in the runtime, a call to | |
| * {@code 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 {@code login.configuration.provider} security property to the fully | |
| * qualified name of the desired Configuration subclass implementation. | |
| * | |
| * <p> 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 {@code getInstance} factory methods | |
| * with a standard type. The default policy type is "JavaLoginConfig". | |
| * See the Configuration section in the <a href= | |
| * "{@docRoot}/../specs/security/standard-names.html#configuration-types"> | |
| * Java Security Standard Algorithm Names Specification</a> | |
| * for a list of standard Configuration types. | |
| * | |
| * @spec security/standard-names.html Java Security Standard Algorithm Names | |
| * @since 1.4 | |
| * @see javax.security.auth.login.LoginContext | |
| * @see java.security.Security security properties | |
| */ | |
| public abstract class Configuration { | |
| private static Configuration configuration; | |
| /** | |
| * Sole constructor. (For invocation by subclass constructors, typically | |
| * implicit.) | |
| */ | |
| protected Configuration() { } | |
| /** | |
| * Get the installed login Configuration. | |
| * | |
| * @return the login Configuration. If a Configuration object was set | |
| * via the {@code Configuration.setConfiguration} method, | |
| * then that object is returned. Otherwise, a default | |
| * Configuration object is returned. | |
| * | |
| * @see #setConfiguration | |
| */ | |
| public static Configuration getConfiguration() { | |
| synchronized (Configuration.class) { | |
| if (configuration == null) { | |
| String config_class = Security.getProperty | |
| ("login.configuration.provider"); | |
| if (config_class == null) { | |
| config_class = "sun.security.provider.ConfigFile"; | |
| } | |
| try { | |
| Class<? extends Configuration> implClass = Class.forName( | |
| config_class, false, | |
| Thread.currentThread().getContextClassLoader() | |
| ).asSubclass(Configuration.class); | |
| @SuppressWarnings("deprecation") | |
| Configuration result = implClass.newInstance(); | |
| setConfiguration(result); | |
| } catch (ReflectiveOperationException e) { | |
| throw new SecurityException | |
| ("Configuration error: " + | |
| e.toString() + | |
| "\n", e); | |
| } | |
| } | |
| return configuration; | |
| } | |
| } | |
| /** | |
| * Set the login {@code Configuration}. | |
| * | |
| * @param configuration the new {@code Configuration} | |
| * | |
| * @see #getConfiguration | |
| */ | |
| public static void setConfiguration(Configuration configuration) { | |
| Configuration.configuration = configuration; | |
| } | |
| /** | |
| * Returns a Configuration object of the specified type. | |
| * | |
| * <p> 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. | |
| * | |
| * <p> Note that the list of registered providers may be retrieved via | |
| * the {@link Security#getProviders() Security.getProviders()} method. | |
| * | |
| * @implNote | |
| * The JDK Reference Implementation additionally uses the | |
| * {@code jdk.security.provider.preferred} | |
| * {@link Security#getProperty(String) Security} property to determine | |
| * the preferred provider order for the specified algorithm. This | |
| * may be different from the order of providers returned by | |
| * {@link Security#getProviders() Security.getProviders()}. | |
| * | |
| * @param type the specified Configuration type. See the Configuration | |
| * section in the <a href= | |
| * "{@docRoot}/../specs/security/standard-names.html#configuration-types"> | |
| * Java Security Standard Algorithm Names Specification</a> | |
| * for a list of standard Configuration types. | |
| * | |
| * @param params parameters for the Configuration, which may be null. | |
| * | |
| * @spec security/standard-names.html Java Security Standard Algorithm Names | |
| * @return the new {@code Configuration} object | |
| * | |
| * @throws IllegalArgumentException if the specified parameters | |
| * are not understood by the {@code ConfigurationSpi} | |
| * implementation from the selected {@code Provider} | |
| * | |
| * @throws NoSuchAlgorithmException if no {@code Provider} supports a | |
| * {@code ConfigurationSpi} implementation for the specified type | |
| * | |
| * @throws NullPointerException if {@code type} is {@code null} | |
| * | |
| * @see Provider | |
| * | |
| * @since 1.6 | |
| */ | |
| public static Configuration getInstance(String type, | |
| Configuration.Parameters params) | |
| throws NoSuchAlgorithmException { | |
| Objects.requireNonNull(type, "null type name"); | |
| 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. | |
| * | |
| * <p> A new Configuration object encapsulating the | |
| * ConfigurationSpi implementation from the specified provider | |
| * is returned. The specified provider must be registered | |
| * in the provider list. | |
| * | |
| * <p> 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 <a href= | |
| * "{@docRoot}/../specs/security/standard-names.html#configuration-types"> | |
| * Java Security Standard Algorithm Names Specification</a> | |
| * for a list of standard Configuration types. | |
| * | |
| * @param params parameters for the Configuration, which may be null. | |
| * | |
| * @param provider the provider. | |
| * | |
| * @spec security/standard-names.html Java Security Standard Algorithm Names | |
| * @return the new {@code Configuration} object | |
| * | |
| * @throws IllegalArgumentException if the specified provider | |
| * is {@code null} or empty, or if the specified parameters | |
| * are not understood by the {@code ConfigurationSpi} | |
| * implementation from the specified provider | |
| * | |
| * @throws NoSuchProviderException if the specified provider is not | |
| * registered in the security provider list | |
| * | |
| * @throws NoSuchAlgorithmException if the specified provider does not | |
| * support a {@code ConfigurationSpi} implementation for the | |
| * specified type | |
| * | |
| * @throws NullPointerException if {@code type} is {@code null} | |
| * | |
| * @see Provider | |
| * @since 1.6 | |
| */ | |
| public static Configuration getInstance(String type, | |
| Configuration.Parameters params, | |
| String provider) | |
| throws NoSuchProviderException, NoSuchAlgorithmException { | |
| Objects.requireNonNull(type, "null type name"); | |
| if (provider == null || provider.isEmpty()) { | |
| throw new IllegalArgumentException("missing provider"); | |
| } | |
| 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. | |
| * | |
| * <p> 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 <a href= | |
| * "{@docRoot}/../specs/security/standard-names.html#configuration-types"> | |
| * Java Security Standard Algorithm Names Specification</a> | |
| * for a list of standard Configuration types. | |
| * | |
| * @param params parameters for the Configuration, which may be null. | |
| * | |
| * @param provider the Provider. | |
| * | |
| * @spec security/standard-names.html Java Security Standard Algorithm Names | |
| * @return the new {@code Configuration} object | |
| * | |
| * @throws IllegalArgumentException if the specified {@code Provider} | |
| * is {@code null}, or if the specified parameters are not | |
| * understood by the {@code ConfigurationSpi} implementation | |
| * from the specified Provider | |
| * | |
| * @throws NoSuchAlgorithmException if the specified {@code Provider} | |
| * does not support a {@code ConfigurationSpi} implementation | |
| * for the specified type | |
| * | |
| * @throws NullPointerException if {@code type} is {@code null} | |
| * | |
| * @see Provider | |
| * @since 1.6 | |
| */ | |
| public static Configuration getInstance(String type, | |
| Configuration.Parameters params, | |
| Provider provider) | |
| throws NoSuchAlgorithmException { | |
| Objects.requireNonNull(type, "null type name"); | |
| if (provider == null) { | |
| throw new IllegalArgumentException("missing provider"); | |
| } | |
| 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. | |
| * | |
| * <p> This Configuration instance will only have a Provider if it | |
| * was obtained via a call to {@code 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. | |
| * | |
| * <p> This Configuration instance will only have a type if it | |
| * was obtained via a call to {@code 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. | |
| * | |
| * <p> This Configuration instance will only have parameters if it | |
| * was obtained via a call to {@code 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 {@code name} | |
| * from this Configuration. | |
| * | |
| * @param name the name used to index the Configuration. | |
| * | |
| * @return an array of AppConfigurationEntries for the specified {@code name} | |
| * from this Configuration, or null if there are no entries | |
| * for the specified {@code name} | |
| */ | |
| public abstract AppConfigurationEntry[] getAppConfigurationEntry | |
| (String name); | |
| /** | |
| * Refresh and reload the Configuration. | |
| * | |
| * <p> 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 {@code refresh} may cause the file to be re-read. | |
| * | |
| * <p> The default implementation of this method does nothing. | |
| * This method should be overridden if a refresh operation is supported | |
| * by the implementation. | |
| */ | |
| 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 final ConfigurationSpi spi; | |
| private final Provider p; | |
| private final String type; | |
| private final 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 interface Parameters { } | |
| } |