You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2011/02/04 18:28:38 UTC

svn commit: r1067230 - in /cxf/branches/wss4j-1.6-port/rt/ws/security/src: main/java/org/apache/cxf/ws/security/ main/java/org/apache/cxf/ws/security/wss4j/ test/java/org/apache/cxf/ws/security/wss4j/

Author: coheigea
Date: Fri Feb  4 17:28:38 2011
New Revision: 1067230

URL: http://svn.apache.org/viewvc?rev=1067230&view=rev
Log:
Some changes to UsernameToken processing following on the recent addition of Validators to WSS4J.
 - Removed the custom Processor implementations as it is no longer necessary to swap in new processors to handle custom behaviour.

Removed:
    cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenProcessorWithoutCallbacks.java
Modified:
    cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
    cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
    cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java
    cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
    cxf/branches/wss4j-1.6-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/CustomProcessor.java

Modified: cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java?rev=1067230&r1=1067229&r2=1067230&view=diff
==============================================================================
--- cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java (original)
+++ cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java Fri Feb  4 17:28:38 2011
@@ -32,6 +32,7 @@ public final class SecurityConstants {
     public static final String PASSWORD = "ws-security.password";
     public static final String VALIDATE_PASSWORD = "ws-security.validate.password";
     public static final String USERNAME_TOKEN_NO_CALLBACKS = "ws-security.ut.no-callbacks";
+    public static final String USERNAME_TOKEN_VALIDATOR = "ws-security.ut.validator";
     
     public static final String CALLBACK_HANDLER = "ws-security.callback-handler";
     

Modified: cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java?rev=1067230&r1=1067229&r2=1067230&view=diff
==============================================================================
--- cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java (original)
+++ cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java Fri Feb  4 17:28:38 2011
@@ -18,15 +18,12 @@
  */
 package org.apache.cxf.ws.security.wss4j;
 
-import java.io.IOException;
 import java.security.Principal;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.logging.Logger;
 
 import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
 import javax.xml.namespace.QName;
 
 import org.apache.cxf.binding.soap.SoapMessage;
@@ -38,13 +35,10 @@ import org.apache.cxf.interceptor.securi
 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.WSPasswordCallback;
 import org.apache.ws.security.WSSecurityEngine;
 import org.apache.ws.security.WSSecurityException;
-import org.apache.ws.security.WSUsernameTokenPrincipal;
-import org.apache.ws.security.handler.RequestData;
-import org.apache.ws.security.processor.Processor;
+import org.apache.ws.security.validate.UsernameTokenValidator;
+import org.apache.ws.security.validate.Validator;
 
 
 /**
@@ -174,83 +168,61 @@ public abstract class AbstractUsernameTo
                                     String nonce,
                                     String created) throws SecurityException;
     
-    
-    /**
-     * {@inheritDoc}
-     * 
-     */
-    @Override
-    protected CallbackHandler getCallback(RequestData reqData, int doAction, boolean utNoCallbacks) 
-        throws WSSecurityException {
-        
-        // Given that a custom UT processor is used for dealing with digests 
-        // no callback handler is required when the request UT contains a digest;
-        // however a custom callback may still be needed for decrypting the encrypted UT
-        
-        if ((doAction & WSConstants.UT) != 0) {
-            CallbackHandler pwdCallback = null;
-            try {
-                pwdCallback = super.getCallback(reqData, doAction, false);
-            } catch (Exception ex) {
-                // ignore
-            }
-            return new SubjectCreatingCallbackHandler(pwdCallback);
-        }
-        
-        return super.getCallback(reqData, doAction, false);
-    }
-    
     @Override 
     protected WSSecurityEngine getSecurityEngine(boolean utNoCallbacks) {
-        if (!supportDigestPasswords) {
-            return super.getSecurityEngine(true);
-        }
-        Map<QName, Object> profiles = new HashMap<QName, Object>(3);
+        Map<QName, Object> profiles = new HashMap<QName, Object>(1);
         
-        Processor processor = new CustomUsernameTokenProcessor();
-        profiles.put(new QName(WSConstants.WSSE_NS, WSConstants.USERNAME_TOKEN_LN), processor);
-        profiles.put(new QName(WSConstants.WSSE11_NS, WSConstants.USERNAME_TOKEN_LN), processor);
+        Validator validator = new CustomValidator();
+        profiles.put(WSSecurityEngine.USERNAME_TOKEN, validator);
         return createSecurityEngine(profiles);
     }
     
-    protected class SubjectCreatingCallbackHandler extends DelegatingCallbackHandler {
-
-        public SubjectCreatingCallbackHandler(CallbackHandler pwdHandler) {
-            super(pwdHandler);
+    protected class CustomValidator extends UsernameTokenValidator {
+        
+        @Override
+        protected void verifyCustomPassword(
+            org.apache.ws.security.message.token.UsernameToken usernameToken
+        ) throws WSSecurityException {
+            AbstractUsernameTokenAuthenticatingInterceptor.this.setSubject(
+                usernameToken.getName(), usernameToken.getPassword(), false, null, null
+            );
+        }
+        
+        @Override
+        protected void verifyPlaintextPassword(
+            org.apache.ws.security.message.token.UsernameToken usernameToken
+        ) throws WSSecurityException {
+            AbstractUsernameTokenAuthenticatingInterceptor.this.setSubject(
+                usernameToken.getName(), usernameToken.getPassword(), false, null, null
+            );
         }
         
         @Override
-        protected void handleCallback(Callback c) throws IOException {
-            if (c instanceof WSPasswordCallback) {
-                WSPasswordCallback pc = (WSPasswordCallback)c;
-                if (WSConstants.PASSWORD_TEXT.equals(pc.getPasswordType()) 
-                    && pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN) {
-                    AbstractUsernameTokenAuthenticatingInterceptor.this.setSubject(
-                        pc.getIdentifier(), pc.getPassword(), false, null, null);
-                } 
+        protected void verifyDigestPassword(
+            org.apache.ws.security.message.token.UsernameToken usernameToken
+        ) throws WSSecurityException {
+            if (!supportDigestPasswords) {
+                throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
             }
+            String user = usernameToken.getName();
+            String password = usernameToken.getPassword();
+            boolean isHashed = usernameToken.isDerivedKey();
+            String nonce = usernameToken.getNonce();
+            String createdTime = usernameToken.getCreated();
+            AbstractUsernameTokenAuthenticatingInterceptor.this.setSubject(
+                user, password, isHashed, nonce, createdTime
+            );
         }
-    }
-    
-    /**
-     * Custom UsernameTokenProcessor
-     * Unfortunately, WSS4J UsernameTokenProcessor makes it impossible to
-     * override its handleUsernameToken only. 
-     *
-     */
-    protected class CustomUsernameTokenProcessor extends UsernameTokenProcessorWithoutCallbacks {
         
         @Override
-        protected WSUsernameTokenPrincipal createPrincipal(String user, 
-                                                           String password,
-                                                           boolean isHashed,
-                                                           String nonce,
-                                                           String createdTime,
-                                                           String pwType) throws WSSecurityException {
+        protected void verifyUnknownPassword(
+            org.apache.ws.security.message.token.UsernameToken usernameToken
+        ) throws WSSecurityException {
             AbstractUsernameTokenAuthenticatingInterceptor.this.setSubject(
-                 user, password, isHashed, nonce, createdTime);
-            return super.createPrincipal(user, password, isHashed, nonce, createdTime, pwType);
+                usernameToken.getName(), null, false, null, null
+            );
         }
+        
     }
     
 }

Modified: cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java?rev=1067230&r1=1067229&r2=1067230&view=diff
==============================================================================
--- cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java (original)
+++ cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java Fri Feb  4 17:28:38 2011
@@ -20,11 +20,11 @@
 package org.apache.cxf.ws.security.wss4j;
 
 import java.security.Principal;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.Vector;
 import java.util.logging.Logger;
 
 import javax.security.auth.Subject;
@@ -66,6 +66,7 @@ import org.apache.ws.security.handler.WS
 import org.apache.ws.security.handler.WSHandlerResult;
 import org.apache.ws.security.message.WSSecUsernameToken;
 import org.apache.ws.security.processor.UsernameTokenProcessor;
+import org.apache.ws.security.validate.Validator;
 
 /**
  * 
@@ -129,12 +130,16 @@ public class UsernameTokenInterceptor ex
                 try  {
                     final WSUsernameTokenPrincipal princ = getPrincipal(child, message);
                     if (princ != null) {
-                        List<WSSecurityEngineResult>v = new Vector<WSSecurityEngineResult>();
-                        v.add(0, new WSSecurityEngineResult(WSConstants.UT, princ, null, null, null));
+                        List<WSSecurityEngineResult>v = new ArrayList<WSSecurityEngineResult>();
+                        int action = WSConstants.UT;
+                        if (princ.getPassword() == null) {
+                            action = WSConstants.UT_UNKNOWN;
+                        }
+                        v.add(0, new WSSecurityEngineResult(action, princ, null, null, null));
                         List<WSHandlerResult> results = CastUtils.cast((List<?>)message
                                                                   .get(WSHandlerConstants.RECV_RESULTS));
                         if (results == null) {
-                            results = new Vector<WSHandlerResult>();
+                            results = new ArrayList<WSHandlerResult>();
                             message.put(WSHandlerConstants.RECV_RESULTS, results);
                         }
                         WSHandlerResult rResult = new WSHandlerResult(null, v);
@@ -165,6 +170,11 @@ public class UsernameTokenInterceptor ex
         Object validateProperty = message.getContextualProperty(SecurityConstants.VALIDATE_PASSWORD);
         if (validateProperty == null || MessageUtils.isTrue(validateProperty)) {
             UsernameTokenProcessor p = new UsernameTokenProcessor();
+            Object validator = 
+                message.getContextualProperty(SecurityConstants.USERNAME_TOKEN_VALIDATOR);
+            if (validator instanceof Validator) {
+                p.setValidator((Validator)validator);
+            }
             WSDocInfo wsDocInfo = new WSDocInfo(tokenElement.getOwnerDocument());
             List<WSSecurityEngineResult> results = 
                 p.handleToken(tokenElement, null, null, getCallback(message), wsDocInfo, null);

Modified: cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java?rev=1067230&r1=1067229&r2=1067230&view=diff
==============================================================================
--- cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java (original)
+++ cxf/branches/wss4j-1.6-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java Fri Feb  4 17:28:38 2011
@@ -20,10 +20,10 @@ package org.apache.cxf.ws.security.wss4j
 
 import java.io.IOException;
 import java.security.Principal;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Vector;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -68,9 +68,10 @@ import org.apache.ws.security.handler.Re
 import org.apache.ws.security.handler.WSHandlerConstants;
 import org.apache.ws.security.handler.WSHandlerResult;
 import org.apache.ws.security.message.token.SecurityTokenReference;
-import org.apache.ws.security.message.token.Timestamp;
 import org.apache.ws.security.processor.Processor;
 import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.validate.NoOpValidator;
+import org.apache.ws.security.validate.Validator;
 
 /**
  * Performs WS-Security inbound actions.
@@ -83,6 +84,7 @@ public class WSS4JInInterceptor extends 
     public static final String SIGNATURE_RESULT = "wss4j.signature.result";
     public static final String PRINCIPAL_RESULT = "wss4j.principal.result";
     public static final String PROCESSOR_MAP = "wss4j.processor.map";
+    public static final String VALIDATOR_MAP = "wss4j.validator.map";
 
     public static final String SECURITY_PROCESSED = WSS4JInInterceptor.class.getName() + ".DONE";
     
@@ -113,10 +115,21 @@ public class WSS4JInInterceptor extends 
     public WSS4JInInterceptor(Map<String, Object> properties) {
         this();
         setProperties(properties);
-        final Map<QName, Object> map = CastUtils.cast(
+        final Map<QName, Object> processorMap = CastUtils.cast(
             (Map<?, ?>)properties.get(PROCESSOR_MAP));
-        if (map != null) {
-            secEngineOverride = createSecurityEngine(map);
+        final Map<QName, Object> validatorMap = CastUtils.cast(
+            (Map<?, ?>)properties.get(VALIDATOR_MAP));
+        
+        if (processorMap != null) {
+            if (validatorMap != null) {
+                processorMap.putAll(validatorMap);
+            }
+            secEngineOverride = createSecurityEngine(processorMap);
+        } else if (validatorMap != null) {
+            if (processorMap != null) {
+                validatorMap.putAll(processorMap);
+            }
+            secEngineOverride = createSecurityEngine(validatorMap);
         }
     }
 
@@ -192,7 +205,7 @@ public class WSS4JInInterceptor extends 
         try {
             reqData.setMsgContext(msg);
             computeAction(msg, reqData);
-            List<Integer> actions = new Vector<Integer>();
+            List<Integer> actions = new ArrayList<Integer>();
             String action = getAction(msg, version);
 
             int doAction = WSSecurityUtil.decodeAction(action, actions);
@@ -233,14 +246,14 @@ public class WSS4JInInterceptor extends 
                     checkSignatureConfirmation(reqData, wsResult);
                 }
 
-                checkSignatures(msg, reqData, wsResult);
-                checkTimestamps(msg, reqData, wsResult);
+                storeSignature(msg, reqData, wsResult);
+                storeTimestamp(msg, reqData, wsResult);
                 checkActions(msg, reqData, wsResult, actions);
                 doResults(msg, actor, doc, wsResult, utWithCallbacks);
             } else { // no security header found
-                // Create an empty result vector to pass into the required validation
+                // Create an empty result list to pass into the required validation
                 // methods.
-                wsResult = new Vector<WSSecurityEngineResult>();
+                wsResult = new ArrayList<WSSecurityEngineResult>();
                 
                 if (doc.getSOAPPart().getEnvelope().getBody().hasFault()) {
                     LOG.warning("Request does not contain Security header, " 
@@ -303,11 +316,11 @@ public class WSS4JInInterceptor extends 
         }
     }
     
-    private void checkSignatures(
+    private void storeSignature(
         SoapMessage msg, RequestData reqData, List<WSSecurityEngineResult> wsResult
     ) throws WSSecurityException {
-        // Extract the signature action result from the action vector
-        List<WSSecurityEngineResult> signatureResults = new Vector<WSSecurityEngineResult>();
+        // Extract the signature action result from the action list
+        List<WSSecurityEngineResult> signatureResults = new ArrayList<WSSecurityEngineResult>();
         signatureResults = 
             WSSecurityUtil.fetchAllActionResults(wsResult, WSConstants.SIGN, signatureResults);
 
@@ -317,32 +330,16 @@ public class WSS4JInInterceptor extends 
         }
     }
     
-    protected void checkTimestamps(
+    private void storeTimestamp(
         SoapMessage msg, RequestData reqData, List<WSSecurityEngineResult> wsResult
     ) throws WSSecurityException {
-        /*
-         * Perform further checks on the timestamp that was transmitted in
-         * the header. In the following implementation the timestamp is
-         * valid if it was created after (now-ttl), where ttl is set on
-         * server side, not by the client. Note: the method
-         * verifyTimestamp(Timestamp) allows custom implementations with
-         * other validation algorithms for subclasses.
-         */
-        // Extract the timestamp action result from the action vector
-        List<WSSecurityEngineResult> timestampResults = new Vector<WSSecurityEngineResult>();
+        // Extract the timestamp action result from the action list
+        List<WSSecurityEngineResult> timestampResults = new ArrayList<WSSecurityEngineResult>();
         timestampResults = 
             WSSecurityUtil.fetchAllActionResults(wsResult, WSConstants.TS, timestampResults);
 
         if (!timestampResults.isEmpty()) {
-            for (WSSecurityEngineResult result : timestampResults) {
-                Timestamp timestamp = (Timestamp)result.get(WSSecurityEngineResult.TAG_TIMESTAMP);
-
-                if (timestamp != null && !verifyTimestamp(timestamp, decodeTimeToLive(reqData))) {
-                    LOG.warning("The timestamp could not be validated");
-                    throw new WSSecurityException(WSSecurityException.MESSAGE_EXPIRED);
-                }
-                msg.put(TIMESTAMP_RESULT, result);
-            }
+            msg.put(TIMESTAMP_RESULT, timestampResults.get(timestampResults.size() - 1));
         }
     }
     
@@ -373,7 +370,7 @@ public class WSS4JInInterceptor extends 
          */
         List<WSHandlerResult> results = CastUtils.cast((List<?>)msg.get(WSHandlerConstants.RECV_RESULTS));
         if (results == null) {
-            results = new Vector<WSHandlerResult>();
+            results = new ArrayList<WSHandlerResult>();
             msg.put(WSHandlerConstants.RECV_RESULTS, results);
         }
         WSHandlerResult rResult = new WSHandlerResult(actor, wsResult);
@@ -479,7 +476,8 @@ public class WSS4JInInterceptor extends 
 
     protected CallbackHandler getCallback(RequestData reqData, int doAction, boolean utWithCallbacks) 
         throws WSSecurityException {
-        if (!utWithCallbacks && (doAction & WSConstants.UT) != 0) {
+        if (!utWithCallbacks 
+            && ((doAction & WSConstants.UT) != 0 || (doAction & WSConstants.UT_UNKNOWN) != 0)) {
             CallbackHandler pwdCallback = null;
             try {
                 pwdCallback = getCallback(reqData, doAction);
@@ -553,10 +551,9 @@ public class WSS4JInInterceptor extends 
         }
         
         if (!utWithCallbacks) {
-            Map<QName, Object> profiles = new HashMap<QName, Object>(3);
-            Processor processor = new UsernameTokenProcessorWithoutCallbacks();
-            profiles.put(new QName(WSConstants.WSSE_NS, WSConstants.USERNAME_TOKEN_LN), processor);
-            profiles.put(new QName(WSConstants.WSSE11_NS, WSConstants.USERNAME_TOKEN_LN), processor);
+            Map<QName, Object> profiles = new HashMap<QName, Object>(1);
+            Validator validator = new NoOpValidator();
+            profiles.put(WSSecurityEngine.USERNAME_TOKEN, validator);
             return createSecurityEngine(profiles);
         }
         
@@ -581,6 +578,8 @@ public class WSS4JInInterceptor extends 
                 config.setProcessor(key, (Class<?>)val);
             } else if (val instanceof Processor) {
                 config.setProcessor(key, (Processor)val);
+            } else if (val instanceof Validator) {
+                config.setValidator(key, (Validator)val);
             } else if (val == null) {
                 config.setProcessor(key, (Class<?>)val);
             }

Modified: cxf/branches/wss4j-1.6-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/CustomProcessor.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j-1.6-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/CustomProcessor.java?rev=1067230&r1=1067229&r2=1067230&view=diff
==============================================================================
--- cxf/branches/wss4j-1.6-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/CustomProcessor.java (original)
+++ cxf/branches/wss4j-1.6-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/CustomProcessor.java Fri Feb  4 17:28:38 2011
@@ -26,6 +26,7 @@ import org.apache.ws.security.WSSecurity
 import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.message.token.SecurityContextToken;
 import org.apache.ws.security.processor.Processor;
+import org.apache.ws.security.validate.Validator;
 
 /**
  * a custom processor that inserts itself into the results vector
@@ -49,5 +50,9 @@ public class CustomProcessor implements 
         result.put("foo", this);
         return java.util.Collections.singletonList(result);
     }
+    
+    public void setValidator(Validator validator) {
+        //
+    }
 
 }