/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.catalina.security;


import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.security.auth.Subject;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.catalina.Globals;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
 * This utility class associates a <code>Subject</code> to the current
 * <code>AccessControlContext</code>. When a <code>SecurityManager</code> is
 * used, the container will always associate the called thread with an
 * AccessControlContext containing only the principal of the requested
 * Servlet/Filter.
 *
 * This class uses reflection to invoke the methods.
 */

public final class SecurityUtil{

    // Note that indexes overlap.
    // A Servlet uses "init", "service", "event", "destroy".
    // A Filter uses "doFilter", "doFilterEvent", "destroy".
    private static final int INIT= 0;
    private static final int SERVICE = 1;
    private static final int DOFILTER = 1;
    private static final int EVENT = 2;
    private static final int DOFILTEREVENT = 2;
    private static final int DESTROY = 3;

    private static final String INIT_METHOD = "init";
    private static final String DOFILTER_METHOD = "doFilter";
    private static final String SERVICE_METHOD = "service";
    private static final String EVENT_METHOD = "event";
    private static final String DOFILTEREVENT_METHOD = "doFilterEvent";
    private static final String DESTROY_METHOD = "destroy";

    /**
     * Cache every class for which we are creating methods.
     */
    private static final Map<Class<?>,Method[]> classCache = new ConcurrentHashMap<>();

    private static final Log log = LogFactory.getLog(SecurityUtil.class);

    private static final boolean packageDefinitionEnabled =
         (System.getProperty("package.definition") == null &&
           System.getProperty("package.access")  == null) ? false : true;

    /**
     * The string resources for this package.
     */
    private static final StringManager sm =
        StringManager.getManager(Constants.PACKAGE);


    /**
     * Perform work as a particular <code>Subject</code>. Here the work
     * will be granted to a <code>null</code> subject.
     *
     * @param methodName the method to apply the security restriction
     * @param targetObject the <code>Servlet</code> on which the method will
     * be called.
     * @throws Exception an execution error occurred
     */
    public static void doAsPrivilege(final String methodName,
                                     final Servlet targetObject) throws Exception {
         doAsPrivilege(methodName, targetObject, null, null, null);
    }


    /**
     * Perform work as a particular <code>Subject</code>. Here the work
     * will be granted to a <code>null</code> subject.
     *
     * @param methodName the method to apply the security restriction
     * @param targetObject the <code>Servlet</code> on which the method will
     * be called.
     * @param targetType <code>Class</code> array used to instantiate a
     * <code>Method</code> object.
     * @param targetArguments <code>Object</code> array contains the runtime
     * parameters instance.
     * @throws Exception an execution error occurred
     */
    public static void doAsPrivilege(final String methodName,
                                     final Servlet targetObject,
                                     final Class<?>[] targetType,
                                     final Object[] targetArguments)
        throws Exception {

         doAsPrivilege(methodName,
                       targetObject,
                       targetType,
                       targetArguments,
                       null);
    }


    /**
     * Perform work as a particular <code>Subject</code>. Here the work
     * will be granted to a <code>null</code> subject.
     *
     * @param methodName the method to apply the security restriction
     * @param targetObject the <code>Servlet</code> on which the method will
     *  be called.
     * @param targetParameterTypes <code>Class</code> array used to instantiate a
     *  <code>Method</code> object.
     * @param targetArguments <code>Object</code> array contains the
     *  runtime parameters instance.
     * @param principal the <code>Principal</code> to which the security
     *  privilege applies
     * @throws Exception an execution error occurred
     */
    public static void doAsPrivilege(final String methodName,
                                     final Servlet targetObject,
                                     final Class<?>[] targetParameterTypes,
                                     final Object[] targetArguments,
                                     Principal principal)
        throws Exception {

        Method method = null;
        Method[] methodsCache = classCache.get(Servlet.class);
        if(methodsCache == null) {
            method = createMethodAndCacheIt(null,
                                            Servlet.class,
                                            methodName,
                                            targetParameterTypes);
        } else {
            method = findMethod(methodsCache, methodName);
            if (method == null) {
                method = createMethodAndCacheIt(methodsCache,
                                                Servlet.class,
                                                methodName,
                                                targetParameterTypes);
            }
        }

        execute(method, targetObject, targetArguments, principal);
    }


