This is an automated email from the ASF dual-hosted git repository.

ChristopherSchultz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new e12e023930 Remove JAASRealm
e12e023930 is described below

commit e12e0239309f8e3113f9c531aaa889329a063a6b
Author: Christopher Schultz <[email protected]>
AuthorDate: Tue Oct 13 18:11:52 2026 +0100

    Remove JAASRealm
    
    NOTE: This will not be back-ported
---
 .../apache/catalina/realm/JAASCallbackHandler.java | 207 -------
 java/org/apache/catalina/realm/JAASRealm.java      | 666 ---------------------
 test/org/apache/catalina/realm/TestJAASRealm.java  | 184 ------
 webapps/docs/changelog.xml                         |   3 +
 4 files changed, 3 insertions(+), 1057 deletions(-)

diff --git a/java/org/apache/catalina/realm/JAASCallbackHandler.java 
b/java/org/apache/catalina/realm/JAASCallbackHandler.java
deleted file mode 100644
index 9ef1e0890d..0000000000
--- a/java/org/apache/catalina/realm/JAASCallbackHandler.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.catalina.realm;
-
-
-import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.TextInputCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.apache.tomcat.util.res.StringManager;
-
-/**
- * Implementation of the JAAS <code>CallbackHandler</code> interface, used to 
negotiate delivery of the username and
- * credentials that were specified to our constructor. No interaction with the 
user is required (or possible).
- * <p>
- * The supplied password or client digest is passed to the 
<code>LoginModule</code> unchanged. Any digest comparison is
- * expected to be performed by the <code>LoginModule</code> when it calls back 
into the <code>Realm</code>.
- * <p>
- * At present, <code>JAASCallbackHandler</code> knows how to handle callbacks 
of type
- * <code>javax.security.auth.callback.NameCallback</code>,
- * <code>javax.security.auth.callback.PasswordCallback</code> and
- * <code>javax.security.auth.callback.TextInputCallback</code>.
- */
-public class JAASCallbackHandler implements CallbackHandler {
-
-    // ------------------------------------------------------------ Constructor
-
-
-    /**
-     * Construct a callback handler configured with the specified values.
-     *
-     * @param realm    Our associated JAASRealm instance
-     * @param username Username to be authenticated with
-     * @param password Password to be authenticated with
-     */
-    public JAASCallbackHandler(JAASRealm realm, String username, String 
password) {
-
-        this(realm, username, password, null, null, null, null, null, null, 
null, null);
-    }
-
-
-    /**
-     * Construct a callback handler for DIGEST authentication.
-     *
-     * @param realm      Our associated JAASRealm instance
-     * @param username   Username to be authenticated with
-     * @param password   Password to be authenticated with. For DIGEST 
authentication this is the client digest, which
-     *                       is passed through unchanged since the digest 
comparison is performed by the LoginModule
-     *                       when it calls back into the Realm
-     * @param nonce      Server generated nonce
-     * @param nc         Nonce count
-     * @param cnonce     Client generated nonce
-     * @param qop        Quality of protection applied to the message
-     * @param realmName  Realm name
-     * @param digestA2   Second digest calculated as digest(Method + ":" + uri)
-     * @param algorithm  The digest algorithm to use
-     * @param authMethod The authentication method in use
-     */
-    public JAASCallbackHandler(JAASRealm realm, String username, String 
password, String nonce, String nc,
-            String cnonce, String qop, String realmName, String digestA2, 
String algorithm, String authMethod) {
-        this.realm = realm;
-        this.username = username;
-        this.password = password;
-        this.nonce = nonce;
-        this.nc = nc;
-        this.cnonce = cnonce;
-        this.qop = qop;
-        this.realmName = realmName;
-        this.digestA2 = digestA2;
-        this.authMethod = authMethod;
-        this.algorithm = algorithm;
-    }
-
-    // ----------------------------------------------------- Instance Variables
-
-    /**
-     * The string manager for this package.
-     */
-    protected static final StringManager sm = 
StringManager.getManager(JAASCallbackHandler.class);
-
-    /**
-     * The password to be authenticated with.
-     */
-    protected final String password;
-
-
-    /**
-     * The associated <code>JAASRealm</code> instance.
-     */
-    protected final JAASRealm realm;
-
-    /**
-     * The username to be authenticated with.
-     */
-    protected final String username;
-
-    /**
-     * Server generated nonce.
-     */
-    protected final String nonce;
-
-    /**
-     * Nonce count.
-     */
-    protected final String nc;
-
-    /**
-     * Client generated nonce.
-     */
-    protected final String cnonce;
-
-    /**
-     * Quality of protection applied to the message.
-     */
-    protected final String qop;
-
-    /**
-     * Realm name.
-     */
-    protected final String realmName;
-
-    /**
-     * Second digest.
-     */
-    protected final String digestA2;
-
-    /**
-     * The authentication method to be used. If null, assume BASIC/FORM.
-     */
-    protected final String authMethod;
-
-    /**
-     * Algorithm.
-     */
-    protected final String algorithm;
-
-    // --------------------------------------------------------- Public Methods
-
-
-    /**
-     * Retrieve the information requested in the provided 
<code>Callbacks</code>. This implementation only recognizes
-     * {@link NameCallback}, {@link PasswordCallback} and {@link 
TextInputCallback}. {@link TextInputCallback} is used
-     * to pass the various additional parameters required for DIGEST 
authentication.
-     *
-     * @param callbacks The set of <code>Callback</code>s to be processed
-     *
-     * @exception IOException                  if an input/output error occurs
-     * @exception UnsupportedCallbackException if the login method requests an 
unsupported callback type
-     */
-    @Override
-    public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
-
-        for (Callback callback : callbacks) {
-            switch (callback) {
-                case NameCallback nameCallback -> {
-                    if (realm.getContainer().getLogger().isTraceEnabled()) {
-                        
realm.getContainer().getLogger().trace(sm.getString("jaasCallback.username", 
username));
-                    }
-                    nameCallback.setName(username);
-                }
-                case PasswordCallback passwordCallback -> {
-                    final char[] passwordcontents;
-                    if (password != null) {
-                        passwordcontents = password.toCharArray();
-                    } else {
-                        passwordcontents = new char[0];
-                    }
-                    passwordCallback.setPassword(passwordcontents);
-                }
-                case TextInputCallback cb -> {
-                    switch (cb.getPrompt()) {
-                        case "nonce" -> cb.setText(nonce);
-                        case "nc" -> cb.setText(nc);
-                        case "cnonce" -> cb.setText(cnonce);
-                        case "qop" -> cb.setText(qop);
-                        case "realmName" -> cb.setText(realmName);
-                        case "digestA2" -> cb.setText(digestA2);
-                        case "authMethod" -> cb.setText(authMethod);
-                        case "algorithm" -> cb.setText(algorithm);
-                        case "catalinaBase" -> 
cb.setText(realm.getContainer().getCatalinaBase().getAbsolutePath());
-                        default -> throw new 
UnsupportedCallbackException(callback);
-                    }
-                }
-                case null, default -> throw new 
UnsupportedCallbackException(callback);
-            }
-        }
-    }
-}
diff --git a/java/org/apache/catalina/realm/JAASRealm.java 
b/java/org/apache/catalina/realm/JAASRealm.java
deleted file mode 100644
index 40f8d0c8e1..0000000000
--- a/java/org/apache/catalina/realm/JAASRealm.java
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.catalina.realm;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.AccountExpiredException;
-import javax.security.auth.login.Configuration;
-import javax.security.auth.login.CredentialExpiredException;
-import javax.security.auth.login.FailedLoginException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import jakarta.servlet.http.HttpServletRequest;
-
-import org.apache.catalina.Container;
-import org.apache.catalina.LifecycleException;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.file.ConfigFileLoader;
-import org.apache.tomcat.util.file.ConfigurationSource;
-
-/**
- * <p>
- * Implementation of <b>Realm</b> that authenticates users via the <em>Java 
Authentication and Authorization
- * Service</em> (JAAS).
- * </p>
- * <p>
- * The value configured for the <code>appName</code> property is passed to the
- * <code>javax.security.auth.login.LoginContext</code> constructor, to specify 
the <em>application name</em> used to
- * select the set of relevant <code>LoginModules</code> required.
- * </p>
- * <p>
- * The JAAS Specification describes the result of a successful login as a 
<code>javax.security.auth.Subject</code>
- * instance, which can contain zero or more 
<code>java.security.Principal</code> objects in the return value of the
- * <code>Subject.getPrincipals()</code> method. However, it provides no 
guidance on how to distinguish Principals that
- * describe the individual user (and are thus appropriate to return as the 
value of request.getUserPrincipal() in a web
- * application) from the Principal(s) that describe the authorized roles for 
this user. To maintain as much independence
- * as possible from the underlying <code>LoginMethod</code> implementation 
executed by JAAS, the following policy is
- * implemented by this Realm:
- * </p>
- * <ul>
- * <li>The JAAS <code>LoginModule</code> is assumed to return a 
<code>Subject</code> with at least one
- * <code>Principal</code> instance representing the user himself or herself, 
and zero or more separate
- * <code>Principals</code> representing the security roles authorized for this 
user.</li>
- * <li>On the <code>Principal</code> representing the user, the Principal name 
is an appropriate value to return via the
- * Servlet API method <code>HttpServletRequest.getRemoteUser()</code>.</li>
- * <li>On the <code>Principals</code> representing the security roles, the 
name is the name of the authorized security
- * role.</li>
- * <li>This Realm will be configured with two lists of fully qualified Java 
class names of classes that implement
- * <code>java.security.Principal</code> - one that identifies class(es) 
representing a user, and one that identifies
- * class(es) representing a security role.</li>
- * <li>As this Realm iterates over the <code>Principals</code> returned by 
<code>Subject.getPrincipals()</code>, it will
- * identify the first <code>Principal</code> that matches the "user classes" 
list as the <code>Principal</code> for this
- * user.</li>
- * <li>As this Realm iterates over the <code>Principals</code> returned by 
<code>Subject.getPrincipals()</code>, it will
- * accumulate the set of all <code>Principals</code> matching the "role 
classes" list as identifying the security roles
- * for this user.</li>
- * <li>It is a configuration error for the JAAS login method to return a 
validated <code>Subject</code> without a
- * <code>Principal</code> that matches the "user classes" list.</li>
- * <li>By default, the enclosing Container's name serves as the application 
name used to obtain the JAAS LoginContext
- * ("Catalina" in a default installation). Tomcat must be able to find an 
application with this name in the JAAS
- * configuration file. Here is a hypothetical JAAS configuration file entry 
for a database-oriented login module that
- * uses a Tomcat-managed JNDI database resource: <blockquote>
- *
- * <pre>
- * Catalina {
- * org.foobar.auth.DatabaseLoginModule REQUIRED
- *   JNDI_RESOURCE=jdbc/AuthDB
- *   USER_TABLE=users
- *   USER_ID_COLUMN=id
- *   USER_NAME_COLUMN=name
- *   USER_CREDENTIAL_COLUMN=password
- *   ROLE_TABLE=roles
- *   ROLE_NAME_COLUMN=name
- *   PRINCIPAL_FACTORY=org.foobar.auth.impl.SimplePrincipalFactory;
- * };
- * </pre>
- *
- * </blockquote></li>
- * <li>To set the JAAS configuration file location, set the 
<code>CATALINA_OPTS</code> environment variable similar to
- * the following:
- * 
<blockquote><code>CATALINA_OPTS="-Djava.security.auth.login.config=$CATALINA_HOME/conf/jaas.config"</code></blockquote>
- * </li>
- * <li>As part of the login process, JAASRealm registers its own 
<code>CallbackHandler</code>, called (unsurprisingly)
- * <code>JAASCallbackHandler</code>. This handler supplies the HTTP requests' 
username and credentials to the
- * user-supplied <code>LoginModule</code></li>
- * <li>As with other <code>Realm</code> implementations, digested passwords 
are supported via the configured
- * <code>CredentialHandler</code>. The credentials are passed to the 
<code>LoginModule</code> unchanged; any digest
- * comparison is expected to be performed by the <code>LoginModule</code> when 
it calls back into the
- * <code>Realm</code></li>
- * </ul>
- */
-public class JAASRealm extends RealmBase {
-
-    private static final Log log = LogFactory.getLog(JAASRealm.class);
-
-    /**
-     * Constructs a new JAASRealm.
-     */
-    public JAASRealm() {
-    }
-
-    // ----------------------------------------------------- Instance Variables
-
-
-    /**
-     * The application name passed to the JAAS <code>LoginContext</code>, 
which uses it to select the set of relevant
-     * <code>LoginModule</code>s.
-     */
-    protected String appName = null;
-
-
-    /**
-     * The list of role class names, split out for easy processing.
-     */
-    protected final List<String> roleClasses = new ArrayList<>();
-
-
-    /**
-     * The set of user class names, split out for easy processing.
-     */
-    protected final List<String> userClasses = new ArrayList<>();
-
-
-    /**
-     * Whether to use context ClassLoader or default ClassLoader. True means 
use context ClassLoader, and True is the
-     * default value.
-     */
-    protected boolean useContextClassLoader = true;
-
-
-    /**
-     * Path to find a JAAS configuration file, if not set global JVM JAAS 
configuration will be used.
-     */
-    protected String configFile;
-
-    /**
-     * The loaded JAAS Configuration instance.
-     */
-    protected volatile Configuration jaasConfiguration;
-
-    /**
-     * Flag indicating whether the JAAS configuration has been loaded.
-     */
-    protected volatile boolean jaasConfigurationLoaded = false;
-
-    /**
-     * Keeps track if JAAS invocation of login modules was successful or not. 
By default, it is true unless we detect
-     * JAAS login module can't perform the login. This will be used for 
realm's {@link #isAvailable()} status so that
-     * {@link LockOutRealm} will not lock the user out if JAAS login modules 
are unavailable to perform the actual
-     * login.
-     */
-    private volatile boolean invocationSuccess = true;
-
-    // ------------------------------------------------------------- Properties
-
-    /**
-     * Get the path of the JAAS configuration file.
-     *
-     * @return the path of the JAAS configuration file
-     */
-    public String getConfigFile() {
-        return configFile;
-    }
-
-    /**
-     * Set the JAAS configuration file.
-     *
-     * @param configFile The JAAS configuration file
-     */
-    public void setConfigFile(String configFile) {
-        this.configFile = configFile;
-    }
-
-    /**
-     * Set the JAAS <code>LoginContext</code> app name.
-     *
-     * @param name The application name that will be used to retrieve the set 
of relevant <code>LoginModule</code>s
-     */
-    public void setAppName(String name) {
-        appName = name;
-    }
-
-    /**
-     * Get the JAAS application name.
-     *
-     * @return the application name
-     */
-    public String getAppName() {
-        return appName;
-    }
-
-    /**
-     * Sets whether to use the context or default ClassLoader. True means use 
context ClassLoader.
-     *
-     * @param useContext True means use context ClassLoader
-     */
-    public void setUseContextClassLoader(boolean useContext) {
-        useContextClassLoader = useContext;
-    }
-
-    /**
-     * Returns whether to use the context or default ClassLoader. True means 
to use the context ClassLoader.
-     *
-     * @return The value of useContextClassLoader
-     */
-    public boolean isUseContextClassLoader() {
-        return useContextClassLoader;
-    }
-
-    @Override
-    public void setContainer(Container container) {
-        super.setContainer(container);
-
-        if (appName == null) {
-            appName = makeLegalForJAAS(container.getName());
-            log.info(sm.getString("jaasRealm.appName", appName));
-        }
-    }
-
-    /**
-     * Comma-delimited list of <code>java.security.Principal</code> classes 
that represent security roles.
-     */
-    protected String roleClassNames = null;
-
-    /**
-     * Get the comma-delimited list of role class names.
-     *
-     * @return the role class names
-     */
-    public String getRoleClassNames() {
-        return this.roleClassNames;
-    }
-
-    /**
-     * Sets the list of comma-delimited classes that represent roles. The 
classes in the list must implement
-     * <code>java.security.Principal</code>. The supplied list of classes will 
be parsed when {@link #start()} is
-     * called.
-     *
-     * @param roleClassNames The class names list
-     */
-    public void setRoleClassNames(String roleClassNames) {
-        this.roleClassNames = roleClassNames;
-    }
-
-    /**
-     * Parses a comma-delimited list of class names, and store the class names 
in the provided List. Each class must
-     * implement <code>java.security.Principal</code>.
-     *
-     * @param classNamesString a comma-delimited list of fully qualified class 
names.
-     * @param classNamesList   the list in which the class names will be 
stored. The list is cleared before being
-     *                             populated.
-     */
-    protected void parseClassNames(String classNamesString, List<String> 
classNamesList) {
-        classNamesList.clear();
-        if (classNamesString == null) {
-            return;
-        }
-
-        ClassLoader loader = this.getClass().getClassLoader();
-        if (isUseContextClassLoader()) {
-            loader = Thread.currentThread().getContextClassLoader();
-        }
-
-        String[] classNames = classNamesString.split("[ ]*,[ ]*");
-        for (String className : classNames) {
-            if (className.isEmpty()) {
-                continue;
-            }
-            try {
-                Class<?> principalClass = Class.forName(className, false, 
loader);
-                if (Principal.class.isAssignableFrom(principalClass)) {
-                    classNamesList.add(className);
-                } else {
-                    log.error(sm.getString("jaasRealm.notPrincipal", 
className));
-                }
-            } catch (ClassNotFoundException e) {
-                log.error(sm.getString("jaasRealm.classNotFound", className));
-            }
-        }
-    }
-
-    /**
-     * Comma-delimited list of <code>java.security.Principal</code> classes 
that represent individual users.
-     */
-    protected String userClassNames = null;
-
-    /**
-     * Get the comma-delimited list of user class names.
-     *
-     * @return the user class names
-     */
-    public String getUserClassNames() {
-        return this.userClassNames;
-    }
-
-    /**
-     * Sets the list of comma-delimited classes that represent individual 
users. The classes in the list must implement
-     * <code>java.security.Principal</code>. The supplied list of classes will 
be parsed when {@link #start()} is
-     * called.
-     *
-     * @param userClassNames The class names list
-     */
-    public void setUserClassNames(String userClassNames) {
-        this.userClassNames = userClassNames;
-    }
-
-
-    // --------------------------------------------------------- Public Methods
-
-    @Override
-    public Principal authenticate(String username, String credentials) {
-        return authenticate(username, new JAASCallbackHandler(this, username, 
credentials));
-    }
-
-
-    @Override
-    public Principal authenticate(String username, String clientDigest, String 
nonce, String nc, String cnonce,
-            String qop, String realmName, String digestA2, String algorithm) {
-        return authenticate(username, new JAASCallbackHandler(this, username, 
clientDigest, nonce, nc, cnonce, qop,
-                realmName, digestA2, algorithm, 
HttpServletRequest.DIGEST_AUTH));
-    }
-
-
-    // ------------------------------------------------------ Protected Methods
-
-    /**
-     * Perform the actual JAAS authentication.
-     *
-     * @param username        The username
-     * @param callbackHandler The callback handler
-     *
-     * @return the associated principal, or <code>null</code> if there is none.
-     */
-    protected Principal authenticate(String username, CallbackHandler 
callbackHandler) {
-
-        // Establish a LoginContext to use for authentication
-        try {
-            if (log.isTraceEnabled()) {
-                log.trace(sm.getString("jaasRealm.beginLogin", username, 
appName));
-            }
-
-            // What if the LoginModule is in the container class loader ?
-            ClassLoader ocl = null;
-            Thread currentThread = null;
-
-            if (!isUseContextClassLoader()) {
-                currentThread = Thread.currentThread();
-                ocl = currentThread.getContextClassLoader();
-                
currentThread.setContextClassLoader(this.getClass().getClassLoader());
-            }
-
-            LoginContext loginContext;
-            try {
-                Configuration config = getConfig();
-                loginContext = new LoginContext(appName, null, 
callbackHandler, config);
-            } catch (Throwable t) {
-                ExceptionUtils.handleThrowable(t);
-                log.error(sm.getString("jaasRealm.unexpectedError"), t);
-                // There is configuration issue with JAAS so mark the realm as
-                // unavailable
-                invocationSuccess = false;
-                return null;
-            } finally {
-                if (currentThread != null) {
-                    currentThread.setContextClassLoader(ocl);
-                }
-            }
-
-            if (log.isTraceEnabled()) {
-                log.trace("Login context created " + username);
-            }
-
-            // Negotiate a login via this LoginContext
-            Subject subject;
-            try {
-                loginContext.login();
-                subject = loginContext.getSubject();
-                // We were able to perform login successfully so mark JAAS 
realm as
-                // available as it could have been set to false in prior 
attempts.
-                // Change invocationSuccess variable only when we know the 
outcome
-                // of the JAAS operation to keep variable consistent.
-                invocationSuccess = true;
-                if (subject == null) {
-                    if (log.isDebugEnabled()) {
-                        log.debug(sm.getString("jaasRealm.nullSubject", 
username));
-                    }
-                    silentLogout(loginContext);
-                    return null;
-                }
-            } catch (AccountExpiredException e) {
-                if (log.isDebugEnabled()) {
-                    log.debug(sm.getString("jaasRealm.accountExpired", 
username), e);
-                }
-                // JAAS checked LoginExceptions are successful authentication
-                // invocations so mark JAAS realm as available
-                invocationSuccess = true;
-                return null;
-            } catch (CredentialExpiredException e) {
-                if (log.isDebugEnabled()) {
-                    log.debug(sm.getString("jaasRealm.credentialExpired", 
username), e);
-                }
-                // JAAS checked LoginExceptions are successful authentication
-                // invocations so mark JAAS realm as available
-                invocationSuccess = true;
-                return null;
-            } catch (FailedLoginException e) {
-                if (log.isDebugEnabled()) {
-                    log.debug(sm.getString("jaasRealm.failedLogin", username), 
e);
-                }
-                // JAAS checked LoginExceptions are successful authentication
-                // invocations so mark JAAS realm as available
-                invocationSuccess = true;
-                return null;
-            } catch (LoginException e) {
-                log.warn(sm.getString("jaasRealm.loginException", username), 
e);
-                // JAAS checked LoginExceptions are successful authentication
-                // invocations so mark JAAS realm as available
-                invocationSuccess = true;
-                return null;
-            } catch (Throwable t) {
-                ExceptionUtils.handleThrowable(t);
-                log.error(sm.getString("jaasRealm.unexpectedError"), t);
-                // JAAS throws exception different from LoginException so mark 
the
-                // realm as unavailable
-                invocationSuccess = false;
-                return null;
-            }
-
-            if (log.isTraceEnabled()) {
-                log.trace(sm.getString("jaasRealm.loginContextCreated", 
username));
-            }
-
-            // Return the appropriate Principal for this authenticated Subject
-            Principal principal = createPrincipal(username, subject, 
loginContext);
-            if (principal == null) {
-                if (log.isDebugEnabled()) {
-                    log.debug(sm.getString("jaasRealm.authenticateFailure", 
username));
-                }
-                silentLogout(loginContext);
-                return null;
-            }
-            if (log.isTraceEnabled()) {
-                log.trace(sm.getString("jaasRealm.authenticateSuccess", 
username, principal));
-            }
-
-            return principal;
-        } catch (Throwable t) {
-            log.error(sm.getString("jaasRealm.unexpectedError"), t);
-            // JAAS throws exception different from LoginException so mark the 
realm as unavailable
-            invocationSuccess = false;
-            return null;
-        }
-    }
-
-
-    private void silentLogout(LoginContext loginContext) {
-        try {
-            loginContext.logout();
-        } catch (Throwable t) {
-            ExceptionUtils.handleThrowable(t);
-            // Ignore anything else. Caller should have created any necessary 
log entries.
-        }
-    }
-
-
-    /**
-     * @return the password associated with the given principal's username. 
This always returns null as the JAASRealm
-     *             has no way of obtaining this information.
-     */
-    @Override
-    protected String getPassword(String username) {
-        return null;
-    }
-
-
-    @Override
-    protected Principal getPrincipal(String username) {
-
-        return authenticate(username, new JAASCallbackHandler(this, username, 
null, null, null, null, null, null, null,
-                null, HttpServletRequest.CLIENT_CERT_AUTH));
-
-    }
-
-
-    /**
-     * Identify and return a <code>java.security.Principal</code> instance 
representing the authenticated user for the
-     * specified <code>Subject</code>. The Principal is constructed by 
scanning the list of Principals returned by the
-     * JAASLoginModule. The first <code>Principal</code> object that matches 
one of the class names supplied as a "user
-     * class" is the user Principal. This object is returned to the caller. 
Any remaining principal objects returned by
-     * the LoginModules are mapped to roles, but only if their respective 
classes match one of the "role class" classes.
-     * If a user Principal cannot be constructed, return <code>null</code>.
-     *
-     * @param username     The associated username
-     * @param subject      The <code>Subject</code> representing the logged-in 
user
-     * @param loginContext Associated with the Principal so {@link 
LoginContext#logout()} can be called later
-     *
-     * @return the principal object
-     */
-    protected Principal createPrincipal(String username, Subject subject, 
LoginContext loginContext) {
-        // Prepare to scan the Principals for this Subject
-
-        List<String> roles = new ArrayList<>();
-        Principal userPrincipal = null;
-
-        // Scan the Principals for this Subject
-        for (Principal principal : subject.getPrincipals()) {
-            String principalClass = principal.getClass().getName();
-
-            if (log.isTraceEnabled()) {
-                log.trace(sm.getString("jaasRealm.checkPrincipal", principal, 
principalClass));
-            }
-
-            if (userPrincipal == null && userClasses.contains(principalClass)) 
{
-                userPrincipal = principal;
-                if (log.isTraceEnabled()) {
-                    log.trace(sm.getString("jaasRealm.userPrincipalSuccess", 
principal.getName()));
-                }
-            }
-
-            if (roleClasses.contains(principalClass)) {
-                roles.add(principal.getName());
-                if (log.isTraceEnabled()) {
-                    log.trace(sm.getString("jaasRealm.rolePrincipalAdd", 
principal.getName()));
-                }
-            }
-        }
-
-        // Print failure message if needed
-        if (userPrincipal == null) {
-            if (log.isDebugEnabled()) {
-                log.debug(sm.getString("jaasRealm.userPrincipalFailure"));
-                log.debug(sm.getString("jaasRealm.rolePrincipalFailure"));
-            }
-            return null;
-        } else {
-            if (roles.isEmpty()) {
-                if (log.isDebugEnabled()) {
-                    log.debug(sm.getString("jaasRealm.rolePrincipalFailure"));
-                }
-            }
-        }
-
-        // Return the resulting Principal for our authenticated user
-        return new GenericPrincipal(username, roles, userPrincipal, 
loginContext);
-    }
-
-    /**
-     * Ensure the given name is legal for JAAS configuration. Added for 
Bugzilla 30869, made protected for easy
-     * customization in case my implementation is insufficient, which I think 
is very likely.
-     *
-     * @param src The name to validate
-     *
-     * @return A string that's a valid JAAS realm name
-     */
-    protected String makeLegalForJAAS(final String src) {
-        String result = src;
-
-        // Default name is "other" per JAAS spec
-        if (result == null) {
-            result = "other";
-        }
-
-        // Strip leading slash if present, as Sun JAAS impl
-        // barfs on it (see Bugzilla 30869 bug report).
-        if (result.startsWith("/")) {
-            result = result.substring(1);
-        }
-
-        return result;
-    }
-
-
-    // ------------------------------------------------------ Lifecycle Methods
-
-    @Override
-    protected void startInternal() throws LifecycleException {
-
-        // These need to be called after loading configuration, in case
-        // useContextClassLoader appears after them in xml config
-        parseClassNames(userClassNames, userClasses);
-        parseClassNames(roleClassNames, roleClasses);
-
-        super.startInternal();
-    }
-
-
-    /**
-     * Load custom JAAS Configuration.
-     *
-     * @return the loaded configuration
-     */
-    protected Configuration getConfig() {
-        // Local copy to avoid possible NPE due to concurrent change
-        String configFile = this.configFile;
-        try {
-            if (jaasConfigurationLoaded) {
-                return jaasConfiguration;
-            }
-            synchronized (this) {
-                if (configFile == null) {
-                    jaasConfigurationLoaded = true;
-                    return null;
-                }
-                if (jaasConfigurationLoaded) {
-                    return jaasConfiguration;
-                }
-                @SuppressWarnings("unchecked")
-                Class<Configuration> sunConfigFile =
-                        (Class<Configuration>) 
Class.forName("com.sun.security.auth.login.ConfigFile");
-                Constructor<Configuration> constructor = 
sunConfigFile.getConstructor(URI.class);
-                URL resource = 
Thread.currentThread().getContextClassLoader().getResource(configFile);
-                Configuration config;
-                if (resource == null) {
-                    try (ConfigurationSource.Resource configFileResource =
-                            
ConfigFileLoader.getSource().getResource(configFile)) {
-                        config = 
constructor.newInstance(configFileResource.getURI());
-                    } catch (IOException ioe) {
-                        throw new 
RuntimeException(sm.getString("jaasRealm.configFileNotFound", configFile));
-                    }
-                } else {
-                    URI uri = resource.toURI();
-                    config = constructor.newInstance(uri);
-                }
-                this.jaasConfiguration = config;
-                this.jaasConfigurationLoaded = true;
-                return this.jaasConfiguration;
-            }
-        } catch (InvocationTargetException ex) {
-            throw new 
RuntimeException(ExceptionUtils.unwrapInvocationTargetException(ex));
-        } catch (SecurityException | URISyntaxException | 
ReflectiveOperationException | IllegalArgumentException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return invocationSuccess;
-    }
-}
diff --git a/test/org/apache/catalina/realm/TestJAASRealm.java 
b/test/org/apache/catalina/realm/TestJAASRealm.java
deleted file mode 100644
index 2ce87e8289..0000000000
--- a/test/org/apache/catalina/realm/TestJAASRealm.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.catalina.realm;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.Principal;
-import java.util.Locale;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.startup.Tomcat;
-import org.apache.catalina.startup.TomcatBaseTest;
-import org.apache.tomcat.util.buf.HexUtils;
-
-public class TestJAASRealm extends TomcatBaseTest {
-
-    private static final String ALGORITHM = "MD5";
-
-    private static final String CONFIG =
-            "CustomLogin {\n" +
-            "    org.apache.catalina.realm.TesterLoginModule\n" +
-            "    sufficient;\n" +
-            "};";
-
-    private static final String CONFIG_MEMORY =
-            "MemoryLogin {\n" +
-            "    org.apache.catalina.realm.JAASMemoryLoginModule\n" +
-            "    sufficient pathname=\"tomcat-users-lm.xml\";\n" +
-            "};";
-
-    @Test
-    public void testRealm() throws Exception {
-
-        Tomcat tomcat = getTomcatInstance();
-
-        // Write login config to the temp path
-        File loginConfFile = new File(getTemporaryDirectory(), 
"customLoginConfig.conf");
-        try (PrintWriter writer = new PrintWriter(loginConfFile)) {
-            writer.write(CONFIG);
-        }
-        addDeleteOnTearDown(loginConfFile);
-
-        JAASRealm jaasRealm = new JAASRealm();
-        jaasRealm.setAppName("CustomLogin");
-        jaasRealm.setCredentialHandler(new MessageDigestCredentialHandler());
-        jaasRealm.setUserClassNames(TesterPrincipal.class.getName());
-        jaasRealm.setRoleClassNames(TesterRolePrincipal.class.getName());
-        jaasRealm.setConfigFile(loginConfFile.getAbsolutePath());
-        Context context = tomcat.addContext("/jaastest", null);
-        context.setRealm(jaasRealm);
-
-        tomcat.start();
-
-        Principal p = jaasRealm.authenticate("foo", "bar");
-        Assert.assertNull(p);
-        p = jaasRealm.authenticate("tomcatuser", "pass");
-        Assert.assertNotNull(p);
-        Assert.assertTrue(p instanceof GenericPrincipal);
-        GenericPrincipal gp = (GenericPrincipal) p;
-        Assert.assertTrue(gp.hasRole("role1"));
-    }
-
-    @Test
-    public void testMemoryLoginModule() throws Exception {
-        Tomcat tomcat = getTomcatInstance();
-
-        File tomcatUsersXml = new File(getTemporaryDirectory(), 
"tomcat-users-lm.xml");
-        try (PrintWriter writer = new PrintWriter(tomcatUsersXml)) {
-            writer.write(TestMemoryRealm.CONFIG);
-        }
-        addDeleteOnTearDown(tomcatUsersXml);
-
-        // Write login config to the temp path
-        File loginConfFile = new File(getTemporaryDirectory(), 
"memoryLoginConfig.conf");
-        try (PrintWriter writer = new PrintWriter(loginConfFile)) {
-            String path = tomcatUsersXml.getAbsolutePath();
-            if (File.separatorChar == '\\') {
-                path = path.replace("\\", "\\\\");
-            }
-            writer.write(CONFIG_MEMORY.replace("tomcat-users-lm.xml", path));
-        }
-        addDeleteOnTearDown(loginConfFile);
-
-        JAASRealm jaasRealm = new JAASRealm();
-        jaasRealm.setAppName("MemoryLogin");
-        jaasRealm.setCredentialHandler(new MessageDigestCredentialHandler());
-        jaasRealm.setUserClassNames(GenericPrincipal.class.getName());
-        jaasRealm.setRoleClassNames(GenericPrincipal.class.getName());
-        jaasRealm.setConfigFile(loginConfFile.getAbsolutePath());
-        Context context = tomcat.addContext("/jaastest", null);
-        context.setRealm(jaasRealm);
-
-        tomcat.start();
-
-        Principal p = jaasRealm.authenticate("foo", "bar");
-        Assert.assertNull(p);
-        p = jaasRealm.authenticate("admin", "sekr3t");
-        Assert.assertNotNull(p);
-        Assert.assertTrue(p instanceof GenericPrincipal);
-        GenericPrincipal gp = (GenericPrincipal) p;
-        Assert.assertTrue(gp.hasRole("testrole"));
-        gp.logout();
-    }
-
-    @Test
-    public void testMemoryLoginModuleDigestAuth() throws Exception {
-        Tomcat tomcat = getTomcatInstance();
-
-        File tomcatUsersXml = new File(getTemporaryDirectory(), 
"tomcat-users-lm-digest.xml");
-        try (PrintWriter writer = new PrintWriter(tomcatUsersXml)) {
-            writer.write(TestMemoryRealm.CONFIG);
-        }
-        addDeleteOnTearDown(tomcatUsersXml);
-
-        // Write login config to the temp path
-        File loginConfFile = new File(getTemporaryDirectory(), 
"memoryLoginConfigDigest.conf");
-        try (PrintWriter writer = new PrintWriter(loginConfFile)) {
-            String path = tomcatUsersXml.getAbsolutePath();
-            if (File.separatorChar == '\\') {
-                path = path.replace("\\", "\\\\");
-            }
-            writer.write(CONFIG_MEMORY.replace("tomcat-users-lm.xml", path));
-        }
-        addDeleteOnTearDown(loginConfFile);
-
-        JAASRealm jaasRealm = new JAASRealm();
-        jaasRealm.setAppName("MemoryLogin");
-        // Use the same algorithm for the realm credential handler as used for
-        // the digest authentication
-        MessageDigestCredentialHandler credentialHandler = new 
MessageDigestCredentialHandler();
-        credentialHandler.setAlgorithm(ALGORITHM);
-        jaasRealm.setCredentialHandler(credentialHandler);
-        jaasRealm.setUserClassNames(GenericPrincipal.class.getName());
-        jaasRealm.setRoleClassNames(GenericPrincipal.class.getName());
-        jaasRealm.setConfigFile(loginConfFile.getAbsolutePath());
-        Context context = tomcat.addContext("/jaastest", null);
-        context.setRealm(jaasRealm);
-
-        tomcat.start();
-
-        String nonce = "test-nonce";
-        String nc = "00000001";
-        String cnonce = "test-cnonce";
-        String qop = "auth";
-        String realmName = "test-realm";
-
-        MessageDigest md5 = MessageDigest.getInstance(ALGORITHM);
-        String digestA2 = 
HexUtils.toHexString(md5.digest("GET:/jaastest".getBytes(StandardCharsets.UTF_8)));
-        // digestA1 as the client computes it from the stored (clear text in
-        // the login module's user file) password
-        String digestA1 = HexUtils.toHexString(
-                md5.digest(("admin:" + realmName + 
":sekr3t").getBytes(StandardCharsets.UTF_8)));
-        String clientDigest = HexUtils.toHexString(md5.digest(
-                (digestA1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop 
+ ":" + digestA2)
-                        .getBytes(StandardCharsets.UTF_8)));
-
-        Principal p = jaasRealm.authenticate("admin", 
clientDigest.toLowerCase(Locale.ENGLISH), nonce, nc, cnonce,
-                qop, realmName, digestA2, ALGORITHM);
-        Assert.assertNotNull(p);
-        Assert.assertTrue(p instanceof GenericPrincipal);
-        GenericPrincipal gp = (GenericPrincipal) p;
-        Assert.assertTrue(gp.hasRole("testrole"));
-        gp.logout();
-    }
-}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index d5f5d3a36f..95f484dada 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -399,6 +399,9 @@
         Connector compression will now enable gzip compression with a request
         header of the form <code>Accept-Encoding: *</code>. (markt)
       </fix>
+      <fix>
+        Remove JAASRealm. (schultz)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to