/** * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: FSAssertionConsumerService.java,v 1.3 2008/06/25 05:46:57 qcheng Exp $ * */ package com.sun.identity.federation.services.fednsso; import com.sun.identity.federation.common.FSException; import com.sun.identity.federation.common.FSUtils; import com.sun.identity.federation.common.IFSConstants; import com.sun.identity.federation.common.LogUtil; import com.sun.identity.federation.jaxb.entityconfig.BaseConfigType; import com.sun.identity.federation.key.KeyUtil; import com.sun.identity.federation.message.FSAssertionArtifact; import com.sun.identity.federation.message.FSAuthnRequest; import com.sun.identity.federation.message.FSAuthnResponse; import com.sun.identity.federation.message.FSRequest; import com.sun.identity.federation.message.common.FSMsgException; import com.sun.identity.federation.meta.IDFFMetaManager; import com.sun.identity.federation.meta.IDFFMetaUtils; import com.sun.identity.federation.services.FSServiceManager; import com.sun.identity.federation.services.FSSessionManager; import com.sun.identity.federation.services.util.FSServiceUtils; import com.sun.identity.liberty.ws.meta.jaxb.IDPDescriptorType; import com.sun.identity.liberty.ws.meta.jaxb.SPDescriptorType; import com.sun.identity.saml.common.SAMLException; import com.sun.identity.saml.xmlsig.XMLSignatureManager; import com.sun.identity.shared.encode.Base64; import com.sun.identity.shared.xml.XMLUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.w3c.dom.Document; /** * SP AssertionConsumerService. */ public class FSAssertionConsumerService extends HttpServlet { private IDFFMetaManager metaManager = null; /** * Initializes the servlet. */ public void init(ServletConfig config) throws ServletException { super.init(config); metaManager = FSUtils.getIDFFMetaManager(); } /** * Default constructor. */ public FSAssertionConsumerService() { } /** * Handles artifact profile. * @param request HttpServletRequest object * @param response HttpServletResponse object * @exception ServletException, IOException if error occurrs. */ public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { if ((request == null) || (response == null)) { response.sendError(response.SC_INTERNAL_SERVER_ERROR, FSUtils.bundle.getString("nullInputParameter")); return; } FSUtils.debug.message("FSAssertionConsumerService.doGet(): called"); String relayState = request.getParameter(IFSConstants.LRURL); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSAssertionConsumerService.doGet():Resource URL: " + relayState); } String metaAlias = FSServiceUtils.getMetaAlias(request); String realm = IDFFMetaUtils.getRealmByMetaAlias(metaAlias); String baseURL = FSServiceUtils.getBaseURL(request); String framedPageURL = FSServiceUtils.getCommonLoginPageURL( metaAlias, relayState, null,request,baseURL); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSAssertionConsumerService: CommonLoginPage: " + framedPageURL); } SPDescriptorType hostDesc = null; BaseConfigType hostConfig = null; String hostEntityId = null; try { hostEntityId = metaManager.getEntityIDByMetaAlias(metaAlias); hostDesc = metaManager.getSPDescriptor(realm, hostEntityId); hostConfig = metaManager.getSPDescriptorConfig( realm, hostEntityId); } catch (Exception e) { FSUtils.debug.error("FSAssertionConsumerService.doGet: ", e); FSUtils.forwardRequest(request, response, framedPageURL); return; } FSRequest samlRequest = null; String firstSourceID = null; String artifactName = IFSConstants.ARTIFACT_NAME_DEFAULT; String[] arti =(String[])request.getParameterValues(artifactName); if ((arti == null) ||(arti.length < 0) ||(arti[0] == null)) { FSUtils.debug.error("FSAssertionConsumerService.doGet: " + "AuthnRequest Processing Failed at the IDP " + "Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); } List al = new ArrayList(); try { FSAssertionArtifact firstArtifact = new FSAssertionArtifact(arti[0]); firstSourceID = firstArtifact.getSourceID(); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doGet: " + "SourceID within the Artifact is " + firstSourceID); } al.add(firstArtifact); for (int k = 1; k < arti.length; k++) { // check all artifacts coming from the same source id FSAssertionArtifact assertArtifact = new FSAssertionArtifact(arti[k]); String dest = assertArtifact.getSourceID(); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doGet: " + "SourceID within the Artifact is " + dest); } if (!dest.equals(firstSourceID)) { FSUtils.debug.error("FSAssertionConsumerService.doGet: " + "Received multiple artifacts have different source id"); FSUtils.forwardRequest(request, response, framedPageURL); return; } al.add(assertArtifact); } samlRequest = new FSRequest(null, al); } catch(SAMLException se) { FSUtils.debug.error("FSAssertionConsumerService.doGet: ", se); FSUtils.forwardRequest(request, response, framedPageURL); return; } catch(FSMsgException se) { FSUtils.debug.error("FSAssertionConsumerService.doGet: ", se); FSUtils.forwardRequest(request, response, framedPageURL); return; } try { // handle sso if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doGet: " + "Trying to get BrowserArtifactHandler"); } FSServiceManager sm = FSServiceManager.getInstance(); FSAssertionArtifactHandler handler = sm.getBrowserArtifactHandler( request, response, realm, firstSourceID, samlRequest, relayState); if (handler == null){ FSUtils.debug.error("FSAssertionConsumerService.doGet: " + FSUtils.bundle.getString("internalError")); FSUtils.forwardRequest(request, response, framedPageURL); return; } if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doGet: " + "BrowserArtifactHandler created"); } handler.setRealm(realm); handler.setHostEntityId(hostEntityId); handler.setMetaAlias(metaAlias); handler.setHostDescriptor(hostDesc); handler.setHostDescriptorConfig(hostConfig); handler.processSAMLRequest(); return; } catch(Exception e) { FSUtils.debug.error("FSAssertionConsumerService.doGet: " + "Exception occurred :", e); FSUtils.forwardRequest(request, response, framedPageURL); return; } } /** * Handles post profile. * @param request HttpServletRequest object * @param response HttpServletResponse object * @exception ServletException, IOException if error occurs. */ public void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { FSUtils.debug.message("FSAssertionConsumerService.doPost : called"); Document doc = null; if ((request == null) ||(response == null)) { response.sendError(response.SC_INTERNAL_SERVER_ERROR, FSUtils.bundle.getString("nullInputParameter")); return; } String metaAlias = FSServiceUtils.getMetaAlias(request); String realm = IDFFMetaUtils.getRealmByMetaAlias(metaAlias); String baseURL = FSServiceUtils.getBaseURL(request); String framedPageURL = FSServiceUtils.getCommonLoginPageURL( metaAlias, null, null, request, baseURL); String hostEntityId = null; SPDescriptorType hostDesc = null; BaseConfigType hostConfig = null; try { hostEntityId = metaManager.getEntityIDByMetaAlias(metaAlias); hostDesc = metaManager.getSPDescriptor(realm, hostEntityId); hostConfig = metaManager.getSPDescriptorConfig(realm, hostEntityId); } catch (Exception e) { FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Exception when obtain host meta data:", e); FSUtils.forwardRequest(request, response, framedPageURL); return; } // obtain AuthnResponse message String encodedAuthnResponse = request.getParameter(IFSConstants.POST_AUTHN_RESPONSE_PARAM); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doPost: " + "Base64 encoded AuthnResponse: " + encodedAuthnResponse); } if (encodedAuthnResponse == null) { String[] data = { FSUtils.bundle.getString("missingAuthnResponse") }; LogUtil.error(Level.INFO,LogUtil.MISSING_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("missingAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); return; } encodedAuthnResponse = encodedAuthnResponse.replace (' ', '\n'); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doPost: " + "Base64 encoded AuthnResponse2: " + encodedAuthnResponse); } FSAuthnResponse authnResponse = null; try { String decodedAuthnResponse = new String(Base64.decode(encodedAuthnResponse)); FSUtils.debug.message("Decoded authnResponse" + decodedAuthnResponse); doc = XMLUtils.toDOMDocument(decodedAuthnResponse, FSUtils.debug); if (doc == null) { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSAssertionConsumerService.doPost:Error " + "while parsing input xml string"); } throw new FSMsgException("parseError", null); } authnResponse = new FSAuthnResponse(doc.getDocumentElement()); if (authnResponse == null){ FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Invalid AuthnResponse. " + "Can't parse Base64 encoded AuthnResponse"); String[] data = { FSUtils.bundle.getString("invalidAuthnResponse") }; LogUtil.error(Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("invalidAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); return; } } catch(FSException e){ FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Invalid AuthnResponse. FSException" + " occured while parsing Base64 encoded AuthnResponse: ", e); String[] data = { FSUtils.bundle.getString("invalidAuthnResponse") }; LogUtil.error(Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("invalidAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); return; } catch(SAMLException e) { FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Invalid AuthnResponse. SAMLException" + " occurred while parsing Base64 encoded AuthnResponse: ", e); String[] data = { FSUtils.bundle.getString("invalidAuthnResponse") }; LogUtil.error(Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("invalidAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); return; } try { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doPost: " + "AuthnResponse received is valid: " + authnResponse.toXMLString()); } } catch(FSException e){ FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Invalid AuthnResponse. FSException" + " occurred while calling AuthnResponse.toXMLString(): ", e); String[] data = { FSUtils.bundle.getString("invalidAuthnResponse") }; LogUtil.error(Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("invalidAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); return; } FSAuthnRequest authnRequest = null; String requestID = authnResponse.getInResponseTo(); if (requestID == null){ FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Invalid AuthnResponse. AuthnResponse " + "received does not have inResponseTo attribute"); String[] data = { FSUtils.bundle.getString("invalidAuthnResponse") }; LogUtil.error(Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("invalidAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); return; } if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doPost: " + "AuthnResponse received is against requestID: " + requestID); } authnRequest = getInResponseToRequest(requestID, metaAlias); if (authnRequest == null){ FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Invalid AuthnResponse. AuthnResponse" + " received does not have an associated AuthnRequest"); String[] data = { FSUtils.bundle.getString("invalidAuthnResponse") }; LogUtil.error(Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("invalidAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedPageURL); return; } String framedLoginPageURL = FSServiceUtils.getCommonLoginPageURL( metaAlias, authnRequest.getRelayState(), null,request,baseURL); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doPost: " + "inResponseTo validation is successful"); } try { String idpEntityId = null; IDPDescriptorType idpDescriptor = null; if (!authnRequest.getProtocolProfile().equals( IFSConstants.SSO_PROF_LECP)) { idpEntityId = getProvider( authnResponse.getInResponseTo(), metaAlias); idpDescriptor = metaManager.getIDPDescriptor( realm, idpEntityId); if (idpEntityId == null || idpDescriptor == null) { FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Invalid AuthnResponse. Sender information " + "not found for the received AuthnResponse"); String[] data = { FSUtils.bundle.getString("invalidAuthnResponse") }; LogUtil.error( Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("invalidAuthnResponse") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest( request, response, framedLoginPageURL); return; } if ((FSServiceUtils.isSigningOn () || (FSServiceUtils.isSigningOptional() && authnRequest.getProtocolProfile().equals( IFSConstants.SSO_PROF_BROWSER_POST))) && !verifyAuthnResponseSignature( doc, idpDescriptor, idpEntityId)) { FSUtils.debug.error( "FSAssertionConsumerService.doPost: Signature " + "verification failed"); FSUtils.forwardRequest( request, response, framedLoginPageURL); return; } } else { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("FSAssertionConsumerService.doPost: " + "LECP Profile identified. IDP info is unknown so far" + "Get providerId from the response"); } idpEntityId = authnResponse.getProviderId(); idpDescriptor = metaManager.getIDPDescriptor( realm, idpEntityId); } // handle sso FSServiceManager sm = FSServiceManager.getInstance(); FSAssertionArtifactHandler handler = sm.getAssertionArtifactHandler( request, response, authnRequest, authnResponse, idpDescriptor, idpEntityId); if (handler == null) { FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "could not create AssertionArtifactHandler"); String[] data = { FSUtils.bundle.getString("requestProcessingFailed") }; LogUtil.error( Level.INFO, LogUtil.AUTHN_REQUEST_PROCESSING_FAILED, data); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("requestProcessingFailed") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedLoginPageURL); return; } handler.setHostEntityId(hostEntityId); handler.setHostDescriptor(hostDesc); handler.setHostDescriptorConfig(hostConfig); handler.setMetaAlias(metaAlias); handler.setRealm(realm); handler.processAuthnResponse(authnResponse); return; } catch (Exception se) { FSUtils.debug.error("FSAssertionConsumerService.doPost: " + "Exception: ", se); FSUtils.debug.error("FSAssertionConsumerService.doPost: " + FSUtils.bundle.getString("requestProcessingFailed") + " AuthnRequest Processing Failed at the IDP" + " Redirecting to the Framed Login Page"); FSUtils.forwardRequest(request, response, framedLoginPageURL); return; } } private FSAuthnRequest getInResponseToRequest( String requestID, String metaAlias ) { FSUtils.debug.message( "FSAssertionConsumerService::getInResponseToRequest: Called"); FSSessionManager sessionManager = FSSessionManager.getInstance( metaAlias); return sessionManager.getAuthnRequest(requestID); } private String getProvider( String requestID, String metaAlias) { FSUtils.debug.message("FSAssertionConsumerService.getProvider: Called"); FSSessionManager sessionManager = FSSessionManager.getInstance( metaAlias); return sessionManager.getIDPEntityID(requestID); } private boolean verifyAuthnResponseSignature( Document doc, IDPDescriptorType idpDescriptor, String idpEntityId) { FSUtils.debug.message( "FSAssertionConsumerService.verifyAuthnResponseSignature: Called"); try { X509Certificate cert = KeyUtil.getVerificationCert( idpDescriptor, idpEntityId, true); if (cert == null) { FSUtils.debug.error("FSAssertionConsumerService." + "verifyAuthnResponseSignature: couldn't obtain " + "this site's cert."); return false; } XMLSignatureManager manager = XMLSignatureManager.getInstance(); return manager.verifyXMLSignature( doc, cert); } catch(Exception e){ FSUtils.debug.error("FSAssertionConsumerService." + "verifyAuthnResponseSignature: Exception occurred while " + "verifying signature: " , e); return false; } } }