/* * JBoss, Home of Professional Open Source. Copyright 2008, Red Hat Middleware LLC, and individual contributors as * indicated by the @author tags. See the copyright.txt file in the distribution for a full listing of individual * contributors. * * This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any * later version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: * http://www.fsf.org. */ package org.picketlink.identity.federation.core.wstrust.writers; import org.picketlink.common.ErrorCodes; import org.picketlink.common.PicketLinkLogger; import org.picketlink.common.PicketLinkLoggerFactory; import org.picketlink.common.constants.WSTrustConstants; import org.picketlink.common.exceptions.ProcessingException; import org.picketlink.common.util.StaxUtil; import org.picketlink.common.util.StringUtil; import org.picketlink.identity.federation.core.saml.v2.writers.SAMLAssertionWriter; import org.picketlink.identity.federation.core.wstrust.wrappers.Lifetime; import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenResponse; import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityTokenResponseCollection; import org.picketlink.identity.federation.saml.v2.assertion.AssertionType; import org.picketlink.identity.federation.ws.trust.BinarySecretType; import org.picketlink.identity.federation.ws.trust.ComputedKeyType; import org.picketlink.identity.federation.ws.trust.EntropyType; import org.picketlink.identity.federation.ws.trust.RenewingType; import org.picketlink.identity.federation.ws.trust.RequestedProofTokenType; import org.picketlink.identity.federation.ws.trust.RequestedReferenceType; import org.picketlink.identity.federation.ws.trust.StatusType; import org.w3c.dom.Element; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.Result; import java.io.OutputStream; import java.util.List; /** * <p> * A Stax writer for WS-Trust response messages. * </p> * * @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a> */ public class WSTrustResponseWriter { private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private final XMLStreamWriter writer; /** * <p> * Creates a {@code WSTrustResponseWriter} instance that writes WS-Trust response messages to the specified * {@code OutputStream}. * </p> * * @param stream the where the response is to be written. * * @throws ProcessingException if an error occurs when creating the {@code XMLStreamWriter} for the specified * stream. */ public WSTrustResponseWriter(OutputStream stream) throws ProcessingException { this.writer = StaxUtil.getXMLStreamWriter(stream); } /** * <p> * Creates a {@code WSTrustResponseWriter} instance that writes WS-Trust response messages to the specified {@code * Result}. * </p> * * @param result the {@code Result} object where the response is to be written. * * @throws ProcessingException if an error occurs when creating the {@code XMLStreamWriter} for the specified * result. */ public WSTrustResponseWriter(Result result) throws ProcessingException { this.writer = StaxUtil.getXMLStreamWriter(result); } /** * <p> * Creates a {@code WSTrustResponseWriter} instance that uses the specified {@code XMLStreamWriter} to write the * WS-Trust * response messages. * </p> * * @param writer the {@code XMLStreamWriter} that will be used to write the response messages. */ public WSTrustResponseWriter(XMLStreamWriter writer) { this.writer = writer; } /** * <p> * Writes the WS-Trust response message represented by the specified {@code RequestSecurityTokenResponseCollection} * object. * </p> * * @param collection the object that contains the WS-Trust response message to be written. * * @throws ProcessingException if an error occurs while writing the response message. */ public void write(RequestSecurityTokenResponseCollection collection) throws ProcessingException { // write the "root" response collection element with its namespace. StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.RSTR_COLLECTION, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeNameSpace(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.BASE_NAMESPACE); // write all individual response messages. List<RequestSecurityTokenResponse> responses = collection.getRequestSecurityTokenResponses(); if (responses == null) throw new ProcessingException(ErrorCodes.NULL_VALUE + "WS-Trust response message doesn't contain any response"); for (RequestSecurityTokenResponse response : responses) this.write(response); // write the response collection end element. StaxUtil.writeEndElement(this.writer); StaxUtil.flush(this.writer); } private void write(RequestSecurityTokenResponse response) throws ProcessingException { // write the response element and the context attribute. StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.RSTR, WSTrustConstants.BASE_NAMESPACE); String context = response.getContext(); StaxUtil.writeAttribute(this.writer, WSTrustConstants.RST_CONTEXT, context); // write the token type, if available. if (response.getTokenType() != null) { StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.TOKEN_TYPE, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeCharacters(this.writer, response.getTokenType().toASCIIString()); StaxUtil.writeEndElement(this.writer); } // write the token lifetime, if available. if (response.getLifetime() != null) { Lifetime lifetime = response.getLifetime(); StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.LIFETIME, WSTrustConstants.BASE_NAMESPACE); new WSSecurityWriter(this.writer).writeLifetime(lifetime.getCreated(), lifetime.getExpires()); StaxUtil.writeEndElement(this.writer); } // write the applies-to element, if available. if (response.getAppliesTo() != null) { WSPolicyWriter policyWriter = new WSPolicyWriter(this.writer); policyWriter.write(response.getAppliesTo()); } // write the key size, if available. if (response.getKeySize() != 0) { StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.KEY_SIZE, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeCharacters(this.writer, Long.toString(response.getKeySize())); StaxUtil.writeEndElement(this.writer); } // write the key type, if available. if (response.getKeyType() != null) { StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.KEY_TYPE, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeCharacters(this.writer, response.getKeyType().toString()); StaxUtil.writeEndElement(this.writer); } // write the security token, if available. if (response.getRequestedSecurityToken() != null) { StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.REQUESTED_TOKEN, WSTrustConstants.BASE_NAMESPACE); List<Object> theList = response.getRequestedSecurityToken().getAny(); for (Object securityToken : theList) { if (securityToken instanceof AssertionType) { AssertionType assertion = (AssertionType) securityToken; SAMLAssertionWriter samlAssertionWriter = new SAMLAssertionWriter(this.writer); samlAssertionWriter.write(assertion); } else if (securityToken instanceof Element) { StaxUtil.writeDOMElement(this.writer, (Element) securityToken); } else throw logger.writerUnknownTypeError(securityToken.getClass().getName()); } /* * Object securityToken = response.getRequestedSecurityToken().getAny(); if (securityToken != null) { if * (securityToken instanceof AssertionType) { AssertionType assertion = (AssertionType) securityToken; * SAMLAssertionWriter samlAssertionWriter = new SAMLAssertionWriter(this.writer); * samlAssertionWriter.write(assertion); } else if (securityToken instanceof Element) { * StaxUtil.writeDOMElement(this.writer, (Element) securityToken); } else throw new * ProcessingException("Unknown security token type=" + securityToken.getClass().getName()); } */ StaxUtil.writeEndElement(this.writer); } // write the attached reference, if available. if (response.getRequestedAttachedReference() != null) { RequestedReferenceType ref = response.getRequestedAttachedReference(); StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.REQUESTED_ATTACHED_REFERENCE, WSTrustConstants.BASE_NAMESPACE); new WSSecurityWriter(this.writer).writeSecurityTokenReference(ref.getSecurityTokenReference()); StaxUtil.writeEndElement(this.writer); } // write the unattached reference, if available. if (response.getRequestedUnattachedReference() != null) { RequestedReferenceType ref = response.getRequestedUnattachedReference(); StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.REQUESTED_UNATTACHED_REFERENCE, WSTrustConstants.BASE_NAMESPACE); new WSSecurityWriter(this.writer).writeSecurityTokenReference(ref.getSecurityTokenReference()); StaxUtil.writeEndElement(this.writer); } // write the requested proof token, if available. if (response.getRequestedProofToken() != null) { RequestedProofTokenType requestedProof = response.getRequestedProofToken(); StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.REQUESTED_PROOF_TOKEN, WSTrustConstants.BASE_NAMESPACE); List<Object> theList = requestedProof.getAny(); for (Object content : theList) { if (content instanceof BinarySecretType) { BinarySecretType binarySecret = (BinarySecretType) content; StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.BINARY_SECRET, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeAttribute(this.writer, WSTrustConstants.TYPE, binarySecret.getType()); StaxUtil.writeCharacters(this.writer, new String(binarySecret.getValue())); StaxUtil.writeEndElement(this.writer); } else if (content instanceof ComputedKeyType) { ComputedKeyType computedKey = (ComputedKeyType) content; StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.COMPUTED_KEY, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeCharacters(this.writer, computedKey.getAlgorithm()); StaxUtil.writeEndElement(this.writer); } else throw new ProcessingException(ErrorCodes.UNSUPPORTED_TYPE + content); } StaxUtil.writeEndElement(this.writer); } // write the server entropy, if available. if (response.getEntropy() != null) { EntropyType entropy = response.getEntropy(); StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.ENTROPY, WSTrustConstants.BASE_NAMESPACE); List<Object> entropyList = entropy.getAny(); if (entropyList != null && entropyList.size() != 0) { for (Object entropyObj : entropyList) { if (entropyObj instanceof BinarySecretType) { BinarySecretType binarySecret = (BinarySecretType) entropyObj; StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.BINARY_SECRET, WSTrustConstants.BASE_NAMESPACE); if (binarySecret.getType() != null) { StaxUtil.writeAttribute(this.writer, WSTrustConstants.TYPE, binarySecret.getType()); } StaxUtil.writeCharacters(this.writer, new String(binarySecret.getValue())); StaxUtil.writeEndElement(this.writer); } } } StaxUtil.writeEndElement(writer); } // write the validation status, if available. if (response.getStatus() != null) { StatusType status = response.getStatus(); StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.STATUS, WSTrustConstants.BASE_NAMESPACE); // write the status code. if (StringUtil.isNullOrEmpty(status.getCode())) { throw logger.wsTrustValidationStatusCodeMissing(); } StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.CODE, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeCharacters(this.writer, response.getStatus().getCode()); StaxUtil.writeEndElement(this.writer); // write the status reason, if available. if (status.getReason() != null) { StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.REASON, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeCharacters(this.writer, response.getStatus().getReason()); StaxUtil.writeEndElement(this.writer); } // write the status end element. StaxUtil.writeEndElement(this.writer); } // write the cancel status, if available. if (response.getRequestedTokenCancelled() != null) { StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.REQUESTED_TOKEN_CANCELLED, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeEndElement(this.writer); } if (response.getRenewing() != null) { RenewingType renewingType = response.getRenewing(); StaxUtil.writeStartElement(this.writer, WSTrustConstants.PREFIX, WSTrustConstants.RENEWING, WSTrustConstants.BASE_NAMESPACE); StaxUtil.writeAttribute(this.writer, WSTrustConstants.ALLOW, "" + renewingType.isAllow()); StaxUtil.writeAttribute(this.writer, WSTrustConstants.OK, "" + renewingType.isOK()); StaxUtil.writeEndElement(this.writer); } // write the response end element. StaxUtil.writeEndElement(this.writer); StaxUtil.flush(writer); } }