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

import java.io.IOException;
import java.security.Principal;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;

import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Manager;
import org.apache.catalina.Realm;
import org.apache.catalina.Session;
import org.apache.catalina.SessionListener;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.tomcat.util.res.StringManager;

/**
 * A <strong>Valve</strong> that supports a "single sign on" user experience, where the security identity of a user who
 * successfully authenticates to one web application is propagated to other web applications in the same security
 * domain. For successful use, the following requirements must be met:
 * <ul>
 * <li>This Valve must be configured on the Container that represents a virtual host (typically an implementation of
 * <code>Host</code>).</li>
 * <li>The <code>Realm</code> that contains the shared user and role information must be configured on the same
 * Container (or a higher one), and not overridden at the web application level.</li>
 * <li>The web applications themselves must use one of the standard Authenticators found in the
 * <code>org.apache.catalina.authenticator</code> package.</li>
 * </ul>
 */
public class SingleSignOn extends ValveBase {

    private static final StringManager sm = StringManager.getManager(SingleSignOn.class);

    /*
     * The engine at the top of the container hierarchy in which this SSO Valve has been placed. It is used to get back
     * to a session object from a SingleSignOnSessionKey and is updated when the Valve starts and stops.
     */
    private Engine engine;

    // ------------------------------------------------------ Constructor

    public SingleSignOn() {
        super(true);
    }


    // ----------------------------------------------------- Instance Variables

    /**
     * The cache of SingleSignOnEntry instances for authenticated Principals, keyed by the cookie value that is used to
     * select them.
     */
    protected Map<String,SingleSignOnEntry> cache = new ConcurrentHashMap<>();

    /**
     * Indicates whether this valve should require a downstream Authenticator to reauthenticate each request, or if it
     * itself can bind a UserPrincipal and AuthType object to the request.
     */
    private boolean requireReauthentication = false;

    /**
     * Optional SSO cookie domain.
     */
    private String cookieDomain;

    /**
     * SSO cookie name, the default value is <code>JSESSIONIDSSO</code>.
     */
    private String cookieName = Constants.SINGLE_SIGN_ON_COOKIE;

    // ------------------------------------------------------------- Properties

    /**
     * Returns the optional cookie domain. May return null.
     *
     * @return The cookie domain
     */
    public String getCookieDomain() {
        return cookieDomain;
    }


    /**
     * Sets the domain to be used for sso cookies.
     *
     * @param cookieDomain cookie domain name
     */
    public void setCookieDomain(String cookieDomain) {
        if (cookieDomain != null && cookieDomain.trim().isEmpty()) {
            this.cookieDomain = null;
        } else {
            this.cookieDomain = cookieDomain;
        }
    }


    /**
     * @return the cookie name
     */
    public String getCookieName() {
        return cookieName;
    }


    /**
     * Set the cookie name that will be used for the SSO cookie.
     *
     * @param cookieName the cookieName to set
     */
    public void setCookieName(String cookieName) {
        this.cookieName = cookieName;
    }


    /**
     * Gets whether each request needs to be reauthenticated (by an Authenticator downstream in the pipeline) to the
     * security <code>Realm</code>, or if this Valve can itself bind security info to the request based on the presence
     * of a valid SSO entry without rechecking with the <code>Realm</code>.
     *
     * @return <code>true</code> if it is required that a downstream Authenticator reauthenticate each request before
     *             calls to <code>HttpServletRequest.setUserPrincipal()</code> and
     *             <code>HttpServletRequest.setAuthType()</code> are made; <code>false</code> if the <code>Valve</code>
     *             can itself make those calls relying on the presence of a valid SingleSignOn entry associated with the
     *             request.
     *
     * @see #setRequireReauthentication
     */
    public boolean getRequireReauthentication() {
        return requireReauthentication;
    }