    /**
     * Perform work as a particular <code>Subject</code>. Here the work
     * will be granted to a <code>null</code> subject.
     *
     * @param methodName the method to apply the security restriction
     * @param targetObject the <code>Filter</code> on which the method will
     *  be called.
     * @throws Exception an execution error occurred
     */
    public static void doAsPrivilege(final String methodName,
                                     final Filter targetObject)
        throws Exception {

         doAsPrivilege(methodName, targetObject, null, null);
    }


    /**
     * Perform work as a particular <code>Subject</code>. Here the work
     * will be granted to a <code>null</code> subject.
     *
     * @param methodName the method to apply the security restriction
     * @param targetObject the <code>Filter</code> on which the method will
     *  be called.
     * @param targetType <code>Class</code> array used to instantiate a
     *  <code>Method</code> object.
     * @param targetArguments <code>Object</code> array contains the
     *  runtime parameters instance.
     * @throws Exception an execution error occurred
     */
    public static void doAsPrivilege(final String methodName,
                                     final Filter targetObject,
                                     final Class<?>[] targetType,
                                     final Object[] targetArguments)
        throws Exception {

        doAsPrivilege(
                methodName, targetObject, targetType, targetArguments, null);
    }

    /**
     * Perform work as a particular <code>Subject</code>. Here the work
     * will be granted to a <code>null</code> subject.
     *
     * @param methodName the method to apply the security restriction
     * @param targetObject the <code>Filter</code> on which the method will
     *  be called.
     * @param targetParameterTypes <code>Class</code> array used to instantiate a
     *  <code>Method</code> object.
     * @param targetParameterValues <code>Object</code> array contains the
     *  runtime parameters instance.
     * @param principal the <code>Principal</code> to which the security
     *  privilege applies
     * @throws Exception an execution error occurred
     */
    public static void doAsPrivilege(final String methodName,
                                     final Filter targetObject,
                                     final Class<?>[] targetParameterTypes,
                                     final Object[] targetParameterValues,
                                     Principal principal)
        throws Exception {

        Method method = null;
        Method[] methodsCache = classCache.get(Filter.class);
        if(methodsCache == null) {
            method = createMethodAndCacheIt(null,
                                            Filter.class,
                                            methodName,
                                            targetParameterTypes);
        } else {
            method = findMethod(methodsCache, methodName);
            if (method == null) {
                method = createMethodAndCacheIt(methodsCache,
                                                Filter.class,
                                                methodName,
                                                targetParameterTypes);
            }
        }

        execute(method, targetObject, targetParameterValues, principal);
    }


    /**
     * Perform work as a particular <code>Subject</code>. Here the work
     * will be granted to a <code>null</code> subject.
     *
     * @param method the method to apply the security restriction
     * @param targetObject the <code>Servlet</code> on which the method will
     *  be called.
     * @param targetArguments <code>Object</code> array contains the
     *  runtime parameters instance.
     * @param principal the <code>Principal</code> to which the security
     *  privilege applies
     * @throws Exception an execution error occurred
     */
    private static void execute(final Method method,
                                final Object targetObject,
                                final Object[] targetArguments,
                                Principal principal)
        throws Exception {

        try{
            Subject subject = null;
            PrivilegedExceptionAction<Void> pea =
                new PrivilegedExceptionAction<Void>(){
                    @Override
                    public Void run() throws Exception{
                       method.invoke(targetObject, targetArguments);
                       return null;
                    }
            };

            // The first argument is always the request object
            if (targetArguments != null
                    && targetArguments[0] instanceof HttpServletRequest){
                HttpServletRequest request =
                    (HttpServletRequest)targetArguments[0];

                boolean hasSubject = false;
                HttpSession session = request.getSession(false);
                if (session != null){
                    subject =
                        (Subject)session.getAttribute(Globals.SUBJECT_ATTR);
                    hasSubject = (subject != null);
                }

                if (subject == null){
                    subject = new Subject();

                    if (principal != null){
                        subject.getPrincipals().add(principal);
                    }
                }

                if (session != null && !hasSubject) {
                    session.setAttribute(Globals.SUBJECT_ATTR, subject);
                }
            }

            Subject.doAsPrivileged(subject, pea, null);
        } catch( PrivilegedActionException pe) {
            Throwable e;
            if (pe.getException() instanceof InvocationTargetException) {
                e = pe.getException().getCause();
                ExceptionUtils.handleThrowable(e);
            } else {
                e = pe;
            }

            if (log.isDebugEnabled()){
                log.debug(sm.getString("SecurityUtil.doAsPrivilege"), e);
            }

            if (e instanceof UnavailableException)
                throw (UnavailableException) e;
            else if (e instanceof ServletException)
                throw (ServletException) e;
            else if (e instanceof IOException)
                throw (IOException) e;
            else if (e instanceof RuntimeException)
                throw (RuntimeException) e;
            else
                throw new ServletException(e.getMessage(), e);
        }
    }


