/*
 * Copyright (c) 1999-2003 Novell, Inc. All Rights Reserved.
 *
 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
 * USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
 * ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
 * PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
 * ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
 * PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
 * DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
 * PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
 * CUSTOMERS WITH RESPECT TO THIS CODE.
 */

import com.novell.security.sso.*;

import java.security.*;
import java.util.*;
import javax.naming.*;
import javax.naming.ldap.*;

/**
 * Sample code demonstrating how to create/write secrets to an object's
 * SecretStore when logged in as the administrator.
 *
 * @version 3.2
 * @author Steve Kinser
 */
public class AdminDemo extends Object {
    /**
     * The user SecretStore.
     */
    private SecretStore userStore;

    /**
     * Default constructor.
     */
    public AdminDemo() throws Exception {
        setup();
    }

    /**
     * The program's entry point.
     *
     * @param args The command line arguments.
     */
    public static void main(String[] args) {
        try {
            AdminDemo test = new AdminDemo();
            test.runTest();
        } catch (SSException ex) {
            if (ex.hasRoot()) {
                System.err.println(ex.getRoot().getClass().getName() + " ");
                System.err.println(ex.getMessage());
            } else {
                System.err.println(ex.getErrorCode() + " " + ex.getMessage());
            }
            ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Sets up the environment properties and initializes the SecretStore
     * instance variables.
     * <br><br>
     * <b>NOTE</b>: For this to work, the Trusted Root Certificate for the LDAP
     * server must be in the default truststore located in the
     * <java.home>/lib/security/cacerts file.
     */
    protected void setup() throws Exception {
        System.out.print("\nSetting up environment...");

        //ensure the default JSSE provider is added by dynamically adding it
        try {
            Class cls = Class.forName("com.sun.net.ssl.internal.ssl.Provider");
            Provider sunJsse = (Provider) cls.newInstance();
            Security.addProvider(sunJsse);
        } catch (Throwable t) {
            //do nothing, may already be added or another provider may be in use
        }

        //form LdapContext environment properties
        Hashtable ldapEnv = new Hashtable();
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
        ldapEnv.put(Context.PROVIDER_URL, "ldap://127.0.0.1:636");
        ldapEnv.put(Context.SECURITY_PRINCIPAL, "cn=admin,o=novell");
        ldapEnv.put(Context.SECURITY_CREDENTIALS, "test");
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        System.out.print("  done");

        //get LdapContext handle to the initial context
        System.out.print("\nSetting up SSL and Logging in...");
        LdapContext rootContext = new InitialLdapContext(ldapEnv, null);
        System.out.print("  done");

        //get the handle to the admin user object
        LdapContext adminContext = (LdapContext) rootContext.lookup(
                "cn=admin,o=novell");

        //get the handle to the test user object
        LdapContext userContext = (LdapContext) rootContext.lookup(
                "cn=user,o=novell");

        //form the SecretStore environment properties for the admin
        Hashtable ssEnvAdmin = new Hashtable();
        ssEnvAdmin.put(SecretStore.SECRET_STORE,
                "com.novell.security.sso.ldap.jndi.JNDISecretStore");
        ssEnvAdmin.put(SecretStore.HANDLE, adminContext);
        ssEnvAdmin.put(SecretStore.TARGET_DN, "cn=admin,o=novell");

        //get the admin's SecretStore
        System.out.print("\nAccessing SecretStore...");
        SecretStore.getInstance(ssEnvAdmin);

        //form the SecretStore environment properties for the user
        Hashtable ssEnvUser = new Hashtable();
        ssEnvUser.put(SecretStore.SECRET_STORE,
                "com.novell.security.sso.ldap.jndi.JNDISecretStore");
        ssEnvUser.put(SecretStore.HANDLE, userContext);
        ssEnvUser.put(SecretStore.TARGET_DN, "cn=user,o=novell");

        //get the user's SecretStore. Remember, still logged in as admin.
        //The userContext still has admin as the Context.SECURITY_CREDENTIALS
        userStore = SecretStore.getInstance(ssEnvUser);

        /*Use the following code if connecting to SecretStore over ncp
        Hashtable ssEnvAdmin = new Hashtable();
        ssEnvAdmin.put(SecretStore.SECRET_STORE,
              "com.novell.security.sso.ncp.NCPSecretStore");
        ssEnvAdmin.put(SecretStore.TREE, "MYTREE");
        ssEnvAdmin.put(SecretStore.USER_DN, "admin.novell");

        adminStore = SecretStore.getInstance(ssEnvAdmin);

        Hashtable ssEnvUser = new Hashtable();
        ssEnvUser.put(SecretStore.SECRET_STORE,
              "com.novell.security.sso.ncp.NCPSecretStore");
        ssEnvUser.put(SecretStore.TREE, "M");
        ssEnvUser.put(SecretStore.USER_DN, "user.novell");
        userStore = SecretStore.getInstance(ssEnvUser);
        */

        System.out.print("  done");
    }

    /**
     * Runs the test code. Demonstrates how to access another object's
     * SecretStore when logged in as admin.
     */
    public void runTest() throws Exception {
        System.out.print("\nPerforming test...");

        //get a handle to the user secret
        Secret userSecret = userStore.getSecret("\\\\Novell.com\\test");

        //write out the secret, will work if admin has rights to user account.
        userSecret.setValue("password".getBytes());

        try {
            //ensure we get the latest information from SecretStore
            userSecret.read();

            //try to access the secret value
            userSecret.getValue();
        } catch (SSException e) {
            //should fail since admin cannot view user secrets.
        }

        //get a handle to the admin secret
        Secret adminSecret = userStore.getSecret("\\\\Novell.com\\test");

        //write out the secret
        adminSecret.setValue("password".getBytes());

        try {
            //ensure we get the latest information from SecretStore
            adminSecret.read();

            //try to access the secret value
            adminSecret.getValue();
        } catch (SSException e) {
            //shouldn't fail since admin can view its own secrets.
        }

        System.out.print("  done");
    }
}