Author: remm Date: Thu Oct 22 15:11:06 2015 New Revision: 1710030 URL: http://svn.apache.org/viewvc?rev=1710030&view=rev Log: Remove some duplicate code (helper classes are public for now), add configuration for digest, cleanups.
Modified: tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/BasicAuthModule.java tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/DigestAuthModule.java tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/FormAuthModule.java tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/SpnegoAuthModule.java tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/TomcatAuthModule.java Modified: tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java?rev=1710030&r1=1710029&r2=1710030&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java Thu Oct 22 15:11:06 2015 @@ -402,7 +402,7 @@ public class DigestAuthenticator extends }; } - private static class DigestInfo { + public static class DigestInfo { private final String opaque; private final long nonceValidity; @@ -608,7 +608,7 @@ public class DigestAuthenticator extends } - private static class NonceInfo { + public static class NonceInfo { private final long timestamp; private final boolean seen[]; private final int offset; Modified: tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java?rev=1710030&r1=1710029&r2=1710030&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java Thu Oct 22 15:11:06 2015 @@ -307,13 +307,13 @@ public class SpnegoAuthenticator extends /** * This class gets a gss credential via a privileged action. */ - private static class AcceptAction implements PrivilegedExceptionAction<byte[]> { + public static class AcceptAction implements PrivilegedExceptionAction<byte[]> { GSSContext gssContext; byte[] decoded; - AcceptAction(GSSContext context, byte[] decodedToken) { + public AcceptAction(GSSContext context, byte[] decodedToken) { this.gssContext = context; this.decoded = decodedToken; } @@ -326,7 +326,7 @@ public class SpnegoAuthenticator extends } - private static class AuthenticateAction implements PrivilegedAction<Principal> { + public static class AuthenticateAction implements PrivilegedAction<Principal> { private final Realm realm; private final GSSContext gssContext; @@ -359,7 +359,7 @@ public class SpnegoAuthenticator extends * This hack works by re-ordering the list of mechTypes in the NegTokenInit * token. */ - private static class SpnegoTokenFixer { + public static class SpnegoTokenFixer { public static void fix(byte[] token) { SpnegoTokenFixer fixer = new SpnegoTokenFixer(token); Modified: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/BasicAuthModule.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/BasicAuthModule.java?rev=1710030&r1=1710029&r2=1710030&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/BasicAuthModule.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/BasicAuthModule.java Thu Oct 22 15:11:06 2015 @@ -18,7 +18,6 @@ package org.apache.catalina.authenticato import java.io.IOException; import java.text.MessageFormat; -import java.util.Iterator; import java.util.Map; import javax.security.auth.Subject; @@ -35,7 +34,6 @@ import javax.servlet.http.HttpServletRes import org.apache.catalina.Context; import org.apache.catalina.authenticator.BasicAuthenticator.BasicCredentials; import org.apache.catalina.connector.Request; -import org.apache.catalina.realm.GenericPrincipal; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; @@ -53,10 +51,9 @@ public class BasicAuthModule extends Tom } - @SuppressWarnings("rawtypes") @Override public void initializeModule(MessagePolicy requestPolicy, MessagePolicy responsePolicy, - CallbackHandler handler, Map options) throws AuthException { + CallbackHandler handler, Map<String, String> options) throws AuthException { } @@ -114,13 +111,6 @@ public class BasicAuthModule extends Tom } - private GenericPrincipal getPrincipal(PasswordValidationCallback passwordCallback) { - Iterator<Object> credentials = passwordCallback.getSubject().getPrivateCredentials() - .iterator(); - return (GenericPrincipal) credentials.next(); - } - - @Override public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException { Modified: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/DigestAuthModule.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/DigestAuthModule.java?rev=1710030&r1=1710029&r2=1710030&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/DigestAuthModule.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/DigestAuthModule.java Thu Oct 22 15:11:06 2015 @@ -17,7 +17,6 @@ package org.apache.catalina.authenticator.jaspic.provider.modules; import java.io.IOException; -import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.security.Principal; import java.text.MessageFormat; @@ -36,10 +35,12 @@ import javax.servlet.http.HttpServletRes import org.apache.catalina.Context; import org.apache.catalina.Realm; +import org.apache.catalina.authenticator.DigestAuthenticator.DigestInfo; +import org.apache.catalina.authenticator.DigestAuthenticator.NonceInfo; +import org.apache.catalina.connector.Request; import org.apache.catalina.util.StandardSessionIdGenerator; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.util.http.parser.Authorization; import org.apache.tomcat.util.security.ConcurrentMessageDigest; import org.apache.tomcat.util.security.MD5Encoder; @@ -179,17 +180,31 @@ public class DigestAuthModule extends To @Override - @SuppressWarnings("rawtypes") - public void initializeModule(MessagePolicy requestPolicy, MessagePolicy responsePolicy, - CallbackHandler handler, Map options) throws AuthException { + public synchronized void initializeModule(MessagePolicy requestPolicy, MessagePolicy responsePolicy, + CallbackHandler handler, Map<String, String> options) throws AuthException { this.handler = handler; - startInternal(); - } - - - protected synchronized void startInternal() { this.sessionIdGenerator = new StandardSessionIdGenerator(); + // Get properties from options + this.key = options.get("key"); + String nonceCacheSizeValue = options.get("nonceCacheSize"); + if (nonceCacheSizeValue != null) { + this.nonceCacheSize = Integer.parseInt(nonceCacheSizeValue); + } + String nonceCountWindowSizeValue = options.get("nonceCountWindowSize"); + if (nonceCountWindowSizeValue != null) { + this.nonceCountWindowSize = Integer.parseInt(nonceCountWindowSizeValue); + } + String nonceValidityValue = options.get("nonceValidity"); + if (nonceValidityValue != null) { + this.nonceValidity = Long.parseLong(nonceValidityValue); + } + this.opaque = options.get("opaque"); + String validateUriValue = options.get("validateUri"); + if (validateUriValue != null) { + this.validateUri = Boolean.parseBoolean(validateUriValue); + } + // Generate a random secret key if (getKey() == null) { setKey(sessionIdGenerator.generateSessionId()); @@ -231,12 +246,12 @@ public class DigestAuthModule extends To Subject serviceSubject) throws AuthException { Principal principal = null; - HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); + Request request = (Request) messageInfo.getRequestMessage(); HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage(); String authorization = request.getHeader(AUTHORIZATION_HEADER); DigestInfo digestInfo = new DigestInfo(getOpaque(), getNonceValidity(), getKey(), nonces, - isValidateUri(), getRealmName()); + isValidateUri()); if (authorization == null || !digestInfo.parse(request, authorization)) { String nonce = generateNonce(request); @@ -245,6 +260,7 @@ public class DigestAuthModule extends To } if (digestInfo.validate(request)) { + // FIXME: maybe use a custom callback handler instead principal = digestInfo.authenticate(realm); } @@ -391,240 +407,4 @@ public class DigestAuthModule extends To } - private static class DigestInfo { - - private final String opaque; - private final long nonceValidity; - private final String key; - private final Map<String, NonceInfo> nonces; - private boolean validateUri = true; - - private String userName = null; - private String method = null; - private String uri = null; - private String response = null; - private String nonce = null; - private String nc = null; - private String cnonce = null; - private String realmName = null; - private String qop = null; - private String opaqueReceived = null; - - private boolean nonceStale = false; - - private String contextRealmName; - - public DigestInfo(String opaque, long nonceValidity, String key, - Map<String, NonceInfo> nonces, boolean validateUri, String contextRealmName) { - this.opaque = opaque; - this.nonceValidity = nonceValidity; - this.key = key; - this.nonces = nonces; - this.validateUri = validateUri; - this.contextRealmName = contextRealmName; - } - - public String getUsername() { - return userName; - } - - public boolean parse(HttpServletRequest request, String authorization) { - // Validate the authorization credentials format - if (authorization == null) { - return false; - } - - Map<String, String> directives; - try { - directives = Authorization.parseAuthorizationDigest( - new StringReader(authorization)); - } catch (IOException e) { - return false; - } - - if (directives == null) { - return false; - } - - method = request.getMethod(); - userName = directives.get("username"); - realmName = directives.get("realm"); - nonce = directives.get("nonce"); - nc = directives.get("nc"); - cnonce = directives.get("cnonce"); - qop = directives.get("qop"); - uri = directives.get("uri"); - response = directives.get("response"); - opaqueReceived = directives.get("opaque"); - - return true; - } - - public boolean validate(HttpServletRequest request) { - if ((userName == null) || (realmName == null) || (nonce == null) || (uri == null) - || (response == null)) { - return false; - } - - // Validate the URI - should match the request line sent by client - if (validateUri) { - String uriQuery; - String query = request.getQueryString(); - if (query == null) { - uriQuery = request.getRequestURI(); - } else { - uriQuery = request.getRequestURI() + "?" + query; - } - if (!uri.equals(uriQuery)) { - // Some clients (older Android) use an absolute URI for - // DIGEST but a relative URI in the request line. - // request. 2.3.5 < fixed Android version <= 4.0.3 - String host = request.getHeader("host"); - String scheme = request.getScheme(); - if (host != null && !uriQuery.startsWith(scheme)) { - StringBuilder absolute = new StringBuilder(); - absolute.append(scheme); - absolute.append("://"); - absolute.append(host); - absolute.append(uriQuery); - if (!uri.equals(absolute.toString())) { - return false; - } - } else { - return false; - } - } - } - - // Validate the Realm name - if (!contextRealmName.equals(realmName)) { - return false; - } - - // Validate the opaque string - if (!opaque.equals(opaqueReceived)) { - return false; - } - - // Validate nonce - int i = nonce.indexOf(":"); - if (i < 0 || (i + 1) == nonce.length()) { - return false; - } - long nonceTime; - try { - nonceTime = Long.parseLong(nonce.substring(0, i)); - } catch (NumberFormatException nfe) { - return false; - } - String md5clientIpTimeKey = nonce.substring(i + 1); - long currentTime = System.currentTimeMillis(); - if ((currentTime - nonceTime) > nonceValidity) { - nonceStale = true; - synchronized (nonces) { - nonces.remove(nonce); - } - } - String serverIpTimeKey = request.getRemoteAddr() + ":" + nonceTime + ":" + key; - byte[] buffer = ConcurrentMessageDigest.digestMD5(serverIpTimeKey - .getBytes(StandardCharsets.ISO_8859_1)); - String md5ServerIpTimeKey = MD5Encoder.encode(buffer); - if (!md5ServerIpTimeKey.equals(md5clientIpTimeKey)) { - return false; - } - - // Validate qop - if (qop != null && !QOP.equals(qop)) { - return false; - } - - // Validate cnonce and nc - // Check if presence of nc and Cnonce is consistent with presence of - // qop - if (qop == null) { - if (cnonce != null || nc != null) { - return false; - } - } else { - if (cnonce == null || nc == null) { - return false; - } - // RFC 2617 says nc must be 8 digits long. Older Android clients - // use 6. 2.3.5 < fixed Android version <= 4.0.3 - if (nc.length() < 6 || nc.length() > 8) { - return false; - } - long count; - try { - count = Long.parseLong(nc, 16); - } catch (NumberFormatException nfe) { - return false; - } - NonceInfo info; - synchronized (nonces) { - info = nonces.get(nonce); - } - if (info == null) { - // Nonce is valid but not in cache. It must have dropped out - // of the cache - force a re-authentication - nonceStale = true; - } else { - if (!info.nonceCountValid(count)) { - return false; - } - } - } - return true; - } - - public boolean isNonceStale() { - return nonceStale; - } - - public Principal authenticate(Realm realm) { - // Second MD5 digest used to calculate the digest : - // MD5(Method + ":" + uri) - String a2 = method + ":" + uri; - - byte[] buffer = ConcurrentMessageDigest.digestMD5(a2 - .getBytes(StandardCharsets.ISO_8859_1)); - String md5a2 = MD5Encoder.encode(buffer); - - return realm.authenticate(userName, response, nonce, nc, cnonce, qop, realmName, md5a2); - } - - } - - - private static class NonceInfo { - private final long timestamp; - private final boolean seen[]; - private final int offset; - private int count = 0; - - public NonceInfo(long currentTime, int seenWindowSize) { - this.timestamp = currentTime; - seen = new boolean[seenWindowSize]; - offset = seenWindowSize / 2; - } - - public synchronized boolean nonceCountValid(long nonceCount) { - if ((count - offset) >= nonceCount || (nonceCount > count - offset + seen.length)) { - return false; - } - int checkIndex = (int) ((nonceCount + offset) % seen.length); - if (seen[checkIndex]) { - return false; - } else { - seen[checkIndex] = true; - seen[count % seen.length] = false; - count++; - return true; - } - } - - public long getTimestamp() { - return timestamp; - } - } } Modified: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/FormAuthModule.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/FormAuthModule.java?rev=1710030&r1=1710029&r2=1710030&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/FormAuthModule.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/FormAuthModule.java Thu Oct 22 15:11:06 2015 @@ -25,6 +25,7 @@ import java.util.Locale; import java.util.Map; import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.AuthException; @@ -45,7 +46,6 @@ import org.apache.catalina.authenticator import org.apache.catalina.authenticator.SavedRequest; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; -import org.apache.catalina.realm.GenericPrincipal; import org.apache.coyote.ActionCode; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -124,7 +124,6 @@ public class FormAuthModule extends Tomc } - // TODO Extract common patterns in processing cached principal and cached credentials private AuthStatus handleSavedCredentials(Subject clientSubject, Request request, HttpServletResponse response) throws IOException, UnsupportedCallbackException { Session session = request.getSessionInternal(true); @@ -133,16 +132,20 @@ public class FormAuthModule extends Tomc } String username = (String) session.getNote(Constants.SESS_USERNAME_NOTE); - String password = (String) session.getNote(Constants.SESS_PASSWORD_NOTE); + String passwordString = (String) session.getNote(Constants.SESS_PASSWORD_NOTE); + char[] password = (passwordString != null) ? passwordString.toCharArray() : null; if (log.isDebugEnabled()) { log.debug("Reauthenticating username '" + username + "'"); } - Principal principal = realm.authenticate(username, password); - if (principal == null) { + PasswordValidationCallback passwordCallback = new PasswordValidationCallback( + clientSubject, username, password); + handler.handle(new Callback[] { passwordCallback }); + if (!passwordCallback.getResult()) { forwardToErrorPage(request, response); return AuthStatus.FAILURE; } + Principal principal = getPrincipal(passwordCallback); session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal); if (isMatchingSavedRequest(request)) { @@ -342,13 +345,6 @@ public class FormAuthModule extends Tomc } - private GenericPrincipal getPrincipal(PasswordValidationCallback passwordCallback) { - Iterator<Object> credentials = passwordCallback.getSubject().getPrivateCredentials() - .iterator(); - return (GenericPrincipal) credentials.next(); - } - - /** * Called to forward to the login page * Modified: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/SpnegoAuthModule.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/SpnegoAuthModule.java?rev=1710030&r1=1710029&r2=1710030&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/SpnegoAuthModule.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/SpnegoAuthModule.java Thu Oct 22 15:11:06 2015 @@ -19,10 +19,8 @@ package org.apache.catalina.authenticato 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.LinkedHashMap; import java.util.Map; import java.util.regex.Pattern; @@ -39,8 +37,10 @@ import javax.servlet.http.HttpServletReq import javax.servlet.http.HttpServletResponse; import org.apache.catalina.Context; -import org.apache.catalina.Realm; import org.apache.catalina.authenticator.Constants; +import org.apache.catalina.authenticator.SpnegoAuthenticator.AcceptAction; +import org.apache.catalina.authenticator.SpnegoAuthenticator.AuthenticateAction; +import org.apache.catalina.authenticator.SpnegoAuthenticator.SpnegoTokenFixer; import org.apache.catalina.connector.Request; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -317,193 +317,4 @@ public class SpnegoAuthModule extends To } - /** - * This class gets a gss credential via a privileged action. - */ - private static class AcceptAction implements PrivilegedExceptionAction<byte[]> { - - GSSContext gssContext; - - byte[] decoded; - - AcceptAction(GSSContext context, byte[] decodedToken) { - this.gssContext = context; - this.decoded = decodedToken; - } - - @Override - public byte[] run() throws GSSException { - return gssContext.acceptSecContext(decoded, - 0, decoded.length); - } - } - - private 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: - * https://bugs.openjdk.java.net/browse/JDK-8048194 - * (note: the change applied is not the one suggested in the bug report) - * <p> - * It is not clear to me if Windows, Java or Tomcat is at fault here. I - * think it is Java but I could be wrong. - * <p> - * This hack works by re-ordering the list of mechTypes in the NegTokenInit - * token. - */ - private static class SpnegoTokenFixer { - - public static void fix(byte[] token) { - SpnegoTokenFixer fixer = new SpnegoTokenFixer(token); - fixer.fix(); - } - - - private final byte[] token; - private int pos = 0; - - - private SpnegoTokenFixer(byte[] token) { - this.token = token; - } - - - // Fixes the token in-place - private void fix() { - /* - * Useful references: - * http://tools.ietf.org/html/rfc4121#page-5 - * http://tools.ietf.org/html/rfc2743#page-81 - * https://msdn.microsoft.com/en-us/library/ms995330.aspx - */ - - // Scan until we find the mech types list. If we find anything - // unexpected, abort the fix process. - if (!tag(0x60)) return; - if (!length()) return; - if (!oid("1.3.6.1.5.5.2")) return; - if (!tag(0xa0)) return; - if (!length()) return; - if (!tag(0x30)) return; - if (!length()) return; - if (!tag(0xa0)) return; - lengthAsInt(); - if (!tag(0x30)) return; - // Now at the start of the mechType list. - // Read the mechTypes into an ordered set - int mechTypesLen = lengthAsInt(); - int mechTypesStart = pos; - LinkedHashMap<String, int[]> mechTypeEntries = new LinkedHashMap<>(); - while (pos < mechTypesStart + mechTypesLen) { - int[] value = new int[2]; - value[0] = pos; - String key = oidAsString(); - value[1] = pos - value[0]; - mechTypeEntries.put(key, value); - } - // Now construct the re-ordered mechType list - byte[] replacement = new byte[mechTypesLen]; - int replacementPos = 0; - - int[] first = mechTypeEntries.remove("1.2.840.113554.1.2.2"); - if (first != null) { - System.arraycopy(token, first[0], replacement, replacementPos, first[1]); - replacementPos += first[1]; - } - for (int[] markers : mechTypeEntries.values()) { - System.arraycopy(token, markers[0], replacement, replacementPos, markers[1]); - replacementPos += markers[1]; - } - - // Finally, replace the original mechType list with the re-ordered - // one. - System.arraycopy(replacement, 0, token, mechTypesStart, mechTypesLen); - } - - - private boolean tag(int expected) { - return (token[pos++] & 0xFF) == expected; - } - - - private boolean length() { - // No need to retain the length - just need to consume it and make - // sure it is valid. - int len = lengthAsInt(); - return pos + len == token.length; - } - - - private int lengthAsInt() { - int len = token[pos++] & 0xFF; - if (len > 127) { - int bytes = len - 128; - len = 0; - for (int i = 0; i < bytes; i++) { - len = len << 8; - len = len + (token[pos++] & 0xff); - } - } - return len; - } - - - private boolean oid(String expected) { - return expected.equals(oidAsString()); - } - - - private String oidAsString() { - if (!tag(0x06)) return null; - StringBuilder result = new StringBuilder(); - int len = lengthAsInt(); - // First byte is special case - int v = token[pos++] & 0xFF; - int c2 = v % 40; - int c1 = (v - c2) / 40; - result.append(c1); - result.append('.'); - result.append(c2); - int c = 0; - boolean write = false; - for (int i = 1; i < len; i++) { - int b = token[pos++] & 0xFF; - if (b > 127) { - b -= 128; - } else { - write = true; - } - c = c << 7; - c += b; - if (write) { - result.append('.'); - result.append(c); - c = 0; - write = false; - } - } - return result.toString(); - } - } - } Modified: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/TomcatAuthModule.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/TomcatAuthModule.java?rev=1710030&r1=1710029&r2=1710030&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/TomcatAuthModule.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/provider/modules/TomcatAuthModule.java Thu Oct 22 15:11:06 2015 @@ -18,6 +18,7 @@ package org.apache.catalina.authenticato import java.io.IOException; import java.security.Principal; +import java.util.Iterator; import java.util.Map; import javax.security.auth.Subject; @@ -29,10 +30,12 @@ import javax.security.auth.message.Messa import javax.security.auth.message.MessagePolicy; import javax.security.auth.message.callback.CallerPrincipalCallback; import javax.security.auth.message.callback.GroupPrincipalCallback; +import javax.security.auth.message.callback.PasswordValidationCallback; import javax.security.auth.message.module.ServerAuthModule; import org.apache.catalina.Context; import org.apache.catalina.authenticator.jaspic.MessageInfoImpl; +import org.apache.catalina.realm.GenericPrincipal; import org.apache.tomcat.util.res.StringManager; /** @@ -123,4 +126,12 @@ public abstract class TomcatAuthModule i GroupPrincipalCallback groupCallback = new GroupPrincipalCallback(clientSubject, roles); handler.handle(new Callback[] { principalCallback, groupCallback }); } + + protected GenericPrincipal getPrincipal(PasswordValidationCallback passwordCallback) { + Iterator<Object> credentials = passwordCallback.getSubject().getPrivateCredentials() + .iterator(); + return (GenericPrincipal) credentials.next(); + } + + } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org