You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2013/04/26 14:31:57 UTC

svn commit: r1476169 - in /webservices/wss4j/trunk/ws-security-stax/src: main/java/org/apache/wss4j/stax/ main/java/org/apache/wss4j/stax/ext/ main/java/org/apache/wss4j/stax/impl/processor/output/ test/java/org/apache/wss4j/stax/test/

Author: coheigea
Date: Fri Apr 26 12:31:56 2013
New Revision: 1476169

URL: http://svn.apache.org/r1476169
Log:
Finished with the ConfigurationConverter + wrote some unit tests for it

Added:
    webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/ConfigurationConverterTest.java
Modified:
    webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ConfigurationConverter.java
    webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSConstants.java
    webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSCrypto.java
    webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
    webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ConfigurationConverter.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ConfigurationConverter.java?rev=1476169&r1=1476168&r2=1476169&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ConfigurationConverter.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ConfigurationConverter.java Fri Apr 26 12:31:56 2013
@@ -21,10 +21,16 @@ package org.apache.wss4j.stax;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 
+import javax.security.auth.callback.CallbackHandler;
 import javax.xml.namespace.QName;
 
 import org.apache.wss4j.common.ConfigurationConstants;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.util.Loader;
 import org.apache.wss4j.common.util.StringUtil;
 import org.apache.wss4j.stax.ext.WSSConstants;
 import org.apache.wss4j.stax.ext.WSSConstants.UsernameTokenPasswordType;
@@ -38,6 +44,9 @@ import org.apache.xml.security.stax.ext.
  */
 public final class ConfigurationConverter {
     
+    private static org.slf4j.Logger log = 
+        org.slf4j.LoggerFactory.getLogger(ConfigurationConverter.class);
+                                          
     private ConfigurationConverter() {
         // complete
     }
@@ -51,7 +60,8 @@ public final class ConfigurationConverte
         
         parseActions(config, properties);
         parseUserProperties(config, properties);
-        // parseCallbackCrypto(config, properties);
+        parseCrypto(config, properties);
+        parseCallback(config, properties);
         parseBooleanProperties(config, properties);
         parseNonBooleanProperties(config, properties);
         
@@ -105,32 +115,174 @@ public final class ConfigurationConverte
         properties.setActor(actor);
         
         String encUser = getString(ConfigurationConstants.ENCRYPTION_USER, config);
+        if (encUser == null) {
+            encUser = user;
+        }
         properties.setEncryptionUser(encUser);
         if (ConfigurationConstants.USE_REQ_SIG_CERT.equals(encUser)) {
             properties.setUseReqSigCertForEncryption(true);
         }
         
         String sigUser = getString(ConfigurationConstants.SIGNATURE_USER, config);
+        if (sigUser == null) {
+            sigUser = user;
+        }
         properties.setSignatureUser(sigUser);
     }
     
