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