/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 *
 *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
 *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
 */

package sun.security.krb5.internal.ktab;

import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
import sun.security.jgss.krb5.ServiceCreds;

/**
 * This class represents key table. The key table functions deal with storing
 * and retrieving service keys for use in authentication exchanges.
 *
 * A KeyTab object is always constructed, if the file specified does not
 * exist, it's still valid but empty. If there is an I/O error or file format
 * error, it's invalid.
 *
 * The class is immutable on the read side (the write side is only used by
 * the ktab tool).
 *
 * @author Yanni Zhang
 */
public class KeyTab implements KeyTabConstants {

    private static final boolean DEBUG = Krb5.DEBUG;
    private static String defaultTabName = null;

    // Attention: Currently there is no way to remove a keytab from this map,
    // this might lead to a memory leak.
    private static Map<String,KeyTab> map = new HashMap<>();

    // KeyTab file does not exist. Note: a missing keytab is still valid
    private boolean isMissing = false;

    // KeyTab file is invalid, possibly an I/O error or a file format error.
    private boolean isValid = true;

    private final String tabName;
    private long lastModified;
    private int kt_vno = KRB5_KT_VNO;

    private Vector<KeyTabEntry> entries = new Vector<>();

    /**
     * Constructs a KeyTab object.
     *
     * If there is any I/O error or format errot during the loading, the
     * isValid flag is set to false, and all half-read entries are dismissed.
     * @param filename path name for the keytab file, must not be null
     */
    private KeyTab(String filename) {
        tabName = filename;
        try {
            lastModified = new File(tabName).lastModified();
            try (KeyTabInputStream kis =
                    new KeyTabInputStream(new FileInputStream(filename))) {
                load(kis);
            }
        } catch (FileNotFoundException e) {
            entries.clear();
            isMissing = true;
        } catch (Exception ioe) {
            entries.clear();
            isValid = false;
        }
    }

    /**
     * Read a keytab file. Returns a new object and save it into cache when
     * new content (modified since last read) is available. If keytab file is
     * invalid, the old object will be returned. This is a safeguard for
     * partial-written keytab files or non-stable network. Please note that
     * a missing keytab is valid, which is equivalent to an empty keytab.
     *
     * @param s file name of keytab, must not be null
     * @return the keytab object, can be invalid, but never null.
     */
    private synchronized static KeyTab getInstance0(String s) {
        long lm = new File(s).lastModified();
        KeyTab old = map.get(s);
        if (old != null && old.isValid() && old.lastModified == lm) {
            return old;
        }
        KeyTab ktab = new KeyTab(s);
        if (ktab.isValid()) {               // A valid new keytab
            map.put(s, ktab);
            return ktab;
        } else if (old != null) {           // An existing old one
            return old;
        } else {
            return ktab;                    // first read is invalid
        }
    }

    /**
     * Gets a KeyTab object.
     * @param s the key tab file name.
     * @return the KeyTab object, never null.
     */
    public static KeyTab getInstance(String s) {
        if (s == null) {
            return getInstance();
        } else {
            return getInstance0(normalize(s));
        }
    }

    /**
     * Gets a KeyTab object.
     * @param file the key tab file.
     * @return the KeyTab object, never null.
     */
    public static KeyTab getInstance(File file) {
        if (file == null) {
            return getInstance();
        } else {
            return getInstance0(file.getPath());
        }
    }

    /**
     * Gets the default KeyTab object.
     * @return the KeyTab object, never null.
     */
    public static KeyTab getInstance() {
        return getInstance(getDefaultTabName());
    }

    public boolean isMissing() {
        return isMissing;
    }

    public boolean isValid() {
        return isValid;
    }

    /**
     * The location of keytab file will be read from the configuration file
     * If it is not specified, consider user.home as the keytab file's
     * default location.
     * @return never null
     */
    private static String getDefaultTabName() {
        if (defaultTabName != null) {
            return defaultTabName;
        } else {
            String kname = null;
            try {
                String keytab_names = Config.getInstance().get
                        ("libdefaults", "default_keytab_name");
                if (keytab_names != null) {
                    StringTokenizer st = new StringTokenizer(keytab_names, " ");
                    while (st.hasMoreTokens()) {
                        kname = normalize(st.nextToken());
                        if (new File(kname).exists()) {
                            break;
                        }
                    }
                }
            } catch (KrbException e) {
                kname = null;
            }

            if (kname == null) {
                String user_home =
                        java.security.AccessController.doPrivileged(
                        new sun.security.action.GetPropertyAction("user.home"));

                if (user_home == null) {
                    user_home =
                        java.security.AccessController.doPrivileged(
                        new sun.security.action.GetPropertyAction("user.dir"));
                }

                kname = user_home + File.separator  + "krb5.keytab";
            }
            defaultTabName = kname;
            return kname;
        }
    }

