Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/security/auth/login/Configuration.java
38918 views
/*1* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.security.auth.login;2627import javax.security.auth.AuthPermission;2829import java.security.AccessController;30import java.security.PrivilegedAction;31import java.security.PrivilegedExceptionAction;32import java.security.PrivilegedActionException;33import java.security.NoSuchAlgorithmException;34import java.security.NoSuchProviderException;35import java.security.Provider;36import java.security.Security;37import java.util.Objects;3839import sun.security.jca.GetInstance;4041/**42* A Configuration object is responsible for specifying which LoginModules43* should be used for a particular application, and in what order the44* LoginModules should be invoked.45*46* <p> A login configuration contains the following information.47* Note that this example only represents the default syntax for the48* {@code Configuration}. Subclass implementations of this class49* may implement alternative syntaxes and may retrieve the50* {@code Configuration} from any source such as files, databases,51* or servers.52*53* <pre>54* Name {55* ModuleClass Flag ModuleOptions;56* ModuleClass Flag ModuleOptions;57* ModuleClass Flag ModuleOptions;58* };59* Name {60* ModuleClass Flag ModuleOptions;61* ModuleClass Flag ModuleOptions;62* };63* other {64* ModuleClass Flag ModuleOptions;65* ModuleClass Flag ModuleOptions;66* };67* </pre>68*69* <p> Each entry in the {@code Configuration} is indexed via an70* application name, <i>Name</i>, and contains a list of71* LoginModules configured for that application. Each {@code LoginModule}72* is specified via its fully qualified class name.73* Authentication proceeds down the module list in the exact order specified.74* If an application does not have a specific entry,75* it defaults to the specific entry for "<i>other</i>".76*77* <p> The <i>Flag</i> value controls the overall behavior as authentication78* proceeds down the stack. The following represents a description of the79* valid values for <i>Flag</i> and their respective semantics:80*81* <pre>82* 1) Required - The {@code LoginModule} is required to succeed.83* If it succeeds or fails, authentication still continues84* to proceed down the {@code LoginModule} list.85*86* 2) Requisite - The {@code LoginModule} is required to succeed.87* If it succeeds, authentication continues down the88* {@code LoginModule} list. If it fails,89* control immediately returns to the application90* (authentication does not proceed down the91* {@code LoginModule} list).92*93* 3) Sufficient - The {@code LoginModule} is not required to94* succeed. If it does succeed, control immediately95* returns to the application (authentication does not96* proceed down the {@code LoginModule} list).97* If it fails, authentication continues down the98* {@code LoginModule} list.99*100* 4) Optional - The {@code LoginModule} is not required to101* succeed. If it succeeds or fails,102* authentication still continues to proceed down the103* {@code LoginModule} list.104* </pre>105*106* <p> The overall authentication succeeds only if all <i>Required</i> and107* <i>Requisite</i> LoginModules succeed. If a <i>Sufficient</i>108* {@code LoginModule} is configured and succeeds,109* then only the <i>Required</i> and <i>Requisite</i> LoginModules prior to110* that <i>Sufficient</i> {@code LoginModule} need to have succeeded for111* the overall authentication to succeed. If no <i>Required</i> or112* <i>Requisite</i> LoginModules are configured for an application,113* then at least one <i>Sufficient</i> or <i>Optional</i>114* {@code LoginModule} must succeed.115*116* <p> <i>ModuleOptions</i> is a space separated list of117* {@code LoginModule}-specific values which are passed directly to118* the underlying LoginModules. Options are defined by the119* {@code LoginModule} itself, and control the behavior within it.120* For example, a {@code LoginModule} may define options to support121* debugging/testing capabilities. The correct way to specify options in the122* {@code Configuration} is by using the following key-value pairing:123* <i>debug="true"</i>. The key and value should be separated by an124* 'equals' symbol, and the value should be surrounded by double quotes.125* If a String in the form, ${system.property}, occurs in the value,126* it will be expanded to the value of the system property.127* Note that there is no limit to the number of128* options a {@code LoginModule} may define.129*130* <p> The following represents an example {@code Configuration} entry131* based on the syntax above:132*133* <pre>134* Login {135* com.sun.security.auth.module.UnixLoginModule required;136* com.sun.security.auth.module.Krb5LoginModule optional137* useTicketCache="true"138* ticketCache="${user.home}${/}tickets";139* };140* </pre>141*142* <p> This {@code Configuration} specifies that an application named,143* "Login", requires users to first authenticate to the144* <i>com.sun.security.auth.module.UnixLoginModule</i>, which is145* required to succeed. Even if the <i>UnixLoginModule</i>146* authentication fails, the147* <i>com.sun.security.auth.module.Krb5LoginModule</i>148* still gets invoked. This helps hide the source of failure.149* Since the <i>Krb5LoginModule</i> is <i>Optional</i>, the overall150* authentication succeeds only if the <i>UnixLoginModule</i>151* (<i>Required</i>) succeeds.152*153* <p> Also note that the LoginModule-specific options,154* <i>useTicketCache="true"</i> and155* <i>ticketCache=${user.home}${/}tickets"</i>,156* are passed to the <i>Krb5LoginModule</i>.157* These options instruct the <i>Krb5LoginModule</i> to158* use the ticket cache at the specified location.159* The system properties, <i>user.home</i> and <i>/</i>160* (file.separator), are expanded to their respective values.161*162* <p> There is only one Configuration object installed in the runtime at any163* given time. A Configuration object can be installed by calling the164* {@code setConfiguration} method. The installed Configuration object165* can be obtained by calling the {@code getConfiguration} method.166*167* <p> If no Configuration object has been installed in the runtime, a call to168* {@code getConfiguration} installs an instance of the default169* Configuration implementation (a default subclass implementation of this170* abstract class).171* The default Configuration implementation can be changed by setting the value172* of the {@code login.configuration.provider} security property to the fully173* qualified name of the desired Configuration subclass implementation.174*175* <p> Application code can directly subclass Configuration to provide a custom176* implementation. In addition, an instance of a Configuration object can be177* constructed by invoking one of the {@code getInstance} factory methods178* with a standard type. The default policy type is "JavaLoginConfig".179* See the Configuration section in the <a href=180* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">181* Java Cryptography Architecture Standard Algorithm Name Documentation</a>182* for a list of standard Configuration types.183*184* @see javax.security.auth.login.LoginContext185* @see java.security.Security security properties186*/187public abstract class Configuration {188189private static Configuration configuration;190191private final java.security.AccessControlContext acc =192java.security.AccessController.getContext();193194private static void checkPermission(String type) {195SecurityManager sm = System.getSecurityManager();196if (sm != null) {197sm.checkPermission(new AuthPermission198("createLoginConfiguration." + type));199}200}201202/**203* Sole constructor. (For invocation by subclass constructors, typically204* implicit.)205*/206protected Configuration() { }207208/**209* Get the installed login Configuration.210*211* <p>212*213* @return the login Configuration. If a Configuration object was set214* via the {@code Configuration.setConfiguration} method,215* then that object is returned. Otherwise, a default216* Configuration object is returned.217*218* @exception SecurityException if the caller does not have permission219* to retrieve the Configuration.220*221* @see #setConfiguration222*/223public static Configuration getConfiguration() {224225SecurityManager sm = System.getSecurityManager();226if (sm != null)227sm.checkPermission(new AuthPermission("getLoginConfiguration"));228229synchronized (Configuration.class) {230if (configuration == null) {231String config_class = null;232config_class = AccessController.doPrivileged233(new PrivilegedAction<String>() {234public String run() {235return java.security.Security.getProperty236("login.configuration.provider");237}238});239if (config_class == null) {240config_class = "sun.security.provider.ConfigFile";241}242243try {244final String finalClass = config_class;245Configuration untrustedImpl = AccessController.doPrivileged(246new PrivilegedExceptionAction<Configuration>() {247public Configuration run() throws ClassNotFoundException,248InstantiationException,249IllegalAccessException {250Class<? extends Configuration> implClass = Class.forName(251finalClass, false,252Thread.currentThread().getContextClassLoader()253).asSubclass(Configuration.class);254return implClass.newInstance();255}256});257AccessController.doPrivileged(258new PrivilegedExceptionAction<Void>() {259public Void run() {260setConfiguration(untrustedImpl);261return null;262}263}, Objects.requireNonNull(untrustedImpl.acc)264);265} catch (PrivilegedActionException e) {266Exception ee = e.getException();267if (ee instanceof InstantiationException) {268throw (SecurityException) new269SecurityException270("Configuration error:" +271ee.getCause().getMessage() +272"\n").initCause(ee.getCause());273} else {274throw (SecurityException) new275SecurityException276("Configuration error: " +277ee.toString() +278"\n").initCause(ee);279}280}281}282return configuration;283}284}285286/**287* Set the login {@code Configuration}.288*289* <p>290*291* @param configuration the new {@code Configuration}292*293* @exception SecurityException if the current thread does not have294* Permission to set the {@code Configuration}.295*296* @see #getConfiguration297*/298public static void setConfiguration(Configuration configuration) {299SecurityManager sm = System.getSecurityManager();300if (sm != null)301sm.checkPermission(new AuthPermission("setLoginConfiguration"));302Configuration.configuration = configuration;303}304305/**306* Returns a Configuration object of the specified type.307*308* <p> This method traverses the list of registered security providers,309* starting with the most preferred Provider.310* A new Configuration object encapsulating the311* ConfigurationSpi implementation from the first312* Provider that supports the specified type is returned.313*314* <p> Note that the list of registered providers may be retrieved via315* the {@link Security#getProviders() Security.getProviders()} method.316*317* @param type the specified Configuration type. See the Configuration318* section in the <a href=319* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">320* Java Cryptography Architecture Standard Algorithm Name321* Documentation</a> for a list of standard Configuration types.322*323* @param params parameters for the Configuration, which may be null.324*325* @return the new Configuration object.326*327* @exception SecurityException if the caller does not have permission328* to get a Configuration instance for the specified type.329*330* @exception NullPointerException if the specified type is null.331*332* @exception IllegalArgumentException if the specified parameters333* are not understood by the ConfigurationSpi implementation334* from the selected Provider.335*336* @exception NoSuchAlgorithmException if no Provider supports a337* ConfigurationSpi implementation for the specified type.338*339* @see Provider340* @since 1.6341*/342public static Configuration getInstance(String type,343Configuration.Parameters params)344throws NoSuchAlgorithmException {345346checkPermission(type);347try {348GetInstance.Instance instance = GetInstance.getInstance349("Configuration",350ConfigurationSpi.class,351type,352params);353return new ConfigDelegate((ConfigurationSpi)instance.impl,354instance.provider,355type,356params);357} catch (NoSuchAlgorithmException nsae) {358return handleException (nsae);359}360}361362/**363* Returns a Configuration object of the specified type.364*365* <p> A new Configuration object encapsulating the366* ConfigurationSpi implementation from the specified provider367* is returned. The specified provider must be registered368* in the provider list.369*370* <p> Note that the list of registered providers may be retrieved via371* the {@link Security#getProviders() Security.getProviders()} method.372*373* @param type the specified Configuration type. See the Configuration374* section in the <a href=375* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">376* Java Cryptography Architecture Standard Algorithm Name377* Documentation</a> for a list of standard Configuration types.378*379* @param params parameters for the Configuration, which may be null.380*381* @param provider the provider.382*383* @return the new Configuration object.384*385* @exception SecurityException if the caller does not have permission386* to get a Configuration instance for the specified type.387*388* @exception NullPointerException if the specified type is null.389*390* @exception IllegalArgumentException if the specified provider391* is null or empty,392* or if the specified parameters are not understood by393* the ConfigurationSpi implementation from the specified provider.394*395* @exception NoSuchProviderException if the specified provider is not396* registered in the security provider list.397*398* @exception NoSuchAlgorithmException if the specified provider does not399* support a ConfigurationSpi implementation for the specified400* type.401*402* @see Provider403* @since 1.6404*/405public static Configuration getInstance(String type,406Configuration.Parameters params,407String provider)408throws NoSuchProviderException, NoSuchAlgorithmException {409410if (provider == null || provider.length() == 0) {411throw new IllegalArgumentException("missing provider");412}413414checkPermission(type);415try {416GetInstance.Instance instance = GetInstance.getInstance417("Configuration",418ConfigurationSpi.class,419type,420params,421provider);422return new ConfigDelegate((ConfigurationSpi)instance.impl,423instance.provider,424type,425params);426} catch (NoSuchAlgorithmException nsae) {427return handleException (nsae);428}429}430431/**432* Returns a Configuration object of the specified type.433*434* <p> A new Configuration object encapsulating the435* ConfigurationSpi implementation from the specified Provider436* object is returned. Note that the specified Provider object437* does not have to be registered in the provider list.438*439* @param type the specified Configuration type. See the Configuration440* section in the <a href=441* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">442* Java Cryptography Architecture Standard Algorithm Name443* Documentation</a> for a list of standard Configuration types.444*445* @param params parameters for the Configuration, which may be null.446*447* @param provider the Provider.448*449* @return the new Configuration object.450*451* @exception SecurityException if the caller does not have permission452* to get a Configuration instance for the specified type.453*454* @exception NullPointerException if the specified type is null.455*456* @exception IllegalArgumentException if the specified Provider is null,457* or if the specified parameters are not understood by458* the ConfigurationSpi implementation from the specified Provider.459*460* @exception NoSuchAlgorithmException if the specified Provider does not461* support a ConfigurationSpi implementation for the specified462* type.463*464* @see Provider465* @since 1.6466*/467public static Configuration getInstance(String type,468Configuration.Parameters params,469Provider provider)470throws NoSuchAlgorithmException {471472if (provider == null) {473throw new IllegalArgumentException("missing provider");474}475476checkPermission(type);477try {478GetInstance.Instance instance = GetInstance.getInstance479("Configuration",480ConfigurationSpi.class,481type,482params,483provider);484return new ConfigDelegate((ConfigurationSpi)instance.impl,485instance.provider,486type,487params);488} catch (NoSuchAlgorithmException nsae) {489return handleException (nsae);490}491}492493private static Configuration handleException(NoSuchAlgorithmException nsae)494throws NoSuchAlgorithmException {495Throwable cause = nsae.getCause();496if (cause instanceof IllegalArgumentException) {497throw (IllegalArgumentException)cause;498}499throw nsae;500}501502/**503* Return the Provider of this Configuration.504*505* <p> This Configuration instance will only have a Provider if it506* was obtained via a call to {@code Configuration.getInstance}.507* Otherwise this method returns null.508*509* @return the Provider of this Configuration, or null.510*511* @since 1.6512*/513public Provider getProvider() {514return null;515}516517/**518* Return the type of this Configuration.519*520* <p> This Configuration instance will only have a type if it521* was obtained via a call to {@code Configuration.getInstance}.522* Otherwise this method returns null.523*524* @return the type of this Configuration, or null.525*526* @since 1.6527*/528public String getType() {529return null;530}531532/**533* Return Configuration parameters.534*535* <p> This Configuration instance will only have parameters if it536* was obtained via a call to {@code Configuration.getInstance}.537* Otherwise this method returns null.538*539* @return Configuration parameters, or null.540*541* @since 1.6542*/543public Configuration.Parameters getParameters() {544return null;545}546547/**548* Retrieve the AppConfigurationEntries for the specified <i>name</i>549* from this Configuration.550*551* <p>552*553* @param name the name used to index the Configuration.554*555* @return an array of AppConfigurationEntries for the specified <i>name</i>556* from this Configuration, or null if there are no entries557* for the specified <i>name</i>558*/559public abstract AppConfigurationEntry[] getAppConfigurationEntry560(String name);561562/**563* Refresh and reload the Configuration.564*565* <p> This method causes this Configuration object to refresh/reload its566* contents in an implementation-dependent manner.567* For example, if this Configuration object stores its entries in a file,568* calling {@code refresh} may cause the file to be re-read.569*570* <p> The default implementation of this method does nothing.571* This method should be overridden if a refresh operation is supported572* by the implementation.573*574* @exception SecurityException if the caller does not have permission575* to refresh its Configuration.576*/577public void refresh() { }578579/**580* This subclass is returned by the getInstance calls. All Configuration581* calls are delegated to the underlying ConfigurationSpi.582*/583private static class ConfigDelegate extends Configuration {584585private ConfigurationSpi spi;586private Provider p;587private String type;588private Configuration.Parameters params;589590private ConfigDelegate(ConfigurationSpi spi, Provider p,591String type, Configuration.Parameters params) {592this.spi = spi;593this.p = p;594this.type = type;595this.params = params;596}597598public String getType() { return type; }599600public Configuration.Parameters getParameters() { return params; }601602public Provider getProvider() { return p; }603604public AppConfigurationEntry[] getAppConfigurationEntry(String name) {605return spi.engineGetAppConfigurationEntry(name);606}607608public void refresh() {609spi.engineRefresh();610}611}612613/**614* This represents a marker interface for Configuration parameters.615*616* @since 1.6617*/618public static interface Parameters { }619}620621622