-    // TODO
-    /*
-    private static void parseCallbackCrypto(
+    private static void parseCrypto(
         Map<String, Object> config, 
         WSSSecurityProperties properties
     ) {
-        String sigPropRef = getString(ConfigurationConstants.SIG_PROP_REF_ID, config);
-        if (sigPropRef != null) {
-            
+        Object sigPropRef = config.get(ConfigurationConstants.SIG_PROP_REF_ID);
+        if (sigPropRef instanceof Crypto) {
+            properties.setSignatureCrypto((Crypto)sigPropRef);
+        } else if (sigPropRef instanceof Properties) {
+            properties.setSignatureCryptoProperties((Properties)sigPropRef);
+        } else {
+            String sigPropFile = getString(ConfigurationConstants.SIG_PROP_FILE, config);
+            if (sigPropFile != null) {
+                try {
+                    Properties sigProperties = 
+                        CryptoFactory.getProperties(sigPropFile, getClassLoader());
+                    properties.setSignatureCryptoProperties(sigProperties);
+                } catch (WSSecurityException e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+        }
+        
+        Object sigVerPropRef = config.get(ConfigurationConstants.SIG_VER_PROP_REF_ID);
+        if (sigVerPropRef instanceof Crypto) {
+            properties.setSignatureVerificationCrypto((Crypto)sigVerPropRef);
+        } else if (sigVerPropRef instanceof Properties) {
+            properties.setSignatureVerificationCryptoProperties((Properties)sigVerPropRef);
+        } else {
+            String sigPropFile = getString(ConfigurationConstants.SIG_VER_PROP_FILE, config);
+            if (sigPropFile != null) {
+                try {
+                    Properties sigProperties = 
+                        CryptoFactory.getProperties(sigPropFile, getClassLoader());
+                    properties.setSignatureVerificationCryptoProperties(sigProperties);
+                } catch (WSSecurityException e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
         }
         
-        String sigPropFile = getString(ConfigurationConstants.SIG_PROP_FILE, config);
-        if (sigPropFile != null) {
-            
+        Object encPropRef = config.get(ConfigurationConstants.ENC_PROP_REF_ID);
+        if (encPropRef instanceof Crypto) {
+            properties.setEncryptionCrypto((Crypto)encPropRef);
+        } else if (encPropRef instanceof Properties) {
+            properties.setEncryptionCryptoProperties((Properties)encPropRef);
+        } else {
+            String encPropFile = getString(ConfigurationConstants.ENC_PROP_FILE, config);
+            if (encPropFile != null) {
+                try {
+                    Properties encProperties = 
+                        CryptoFactory.getProperties(encPropFile, getClassLoader());
+                    properties.setEncryptionCryptoProperties(encProperties);
+                } catch (WSSecurityException e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+        }
+        
+        Object decPropRef = config.get(ConfigurationConstants.DEC_PROP_REF_ID);
+        if (decPropRef instanceof Crypto) {
+            properties.setDecryptionCrypto((Crypto)decPropRef);
+        } else if (encPropRef instanceof Properties) {
+            properties.setDecryptionCryptoProperties((Properties)decPropRef);
+        } else {
+            String encPropFile = getString(ConfigurationConstants.DEC_PROP_FILE, config);
+            if (encPropFile != null) {
+                try {
+                    Properties encProperties = 
+                        CryptoFactory.getProperties(encPropFile, getClassLoader());
+                    properties.setDecryptionCryptoProperties(encProperties);
+                } catch (WSSecurityException e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+        }
+    }
+    
+    private static void parseCallback(
+        Map<String, Object> config, 
+        WSSSecurityProperties properties
+    ) {
+        Object pwPropRef = config.get(ConfigurationConstants.PW_CALLBACK_REF);
+        if (pwPropRef instanceof CallbackHandler) {
+            properties.setCallbackHandler((CallbackHandler)pwPropRef);
+        } else {
+            String pwCallback = getString(ConfigurationConstants.PW_CALLBACK_CLASS, config);
+            if (pwCallback != null) {
+                try {
+                    CallbackHandler pwCallbackHandler = loadCallbackHandler(pwCallback);
+                    properties.setCallbackHandler(pwCallbackHandler);
+                } catch (WSSecurityException e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+        }
+        
+        Object samlPropRef = config.get(ConfigurationConstants.SAML_CALLBACK_REF);
+        if (samlPropRef instanceof CallbackHandler) {
+            properties.setSamlCallbackHandler((CallbackHandler)samlPropRef);
+        } else {
+            String samlCallback = getString(ConfigurationConstants.SAML_CALLBACK_CLASS, config);
+            if (samlCallback != null) {
+                try {
+                    CallbackHandler samlCallbackHandler = loadCallbackHandler(samlCallback);
+                    properties.setSamlCallbackHandler(samlCallbackHandler);
+                } catch (WSSecurityException e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+        }
+    }
+    
+    /**
+     * Load a CallbackHandler instance.
+     * @param callbackHandlerClass The class name of the CallbackHandler instance
+     * @return a CallbackHandler instance
+     * @throws WSSecurityException
+     */
+    private static CallbackHandler loadCallbackHandler(
+        String callbackHandlerClass
+    ) throws WSSecurityException {
+
+        Class<? extends CallbackHandler> cbClass = null;
+        CallbackHandler cbHandler = null;
+        try {
+            cbClass = 
+                Loader.loadClass(getClassLoader(), 
+                                 callbackHandlerClass,
+                                 CallbackHandler.class);
+        } catch (ClassNotFoundException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
+                    "empty", e,
+                    "WSHandler: cannot load callback handler class: " + callbackHandlerClass
+            );
+        }
+        try {
+            cbHandler = cbClass.newInstance();
+        } catch (Exception e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
+                    "empty", e,
+                    "WSHandler: cannot create instance of callback handler: " + callbackHandlerClass
+            );
+        }
+        return cbHandler;
+    }
+    
+    private static ClassLoader getClassLoader() {
+        try {
+            return Loader.getTCL();
+        } catch (Exception ex) {
+            return null;
         }
     }
