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

markt pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 86d3fcf914fd754ede19ed3557dc5a4511dc1124
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Jul 24 17:53:22 2024 +0100

    Refactor SpnegoAuthenticator to use Subject.callAs() when available
---
 .../authenticator/SpnegoAuthenticator.java         | 66 +++++-----------------
 .../org/apache/tomcat/util/compat/Jre18Compat.java |  2 +-
 webapps/docs/changelog.xml                         |  5 ++
 3 files changed, 20 insertions(+), 53 deletions(-)

diff --git a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java 
b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
index c314f5d893..570ce65413 100644
--- a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
@@ -19,11 +19,9 @@ package org.apache.catalina.authenticator;
 import java.io.File;
 import java.io.IOException;
 import java.security.Principal;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 import java.util.Base64;
 import java.util.LinkedHashMap;
+import java.util.concurrent.CompletionException;
 import java.util.regex.Pattern;
 
 import javax.security.auth.Subject;
@@ -33,12 +31,12 @@ import javax.security.auth.login.LoginException;
 import jakarta.servlet.http.HttpServletResponse;
 
 import org.apache.catalina.LifecycleException;
-import org.apache.catalina.Realm;
 import org.apache.catalina.connector.Request;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.compat.JreCompat;
 import org.apache.tomcat.util.compat.JreVendor;
 import org.ietf.jgss.GSSContext;
 import org.ietf.jgss.GSSCredential;
@@ -210,11 +208,15 @@ public class SpnegoAuthenticator extends 
AuthenticatorBase {
             } else {
                 credentialLifetime = GSSCredential.DEFAULT_LIFETIME;
             }
-            final PrivilegedExceptionAction<GSSCredential> action = () -> 
manager.createCredential(null,
-                    credentialLifetime, new Oid("1.3.6.1.5.5.2"), 
GSSCredential.ACCEPT_ONLY);
-            gssContext = manager.createContext(Subject.doAs(subject, action));
+            gssContext = 
manager.createContext(JreCompat.getInstance().callAs(subject, () -> {
+                return manager.createCredential(null, credentialLifetime, new 
Oid("1.3.6.1.5.5.2"),
+                        GSSCredential.ACCEPT_ONLY);
+            }));
 
-            outToken = Subject.doAs(lc.getSubject(), new 
AcceptAction(gssContext, decoded));
+            final GSSContext gssContextFinal = gssContext;
+            outToken = JreCompat.getInstance().callAs(subject, () -> {
+                return gssContextFinal.acceptSecContext(decoded, 0, 
decoded.length);
+            });
 
             if (outToken == null) {
                 if (log.isDebugEnabled()) {
@@ -226,9 +228,9 @@ public class SpnegoAuthenticator extends AuthenticatorBase {
                 return false;
             }
 
-            principal = Subject.doAs(subject,
-                    new AuthenticateAction(context.getRealm(), gssContext, 
storeDelegatedCredential));
-
+            principal = JreCompat.getInstance().callAs(subject, () -> {
+                return context.getRealm().authenticate(gssContextFinal, 
storeDelegatedCredential);
+            });
         } catch (GSSException e) {
             if (log.isDebugEnabled()) {
                 
log.debug(sm.getString("spnegoAuthenticator.ticketValidateFail"), e);
@@ -236,7 +238,7 @@ public class SpnegoAuthenticator extends AuthenticatorBase {
             response.setHeader(AUTH_HEADER_NAME, AUTH_HEADER_VALUE_NEGOTIATE);
             response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
             return false;
-        } catch (PrivilegedActionException e) {
+        } catch (CompletionException e) {
             Throwable cause = e.getCause();
             if (cause instanceof GSSException) {
                 if (log.isDebugEnabled()) {
@@ -294,46 +296,6 @@ public class SpnegoAuthenticator extends AuthenticatorBase 
{
     }
 
 
-    /**
-     * This class gets a gss credential via a privileged action.
-     */
-    public static class AcceptAction implements 
PrivilegedExceptionAction<byte[]> {
-
-        GSSContext gssContext;
-
-        byte[] decoded;
-
-        public AcceptAction(GSSContext context, byte[] decodedToken) {
-            this.gssContext = context;
-            this.decoded = decodedToken;
-        }
-
-        @Override
-        public byte[] run() throws GSSException {
-            return gssContext.acceptSecContext(decoded, 0, decoded.length);
-        }
-    }
-
-
-    public static class AuthenticateAction implements 
PrivilegedAction<Principal> {
-
-        private final Realm realm;
-        private final GSSContext gssContext;
-        private final boolean storeDelegatedCredential;
-
-        public AuthenticateAction(Realm realm, GSSContext gssContext, boolean 
storeDelegatedCredential) {
-            this.realm = realm;
-            this.gssContext = gssContext;
-            this.storeDelegatedCredential = storeDelegatedCredential;
-        }
-
-        @Override
-        public Principal run() {
-            return realm.authenticate(gssContext, storeDelegatedCredential);
-        }
-    }
-
-
     /**
      * This class implements a hack around an incompatibility between the 
SPNEGO implementation in Windows and the
      * SPNEGO implementation in Java 8 update 40 onwards. It was introduced by 
the change to fix this bug:
diff --git a/java/org/apache/tomcat/util/compat/Jre18Compat.java 
b/java/org/apache/tomcat/util/compat/Jre18Compat.java
index 50c744b1d5..be53a73d74 100644
--- a/java/org/apache/tomcat/util/compat/Jre18Compat.java
+++ b/java/org/apache/tomcat/util/compat/Jre18Compat.java
@@ -38,7 +38,7 @@ public class Jre18Compat extends Jre16Compat {
         Method m1 = null;
 
         try {
-            m1 = Subject.class.getMethod("classAS", Subject.class, 
Callable.class);
+            m1 = Subject.class.getMethod("callAs", Subject.class, 
Callable.class);
         } catch (NoSuchMethodException e) {
             // Must before-Java 18
             log.debug(sm.getString("jre18Compat.javaPre18"), e);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 52de3c6ad6..b612e8e01d 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -121,6 +121,11 @@
         processes this as a simple CORS request. Based on a patch suggested by
         thebluemountain. (markt)
       </fix>
+      <fix>
+        Refactor <code>SpnegoAuthenticator</code> so it uses
+        <code>Subject.callAs()</code> rather than <code>Subject.doAs()</code>
+        when the available. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to