CDCClientServlet.java revision 0785b28d0aa9b62b04ed457a37d2191f45ae0d72
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: CDCClientServlet.java,v 1.6 2009/01/12 18:57:12 madan_ranganath Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Portions Copyrighted 2010-2014 ForgeRock AS.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.encode.URLEncDec;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.configuration.SystemPropertiesManager;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.dpro.session.SessionException;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.encode.CookieUtils;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The <code>CDCClientServlet</code> is the heart of the Cross Domain Single Signon mechanism of OpenAM in the DMZ
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * along with the distributed auth.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The following is the algorithm used by the program:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <li>If request does not contain SSO related cookie or policy has generated some advices then redirect request to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the distributed auth service.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <li>If request contains SSO related cookie and no advices.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <li>Tunnel the Request to OpenAM.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <li>Send the received AuthNResponse as Form POST to the original request requested using the goto parameter in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the query string.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class CDCClientServlet extends HttpServlet {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final ArrayList adviceParams = new ArrayList();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final Set<String> INVALID_SET = new HashSet<String>();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final Set<String> VALID_LOGIN_URIS = new HashSet<String>();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String URLENC_RIGHT_ANGLE = "%3e";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String URLENC_LEFT_ANGLE = "%3c";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String URLENC_JAVASCRIPT = "javascript%3a";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String JAVASCRIPT = "javascript:";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String DEBUG_FILE_NAME = "amCDC";
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee private static final String GOTO_PARAMETER = "goto";
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee private static final String TARGET_PARAMETER = "TARGET";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String CDCURI = "/cdcservlet";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String LOGIN_URI = "loginURI";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String AUTHURI = "/UI/Login";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String RESPONSE_HEADER_ALERT =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "X-DSAME-Assertion-Form";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String RESPONSE_HEADER_ALERT_VALUE =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String FORBIDDEN_STR_MATCH = "#403x";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String SERVER_ERROR_STR_MATCH = "#500x";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster static Debug debug = Debug.getInstance(DEBUG_FILE_NAME);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static String sessionServiceName = "iPlanetAMSessionService";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean serverMode = Boolean.valueOf(System.getProperty(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Constants.SERVER_MODE, SystemProperties.get(Constants.SERVER_MODE,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static boolean cookieEncoding =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SystemProperties.getAsBoolean(Constants.AM_COOKIE_ENCODE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param config the ServletConfig object that contains configutation
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * information for this servlet.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception ServletException if an exception occurs that interrupts
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the servlet's normal operation.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void init(ServletConfig config) throws ServletException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.message("CDCClientServlet.init:CDCClientServlet "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster +"Initializing...");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("CDCClientServlet.init:unable to get SSOTokenManager",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Constants.AUTH_UNIQUE_COOKIE_NAME, "sunIdentityServerAuthNServer");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Constants.AM_DISTAUTH_DEPLOYMENT_DESCRIPTOR, "/distauth");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Handles the HTTP GET request.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param request an HttpServletRequest object that contains the request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the client has made of the servlet.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param response an HttpServletResponse object that contains the response
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the servlet sends to the client.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception ServletException if an input or output error is detected when
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the servlet handles the GET request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception IOException if the request for the GET could not be handled
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void doGet(HttpServletRequest request, HttpServletResponse response)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Handles the HTTP POST request.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param request an HttpServletRequest object that contains the request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the client has made of the servlet.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param response an HttpServletResponse object that contains the response
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the servlet sends to the client.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception ServletException if an input or output error is detected when
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the servlet handles the GET request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception IOException if the request for the GET could not be handled
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void doPost(HttpServletRequest request, HttpServletResponse
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The method redirects the user to the authentication module if he is not
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * authenticated; else redirects him back to the original referrer.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param request an HttpServletRequest object that contains the request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the client has made of the servlet.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param response an HttpServletResponse object that contains the response
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the servlet sends to the client.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception ServletException if an input or output error is detected when
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the servlet handles the GET request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception IOException if the request for the GET could not be handled
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void doGetPost(HttpServletRequest request,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster HttpServletResponse response) throws ServletException, IOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.message("CDCClientServlet.doGetPost:Query String received= "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String gotoParameter = request.getParameter(GOTO_PARAMETER);
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee String targetParameter = request.getParameter(TARGET_PARAMETER);
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee request.getParameter(TARGET_PARAMETER.toLowerCase());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // if check if goto ot target have invalid strings, to avoid
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // accepting invalid injected javascript.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((gotoParameter != null ) || (targetParameter != null)) {
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna debug.message("CDCClientServlet:doGetPost():validating goto: " + gotoParameter
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna if (gotoParameter != null && gotoParameter.toLowerCase().contains(invalidStr)) {
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna showError(response, SERVER_ERROR_STR_MATCH + "GOTO parameter has invalid characters");
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna if (targetParameter != null && targetParameter.toLowerCase().contains(invalidStr)) {
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna showError(response, SERVER_ERROR_STR_MATCH + "TARGET parameter has invalid characters");
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna /* Steps to be done
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna * 1. If no SSOToken or policy advice present , forward to
61b4091b1d49fc8b736ee1e150a1b76c14f05c91David Luna * authentication.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * 2. If SSOToken is valid tunnel request to the backend AM's
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * CDCServlet and Form POST the received response to the agent.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Check for a valid SSOToken in the request. If SSOToken is not found
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee // or if the token is invalid, redirect the user for authentication.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Also re-direct if there are policy advices in the query string
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SSOToken token = getSSOToken(request, response);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // collect advices in parsedRequestParams[0] String and rest of params
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // other than original goto url in parsedRequestParams[1] String.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String[] parsedRequestParams = parseRequestParams(request);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((token == null) || (parsedRequestParams[0] != null)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Redirect to authentication
int len;
+"code NOT OK/MOVED_TEMP ");
+ CDCServletURL);
return strCookies;
throws IOException {
+ loginURI);
throws IOException {
} catch (IOException e) {
return (token);
* Return <code>true</code> if the passed URI is valid compared to the valid set loaded during initialization.
return result;
private static void initConfig() {