Package com.sun.enterprise.admin.servermgmt

Source Code of com.sun.enterprise.admin.servermgmt.KeystoreManager$KeytoolExecutor

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*
* RepositoryManager.java
*
* Created on August 19, 2003, 2:29 PM
*/

package com.sun.enterprise.admin.servermgmt;

import com.sun.enterprise.security.store.PasswordAdapter;
import com.sun.enterprise.admin.jmx.remote.https.AsadminTruststore;

import com.sun.enterprise.admin.servermgmt.pe.PEFileLayout;

import com.sun.enterprise.util.io.FileUtils;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.enterprise.util.OS;
import com.sun.enterprise.util.SystemPropertyConstants;
import com.sun.enterprise.util.ProcessExecutor;
import com.sun.enterprise.util.ExecException;
import com.sun.enterprise.util.net.NetUtils;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;
import java.util.List;


/**
* @author  kebbs
*/
public class KeystoreManager {
   
    private static final String KEYTOOL_CMD =
        System.getProperty(SystemPropertyConstants.JAVA_ROOT_PROPERTY) + "/bin/keytool";
   
    private static String CERTIFICATE_DN_PREFIX = "CN=";
   
    private static String CERTIFICATE_DN_SUFFIX =
        ",OU=Sun GlassFish Enterprise Server,O=Sun Microsystems,L=Santa Clara,ST=California,C=US";
   
    private static String _certificateDN = null;         
   
    public static final String CERTIFICATE_ALIAS = "s1as";
    public static final String DEFAULT_MASTER_PASSWORD = "changeit";
   
    private static final String SKID_EXTENSION_SYSTEM_PROPERTY =
            "-J-Dsun.security.internal.keytool.skid";
   
    protected class KeytoolExecutor extends ProcessExecutor {           
               
        public KeytoolExecutor(String[] args, long timeoutInSeconds)
        {
            super(args, timeoutInSeconds);
            setExecutionRetentionFlag(true);
            addKeytoolCommand();
        }
       
        public KeytoolExecutor(String[] args, long timeoutInSeconds, String[] inputLines)
        {
            super(args, timeoutInSeconds, inputLines);
            setExecutionRetentionFlag(true);
            addKeytoolCommand();
        }                              
       
        //We must override this message so that the stdout appears in the exec exception.
        //Keytool seems to output errors to stdout.
        protected String getExceptionMessage()
        {           
            return getLatestOutput(mOutFile) + " " +  getFileBuffer(mErrFile);
        }
       
        private void addKeytoolCommand() {
            if (!mCmdStrings[0].equals(KEYTOOL_CMD)) {
                String[] newArgs = new String[mCmdStrings.length + 1];
                newArgs[0] = KEYTOOL_CMD;
                System.arraycopy(mCmdStrings, 0, newArgs, 1, mCmdStrings.length);
                mCmdStrings = newArgs;
            }
        }
       
        public void execute(String keystoreErrorMsg, File keystoreName) throws RepositoryException
        {
            try {
                super.execute();                   
                if (getProcessExitValue() != 0) {
                    throw new RepositoryException(_strMgr.getString(keystoreErrorMsg, keystoreName) +
                        getLastExecutionError() + " " +  getLastExecutionOutput());
                }
            } catch (ExecException ex) {                       
                throw new RepositoryException(_strMgr.getString(keystoreErrorMsg,
                    keystoreName) + getLastExecutionError() + " " +  getLastExecutionOutput(), ex);
            }              
        }
    }   

    protected PEFileLayout _fileLayout = null;
         
    private static final StringManager _strMgr =
        StringManager.getManager(KeystoreManager.class);
      
    /** Creates a new instance of RepositoryManager */
    public KeystoreManager() {
    }
  
