This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 11.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit d0a0db635c2956b9d0f600cef18d46effc0fcc71 Author: opencode <[email protected]> AuthorDate: Wed Sep 30 10:14:02 2026 +0200 Guard SpnegoAuthenticator against missing JAAS/Kerberos config files, handle the unchecked SecurityException they would cause and log GSS ticket failures with the correct message --- .../authenticator/SpnegoAuthenticator.java | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java index 0147000700..52287593e7 100644 --- a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java +++ b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java @@ -167,17 +167,25 @@ public class SpnegoAuthenticator extends AuthenticatorBase { // Kerberos configuration file location String krb5Conf = System.getProperty(Constants.KRB5_CONF_PROPERTY); if (krb5Conf == null) { - // System property not set, use the Tomcat default + // System property not set, use the Tomcat default if the file exists. If it does not, leave the JVM + // defaults in place. Pointing the property at a file that does not exist breaks Kerberos/JAAS for the + // whole JVM. File krb5ConfFile = new File(container.getCatalinaBase(), Constants.DEFAULT_KRB5_CONF); - System.setProperty(Constants.KRB5_CONF_PROPERTY, krb5ConfFile.getAbsolutePath()); + if (krb5ConfFile.isFile()) { + System.setProperty(Constants.KRB5_CONF_PROPERTY, krb5ConfFile.getAbsolutePath()); + } } // JAAS configuration file location String jaasConf = System.getProperty(Constants.JAAS_CONF_PROPERTY); if (jaasConf == null) { - // System property not set, use the Tomcat default + // System property not set, use the Tomcat default if the file exists. If it does not, leave the JVM + // defaults in place. Pointing the property at a file that does not exist causes the LoginContext + // constructor to throw an unchecked SecurityException for the whole JVM. File jaasConfFile = new File(container.getCatalinaBase(), Constants.DEFAULT_JAAS_CONF); - System.setProperty(Constants.JAAS_CONF_PROPERTY, jaasConfFile.getAbsolutePath()); + if (jaasConfFile.isFile()) { + System.setProperty(Constants.JAAS_CONF_PROPERTY, jaasConfFile.getAbsolutePath()); + } } } @@ -256,7 +264,10 @@ public class SpnegoAuthenticator extends AuthenticatorBase { try { lc = new LoginContext(getLoginConfigName()); lc.login(); - } catch (LoginException e) { + } catch (LoginException | SecurityException e) { + // SecurityException may be thrown (wrapping an IOException) by the LoginContext constructor if the + // JAAS configuration file referenced by the java.security.auth.login.config system property does not + // exist. log.error(sm.getString("spnegoAuthenticator.serviceLoginFail"), e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return false; @@ -305,10 +316,13 @@ public class SpnegoAuthenticator extends AuthenticatorBase { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return false; } catch (CompletionException e) { + // Subject.callAs() wraps any exception thrown by the action in a CompletionException, so GSS failures + // (e.g. an invalid or expired client ticket) arrive here rather than in the GSSException catch block + // above. Throwable cause = e.getCause(); if (cause instanceof GSSException) { if (log.isDebugEnabled()) { - log.debug(sm.getString("spnegoAuthenticator.serviceLoginFail"), e); + log.debug(sm.getString("spnegoAuthenticator.ticketValidateFail"), e); } } else { log.error(sm.getString("spnegoAuthenticator.serviceLoginFail"), e); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