    /**
     * Sets whether each request needs to be reauthenticated (by an Authenticator downstream in the pipeline) to the
     * security <code>Realm</code>, or if this Valve can itself bind security info to the request, based on the presence
     * of a valid SSO entry, without rechecking with the <code>Realm</code>.
     * <p>
     * If this property is <code>false</code> (the default), this <code>Valve</code> will bind a UserPrincipal and
     * AuthType to the request if a valid SSO entry is associated with the request. It will not notify the security
     * <code>Realm</code> of the incoming request.
     * <p>
     * This property should be set to <code>true</code> if the overall server configuration requires that the
     * <code>Realm</code> reauthenticate each request thread. An example of such a configuration would be one where the
     * <code>Realm</code> implementation provides security for both a web tier and an associated EJB tier, and needs to
     * set security credentials on each request thread in order to support EJB access.
     * <p>
     * If this property is set to <code>true</code>, this Valve will set flags on the request notifying the downstream
     * Authenticator that the request is associated with an SSO session. The Authenticator will then call its
     * {@link AuthenticatorBase#reauthenticateFromSSO reauthenticateFromSSO} method to attempt to reauthenticate the
     * request to the <code>Realm</code>, using any credentials that were cached with this Valve.
     * <p>
     * The default value of this property is <code>false</code>, in order to maintain backward compatibility with
     * previous versions of Tomcat.
     *
     * @param required <code>true</code> if it is required that a downstream Authenticator reauthenticate each request
     *                     before calls to <code>HttpServletRequest.setUserPrincipal()</code> and
     *                     <code>HttpServletRequest.setAuthType()</code> are made; <code>false</code> if the
     *                     <code>Valve</code> can itself make those calls relying on the presence of a valid
     *                     SingleSignOn entry associated with the request.
     *
     * @see AuthenticatorBase#reauthenticateFromSSO
     */
    public void setRequireReauthentication(boolean required) {
        this.requireReauthentication = required;
    }


    // ---------------------------------------------------------- Valve Methods

    /**
     * Perform single-sign-on support processing for this request.
     *
     * @param request  The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException      if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {

        request.removeNote(Constants.REQ_SSOID_NOTE);

        // Has a valid user already been authenticated?
        if (containerLog.isTraceEnabled()) {
            containerLog.trace(sm.getString("singleSignOn.debug.invoke", request.getRequestURI()));
        }
        if (request.getUserPrincipal() != null) {
            if (containerLog.isDebugEnabled()) {
                containerLog
                        .debug(sm.getString("singleSignOn.debug.hasPrincipal", request.getUserPrincipal().getName()));
            }
            getNext().invoke(request, response);
            return;
        }

        // Check for the single sign on cookie
        if (containerLog.isTraceEnabled()) {
            containerLog.trace(sm.getString("singleSignOn.debug.cookieCheck"));
        }
        Cookie cookie = null;
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie value : cookies) {
                if (cookieName.equals(value.getName())) {
                    cookie = value;
                    break;
                }
            }
        }
        if (cookie == null) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.cookieNotFound"));
            }
            getNext().invoke(request, response);
            return;
        }

        // Look up the cached Principal associated with this cookie value
        if (containerLog.isTraceEnabled()) {
            containerLog.trace(sm.getString("singleSignOn.debug.principalCheck", cookie.getValue()));
        }
        SingleSignOnEntry entry = cache.get(cookie.getValue());
        if (entry != null) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.principalFound",
                        entry.getPrincipal() != null ? entry.getPrincipal().getName() : "", entry.getAuthType()));
            }
            request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
            // Only set security elements if reauthentication is not required
            if (!getRequireReauthentication()) {
                request.setAuthType(entry.getAuthType());
                request.setUserPrincipal(entry.getPrincipal());
            }
        } else {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.principalNotFound", cookie.getValue()));
            }
            // No need to return a valid SSO session ID
            cookie.setValue("REMOVE");
            // Age of zero will trigger removal
            cookie.setMaxAge(0);
            // Domain and path have to match the original cookie to 'replace'
            // the original cookie
            cookie.setPath("/");
            String domain = getCookieDomain();
            if (domain != null) {
                cookie.setDomain(domain);
            }
            /*
             * This is going to trigger a Set-Cookie header. While the value is not security sensitive, ensure that
             * expectations for secure, httpOnly and Partitioned are met.
             */
            cookie.setSecure(request.isSecure());
            if (request.getServletContext().getSessionCookieConfig().isHttpOnly() ||
                    request.getContext().getUseHttpOnly()) {
                cookie.setHttpOnly(true);
            }
            cookie.setAttribute(Constants.COOKIE_PARTITIONED_ATTR,
                    Boolean.toString(request.getContext().getUsePartitioned()));

