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

import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.SessionIdGenerator;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;

public abstract class SessionIdGeneratorBase extends LifecycleBase implements SessionIdGenerator {

    private final Log log = LogFactory.getLog(SessionIdGeneratorBase.class); // must not be static

    private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");

    public static final String DEFAULT_SECURE_RANDOM_ALGORITHM;

    static {
        /*
         * The default is normally SHA1PRNG. This was chosen because a) it is quick and b) it available by default in
         * all JREs. However, it may not be available in some configurations such as those that use a FIPS certified
         * provider. In those cases, use the platform default.
         */
        Set<String> algorithmNames = Security.getAlgorithms("SecureRandom");
        if (algorithmNames.contains("SHA1PRNG")) {
            DEFAULT_SECURE_RANDOM_ALGORITHM = "SHA1PRNG";
        } else {
            // Empty string - This will trigger the use of the platform default.
            DEFAULT_SECURE_RANDOM_ALGORITHM = "";
            Log log = LogFactory.getLog(SessionIdGeneratorBase.class);
            log.warn(sm.getString("sessionIdGeneratorBase.noSHA1PRNG"));
        }
    }

    /**
     * Queue of random number generator objects to be used when creating session identifiers. If the queue is empty when
     * a random number generator is required, a new random number generator object is created. This is designed this way
     * since random number generators use a sync to make them thread-safe and the sync makes using a single object
     * slow(er).
     */
    private final Queue<SecureRandom> randoms = new ConcurrentLinkedQueue<>();

    private String secureRandomClass = null;

    private String secureRandomAlgorithm = DEFAULT_SECURE_RANDOM_ALGORITHM;

    private String secureRandomProvider = null;


    /** Node identifier when in a cluster. Defaults to the empty string. */
    private String jvmRoute = "";


    /** Number of bytes in a session ID. Defaults to 16. */
    private int sessionIdLength = 16;


    /**
     * Get the class name of the {@link SecureRandom} implementation used to generate session IDs.
     *
     * @return The fully qualified class name. {@code null} indicates that the JRE provided {@link SecureRandom}
     *             implementation will be used
     */
    public String getSecureRandomClass() {
        return secureRandomClass;
    }


    /**
     * Specify a non-default {@link SecureRandom} implementation to use. The implementation must be self-seeding and
     * have a zero-argument constructor. If not specified, an instance of {@link SecureRandom} will be generated.
     *
     * @param secureRandomClass The fully-qualified class name
     */
    public void setSecureRandomClass(String secureRandomClass) {
        this.secureRandomClass = secureRandomClass;
    }


    /**
     * Get the name of the algorithm used to create the {@link SecureRandom} instances which generate new session IDs.
     *
     * @return The name of the algorithm. {@code null} or the empty string means that platform default will be used
     */
    public String getSecureRandomAlgorithm() {
        return secureRandomAlgorithm;
    }


    /**
     * Specify a non-default algorithm to use to create instances of {@link SecureRandom} which are used to generate
     * session IDs. If no algorithm is specified, SHA1PRNG will be used. If SHA1PRNG is not available, the platform
     * default will be used. To use the platform default (which may be SHA1PRNG), specify {@code null} or the empty
     * string. If an invalid algorithm and/or provider is specified the {@link SecureRandom} instances will be created
     * using the defaults for this {@link SessionIdGenerator} implementation. If that fails, the {@link SecureRandom}
     * instances will be created using platform defaults.
     *
     * @param secureRandomAlgorithm The name of the algorithm
     */
    public void setSecureRandomAlgorithm(String secureRandomAlgorithm) {
        this.secureRandomAlgorithm = secureRandomAlgorithm;
    }


    /**
     * Get the name of the provider used to create the {@link SecureRandom} instances which generate new session IDs.
     *
     * @return The name of the provider. {@code null} or the empty string means that platform default will be used
     */
    public String getSecureRandomProvider() {
        return secureRandomProvider;
    }


