Java tutorial
/** * Copyright (C) 2008 Google - Enterprise EMEA SE * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gsa; import com.google.gsa.sessions.SessionTimer; import com.google.gsa.valve.modules.krb.KerberosAuthenticationProcess; import com.google.gsa.sessions.Sessions; import com.google.gsa.sessions.UserIDEncoder; import com.google.gsa.sessions.UserSession; import com.google.gsa.valve.configuration.ValveConfiguration; import com.google.gsa.valve.configuration.ValveConfigurationException; import com.google.gsa.valve.configuration.ValveConfigurationInstance; import com.google.gsa.valve.saml.SAMLArtifactProcessor; import com.google.gsa.valve.saml.authn.SAMLAuthN; import com.google.gsa.valve.utils.ValveUtils; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.Principal; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Vector; import javax.naming.NamingException; import javax.security.auth.Subject; import javax.servlet.*; import javax.servlet.http.*; import org.apache.commons.httpclient.HttpException; import org.apache.log4j.Logger; /** * This is the main authentication servlet when a silent kerberos tickets are * being used to get user credentials. It implements the whole authentication * process when the user is authenticated using his/her kerberos ticket obtained * silently during the browser connection. This ticket is collected up, * included in the authentication credentials and starts the global * authentication process for the user. * <p> * It invokes the root authentication process to garantee the user is * authenticated in all the backend repositories. It supports both the SAML * and the Forms Based interface. * <p> * If the overall process result is an unauthorized, a 401 error message is * sent back to the user's browser. * <p> * It also handles crawling when Forms Based authentication has been set. * */ public class Kerberos extends HttpServlet { //logger private static Logger logger = null; //Cookie vars private String authCookieDomain = null; private String authCookiePath = null; private String authCookieName = null; private int authMaxAge = 300; private String refererCookieName = null; //user session vars SessionTimer sessionTimer; long maxSessionAge; long sessionTimeout; long sessionCleanup; boolean isSessionEnabled = false; //Non Krb AuthN var private String authenticationProcessClsName = null; //Kerberos Subject Map private static Map<String, Subject> krbSubjects = new HashMap<String, Subject>(); private static String gsaValveConfigPath = null; private ValveConfiguration valveConf; //Krb vars boolean KrbUsrPwdCrawler = false; boolean KrbAdditionalAuthN = false; String KrbLoginUrl = null; String KrbUsrPwdCrawlerUrl = null; String loginUrl = null; boolean isKerberos = false; boolean isNegotiate = false; //Var that tells the default Credential ID for Kerberos private static final String KRB5_ID = "krb5"; private static final String GSA_CRAWLER_USER = "gsa-crawler"; private static final String GSA_CRAWLING_CONTENT = "(Enterprise"; private static final String KRB_COOKIE_NAME = "gsa_krb5_auth"; //encoding private static String encoder = "UTF-8"; //SAML boolean isSAML = false; String refererSAML = null; String relayState = null; String samlRequest = null; static { // Instantiate logger logger = Logger.getLogger(Kerberos.class); } /** * Init method * * @param config servlet config * * @throws ServletException */ public void init(ServletConfig config) throws ServletException { super.init(config); } /** * Servlet's doGet: processes a doGet request. Calls doPost. * * @param request HTTP request * @param response HTTP response * * @throws ServletException * @throws IOException */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * Servlet's doPost: processes a POST request. Controls the overall * kerberos silent authentication process. It supports both the Security * Framework's SAML and Forms Based interface. * <p> * You can find more information on the Security Framework's Kerberos guide * about the scenarios implemented here * * @param request HTTP request * @param response HTTP response * * @throws ServletException * @throws IOException */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { logger.debug("Kerberos servlet"); if (gsaValveConfigPath == null) { if (request.getAttribute("gsaValveConfigPath") == null) { //Read parameter from config file: SAML gsaValveConfigPath = readValveConfigPath(); } else { gsaValveConfigPath = request.getAttribute("gsaValveConfigPath").toString(); } } logger.debug("Valve Config Path is: " + gsaValveConfigPath); // Initialize status code int statusCode = HttpServletResponse.SC_UNAUTHORIZED; //Authentication Processes AuthenticationProcessImpl authenticationProcessCls = null; KerberosAuthenticationProcess krbAuthN = new KerberosAuthenticationProcess(); //Initialize cookies vars Cookie gsaRefererCookie = null; Cookie gsaAuthCookie = null; //Session Cookie arrays Vector<Cookie> krbCookies = new Vector<Cookie>(); Vector<Cookie> nonKrbCookies = new Vector<Cookie>(); //user agent String userAgent = null; //user credentials Credentials creds = null; //User Session and Session ID vars definition UserSession userSession = null; String sessionID = null; String encodedSessionID = null; //Create the credentials store try { this.valveConf = ValveConfigurationInstance.getValveConfig(gsaValveConfigPath); } catch (ValveConfigurationException e) { logger.error("Valve Config instantiation error: " + e); } logger.debug("Creating the credentials store"); creds = new Credentials(); String username = null; //Setting Valve parameters logger.debug("Setting Valve params"); setValveParams(request); //Protection if ((!isKerberos) || (!isNegotiate)) { logger.error( "Configuration error: if you want to use Kerberos silent AuthN, isKerberos and isNegotiate config vars have to be set to true"); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Configuration error - Kerberos is not set properly"); return; } Cookie cookies[] = null; // Retrieve cookies cookies = request.getCookies(); // Protection: look for auth and referer cookies if (cookies != null) { // Look for the referer cookie for (int i = 0; i < cookies.length; i++) { // Look for the referer cookie if ((cookies[i].getName()).equals(refererCookieName)) { // Cache cookie gsaRefererCookie = cookies[i]; logger.debug("Referer cookie already exists: " + gsaRefererCookie.getValue()); } else { // Look for the auth cookie if ((cookies[i].getName()).equals(authCookieName)) { // Cache cookie gsaAuthCookie = cookies[i]; logger.debug("Auth cookie already exists: " + gsaAuthCookie.getValue()); } } if ((gsaRefererCookie != null) && (gsaAuthCookie != null)) { // Exit break; } } } // Protection if (!isSAML) { if (gsaRefererCookie == null) { // Raise error response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "The GSA authentication servlet couldn't read the referer cookie"); // Log error logger.error( "The GSA authentication servlet couldn't read the referer cookie, pls. check the cookie domain value"); // Return return; } } else { //SAML //Get SAML Params relayState = request.getParameter("RelayState"); samlRequest = request.getParameter("SAMLRequest"); //String relayStateCookie = valveConf.getSAMLConfig().getRelayStateCookie(); boolean noParams = false; boolean cookieExist = true; //Protection if ((relayState == null) || (relayState.equals(""))) { noParams = true; } else { if ((samlRequest == null) || (samlRequest.equals(""))) { noParams = true; } } createRefererCookie(gsaRefererCookie); //if ((noParams)&&(!cookieExist)) { if (noParams) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid request"); return; } } logger.debug("Let's validate if gsaAuthCookie is present"); if (gsaAuthCookie != null) { if (!isSAML) { //redirect String redirect = gsaRefererCookie.getValue(); logger.debug("redirect is " + redirect); //redirect only if the URL is different than the login one if (!redirect.equals(loginUrl)) { //user properly authenticated logger.debug("The user was properly authenticated. Lets redirect to..." + redirect); // Redirect response.sendRedirect(redirect); } else { logger.debug("It's the login URL. No redirect"); } } else { logger.debug("As this is SAML. Let's obviate the previous authentication cookie"); gsaAuthCookie = null; } } userSession = new UserSession(); Sessions sessions = Sessions.getInstance(); sessions.setMaxSessionAgeMinutes(maxSessionAge); sessions.setSessionTimeoutMinutes(sessionTimeout); if (gsaAuthCookie == null) { logger.debug("gsaAuthCookie does not exist"); isNegotiate = true; // Read User-Agent header userAgent = request.getHeader("User-Agent"); logger.debug("userAgent is... " + userAgent); //check if user is gsa-crawler if (userAgent.startsWith(GSA_CRAWLER_USER)) { logger.debug("User is " + GSA_CRAWLER_USER); //check if user is gsa-crawler and have to authenticate it thru a form if (KrbUsrPwdCrawler) { logger.debug("gsa-crawler has to access thru username and password"); //check if crawler already provided credentials if (request.getParameter("UserIDKrb") == null) { //the login page have to be filled in by the admin user before reaching here. Return error logger.error("The login page [" + KrbUsrPwdCrawlerUrl + "] has to be invoked and its credentials fields filled in before reaching here"); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "It means the GSA Valve Kerberos configuration is not done properly or you just forgot to fill in the Kerberos credentials in the login page"); return; } else { //user already submits credentials logger.debug("Crawler has already sent credentials"); //set isNegotiate equal false (it authenticates the user thru username and pwd credentials) isNegotiate = false; //set Crawler credentials setCrawlerCredentials(request, creds, KrbAdditionalAuthN); //authenticate user statusCode = krbAuthentication(request, response, krbAuthN, krbCookies, gsaRefererCookie.getValue(), creds, isNegotiate); // Protection: check status code if (statusCode != HttpServletResponse.SC_OK) { // Raise error response.sendError(statusCode, "Authentication process failed!"); // Debug if (logger.isDebugEnabled()) logger.debug("Krb Authentication process failed with code: " + statusCode); if (statusCode == HttpServletResponse.SC_UNAUTHORIZED) { logger.debug( "Note: this 401 could not be an error as sending 401 could be part of the Negotiation process"); } // Return return; } //check if the additional authN method is available. If so, start authN with these creds as well //N: modification for always lanching the root authN process. Comment out the following line //if (KrbAdditionalAuthN) { statusCode = nonKrbAuthentication(request, response, authenticationProcessCls, nonKrbCookies, gsaRefererCookie.getValue(), creds); //check if the status code is indeterminate if (statusCode == -1) { //the process could not determinate the authorization //as there is no pattern that matches with any repository statusCode = HttpServletResponse.SC_UNAUTHORIZED; } // Protection: check status code if (statusCode != HttpServletResponse.SC_OK) { // Raise error response.sendError(statusCode, "Authentication process failed!"); // Debug if (logger.isDebugEnabled()) logger.debug("Non Krb Authentication process failed with code: " + statusCode); // Return return; } //} } } else { // end KrbUsrPwdCrawler is set. //If KrbUsrPwdCrawler is not set to true, then do nothing (assume content is feeded) //just send back the error as a configuration one (we shouldn't configure Froms-based crawling) response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Configuration error. Review your configuration as you can not define this rule if it's not set properly (see doc on how to set it up using Kerberos config attributes)"); return; } } else { //User is not Crawler logger.debug("User is NOT crawler"); //check if we have double AuthN or not if (!KrbAdditionalAuthN) { logger.debug("Krb silent authN only"); //set isNegotiate equal true (it authenticates the user thru kerberos ticket) isNegotiate = true; String refererCookieValue = null; if (gsaRefererCookie != null) { refererCookieValue = new String(gsaRefererCookie.getValue()); } //authenticate user statusCode = krbAuthentication(request, response, krbAuthN, krbCookies, refererCookieValue, creds, isNegotiate); // Protection: check status code if (statusCode != HttpServletResponse.SC_OK) { // Raise error response.sendError(statusCode, "Authentication process failed!"); // Debug if (logger.isDebugEnabled()) logger.debug("Krb Authentication process failed with code: " + statusCode); if (statusCode == HttpServletResponse.SC_UNAUTHORIZED) { logger.debug( "Note: this 401 could not be an error as sending 401 could be part of the Negotiation process"); } // Return return; } else { boolean doesKrbSubjectExist = lookForKrbCreds(creds); if (!doesKrbSubjectExist) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Credentials not valid. Try to close your browser and try it again"); // Log error logger.error("Kerberos Subject is not present when authenticating"); // Return return; } //N: call rootAuthN once we have the Kerberos creds //N: Begin update if (!KrbAdditionalAuthN) { statusCode = nonKrbAuthentication(request, response, authenticationProcessCls, nonKrbCookies, refererCookieValue, creds); //check if the status code is indeterminate if (statusCode == -1) { //the process could not determinate the authorization //as there is no pattern that matches with any repository statusCode = HttpServletResponse.SC_UNAUTHORIZED; } // Protection: check status code if (statusCode != HttpServletResponse.SC_OK) { // Raise error response.sendError(statusCode, "Authentication process failed!"); // Debug if (logger.isDebugEnabled()) logger.debug("Non Krb Authentication process failed with code: " + statusCode); // Return return; } } //N:End update } } else { //Double AuthN required. So that apart from the Krb silent authN, we authN the user as well thru username and pwd logger.debug("Krb and Forms based AuthN mechanisms"); //check if Krb credentials are already set Cookie gsaKrbCookie = getCookie(request, KRB_COOKIE_NAME); //if (gsaKrbCookie != null) { //Kerberos cookie set if (!isKrbProcess(gsaKrbCookie)) { //Kerberos cookie set logger.debug("Krb cookie is set. Krb AuthN already in place"); Subject krbSubj = getKrbSubject(gsaKrbCookie.getValue()); //Protection if (krbSubj == null) { // couldn't localize the subject. response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Credentials not valid. Try to close your browser and try it again"); // Log error logger.error("Kerberos Subject is not present when authenticating"); // Return return; } else { logger.debug("The Krb subject exists. This is the Forms based AuthN part"); //check if parameters are present if (request.getParameter("UserIDKrb") == null) { logger.debug("Login page has not been already invoked"); String redirectUrl = contructKrbLoginURL(); logger.debug("Redirecting to...." + redirectUrl); //redirect to the login page response.sendRedirect(response.encodeRedirectURL(redirectUrl)); // Return return; } else { //user already submits credentials logger.debug("User has already sent credentials"); createCredsDoubleAuthN(request, creds, krbSubj); logger.debug("User Credentials created. Let's authenticate the user without Krb"); statusCode = nonKrbAuthentication(request, response, authenticationProcessCls, nonKrbCookies, gsaRefererCookie.getValue(), creds); //check if the status code is indeterminate if (statusCode == -1) { //the process could not determinate the authorization //as there is no pattern that matches with any repository statusCode = HttpServletResponse.SC_UNAUTHORIZED; } // Protection: check status code if (statusCode != HttpServletResponse.SC_OK) { // Raise error response.sendError(statusCode, "Authentication process failed!"); // Debug if (logger.isDebugEnabled()) logger.debug( "Non Krb Authentication process failed with code: " + statusCode); // Return return; } boolean resultDelete = deleteKrbSubject(gsaKrbCookie.getValue()); if (!resultDelete) { logger.error("Not KrbSubj found when deleting it"); } } } } else { //Krb cookie does not exist logger.debug( "Krb cookie does not exist. Let's silently authenticate the user thru Krb firstly"); logger.debug("Krb silent authN only"); //set isNegotiate equal true (it authenticates the user thru kerberos ticket) isNegotiate = true; //authenticate user statusCode = krbAuthentication(request, response, krbAuthN, krbCookies, gsaRefererCookie.getValue(), creds, isNegotiate); // Protection: check status code if (statusCode != HttpServletResponse.SC_OK) { // Raise error response.sendError(statusCode, "Authentication process failed!"); // Debug if (logger.isDebugEnabled()) logger.debug("Krb Authentication process failed with code: " + statusCode); if (statusCode == HttpServletResponse.SC_UNAUTHORIZED) { logger.debug( "Note: this 401 could not be an error as sending 401 could be part of the Negotiation process"); } // Return return; } else { Cookie krbCookie = krbCookies.elementAt(0); String krbAuthCookieValue = krbCookie.getValue(); logger.debug("Krb cookie value: " + krbAuthCookieValue); if (krbAuthCookieValue == null) { logger.error("Krb cookie not present"); // Raise error response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Kerberos cookie not present"); // Return return; } else { addKrbCookie(response, krbCookie); addKrbSubject(krbAuthCookieValue, krbAuthN.getUserSubject()); logger.debug( "The User Krb identity is already present. Let's authenticate the user thru username/password"); //redirect to Login page String redirectUrl = contructKrbLoginURL(); response.sendRedirect(response.encodeRedirectURL(redirectUrl)); logger.debug("Redirect to.... " + redirectUrl); return; } } } } } logger.debug("Krb and/or Forms based AuthN OK. Let's create the session"); //set username and cookies username = creds.getCredential(KRB5_ID).getUsername(); //creation time var long creationTime = System.currentTimeMillis(); //Setting session values sessionID = UserIDEncoder.getID(username, creationTime); encodedSessionID = URLEncoder.encode(sessionID, encoder); logger.debug("Krb Username is... " + username); // setSession boolean sessionOk = settingSession(userSession, gsaAuthCookie, creds, username, krbAuthN, creationTime, encodedSessionID, krbCookies, nonKrbCookies); logger.debug("Session is .... " + sessionOk); if (!sessionOk) { //SAML statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; response.setStatus(statusCode); // Log error logger.error("Kerberos Subject has not been created properly"); // Return return; } else { //Store Session in the Session Map sessions.addSession(sessionID, userSession); sessions.setMaxSessionAgeMinutes(maxSessionAge); if (isSessionEnabled) { sessions.setSessionTimeoutMinutes(sessionTimeout); } else { sessions.setSessionTimeoutMinutes(-1); } logger.debug("User Session created"); // Add internal authentication cookie response.addCookie(gsaAuthCookie); logger.debug("Auth cookie added"); // Debug if (logger.isDebugEnabled()) logger.debug("Authentication process successful"); if (!isSAML) { // Debug if (logger.isDebugEnabled()) logger.debug("Redirecting user to: " + gsaRefererCookie.getValue()); // Redirect response.sendRedirect(gsaRefererCookie.getValue()); } else { try { redirectingSAML(response, cookies, sessionID); } catch (ValveConfigurationException e) { logger.error("Configuration error: " + e.getMessage(), e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } } } } //end of AuthN cases } /** * Sets the crawler credentials recovered during the crawling process * * @param request HTTP request * @param KrbAdditionalAuthN if there is an additional authentication process */ private void setCrawlerCredentials(HttpServletRequest request, Credentials creds, boolean KrbAdditionalAuthN) { // Read HTTP request parameters String username = request.getParameter("UserIDKrb"); String password = request.getParameter("PasswordKrb"); Credential krb5Cred = new Credential(KRB5_ID); Credential rootCred = new Credential("root"); krb5Cred.setUsername(username); krb5Cred.setPassword(password); creds = new Credentials(); if (KrbAdditionalAuthN) { username = request.getParameter("UserID"); password = request.getParameter("Password"); rootCred = new Credential("root"); rootCred.setUsername(username); rootCred.setPassword(password); creds.add(rootCred); creds.add(krb5Cred); } else { creds.add(krb5Cred); } } /** * It invokes the kerberos authentication class to validate the * authentication process * * @param request HTTP request * @param response HTTP response * @param krbAuthCookies authentication cookies * @param url document url * @param creds credentials * @param isNegotiate if it's a negotiate process * * @return HTTP error code */ private int krbAuthentication(HttpServletRequest request, HttpServletResponse response, KerberosAuthenticationProcess krbAuthN, Vector<Cookie> krbAuthCookies, String url, Credentials creds, boolean isNegotiate) { int statusCode = HttpServletResponse.SC_UNAUTHORIZED; logger.debug("krbAuthentication: Krb authentication process"); try { krbAuthN.setIsNegotiate(isNegotiate); krbAuthN.setValveConfiguration(valveConf); statusCode = krbAuthN.authenticate(request, response, krbAuthCookies, url, creds, KRB5_ID); } catch (HttpException e) { logger.error("Http error during Kerberos authentication " + e); statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } catch (IOException e) { logger.error("I/O error during Kerberos authentication " + e); statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } logger.debug("Krb Auth - Status code is... " + statusCode); return statusCode; } /** * It invokes the additional non-Kerberos authentication process * * @param request HTTP request * @param response HTTP response * @param nonKrbAuthCookies authentication cookies * @param url document url * @param creds credentials * * @return HTTP error code */ private int nonKrbAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationProcessImpl authenticationProcessCls, Vector<Cookie> nonKrbAuthCookies, String url, Credentials creds) { int statusCode = HttpServletResponse.SC_UNAUTHORIZED; // Instantiate the authentication process class try { // Instantiate the authorization process class authenticationProcessCls = (AuthenticationProcessImpl) Class.forName(authenticationProcessClsName) .newInstance(); } catch (InstantiationException e) { // Log error logger.error( "InstantiationException - Authentication servlet parameter [authenticationProcessImpl] has not been set correctly"); statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; // Return return statusCode; } catch (IllegalAccessException e) { // Log error logger.error( "IllegalAccessException - Authentication servlet parameter [authenticationProcessImpl] has not been set correctly"); statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; // Return return statusCode; } catch (ClassNotFoundException e) { // Log error logger.error( "ClassNotFoundException - Authentication servlet parameter [authenticationProcessImpl] has not been set correctly"); logger.error("Cannot find class: " + authenticationProcessClsName); statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; // Return return statusCode; } try { logger.debug("Lets authenticate the user"); // Execute the authentication process in here authenticationProcessCls.setValveConfiguration(valveConf); statusCode = authenticationProcessCls.authenticate(request, response, nonKrbAuthCookies, url, creds, "root"); logger.debug("Non Krb Auth - Status code is... " + statusCode); } catch (Exception e) { // Debug logger.error("Authentication process raised exception: " + e.getMessage(), e); } return statusCode; } /** * Setting the authentication cookie and the user session * * @param username username * @param creationTime creation time * @param encodedSessionID encoded session id * * @return if the setting process was successful */ private boolean settingSession(UserSession userSession, Cookie gsaAuthCookie, Credentials creds, String username, KerberosAuthenticationProcess krbAuthN, long creationTime, String encodedSessionID, Vector<Cookie> krbCookies, Vector<Cookie> nonKrbCookies) { boolean result = false; logger.debug("Creating auth cookie with value: " + encodedSessionID); // Instantiate authentication cookie with default value gsaAuthCookie = new Cookie(authCookieName, encodedSessionID); // Set cookie domain gsaAuthCookie.setDomain(authCookieDomain); // Set cookie path gsaAuthCookie.setPath(authCookiePath); // Set expiration time gsaAuthCookie.setMaxAge(authMaxAge); logger.debug("Creating Session"); userSession.setUserName(username); userSession.setSessionCreationTime(creationTime); userSession.setSessionLastAccessTime(creationTime); userSession.setUserCredentials(creds); //Cookies settingSessionCookies(krbCookies, nonKrbCookies, gsaAuthCookie, userSession); if (krbAuthN.getUserSubject() != null) { logger.debug("Kerberos Subject exists"); userSession.setKerberosCredentials(krbAuthN.getUserSubject()); result = true; } else { // Log error logger.error("Kerberos Subject has not been created properly"); // Return return result; } return result; } /** * Sets the kerberos and non-kerberos authentication cookies * */ private void settingSessionCookies(Vector<Cookie> krbCookies, Vector<Cookie> nonKrbCookies, Cookie gsaAuthCookie, UserSession userSession) { int numKrb = 0; int numNonKrb = 0; int authCookie = 1; Cookie[] totalCookies; //check number of cookies if (!krbCookies.isEmpty()) { numKrb = krbCookies.size(); logger.debug("numKrb: " + numKrb); } if (!nonKrbCookies.isEmpty()) { numNonKrb = nonKrbCookies.size(); logger.debug("numNonKrb: " + numNonKrb); } //setting Cookies int numCookies = numKrb + numNonKrb + authCookie; logger.debug("numCookies: " + numCookies); totalCookies = new Cookie[numCookies]; //setting authCookie logger.debug("Inserting authCoookie at totalCookie"); totalCookies[0] = gsaAuthCookie; int index = 1; //getting Krb cookies if (numKrb > 0) { int krbIndex = 0; for (int i = index; i < (numKrb + 1); i++) { logger.debug("Inserting totalCookie [i=" + (i) + "]"); logger.debug("with cookie: " + krbCookies.elementAt(krbIndex)); totalCookies[i] = krbCookies.elementAt(krbIndex); krbIndex++; index++; } } //getting nonKrb cookies if (numNonKrb > 0) { int nonKrbIndex = 0; for (int j = index; j < numCookies; j++) { logger.debug("Inserting totalCookie [j=" + (j) + "]: "); logger.debug("with cookie: " + nonKrbCookies.elementAt(nonKrbIndex)); totalCookies[j] = nonKrbCookies.elementAt(nonKrbIndex); nonKrbIndex++; } } userSession.setCookies(totalCookies); } /** * Gets a cookie from the request * * @param request HTTP request * @param cookieName cookie name * * @return cookie (if it exists) */ private Cookie getCookie(HttpServletRequest request, String cookieName) { Cookie cookie = null; Cookie[] cookies = null; // Retrieve cookies from the request cookies = request.getCookies(); // Protection: look for auth and referer cookies if (cookies != null) { // Look for the referer cookie for (int i = 0; i < cookies.length; i++) { // Look for the referer cookie if ((cookies[i].getName()).equals(cookieName)) { // Cache cookie cookie = cookies[i]; logger.debug("Cookie already exists: " + cookie.getValue()); // Exit break; } } } return cookie; } /** * Add a new cookie to the response * * @param response HTTP response * @param krbCookie cookie */ private void addKrbCookie(HttpServletResponse response, Cookie krbCookie) { boolean sendCookies = true; if (valveConf.getSessionConfig().isSessionEnabled().equals("true")) { if (valveConf.getSessionConfig().getSendCookies().equals("false")) { sendCookies = false; } } if (!sendCookies) { //add Krb cookie into the response response.addCookie(krbCookie); } } /** * Adds a new Kerberos subject into the vector * * @param key subject key * @param sub subject */ private void addKrbSubject(String key, Subject sub) { krbSubjects.put(key, sub); } /** * Gets a kerberos subject from the vector * * @param key subject key * * @return subject */ private Subject getKrbSubject(String key) { Subject sub = null; if (krbSubjects != null) { sub = krbSubjects.get(key); } return sub; } /** * Deletes a Kerberos subject * * @param key subject key * * @return if the subject was deleted */ private boolean deleteKrbSubject(String key) { Subject sub = null; boolean result = false; if (krbSubjects != null) { sub = krbSubjects.remove(key); if (sub != null) { result = true; } } return result; } /** * Looks for Kerberos credentials in the credentials * * @return */ private boolean lookForKrbCreds(Credentials creds) { //check if Krb subject is Ok boolean krbCredFound = false; if (creds.getCredential(KRB5_ID) != null) { Subject krbSubject = creds.getCredential(KRB5_ID).getSubject(); if (krbSubject != null) { krbCredFound = true; //set new Krb cred creds.getCredential(KRB5_ID).setKrbSubject(krbSubject); } } return krbCredFound; } /** * Creates credentials for managing double authentication * * @param request HTTP request * @param krbSubject user subject */ private void createCredsDoubleAuthN(HttpServletRequest request, Credentials creds, Subject krbSubject) { //set creds String username = request.getParameter("UserIDKrb"); String password = request.getParameter("PasswordKrb"); //Add krb creds Credential krb5Cred = new Credential(KRB5_ID); krb5Cred.setKrbSubject(krbSubject); krb5Cred.setUsername(getPrincipalFromSubject(krbSubject)); creds.add(krb5Cred); //Add root creds Credential rootCred = new Credential("root"); rootCred.setUsername(username); rootCred.setPassword(password); //add them to creds creds.add(rootCred); } /** * Gets the principal from the subject * * @param subject user subject * * @return principal */ public String getPrincipalFromSubject(Subject subject) { String principal = null; logger.debug("Getting principal from Subject"); try { Set principals = subject.getPrincipals(); if (!principals.isEmpty()) { logger.debug("Subject contains at least one Principal"); Iterator it = principals.iterator(); if (it.hasNext()) { Principal ppal = (Principal) it.next(); principal = ppal.getName().substring(0, ppal.getName().indexOf("@")); logger.debug("Getting the first principal: " + principal); } } } catch (Exception e) { logger.error("Error retrieving the client's Principal from the Subject: " + e.getMessage(), e); } return principal; } /** * Sets Valve configuration parameters * * @param request HTTP request */ public void setValveParams(HttpServletRequest request) { // Read HTTP request attributes try { authCookieName = valveConf.getAuthCookieName(); logger.debug("authCookieName: " + authCookieName); refererCookieName = valveConf.getRefererCookieName(); logger.debug("refererCookieName: " + refererCookieName); authCookieDomain = valveConf.getAuthCookieDomain(); authCookiePath = valveConf.getAuthCookiePath(); try { authMaxAge = Integer.parseInt(valveConf.getAuthMaxAge()); } catch (NumberFormatException nfe) { } authenticationProcessClsName = valveConf.getAuthenticationProcessImpl(); KrbLoginUrl = valveConf.getKrbConfig().getKrbLoginUrl(); KrbUsrPwdCrawlerUrl = valveConf.getKrbConfig().getKrbUsrPwdCrawlerUrl(); loginUrl = valveConf.getLoginUrl(); //Set Kerberos and Session vars maxSessionAge = (new Long(valveConf.getSessionConfig().getMaxSessionAge())).longValue(); sessionTimeout = (new Long(valveConf.getSessionConfig().getSessionTimeout())).longValue(); sessionCleanup = (new Long(valveConf.getSessionConfig().getSessionCleanup())).longValue(); //Is it SAML if (valveConf.getSAMLConfig().isSAML().equals("true")) { isSAML = true; } //Is it Kerberos? if (valveConf.getKrbConfig().isKerberos().equals("true")) { isKerberos = true; //Is it Negotiate? if (valveConf.getKrbConfig().isNegotiate().equals("true")) { isNegotiate = true; } else { isNegotiate = false; } } else { isKerberos = false; } //Set Session Vars if (valveConf.getSessionConfig().isSessionEnabled().equals("true")) { isSessionEnabled = true; } else { isSessionEnabled = false; } if (valveConf.getKrbConfig().isKrbUsrPwdCrawler().equals("true")) { KrbUsrPwdCrawler = true; } else { KrbUsrPwdCrawler = false; } if (valveConf.getKrbConfig().isKrbAdditionalAuthN().equals("true")) { KrbAdditionalAuthN = true; } else { KrbAdditionalAuthN = false; } //Session support: cleanup process if ((isSessionEnabled) || (isKerberos)) { logger.debug("Getting sessionTimer instance"); sessionTimer = SessionTimer.getInstance(isSessionEnabled, isKerberos, sessionCleanup); sessionTimer.setTimer(); } } catch (Exception e) { logger.error("Exception reading Configuration parameters: " + e.getMessage(), e); } } /** * Reads the valve configuration path * * @return */ public String readValveConfigPath() { String valveConfigPath = null; try { //Get Config javax.naming.Context ctx = new javax.naming.InitialContext(); javax.naming.Context env = (javax.naming.Context) ctx.lookup("java:comp/env"); //Get gsaValveConfigPath valveConfigPath = (String) env.lookup("gsaValveConfigPath"); } catch (NamingException e) { logger.debug("Error when reading the Valve Config Path " + e); } return valveConfigPath; } /** * Creates the referer cookie * */ private void createRefererCookie(Cookie gsaRefererCookie) { // Instantiate authentication cookie with default value gsaRefererCookie = new Cookie(refererCookieName, valveConf.getTestFormsCrawlUrl()); // Set cookie domain gsaRefererCookie.setDomain(authCookieDomain); // Set cookie path gsaRefererCookie.setPath(authCookiePath); // Set expiration time gsaRefererCookie.setMaxAge(authMaxAge); } /** * Redirects the user back to the client's URL that checks the SAML * authentication process * * @param response HTTP response * @param cookies authentication cookies * @param sessionID session identifier * * @throws IOException */ private void redirectingSAML(HttpServletResponse response, Cookie[] cookies, String sessionID) throws IOException, ValveConfigurationException { //create the artifact long maxArtifactAge = new Long(valveConf.getSAMLConfig().getMaxArtifactAge()).longValue(); //Instead of using the username, we'll use the session id String artifact = SAMLArtifactProcessor.getInstance(maxArtifactAge).storeArtifact(sessionID); //Create the referer var refererSAML = ValveUtils.getGSAHost("", valveConf, cookies, valveConf.getRefererCookieName()); //redirect to the GSA's Artifact consumer SAMLAuthN samlAuthN = new SAMLAuthN(); String redirectURL = null; try { redirectURL = samlAuthN.redirectLocation(refererSAML, relayState, artifact); } catch (UnsupportedEncodingException e) { logger.error("Error when creating the SAML redirecting URL: " + e); } logger.debug("SAML:Redirecting to " + redirectURL); response.sendRedirect(redirectURL); } /** * Constructs the SAML URL for Kerberos authentication * * @return SAML URL for Kerberos authentication */ private String contructKrbLoginURL() { String loginURL = null; try { boolean isSAML = new Boolean(valveConf.getSAMLConfig().isSAML()).booleanValue(); if (!isSAML) { loginURL = KrbLoginUrl; } else { loginURL = KrbLoginUrl + "?SAMLRequest=" + URLEncoder.encode(samlRequest, encoder) + "&RelayState=" + URLEncoder.encode(relayState, encoder); } } catch (Exception ex) { logger.error("Error during Kerberos Login URL construction: " + ex); } return loginURL; } /** * Checks if it's a Kerberos process when there is double authentication * process. * * @param krbCookie kerberos authentication cookie * * @return boolean - if it's Kerberos processing point */ private boolean isKrbProcess(Cookie krbCookie) { boolean isKrbProcess = false; try { if ((krbCookie != null) && (!isSAML)) { isKrbProcess = false; } else { if (!isSAML) { //Krb cookie exists for Forms based authentication isKrbProcess = true; } else { //is SAML if (krbCookie == null) { //Krb cookie does not exist. First authentication process //Lets process Krb authn isKrbProcess = true; } else { //check if this is part of first authentication process //or it's part of a reauthenication one (so that the krb cookie already exists) Subject krbSubj = getKrbSubject(krbCookie.getValue()); if (krbSubj == null) { //the Krb process has not been launched yet isKrbProcess = true; } else { //the Krb process was already launched isKrbProcess = false; } } } } } catch (Exception ex) { logger.error("Error during checking if it's Kerberos process: " + ex); isKrbProcess = false; } return isKrbProcess; } }