/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed 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.conscrypt;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import libcore.io.IoUtils;
import libcore.util.BasicLruCache;

/**
 * This class provides a simple interface for cert pinning.
 */
public class CertPinManager {

    private long lastModified;

    private final Map<String, PinListEntry> entries = new HashMap<String, PinListEntry>();
    private final BasicLruCache<String, String> hostnameCache = new BasicLruCache<String, String>(10);

    private boolean initialized = false;
    private static final boolean DEBUG = false;

    private final File pinFile;
    private final TrustedCertificateStore certStore;

    public CertPinManager(TrustedCertificateStore store) throws PinManagerException {
        pinFile = new File("/data/misc/keychain/pins");
        certStore = store;
    }

    /** Test only */
    public CertPinManager(String path, TrustedCertificateStore store) throws PinManagerException {
        if (path == null) {
            throw new NullPointerException("path == null");
        }
        pinFile = new File(path);
        certStore = store;
    }

    /**
     * Given a {@code hostname} and a {@code chain} this verifies that the
     * certificate chain includes certificates from the pinned list iff the
     * {@code hostname} is on the list of sites that should be pinned.
     *
     * <p>If {@code chain} doesn't include those certificates and enforcing
     * mode is enabled, then this method returns {@code false} and the
     * certificate chain validation should fail.
     */
    public boolean isChainValid(String hostname, List<X509Certificate> chain)
            throws PinManagerException {
        // lookup the entry
        final PinListEntry entry = lookup(hostname);

        // There was no entry in the pin list for this hostname.
        if (entry == null) {
            return true;
        }

        return entry.isChainValid(chain);
    }

    /**
     * Tries to initialize the cache. Will return {@code true} if the
     * initialization succeeded, or {@code false} if there is no data available.
     */
    private synchronized boolean ensureInitialized() throws PinManagerException {
        if (initialized && isCacheValid()) {
            return true;
        }

        // reread the pin file
        String pinFileContents = readPinFile();

        if (pinFileContents != null) {
            // rebuild the pinned certs
            for (String entry : getPinFileEntries(pinFileContents)) {
                try {
                    PinListEntry pin = new PinListEntry(entry, certStore);
                    entries.put(pin.getCommonName(), pin);
                } catch (PinEntryException e) {
                    log("Pinlist contains a malformed pin: " + entry, e);
                }
            }

            // clear the cache
            hostnameCache.evictAll();

            // set the last modified time
            lastModified = pinFile.lastModified();

            // we've been fully initialized and are ready to go
            initialized = true;
        }

        return initialized;
    }

    private String readPinFile() throws PinManagerException {
        try {
            return IoUtils.readFileAsString(pinFile.getPath());
        } catch (FileNotFoundException e) {
            // there's no pin list, all certs are unpinned
            return null;
        } catch (IOException e) {
            // this is unexpected, fail
            throw new PinManagerException("Unexpected error reading pin list; failing.", e);
        }
    }

    private static String[] getPinFileEntries(String pinFileContents) {
        return pinFileContents.split("\n");
    }

    private synchronized PinListEntry lookup(String hostname) throws PinManagerException {
        // Ensure we're initialized, but exit early it we couldn't initialize.
        if (!ensureInitialized()) {
            return null;
        }

        // if so, check the hostname cache
        String cn = hostnameCache.get(hostname);
        if (cn != null) {
            // if we hit, return the corresponding entry
            return entries.get(cn);
        }

        // otherwise, get the matching cn
        cn = getMatchingCN(hostname);
        if (cn != null) {
            hostnameCache.put(hostname, cn);
            // we have a matching CN, return that entry
            return entries.get(cn);
        }

        // if we got here, we don't have a matching CN for this hostname
        return null;
    }

    private boolean isCacheValid() {
        return pinFile.lastModified() == lastModified;
    }

    private String getMatchingCN(String hostname) {
        String bestMatch = "";
        for (String cn : entries.keySet()) {
            // skip shorter CNs since they can't be better matches
            if (cn.length() < bestMatch.length()) {
                continue;
            }
            // now verify that the CN matches at all
            if (isHostnameMatchedBy(hostname, cn)) {
                bestMatch = cn;
            }
        }
        return bestMatch;
    }

    /**
     * Returns true if {@code hostName} matches the name or pattern {@code cn}.
     *
     * @param hostName lowercase host name.
     * @param cn certificate host name. May include wildcards like
     *            {@code *.android.com}.
     */
    private static boolean isHostnameMatchedBy(String hostName, String cn) {
        if (hostName == null || hostName.isEmpty() || cn == null || cn.isEmpty()) {
            return false;
        }

        cn = cn.toLowerCase(Locale.US);

        if (!cn.contains("*")) {
            return hostName.equals(cn);
        }

        if (cn.startsWith("*.") && hostName.regionMatches(0, cn, 2, cn.length() - 2)) {
            return true; // "*.foo.com" matches "foo.com"
        }

        int asterisk = cn.indexOf('*');
        int dot = cn.indexOf('.');
        if (asterisk > dot) {
            return false; // malformed; wildcard must be in the first part of
                          // the cn
        }

        if (!hostName.regionMatches(0, cn, 0, asterisk)) {
            return false; // prefix before '*' doesn't match
        }

        int suffixLength = cn.length() - (asterisk + 1);
        int suffixStart = hostName.length() - suffixLength;
        if (hostName.indexOf('.', asterisk) < suffixStart) {
            return false; // wildcard '*' can't match a '.'
        }

        if (!hostName.regionMatches(suffixStart, cn, asterisk + 1, suffixLength)) {
            return false; // suffix after '*' doesn't match
        }

        return true;
    }

    private static void log(String s, Exception e) {
        if (DEBUG) {
            System.out.println("PINFILE: " + s);
            if (e != null) {
                e.printStackTrace();
            }
        }
    }
}