    /**
     * Find a method stored within the cache.
     * @param methodsCache the cache used to store method instance
     * @param methodName the method to apply the security restriction
     * @return the method instance, null if not yet created.
     */
    private static Method findMethod(Method[] methodsCache,
                                     String methodName){
        if (methodName.equals(INIT_METHOD)){
            return methodsCache[INIT];
        } else if (methodName.equals(DESTROY_METHOD)){
            return methodsCache[DESTROY];
        } else if (methodName.equals(SERVICE_METHOD)){
            return methodsCache[SERVICE];
        } else if (methodName.equals(DOFILTER_METHOD)){
            return methodsCache[DOFILTER];
        } else if (methodName.equals(EVENT_METHOD)){
            return methodsCache[EVENT];
        } else if (methodName.equals(DOFILTEREVENT_METHOD)){
            return methodsCache[DOFILTEREVENT];
        }
        return null;
    }


    /**
     * Create the method and cache it for further re-use.
     * @param methodsCache the cache used to store method instance
     * @param targetType the class on which the method will be called.
     * @param methodName the method to apply the security restriction
     * @param parameterTypes <code>Class</code> array used to instantiate a
     *  <code>Method</code> object.
     * @return the method instance.
     * @throws Exception an execution error occurred
     */
    private static Method createMethodAndCacheIt(Method[] methodsCache,
                                                 Class<?> targetType,
                                                 String methodName,
                                                 Class<?>[] parameterTypes)
            throws Exception {

        if (methodsCache == null) {
            methodsCache = new Method[4];
        }

        Method method = targetType.getMethod(methodName, parameterTypes);

        if (methodName.equals(INIT_METHOD)){
            methodsCache[INIT] = method;
        } else if (methodName.equals(DESTROY_METHOD)){
            methodsCache[DESTROY] = method;
        } else if (methodName.equals(SERVICE_METHOD)){
            methodsCache[SERVICE] = method;
        } else if (methodName.equals(DOFILTER_METHOD)){
            methodsCache[DOFILTER] = method;
        } else if (methodName.equals(EVENT_METHOD)){
            methodsCache[EVENT] = method;
        } else if (methodName.equals(DOFILTEREVENT_METHOD)){
            methodsCache[DOFILTEREVENT] = method;
        }

        classCache.put(targetType, methodsCache);

        return method;
    }


    /**
     * Remove the object from the cache.
     *
     * @param cachedObject The object to remove
     */
    public static void remove(Object cachedObject){
        classCache.remove(cachedObject);
    }


    /**
     * Return the <code>SecurityManager</code> only if Security is enabled AND
     * package protection mechanism is enabled.
     * @return <code>true</code> if package level protection is enabled
     */
    public static boolean isPackageProtectionEnabled(){
        if (packageDefinitionEnabled && Globals.IS_SECURITY_ENABLED){
            return true;
        }
        return false;
    }


}