    protected String getCertificateDN(String domainName)
    {
        if (_certificateDN == null) {
            String hostName = null;
            try {
                hostName = NetUtils.getCanonicalHostName();                      
            } catch (Exception ex) {
                hostName = "localhost";
            }
            _certificateDN = CERTIFICATE_DN_PREFIX + hostName + CERTIFICATE_DN_SUFFIX;
        }
        return _certificateDN;
    }
    
    protected PEFileLayout getFileLayout(RepositoryConfig config)
    {
        if (_fileLayout == null) {
            _fileLayout = new PEFileLayout(config);
        }
        return _fileLayout;
    }        

    /**
     * Creates the SSL certificate database. In the case of PE this is a keystore.jks
     * and a truststore.jks. In the case of SE/EE, this will be overridden to create
     * the NSS certificate database.
     * @param config
     * @param masterPassword
     * @throws RepositoryException
     */   
    protected void createSSLCertificateDatabase(RepositoryConfig config,
        String masterPassword) throws RepositoryException   
    {
        createKeyStore(config, masterPassword);               
        createTrustStore(config, masterPassword);
    }
   
    /**
     * Create the default SSL key store using keytool to generate a self signed certificate.
     * @param config
     * @param masterPassword
     * @throws RepositoryException
     */
    protected void createKeyStore(
        RepositoryConfig config, String masterPassword) throws RepositoryException
    {
        //Generate a new self signed certificate with s1as as the alias
        final PEFileLayout layout = getFileLayout(config);  
        final File keystore = layout.getKeyStore();
        //Create the default self signed cert
        final String[] keytoolCmd = {               
            "-genkey",
            "-keyalg", "RSA",
            "-keystore", keystore.getAbsolutePath(),
            "-alias", CERTIFICATE_ALIAS,
            "-dname", getCertificateDN(config.getDisplayName()),
            "-validity", "3650",                
            "-keypass", masterPassword,
            "-storepass", masterPassword,
            SKID_EXTENSION_SYSTEM_PROPERTY
        };

        KeytoolExecutor p = new KeytoolExecutor(keytoolCmd, 60);        
        p.execute("keystoreNotCreated", keystore);                               
    }
   
   
    protected void addToAsadminTrustStore(
        RepositoryConfig config, File certFile) throws RepositoryException
    {       
        boolean newTruststore = false;
        final PEFileLayout layout = getFileLayout(config);                 
        //import the newly created certificate into the asadmin truststore
        final File asadminTruststore = AsadminTruststore.getAsadminTruststore();       
       
        if (!asadminTruststore.exists()) {
            newTruststore = true;
        }       
     
        //The keystore alias name is the repository name. We want to avoid alias
        //name conflicts since multiple domains are likely to live on the same
        //machine.
        String aliasName = layout.getRepositoryDir().getAbsolutePath();
       
        //first delete the alias in case it already exists. This can happen for
        //example if a domain is created, deleted, and re-created again.
        String[] keytoolCmd;
        KeytoolExecutor p;
        if (!newTruststore) {
            //delete the alias only if store exists!
            keytoolCmd = new String[] {
            "-delete",
            "-keystore", asadminTruststore.getAbsolutePath(),               
            "-alias", aliasName,
            "-storepass", AsadminTruststore.getAsadminTruststorePassword()
            };
            p = new KeytoolExecutor(keytoolCmd, 30);
            try {
                p.execute("trustStoreNotCreated", asadminTruststore);
            } catch (RepositoryException ex) {
                //ignore all exceptions. The alias most likely does not exist.
            }
        }
        //now add the recently created server's cert to .asadmintruststore
        keytoolCmd = new String[] {               
            "-import",
            "-noprompt",
            "-keystore", asadminTruststore.getAbsolutePath(),               
            "-alias", aliasName, //alias is the domain name
            "-file", certFile.getAbsolutePath(),
            "-storepass", AsadminTruststore.getAsadminTruststorePassword()
        };                              
       
        p = new KeytoolExecutor(keytoolCmd, 30);             
        p.execute("trustStoreNotCreated", asadminTruststore);         
       
        //If this is a newly created truststore, lock it down.
        if (newTruststore && asadminTruststore.exists()) {
            try {
                chmod("600", asadminTruststore);
            } catch (IOException ex) {
                throw new RepositoryException(_strMgr.getString(
                    "trustStoreNotCreated", asadminTruststore), ex);
            }
        }
    }
   
