You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by gi...@apache.org on 2011/09/18 15:51:36 UTC

svn commit: r1172285 [19/48] - in /webservices/wss4j/branches/swssf: ./ cxf-integration/ cxf-integration/src/ cxf-integration/src/main/ cxf-integration/src/main/java/ cxf-integration/src/main/java/org/ cxf-integration/src/main/java/org/swssf/ cxf-integ...

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/SignatureReferenceVerifyInputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/SignatureReferenceVerifyInputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/SignatureReferenceVerifyInputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/SignatureReferenceVerifyInputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,318 @@
+/**
+ * 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.swssf.impl.processor.input;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.jcs.JCS;
+import org.apache.jcs.access.exception.CacheException;
+import org.apache.jcs.engine.ElementAttributes;
+import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_secext_1_0.TransformationParametersType;
+import org.swssf.config.JCEAlgorithmMapper;
+import org.swssf.ext.*;
+import org.swssf.impl.securityToken.SecurityTokenReference;
+import org.swssf.impl.util.DigestOutputStream;
+import org.swssf.securityEvent.*;
+import org.w3._2000._09.xmldsig_.CanonicalizationMethodType;
+import org.w3._2000._09.xmldsig_.ReferenceType;
+import org.w3._2000._09.xmldsig_.SignatureType;
+import org.w3._2000._09.xmldsig_.TransformType;
+import org.xmlsecurity.ns.configuration.AlgorithmType;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SignatureReferenceVerifyInputProcessor extends AbstractInputProcessor {
+
+    private static final String cacheRegionName = "timestamp";
+
+    private static JCS cache;
+
+    static {
+        try {
+            cache = JCS.getInstance(cacheRegionName);
+        } catch (CacheException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private SignatureType signatureType;
+    private boolean replayChecked = false;
+
+    public SignatureReferenceVerifyInputProcessor(SignatureType signatureType, SecurityProperties securityProperties) {
+        super(securityProperties);
+        this.signatureType = signatureType;
+        this.getAfterProcessors().add(SignatureInputHandler.class.getName());
+        this.getAfterProcessors().add(SignatureReferenceVerifyInputProcessor.class.getName());
+    }
+
+    @Override
+    public XMLEvent processNextHeaderEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        return inputProcessorChain.processHeaderEvent();
+    }
+
+    @Override
+    public XMLEvent processNextEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+        //this is the earliest possible point to check for an replay attack
+        if (!replayChecked) {
+            replayChecked = true;
+            detectReplayAttack(inputProcessorChain);
+        }
+
+        XMLEvent xmlEvent = inputProcessorChain.processEvent();
+
+        if (xmlEvent.isStartElement()) {
+            StartElement startElement = xmlEvent.asStartElement();
+
+            Attribute refId = startElement.getAttributeByName(Constants.ATT_wsu_Id);
+            if (refId != null) {
+                List<ReferenceType> references = signatureType.getSignedInfo().getReference();
+                for (int i = 0; i < references.size(); i++) {
+                    ReferenceType referenceType = references.get(i);
+                    if (refId.getValue().equals(referenceType.getURI())) {
+                        logger.debug("Found signature reference: " + refId.getValue() + " on element" + startElement.getName());
+                        if (referenceType.isProcessed()) {
+                            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, "duplicateId");
+                        }
+                        InternalSignatureReferenceVerifier internalSignatureReferenceVerifier =
+                                new InternalSignatureReferenceVerifier(getSecurityProperties(), inputProcessorChain, referenceType, startElement.getName());
+                        if (!internalSignatureReferenceVerifier.isFinished()) {
+                            internalSignatureReferenceVerifier.processEvent(xmlEvent, inputProcessorChain);
+                            inputProcessorChain.addProcessor(internalSignatureReferenceVerifier);
+                        }
+                        referenceType.setProcessed(true);
+                        inputProcessorChain.getDocumentContext().setIsInSignedContent();
+
+                        //fire a SecurityEvent:
+                        if (inputProcessorChain.getDocumentContext().getDocumentLevel() == 3
+                                && inputProcessorChain.getDocumentContext().isInSOAPHeader()) {
+                            SignedPartSecurityEvent signedPartSecurityEvent = new SignedPartSecurityEvent(SecurityEvent.Event.SignedPart, false);
+                            signedPartSecurityEvent.setElement(startElement.getName());
+                            inputProcessorChain.getSecurityContext().registerSecurityEvent(signedPartSecurityEvent);
+                        } else {
+                            SignedElementSecurityEvent signedElementSecurityEvent = new SignedElementSecurityEvent(SecurityEvent.Event.SignedElement, false);
+                            signedElementSecurityEvent.setElement(startElement.getName());
+                            inputProcessorChain.getSecurityContext().registerSecurityEvent(signedElementSecurityEvent);
+                        }
+                    }
+                }
+            }
+        }
+
+        return xmlEvent;
+    }
+
+    private void detectReplayAttack(InputProcessorChain inputProcessorChain) throws WSSecurityException {
+        TimestampSecurityEvent timestampSecurityEvent = inputProcessorChain.getSecurityContext().get(Constants.PROP_TIMESTAMP_SECURITYEVENT);
+        if (timestampSecurityEvent != null) {
+            final String cacheKey = String.valueOf(timestampSecurityEvent.getCreated().getTimeInMillis()) + signatureType.getSignatureValue().getRawValue();
+            if (cache.get(cacheKey) != null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED);
+            }
+            ElementAttributes elementAttributes = new ElementAttributes();
+            if (timestampSecurityEvent.getExpires() != null) {
+                long lifeTime = timestampSecurityEvent.getExpires().getTime().getTime() - new Date().getTime();
+                elementAttributes.setMaxLifeSeconds(lifeTime / 1000);
+            } else {
+                elementAttributes.setMaxLifeSeconds(300);
+            }
+            try {
+                cache.put(cacheKey, timestampSecurityEvent.getCreated(), elementAttributes);
+            } catch (CacheException e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+            }
+        }
+    }
+
+    @Override
+    public void doFinal(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        List<ReferenceType> references = signatureType.getSignedInfo().getReference();
+        for (int i = 0; i < references.size(); i++) {
+            ReferenceType referenceType = references.get(i);
+            if (!referenceType.isProcessed()) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, "unprocessedSignatureReferences");
+            }
+        }
+        inputProcessorChain.doFinal();
+    }
+
+    class InternalSignatureReferenceVerifier extends AbstractInputProcessor {
+        private ReferenceType referenceType;
+
+        private Transformer transformer;
+        private DigestOutputStream digestOutputStream;
+        private OutputStream bufferedDigestOutputStream;
+        private QName startElement;
+        private int elementCounter = 0;
+        private boolean finished = false;
+
+        public InternalSignatureReferenceVerifier(SecurityProperties securityProperties, InputProcessorChain inputProcessorChain, ReferenceType referenceType, QName startElement) throws WSSecurityException {
+            super(securityProperties);
+            this.getAfterProcessors().add(SignatureReferenceVerifyInputProcessor.class.getName());
+            this.startElement = startElement;
+            this.referenceType = referenceType;
+            try {
+                createMessageDigest(inputProcessorChain.getSecurityContext());
+                buildTransformerChain(referenceType, inputProcessorChain);
+            } catch (Exception e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
+            }
+        }
+
+        private void createMessageDigest(SecurityContext securityContext) throws WSSecurityException, NoSuchAlgorithmException, NoSuchProviderException {
+            AlgorithmType digestAlgorithm = JCEAlgorithmMapper.getAlgorithmMapping(referenceType.getDigestMethod().getAlgorithm());
+
+            AlgorithmSuiteSecurityEvent algorithmSuiteSecurityEvent = new AlgorithmSuiteSecurityEvent(SecurityEvent.Event.AlgorithmSuite);
+            algorithmSuiteSecurityEvent.setAlgorithmURI(digestAlgorithm.getURI());
+            algorithmSuiteSecurityEvent.setKeyUsage(Constants.KeyUsage.Dig);
+            securityContext.registerSecurityEvent(algorithmSuiteSecurityEvent);
+
+            MessageDigest messageDigest = MessageDigest.getInstance(digestAlgorithm.getJCEName(), digestAlgorithm.getJCEProvider());
+            this.digestOutputStream = new DigestOutputStream(messageDigest);
+            this.bufferedDigestOutputStream = new BufferedOutputStream(this.digestOutputStream);
+        }
+
+        private void buildTransformerChain(ReferenceType referenceType, InputProcessorChain inputProcessorChain) throws WSSecurityException, XMLStreamException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
+            List<TransformType> transformTypeList = referenceType.getTransforms().getTransform();
+
+            String algorithm = null;
+            Transformer parentTransformer = null;
+            for (int i = transformTypeList.size() - 1; i >= 0; i--) {
+                TransformType transformType = transformTypeList.get(i);
+
+                if (transformType.getTransformationParametersType() != null) {
+                    TransformationParametersType transformationParametersType = transformType.getTransformationParametersType();
+                    final CanonicalizationMethodType canonicalizationMethodType = transformationParametersType.getCanonicalizationMethodType();
+                    if (canonicalizationMethodType != null) {
+                        algorithm = canonicalizationMethodType.getAlgorithm();
+                        String inclusiveNamespaces = canonicalizationMethodType.getInclusiveNamespaces();
+                        if (Constants.SOAPMESSAGE_NS10_STRTransform.equals(transformType.getAlgorithm())) {
+                            if (inclusiveNamespaces == null) {
+                                inclusiveNamespaces = "#default";
+                            } else {
+                                inclusiveNamespaces = "#default " + inclusiveNamespaces;
+                            }
+                        }
+                        parentTransformer = Utils.getTransformer(inclusiveNamespaces, this.bufferedDigestOutputStream, algorithm);
+                    }
+                }
+                algorithm = transformType.getAlgorithm();
+
+                AlgorithmSuiteSecurityEvent algorithmSuiteSecurityEvent = new AlgorithmSuiteSecurityEvent(SecurityEvent.Event.AlgorithmSuite);
+                algorithmSuiteSecurityEvent.setAlgorithmURI(algorithm);
+                algorithmSuiteSecurityEvent.setKeyUsage(Constants.KeyUsage.C14n);
+                inputProcessorChain.getSecurityContext().registerSecurityEvent(algorithmSuiteSecurityEvent);
+
+                if (parentTransformer != null) {
+                    parentTransformer = Utils.getTransformer(parentTransformer, transformType.getInclusiveNamespaces(), algorithm);
+                } else {
+                    parentTransformer = Utils.getTransformer(transformType.getInclusiveNamespaces(), this.bufferedDigestOutputStream, algorithm);
+                }
+            }
+
+            this.transformer = parentTransformer;
+
+            if (Constants.SOAPMESSAGE_NS10_STRTransform.equals(algorithm)) {
+                SecurityTokenProvider securityTokenProvider = inputProcessorChain.getSecurityContext().getSecurityTokenProvider(referenceType.getURI());
+                if (securityTokenProvider == null) {
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "noReference");
+                }
+                SecurityToken securityToken = securityTokenProvider.getSecurityToken(getSecurityProperties().getSignatureVerificationCrypto());
+                if (!(securityToken instanceof SecurityTokenReference)) {
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN);
+                }
+                SecurityTokenReference securityTokenReference = (SecurityTokenReference) securityToken;
+                this.startElement = securityTokenReference.getXmlEvents().getLast().asStartElement().getName();
+                Iterator<XMLEvent> xmlEventIterator = securityTokenReference.getXmlEvents().descendingIterator();
+                while (xmlEventIterator.hasNext()) {
+                    processEvent(xmlEventIterator.next(), inputProcessorChain);
+                }
+            }
+        }
+
+        @Override
+        public XMLEvent processNextHeaderEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+            return inputProcessorChain.processHeaderEvent();
+        }
+
+        @Override
+        public XMLEvent processNextEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+            XMLEvent xmlEvent = inputProcessorChain.processEvent();
+            processEvent(xmlEvent, inputProcessorChain);
+            return xmlEvent;
+        }
+
+        protected void processEvent(XMLEvent xmlEvent, InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+            transformer.transform(xmlEvent);
+
+            if (xmlEvent.isStartElement()) {
+                elementCounter++;
+            } else if (xmlEvent.isEndElement()) {
+                EndElement endElement = xmlEvent.asEndElement();
+                elementCounter--;
+
+                if (endElement.getName().equals(startElement) && elementCounter == 0) {
+                    try {
+                        bufferedDigestOutputStream.close();
+                    } catch (IOException e) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
+                    }
+
+                    byte[] calculatedDigest = this.digestOutputStream.getDigestValue();
+                    byte[] storedDigest = Base64.decodeBase64(referenceType.getDigestValue());
+
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Calculated Digest: " + new String(Base64.encodeBase64(calculatedDigest)));
+                        logger.debug("Stored Digest: " + new String(Base64.encodeBase64(storedDigest)));
+                    }
+
+                    if (!MessageDigest.isEqual(storedDigest, calculatedDigest)) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, "digestVerificationFailed", referenceType.getURI());
+                    }
+                    inputProcessorChain.removeProcessor(this);
+                    inputProcessorChain.getDocumentContext().unsetIsInSignedContent();
+                    finished = true;
+                }
+            }
+        }
+
+        public boolean isFinished() {
+            return finished;
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/SignatureReferenceVerifyInputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/TimestampInputHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/TimestampInputHandler.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/TimestampInputHandler.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/TimestampInputHandler.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,121 @@
+/**
+ * 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.swssf.impl.processor.input;
+
+import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_utility_1_0.TimestampType;
+import org.swssf.ext.*;
+import org.swssf.securityEvent.SecurityEvent;
+import org.swssf.securityEvent.TimestampSecurityEvent;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.Calendar;
+import java.util.Deque;
+import java.util.GregorianCalendar;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class TimestampInputHandler extends AbstractInputSecurityHeaderHandler {
+
+    //Chapter 10 Security Timestamps: ...may only be present at most once per header (that is, per SOAP actor/role)
+    public TimestampInputHandler(InputProcessorChain inputProcessorChain,
+                                 final SecurityProperties securityProperties,
+                                 Deque<XMLEvent> eventQueue,
+                                 Integer index) throws WSSecurityException {
+
+        Boolean alreadyProcessed = inputProcessorChain.getSecurityContext().<Boolean>get(Constants.TIMESTAMP_PROCESSED);
+        if (Boolean.TRUE.equals(alreadyProcessed)) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED, "invalidTimestamp",
+                    "Message contains two or more timestamps");
+        }
+        inputProcessorChain.getSecurityContext().put(Constants.TIMESTAMP_PROCESSED, Boolean.TRUE);
+
+        final TimestampType timestampType = (TimestampType) parseStructure(eventQueue, index);
+
+        try {
+            DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
+
+            // Validate whether the security semantics have expired
+            //created and expires is optional per spec. But we enforce the created element in the validation
+            Calendar crea = null;
+            if (timestampType.getCreated() != null) {
+                XMLGregorianCalendar created = datatypeFactory.newXMLGregorianCalendar(timestampType.getCreated().getValue());
+                logger.debug("Timestamp created: " + created);
+                crea = created.toGregorianCalendar();
+            }
+
+            Calendar exp = null;
+            if (timestampType.getExpires() != null) {
+                XMLGregorianCalendar expires = datatypeFactory.newXMLGregorianCalendar(timestampType.getExpires().getValue());
+                logger.debug("Timestamp expires: " + expires);
+                exp = expires.toGregorianCalendar();
+            }
+
+            Calendar rightNow = Calendar.getInstance();
+            Calendar ttl = Calendar.getInstance();
+            ttl.add(Calendar.SECOND, -securityProperties.getTimestampTTL());
+
+            if (exp != null && securityProperties.isStrictTimestampCheck() && exp.before(rightNow)) {
+                logger.debug("Time now: " + datatypeFactory.newXMLGregorianCalendar(new GregorianCalendar()).toXMLFormat());
+                throw new WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED, "invalidTimestamp",
+                        "The security semantics of the message have expired");
+            }
+
+            if (crea != null && securityProperties.isStrictTimestampCheck() && crea.before(ttl)) {
+                logger.debug("Time now: " + datatypeFactory.newXMLGregorianCalendar(new GregorianCalendar()).toXMLFormat());
+                throw new WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED, "invalidTimestamp",
+                        "The security semantics of the message have expired");
+            }
+
+            if (crea != null && crea.after(rightNow)) {
+                logger.debug("Time now: " + datatypeFactory.newXMLGregorianCalendar(new GregorianCalendar()).toXMLFormat());
+                throw new WSSecurityException(WSSecurityException.ErrorCode.MESSAGE_EXPIRED, "invalidTimestamp",
+                        "The security semantics of the message is invalid");
+            }
+
+            TimestampSecurityEvent timestampSecurityEvent = new TimestampSecurityEvent(SecurityEvent.Event.Timestamp);
+            timestampSecurityEvent.setCreated(crea);
+            timestampSecurityEvent.setExpires(exp);
+            inputProcessorChain.getSecurityContext().registerSecurityEvent(timestampSecurityEvent);
+            inputProcessorChain.getSecurityContext().put(Constants.PROP_TIMESTAMP_SECURITYEVENT, timestampSecurityEvent);
+
+        } catch (DatatypeConfigurationException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+        } catch (IllegalArgumentException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+        }
+    }
+
+    @Override
+    protected Parseable getParseable(StartElement startElement) {
+        return new TimestampType(startElement);
+    }
+
+    /*
+    <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-1106985890">
+        <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2009-11-18T10:11:28.358Z</wsu:Created>
+        <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2009-11-18T10:26:28.358Z</wsu:Expires>
+    </wsu:Timestamp>
+     */
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/TimestampInputHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/UsernameTokenInputHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/UsernameTokenInputHandler.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/UsernameTokenInputHandler.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/UsernameTokenInputHandler.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,193 @@
+/**
+ * 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.swssf.impl.processor.input;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.jcs.JCS;
+import org.apache.jcs.access.exception.CacheException;
+import org.apache.jcs.engine.ElementAttributes;
+import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_secext_1_0.UsernameTokenType;
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.securityToken.SecurityTokenFactory;
+import org.swssf.securityEvent.SecurityEvent;
+import org.swssf.securityEvent.UsernameTokenSecurityEvent;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.*;
+
+/**
+ * Processor for the UsernameToken XML Structure
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class UsernameTokenInputHandler extends AbstractInputSecurityHeaderHandler {
+
+    private static final String cacheRegionName = "usernameToken";
+
+    private static JCS cache;
+
+    static {
+        try {
+            cache = JCS.getInstance(cacheRegionName);
+        } catch (CacheException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public UsernameTokenInputHandler(final InputProcessorChain inputProcessorChain, final SecurityProperties securityProperties, Deque<XMLEvent> eventQueue, Integer index) throws WSSecurityException {
+
+        final UsernameTokenType usernameTokenType = (UsernameTokenType) parseStructure(eventQueue, index);
+        if (usernameTokenType.getId() == null) {
+            usernameTokenType.setId(UUID.randomUUID().toString());
+        }
+
+        // If the UsernameToken is to be used for key derivation, the (1.1)
+        // spec says that it cannot contain a password, and it must contain
+        // an Iteration element
+        if (usernameTokenType.getSalt() != null && (usernameTokenType.getPassword() != null || usernameTokenType.getIteration() == null)) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "badTokenType01");
+        }
+
+        Integer iteration = null;
+        if (usernameTokenType.getIteration() != null) {
+            iteration = Integer.parseInt(usernameTokenType.getIteration());
+        }
+
+        GregorianCalendar createdCal = null;
+        byte[] nonceVal = null;
+
+        Constants.UsernameTokenPasswordType usernameTokenPasswordType = Constants.UsernameTokenPasswordType.PASSWORD_NONE;
+        if (usernameTokenType.getPasswordType() != null) {
+            usernameTokenPasswordType = Constants.UsernameTokenPasswordType.getUsernameTokenPasswordType(usernameTokenType.getPasswordType());
+        }
+
+        final String username = usernameTokenType.getUsername();
+        if (usernameTokenPasswordType == Constants.UsernameTokenPasswordType.PASSWORD_DIGEST) {
+            final String nonce = usernameTokenType.getNonce();
+            if (nonce == null || usernameTokenType.getCreated() == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "badTokenType01");
+            }
+
+            /*
+                It is RECOMMENDED that used nonces be cached for a period at least as long as
+                the timestamp freshness limitation period, above, and that UsernameToken with
+                nonces that have already been used (and are thus in the cache) be rejected
+            */
+            final String cacheKey = nonce;
+            if (cache.get(cacheKey) != null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+            }
+            ElementAttributes elementAttributes = new ElementAttributes();
+            elementAttributes.setMaxLifeSeconds(300);
+            try {
+                cache.put(cacheKey, usernameTokenType.getCreated(), elementAttributes);
+            } catch (CacheException e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+            }
+
+            DatatypeFactory datatypeFactory = null;
+            try {
+                datatypeFactory = DatatypeFactory.newInstance();
+            } catch (DatatypeConfigurationException e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+            }
+            XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(usernameTokenType.getCreated());
+            createdCal = xmlGregorianCalendar.toGregorianCalendar();
+            GregorianCalendar now = new GregorianCalendar();
+            if (createdCal.after(now)) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+            }
+            now.add(Calendar.MINUTE, 5);
+            if (createdCal.after(now)) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+            }
+
+            WSPasswordCallback pwCb = new WSPasswordCallback(username,
+                    null,
+                    usernameTokenType.getPasswordType(),
+                    WSPasswordCallback.Usage.USERNAME_TOKEN);
+            try {
+                Utils.doPasswordCallback(securityProperties.getCallbackHandler(), pwCb);
+            } catch (WSSecurityException e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION, e);
+            }
+
+            if (pwCb.getPassword() == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+            }
+
+            nonceVal = Base64.decodeBase64(nonce);
+
+            String passDigest = Utils.doPasswordDigest(nonceVal, usernameTokenType.getCreated(), pwCb.getPassword());
+            if (!usernameTokenType.getPassword().equals(passDigest)) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+            }
+            usernameTokenType.setPassword(pwCb.getPassword());
+        } else {
+            WSPasswordCallback pwCb = new WSPasswordCallback(username,
+                    usernameTokenType.getPassword(),
+                    usernameTokenType.getPasswordType(),
+                    WSPasswordCallback.Usage.USERNAME_TOKEN_UNKNOWN);
+            try {
+                Utils.doPasswordCallback(securityProperties.getCallbackHandler(), pwCb);
+            } catch (WSSecurityException e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION, e);
+            }
+            usernameTokenType.setPassword(pwCb.getPassword());
+        }
+
+        SecurityTokenProvider securityTokenProvider = new SecurityTokenProvider() {
+
+            private Map<Crypto, SecurityToken> securityTokens = new HashMap<Crypto, SecurityToken>();
+
+            public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                SecurityToken securityToken = securityTokens.get(crypto);
+                if (securityToken != null) {
+                    return securityToken;
+                }
+                securityToken = SecurityTokenFactory.newInstance().getSecurityToken(
+                        usernameTokenType, inputProcessorChain.getSecurityContext(), null);
+                securityTokens.put(crypto, securityToken);
+                return securityToken;
+            }
+
+            public String getId() {
+                return usernameTokenType.getId();
+            }
+        };
+        inputProcessorChain.getSecurityContext().registerSecurityTokenProvider(usernameTokenType.getId(), securityTokenProvider);
+
+        UsernameTokenSecurityEvent usernameTokenSecurityEvent = new UsernameTokenSecurityEvent(SecurityEvent.Event.UsernameToken);
+        usernameTokenSecurityEvent.setUsernameTokenPasswordType(usernameTokenPasswordType);
+        usernameTokenSecurityEvent.setSecurityToken(securityTokenProvider.getSecurityToken(null));
+        usernameTokenSecurityEvent.setUsernameTokenProfile(Constants.NS_USERNAMETOKEN_PROFILE11);
+        inputProcessorChain.getSecurityContext().registerSecurityEvent(usernameTokenSecurityEvent);
+    }
+
+    @Override
+    protected Parseable getParseable(StartElement startElement) {
+        return new UsernameTokenType(startElement);
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/UsernameTokenInputHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/XMLEventReaderInputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/XMLEventReaderInputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/XMLEventReaderInputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/XMLEventReaderInputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,73 @@
+/**
+ * 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.swssf.impl.processor.input;
+
+import org.swssf.ext.*;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.List;
+
+/**
+ * The XMLEventReaderInputProcessor reads requested XMLEvents from the original XMLEventReader
+ * and returns them to the requestor
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class XMLEventReaderInputProcessor extends AbstractInputProcessor {
+
+    private XMLEventReader xmlEventReader;
+    private Deque<List<ComparableNamespace>> nsStack = new ArrayDeque<List<ComparableNamespace>>(10);
+    private Deque<List<ComparableAttribute>> attrStack = new ArrayDeque<List<ComparableAttribute>>(10);
+
+    public XMLEventReaderInputProcessor(SecurityProperties securityProperties, XMLEventReader xmlEventReader) {
+        super(securityProperties);
+        setPhase(Constants.Phase.PREPROCESSING);
+        this.xmlEventReader = xmlEventReader;
+    }
+
+    @Override
+    public XMLEvent processNextHeaderEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        return processNextEventInternal(inputProcessorChain);
+    }
+
+    @Override
+    public XMLEvent processNextEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        return processNextEventInternal(inputProcessorChain);
+    }
+
+    private XMLEvent processNextEventInternal(InputProcessorChain inputProcessorChain) throws XMLStreamException {
+        XMLEvent xmlEvent = Utils.createXMLEventNS(xmlEventReader.nextEvent(), nsStack, attrStack);
+        if (xmlEvent.isStartElement()) {
+            inputProcessorChain.getDocumentContext().addPathElement(xmlEvent.asStartElement().getName());
+        } else if (xmlEvent.isEndElement()) {
+            inputProcessorChain.getDocumentContext().removePathElement();
+        }
+        return xmlEvent;
+    }
+
+    @Override
+    public void doFinal(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        //nothing to-do. Also don't call super.doFinal() we are the last processor
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/XMLEventReaderInputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/BinarySecurityTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/BinarySecurityTokenOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/BinarySecurityTokenOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/BinarySecurityTokenOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,257 @@
+/**
+ * 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.swssf.impl.processor.output;
+
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.securityToken.DelegatingSecurityToken;
+import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+import org.swssf.impl.securityToken.X509SecurityToken;
+import org.swssf.securityEvent.SecurityEvent;
+import org.swssf.securityEvent.SignatureTokenSecurityEvent;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class BinarySecurityTokenOutputProcessor extends AbstractOutputProcessor {
+
+    public BinarySecurityTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        try {
+            final String bstId = "BST-" + UUID.randomUUID().toString();
+            final X509Certificate[] x509Certificates;
+            final Key key;
+
+            switch (getAction()) {
+                case SIGNATURE:
+                case SAML_TOKEN_SIGNED:
+                case SIGNATURE_WITH_DERIVED_KEY:
+                    String alias = getSecurityProperties().getSignatureUser();
+                    WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.Usage.SIGNATURE);
+                    Utils.doPasswordCallback(getSecurityProperties().getCallbackHandler(), pwCb);
+                    String password = pwCb.getPassword();
+                    if (password == null) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noPassword", alias);
+                    }
+                    key = getSecurityProperties().getSignatureCrypto().getPrivateKey(alias, password);
+                    x509Certificates = getSecurityProperties().getSignatureCrypto().getCertificates(getSecurityProperties().getSignatureUser());
+                    if (x509Certificates == null || x509Certificates.length == 0) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noUserCertsFound", alias);
+                    }
+                    break;
+                case ENCRYPT:
+                case ENCRYPT_WITH_DERIVED_KEY:
+                    X509Certificate x509Certificate = getReqSigCert(outputProcessorChain.getSecurityContext());
+                    if (x509Certificate != null && getSecurityProperties().isUseReqSigCertForEncryption()) {
+                        x509Certificates = new X509Certificate[1];
+                        x509Certificates[0] = x509Certificate;
+                    } else if (getSecurityProperties().getEncryptionUseThisCertificate() != null) {
+                        x509Certificate = getSecurityProperties().getEncryptionUseThisCertificate();
+                        x509Certificates = new X509Certificate[1];
+                        x509Certificates[0] = x509Certificate;
+                    } else {
+                        x509Certificates = getSecurityProperties().getEncryptionCrypto().getCertificates(getSecurityProperties().getEncryptionUser());
+                        if (x509Certificates == null || x509Certificates.length == 0) {
+                            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, "noUserCertsFound", getSecurityProperties().getEncryptionUser());
+                        }
+                    }
+                    key = null;
+                    break;
+                default:
+                    x509Certificates = null;
+                    key = null;
+                    break;
+            }
+
+            final ProcessorInfoSecurityToken binarySecurityToken = new ProcessorInfoSecurityToken() {
+
+                private OutputProcessor outputProcessor;
+
+                public String getId() {
+                    return bstId;
+                }
+
+                public void setProcessor(OutputProcessor outputProcessor) {
+                    this.outputProcessor = outputProcessor;
+                }
+
+                public Object getProcessor() {
+                    return outputProcessor;
+                }
+
+                public boolean isAsymmetric() {
+                    return true;
+                }
+
+                public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    return key;
+                }
+
+                public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    return x509Certificates[0].getPublicKey();
+                }
+
+                public X509Certificate[] getX509Certificates() throws WSSecurityException {
+                    return x509Certificates;
+                }
+
+                public void verify() throws WSSecurityException {
+                }
+
+                public SecurityToken getKeyWrappingToken() {
+                    return null;
+                }
+
+                public String getKeyWrappingTokenAlgorithm() {
+                    return null;
+                }
+
+                public Constants.TokenType getTokenType() {
+                    return null;
+                }
+            };
+
+            final SecurityTokenProvider binarySecurityTokenProvider = new SecurityTokenProvider() {
+                public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                    return binarySecurityToken;
+                }
+
+                public String getId() {
+                    return bstId;
+                }
+            };
+
+            switch (getAction()) {
+                case SIGNATURE:
+                case SAML_TOKEN_SIGNED:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, bstId);
+                    if (getSecurityProperties().getSignatureKeyIdentifierType() == Constants.KeyIdentifierType.BST_DIRECT_REFERENCE) {
+                        outputProcessorChain.getSecurityContext().put(Constants.PROP_APPEND_SIGNATURE_ON_THIS_ID, bstId);
+                        FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor = new FinalBinarySecurityTokenOutputProcessor(getSecurityProperties(), getAction(), binarySecurityToken);
+                        finalBinarySecurityTokenOutputProcessor.getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
+                        outputProcessorChain.addProcessor(finalBinarySecurityTokenOutputProcessor);
+                        binarySecurityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
+                    }
+                    break;
+                case ENCRYPT:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, bstId);
+                    if (getSecurityProperties().getEncryptionKeyIdentifierType() == Constants.KeyIdentifierType.BST_DIRECT_REFERENCE) {
+                        FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor = new FinalBinarySecurityTokenOutputProcessor(getSecurityProperties(), getAction(), binarySecurityToken);
+                        finalBinarySecurityTokenOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+                        outputProcessorChain.addProcessor(finalBinarySecurityTokenOutputProcessor);
+                        binarySecurityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
+                    }
+                    break;
+                case SIGNATURE_WITH_DERIVED_KEY:
+                case ENCRYPT_WITH_DERIVED_KEY:
+                    switch (getSecurityProperties().getDerivedKeyTokenReference()) {
+
+                        case DirectReference:
+                            outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, bstId);
+                            break;
+                        case EncryptedKey:
+                            outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, bstId);
+                            break;
+                        case SecurityContextToken:
+                            outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SECURITYCONTEXTTOKEN, bstId);
+                            break;
+                    }
+                    if ((getAction() == Constants.Action.ENCRYPT_WITH_DERIVED_KEY
+                            && getSecurityProperties().getEncryptionKeyIdentifierType() == Constants.KeyIdentifierType.BST_DIRECT_REFERENCE)
+                            || (getAction() == Constants.Action.SIGNATURE_WITH_DERIVED_KEY
+                            && getSecurityProperties().getSignatureKeyIdentifierType() == Constants.KeyIdentifierType.BST_DIRECT_REFERENCE)) {
+                        FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor = new FinalBinarySecurityTokenOutputProcessor(getSecurityProperties(), getAction(), binarySecurityToken);
+                        finalBinarySecurityTokenOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+                        outputProcessorChain.addProcessor(finalBinarySecurityTokenOutputProcessor);
+                        binarySecurityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
+                    }
+                    break;
+            }
+
+            outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(bstId, binarySecurityTokenProvider);
+
+        } finally {
+            outputProcessorChain.removeProcessor(this);
+        }
+        outputProcessorChain.processEvent(xmlEvent);
+    }
+
+    private X509Certificate getReqSigCert(SecurityContext securityContext) throws WSSecurityException {
+        List<SecurityEvent> securityEventList = securityContext.getAsList(SecurityEvent.class);
+        if (securityEventList != null) {
+            for (int i = 0; i < securityEventList.size(); i++) {
+                SecurityEvent securityEvent = securityEventList.get(i);
+                //todo find correct message signature token...however...
+                if (securityEvent.getSecurityEventType() == SecurityEvent.Event.SignatureToken) {
+                    SignatureTokenSecurityEvent signatureTokenSecurityEvent = (SignatureTokenSecurityEvent) securityEvent;
+                    SecurityToken securityToken = signatureTokenSecurityEvent.getSecurityToken();
+                    if (securityToken instanceof DelegatingSecurityToken) {
+                        securityToken = ((DelegatingSecurityToken) securityToken).getDelegatedSecurityToken();
+                    }
+                    if (securityToken instanceof X509SecurityToken) {
+                        X509SecurityToken x509SecurityToken = (X509SecurityToken) securityToken;
+                        return x509SecurityToken.getX509Certificates()[0];
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    class FinalBinarySecurityTokenOutputProcessor extends AbstractOutputProcessor {
+
+        private SecurityToken securityToken;
+
+        FinalBinarySecurityTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken) throws WSSecurityException {
+            super(securityProperties, action);
+            this.getAfterProcessors().add(BinarySecurityTokenOutputProcessor.class.getName());
+            this.securityToken = securityToken;
+        }
+
+        @Override
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+            outputProcessorChain.processEvent(xmlEvent);
+            if (xmlEvent.isStartElement()) {
+                StartElement startElement = xmlEvent.asStartElement();
+                if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                    OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+
+                    boolean useSingleCertificate = getSecurityProperties().isUseSingleCert();
+                    createBinarySecurityTokenStructure(subOutputProcessorChain, securityToken.getId(), securityToken.getX509Certificates(), useSingleCertificate);
+
+                    outputProcessorChain.removeProcessor(this);
+                }
+            }
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/BinarySecurityTokenOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/DerivedKeyTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/DerivedKeyTokenOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/DerivedKeyTokenOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/DerivedKeyTokenOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,254 @@
+/**
+ * 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.swssf.impl.processor.output;
+
+import org.apache.commons.codec.binary.Base64;
+import org.swssf.config.JCEAlgorithmMapper;
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.derivedKey.AlgoFactory;
+import org.swssf.impl.derivedKey.ConversationException;
+import org.swssf.impl.derivedKey.DerivationAlgorithm;
+import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.io.UnsupportedEncodingException;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class DerivedKeyTokenOutputProcessor extends AbstractOutputProcessor {
+
+    public DerivedKeyTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        try {
+
+            String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY);
+            if (tokenId == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+            SecurityTokenProvider wrappingSecurityTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+            if (wrappingSecurityTokenProvider == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+            final SecurityToken wrappingSecurityToken = wrappingSecurityTokenProvider.getSecurityToken(null);
+            if (wrappingSecurityToken == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+
+            final String wsuIdDKT = "DK-" + UUID.randomUUID().toString();
+
+            int offset = 0;
+            int length = 0;
+            switch (getAction()) {
+                case SIGNATURE_WITH_DERIVED_KEY:
+                    length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getSignatureAlgorithm()).getKeyLength() / 8;
+                    break;
+                case ENCRYPT_WITH_DERIVED_KEY:
+                    length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getEncryptionSymAlgorithm()).getKeyLength() / 8;
+                    break;
+            }
+
+            byte[] label;
+            try {
+                label = (Constants.WS_SecureConversation_DEFAULT_LABEL + Constants.WS_SecureConversation_DEFAULT_LABEL).getBytes("UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                throw new WSSecurityException("UTF-8 encoding is not supported", e);
+            }
+
+            byte[] nonce = new byte[16];
+            Constants.secureRandom.nextBytes(nonce);
+
+            byte[] seed = new byte[label.length + nonce.length];
+            System.arraycopy(label, 0, seed, 0, label.length);
+            System.arraycopy(nonce, 0, seed, label.length, nonce.length);
+
+            DerivationAlgorithm derivationAlgorithm;
+            try {
+                derivationAlgorithm = AlgoFactory.getInstance(Constants.P_SHA_1);
+            } catch (ConversationException e) {
+                throw new WSSecurityException(e.getMessage(), e);
+            }
+
+            final byte[] derivedKeyBytes;
+            try {
+                byte[] secret;
+                if (wrappingSecurityToken.getTokenType() == Constants.TokenType.SecurityContextToken) {
+                    WSPasswordCallback passwordCallback = new WSPasswordCallback(wsuIdDKT, WSPasswordCallback.Usage.SECRET_KEY);
+                    Utils.doSecretKeyCallback(securityProperties.getCallbackHandler(), passwordCallback, wsuIdDKT);
+                    if (passwordCallback.getKey() == null) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noKey", wsuIdDKT);
+                    }
+                    secret = passwordCallback.getKey();
+                } else {
+                    secret = wrappingSecurityToken.getSecretKey(null, null).getEncoded();
+                }
+
+                derivedKeyBytes = derivationAlgorithm.createKey(secret, seed, offset, length);
+            } catch (ConversationException e) {
+                throw new WSSecurityException(e.getMessage(), e);
+            }
+
+            final ProcessorInfoSecurityToken derivedKeySecurityToken = new ProcessorInfoSecurityToken() {
+
+                private Map<String, Key> keyTable = new Hashtable<String, Key>();
+                private OutputProcessor outputProcessor;
+
+                public String getId() {
+                    return wsuIdDKT;
+                }
+
+                public void setProcessor(OutputProcessor outputProcessor) {
+                    this.outputProcessor = outputProcessor;
+                }
+
+                public Object getProcessor() {
+                    return outputProcessor;
+                }
+
+                public boolean isAsymmetric() {
+                    return false;
+                }
+
+                public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    if (keyTable.containsKey(algorithmURI)) {
+                        return keyTable.get(algorithmURI);
+                    } else {
+                        String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+                        Key key = new SecretKeySpec(derivedKeyBytes, algoFamily);
+                        keyTable.put(algorithmURI, key);
+                        return key;
+                    }
+                }
+
+                public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    return null;
+                }
+
+                public X509Certificate[] getX509Certificates() throws WSSecurityException {
+                    return null;
+                }
+
+                public void verify() throws WSSecurityException {
+                }
+
+                public SecurityToken getKeyWrappingToken() {
+                    return wrappingSecurityToken;
+                }
+
+                public String getKeyWrappingTokenAlgorithm() {
+                    return null;
+                }
+
+                public Constants.TokenType getTokenType() {
+                    return null;
+                }
+            };
+
+            SecurityTokenProvider derivedKeysecurityTokenProvider = new SecurityTokenProvider() {
+                public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                    return derivedKeySecurityToken;
+                }
+
+                public String getId() {
+                    return wsuIdDKT;
+                }
+            };
+
+            switch (getAction()) {
+                case SIGNATURE_WITH_DERIVED_KEY:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, wsuIdDKT);
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_APPEND_SIGNATURE_ON_THIS_ID, wsuIdDKT);
+                    break;
+                case ENCRYPT_WITH_DERIVED_KEY:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, wsuIdDKT);
+                    break;
+            }
+            outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(wsuIdDKT, derivedKeysecurityTokenProvider);
+            FinalDerivedKeyTokenOutputProcessor finalDerivedKeyTokenOutputProcessor = new FinalDerivedKeyTokenOutputProcessor(getSecurityProperties(), getAction(), derivedKeySecurityToken, offset, length, new String(Base64.encodeBase64(nonce)));
+            finalDerivedKeyTokenOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+            derivedKeySecurityToken.setProcessor(finalDerivedKeyTokenOutputProcessor);
+            outputProcessorChain.addProcessor(finalDerivedKeyTokenOutputProcessor);
+        } finally {
+            outputProcessorChain.removeProcessor(this);
+        }
+        outputProcessorChain.processEvent(xmlEvent);
+    }
+
+    class FinalDerivedKeyTokenOutputProcessor extends AbstractOutputProcessor {
+
+        private SecurityToken securityToken;
+        private int offset;
+        private int length;
+        private String nonce;
+
+        FinalDerivedKeyTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken, int offset, int length, String nonce) throws WSSecurityException {
+            super(securityProperties, action);
+            this.securityToken = securityToken;
+            this.offset = offset;
+            this.length = length;
+            this.nonce = nonce;
+        }
+
+        @Override
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+            outputProcessorChain.processEvent(xmlEvent);
+            if (xmlEvent.isStartElement()) {
+                StartElement startElement = xmlEvent.asStartElement();
+                if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                    OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+
+                    Map<QName, String> attributes = new HashMap<QName, String>();
+                    attributes.put(Constants.ATT_wsu_Id, securityToken.getId());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_DerivedKeyToken, attributes);
+
+                    createSecurityTokenReferenceStructureForDerivedKey(subOutputProcessorChain, securityToken, getSecurityProperties().getDerivedKeyKeyIdentifierType(), getSecurityProperties().getDerivedKeyTokenReference(), getSecurityProperties().isUseSingleCert());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Offset, null);
+                    createCharactersAndOutputAsEvent(subOutputProcessorChain, "" + offset);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Offset);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Length, null);
+                    createCharactersAndOutputAsEvent(subOutputProcessorChain, "" + length);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Length);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Nonce, null);
+                    createCharactersAndOutputAsEvent(subOutputProcessorChain, nonce);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Nonce);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_DerivedKeyToken);
+
+                    outputProcessorChain.removeProcessor(this);
+                }
+            }
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/DerivedKeyTokenOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptEndingOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptEndingOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptEndingOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,46 @@
+/**
+ * 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.swssf.impl.processor.output;
+
+import org.swssf.ext.*;
+
+import javax.xml.stream.XMLStreamException;
+
+/**
+ * Processor buffers encrypted XMLEvents and forwards them when final is called
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class EncryptEndingOutputProcessor extends AbstractBufferingOutputProcessor {
+
+    public EncryptEndingOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+        this.getAfterProcessors().add(EncryptOutputProcessor.class.getName());
+        this.getAfterProcessors().add(UsernameTokenOutputProcessor.class.getName());
+    }
+
+    @Override
+    protected void processHeaderEvent(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+        if (getAction() == Constants.Action.ENCRYPT_WITH_DERIVED_KEY) {
+            createReferenceListStructure(subOutputProcessorChain);
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptEndingOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision