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

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

import org.apache.catalina.CredentialHandler;
import org.apache.juli.logging.Log;
import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.res.StringManager;

/**
 * Base implementation for the Tomcat provided {@link CredentialHandler}s.
 */
public abstract class DigestCredentialHandlerBase implements CredentialHandler {

    protected static final StringManager sm = StringManager.getManager(Constants.Package);

    public static final int DEFAULT_SALT_LENGTH = 32;

    private int iterations = getDefaultIterations();
    private int saltLength = getDefaultSaltLength();
    private final Object randomLock = new Object();
    private volatile Random random = null;
    private boolean logInvalidStoredCredentials = false;


    /**
     * @return the number of iterations of the associated algorithm that will be
     * used when creating a new stored credential for a given input credential.
     */
    public int getIterations() {
        return iterations;
    }


    /**
     * Set the number of iterations of the associated algorithm that will be
     * used when creating a new stored credential for a given input credential.
     * @param iterations the iterations count
     */
    public void setIterations(int iterations) {
        this.iterations = iterations;
    }


    /**
     * @return the salt length that will be used when creating a new stored
     * credential for a given input credential.
     */
    public int getSaltLength() {
        return saltLength;
    }


    /**
     * Set the salt length that will be used when creating a new stored
     * credential for a given input credential.
     * @param saltLength the salt length
     */
    public void setSaltLength(int saltLength) {
        this.saltLength = saltLength;
    }


    /**
     * When checking input credentials against stored credentials will a warning
     * message be logged if invalid stored credentials are discovered?
     * @return <code>true</code> if logging will occur
     */
    public boolean getLogInvalidStoredCredentials() {
        return logInvalidStoredCredentials;
    }


    /**
     * Set whether a warning message will be logged if invalid stored
     * credentials are discovered while checking input credentials against
     * stored credentials?
     * @param logInvalidStoredCredentials <code>true</code> to log, the
     *   default value is <code>false</code>
     */
    public void setLogInvalidStoredCredentials(boolean logInvalidStoredCredentials) {
        this.logInvalidStoredCredentials = logInvalidStoredCredentials;
    }


    @Override
    public String mutate(String userCredential) {
        byte[] salt = null;
        int iterations = getIterations();
        int saltLength = getSaltLength();
        if (saltLength == 0) {
            salt = new byte[0];
        } else if (saltLength > 0) {
            // Double checked locking. OK since random is volatile.
            if (random == null) {
                synchronized (randomLock) {
                    if (random == null) {
                        random = new SecureRandom();
                    }
                }
            }
            salt = new byte[saltLength];
            // Concurrent use of this random is unlikely to be a performance
            // issue as it is only used during stored password generation.
            random.nextBytes(salt);
        }

        String serverCredential = mutate(userCredential, salt, iterations);

        // Failed to generate server credential from user credential. Points to
        // a configuration issue. The root cause should have been logged in the
        // mutate() method.
        if (serverCredential == null) {
            return null;
        }

        if (saltLength == 0 && iterations == 1) {
            // Output the simple/old format for backwards compatibility
            return serverCredential;
        } else {
            StringBuilder result =
                    new StringBuilder((saltLength << 1) + 10 + serverCredential.length() + 2);
            result.append(HexUtils.toHexString(salt));
            result.append('$');
            result.append(iterations);
            result.append('$');
            result.append(serverCredential);

            return result.toString();
        }
    }


    /**
     * Checks whether the provided credential matches the stored credential when
     * the stored credential is in the form salt$iteration-count$credential
     *
     * @param inputCredentials  The input credential
     * @param storedCredentials The stored credential
     *
     * @return <code>true</code> if they match, otherwise <code>false</code>
     */
    protected boolean matchesSaltIterationsEncoded(String inputCredentials,
            String storedCredentials) {

        if (storedCredentials == null) {
            // Stored credentials are invalid
            // This may be expected if nested credential handlers are being used
            logInvalidStoredCredentials(null);
            return false;
        }

        int sep1 = storedCredentials.indexOf('$');
        int sep2 = storedCredentials.indexOf('$', sep1 + 1);

        if (sep1 < 0 || sep2 < 0) {
            // Stored credentials are invalid
            // This may be expected if nested credential handlers are being used
            logInvalidStoredCredentials(storedCredentials);
            return false;
        }

        String hexSalt = storedCredentials.substring(0,  sep1);

        int iterations = Integer.parseInt(storedCredentials.substring(sep1 + 1, sep2));

        String storedHexEncoded = storedCredentials.substring(sep2 + 1);
        byte[] salt;
        try {
            salt = HexUtils.fromHexString(hexSalt);
        } catch (IllegalArgumentException iae) {
            logInvalidStoredCredentials(storedCredentials);
            return false;
        }

        String inputHexEncoded = mutate(inputCredentials, salt, iterations,
                HexUtils.fromHexString(storedHexEncoded).length * Byte.SIZE);
        if (inputHexEncoded == null) {
            // Failed to mutate user credentials. Automatic fail.
            // Root cause should be logged by mutate()
            return false;
        }

        return storedHexEncoded.equalsIgnoreCase(inputHexEncoded);
    }


    private void logInvalidStoredCredentials(String storedCredentials) {
        if (logInvalidStoredCredentials) {
            // Logging credentials could be a security concern but they are
            // invalid and that is probably a bigger problem
            getLog().warn(sm.getString("credentialHandler.invalidStoredCredential",
                    storedCredentials));
        }
    }


    /**
     * @return the default salt length used by the {@link CredentialHandler}.
     */
    protected int getDefaultSaltLength() {
        return DEFAULT_SALT_LENGTH;
    }


    /**
     * Generates the equivalent stored credentials for the given input
     * credentials, salt and iterations. If the algorithm requires a key length,
     * the default will be used.
     *
     * @param inputCredentials  User provided credentials
     * @param salt              Salt, if any
     * @param iterations        Number of iterations of the algorithm associated
     *                          with this CredentialHandler applied to the
     *                          inputCredentials to generate the equivalent
     *                          stored credentials
     *
     * @return  The equivalent stored credentials for the given input
     *          credentials or <code>null</code> if the generation fails
     */
    protected abstract String mutate(String inputCredentials, byte[] salt, int iterations);


    /**
     * Generates the equivalent stored credentials for the given input
     * credentials, salt, iterations and key length. The default implementation
     * calls ignores the key length and calls
     * {@link #mutate(String, byte[], int)}. Sub-classes that use the key length
     * should override this method.
     *
     * @param inputCredentials  User provided credentials
     * @param salt              Salt, if any
     * @param iterations        Number of iterations of the algorithm associated
     *                          with this CredentialHandler applied to the
     *                          inputCredentials to generate the equivalent
     *                          stored credentials
     * @param keyLength         Length of the produced digest in bits for
     *                          implementations where it's applicable
     *
     * @return  The equivalent stored credentials for the given input
     *          credentials or <code>null</code> if the generation fails
     */
    protected String mutate(String inputCredentials, byte[] salt, int iterations, int keyLength) {
        return mutate(inputCredentials, salt, iterations);
    }


    /**
     * Set the algorithm used to convert input credentials to stored
     * credentials.
     * @param algorithm the algorithm
     * @throws NoSuchAlgorithmException if the specified algorithm
     *  is not supported
     */
    public abstract void setAlgorithm(String algorithm) throws NoSuchAlgorithmException;


    /**
     * @return the algorithm used to convert input credentials to stored
     * credentials.
     */
    public abstract String getAlgorithm();


    /**
     * @return the default number of iterations used by the
     * {@link CredentialHandler}.
     */
    protected abstract int getDefaultIterations();


    /**
     * @return the logger for the CredentialHandler instance.
     */
    protected abstract Log getLog();
}
