Package com.google.gsa.valve.rootAuth

Source Code of com.google.gsa.valve.rootAuth.RootAuthenticationProcess

/**
  * 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.valve.rootAuth;

import java.io.IOException;


import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.apache.commons.httpclient.HttpException;
import org.apache.log4j.Logger;
import org.apache.regexp.RE;

import com.google.gsa.AuthenticationProcessImpl;
import com.google.gsa.Credentials;
import com.google.gsa.valve.configuration.ValveConfiguration;
import com.google.gsa.valve.configuration.ValveRepositoryConfiguration;

import java.util.HashMap;
import java.util.Map;
import java.util.Vector;


/**
* This is the default class that processes the authentication. It reads the
* repositories defined in the config file and invokes those repository's
* authentication classes that require it to be triggered. Those that includes
* the tag "checkauthN" set to false are not processed.
* <p>
* The name of the authentication classes that need to be processed are included
* in a vector that is reused multiple times. Whenever a new authentication
* process needs to be relaunched, all these classes are processed and the
* individual authentication process is treated.
* <p>
* There is a special repository named "root" that is treatly in a special way.
* If any repository is named as "root", it means this is the main authentication
* mechanim and that's why it's trated first. If it fails, the authentication
* process stops here and the return result is an error. If not, the whole
* processing continues.
*
* @see RootAuthorizationProcess
*
*/
public class RootAuthenticationProcess implements AuthenticationProcessImpl {

    //logger
    private Logger logger = null;

    //Valve configuration
    private ValveConfiguration valveConf = null;

    //Support for Krb creds
    boolean isKerberos = false;
    boolean isNegotiate = false;
    String loginUrl = null;

    private Vector<Cookie> rootAuthCookies = new Vector<Cookie>();
    private Vector<Cookie> repositoryAuthCookies = new Vector<Cookie>();

    //Map that represents the authentication modules
    private Map<String, AuthenticationProcessImpl> authenticationImplementations =
        new HashMap<String, AuthenticationProcessImpl>();

    //Map that represents the order of the authentication modules
    private Map<Integer, String> authenticationImplementationsOrder =
        new HashMap<Integer, String>();


    /**
     * Class constructor
     *
     */
    public RootAuthenticationProcess() {

        // Invoke parent constructor
        super();

        // Instantiate logger
        logger = Logger.getLogger(RootAuthenticationProcess.class);

        logger.debug("Initializing " +
                     RootAuthenticationProcess.class.getName());


    }

    /**
     * Sets the request is a Kerberos negotiation process
     * 
     * @param newIsNegotiate boolean - if it's a negotiation process
     */
    public void setIsNegotiate(boolean newIsNegotiate) {
        isNegotiate = newIsNegotiate;
    }

    /**
     * Gets if the request is a Kerberos negotiation process
     *
     * @return boolean - if it's a negotiation process
     */
    public boolean getIsNegotiate() {
        return isNegotiate;
    }


    /**
     * This is the main method that drives the whole authentication
     * process. It launches each individual authentication method declared in
     * the configuration files. Those that includes the tag "checkauthN" set to
     * false are not processed.
     * <p>
     * The name of the authentication classes that need to be processed are included
     * in a vector that is reused multiple times. Whenever a new authentication
     * process needs to be relaunched, all these classes are processed and the
     * individual authentication process is treated.
     * <p>
     * It returns the HTTP error code associated to the process result. If it was
     * OK, this methods returns a 200 and 401 (unauthorized) otherwise.
     * <p>
     * There is a special repository named "root" that is treatly in a special way.
     * If any repository is named as "root", it means this is the main authentication
     * mechanim and that's why it's trated first. If it fails, the authentication
     * process stops here and the return result is an error. If not, the whole
     * processing continues.
     * <p>
     * If there is a "root" repository and the authentication process for this
     * repository is OK, although any other repository would fail, the overall
     * authentication method returns an OK. If there is not such a "root"
     * repository, any authentication error will cause the authentication process
     * to fail.
     *
     * @param request HTTP request
     * @param response HTTP response
     * @param authCookies vector that contains the authentication cookies
     * @param url the document url
     * @param creds an array of credentials for all external sources
     * @param id the default credential id to be retrieved from creds
       
     * @return the HTTP error code
       
     * @throws HttpException
     * @throws IOException
     */
    public int authenticate(HttpServletRequest request,
                            HttpServletResponse response,
                            Vector<Cookie> authCookies, String url,
                            Credentials creds, String id) throws HttpException,
                                                                 IOException {

        // Initialize status code
        int rootStatusCode = HttpServletResponse.SC_UNAUTHORIZED;
        int repositoryAuthStatusCode = HttpServletResponse.SC_UNAUTHORIZED;
        //Check if authn is Ok in multiple repository
        boolean repositoryOKAuthN = false;

        //clear authCookies
        authCookies.clear();

        boolean rootAuthNDefined = false;
        logger.debug("AuthN authenticate [" + url + "]");

        //Read vars
        if (valveConf != null) {
            isKerberos =
                    new Boolean(valveConf.getKrbConfig().isKerberos()).booleanValue();
            if (isKerberos) {
                isNegotiate =
                        new Boolean(valveConf.getKrbConfig().isNegotiate()).booleanValue();
            }
            loginUrl = valveConf.getLoginUrl();
        } else {
            logger.error("Configuration error: Config file is not present");
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                               "Configuration error - Kerberos is not set properly");
            return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        }