    /**
     * Normalizes some common keytab name formats into the bare file name.
     * For example, FILE:/etc/krb5.keytab to /etc/krb5.keytab
     * @param name never null
     * @return never null
     */
    // This method is used in this class and Krb5LoginModule
    public static String normalize(String name) {
        String kname;
        if ((name.length() >= 5) &&
            (name.substring(0, 5).equalsIgnoreCase("FILE:"))) {
            kname = name.substring(5);
        } else if ((name.length() >= 9) &&
                (name.substring(0, 9).equalsIgnoreCase("ANY:FILE:"))) {
            // this format found in MIT's krb5.ini.
            kname = name.substring(9);
        } else if ((name.length() >= 7) &&
                (name.substring(0, 7).equalsIgnoreCase("SRVTAB:"))) {
            // this format found in MIT's krb5.ini.
            kname = name.substring(7);
        } else
            kname = name;
        return kname;
    }

    private void load(KeyTabInputStream kis)
        throws IOException, RealmException {

        entries.clear();
        kt_vno = kis.readVersion();
        if (kt_vno == KRB5_KT_VNO_1) {
            kis.setNativeByteOrder();
        }
        int entryLength = 0;
        KeyTabEntry entry;
        while (kis.available() > 0) {
            entryLength = kis.readEntryLength();
            entry = kis.readEntry(entryLength, kt_vno);
            if (DEBUG) {
                System.out.println(">>> KeyTab: load() entry length: " +
                        entryLength + "; type: " +
                        (entry != null? entry.keyType : 0));
            }
            if (entry != null)
                entries.addElement(entry);
        }
    }

    /**
     * Returns a principal name in this keytab. Used by
     * {@link ServiceCreds#getKKeys()}.
     */
    public PrincipalName getOneName() {
        int size = entries.size();
        return size > 0 ? entries.elementAt(size-1).service : null;
    }

    /**
     * Reads all keys for a service from the keytab file that have
     * etypes that have been configured for use.
     * @param service the PrincipalName of the requested service
     * @return an array containing all the service keys, never null
     */
    public EncryptionKey[] readServiceKeys(PrincipalName service) {
        KeyTabEntry entry;
        EncryptionKey key;
        int size = entries.size();
        ArrayList<EncryptionKey> keys = new ArrayList<>(size);
        if (DEBUG) {
            System.out.println("Looking for keys for: " + service);
        }
        for (int i = size-1; i >= 0; i--) {
            entry = entries.elementAt(i);
            if (entry.service.match(service)) {
                if (EType.isSupported(entry.keyType)) {
                    key = new EncryptionKey(entry.keyblock,
                                        entry.keyType,
                                        new Integer(entry.keyVersion));
                    keys.add(key);
                    if (DEBUG) {
                        System.out.println("Added key: " + entry.keyType +
                            "version: " + entry.keyVersion);
                    }
                } else if (DEBUG) {
                    System.out.println("Found unsupported keytype (" +
                        entry.keyType + ") for " + service);
                }
            }
        }
        size = keys.size();
        EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);

        // Sort the keys by kvno. Sometimes we must choose a single key (say,
        // generate encrypted timestamp in AS-REQ). A key with a higher KVNO
        // sounds like a newer one.
        Arrays.sort(retVal, new Comparator<EncryptionKey>() {
            @Override
            public int compare(EncryptionKey o1, EncryptionKey o2) {
                return o2.getKeyVersionNumber().intValue()
                        - o1.getKeyVersionNumber().intValue();
            }
        });

