/** * 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: SAMLAwareServlet.java,v 1.5 2009/06/12 22:21:39 mallas Exp $ * * Portions Copyrighted 2013 ForgeRock AS */ package com.sun.identity.saml.servlet; import com.sun.identity.shared.encode.URLEncDec; import com.sun.identity.shared.encode.CookieUtils; import com.sun.identity.plugin.session.SessionException; import com.sun.identity.plugin.session.SessionManager; import com.sun.identity.plugin.session.SessionProvider; import com.sun.identity.saml.AssertionManager; import com.sun.identity.saml.common.LogUtils; import com.sun.identity.saml.common.SAMLConstants; import com.sun.identity.saml.common.SAMLException; import com.sun.identity.saml.common.SAMLServiceManager; import com.sun.identity.saml.common.SAMLUtils; import com.sun.identity.saml.protocol.AssertionArtifact; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Endpoint that supports SAML web browser artifact profile. */ public class SAMLAwareServlet extends HttpServlet { /** * Overrides doGet method to support SAML web browser artifact * profile in two ways: *
     * - Initiates SAML single sign-on
     * - Accepts SAML artifact to complete single sign-on
     * 
* * @param request HttpServletRequest instance. * @param response HttpServletResponse instance. * @throws IOException,ServletException if there is an error. */ public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { if (request == null || response == null) { String[] data = {SAMLUtils.bundle.getString("nullInputParameter")}; LogUtils.error(java.util.logging.Level.INFO, LogUtils.NULL_PARAMETER, data); SAMLUtils.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "nullInputParameter", SAMLUtils.bundle.getString("nullInputParameter")); return; } // avoid dos attack SAMLUtils.checkHTTPContentLength(request); String TargetUrl = request.getParameter((String) SAMLServiceManager. getAttribute(SAMLConstants.TARGET_SPECIFIER)); String SamlArt = request.getParameter((String) SAMLServiceManager. getAttribute(SAMLConstants.ARTIFACT_NAME)); if (TargetUrl == null || TargetUrl.length() == 0) { String[] data = {SAMLUtils.bundle.getString("missingTargetSite")}; LogUtils.error(java.util.logging.Level.INFO, LogUtils.MISSING_TARGET, data); SAMLUtils.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "invalidConfig", SAMLUtils.bundle.getString("invalidConfig")); return; } response.setContentType("text/html; charset=UTF-8"); if (SamlArt == null || SamlArt.length() == 0) { IntersiteTransfer(request, response,TargetUrl); } else { ArtifactHandler(request, response); } } /** * Overrides doPost method. It simply calls doGet method. * * @param request HttpServletRequest instance. * @param response HttpServletResponse instance. * @throws IOException,ServletException if there is an error. */ public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { doGet(request, response); } /** * Creates a list of AssertionArtifact's id. * * @param sso the user Session object * @param target A String representing the target host * @param targetUrl A URL String representing the target site * @param version The relying party preferred Assertion version number * @return a List representing a list of AssertionArtifact's id * @throws SAMLException if there is an error. */ private List createArtifact(Object sso,String target, HttpServletRequest request, HttpServletResponse response, String targetUrl, String version) throws SAMLException { if (sso == null || target == null || target.length() == 0 || version == null || version.length() == 0) { throw new SAMLException( SAMLUtils.bundle.getString("createArtifactError")); } List artifactList = new ArrayList(); AssertionManager assertManager = AssertionManager.getInstance(); try { SessionProvider sessionProvider = SessionManager.getProvider(); AssertionArtifact artifact = assertManager.createAssertionArtifact( sessionProvider.getSessionID(sso), target, request, response, targetUrl, version); if (SAMLUtils.debug.messageEnabled()) { SAMLUtils.debug.message("AssertionArtifact id = " + artifact.toString()); } String artid = artifact.getAssertionArtifact(); artifactList.add(artid); } catch (SessionException se) { SAMLUtils.debug.error("Couldn't get SessionProvider."); throw new SAMLException(SAMLUtils.bundle.getString( "nullSessionProvider")); } return artifactList; } /** * Creates a list of AssertionArtifact's id. * * @param request the HttpServletRequest object. * @param response the HttpServletResponse object. * @param target String representing the target host. * @throws IOException if there is an error. * @throws SAMLException if there is an error. */ private void IntersiteTransfer(HttpServletRequest request, HttpServletResponse response, String target) throws IOException, ServletException { // put _Sites as HashSet, loop through _Sites. // to check if the real target contains the siteid from the config // and if the targte port number equals the port number in config // (the port number is optional) URL theTarget = new URL(target); String theHost = theTarget.getHost(); int thePort = theTarget.getPort(); if (theHost == null) { if (SAMLUtils.debug.messageEnabled()) { SAMLUtils.debug.error("SAMLAwareServlet:IntersiteTransfer:" + "Failed to get host name of target URL."); } SAMLUtils.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "missingTargetHost", SAMLUtils.bundle.getString("missingTargetHost")); return; } if (SAMLUtils.debug.messageEnabled()) { SAMLUtils.debug.message("TargetUrl Host = " + theHost+ " Port= " + thePort); } // target break on ":" SAMLServiceManager.SiteEntry thisSite = null; Set trustedserver = (Set) SAMLServiceManager. getAttribute(SAMLConstants.TRUSTED_SERVER_LIST); if (trustedserver == null) { SAMLUtils.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "nullTrustedSite", SAMLUtils.bundle.getString("nullTrustedSite")); return; } Iterator iter = trustedserver.iterator(); while (iter.hasNext()) { String key = null; int portNum = 0; SAMLServiceManager.SiteEntry se = (SAMLServiceManager.SiteEntry) iter.next(); key = se.getHostName(); portNum = se.getPort(); if (portNum != -1) { if (theHost.indexOf(key) != -1) { if (thePort != -1) { if (thePort == portNum) { thisSite = se; break; } } } } else { // there is no port number specified in the SiteEntry:Target if (theHost.indexOf(key) != -1) { thisSite = se; } } } if (thisSite != null) { //create Session Object ssoToken = null; boolean loggedIn = false; try { SessionProvider sessionProvider = SessionManager.getProvider(); ssoToken = sessionProvider.getSession(request); if (ssoToken != null && sessionProvider.isValid(ssoToken)) { loggedIn = true; } } catch (SessionException se) { SAMLUtils.debug.message("Invalid SSO!"); } if (!loggedIn) { response.sendRedirect(SAMLUtils.getLoginRedirectURL(request)); return; } // create AssertionArtifact(s) List artis = new ArrayList(); try { artis = createArtifact(ssoToken, thisSite.getSourceID(), request, response, target, thisSite.getVersion()); } catch (SAMLException se) { SAMLUtils.debug.error("IntersiteTransfer:Failed to create" + " AssertionArtifact(s)"); SAMLUtils.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "errorCreateArtifact", se.getMessage());; return; } //bounce the user off to the remote site, pointing them to the //location of SamlAwareServlet at that site, and adding the //assertion artifact String targetName = (String) SAMLServiceManager. getAttribute(SAMLConstants.TARGET_SPECIFIER); String artifactName = (String) SAMLServiceManager. getAttribute(SAMLConstants.ARTIFACT_NAME); iter = artis.iterator(); StringBuffer sb = new StringBuffer(1000); String samltmp = null; while (iter.hasNext()) { samltmp = URLEncDec.encode((String)iter.next()); if (SAMLUtils.debug.messageEnabled()) { SAMLUtils.debug.message("Encoded SAML AssertionArtifact " + samltmp); } sb.append("&").append(artifactName).append("=").append(samltmp); } String redirecto = thisSite.getSAMLUrl() + "?" + targetName + "=" + URLEncDec.encode(target) + sb.toString(); response.setStatus(response.SC_MOVED_TEMPORARILY); response.setHeader("Location", redirecto); String[] data = {SAMLUtils.bundle.getString("redirectTo"), target, redirecto}; LogUtils.access(java.util.logging.Level.FINE, LogUtils.REDIRECT_TO_URL, data, ssoToken); response.sendRedirect(redirecto); } else { String[] data = {SAMLUtils.bundle.getString("targetForbidden"), target}; LogUtils.error(java.util.logging.Level.INFO, LogUtils.TARGET_FORBIDDEN, data); SAMLUtils.sendError(request, response, HttpServletResponse.SC_FORBIDDEN, "targetForbidden", SAMLUtils.bundle.getString("targetForbidden") + " " + target); return; } } /** * Partner SAML aware servlet part. * Responsible for *
    *
  1. communicate with SOAP Receiver *
  2. parse the replied SOAP Message *
  3. analyze the SOAP Message and SSO Assertion inside the msg *
  4. check the validity of the SSO assertion, if so, generate * Session and set to cookie *
* * @param request the HttpServletRequest object. * @param response the HttpServletResponse object. * @throws IOException if there is an error. * @throws ServletException if there is an error. */ private void ArtifactHandler( HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { javax.security.auth.Subject authSubject = null; String targeturl = request.getParameter((String) SAMLServiceManager. getAttribute(SAMLConstants.TARGET_SPECIFIER)); String artifactName = (String) SAMLServiceManager. getAttribute(SAMLConstants.ARTIFACT_NAME); String[] arti = request.getParameterValues(artifactName); List assts = null; Map attrMap = null; try { Map sessionAttr = SAMLUtils.processArtifact(arti, targeturl); Object token = SAMLUtils.generateSession(request, response, sessionAttr); } catch (Exception ex) { SAMLUtils.debug.error("generateSession: ", ex); String[] data = {SAMLUtils.bundle.getString( "failedCreateSSOToken")}; LogUtils.error(java.util.logging.Level.INFO, LogUtils.FAILED_TO_CREATE_SSO_TOKEN, data); SAMLUtils.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "failedCreateSSOToken", SAMLUtils.bundle.getString("failedCreateSSOToken")); return; } String[] data = {SAMLUtils.bundle.getString("accessGranted")}; LogUtils.access(java.util.logging.Level.INFO, LogUtils.ACCESS_GRANTED, data); // now we know the assertions are valid, so use those to POST if // this target is in the POST to target list if (SAMLUtils.postYN(targeturl)) { if (SAMLUtils.debug.messageEnabled()) { SAMLUtils.debug.message("POST to target:"+targeturl); } SAMLUtils.postToTarget(response, response.getWriter(), assts, targeturl, attrMap); } else { response.sendRedirect(targeturl); } } }