Return-Path: Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: (qmail 35147 invoked from network); 12 Apr 2010 17:20:34 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 12 Apr 2010 17:20:34 -0000 Received: (qmail 73585 invoked by uid 500); 12 Apr 2010 17:20:34 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 73521 invoked by uid 500); 12 Apr 2010 17:20:34 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 73514 invoked by uid 99); 12 Apr 2010 17:20:34 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 12 Apr 2010 17:20:34 +0000 X-ASF-Spam-Status: No, hits=-1261.8 required=10.0 tests=ALL_TRUSTED,AWL X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 12 Apr 2010 17:20:32 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 7929823889BB; Mon, 12 Apr 2010 17:20:12 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r933329 - in /cxf/branches/2.2.x-fixes: ./ common/common/src/main/java/org/apache/cxf/common/security/ common/common/src/test/java/org/apache/cxf/common/security/ rt/core/src/main/java/org/apache/cxf/interceptor/security/ rt/core/src/test/j... Date: Mon, 12 Apr 2010 17:20:12 -0000 To: commits@cxf.apache.org From: sergeyb@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100412172012.7929823889BB@eris.apache.org> Author: sergeyb Date: Mon Apr 12 17:20:11 2010 New Revision: 933329 URL: http://svn.apache.org/viewvc?rev=933329&view=rev Log: Merged revisions 933326 via svnmerge from https://svn.apache.org/repos/asf/cxf/trunk ........ r933326 | sergeyb | 2010-04-12 18:07:19 +0100 (Mon, 12 Apr 2010) | 1 line CXF-2754,CXF-2755: some refactoring, adding unit tests ........ Added: cxf/branches/2.2.x-fixes/common/common/src/main/java/org/apache/cxf/common/security/ - copied from r933326, cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/ cxf/branches/2.2.x-fixes/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java - copied unchanged from r933326, cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java cxf/branches/2.2.x-fixes/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java - copied unchanged from r933326, cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java cxf/branches/2.2.x-fixes/common/common/src/test/java/org/apache/cxf/common/security/ - copied from r933326, cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/ cxf/branches/2.2.x-fixes/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java - copied unchanged from r933326, cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java cxf/branches/2.2.x-fixes/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java - copied unchanged from r933326, cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java cxf/branches/2.2.x-fixes/rt/core/src/test/java/org/apache/cxf/interceptor/security/ - copied from r933326, cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/ cxf/branches/2.2.x-fixes/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java - copied unchanged from r933326, cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java - copied unchanged from r933326, cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java - copied unchanged from r933326, cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java Modified: cxf/branches/2.2.x-fixes/ (props changed) cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java Propchange: cxf/branches/2.2.x-fixes/ ------------------------------------------------------------------------------ svn:mergeinfo = /cxf/trunk:933326 Propchange: cxf/branches/2.2.x-fixes/ ------------------------------------------------------------------------------ Binary property 'svnmerge-integrated' - no diff available. Modified: cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff ============================================================================== --- cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java (original) +++ cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java Mon Apr 12 17:20:11 2010 @@ -19,6 +19,7 @@ package org.apache.cxf.interceptor.security; import java.lang.reflect.Method; +import java.util.Collections; import java.util.List; import org.apache.cxf.frontend.MethodDispatcher; @@ -32,6 +33,9 @@ import org.apache.cxf.service.model.Bind public abstract class AbstractAuthorizingInInterceptor extends AbstractPhaseInterceptor { + private static final String ALL_ROLES = "*"; + + public AbstractAuthorizingInInterceptor() { super(Phase.PRE_INVOKE); } @@ -44,17 +48,10 @@ public abstract class AbstractAuthorizin Method method = getTargetMethod(message); - List expectedRoles = getExpectedRoles(method); - if (expectedRoles == null || expectedRoles.isEmpty()) { + if (authorize(sc, method)) { return; } - for (String role : expectedRoles) { - if (sc.isUserInRole(role)) { - return; - } - } - throw new AccessDeniedException("Unauthorized"); } @@ -65,5 +62,50 @@ public abstract class AbstractAuthorizin return md.getMethod(bop); } + protected boolean authorize(SecurityContext sc, Method method) { + List expectedRoles = getExpectedRoles(method); + if (expectedRoles.isEmpty()) { + + List denyRoles = getDenyRoles(method); + + return denyRoles.isEmpty() ? true : isUserInRole(sc, denyRoles, true); + } + + if (isUserInRole(sc, expectedRoles, false)) { + return true; + } + + return false; + } + + private boolean isUserInRole(SecurityContext sc, List roles, boolean deny) { + + if (roles.size() == 1 && ALL_ROLES.equals(roles.get(0))) { + return !deny; + } + + for (String role : roles) { + if (sc.isUserInRole(role)) { + return !deny; + } + } + return deny; + } + + /** + * Returns a list of expected roles for a given method. + * @param method Method + * @return list, empty if no roles are available + */ protected abstract List getExpectedRoles(Method method); + + + /** + * Returns a list of roles to be denied for a given method. + * @param method Method + * @return list, empty if no roles are available + */ + protected List getDenyRoles(Method method) { + return Collections.emptyList(); + } } Modified: cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff ============================================================================== --- cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java (original) +++ cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java Mon Apr 12 17:20:11 2010 @@ -19,23 +19,24 @@ package org.apache.cxf.interceptor.security; import java.lang.reflect.Method; +import java.util.Collections; import java.util.List; import java.util.Map; public class SimpleAuthorizingInterceptor extends AbstractAuthorizingInInterceptor { - private Map> methodRolesMap; - private Map> classRolesMap; + private Map> methodRolesMap = Collections.emptyMap(); + private List globalRoles = Collections.emptyList(); @Override protected List getExpectedRoles(Method method) { List roles = methodRolesMap.get(method.getName()); - if (roles != null || classRolesMap == null) { + if (roles != null) { return roles; } - return methodRolesMap.get(method.getDeclaringClass().getName()); + return globalRoles; } @@ -44,8 +45,8 @@ public class SimpleAuthorizingIntercepto this.methodRolesMap = rolesMap; } - public void setClassRolesMap(Map> rolesMap) { - this.classRolesMap = rolesMap; + public void setGlobalRoles(List roles) { + globalRoles = roles; } Modified: cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff ============================================================================== --- cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java (original) +++ cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java Mon Apr 12 17:20:11 2010 @@ -20,8 +20,6 @@ package org.apache.cxf.ws.security.wss4j import java.io.IOException; import java.security.Principal; -import java.security.acl.Group; -import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Vector; @@ -36,9 +34,9 @@ import javax.xml.namespace.QName; import org.w3c.dom.Element; -import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.message.Message; +import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.security.SecurityContext; import org.apache.ws.security.WSConstants; import org.apache.ws.security.WSDocInfo; @@ -77,7 +75,6 @@ public abstract class AbstractWSS4JSecur private static final Logger LOG = LogUtils.getL7dLogger(AbstractWSS4JSecurityContextProvidingInterceptor.class); - private ThreadLocal messages = new ThreadLocal(); private boolean supportDigestPasswords; public AbstractWSS4JSecurityContextProvidingInterceptor() { @@ -92,48 +89,48 @@ public abstract class AbstractWSS4JSecur supportDigestPasswords = support; } - @Override - public void handleFault(SoapMessage m) { - messages.remove(); - super.handleFault(m); - } + @Override protected SecurityContext createSecurityContext(final Principal p) { - Message msg = messages.get(); + Message msg = PhaseInterceptorChain.getCurrentMessage(); if (msg == null) { throw new IllegalStateException("Current message is not available"); } - messages.remove(); - final Subject subject = msg.get(Subject.class); - return new SecurityContext() { - public Principal getUserPrincipal() { - return p; - } - public boolean isUserInRole(String role) { - if (subject == null || subject.getPrincipals().size() <= 1) { - return false; - } - for (Principal p : subject.getPrincipals()) { - if (p instanceof Group && ((Group)p).getName().equals(role)) { - return true; - } - } - return false; - } - }; + return doCreateSecurityContext(p, msg.get(Subject.class)); + } + + /** + * Creates default SecurityContext which implements isUserInRole using the + * following approach : skip the first Subject principal, and then check optional + * Groups the principal is a member of. Subclasses can override this method and implement + * a custom strategy instead + * + * @param p principal + * @param subject subject + * @return security context + */ + protected SecurityContext doCreateSecurityContext(final Principal p, final Subject subject) { + return new DefaultSecurityContext(p, subject); } + protected void setSubject(String name, String password, boolean isDigest, String nonce, String created) throws WSSecurityException { - Message msg = messages.get(); + Message msg = PhaseInterceptorChain.getCurrentMessage(); if (msg == null) { throw new IllegalStateException("Current message is not available"); } - Subject subject = createSubject(name, password, isDigest, nonce, created); + Subject subject = null; + try { + subject = createSubject(name, password, isDigest, nonce, created); + } catch (Exception ex) { + throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION, + "Subject has not been created", null, ex); + } if (subject == null || subject.getPrincipals().size() == 0 || !subject.getPrincipals().iterator().next().getName().equals(name)) { throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION, null, null); @@ -144,20 +141,21 @@ public abstract class AbstractWSS4JSecur /** * Create a Subject representing a current user and its roles. * This Subject is expected to contain at least one Principal representing a user - * and optionally followed by one or more principal Groups this user is a member of. + * and optionally followed by one or more principal Groups this user is a member of. + * It will also be available in doCreateSecurityContext. * @param name username * @param password password * @param isDigest true if a password digest is used * @param nonce optional nonce * @param created optional timestamp * @return subject - * @throws WSSecurityException + * @throws SecurityException */ protected abstract Subject createSubject(String name, String password, boolean isDigest, String nonce, - String created) throws WSSecurityException; + String created) throws SecurityException; /** @@ -168,20 +166,16 @@ public abstract class AbstractWSS4JSecur protected CallbackHandler getCallback(RequestData reqData, int doAction) throws WSSecurityException { - if ((doAction & WSConstants.UT) != 0) { - messages.set((Message)reqData.getMsgContext()); - if (!supportDigestPasswords) { - CallbackHandler pwdCallback = null; - try { - pwdCallback = super.getCallback(reqData, doAction); - } catch (Exception ex) { - // ignore - } - return new DelegatingCallbackHandler(pwdCallback); + if ((doAction & WSConstants.UT) != 0 && !supportDigestPasswords) { + CallbackHandler pwdCallback = null; + try { + pwdCallback = super.getCallback(reqData, doAction); + } catch (Exception ex) { + // ignore } + return new DelegatingCallbackHandler(pwdCallback); } - return super.getCallback(reqData, doAction); } @@ -294,51 +288,4 @@ public abstract class AbstractWSS4JSecur } } - /** - * Simple Principal implementation - * - */ - protected static class SimplePrincipal implements Principal { - - private String name; - - public SimplePrincipal(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - } - - /** - * Simple Group implementation - * - */ - protected static class SimpleGroup extends SimplePrincipal implements Group { - - private String memberName; - - public SimpleGroup(String roleName, String memberName) { - super(roleName); - this.memberName = memberName; - } - - public boolean isMember(Principal p) { - return memberName.equals(p.getName()); - } - - public boolean addMember(Principal p) { - throw new UnsupportedOperationException(); - } - - public Enumeration members() { - throw new UnsupportedOperationException(); - } - - public boolean removeMember(Principal arg0) { - throw new UnsupportedOperationException(); - } - } } Modified: cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff ============================================================================== --- cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java (original) +++ cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java Mon Apr 12 17:20:11 2010 @@ -20,7 +20,8 @@ package org.apache.cxf.ws.security.wss4j import javax.security.auth.Subject; -import org.apache.ws.security.WSSecurityException; +import org.apache.cxf.common.security.SimpleGroup; +import org.apache.cxf.common.security.SimplePrincipal; public class SimpleSubjectCreatingInterceptor extends AbstractWSS4JSecurityContextProvidingInterceptor { @@ -29,7 +30,7 @@ public class SimpleSubjectCreatingInterc String password, boolean isDigest, String nonce, - String created) throws WSSecurityException { + String created) throws SecurityException { Subject subject = new Subject(); // delegate to the external security system if possible