        return retVal;
    }



    /**
     * Searches for the service entry in the keytab file.
     * The etype of the key must be one that has been configured
     * to be used.
     * @param service the PrincipalName of the requested service.
     * @return true if the entry is found, otherwise, return false.
     */
    public boolean findServiceEntry(PrincipalName service) {
        KeyTabEntry entry;
        for (int i = 0; i < entries.size(); i++) {
            entry = entries.elementAt(i);
            if (entry.service.match(service)) {
                if (EType.isSupported(entry.keyType)) {
                    return true;
                } else if (DEBUG) {
                    System.out.println("Found unsupported keytype (" +
                        entry.keyType + ") for " + service);
                }
            }
        }
        return false;
    }

    public String tabName() {
        return tabName;
    }

    /////////////////// THE WRITE SIDE ///////////////////////
    /////////////// only used by ktab tool //////////////////

    /**
     * Adds a new entry in the key table.
     * @param service the service which will have a new entry in the key table.
     * @param psswd the password which generates the key.
     * @param kvno the kvno to use, -1 means automatic increasing
     * @param append false if entries with old kvno would be removed.
     * Note: if kvno is not -1, entries with the same kvno are always removed
     */
    public void addEntry(PrincipalName service, char[] psswd,
            int kvno, boolean append) throws KrbException {
        addEntry(service, service.getSalt(), psswd, kvno, append);
    }

    // Called by KDC test
    public void addEntry(PrincipalName service, String salt, char[] psswd,
            int kvno, boolean append) throws KrbException {

        EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
            psswd, salt);

        // There should be only one maximum KVNO value for all etypes, so that
        // all added keys can have the same KVNO.

        int maxKvno = 0;    // only useful when kvno == -1
        for (int i = entries.size()-1; i >= 0; i--) {
            KeyTabEntry e = entries.get(i);
            if (e.service.match(service)) {
                if (e.keyVersion > maxKvno) {
                    maxKvno = e.keyVersion;
                }
                if (!append || e.keyVersion == kvno) {
                    entries.removeElementAt(i);
                }
            }
        }
        if (kvno == -1) {
            kvno = maxKvno + 1;
        }

        for (int i = 0; encKeys != null && i < encKeys.length; i++) {
            int keyType = encKeys[i].getEType();
            byte[] keyValue = encKeys[i].getBytes();

            KeyTabEntry newEntry = new KeyTabEntry(service,
                            service.getRealm(),
                            new KerberosTime(System.currentTimeMillis()),
                                               kvno, keyType, keyValue);
            entries.addElement(newEntry);
        }
    }

    /**
     * Gets the list of service entries in key table.
     * @return array of <code>KeyTabEntry</code>.
     */
    public KeyTabEntry[] getEntries() {
        KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
        for (int i = 0; i < kentries.length; i++) {
            kentries[i] = entries.elementAt(i);
        }
        return kentries;
    }

    /**
     * Creates a new default key table.
     */
    public synchronized static KeyTab create()
        throws IOException, RealmException {
        String dname = getDefaultTabName();
        return create(dname);
    }

    /**
     * Creates a new default key table.
     */
    public synchronized static KeyTab create(String name)
        throws IOException, RealmException {

        try (KeyTabOutputStream kos =
                new KeyTabOutputStream(new FileOutputStream(name))) {
            kos.writeVersion(KRB5_KT_VNO);
        }
        return new KeyTab(name);
    }

    /**
     * Saves the file at the directory.
     */
    public synchronized void save() throws IOException {
        try (KeyTabOutputStream kos =
                new KeyTabOutputStream(new FileOutputStream(tabName))) {
            kos.writeVersion(kt_vno);
            for (int i = 0; i < entries.size(); i++) {
                kos.writeEntry(entries.elementAt(i));
            }
        }
    }

    /**
     * Removes entries from the key table.
     * @param service the service <code>PrincipalName</code>.
     * @param etype the etype to match, remove all if -1
     * @param kvno what kvno to remove, -1 for all, -2 for old
     * @return the number of entries deleted
     */
    public int deleteEntries(PrincipalName service, int etype, int kvno) {
        int count = 0;

        // Remember the highest KVNO for each etype. Used for kvno == -2
        Map<Integer,Integer> highest = new HashMap<>();

        for (int i = entries.size()-1; i >= 0; i--) {
            KeyTabEntry e = entries.get(i);
            if (service.match(e.getService())) {
                if (etype == -1 || e.keyType == etype) {
                    if (kvno == -2) {
                        // Two rounds for kvno == -2. In the first round (here),
                        // only find out highest KVNO for each etype
                        if (highest.containsKey(e.keyType)) {
                            int n = highest.get(e.keyType);
                            if (e.keyVersion > n) {
                                highest.put(e.keyType, e.keyVersion);
                            }
                        } else {
                            highest.put(e.keyType, e.keyVersion);
                        }
                    } else if (kvno == -1 || e.keyVersion == kvno) {
                        entries.removeElementAt(i);
                        count++;
                    }
                }
            }
        }

        // Second round for kvno == -2, remove old entries
        if (kvno == -2) {
            for (int i = entries.size()-1; i >= 0; i--) {
                KeyTabEntry e = entries.get(i);
                if (service.match(e.getService())) {
                    if (etype == -1 || e.keyType == etype) {
                        int n = highest.get(e.keyType);
                        if (e.keyVersion != n) {
                            entries.removeElementAt(i);
                            count++;
                        }
                    }
                }
            }
        }
        return count;
    }

    /**
     * Creates key table file version.
     * @param file the key table file.
     * @exception IOException.
     */
    public synchronized void createVersion(File file) throws IOException {
        try (KeyTabOutputStream kos =
                new KeyTabOutputStream(new FileOutputStream(file))) {
            kos.write16(KRB5_KT_VNO);
        }
    }
}
