/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF 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.sling.auth.form.impl;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>TokenStore</code> class provides the secure token hash
 * implementation used by the {@link FormAuthenticationHandler} to generate,
 * validate and persist secure tokens.
 */
class TokenStore {

    /**
     * Array of hex characters used by {@link #byteToHex(byte[])} to convert a
     * byte array to a hex string.
     */
    private static final char[] TOHEX = "0123456789abcdef".toCharArray();

    /**
     * Name of the <code>SecureRandom</code> generator algorithm
     */
    private static final String SHA1PRNG = "SHA1PRNG";

    /**
     * The name of the HMAC function to calculate the hash code of the payload
     * with the secure token.
     */
    private static final String HMAC_SHA1 = "HmacSHA1";

    /**
     * String encoding to convert byte arrays to strings and vice-versa.
     */
    private static final String UTF_8 = "UTF-8";

    /** The number of secret keys in the token buffer currentTokens */
    private static final int TOKEN_BUFFER_SIZE = 5;

    public final Logger log = LoggerFactory.getLogger(TokenStore.class);

    /**
     * The ttl of the cookie before it becomes invalid (in ms)
     */
    private final long ttl;

    /**
     * The time when a new token should be created.
     */
    private long nextUpdate = System.currentTimeMillis();

    /**
     * The location of the current token.
     */
    private volatile int currentToken = 0;

    /**
     * A ring of tokens used to encrypt.
     */
    private volatile SecretKey[] currentTokens;

    /**
     * A secure random used for generating new tokens.
     */
    private SecureRandom random;

    /** The token file to persist the secure tokens */
    private File tokenFile;

    /** A temporary file used to update the secure token file */
    private File tmpTokenFile;

    /**
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws IllegalStateException
     * @throws NullPointerException if <code>tokenFile</code> is
     *             <code>null</code>.
     */
    TokenStore(final File tokenFile, final long sessionTimeout,
            final boolean fastSeed) throws NoSuchAlgorithmException,
            InvalidKeyException, IllegalStateException,
            UnsupportedEncodingException {

        if (tokenFile == null) {
            throw new NullPointerException("tokenfile");
        }

        this.random = SecureRandom.getInstance(SHA1PRNG);
        this.ttl = sessionTimeout;
        this.tokenFile = tokenFile;
        this.tmpTokenFile = new File(tokenFile + ".tmp");

        // prime the secret keys from persistence
        loadTokens();

        // warm up the crypto API
        if (fastSeed) {
            random.setSeed(getFastEntropy());
        } else {
            log.info("Seeding the secure random number generator can take "
                + "up to several minutes on some operating systems depending "
                + "upon environment factors. If this is a problem for you, "
                + "set the system property 'java.security.egd' to "
                + "'file:/dev/./urandom' or enable the Fast Seed Generator "
                + "in the Web Console");
        }
        byte[] b = new byte[20];
        random.nextBytes(b);
        final SecretKey secretKey = new SecretKeySpec(b, HMAC_SHA1);
        final Mac m = Mac.getInstance(HMAC_SHA1);
        m.init(secretKey);
        m.update(UTF_8.getBytes(UTF_8));
        m.doFinal();
    }

    /**
     * @param expires
     * @param userId
     * @return
     * @throws UnsupportedEncodingException
     * @throws IllegalStateException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    String encode(final long expires, final String userId)
            throws IllegalStateException, UnsupportedEncodingException,
            NoSuchAlgorithmException, InvalidKeyException {
        int token = getActiveToken();
        SecretKey key = currentTokens[token];
        return encode(expires, userId, token, key);
    }

    private String encode(final long expires, final String userId,
            final int token, final SecretKey key) throws IllegalStateException,
            UnsupportedEncodingException, NoSuchAlgorithmException,
            InvalidKeyException {

        String cookiePayload = String.valueOf(token) + String.valueOf(expires)
            + "@" + userId;
        Mac m = Mac.getInstance(HMAC_SHA1);
        m.init(key);
        m.update(cookiePayload.getBytes(UTF_8));
        String cookieValue = byteToHex(m.doFinal());
        return cookieValue + "@" + cookiePayload;
    }

    /**
     * Splits the authentication data into the three parts packed together while
     * encoding the cookie.
     *
     * @param authData The authentication data to split in three parts
     * @return A string array with three elements being the three parts of the
     *         cookie value or <code>null</code> if the input is
     *         <code>null</code> or if the string does not contain (at least)
     *         three '@' separated parts.
     */
    static String[] split(final String authData) {
        String[] parts = StringUtils.split(authData, "@", 3);
        if (parts != null && parts.length == 3) {
            return parts;
        }
        return null;
    }