        //ValveHost: it's the same URL as the login page, without
        String valveHost =
            loginUrl.substring(0, loginUrl.lastIndexOf("/") + 1);

        RE internal = new RE(valveHost, RE.MATCH_CASEINDEPENDENT);

        // The host and URL of the GSA for the search
        //TODO add support for multiple GSA's
        RE query = new RE("/search", RE.MATCH_CASEINDEPENDENT);


        //Request has come from the same host as the valve, so must be the login authenticate
        if (internal.match(url)) {

            //Authentication vars
            String repositoryID = null;
            AuthenticationProcessImpl authProcess = null;
            ValveRepositoryConfiguration repositoryConfig = null;

            int order = 1;
            int size = authenticationImplementationsOrder.size();
            if (authenticationImplementationsOrder == null) {
                order = 0;
                logger.error("No Authentication module has been defined. Please check and add those needed at config file");
            }

            while ((1 <= order) && (order <= size)) {

                //Get the repository ID
                logger.debug("###Processing repository # " + order + " ###");
                Integer orderInt = new Integer(order);
                if (authenticationImplementationsOrder.containsKey(orderInt)) {
                    repositoryID =
                            authenticationImplementationsOrder.get(orderInt);
                } else {
                    logger.error("Error during processing authentication methods. Order is not valid");
                    break;
                }

                //Get the Repository config and authentication class                                                   
                authProcess = authenticationImplementations.get(repositoryID);
                repositoryConfig = valveConf.getRepository(repositoryID);

                logger.debug("Authenticating ID: " + repositoryConfig.getId());
                if (repositoryConfig.getId().equals("root")) {
                    //Root should be used for main authentication against an identity repository (LDAP, DB, ..)
                    //and should not be used as a content repository that contains documents
                    try {
                        //add support to cookie array
                        rootAuthCookies.clear();
                        rootStatusCode =
                                authProcess.authenticate(request, response,
                                                         rootAuthCookies, url,
                                                         creds, "root");
                        logger.info("Repository authentication - " +
                                    repositoryConfig.getId() +
                                    " completed. Response was " +
                                    rootStatusCode);
                        if (rootStatusCode ==
                            HttpServletResponse.SC_UNAUTHORIZED) {
                            logger.error("Root AuthN failed");
                        } else {
                            //Support to cookie array
                            if (rootStatusCode == HttpServletResponse.SC_OK) {
                                logger.debug("Root AuthN is SC_OK (200)");
                                if (!rootAuthCookies.isEmpty()) {
                                    logger.debug("Root AuthN returns cookies");
                                    for (int j = 0; j < rootAuthCookies.size();
                                         j++) {
                                        logger.debug("Root Cookie found: " +
                                                     rootAuthCookies.elementAt(j).getName() +
                                                     ":" +
                                                     rootAuthCookies.elementAt(j).getValue());
                                        authCookies.add(rootAuthCookies.elementAt(j));
                                    }
                                } else {
                                    logger.debug("Root AuthN does NOT return cookies");
                                }
                            }
                        }

                        //If no repository is defined called root then rootStatusCode must be set to OK
                        // This flag is used to indicate that a root repository has been defined.
                        rootAuthNDefined = true;
                        //
                    } catch (Exception e) {
                        logger.debug("Exception with authentication for ID: " +
                                     repositoryConfig.getId() + " - " +
                                     e.getMessage());
                        rootAuthNDefined = true;
                    }
                } else {
                    try {

                        //add support to cookie array
                        repositoryAuthCookies.clear();

                        logger.debug("Let's do the authentication");

                        repositoryAuthStatusCode =
                                authProcess.authenticate(request, response,
                                                         repositoryAuthCookies,
                                                         url, creds,
                                                         repositoryConfig.getId());

                        //add support to cookie array
                        if (repositoryAuthStatusCode ==
                            HttpServletResponse.SC_OK) {
                            logger.debug("Repository AuthN [" +
                                         repositoryConfig.getId() +
                                         "] is SC_OK (200)");
                            //check if multiple repository is set to valid
                            if (repositoryOKAuthN == false) {
                                repositoryOKAuthN = true;
                            }
                            //check if cookie array is not empty and consume it
                            if (!repositoryAuthCookies.isEmpty()) {
                                logger.debug("Repository AuthN [" +
                                             repositoryConfig.getId() +
                                             "] returns " +
                                             repositoryAuthCookies.size() +
                                             " cookies");
                                for (int j = 0;
                                     j < repositoryAuthCookies.size(); j++) {
                                    logger.debug("Repository Cookie found: " +
                                                 repositoryAuthCookies.elementAt(j).getName() +
                                                 ":" +
                                                 repositoryAuthCookies.elementAt(j).getValue());
                                    authCookies.add(repositoryAuthCookies.elementAt(j));
                                }
                            } else {
                                logger.debug("Repository AuthN [" +
                                             repositoryConfig.getId() +
                                             "] does NOT return cookies");
                            }
                        }

                        //end Krb support
                        logger.info("Repository authentication - " +
                                    repositoryConfig.getId() +
                                    " completed. Response was " +
                                    repositoryAuthStatusCode);
                    } catch (Exception e) {
                        logger.debug("Exception with authentication for ID: " +
                                     repositoryConfig.getId() + " - " +
                                     e.getMessage());
                    }
                }

                //increase order
                order++;
            }
        } else if (query.match(url)) {

            logger.debug("Query pattern [" + url + "]");

            // Don't do anything in here
            rootStatusCode = HttpServletResponse.SC_OK;

        } else {

            logger.error("No pattern defined for URL: " + url +
                         ". It should not have been possible to get here!");

            // Protection
            rootStatusCode = HttpServletResponse.SC_UNAUTHORIZED;

        }

