/* * Atricore IDBus * * Copyright (c) 2009, Atricore Inc. * * 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.atricore.idbus.capabilities.sso.main.common.plans.actions; import oasis.names.tc.saml._2_0.assertion.AssertionType; import oasis.names.tc.saml._2_0.metadata.EntityDescriptorType; import oasis.names.tc.saml._2_0.metadata.RoleDescriptorType; import oasis.names.tc.saml._2_0.metadata.SPSSODescriptorType; import oasis.names.tc.saml._2_0.protocol.ResponseType; import oasis.names.tc.saml._2_0.protocol.StatusResponseType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.atricore.idbus.capabilities.sso.main.common.AbstractSSOMediator; import org.atricore.idbus.capabilities.sso.support.core.signature.SamlR2Signer; import org.atricore.idbus.capabilities.sso.support.metadata.SSOService; import org.atricore.idbus.kernel.main.federation.metadata.CircleOfTrustMemberDescriptor; import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptor; import org.atricore.idbus.kernel.main.mediation.channel.FederationChannel; import org.atricore.idbus.kernel.planning.IdentityArtifact; import org.jbpm.graph.exe.ExecutionContext; import java.util.ArrayList; import java.util.List; /** * @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a> * @version $Id: SignResponseAction.java 1335 2009-06-24 16:34:38Z sgonzalez $ */ public class SignResponseAction extends AbstractSSOAction { private static final Log logger = LogFactory.getLog(SignResponseAction.class); protected void doExecute(IdentityArtifact in, IdentityArtifact out, ExecutionContext executionContext) throws Exception { StatusResponseType response = (StatusResponseType) out.getContent(); FederationChannel channel = (FederationChannel) executionContext.getContextInstance().getVariable(VAR_CHANNEL); AbstractSSOMediator mediator = (AbstractSSOMediator) channel.getIdentityMediator(); SamlR2Signer signer = mediator.getSigner(); CircleOfTrustMemberDescriptor dest = (CircleOfTrustMemberDescriptor) executionContext.getContextInstance().getVariable(VAR_DESTINATION_COT_MEMBER); // If the Response can contains assertions if (response instanceof ResponseType) { // Mediator configuration as default for assertions signature boolean signAssertion = true; if (dest != null) { EntityDescriptorType entity = (EntityDescriptorType) dest.getMetadata().getEntry(); // This is the destination entity, we need to figure out the role, only SPs can request signed assertions: for (RoleDescriptorType role : entity.getRoleDescriptorOrIDPSSODescriptorOrSPSSODescriptor()) { if (role instanceof SPSSODescriptorType) { SPSSODescriptorType spRole = (SPSSODescriptorType) role; if (spRole.getWantAssertionsSigned() != null) signAssertion = spRole.getWantAssertionsSigned(); break; } } } if (((ResponseType)response).getAssertionOrEncryptedAssertion().size() > 0) { List assertions = new ArrayList(); for (Object o : ((ResponseType)response).getAssertionOrEncryptedAssertion()) { if (o instanceof AssertionType) { AssertionType assertion = (AssertionType) o; if (logger.isDebugEnabled()) logger.debug("Signing SAMLR2 Assertion: " + assertion.getID() + " in channel " + channel.getName()); // The Assertion is now enveloped within a SAML Response so we need to sign a second time within this context. assertion.setSignature(null); // If the response has an assertion, remove the signature and re-sign it ... (we're discarding STS signature!) if (signAssertion) { AssertionType signedAssertion = signer.sign(assertion); assertions.add(signedAssertion); } else { assertions.add(assertion); } } } // Replace assertions ((ResponseType)response).getAssertionOrEncryptedAssertion().clear(); ((ResponseType)response).getAssertionOrEncryptedAssertion().addAll(assertions); } } // Let's see the type of response: String element = "Response"; EndpointDescriptor ed = (EndpointDescriptor) executionContext.getContextInstance().getVariable(VAR_DESTINATION_ENDPOINT_DESCRIPTOR); if (ed != null && ed.getType() != null) { if (SSOService.SingleLogoutService.toString().equals(ed.getType())) element = "LogoutResponse"; } // TODO : Support other type of responses, // Always Sign responses if (logger.isDebugEnabled()) logger.debug("Signing SAMLR2 Response: " + response.getID() + " in channel " + channel.getName()); StatusResponseType signedResponse = signer.sign(response, element); out.replaceContent(signedResponse); } }