    /**
     * Returns <code>true</code> if the <code>value</code> is a valid secure
     * token as follows:
     * <ul>
     * <li>The string is not <code>null</code></li>
     * <li>The string contains three fields separated by an @ sign</li>
     * <li>The expiry time encoded in the second field has not yet passed</li>
     * <li>The hashing the third field, the expiry time and token number with
     * the secure token (indicated by the token number) gives the same value as
     * contained in the first field</li>
     * </ul>
     * <p>
     * Otherwise the method returns <code>false</code>.
     */
    boolean isValid(String value) {
        String[] parts = split(value);
        if (parts != null) {

            // single digit token number
            int tokenNumber = parts[1].charAt(0) - '0';
            if (tokenNumber >= 0 && tokenNumber < currentTokens.length) {

                long cookieTime = Long.parseLong(parts[1].substring(1));
                if (System.currentTimeMillis() < cookieTime) {

                    try {
                        SecretKey secretKey = currentTokens[tokenNumber];
                        if ( secretKey == null ) {
                            log.error("AuthNCookie value '{}' points to an unknown token number", value);
                            return false;
                        }
                        String hmac = encode(cookieTime, parts[2], tokenNumber,
                            secretKey);
                        return value.equals(hmac);
                    } catch (ArrayIndexOutOfBoundsException e) {
                        log.error(e.getMessage(), e);
                    } catch (InvalidKeyException e) {
                        log.error(e.getMessage(), e);
                    } catch (IllegalStateException e) {
                        log.error(e.getMessage(), e);
                    } catch (UnsupportedEncodingException e) {
                        log.error(e.getMessage(), e);
                    } catch (NoSuchAlgorithmException e) {
                        log.error(e.getMessage(), e);
                    }

                    log.error("AuthNCookie value '{}' is invalid", value);

                } else {
                    log.error("AuthNCookie value '{}' has expired {}ms ago",
                        value, (System.currentTimeMillis() - cookieTime));
                }

            } else {
                log.error(
                    "AuthNCookie value '{}' is invalid: refers to an invalid token number",
                    value, tokenNumber);
            }

        } else {
            log.error("AuthNCookie value '{}' has invalid format", value);
        }

        // failed verification, reason is logged
        return false;
    }

    /**
     * Maintain a circular buffer to tokens, and return the current one.
     *
     * @return the current token.
     */
    private synchronized int getActiveToken() {
        if (System.currentTimeMillis() > nextUpdate
            || currentTokens[currentToken] == null) {
            // cycle so that during a typical ttl the tokens get completely
            // refreshed.
            nextUpdate = System.currentTimeMillis() + ttl
                / (currentTokens.length - 1);
            byte[] b = new byte[20];
            random.nextBytes(b);

            SecretKey newToken = new SecretKeySpec(b, HMAC_SHA1);
            int nextToken = currentToken + 1;
            if (nextToken == currentTokens.length) {
                nextToken = 0;
            }
            currentTokens[nextToken] = newToken;
            currentToken = nextToken;
            saveTokens();
        }
        return currentToken;
    }

    /**
     * Stores the current set of tokens to the token file
     */
    private void saveTokens() {
        FileOutputStream fout = null;
        DataOutputStream keyOutputStream = null;
        try {
            File parent = tokenFile.getAbsoluteFile().getParentFile();
            log.info("Token File {} parent {} ", tokenFile, parent);
            if (!parent.exists()) {
                parent.mkdirs();
            }
            fout = new FileOutputStream(tmpTokenFile);
            keyOutputStream = new DataOutputStream(fout);
            keyOutputStream.writeInt(currentToken);
            keyOutputStream.writeLong(nextUpdate);
            for (int i = 0; i < currentTokens.length; i++) {
                if (currentTokens[i] == null) {
                    keyOutputStream.writeInt(0);
                } else {
                    keyOutputStream.writeInt(1);
                    byte[] b = currentTokens[i].getEncoded();
                    keyOutputStream.writeInt(b.length);
                    keyOutputStream.write(b);
                }
            }
            keyOutputStream.close();
            tmpTokenFile.renameTo(tokenFile);
        } catch (IOException e) {
            log.error("Failed to save cookie keys " + e.getMessage());
        } finally {
            try {
                keyOutputStream.close();
            } catch (Exception e) {
            }
            try {
                fout.close();
            } catch (Exception e) {
            }

        }
    }