    /**
     * Specify a non-default provider to use to create instances of {@link SecureRandom} which are used to generate
     * session IDs. If no provider is specified, the platform default is used. To use the platform default specify
     * {@code null} or the empty string. If an invalid algorithm and/or provider is specified the {@link SecureRandom}
     * instances will be created using the defaults for this {@link SessionIdGenerator} implementation. If that fails,
     * the {@link SecureRandom} instances will be created using platform defaults.
     *
     * @param secureRandomProvider The name of the provider
     */
    public void setSecureRandomProvider(String secureRandomProvider) {
        this.secureRandomProvider = secureRandomProvider;
    }


    @Override
    public String getJvmRoute() {
        return jvmRoute;
    }


    @Override
    public void setJvmRoute(String jvmRoute) {
        this.jvmRoute = jvmRoute;
    }


    @Override
    public int getSessionIdLength() {
        return sessionIdLength;
    }


    @Override
    public void setSessionIdLength(int sessionIdLength) {
        this.sessionIdLength = sessionIdLength;
    }

    @Override
    public String generateSessionId() {
        return generateSessionId(jvmRoute);
    }


    protected void getRandomBytes(byte[] bytes) {

        SecureRandom random = randoms.poll();
        if (random == null) {
            random = createSecureRandom();
        }
        random.nextBytes(bytes);
        randoms.add(random);
    }


    /**
     * Create a new random number generator instance we should use for generating session identifiers.
     */
    private SecureRandom createSecureRandom() {

        SecureRandom result = null;

        long t1 = System.currentTimeMillis();
        if (secureRandomClass != null) {
            try {
                // Construct and seed a new random number generator
                Class<?> clazz = Class.forName(secureRandomClass);
                result = (SecureRandom) clazz.getConstructor().newInstance();
            } catch (Exception e) {
                log.error(sm.getString("sessionIdGeneratorBase.random", secureRandomClass), e);
            }
        }

        boolean error = false;
        if (result == null) {
            // No secureRandomClass or creation failed. Use SecureRandom.
            try {
                if (secureRandomProvider != null && !secureRandomProvider.isEmpty()) {
                    result = SecureRandom.getInstance(secureRandomAlgorithm, secureRandomProvider);
                } else if (secureRandomAlgorithm != null && !secureRandomAlgorithm.isEmpty()) {
                    result = SecureRandom.getInstance(secureRandomAlgorithm);
                }
            } catch (NoSuchAlgorithmException e) {
                error = true;
                log.error(sm.getString("sessionIdGeneratorBase.randomAlgorithm", secureRandomAlgorithm), e);
            } catch (NoSuchProviderException e) {
                error = true;
                log.error(sm.getString("sessionIdGeneratorBase.randomProvider", secureRandomProvider), e);
            }
        }

        // In theory, DEFAULT_SECURE_RANDOM_ALGORITHM should always work but
        // with custom providers that might not be the case.
        if (result == null && error && !DEFAULT_SECURE_RANDOM_ALGORITHM.equals(secureRandomAlgorithm)) {
            // Invalid provider / algorithm - use the default
            try {
                result = SecureRandom.getInstance(DEFAULT_SECURE_RANDOM_ALGORITHM);
            } catch (NoSuchAlgorithmException e) {
                log.error(sm.getString("sessionIdGeneratorBase.randomAlgorithm", secureRandomAlgorithm), e);
            }
        }

        if (result == null) {
            // Nothing works - use platform default
            result = new SecureRandom();
        }

        // Force seeding to take place
        result.nextInt();

        long t2 = System.currentTimeMillis();
        if ((t2 - t1) > 100) {
            log.warn(sm.getString("sessionIdGeneratorBase.createRandom", result.getAlgorithm(), Long.valueOf(t2 - t1)));
        }
        return result;
    }


    @Override
    protected void initInternal() throws LifecycleException {
        // NO-OP
    }


    @Override
    protected void startInternal() throws LifecycleException {
        // Ensure SecureRandom has been initialised
        generateSessionId();

        setState(LifecycleState.STARTING);
    }


    @Override
    protected void stopInternal() throws LifecycleException {
        setState(LifecycleState.STOPPING);
        randoms.clear();
    }


    @Override
    protected void destroyInternal() throws LifecycleException {
        // NO-OP
    }
}