        //add support to multiple repositories
        if ((!rootAuthNDefined) && (repositoryOKAuthN)) {
            //If no root repository has been defined then rootStatusCode has to be set valid, to OK
            rootStatusCode = HttpServletResponse.SC_OK;
        }

        // Return status code
        logger.debug("RootAuthN Complete - Status Code: " + rootStatusCode);

        return rootStatusCode;


    }

    /**
     * Sets the Valve Configuration instance to read the parameters
     * from there
     *
     * @param valveConf the Valve configuration instance
     */
    public void setValveConfiguration(ValveConfiguration valveConf) {

        this.valveConf = valveConf;

        //Protection. Make sure the Map is empty before proceeding
        authenticationImplementations.clear();

        //Authentication process instance
        AuthenticationProcessImpl authenticationProcess = null;

        String repositoryIds[] = valveConf.getRepositoryIds();

        ValveRepositoryConfiguration repository = null;

        int order = 1;

        for (int i = 0; i < repositoryIds.length; i++) {
            try {

                repository = valveConf.getRepository(repositoryIds[i]);

                //Check if repository has to be included in the authentication process. By default set it to true
                boolean checkAuthN = true;
                try {
                    if ((repository.getCheckAuthN() != null) &&
                        (!repository.getCheckAuthN().equals(""))) {
                        checkAuthN =
                                new Boolean(repository.getCheckAuthN()).booleanValue();
                    }
                } catch (Exception e) {
                    logger.error("Error when reading checkAuthN param: " +
                                 e.getMessage(), e);
                    //protection
                    checkAuthN = true;
                }

                if (checkAuthN) {
                    logger.info("Initialising authentication process for " +
                                repository.getId() + " [#" + order + "]");
                    authenticationProcess =
                            (AuthenticationProcessImpl)Class.forName(repository.getAuthN()).newInstance();
                    authenticationProcess.setValveConfiguration(valveConf);
                    //add this authentication process to the Map
                    synchronized (authenticationImplementations) {
                        synchronized (authenticationImplementations) {
                            authenticationImplementations.put(repository.getId(),
                                                              authenticationProcess);
                            authenticationImplementationsOrder.put(new Integer(order),
                                                                   repository.getId());
                            order++;
                        }
                    }

                } else {
                    logger.debug("Authentication process for repository [" +
                                 repository.getId() +
                                 "] is not going to be launched");
                }

            } catch (LinkageError le) {
                logger.error(repository.getId() +
                             " - Can't instantiate class [AuthenticationProcess-LinkageError]: " +
                             le.getMessage(), le);
            } catch (InstantiationException ie) {
                logger.error(repository.getId() +
                             " - Can't instantiate class [AuthenticationProcess-InstantiationException]: " +
                             ie.getMessage(), ie);
            } catch (IllegalAccessException iae) {
                logger.error(repository.getId() +
                             " - Can't instantiate class [AuthenticationProcess-IllegalAccessException]: " +
                             iae.getMessage(), iae);
            } catch (ClassNotFoundException cnfe) {
                logger.error(repository.getId() +
                             " - Can't instantiate class [AuthenticationProcess-ClassNotFoundException]: " +
                             cnfe.getMessage(), cnfe);
            } catch (Exception e) {
                logger.error(repository.getId() +
                             " - Can't instantiate class [AuthenticationProcess-Exception]: " +
                             e.getMessage(), e);
            }
        }
        logger.debug(RootAuthenticationProcess.class.getName() +
                     " initialised");
    }

}
TOP

Related Classes of com.google.gsa.valve.rootAuth.RootAuthenticationProcess

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.