    /**
     * Load the current set of tokens from the token file. If reading the tokens
     * fails or the token file does not exist, tokens will be generated on
     * demand.
     */
    private void loadTokens() {
        if (tokenFile.isFile() && tokenFile.canRead()) {
            FileInputStream fin = null;
            DataInputStream keyInputStream = null;
            try {
                fin = new FileInputStream(tokenFile);
                keyInputStream = new DataInputStream(fin);
                int newCurrentToken = keyInputStream.readInt();
                long newNextUpdate = keyInputStream.readLong();
                SecretKey[] newKeys = new SecretKey[TOKEN_BUFFER_SIZE];
                for (int i = 0; i < newKeys.length; i++) {
                    int isNull = keyInputStream.readInt();
                    if (isNull == 1) {
                        int l = keyInputStream.readInt();
                        byte[] b = new byte[l];
                        keyInputStream.read(b);
                        newKeys[i] = new SecretKeySpec(b, HMAC_SHA1);
                    } else {
                        newKeys[i] = null;
                    }
                }

                // assign the tokes and schedule a next update
                nextUpdate = newNextUpdate;
                currentToken = newCurrentToken;
                currentTokens = newKeys;

            } catch (IOException e) {

                log.error("Failed to load cookie keys " + e.getMessage());

            } finally {

                if (keyInputStream != null) {
                    try {
                        keyInputStream.close();
                    } catch (IOException e) {
                    }
                } else if (fin != null) {
                    try {
                        fin.close();
                    } catch (IOException e) {
                    }
                }
            }
        }

        // if there was a failure to read the current tokens, create new ones
        if (currentTokens == null) {
            currentTokens = new SecretKey[TOKEN_BUFFER_SIZE];
            nextUpdate = System.currentTimeMillis();
            currentToken = 0;
        }
    }

    /**
     * Encode a byte array.
     *
     * @param base
     * @return
     */
    private String byteToHex(byte[] base) {
        char[] c = new char[base.length * 2];
        int i = 0;

        for (byte b : base) {
            int j = b;
            j = j + 128;
            c[i++] = TOHEX[j / 0x10];
            c[i++] = TOHEX[j % 0x10];
        }
        return new String(c);
    }

    /**
     * Creates a byte array of entry from the current state of the system:
     * <ul>
     * <li>The current system time in milliseconds since the epoch</li>
     * <li>The number of nanoseconds since system startup</li>
     * <li>The name, size and last modification time of the files in the
     * <code>java.io.tmpdir</code> folder.</li>
     * </ul>
     * <p>
     * <b>NOTE</b> This method generates entropy fast but not necessarily
     * secure enough for seeding the random number generator.
     *
     * @return bytes of entropy
     */
    private static byte[] getFastEntropy() {
        final MessageDigest md;

        try {
            md = MessageDigest.getInstance("SHA");
        } catch (NoSuchAlgorithmException nsae) {
            throw new InternalError("internal error: SHA-1 not available.");
        }

        // update with XorShifted time values
        update(md, System.currentTimeMillis());
        update(md, System.nanoTime());

        // scan the temp file system
        File file = new File(System.getProperty("java.io.tmpdir"));
        File[] entries = file.listFiles();
        if (entries != null) {
            for (File entry : entries) {
                md.update(entry.getName().getBytes());
                update(md, entry.lastModified());
                update(md, entry.length());
            }
        }

        return md.digest();
    }

    /**
     * Updates the message digest with an XOR-Shifted value.
     *
     * @param md The MessageDigest to update
     * @param value The original value to be XOR-Shifted first before taking the
     *            bytes ot update the message digest
     */
    private static void update(final MessageDigest md, long value) {
        value ^= (value << 21);
        value ^= (value >>> 35);
        value ^= (value << 4);

        for (int i = 0; i < 8; i++) {
            md.update((byte) value);
            value >>= 8;
        }
    }
}