            response.addCookie(cookie);
        }

        // Invoke the next Valve in our pipeline
        getNext().invoke(request, response);
    }


    // ------------------------------------------------------ Protected Methods

    /**
     * Process a session destroyed event by removing references to that session from the caches and - if the session
     * destruction is the result of a logout - destroy the associated SSO session.
     *
     * @param ssoId   The id of the SSO session with which the destroyed session was associated
     * @param session The session that has been destroyed
     */
    public void sessionDestroyed(String ssoId, Session session) {

        if (!getState().isAvailable()) {
            return;
        }

        // Was the session destroyed as the result of a timeout or context stop?
        // If so, we'll just remove the expired session from the SSO. If the
        // session was logged out, we'll log out of all session associated with
        // the SSO.
        if (((session.getMaxInactiveInterval() > 0) &&
                (session.getIdleTimeInternal() >= session.getMaxInactiveInterval() * 1000L)) ||
                (!session.getManager().getContext().getState().isAvailable())) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.sessionTimeout", ssoId, session));
            }
            removeSession(ssoId, session);
        } else {
            // The session was logged out.
            // Deregister this single session id, invalidating
            // associated sessions
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.sessionLogout", ssoId, session));
            }
            // First remove the session that we know has expired / been logged
            // out since it has already been removed from its Manager and, if
            // we don't remove it first, deregister() will log a warning that it
            // can't be found
            removeSession(ssoId, session);
            // If the SSO session was only associated with one web app the call
            // above will have removed the SSO session from the cache
            if (cache.containsKey(ssoId)) {
                deregister(ssoId);
            }
        }
    }


    /**
     * Associate the specified single sign on identifier with the specified Session.
     *
     * @param ssoId   Single sign on identifier
     * @param session Session to be associated
     *
     * @return <code>true</code> if the session was associated to the given SSO session, otherwise <code>false</code>
     */
    protected boolean associate(String ssoId, Session session) {
        SingleSignOnEntry sso = cache.get(ssoId);
        if (sso == null) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.associateFail", ssoId, session));
            }
            return false;
        } else {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.associate", ssoId, session));
            }
            sso.addSession(this, ssoId, session);
            return true;
        }
    }


    /**
     * Deregister the specified single sign on identifier, and invalidate any associated sessions.
     *
     * @param ssoId Single sign on identifier to deregister
     */
    protected void deregister(String ssoId) {

        // Look up and remove the corresponding SingleSignOnEntry
        SingleSignOnEntry sso = cache.remove(ssoId);

        if (sso == null) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.deregisterFail", ssoId));
            }
            return;
        }

        // Expire any associated sessions
        Set<SingleSignOnSessionKey> ssoKeys = sso.findSessions();
        if (ssoKeys.isEmpty()) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.deregisterNone", ssoId));
            }
        }
        for (SingleSignOnSessionKey ssoKey : ssoKeys) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.deregister", ssoKey, ssoId));
            }
            // Invalidate this session
            expire(ssoKey);
        }

        // NOTE: Clients may still possess the old single sign on cookie,
        // but it will be removed on the next request since it is no longer
        // in the cache
    }


    private void expire(SingleSignOnSessionKey key) {
        if (engine == null) {
            containerLog.warn(sm.getString("singleSignOn.sessionExpire.engineNull", key));
            return;
        }
        Container host = engine.findChild(key.getHostName());
        if (host == null) {
            containerLog.warn(sm.getString("singleSignOn.sessionExpire.hostNotFound", key));
            return;
        }
        Context context = (Context) host.findChild(key.getContextName());
        if (context == null) {
            containerLog.warn(sm.getString("singleSignOn.sessionExpire.contextNotFound", key));
            return;
        }
        Manager manager = context.getManager();
        if (manager == null) {
            containerLog.warn(sm.getString("singleSignOn.sessionExpire.managerNotFound", key));
            return;
        }
        Session session;
        try {
            session = manager.findSession(key.getSessionId());
        } catch (IOException ioe) {
            containerLog.warn(sm.getString("singleSignOn.sessionExpire.managerError", key), ioe);
            return;
        }
        if (session == null) {
            containerLog.warn(sm.getString("singleSignOn.sessionExpire.sessionNotFound", key));
            return;
        }
        session.expire();
    }


    /**
     * Attempts reauthentication to the given <code>Realm</code> using the credentials associated with the single
     * sign-on session identified by argument <code>ssoId</code>.
     * <p>
     * If reauthentication is successful, the <code>Principal</code> and authorization type associated with the SSO
     * session will be bound to the given <code>Request</code> object via calls to {@link Request#setAuthType
     * Request.setAuthType()} and {@link Request#setUserPrincipal Request.setUserPrincipal()}
     * </p>
     *
     * @param ssoId   identifier of SingleSignOn session with which the caller is associated
     * @param realm   Realm implementation against which the caller is to be authenticated
     * @param request the request that needs to be authenticated
     *
     * @return <code>true</code> if reauthentication was successful, <code>false</code> otherwise.
     */
    protected boolean reauthenticate(String ssoId, Realm realm, Request request) {

        if (ssoId == null || realm == null) {
            return false;
        }

        boolean reauthenticated = false;

        SingleSignOnEntry entry = cache.get(ssoId);
        if (entry != null && entry.getCanReauthenticate()) {

            String username = entry.getUsername();
            if (username != null) {
                Principal reauthPrincipal = realm.authenticate(username, entry.getPassword());
                if (reauthPrincipal != null) {
                    reauthenticated = true;
                    // Bind the authorization credentials to the request
                    request.setAuthType(entry.getAuthType());
                    request.setUserPrincipal(reauthPrincipal);
                }
            }
        }

        return reauthenticated;
    }


    /**
     * Register the specified Principal as being associated with the specified value for the single sign on identifier.
     *
     * @param ssoId     Single sign on identifier to register
     * @param principal Associated user principal that is identified
     * @param authType  Authentication type used to authenticate this user principal
     * @param username  Username used to authenticate this user
     * @param password  Password used to authenticate this user
     */
    protected void register(String ssoId, Principal principal, String authType, String username, String password) {

        if (containerLog.isDebugEnabled()) {
            containerLog.debug(sm.getString("singleSignOn.debug.register", ssoId,
                    principal != null ? principal.getName() : "", authType));
        }

        cache.put(ssoId, new SingleSignOnEntry(principal, authType, username, password));
    }


    /**
     * Updates any <code>SingleSignOnEntry</code> found under key <code>ssoId</code> with the given authentication data.
     * <p>
     * The purpose of this method is to allow an SSO entry that was established without a username/password combination
     * (i.e. established following DIGEST or CLIENT_CERT authentication) to be updated with a username and password if
     * one becomes available through a subsequent BASIC or FORM authentication. The SSO entry will then be usable for
     * reauthentication.
     * <p>
     * <b>NOTE:</b> Only updates the SSO entry if a call to <code>SingleSignOnEntry.getCanReauthenticate()</code>
     * returns <code>false</code>; otherwise, it is assumed that the SSO entry already has sufficient information to
     * allow reauthentication and that no update is needed.
     *
     * @param ssoId     identifier of Single sign to be updated
     * @param principal the <code>Principal</code> returned by the latest call to <code>Realm.authenticate</code>.
     * @param authType  the type of authenticator used (BASIC, CLIENT_CERT, DIGEST or FORM)
     * @param username  the username (if any) used for the authentication
     * @param password  the password (if any) used for the authentication
     *
     * @return <code>true</code> if the credentials were updated, otherwise <code>false</code>
     */
    protected boolean update(String ssoId, Principal principal, String authType, String username, String password) {

        SingleSignOnEntry sso = cache.get(ssoId);
        if (sso != null && !sso.getCanReauthenticate()) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(sm.getString("singleSignOn.debug.update", ssoId, authType));
            }

            sso.updateCredentials(principal, authType, username, password);
            return true;
        }
        return false;
    }


    /**
     * Remove a single Session from a SingleSignOn. Called when a session is timed out and no longer active.
     *
     * @param ssoId   Single sign on identifier from which to remove the session.
     * @param session the session to be removed.
     */
    protected void removeSession(String ssoId, Session session) {

        if (containerLog.isDebugEnabled()) {
            containerLog.debug(sm.getString("singleSignOn.debug.removeSession", session, ssoId));
        }

        // Get a reference to the SingleSignOn
        SingleSignOnEntry entry = cache.get(ssoId);
        if (entry == null) {
            return;
        }

        // Remove the inactive session from SingleSignOnEntry
        entry.removeSession(session);

        // If there are no sessions left in the SingleSignOnEntry,
        // deregister the entry.
        if (entry.findSessions().isEmpty()) {
            deregister(ssoId);
        }
    }


    protected SessionListener getSessionListener(String ssoId) {
        return new SingleSignOnListener(ssoId);
    }


    @Override
    protected void startInternal() throws LifecycleException {
        Container c = getContainer();
        while (c != null && !(c instanceof Engine)) {
            c = c.getParent();
        }
        if (c != null) {
            engine = (Engine) c;
        }
        super.startInternal();
    }


    @Override
    protected void stopInternal() throws LifecycleException {
        super.stopInternal();
        engine = null;
    }
}
