/*
 * Copyright (c) 2008, 2009, 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.
 *
 * 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.
 */

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Security;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import sun.security.krb5.Config;

/**
 * This class starts a simple KDC with one realm, several typical principal
 * names, generates delete-on-exit krb5.conf and keytab files, and setup
 * system properties for them. There's also a helper method to generate a
 * JAAS login config file that can be used for JAAS or JGSS apps.
 * <p>
 * Just call this line to start everything:
 * <pre>
 * new OneKDC(null).writeJaasConf();
 * </pre>
 */
public class OneKDC extends KDC {

    public static final String USER = "dummy";
    public static final char[] PASS = "bogus".toCharArray();
    public static final String KRB5_CONF = "localkdc-krb5.conf";
    public static final String KTAB = "localkdc.ktab";
    public static final String JAAS_CONF = "localkdc-jaas.conf";
    public static final String REALM = "RABBIT.HOLE";
    public static String SERVER = "server/host." + REALM.toLowerCase();
    public static String BACKEND = "backend/host." + REALM.toLowerCase();
    public static String KDCHOST = "kdc." + REALM.toLowerCase();
    /**
     * Creates the KDC and starts it.
     * @param etype Encryption type, null if not specified
     * @throws java.lang.Exception if there's anything wrong
     */
    public OneKDC(String etype) throws Exception {
        super(REALM, KDCHOST, 0, true);
        addPrincipal(USER, PASS);
        addPrincipalRandKey("krbtgt/" + REALM);
        addPrincipalRandKey(SERVER);
        addPrincipalRandKey(BACKEND);
        KDC.saveConfig(KRB5_CONF, this,
                "forwardable = true",
                "default_keytab_name = " + KTAB,
                etype == null ? "" : "default_tkt_enctypes=" + etype + "\ndefault_tgs_enctypes=" + etype);
        System.setProperty("java.security.krb5.conf", KRB5_CONF);
        // Whatever krb5.conf had been loaded before, we reload ours now.
        Config.refresh();

        writeKtab(KTAB);
        new File(KRB5_CONF).deleteOnExit();
        new File(KTAB).deleteOnExit();
    }

    /**
     * Writes a JAAS login config file, which contains as many as useful
     * entries, including JGSS style initiator/acceptor and normal JAAS
     * entries with names using existing OneKDC principals.
     * @throws java.lang.Exception if anything goes wrong
     */
    public void writeJAASConf() throws IOException {
        System.setProperty("java.security.auth.login.config", JAAS_CONF);
        File f = new File(JAAS_CONF);
        FileOutputStream fos = new FileOutputStream(f);
        fos.write((
                "com.sun.security.jgss.krb5.initiate {\n" +
                "    com.sun.security.auth.module.Krb5LoginModule required;\n};\n" +
                "com.sun.security.jgss.krb5.accept {\n" +
                "    com.sun.security.auth.module.Krb5LoginModule required\n" +
                "    principal=\"" + SERVER + "\"\n" +
                "    useKeyTab=true\n" +
                "    isInitiator=false\n" +
                "    storeKey=true;\n};\n" +
                "client {\n" +
                "    com.sun.security.auth.module.Krb5LoginModule required;\n};\n" +
                "server {\n" +
                "    com.sun.security.auth.module.Krb5LoginModule required\n" +
                "    principal=\"" + SERVER + "\"\n" +
                "    useKeyTab=true\n" +
                "    storeKey=true;\n};\n" +
                "backend {\n" +
                "    com.sun.security.auth.module.Krb5LoginModule required\n" +
                "    principal=\"" + BACKEND + "\"\n" +
                "    useKeyTab=true\n" +
                "    storeKey=true\n" +
                "    isInitiator=false;\n};\n"
                ).getBytes());
        fos.close();
        f.deleteOnExit();
        Security.setProperty("auth.login.defaultCallbackHandler", "OneKDC$CallbackForClient");
    }

    /**
     * The default callback handler for JAAS login. Note that this handler is
     * hard coded to provide only info for USER1. If you need to provide info
     * for another principal, please use Context.fromUserPass() instead.
     */
    public static class CallbackForClient implements CallbackHandler {
        public void handle(Callback[] callbacks) {
            String user = OneKDC.USER;
            char[] pass = OneKDC.PASS;
            for (Callback callback : callbacks) {
                if (callback instanceof NameCallback) {
                    System.out.println("Callback for name: " + user);
                    ((NameCallback) callback).setName(user);
                }
                if (callback instanceof PasswordCallback) {
                    System.out.println("Callback for pass: "
                            + new String(pass));
                    ((PasswordCallback) callback).setPassword(pass);
                }
            }
        }
    }
}