-    */
     
     private static void parseBooleanProperties(
         Map<String, Object> config, 
@@ -139,7 +291,11 @@ public final class ConfigurationConverte
         boolean sigConf = 
             decodeBooleanConfigValue(ConfigurationConstants.ENABLE_SIGNATURE_CONFIRMATION, false, config);
         properties.setEnableSignatureConfirmation(sigConf);
-        // TODO verification as well?
+        properties.setEnableSignatureConfirmationVerification(sigConf);
+        
+        boolean mustUnderstand = 
+            decodeBooleanConfigValue(ConfigurationConstants.MUST_UNDERSTAND, true, config);
+        properties.setMustUnderstand(mustUnderstand);
         
         boolean bspCompliant = 
             decodeBooleanConfigValue(ConfigurationConstants.IS_BSP_COMPLIANT, true, config);
@@ -219,8 +375,7 @@ public final class ConfigurationConverte
         String sigParts = getString(ConfigurationConstants.SIGNATURE_PARTS, config);
         if (sigParts != null) {
             List<SecurePart> parts = new ArrayList<SecurePart>();
-            // TODO Soap NS
-            splitEncParts(sigParts, parts, "http://schemas.xmlsoap.org/soap/envelope/");
+            splitEncParts(sigParts, parts, WSSConstants.NS_SOAP11);
             for (SecurePart part : parts) {
                 properties.addSignaturePart(part);
             }
@@ -242,8 +397,7 @@ public final class ConfigurationConverte
         String encParts = getString(ConfigurationConstants.ENCRYPTION_PARTS, config);
         if (encParts != null) {
             List<SecurePart> parts = new ArrayList<SecurePart>();
-            // TODO Soap NS
-            splitEncParts(encParts, parts, "http://schemas.xmlsoap.org/soap/envelope/");
+            splitEncParts(encParts, parts, WSSConstants.NS_SOAP11);
             for (SecurePart part : parts) {
                 properties.addEncryptionPart(part);
             }

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSConstants.java?rev=1476169&r1=1476168&r2=1476169&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSConstants.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSConstants.java Fri Apr 26 12:31:56 2013
@@ -140,11 +140,13 @@ public class WSSConstants extends XMLSec
     public static final QName TAG_soap11_Header = new QName(NS_SOAP11, TAG_soap_Header_LocalName, PREFIX_SOAPENV);
     public static final QName TAG_soap11_Body = new QName(NS_SOAP11, TAG_soap_Body_LocalName, PREFIX_SOAPENV);
     public static final QName ATT_soap11_Actor = new QName(NS_SOAP11, "actor", PREFIX_SOAPENV);
+    public static final QName ATT_soap11_MustUnderstand = new QName(NS_SOAP11, "mustUnderstand", PREFIX_SOAPENV);
 
     public static final QName TAG_soap12_Envelope = new QName(NS_SOAP12, TAG_soap_Envelope_LocalName, PREFIX_SOAPENV);
     public static final QName TAG_soap12_Header = new QName(NS_SOAP12, TAG_soap_Header_LocalName, PREFIX_SOAPENV);
     public static final QName TAG_soap12_Body = new QName(NS_SOAP12, TAG_soap_Body_LocalName, PREFIX_SOAPENV);
     public static final QName ATT_soap12_Role = new QName(NS_SOAP12, "role", PREFIX_SOAPENV);
+    public static final QName ATT_soap12_MustUnderstand = new QName(NS_SOAP12, "mustUnderstand", PREFIX_SOAPENV);
 
     public static final String PREFIX_WSSE = "wsse";
     public static final String PREFIX_WSSE11 = "wsse11";

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSCrypto.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSCrypto.java?rev=1476169&r1=1476168&r2=1476169&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSCrypto.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSCrypto.java Fri Apr 26 12:31:56 2013
@@ -74,6 +74,14 @@ class WSSCrypto {
         return crypto;
     }
     
+    public void setCrypto(Crypto crypto) {
+        cachedCrypto = crypto;
+        if (crypto instanceof Merlin) {
+            keyStore = ((Merlin)crypto).getKeyStore();
+            cachedKeyStore = keyStore;
+        }
+    }
+    
     public Class<? extends Merlin> getCryptoClass() {
         return cryptoClass;
     }

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java?rev=1476169&r1=1476168&r2=1476169&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java Fri Apr 26 12:31:56 2013
@@ -52,6 +52,7 @@ import org.apache.xml.security.utils.Bas
  */
 public class WSSSecurityProperties extends XMLSecurityProperties {
 
+    private boolean mustUnderstand = true;
     private String actor;
     private CallbackHandler callbackHandler;
     private CallbackHandler samlCallbackHandler;
@@ -110,6 +111,7 @@ public class WSSSecurityProperties exten
     public WSSSecurityProperties(WSSSecurityProperties wssSecurityProperties) {
         super(wssSecurityProperties);
 
+        this.mustUnderstand = wssSecurityProperties.mustUnderstand;
         this.actor = wssSecurityProperties.actor;
         this.callbackHandler = wssSecurityProperties.callbackHandler;
         this.samlCallbackHandler = wssSecurityProperties.samlCallbackHandler;
@@ -360,6 +362,13 @@ public class WSSSecurityProperties exten
 
         return signatureWSSCrypto.getCrypto();
     }
+    
+    public void setSignatureCrypto(Crypto sigCrypto) {
+        if (signatureWSSCrypto == null) {
+            signatureWSSCrypto = new WSSCrypto();
+        }
+        signatureWSSCrypto.setCrypto(sigCrypto);
+    }
 
     public KeyStore getSignatureVerificationKeyStore() {
         if (signatureVerificationWSSCrypto != null) {
@@ -424,6 +433,13 @@ public class WSSSecurityProperties exten
         signatureVerificationWSSCrypto.setCrlCertStore(crlCertStore);
         return signatureVerificationWSSCrypto.getCrypto();
     }
+    
+    public void setSignatureVerificationCrypto(Crypto sigVerCrypto) {
+        if (signatureVerificationWSSCrypto == null) {
+            signatureVerificationWSSCrypto = new WSSCrypto();
+        }
+        signatureVerificationWSSCrypto.setCrypto(sigVerCrypto);
+    }
 
     /**
      * Returns the decryption keystore
@@ -505,6 +521,13 @@ public class WSSSecurityProperties exten
 
         return decryptionWSSCrypto.getCrypto();
     }
+    
+    public void setDecryptionCrypto(Crypto decCrypto) {
+        if (decryptionWSSCrypto == null) {
+            decryptionWSSCrypto = new WSSCrypto();
+        }
+        decryptionWSSCrypto.setCrypto(decCrypto);
+    }
 
     /**
      * Returns the encryption keystore
@@ -588,6 +611,13 @@ public class WSSSecurityProperties exten
         return encryptionWSSCrypto.getCrypto();
     }
     
+    public void setEncryptionCrypto(Crypto encCrypto) {
+        if (encryptionWSSCrypto == null) {
+            encryptionWSSCrypto = new WSSCrypto();
+        }
+        encryptionWSSCrypto.setCrypto(encCrypto);
+    }
+    
     /**
      * Returns the alias for the encryption key in the keystore
      *
@@ -771,5 +801,13 @@ public class WSSSecurityProperties exten
     public void setValidateSamlSubjectConfirmation(boolean validateSamlSubjectConfirmation) {
         this.validateSamlSubjectConfirmation = validateSamlSubjectConfirmation;
     }
+
+    public boolean isMustUnderstand() {
+        return mustUnderstand;
+    }
+
+    public void setMustUnderstand(boolean mustUnderstand) {
+        this.mustUnderstand = mustUnderstand;
+    }
     
 }

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java?rev=1476169&r1=1476168&r2=1476169&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java Fri Apr 26 12:31:56 2013
@@ -75,6 +75,10 @@ public class SecurityHeaderOutputProcess
                     } else {
                         for (int i = 0; i < encryptionParts.size(); i++) {
                             SecurePart securePart = encryptionParts.get(i);
+                            // Check to see if the wrong SOAP NS was used
+                            QName secureName = securePart.getName();
+                            securePart.setName(convertQName(secureName, soapMessageVersion));
+                            
                             if (securePart.getIdToSign() == null) {
                                 outputProcessorChain.getSecurityContext().putAsMap(
                                         WSSConstants.ENCRYPTION_PARTS,
@@ -102,6 +106,10 @@ public class SecurityHeaderOutputProcess
                     } else {
                         for (int i = 0; i < signatureParts.size(); i++) {
                             SecurePart securePart = signatureParts.get(i);
+                            // Check to see if the wrong SOAP NS was used
+                            QName secureName = securePart.getName();
+                            securePart.setName(convertQName(secureName, soapMessageVersion));
+                            
                             if (securePart.getIdToSign() == null) {
                                 outputProcessorChain.getSecurityContext().putAsMap(
                                         WSSConstants.SIGNATURE_PARTS,
@@ -132,7 +140,8 @@ public class SecurityHeaderOutputProcess
                     OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this, xmlSecStartElement.getParentXMLSecStartElement());
                     createStartElementAndOutputAsEvent(subOutputProcessorChain,
                             new QName(soapMessageVersion, WSSConstants.TAG_soap_Header_LocalName, WSSConstants.PREFIX_SOAPENV), true, null);
-                    buildSecurityHeader(soapMessageVersion, subOutputProcessorChain);
+                    boolean mustUnderstand = ((WSSSecurityProperties) getSecurityProperties()).isMustUnderstand();
+                    buildSecurityHeader(soapMessageVersion, subOutputProcessorChain, mustUnderstand);
                     createEndElementAndOutputAsEvent(subOutputProcessorChain,
                             new QName(soapMessageVersion, WSSConstants.TAG_soap_Header_LocalName, WSSConstants.PREFIX_SOAPENV));
 
@@ -150,7 +159,8 @@ public class SecurityHeaderOutputProcess
                 if (documentLevel == 2 && WSSConstants.TAG_soap_Header_LocalName.equals(xmlSecEndElement.getName().getLocalPart())
                         && xmlSecEndElement.getName().getNamespaceURI().equals(WSSUtils.getSOAPMessageVersionNamespace(xmlSecEndElement.getParentXMLSecStartElement()))) {
                     OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
-                    buildSecurityHeader(xmlSecEndElement.getName().getNamespaceURI(), subOutputProcessorChain);
+                    boolean mustUnderstand = ((WSSSecurityProperties) getSecurityProperties()).isMustUnderstand();
+                    buildSecurityHeader(xmlSecEndElement.getName().getNamespaceURI(), subOutputProcessorChain, mustUnderstand);
                     //output current soap-header event
                     outputProcessorChain.processEvent(xmlSecEvent);
                     //remove this processor. its no longer needed.
@@ -165,8 +175,23 @@ public class SecurityHeaderOutputProcess
             outputProcessorChain.processEvent(xmlSecEvent);
         }
     }
+    
+    private QName convertQName(QName secureName, String soapVersion) {
+        if (WSSConstants.NS_SOAP11.equals(secureName.getNamespaceURI())
+            && WSSConstants.NS_SOAP12.equals(soapVersion)) {
+            return new QName(soapVersion, secureName.getLocalPart(), secureName.getPrefix());
+        } else if (WSSConstants.NS_SOAP12.equals(secureName.getNamespaceURI())
+            && WSSConstants.NS_SOAP11.equals(soapVersion)) {
+            return new QName(soapVersion, secureName.getLocalPart(), secureName.getPrefix());
+        }
+        return secureName;
+    }
 
-    private void buildSecurityHeader(String soapMessageVersion, OutputProcessorChain subOutputProcessorChain) throws XMLStreamException, XMLSecurityException {
+    private void buildSecurityHeader(
+        String soapMessageVersion, 
+        OutputProcessorChain subOutputProcessorChain,
+        boolean mustUnderstand
+    ) throws XMLStreamException, XMLSecurityException {
         List<XMLSecAttribute> attributes = new ArrayList<XMLSecAttribute>(1);
         final String actor = ((WSSSecurityProperties) getSecurityProperties()).getActor();
         if (actor != null && !actor.isEmpty()) {
@@ -176,6 +201,13 @@ public class SecurityHeaderOutputProcess
                 attributes.add(createAttribute(WSSConstants.ATT_soap12_Role, actor));
             }
         }
+        if (mustUnderstand) {
+            if (WSSConstants.NS_SOAP11.equals(soapMessageVersion)) {
+                attributes.add(createAttribute(WSSConstants.ATT_soap11_MustUnderstand, "1"));
+            } else {
+                attributes.add(createAttribute(WSSConstants.ATT_soap12_MustUnderstand, "true"));
+            }
+        }
         createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsse_Security, true, attributes);
         createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsse_Security);
     }

Added: webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/ConfigurationConverterTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/ConfigurationConverterTest.java?rev=1476169&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/ConfigurationConverterTest.java (added)
+++ webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/ConfigurationConverterTest.java Fri Apr 26 12:31:56 2013
@@ -0,0 +1,209 @@
+/**
+ * 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.wss4j.stax.test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.apache.wss4j.common.ConfigurationConstants;
+import org.apache.wss4j.stax.ConfigurationConverter;
+import org.apache.wss4j.stax.WSSec;
+import org.apache.wss4j.stax.ext.WSSConstants;
+import org.apache.wss4j.stax.ext.WSSSecurityProperties;
+import org.apache.wss4j.stax.ext.WSSConstants.UsernameTokenPasswordType;
+import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
+import org.apache.wss4j.stax.test.saml.SAMLCallbackHandlerImpl;
+import org.testng.annotations.Test;
+
+/**
+ * Some tests for the ConfigurationConverter utility
+ */
+public class ConfigurationConverterTest extends AbstractTestBase {
+
+    @Test
+    public void testUsernameTokenConfiguration() throws Exception {
+        Map<String, Object> config = new HashMap<String, Object>();
+        config.put(ConfigurationConstants.ACTION, ConfigurationConstants.USERNAME_TOKEN);
+        config.put(ConfigurationConstants.USER, "testuser");
+        config.put(ConfigurationConstants.PW_CALLBACK_CLASS, "org.apache.wss4j.stax.test.CallbackHandlerImpl");
+        config.put(ConfigurationConstants.PASSWORD_TYPE, "PasswordText");
+        config.put(ConfigurationConstants.ADD_USERNAMETOKEN_NONCE, "true");
+        config.put(ConfigurationConstants.ADD_USERNAMETOKEN_CREATED, "false");
+        
+        WSSSecurityProperties properties = ConfigurationConverter.convert(config);
+        Assert.assertEquals(properties.getTokenUser(), "testuser");
+        Assert.assertEquals(properties.getOutAction().length, 1);
+        Assert.assertEquals(properties.getOutAction()[0], WSSConstants.USERNAMETOKEN);
+        Assert.assertTrue(properties.getCallbackHandler() instanceof CallbackHandlerImpl);
+        Assert.assertEquals(properties.getUsernameTokenPasswordType(),
+                            UsernameTokenPasswordType.PASSWORD_TEXT);
+        Assert.assertTrue(properties.isAddUsernameTokenNonce());
+        Assert.assertFalse(properties.isAddUsernameTokenCreated());
+        
+        WSSec.validateAndApplyDefaultsToOutboundSecurityProperties(properties);
+    }
+    
+    @Test
+    public void testOutboundSignatureConfiguration() throws Exception {
+        Map<String, Object> config = new HashMap<String, Object>();
+        config.put(ConfigurationConstants.ACTION, ConfigurationConstants.SIGNATURE);
+        config.put(ConfigurationConstants.USER, "transmitter");
+        config.put(ConfigurationConstants.PW_CALLBACK_REF, new CallbackHandlerImpl());
+        String sigAlgo = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
+        config.put(ConfigurationConstants.SIG_ALGO, sigAlgo);
+        config.put(ConfigurationConstants.SIG_KEY_ID, "Thumbprint");
+        config.put(ConfigurationConstants.ADD_INCLUSIVE_PREFIXES, "false");
+        config.put(ConfigurationConstants.SIG_PROP_FILE, "transmitter-crypto.properties");
+        config.put(ConfigurationConstants.SIGNATURE_PARTS, 
+                   "{}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
+        
+        WSSSecurityProperties properties = ConfigurationConverter.convert(config);
+        
+        Assert.assertEquals(properties.getSignatureUser(), "transmitter");
+        Assert.assertEquals(properties.getOutAction().length, 1);
+        Assert.assertEquals(properties.getOutAction()[0], WSSConstants.SIGNATURE);
+        Assert.assertTrue(properties.getCallbackHandler() instanceof CallbackHandlerImpl);
+        Assert.assertEquals(properties.getSignatureAlgorithm(), sigAlgo);
+        Assert.assertEquals(properties.getSignatureKeyIdentifier(), 
+                            WSSecurityTokenConstants.KeyIdentifier_ThumbprintIdentifier);
+        Assert.assertFalse(properties.isAddExcC14NInclusivePrefixes());
+        Assert.assertNotNull(properties.getSignatureCrypto());
+        Assert.assertTrue(properties.getSignatureSecureParts() != null);
+        Assert.assertEquals(properties.getSignatureSecureParts().size(), 1);
+        Assert.assertEquals(properties.getSignatureSecureParts().get(0).getName().getLocalPart(), 
+                            "Body");
+        Assert.assertEquals(properties.getSignatureSecureParts().get(0).getName().getNamespaceURI(), 
+                            "http://schemas.xmlsoap.org/soap/envelope/");
+        
+        WSSec.validateAndApplyDefaultsToOutboundSecurityProperties(properties);
+    }
+    
+    @Test
+    public void testInboundSignatureConfiguration() throws Exception {
+        Map<String, Object> config = new HashMap<String, Object>();
+        config.put(ConfigurationConstants.ACTION, ConfigurationConstants.SIGNATURE);
+        config.put(ConfigurationConstants.PW_CALLBACK_REF, new CallbackHandlerImpl());
+        config.put(ConfigurationConstants.ADD_INCLUSIVE_PREFIXES, "false");
+        config.put(ConfigurationConstants.SIG_VER_PROP_FILE, "transmitter-crypto.properties");
+        config.put(ConfigurationConstants.IS_BSP_COMPLIANT, "false");
+        config.put(ConfigurationConstants.ENABLE_REVOCATION, "true");
+        
+        WSSSecurityProperties properties = ConfigurationConverter.convert(config);
+        
+        Assert.assertEquals(properties.getOutAction().length, 1);
+        Assert.assertEquals(properties.getOutAction()[0], WSSConstants.SIGNATURE);
+        Assert.assertTrue(properties.getCallbackHandler() instanceof CallbackHandlerImpl);
+        Assert.assertTrue(properties.isDisableBSPEnforcement());
+        Assert.assertTrue(properties.isEnableRevocation());
+        Assert.assertNotNull(properties.getSignatureVerificationCrypto());
+        
+        WSSec.validateAndApplyDefaultsToInboundSecurityProperties(properties);
+    }
+    
+    @Test
+    public void testOutboundEncryptionConfiguration() throws Exception {
+        Map<String, Object> config = new HashMap<String, Object>();
+        config.put(ConfigurationConstants.ACTION, ConfigurationConstants.ENCRYPT);
+        config.put(ConfigurationConstants.USER, "transmitter");
+        config.put(ConfigurationConstants.PW_CALLBACK_REF, new CallbackHandlerImpl());
+        config.put(ConfigurationConstants.ENC_KEY_TRANSPORT, WSSConstants.NS_XENC_RSA15);
+        config.put(ConfigurationConstants.ENC_KEY_ID, "EncryptedKeySHA1");
+        config.put(ConfigurationConstants.ENC_PROP_FILE, "receiver-crypto.properties");
+        config.put(ConfigurationConstants.ENCRYPTION_PARTS, 
+                   "{}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
+        
+        WSSSecurityProperties properties = ConfigurationConverter.convert(config);
+        
+        Assert.assertEquals(properties.getEncryptionUser(), "transmitter");
+        Assert.assertEquals(properties.getOutAction().length, 1);
+        Assert.assertEquals(properties.getOutAction()[0], WSSConstants.ENCRYPT);
+        Assert.assertTrue(properties.getCallbackHandler() instanceof CallbackHandlerImpl);
+        Assert.assertEquals(properties.getEncryptionKeyTransportAlgorithm(), 
+                            WSSConstants.NS_XENC_RSA15);
+        Assert.assertEquals(properties.getEncryptionKeyIdentifier(),
+                            WSSecurityTokenConstants.KeyIdentifier_EncryptedKeySha1Identifier);
+        Assert.assertNotNull(properties.getEncryptionCrypto());
+        Assert.assertTrue(properties.getEncryptionSecureParts() != null);
+        Assert.assertEquals(properties.getEncryptionSecureParts().size(), 1);
+        Assert.assertEquals(properties.getEncryptionSecureParts().get(0).getName().getLocalPart(), 
+                            "Body");
+        Assert.assertEquals(properties.getEncryptionSecureParts().get(0).getName().getNamespaceURI(), 
+                            "http://schemas.xmlsoap.org/soap/envelope/");
+        
+        WSSec.validateAndApplyDefaultsToOutboundSecurityProperties(properties);
+    }
+    
+    @Test
+    public void testInboundEncryptionConfiguration() throws Exception {
+        Map<String, Object> config = new HashMap<String, Object>();
+        config.put(ConfigurationConstants.ACTION, ConfigurationConstants.ENCRYPT);
+        config.put(ConfigurationConstants.PW_CALLBACK_REF, new CallbackHandlerImpl());
+        config.put(ConfigurationConstants.DEC_PROP_FILE, "receiver-crypto.properties");
+        config.put(ConfigurationConstants.ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM, "true");
+        
+        WSSSecurityProperties properties = ConfigurationConverter.convert(config);
+        
+        Assert.assertEquals(properties.getOutAction().length, 1);
+        Assert.assertEquals(properties.getOutAction()[0], WSSConstants.ENCRYPT);
+        Assert.assertTrue(properties.getCallbackHandler() instanceof CallbackHandlerImpl);
+        Assert.assertNotNull(properties.getDecryptionCrypto());
+        
+        WSSec.validateAndApplyDefaultsToInboundSecurityProperties(properties);
+    }
+    
+    @Test
+    public void testSAMLConfiguration() throws Exception {
+        Map<String, Object> config = new HashMap<String, Object>();
+        config.put(ConfigurationConstants.ACTION, ConfigurationConstants.SAML_TOKEN_UNSIGNED);
+        config.put(ConfigurationConstants.SAML_CALLBACK_REF, new SAMLCallbackHandlerImpl());
+        
+        WSSSecurityProperties properties = ConfigurationConverter.convert(config);
+        Assert.assertEquals(properties.getOutAction()[0], WSSConstants.SAML_TOKEN_UNSIGNED);
+        Assert.assertTrue(properties.getSamlCallbackHandler() instanceof SAMLCallbackHandlerImpl);
+        
+        WSSec.validateAndApplyDefaultsToOutboundSecurityProperties(properties);
+    }
+    
+    @Test
+    public void testTimestampConfiguration() throws Exception {
+        // Outbound
+        Map<String, Object> config = new HashMap<String, Object>();
+        config.put(ConfigurationConstants.ACTION, ConfigurationConstants.TIMESTAMP);
+        config.put(ConfigurationConstants.TTL_TIMESTAMP, "180");
+        
+        WSSSecurityProperties properties = ConfigurationConverter.convert(config);
+        Assert.assertEquals(properties.getOutAction()[0], WSSConstants.TIMESTAMP);
+        Assert.assertEquals(properties.getTimestampTTL(), Integer.valueOf(180));
+        
+        WSSec.validateAndApplyDefaultsToOutboundSecurityProperties(properties);
+        
+        // Inbound
+        config.put(ConfigurationConstants.TTL_FUTURE_TIMESTAMP, "120");
+        config.put(ConfigurationConstants.TIMESTAMP_STRICT, "false");
+        
+        properties = ConfigurationConverter.convert(config);
+        Assert.assertEquals(properties.getTimeStampFutureTTL(), Integer.valueOf(120));
+        Assert.assertFalse(properties.isStrictTimestampCheck());
+        
+        WSSec.validateAndApplyDefaultsToInboundSecurityProperties(properties);
+    }
+   
+}