Author: markt Date: Mon Jun 15 22:11:10 2015 New Revision: 1685678 URL: http://svn.apache.org/r1685678 Log: Implemented very basic JASPIC support with ability to register providers Patch by fjodorver
Added: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicCallbackHandler.java (with props) tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java (with props) tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PrincipalGroupCallback.java (with props) Modified: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicAuthenticator.java Modified: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicAuthenticator.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicAuthenticator.java?rev=1685678&r1=1685677&r2=1685678&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicAuthenticator.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicAuthenticator.java Mon Jun 15 22:11:10 2015 @@ -17,38 +17,120 @@ package org.apache.catalina.authenticator.jaspic; import java.io.IOException; +import java.security.Principal; +import java.util.Map; +import javax.security.auth.Subject; +import javax.security.auth.message.AuthException; +import javax.security.auth.message.AuthStatus; +import javax.security.auth.message.MessageInfo; +import javax.security.auth.message.config.AuthConfigFactory; +import javax.security.auth.message.config.AuthConfigProvider; +import javax.security.auth.message.config.ServerAuthConfig; +import javax.security.auth.message.config.ServerAuthContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; -import org.apache.catalina.Authenticator; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.authenticator.AuthenticatorBase; import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.catalina.valves.ValveBase; + import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; -public class JaspicAuthenticator extends ValveBase implements Authenticator { +public class JaspicAuthenticator extends AuthenticatorBase { private static final Log log = LogFactory.getLog(JaspicAuthenticator.class); + private static final String AUTH_TYPE = "JASPIC"; + private static final String MESSAGE_LAYER = "HttpServlet"; + + private JaspicCallbackHandler callbackHandler; + private Subject serviceSubject; + + @SuppressWarnings("rawtypes") + private Map authProperties = null; + + + @Override + protected synchronized void startInternal() throws LifecycleException { + super.startInternal(); + callbackHandler = new JaspicCallbackHandler(container.getRealm()); + serviceSubject = new Subject(); + } + + @Override public boolean authenticate(Request request, HttpServletResponse response) throws IOException { - return true; + MessageInfo messageInfo = new MessageInfoImpl(request, response, true); + AuthConfigFactory factory = AuthConfigFactory.getFactory(); + String appContext = request.getLocalName() + " " + request.getContextPath(); + + AuthConfigProvider configProvider = + factory.getConfigProvider(MESSAGE_LAYER, appContext, null); + ServerAuthConfig authConfig = getAuthConfig(appContext, configProvider); + String authContextId = authConfig.getAuthContextID(messageInfo); + + ServerAuthContext authContext = null; + authContext = getAuthContext(authConfig, authContextId, authProperties, authContext); + AuthStatus authStatus = validateRequest(messageInfo, authContext); + + if (authStatus == AuthStatus.SUCCESS) { + Principal principal = callbackHandler.getPrincipal(); + if (principal != null) { + register(request, response, principal, AUTH_TYPE, null, null); + } + return true; + } + + return false; + } + + + private AuthStatus validateRequest(MessageInfo messageInfo, ServerAuthContext authContext) { + Subject clientSubject = new Subject(); + try { + return authContext.validateRequest(messageInfo, clientSubject, serviceSubject); + } catch (AuthException e) { + throw new IllegalStateException(e); + } + } + + + @SuppressWarnings("rawtypes") + private ServerAuthContext getAuthContext(ServerAuthConfig authConfig, String authContextId, + Map authProperties, ServerAuthContext authContext) { + try { + return authConfig.getAuthContext(authContextId, serviceSubject, authProperties); + } catch (AuthException e) { + throw new IllegalStateException(e); + } } + @Override public void login(String userName, String password, Request request) throws ServletException { - + throw new IllegalStateException("not implemented yet!"); } + @Override public void logout(Request request) { + throw new IllegalStateException("not implemented yet!"); + } + + private ServerAuthConfig getAuthConfig(String appContext, AuthConfigProvider configProvider) { + try { + return configProvider.getServerAuthConfig(MESSAGE_LAYER, appContext, callbackHandler); + } catch (AuthException e) { + throw new IllegalStateException(e); + } } + @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - getNext().invoke(request, response); + protected String getAuthMethod() { + return AUTH_TYPE; } } Added: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicCallbackHandler.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicCallbackHandler.java?rev=1685678&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicCallbackHandler.java (added) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicCallbackHandler.java Mon Jun 15 22:11:10 2015 @@ -0,0 +1,76 @@ +/* + * 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.authenticator.jaspic; + +import java.io.IOException; +import java.security.Principal; +import java.util.Collections; + +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.callback.CallerPrincipalCallback; +import javax.security.auth.message.callback.GroupPrincipalCallback; +import javax.security.auth.message.callback.PasswordValidationCallback; + +import org.apache.catalina.Realm; +import org.apache.catalina.realm.GenericPrincipal; + +public class JaspicCallbackHandler implements CallbackHandler { + + private Realm realm; + + private ThreadLocal<PrincipalGroupCallback> principalGroupCallback = new ThreadLocal<>(); + + public JaspicCallbackHandler(Realm realm) { + this.realm = realm; + } + + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + principalGroupCallback.set(new PrincipalGroupCallback()); + for (Callback callback : callbacks) { + handleCallback(callback); + } + } + + public Principal getPrincipal() { + return principalGroupCallback.get().getPrincipal(); + } + + private void handleCallback(Callback callback) { + if (callback instanceof CallerPrincipalCallback) { + principalGroupCallback.get().addCallback(callback); + } else if (callback instanceof GroupPrincipalCallback) { + principalGroupCallback.get().addCallback(callback); + } else if (callback instanceof PasswordValidationCallback) { + handlePasswordValidationCallback((PasswordValidationCallback) callback); + } else { + throw new IllegalStateException("Unknown callback!"); + } + } + + private void handlePasswordValidationCallback( + PasswordValidationCallback passwordValidationCallback) { + Subject subject = passwordValidationCallback.getSubject(); + + passwordValidationCallback.setResult(true); + subject.getPrincipals().add( + new GenericPrincipal("user", "password", Collections.singletonList("user"))); + } +} Propchange: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/JaspicCallbackHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java?rev=1685678&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java (added) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java Mon Jun 15 22:11:10 2015 @@ -0,0 +1,78 @@ +/* + * 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.authenticator.jaspic; + +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.message.MessageInfo; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.catalina.connector.Request; + +public class MessageInfoImpl implements MessageInfo { + private static final String IS_MANDATORY = "javax.security.auth.message.MessagePolicy.isMandatory"; + + private final Map<String, Object> map = new HashMap<>(); + private HttpServletRequest request; + private HttpServletResponse response; + + public MessageInfoImpl() { + } + + public MessageInfoImpl(Request request, HttpServletResponse response, boolean authMandatory) { + this.request = request; + this.response = response; + map.put(IS_MANDATORY, Boolean.toString(authMandatory)); + } + + @Override + @SuppressWarnings("rawtypes") + // JASPIC uses raw types + public Map getMap() { + return map; + } + + @Override + public Object getRequestMessage() { + return request; + } + + @Override + public Object getResponseMessage() { + return response; + } + + @Override + public void setRequestMessage(Object request) { + if (!(request instanceof HttpServletRequest)) { + throw new IllegalArgumentException("Request is not a servlet request but " + + request.getClass().getName()); + } + this.request = (HttpServletRequest) request; + } + + @Override + public void setResponseMessage(Object response) { + if (!(response instanceof HttpServletResponse)) { + throw new IllegalArgumentException("response is not a servlet response but " + + response.getClass().getName()); + } + this.response = (HttpServletResponse) response; + } +} \ No newline at end of file Propchange: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/MessageInfoImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PrincipalGroupCallback.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PrincipalGroupCallback.java?rev=1685678&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PrincipalGroupCallback.java (added) +++ tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PrincipalGroupCallback.java Mon Jun 15 22:11:10 2015 @@ -0,0 +1,82 @@ +/* + * 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.authenticator.jaspic; + +import java.security.Principal; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.security.auth.callback.Callback; +import javax.security.auth.message.callback.CallerPrincipalCallback; +import javax.security.auth.message.callback.GroupPrincipalCallback; + +import org.apache.catalina.realm.GenericPrincipal; + +public class PrincipalGroupCallback { + private CallerPrincipalCallback callerPrincipalCallback; + private GroupPrincipalCallback groupPrincipalCallback; + + public void addCallback(Callback callback) { + if (callback instanceof CallerPrincipalCallback) { + callerPrincipalCallback = (CallerPrincipalCallback) callback; + } + if (callback instanceof GroupPrincipalCallback) { + groupPrincipalCallback = (GroupPrincipalCallback) callback; + } + } + + public Principal getPrincipal() { + if (callerPrincipalCallback != null) { + } + Principal userPrincipal = getUserPrincipal(); + return new GenericPrincipal(getUserName(), null, getRoles(), userPrincipal); + } + + private Principal getUserPrincipal() { + if (callerPrincipalCallback == null) { + return null; + } + return callerPrincipalCallback.getPrincipal(); + } + + private List<String> getRoles() { + if (groupPrincipalCallback == null) { + return Collections.emptyList(); + } + return Arrays.asList(groupPrincipalCallback.getGroups()); + } + + private String getUserName() { + String name = null; + if (callerPrincipalCallback != null) { + name = callerPrincipalCallback.getName(); + } + if (name != null) { + return name; + } + return getUserPrincipalName(); + } + + private String getUserPrincipalName() { + Principal principal = getUserPrincipal(); + if (principal == null) { + return null; + } + return principal.getName(); + } +} Propchange: tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/PrincipalGroupCallback.java ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org