    /**
     * Create the default SSL trust store. We take throws template cacerts.jks, change its password
     * to the master password, and then add in the self signed s1as certificate created earlier.
     * All this is done my exec'ing keytool
     * @param config
     * @param masterPassword
     * @throws RepositoryException
     */
    protected void createTrustStore(
        RepositoryConfig config, String masterPassword) throws RepositoryException
    {
        //copy the default truststore from the installation template directory
        final PEFileLayout layout = getFileLayout(config);
        final File src = layout.getTrustStoreTemplate();
        final File truststore = layout.getTrustStore();
        File certFile = null;
       
        try {
            FileUtils.copy(src, truststore);
        } catch (IOException ioe) {
            throw new RepositoryException(
                _strMgr.getString("trustStoreNotCreated", truststore), ioe);
        }
               
        try {
            String[] input = {masterPassword};
            String[] keytoolCmd = null;
            KeytoolExecutor p = null;
           
            changeKeystorePassword(DEFAULT_MASTER_PASSWORD, masterPassword, truststore);
           
            //export the newly created certificate from the keystore
            certFile = new File(layout.getConfigRoot(), CERTIFICATE_ALIAS + ".cer");           
            keytoolCmd = new String[] {               
                "-export",
                "-keystore", layout.getKeyStore().getAbsolutePath(),               
                "-alias", CERTIFICATE_ALIAS,
                "-file", certFile.getAbsolutePath(),               
            };                       
           
            p = new KeytoolExecutor(keytoolCmd, 30, input);
            p.execute("trustStoreNotCreated", truststore);
                      
            //import the newly created certificate into the truststore
            keytoolCmd = new String[] {               
                "-import",
                "-noprompt",
                "-keystore", truststore.getAbsolutePath(),               
                "-alias", CERTIFICATE_ALIAS,
                "-file", certFile.getAbsolutePath(),               
            };                       
           
            p = new KeytoolExecutor(keytoolCmd, 30, input);             
            p.execute("trustStoreNotCreated", truststore);                                     
            
            //import the newly created certificate into the asadmin truststore
            addToAsadminTrustStore(config, certFile);
           
            //clean up the exported cert file
            certFile.delete();          
            certFile = null;
        finally {
            if (certFile != null) {
                certFile.delete();
            }
        }
    }   

    /**
     * Changes the keystore password
     * @param oldPassword the old keystore password
     * @param newPassword the new keystore password
     * @param keystore the keystore whose password is to be changed.
     * @throws RepositoryException
     */   
    protected void changeKeystorePassword(String oldPassword, String newPassword,
        File keystore) throws RepositoryException
    {
        if (!oldPassword.equals(newPassword)) {
            //change truststore password from the default
            String[] keytoolCmd = {               
                "-storepasswd",
                "-keystore", keystore.getAbsolutePath(),                                          
            };

            KeytoolExecutor p = new KeytoolExecutor(keytoolCmd, 30,
                new String[] {oldPassword, newPassword, newPassword});             
            p.execute("keyStorePasswordNotChanged", keystore);
        }
    }
   
   
    /**
     * Changes the key password for the default cert whose alias is s1as. The assumption
     * here is that the keystore password is not the same as the key password. This is
     * due to the fact that the keystore password should first be changed followed next
     * by the key password. The end result is that the keystore and s1as key both have
     * the same passwords. This function will tolerate deletion of the s1as alias, but
     * it will not tolerate changing the s1as key from something other than the
     * database password.
     * @param config
     * @param storePassword the keystore password
     * @param oldKeyPassword the old password for the s1as alias
     * @param newKeyPassword the new password for the s1as alias
     * @throws RepositoryException
     */   
    protected void changeS1ASAliasPassword(RepositoryConfig config,
        String storePassword, String oldKeyPassword, String newKeyPassword)
        throws RepositoryException
    {               
        if (!storePassword.equals(oldKeyPassword) && !oldKeyPassword.equals(newKeyPassword)) {
            final PEFileLayout layout = getFileLayout(config);
            final File src = layout.getTrustStoreTemplate();
            final File keystore = layout.getKeyStore();
            //First see if the alias exists. The user could have deleted it. Any failure in the
            //command indicates that the alias does not exist, so we return without error.
            String[] keytoolCmd = {               
                "-list",
                "-keystore", keystore.getAbsolutePath(),  
                "-alias", CERTIFICATE_ALIAS,
            };           
            KeytoolExecutor p = new KeytoolExecutor(keytoolCmd, 30,
                new String[] {storePassword})
            try {
                p.execute("s1asKeyPasswordNotChanged", keystore);                                   
            } catch (RepositoryException ex) {
                return;
            }
           
            //change truststore password from the default
            keytoolCmd = new String[] {               
                "-keypasswd",
                "-keystore", keystore.getAbsolutePath(),  
                "-alias", CERTIFICATE_ALIAS,
            };
            p = new KeytoolExecutor(keytoolCmd, 30,
                new String[] {storePassword, oldKeyPassword, newKeyPassword, newKeyPassword});             
            p.execute("s1asKeyPasswordNotChanged", keystore);                                  
        }
    }
   
    /**
     * Changes the password of the keystore, truststore and the key password
     * of the s1as alias. It is expected that the key / truststores may not exist.
     * This is due to the fact that the user may have deleted them and wishes to set
     * up their own key/truststore
     * @param config
     * @param storePassword
     * @param oldKeyPassword
     * @param newKeyPassword
     */   
    protected void changeSSLCertificateDatabasePassword(RepositoryConfig config,
        String oldPassword, String newPassword) throws RepositoryException
    {
        final PEFileLayout layout = getFileLayout(config);
        File keystore = layout.getKeyStore();
        File truststore = layout.getTrustStore();              

        if (keystore.exists()) {
            //Change the password on the keystore      
            changeKeystorePassword(oldPassword, newPassword, keystore);           
            //Change the s1as alias password in the keystore...The assumption
            //here is that the keystore password is not the same as the key password. This is
             //due to the fact that the keystore password should first be changed followed next
             //by the key password. The end result is that the keystore and s1as key both have
             //the same passwords. This function will tolerate deletion of the s1as alias, but
             //it will not tolerate changing the s1as key from something other than the
             //database password.
            try {
                changeS1ASAliasPassword(config, newPassword, oldPassword, newPassword);
            } catch (Exception ex) {
                //For now we eat all exceptions and dump to stderr if the password
                //alias could not be changed.
                ex.printStackTrace();
            }
        }

        if (truststore.exists()) {
            //Change the password on the truststore
            changeKeystorePassword(oldPassword, newPassword, truststore);
        }
    }       
   
    protected void chmod(String args, File file) throws IOException
    {
        if (OS.isUNIX()) {
            //args and file should never be null.
            if (args == null || file == null) throw new IOException(_strMgr.getString("nullArg"));
            if (!file.exists()) throw new IOException(_strMgr.getString("fileNotFound"));           

            // " +" regular expression for 1 or more spaces
            final String[] argsString = args.split(" +");
            List<String> cmdList = new ArrayList<String>();
            cmdList.add("/bin/chmod");
            for (String arg : argsString)
                cmdList.add(arg);
            cmdList.add(file.getAbsolutePath());
            new ProcessBuilder(cmdList).start();
        }
    }
}
TOP

Related Classes of com.sun.enterprise.admin.servermgmt.KeystoreManager$KeytoolExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.