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 [20/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/output/EncryptOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,363 @@
+/**
+ * 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.Base64OutputStream;
+import org.swssf.config.JCEAlgorithmMapper;
+import org.swssf.ext.*;
+import org.swssf.impl.EncryptionPartDef;
+import org.swssf.impl.util.TrimmerOutputStream;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.NoSuchPaddingException;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.*;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
+/**
+ * Processor to encrypt XML structures
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class EncryptOutputProcessor extends AbstractOutputProcessor {
+
+ private List<SecurePart> secureParts;
+ private InternalEncryptionOutputProcessor activeInternalEncryptionOutputProcessor = null;
+
+ public EncryptOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+ super(securityProperties, action);
+ secureParts = securityProperties.getEncryptionSecureParts();
+ }
+
+ @Override
+ public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+ if (xmlEvent.isStartElement()) {
+ StartElement startElement = xmlEvent.asStartElement();
+
+ //avoid double encryption when child elements matches too
+ if (activeInternalEncryptionOutputProcessor == null) {
+ //find an element which matches a user configured securePart
+ Iterator<SecurePart> securePartIterator = secureParts.iterator();
+ while (securePartIterator.hasNext()) {
+ SecurePart securePart = securePartIterator.next();
+ if (securePart.getIdToSign() == null) {
+ if (startElement.getName().getLocalPart().equals(securePart.getName())
+ && startElement.getName().getNamespaceURI().equals(securePart.getNamespace())) {
+
+ logger.debug("Matched securePart for encryption");
+ InternalEncryptionOutputProcessor internalEncryptionOutputProcessor = null;
+ try {
+ String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION);
+ SecurityTokenProvider securityTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+ EncryptionPartDef encryptionPartDef = new EncryptionPartDef();
+ encryptionPartDef.setModifier(securePart.getModifier());
+ encryptionPartDef.setEncRefId("ED-" + UUID.randomUUID().toString());
+ encryptionPartDef.setKeyId(securityTokenProvider.getId());
+ encryptionPartDef.setSymmetricKey(securityTokenProvider.getSecurityToken(null).getSecretKey(getSecurityProperties().getEncryptionSymAlgorithm(), null));
+ outputProcessorChain.getSecurityContext().putAsList(EncryptionPartDef.class, encryptionPartDef);
+ internalEncryptionOutputProcessor =
+ new InternalEncryptionOutputProcessor(
+ getSecurityProperties(),
+ getAction(),
+ encryptionPartDef,
+ startElement,
+ outputProcessorChain.getDocumentContext().getEncoding()
+ );
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ } catch (NoSuchPaddingException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ } catch (InvalidKeyException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ } catch (IOException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ }
+
+ activeInternalEncryptionOutputProcessor = internalEncryptionOutputProcessor;
+ outputProcessorChain.addProcessor(internalEncryptionOutputProcessor);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ outputProcessorChain.processEvent(xmlEvent);
+ }
+
+ /**
+ * Processor which handles the effective enryption of the data
+ */
+ class InternalEncryptionOutputProcessor extends AbstractOutputProcessor {
+
+ private EncryptionPartDef encryptionPartDef;
+ private CharacterEventGeneratorOutputStream characterEventGeneratorOutputStream;
+ private XMLEventWriter xmlEventWriter;
+ private OutputStream cipherOutputStream;
+
+ private StartElement startElement;
+ private int elementCounter = 0;
+ private boolean doEncryptedHeader = false;
+ private OutputProcessorChain subOutputProcessorChain;
+
+ InternalEncryptionOutputProcessor(SecurityProperties securityProperties, Constants.Action action, EncryptionPartDef encryptionPartDef,
+ StartElement startElement, String encoding)
+ throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, XMLStreamException {
+
+ super(securityProperties, action);
+ this.getBeforeProcessors().add(EncryptEndingOutputProcessor.class.getName());
+ this.getBeforeProcessors().add(InternalEncryptionOutputProcessor.class.getName());
+ this.getAfterProcessors().add(EncryptOutputProcessor.class.getName());
+ this.encryptionPartDef = encryptionPartDef;
+ this.startElement = startElement;
+
+ //initialize the cipher
+ String jceAlgorithm = JCEAlgorithmMapper.translateURItoJCEID(securityProperties.getEncryptionSymAlgorithm());
+ Cipher symmetricCipher = Cipher.getInstance(jceAlgorithm);
+
+ //Should internally generate an IV
+ symmetricCipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey());
+ byte[] iv = symmetricCipher.getIV();
+
+ characterEventGeneratorOutputStream = new CharacterEventGeneratorOutputStream(encoding);
+ //Base64EncoderStream calls write every 78byte (line breaks). So we have to buffer again to get optimal performance
+ Base64OutputStream base64EncoderStream = new Base64OutputStream(new BufferedOutputStream(characterEventGeneratorOutputStream), true, 76, new byte[]{'\n'});
+ base64EncoderStream.write(iv);
+
+ //the trimmer output stream is needed to strip away the dummy wrapping element which must be added
+ cipherOutputStream = new TrimmerOutputStream(new CipherOutputStream(base64EncoderStream, symmetricCipher), 8192, 3, 4);
+
+ //we create a new StAX writer for optimized namespace writing.
+ XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
+ xmlOutputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
+ //spec says (4.2): "The cleartext octet sequence obtained in step 3 is interpreted as UTF-8 encoded character data."
+ xmlEventWriter = xmlOutputFactory.createXMLEventWriter(cipherOutputStream, "UTF-8");
+ //we have to output a fake element to workaround text-only encryption:
+ xmlEventWriter.add(XMLEventFactory.newFactory().createStartElement(new QName("a"), null, null));
+ }
+
+ @Override
+ public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+ if (xmlEvent.isStartElement()) {
+
+ StartElement startElement = xmlEvent.asStartElement();
+
+ if (startElement.getName().equals(this.startElement.getName()) && elementCounter == 0) {
+ //if the user selected element encryption we have to encrypt the current element-event...
+ if (encryptionPartDef.getModifier() == SecurePart.Modifier.Element) {
+ subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+ processEventInternal(subOutputProcessorChain);
+ //encrypt the current element event
+ encryptEvent(xmlEvent);
+
+ } //...the user selected content encryption, so we let pass this event as usual
+ else if (encryptionPartDef.getModifier() == SecurePart.Modifier.Content) {
+ outputProcessorChain.processEvent(xmlEvent);
+ subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+ processEventInternal(subOutputProcessorChain);
+ }
+ } else {
+ encryptEvent(xmlEvent);
+ }
+
+ elementCounter++;
+
+ } else if (xmlEvent.isEndElement()) {
+ elementCounter--;
+
+ EndElement endElement = xmlEvent.asEndElement();
+
+ if (endElement.getName().equals(this.startElement.getName()) && elementCounter == 0) {
+ if (encryptionPartDef.getModifier() == SecurePart.Modifier.Element) {
+ encryptEvent(xmlEvent);
+ doFinalInternal(subOutputProcessorChain);
+ } else {
+ doFinalInternal(subOutputProcessorChain);
+ outputAsEvent(subOutputProcessorChain, xmlEvent);
+ }
+ subOutputProcessorChain.removeProcessor(this);
+ subOutputProcessorChain = null;
+ //from now on encryption is possible again
+ activeInternalEncryptionOutputProcessor = null;
+
+ } else {
+ encryptEvent(xmlEvent);
+ }
+ } else {
+ //not an interesting start nor an interesting end element
+ //so encrypt this
+ encryptEvent(xmlEvent);
+
+ //push all buffered encrypted character events through the chain
+ Iterator<Characters> charactersIterator = characterEventGeneratorOutputStream.getCharactersBuffer().iterator();
+ while (charactersIterator.hasNext()) {
+ Characters characters = charactersIterator.next();
+ outputAsEvent(subOutputProcessorChain, characters);
+ charactersIterator.remove();
+ }
+ }
+ }
+
+ private void encryptEvent(XMLEvent xmlEvent) throws XMLStreamException {
+ xmlEventWriter.add(xmlEvent);
+ }
+
+ /**
+ * Creates the Data structure around the cipher data
+ */
+ private void processEventInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+ Map<QName, String> attributes = null;
+
+ //WSS 1.1 EncryptedHeader Element:
+ if (outputProcessorChain.getDocumentContext().getDocumentLevel() == 3
+ && outputProcessorChain.getDocumentContext().isInSOAPHeader()) {
+ doEncryptedHeader = true;
+
+ attributes = new HashMap<QName, String>();
+
+ @SuppressWarnings("unchecked")
+ Iterator<Attribute> attributeIterator = this.startElement.getAttributes();
+ while (attributeIterator.hasNext()) {
+ Attribute attribute = attributeIterator.next();
+ if (!attribute.isNamespace() &&
+ (Constants.NS_SOAP11.equals(attribute.getName().getNamespaceURI()) ||
+ Constants.NS_SOAP12.equals(attribute.getName().getNamespaceURI()))) {
+ attributes.put(attribute.getName(), attribute.getValue());
+ }
+ }
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse11_EncryptedHeader, attributes);
+ }
+
+ attributes = new HashMap<QName, String>();
+ attributes.put(Constants.ATT_NULL_Id, encryptionPartDef.getEncRefId());
+ attributes.put(Constants.ATT_NULL_Type, encryptionPartDef.getModifier().getModifier());
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptedData, attributes);
+
+ attributes = new HashMap<QName, String>();
+ attributes.put(Constants.ATT_NULL_Algorithm, securityProperties.getEncryptionSymAlgorithm());
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptionMethod, attributes);
+
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptionMethod);
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_dsig_KeyInfo, null);
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference, null);
+
+ attributes = new HashMap<QName, String>();
+ attributes.put(Constants.ATT_NULL_URI, "#" + encryptionPartDef.getKeyId());
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_Reference, attributes);
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_Reference);
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference);
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_dsig_KeyInfo);
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherData, null);
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherValue, null);
+
+ /*
+ <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncDataId-1612925417"
+ Type="http://www.w3.org/2001/04/xmlenc#Content">
+ <xenc:EncryptionMethod xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
+ Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+ <wsse:Reference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
+ URI="#EncKeyId-1483925398" />
+ </wsse:SecurityTokenReference>
+ </ds:KeyInfo>
+ <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+ <xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+ ...
+ </xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedData>
+ */
+ }
+
+ private void doFinalInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+ try {
+ xmlEventWriter.add(XMLEventFactory.newFactory().createEndElement(new QName("a"), null));
+ //close the event writer to flush all outstanding events to the encrypt stream
+ xmlEventWriter.close();
+ //call close to force a cipher.doFinal()
+ cipherOutputStream.close();
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+
+ //push all buffered encrypted character events through the chain
+ Iterator<Characters> charactersIterator = characterEventGeneratorOutputStream.getCharactersBuffer().iterator();
+ while (charactersIterator.hasNext()) {
+ Characters characters = charactersIterator.next();
+ outputAsEvent(outputProcessorChain, characters);
+ charactersIterator.remove();
+ }
+
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherValue);
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherData);
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptedData);
+
+ if (doEncryptedHeader) {
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse11_EncryptedHeader);
+ }
+ }
+ }
+
+ /**
+ * Creates Character-XMLEvents from the byte stream
+ */
+ class CharacterEventGeneratorOutputStream extends OutputStream {
+
+ private List<Characters> charactersBuffer = new Vector<Characters>();
+ private String encoding;
+
+ CharacterEventGeneratorOutputStream(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public List<Characters> getCharactersBuffer() {
+ return charactersBuffer;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ charactersBuffer.add(createCharacters(new String(new byte[]{((byte) b)}, encoding)).asCharacters());
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ charactersBuffer.add(createCharacters(new String(b, encoding)).asCharacters());
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ charactersBuffer.add(createCharacters(new String(b, off, len, encoding)).asCharacters());
+ }
+ }
+}
Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,273 @@
+/**
+ * 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.securityToken.ProcessorInfoSecurityToken;
+
+import javax.crypto.*;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class EncryptedKeyOutputProcessor extends AbstractOutputProcessor {
+
+ public EncryptedKeyOutputProcessor(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_ENCRYPTED_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);
+ }
+
+ //prepare the symmetric session key for all encryption parts
+ String keyAlgorithm = JCEAlgorithmMapper.getJCERequiredKeyFromURI(securityProperties.getEncryptionSymAlgorithm());
+ int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(securityProperties.getEncryptionSymAlgorithm());
+ KeyGenerator keyGen = null;
+ try {
+ keyGen = KeyGenerator.getInstance(keyAlgorithm);
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ }
+ keyGen.init(keyLength);
+
+ final Key symmetricKey = keyGen.generateKey();
+
+ final String ekId = "EK-" + UUID.randomUUID().toString();
+
+ final ProcessorInfoSecurityToken encryptedKeySecurityToken = new ProcessorInfoSecurityToken() {
+
+ private OutputProcessor outputProcessor;
+
+ public String getId() {
+ return ekId;
+ }
+
+ 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 {
+ return symmetricKey;
+ }
+
+ 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;
+ }
+ };
+
+ final SecurityTokenProvider encryptedKeySecurityTokenProvider = new SecurityTokenProvider() {
+ public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+ return encryptedKeySecurityToken;
+ }
+
+ public String getId() {
+ return ekId;
+ }
+ };
+
+ FinalEncryptedKeyOutputProcessor finalEncryptedKeyOutputProcessor = new FinalEncryptedKeyOutputProcessor(getSecurityProperties(), getAction(), encryptedKeySecurityToken);
+ switch (getAction()) {
+ case ENCRYPT:
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, ekId);
+ if (wrappingSecurityToken.getProcessor() != null) {
+ finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+ } else {
+ finalEncryptedKeyOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+ }
+ break;
+ case SIGNATURE_WITH_DERIVED_KEY:
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+ if (wrappingSecurityToken.getProcessor() != null) {
+ finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+ } else {
+ finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
+ }
+ break;
+ case ENCRYPT_WITH_DERIVED_KEY:
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+ if (wrappingSecurityToken.getProcessor() != null) {
+ finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+ } else {
+ finalEncryptedKeyOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+ }
+ break;
+ }
+ outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(ekId, encryptedKeySecurityTokenProvider);
+ encryptedKeySecurityToken.setProcessor(finalEncryptedKeyOutputProcessor);
+ outputProcessorChain.addProcessor(finalEncryptedKeyOutputProcessor);
+ } finally {
+ outputProcessorChain.removeProcessor(this);
+ }
+ outputProcessorChain.processEvent(xmlEvent);
+ }
+
+ class FinalEncryptedKeyOutputProcessor extends AbstractOutputProcessor {
+
+ private SecurityToken securityToken;
+
+ FinalEncryptedKeyOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken) throws WSSecurityException {
+ super(securityProperties, action);
+ this.getAfterProcessors().add(FinalEncryptedKeyOutputProcessor.class.getName());
+ this.securityToken = securityToken;
+ }
+
+ /*
+ <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncKeyId-1483925398">
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+ <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier">
+ pHoiKNGY2YsLBKxwIV+jURt858M=
+ </wsse:KeyIdentifier>
+ </wsse:SecurityTokenReference>
+ </ds:KeyInfo>
+ <xenc:CipherData>
+ <xenc:CipherValue>
+ Khsa9SN3ALNXOgGDKOqihvfwGsXb9QN/q4Fpi9uuThgz+3D4oRSMkrGSPCqwG13vddvHywGAA/XNbWNT+5Xivz3lURCDCc2H/92YlXXo/crQNJnPlLrLZ81bGOzbNo7lnYQBLp/77K7b1bhldZAeV9ZfEW7DjbOMZ+k1dnDCu3A=
+ </xenc:CipherValue>
+ </xenc:CipherData>
+ <xenc:ReferenceList>
+ <xenc:DataReference URI="#EncDataId-1612925417" />
+ </xenc:ReferenceList>
+ </xenc:EncryptedKey>
+ */
+
+ @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);
+
+ X509Certificate x509Certificate = securityToken.getKeyWrappingToken().getX509Certificates()[0];
+
+ Map<QName, String> attributes = new HashMap<QName, String>();
+ attributes.put(Constants.ATT_NULL_Id, securityToken.getId());
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptedKey, attributes);
+
+ attributes = new HashMap<QName, String>();
+ attributes.put(Constants.ATT_NULL_Algorithm, getSecurityProperties().getEncryptionKeyTransportAlgorithm());
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptionMethod, attributes);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptionMethod);
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_dsig_KeyInfo, null);
+ createSecurityTokenReferenceStructureForEncryptedKey(subOutputProcessorChain, securityToken, getSecurityProperties().getEncryptionKeyIdentifierType(), getSecurityProperties().isUseSingleCert());
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_dsig_KeyInfo);
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherData, null);
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherValue, null);
+
+ try {
+ //encrypt the symmetric session key with the public key from the receiver:
+ String jceid = JCEAlgorithmMapper.translateURItoJCEID(getSecurityProperties().getEncryptionKeyTransportAlgorithm());
+ Cipher cipher = Cipher.getInstance(jceid);
+ cipher.init(Cipher.ENCRYPT_MODE, x509Certificate);
+
+ byte[] ephemeralKey = securityToken.getSecretKey(null, null).getEncoded();
+
+ int blockSize = cipher.getBlockSize();
+ if (blockSize > 0 && blockSize < ephemeralKey.length) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "unsupportedKeyTransp", "public key algorithm too weak to encrypt symmetric key"
+ );
+ }
+ byte[] encryptedEphemeralKey = cipher.doFinal(ephemeralKey);
+
+ createCharactersAndOutputAsEvent(subOutputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(encryptedEphemeralKey));
+
+ } catch (NoSuchPaddingException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ } catch (InvalidKeyException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ } catch (BadPaddingException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ } catch (IllegalBlockSizeException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+ }
+
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherValue);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherData);
+
+ if (getAction() == Constants.Action.ENCRYPT) {
+ createReferenceListStructure(subOutputProcessorChain);
+ }
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptedKey);
+ outputProcessorChain.removeProcessor(this);
+ }
+ }
+ }
+ }
+}
Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,69 @@
+/**
+ * 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.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import java.io.OutputStream;
+
+/**
+ * Processor which outputs the XMLEvents to an outputStream
+ * This Processor can be extended to allow to write to a StAX writer instead of directly to an output stream
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class FinalOutputProcessor extends AbstractOutputProcessor {
+
+ private XMLEventWriter xmlEventWriter;
+ private static final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
+
+ static {
+ xmlOutputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
+ }
+
+ public FinalOutputProcessor(OutputStream outputStream, String encoding, SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+ super(securityProperties, action);
+ setPhase(Constants.Phase.POSTPROCESSING);
+ try {
+ xmlEventWriter = xmlOutputFactory.createXMLEventWriter(outputStream, encoding);
+ } catch (XMLStreamException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+ }
+ }
+
+ @Override
+ public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+ xmlEventWriter.add(xmlEvent);
+ }
+
+ @Override
+ public void doFinal(OutputProcessorChain outputProcessorChain) throws WSSecurityException {
+ try {
+ xmlEventWriter.flush();
+ xmlEventWriter.close();
+ } catch (XMLStreamException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+ }
+ }
+}
Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,332 @@
+/**
+ * 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.opensaml.common.SAMLVersion;
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.saml.OpenSAMLUtil;
+import org.swssf.impl.saml.SAMLAssertionWrapper;
+import org.swssf.impl.saml.SAMLCallback;
+import org.swssf.impl.saml.SAMLKeyInfo;
+import org.swssf.impl.saml.bean.KeyInfoBean;
+import org.swssf.impl.saml.bean.SubjectBean;
+import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+import org.swssf.impl.securityToken.SAMLSecurityToken;
+import org.w3c.dom.*;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SAMLTokenOutputProcessor extends AbstractOutputProcessor {
+
+ public SAMLTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+ super(securityProperties, action);
+ }
+
+ @Override
+ public void processEvent(XMLEvent xmlEvent, final OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+ try {
+ final SAMLCallback samlCallback = new SAMLCallback();
+ Utils.doPasswordCallback(getSecurityProperties().getCallbackHandler(), samlCallback);
+ SAMLAssertionWrapper samlAssertionWrapper = new SAMLAssertionWrapper(samlCallback);
+
+ boolean senderVouches = false;
+ List<String> methods = samlAssertionWrapper.getConfirmationMethods();
+ if (methods != null && methods.size() > 0) {
+ String confirmMethod = methods.get(0);
+ if (OpenSAMLUtil.isMethodSenderVouches(confirmMethod)) {
+ senderVouches = true;
+ }
+ }
+
+ final String securityTokenReferenceId = "STRSAMLId-" + UUID.randomUUID().toString();
+ final String binarySecurityTokenId = "BST-" + UUID.randomUUID().toString();
+ final String tokenId = samlAssertionWrapper.getId();
+
+ PrivateKey privateKey = null;
+ X509Certificate[] certificates = null;
+
+ if (senderVouches) {
+ // prepare to sign the SAML token
+ certificates = samlCallback.getIssuerCrypto().getCertificates(samlCallback.getIssuerKeyName());
+ if (certificates == null) {
+ throw new WSSecurityException(
+ "No issuer certs were found to sign the SAML Assertion using issuer name: "
+ + samlCallback.getIssuerKeyName()
+ );
+ }
+ try {
+ privateKey = samlCallback.getIssuerCrypto().getPrivateKey(samlCallback.getIssuerKeyName(), samlCallback.getIssuerKeyPassword());
+ } catch (Exception ex) {
+ throw new WSSecurityException(ex.getMessage(), ex);
+ }
+ } else {
+ SubjectBean subjectBean = samlCallback.getSubject();
+ if (subjectBean != null) {
+ KeyInfoBean keyInfoBean = subjectBean.getKeyInfo();
+ if (keyInfoBean != null) {
+ X509Certificate x509Certificate = keyInfoBean.getCertificate();
+ if (x509Certificate != null) {
+ String alias = getSecurityProperties().getSignatureCrypto().getAliasForX509Cert(x509Certificate);
+ if (alias == null) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "aliasIsNull");
+ }
+ WSPasswordCallback wsPasswordCallback = new WSPasswordCallback(alias, WSPasswordCallback.Usage.SIGNATURE);
+ Utils.doPasswordCallback(getSecurityProperties().getCallbackHandler(), wsPasswordCallback);
+ certificates = getSecurityProperties().getSignatureCrypto().getCertificates(alias);
+ privateKey = getSecurityProperties().getSignatureCrypto().getPrivateKey(alias, wsPasswordCallback.getPassword());
+ }
+ }
+ }
+ }
+
+ final SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(certificates);
+ samlKeyInfo.setPublicKey(certificates[0].getPublicKey());
+ samlKeyInfo.setPrivateKey(privateKey);
+
+ final X509Certificate[] x509Certificates;
+ if (certificates != null && certificates.length > 0) {
+ x509Certificates = certificates;
+ } else {
+ x509Certificates = null;
+ }
+
+ final PrivateKey secretKey = privateKey;
+
+ final SecurityToken securityToken;
+ SecurityTokenProvider securityTokenProvider;
+ if (senderVouches) {
+ securityToken = new ProcessorInfoSecurityToken() {
+
+ private OutputProcessor outputProcessor;
+
+ public void setProcessor(OutputProcessor outputProcessor) {
+ this.outputProcessor = outputProcessor;
+ }
+
+ public String getId() {
+ return binarySecurityTokenId;
+ }
+
+ public Object getProcessor() {
+ return outputProcessor;
+ }
+
+ public boolean isAsymmetric() {
+ return true;
+ }
+
+ public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+ return secretKey;
+ }
+
+ 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() {
+ //todo pkiPathToken etc?
+ return Constants.TokenType.X509V3Token;
+ }
+ };
+ } else {
+ securityToken = null;
+ }
+
+ final FinalSAMLTokenOutputProcessor finalSAMLTokenOutputProcessor = new FinalSAMLTokenOutputProcessor(getSecurityProperties(), getAction(), securityToken, samlAssertionWrapper, securityTokenReferenceId, binarySecurityTokenId, senderVouches);
+
+ if (senderVouches) {
+
+ securityTokenProvider = new SecurityTokenProvider() {
+ public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+ return securityToken;
+ }
+
+ public String getId() {
+ return binarySecurityTokenId;
+ }
+ };
+
+ outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(binarySecurityTokenId, securityTokenProvider);
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, binarySecurityTokenId);
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_APPEND_SIGNATURE_ON_THIS_ID, securityTokenReferenceId);
+ } else {
+ securityTokenProvider = new SecurityTokenProvider() {
+ public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+ return new SAMLSecurityToken(samlCallback.getSamlVersion(), samlKeyInfo, outputProcessorChain.getSecurityContext(), crypto, getSecurityProperties().getCallbackHandler(), tokenId, finalSAMLTokenOutputProcessor);
+ }
+
+ public String getId() {
+ return tokenId;
+ }
+ };
+
+ outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(tokenId, securityTokenProvider);
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, tokenId);
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_APPEND_SIGNATURE_ON_THIS_ID, tokenId);
+ }
+
+
+ switch (getAction()) {
+ case SAML_TOKEN_SIGNED:
+ if (senderVouches) {
+ SecurePart securePart = new SecurePart(Constants.SOAPMESSAGE_NS10_STRTransform, null, SecurePart.Modifier.Element, tokenId, securityTokenReferenceId);
+ outputProcessorChain.getSecurityContext().putAsList(SecurePart.class, securePart);
+ }
+ break;
+ case SAML_TOKEN_UNSIGNED:
+ break;
+ }
+ outputProcessorChain.addProcessor(finalSAMLTokenOutputProcessor);
+ } finally {
+ outputProcessorChain.removeProcessor(this);
+ }
+ outputProcessorChain.processEvent(xmlEvent);
+ }
+
+ class FinalSAMLTokenOutputProcessor extends AbstractOutputProcessor {
+
+ private SecurityToken securityToken;
+ private SAMLAssertionWrapper samlAssertionWrapper;
+ private String securityTokenReferenceId;
+ private String binarySecurityTokenReferenceId;
+ private boolean senderVouches = false;
+
+ FinalSAMLTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken, SAMLAssertionWrapper samlAssertionWrapper, String securityTokenReferenceId, String binarySecurityTokenReferenceId, boolean senderVouches)
+ throws WSSecurityException {
+ super(securityProperties, action);
+ this.getAfterProcessors().add(UsernameTokenOutputProcessor.class.getName());
+ this.getAfterProcessors().add(SAMLTokenOutputProcessor.class.getName());
+ this.samlAssertionWrapper = samlAssertionWrapper;
+ this.securityTokenReferenceId = securityTokenReferenceId;
+ this.senderVouches = senderVouches;
+ this.binarySecurityTokenReferenceId = binarySecurityTokenReferenceId;
+ 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);
+ if (senderVouches && getSecurityProperties().getSignatureKeyIdentifierType() == Constants.KeyIdentifierType.BST_DIRECT_REFERENCE) {
+ outputBinarySecurityToken(outputProcessorChain, binarySecurityTokenReferenceId, securityToken.getX509Certificates(), getSecurityProperties().isUseSingleCert());
+ }
+ outputSamlAssertion(samlAssertionWrapper.toDOM(null), subOutputProcessorChain);
+ if (senderVouches) {
+ outputSecurityTokenReference(subOutputProcessorChain, samlAssertionWrapper, securityTokenReferenceId, samlAssertionWrapper.getId());
+ }
+ outputProcessorChain.removeProcessor(this);
+ }
+ }
+ }
+ }
+
+ private void outputSecurityTokenReference(OutputProcessorChain outputProcessorChain, SAMLAssertionWrapper samlAssertionWrapper, String referenceId, String tokenId) throws XMLStreamException, WSSecurityException {
+ Map<QName, String> attributes = new HashMap<QName, String>();
+ if (samlAssertionWrapper.getSAMLVersion() == SAMLVersion.VERSION_11) {
+ attributes.put(Constants.ATT_wsse11_TokenType, Constants.NS_SAML11_TOKEN_PROFILE_TYPE);
+ } else {
+ attributes.put(Constants.ATT_wsse11_TokenType, Constants.NS_SAML20_TOKEN_PROFILE_TYPE);
+ }
+ attributes.put(Constants.ATT_wsu_Id, referenceId);
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference, attributes);
+ attributes = new HashMap<QName, String>();
+ if (samlAssertionWrapper.getSAMLVersion() == SAMLVersion.VERSION_11) {
+ attributes.put(Constants.ATT_NULL_ValueType, Constants.NS_SAML10_TYPE);
+ } else {
+ attributes.put(Constants.ATT_NULL_ValueType, Constants.NS_SAML20_TYPE);
+ }
+ createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_KeyIdentifier, attributes);
+ createCharactersAndOutputAsEvent(outputProcessorChain, tokenId);
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_KeyIdentifier);
+ createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference);
+ }
+
+ private void outputBinarySecurityToken(OutputProcessorChain outputProcessorChain, String referenceId, X509Certificate[] x509Certificates, boolean useSingleCertificate) throws XMLStreamException, WSSecurityException {
+ createBinarySecurityTokenStructure(outputProcessorChain, referenceId, x509Certificates, useSingleCertificate);
+ }
+
+ //todo serialize directly from SAML XMLObject?
+ private void outputSamlAssertion(Element element, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+ Map<QName, String> attributes = new HashMap<QName, String>();
+ Map<QName, String> namespaces = new HashMap<QName, String>();
+ NamedNodeMap namedNodeMap = element.getAttributes();
+ for (int i = 0; i < namedNodeMap.getLength(); i++) {
+ Attr attribute = (Attr) namedNodeMap.item(i);
+ if ("xmlns".equals(attribute.getPrefix()) || "xmlns".equals(attribute.getLocalName())) {
+ namespaces.put(new QName(attribute.getNamespaceURI(), attribute.getLocalName(), attribute.getPrefix()), attribute.getValue());
+ } else if (attribute.getPrefix() == null) {
+ attributes.put(new QName(attribute.getNamespaceURI(), attribute.getLocalName()), attribute.getValue());
+ } else {
+ attributes.put(new QName(attribute.getNamespaceURI(), attribute.getLocalName(), attribute.getPrefix()), attribute.getValue());
+ }
+ }
+
+ QName elementName = new QName(element.getNamespaceURI(), element.getLocalName(), element.getPrefix());
+ createStartElementAndOutputAsEvent(outputProcessorChain, elementName, namespaces, attributes);
+ NodeList childNodes = element.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node childNode = childNodes.item(i);
+ switch (childNode.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ outputSamlAssertion((Element) childNode, outputProcessorChain);
+ break;
+ case Node.TEXT_NODE:
+ createCharactersAndOutputAsEvent(outputProcessorChain, ((Text) childNode).getData());
+ break;
+ }
+ }
+ createEndElementAndOutputAsEvent(outputProcessorChain, elementName);
+ }
+}
Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,186 @@
+/**
+ * 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.ProcessorInfoSecurityToken;
+
+import javax.xml.namespace.QName;
+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.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SecurityContextTokenOutputProcessor extends AbstractOutputProcessor {
+
+ public SecurityContextTokenOutputProcessor(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_SECURITYCONTEXTTOKEN);
+ 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 wsuId = "SCT-" + UUID.randomUUID().toString();
+ final String identifier = UUID.randomUUID().toString();
+
+ final ProcessorInfoSecurityToken securityContextSecurityToken = new ProcessorInfoSecurityToken() {
+
+ private OutputProcessor outputProcessor;
+
+ public String getId() {
+ return wsuId;
+ }
+
+ public void setProcessor(OutputProcessor outputProcessor) {
+ this.outputProcessor = outputProcessor;
+ }
+
+ public Object getProcessor() {
+ return outputProcessor;
+ }
+
+ public boolean isAsymmetric() {
+ return wrappingSecurityToken.isAsymmetric();
+ }
+
+ public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+ return wrappingSecurityToken.getSecretKey(algorithmURI, keyUsage);
+ }
+
+ public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+ return wrappingSecurityToken.getPublicKey(keyUsage);
+ }
+
+ public X509Certificate[] getX509Certificates() throws WSSecurityException {
+ return wrappingSecurityToken.getX509Certificates();
+ }
+
+ public void verify() throws WSSecurityException {
+ wrappingSecurityToken.verify();
+ }
+
+ public SecurityToken getKeyWrappingToken() {
+ return wrappingSecurityToken;
+ }
+
+ public String getKeyWrappingTokenAlgorithm() {
+ return null;
+ }
+
+ public Constants.TokenType getTokenType() {
+ return Constants.TokenType.SecurityContextToken;
+ }
+ };
+
+ SecurityTokenProvider securityContextSecurityTokenProvider = new SecurityTokenProvider() {
+ public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+ return securityContextSecurityToken;
+ }
+
+ public String getId() {
+ return wsuId;
+ }
+ };
+
+ FinalSecurityContextTokenOutputProcessor finalSecurityContextTokenOutputProcessor = new FinalSecurityContextTokenOutputProcessor(getSecurityProperties(), getAction(), securityContextSecurityToken, identifier);
+ switch (getAction()) {
+ case SIGNATURE_WITH_DERIVED_KEY:
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, wsuId);
+ if (wrappingSecurityToken.getProcessor() != null) {
+ finalSecurityContextTokenOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+ } else {
+ finalSecurityContextTokenOutputProcessor.getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
+ }
+ break;
+ case ENCRYPT_WITH_DERIVED_KEY:
+ outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, wsuId);
+ if (wrappingSecurityToken.getProcessor() != null) {
+ finalSecurityContextTokenOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+ } else {
+ finalSecurityContextTokenOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+ }
+ break;
+ }
+
+ outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(wsuId, securityContextSecurityTokenProvider);
+ securityContextSecurityToken.setProcessor(finalSecurityContextTokenOutputProcessor);
+ outputProcessorChain.addProcessor(finalSecurityContextTokenOutputProcessor);
+
+ } finally {
+ outputProcessorChain.removeProcessor(this);
+ }
+ outputProcessorChain.processEvent(xmlEvent);
+ }
+
+ class FinalSecurityContextTokenOutputProcessor extends AbstractOutputProcessor {
+
+ private SecurityToken securityToken;
+ private String identifier;
+
+ FinalSecurityContextTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken, String identifier) throws WSSecurityException {
+ super(securityProperties, action);
+ this.securityToken = securityToken;
+ this.identifier = identifier;
+ }
+
+ @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_SecurityContextToken, attributes);
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Identifier, null);
+ createCharactersAndOutputAsEvent(subOutputProcessorChain, identifier);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Identifier);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_SecurityContextToken);
+
+ outputProcessorChain.removeProcessor(this);
+ }
+ }
+ }
+ }
+}
Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,139 @@
+/**
+ * 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.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Processor to build the Security Header structure
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SecurityHeaderOutputProcessor extends AbstractOutputProcessor {
+
+ public SecurityHeaderOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+ super(securityProperties, action);
+ setPhase(Constants.Phase.PREPROCESSING);
+ }
+
+ @Override
+ public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+ boolean eventHandled = false;
+ int level = outputProcessorChain.getDocumentContext().getDocumentLevel();
+
+ String soapMessageVersion = outputProcessorChain.getDocumentContext().getSOAPMessageVersionNamespace();
+
+ if (xmlEvent.isStartElement()) {
+ StartElement startElement = xmlEvent.asStartElement();
+
+ if (level == 1 && soapMessageVersion == null) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "notASOAPMessage");
+ } else if (level == 1 && soapMessageVersion != null) {
+ //set correct namespace on secure parts
+ List<SecurePart> securePartList = securityProperties.getEncryptionSecureParts();
+ for (int i = 0; i < securePartList.size(); i++) {
+ SecurePart securePart = securePartList.get(i);
+ if (securePart.getName().equals("Body") && securePart.getNamespace().equals("*")) {
+ securePart.setNamespace(soapMessageVersion);
+ break;
+ }
+ }
+ securePartList = securityProperties.getSignatureSecureParts();
+ for (int j = 0; j < securePartList.size(); j++) {
+ SecurePart securePart = securePartList.get(j);
+ if (securePart.getName().equals("Body") && securePart.getNamespace().equals("*")) {
+ securePart.setNamespace(soapMessageVersion);
+ }
+ }
+ } else if (level == 3 && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+ if (Utils.isResponsibleActorOrRole(startElement, soapMessageVersion, getSecurityProperties().getActor())) {
+ outputProcessorChain.getDocumentContext().setInSecurityHeader(true);
+ //remove this processor. its no longer needed.
+ outputProcessorChain.removeProcessor(this);
+ }
+ } else if (level == 2
+ && startElement.getName().getLocalPart().equals(Constants.TAG_soap_Body_LocalName)
+ && startElement.getName().getNamespaceURI().equals(soapMessageVersion)) {
+ //hmm it seems we don't have a soap header in the current document
+ //so output one and add securityHeader
+
+ //create subchain and output soap-header and securityHeader
+ OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+ createStartElementAndOutputAsEvent(subOutputProcessorChain,
+ new QName(soapMessageVersion, Constants.TAG_soap_Header_LocalName, Constants.PREFIX_SOAPENV), null);
+ buildSecurityHeader(soapMessageVersion, subOutputProcessorChain);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain,
+ new QName(soapMessageVersion, Constants.TAG_soap_Header_LocalName, Constants.PREFIX_SOAPENV));
+
+ //output current soap-header event
+ outputProcessorChain.processEvent(xmlEvent);
+ //remove this processor. its no longer needed.
+ outputProcessorChain.removeProcessor(this);
+
+ eventHandled = true;
+ }
+ } else if (xmlEvent.isEndElement()) {
+ EndElement endElement = xmlEvent.asEndElement();
+ if (level == 2 && endElement.getName().equals(Constants.TAG_wsse_Security)) {
+ outputProcessorChain.getDocumentContext().setInSecurityHeader(false);
+ } else if (level == 1 && endElement.getName().getLocalPart().equals(Constants.TAG_soap_Header_LocalName)
+ && endElement.getName().getNamespaceURI().equals(soapMessageVersion)) {
+ OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+ buildSecurityHeader(soapMessageVersion, subOutputProcessorChain);
+ //output current soap-header event
+ outputProcessorChain.processEvent(xmlEvent);
+ //remove this processor. its no longer needed.
+ outputProcessorChain.removeProcessor(this);
+
+ eventHandled = true;
+ }
+ }
+
+ if (!eventHandled) {
+ outputProcessorChain.processEvent(xmlEvent);
+ }
+ }
+
+ private void buildSecurityHeader(String soapMessageVersion, OutputProcessorChain subOutputProcessorChain) throws XMLStreamException, WSSecurityException {
+ Map<QName, String> attributes = new HashMap<QName, String>();
+ final String actor = getSecurityProperties().getActor();
+ if (actor != null && !"".equals(actor)) {
+ if (Constants.NS_SOAP11.equals(soapMessageVersion)) {
+ attributes.put(Constants.ATT_soap11_Actor, actor);
+ } else {
+ attributes.put(Constants.ATT_soap12_Role, actor);
+ }
+ }
+ subOutputProcessorChain.getDocumentContext().setInSecurityHeader(true);
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse_Security, attributes);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse_Security);
+ subOutputProcessorChain.getDocumentContext().setInSecurityHeader(false);
+ }
+}
Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,83 @@
+/**
+ * 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.ext.*;
+import org.swssf.securityEvent.SecurityEvent;
+import org.swssf.securityEvent.SignatureTokenSecurityEvent;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SignatureConfirmationOutputProcessor extends AbstractOutputProcessor {
+
+ public SignatureConfirmationOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+ super(securityProperties, action);
+ getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
+ getBeforeProcessors().add(EncryptOutputProcessor.class.getName());
+ }
+
+ @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 aSignatureFound = false;
+
+ List<SecurityEvent> requestSecurityEvents = outputProcessorChain.getSecurityContext().getAsList(SecurityEvent.class);
+ for (int i = 0; i < requestSecurityEvents.size(); i++) {
+ SecurityEvent securityEvent = requestSecurityEvents.get(i);
+ if (securityEvent.getSecurityEventType() == SecurityEvent.Event.SignatureToken) {
+ aSignatureFound = true;
+ SignatureTokenSecurityEvent signatureTokenSecurityEvent = (SignatureTokenSecurityEvent) securityEvent;
+
+ Map<QName, String> attributes = new HashMap<QName, String>();
+ attributes.put(Constants.ATT_wsu_Id, "SigConf-" + UUID.randomUUID().toString());
+ attributes.put(Constants.ATT_NULL_Value, new Base64(76, new byte[]{'\n'}).encodeToString(signatureTokenSecurityEvent.getSignatureValue()));
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation, attributes);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation);
+ }
+ }
+
+ if (!aSignatureFound) {
+ Map<QName, String> attributes = new HashMap<QName, String>();
+ attributes.put(Constants.ATT_wsu_Id, "SigConf-" + UUID.randomUUID().toString());
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation, attributes);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation);
+ }
+
+ outputProcessorChain.removeProcessor(this);
+ }
+ }
+ }
+}
Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision