KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > admin > servermgmt > KeystoreManager


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * RepositoryManager.java
26  *
27  * Created on August 19, 2003, 2:29 PM
28  */

29
30 package com.sun.enterprise.admin.servermgmt;
31
32 import com.sun.enterprise.security.store.PasswordAdapter;
33 import com.sun.enterprise.admin.jmx.remote.https.AsadminTruststore;
34
35 import com.sun.enterprise.admin.servermgmt.pe.PEFileLayout;
36
37 import com.sun.enterprise.util.io.FileUtils;
38 import com.sun.enterprise.util.i18n.StringManager;
39 import com.sun.enterprise.util.OS;
40 import com.sun.enterprise.util.SystemPropertyConstants;
41 import com.sun.enterprise.util.ProcessExecutor;
42 import com.sun.enterprise.util.ExecException;
43 import com.sun.enterprise.util.net.NetUtils;
44
45 import java.io.File JavaDoc;
46 import java.io.IOException JavaDoc;
47
48 /**
49  * @author kebbs
50  */

51 public class KeystoreManager {
52     
53     private static final String JavaDoc KEYTOOL_CMD =
54         System.getProperty(SystemPropertyConstants.JAVA_ROOT_PROPERTY) + "/bin/keytool";
55     
56     private static String JavaDoc CERTIFICATE_DN_PREFIX = "CN=";
57     
58     private static String JavaDoc CERTIFICATE_DN_SUFFIX =
59         ",OU=Sun Java System Application Server,O=Sun Microsystems,L=Santa Clara,ST=California,C=US";
60     
61     private static String JavaDoc _certificateDN = null;
62     
63     public static final String JavaDoc CERTIFICATE_ALIAS = "s1as";
64     public static final String JavaDoc DEFAULT_MASTER_PASSWORD = "changeit";
65     
66     protected class KeytoolExecutor extends ProcessExecutor {
67                 
68         public KeytoolExecutor(String JavaDoc[] args, long timeoutInSeconds)
69         {
70             super(args, timeoutInSeconds);
71             setExecutionRetentionFlag(true);
72             addKeytoolCommand();
73         }
74         
75         public KeytoolExecutor(String JavaDoc[] args, long timeoutInSeconds, String JavaDoc[] inputLines)
76         {
77             super(args, timeoutInSeconds, inputLines);
78             setExecutionRetentionFlag(true);
79             addKeytoolCommand();
80         }
81         
82         //We must override this message so that the stdout appears in the exec exception.
83
//Keytool seems to output errors to stdout.
84
protected String JavaDoc getExceptionMessage()
85         {
86             return getLatestOutput(mOutFile) + " " + getFileBuffer(mErrFile);
87         }
88         
89         private void addKeytoolCommand() {
90             if (!mCmdStrings[0].equals(KEYTOOL_CMD)) {
91                 String JavaDoc[] newArgs = new String JavaDoc[mCmdStrings.length + 1];
92                 newArgs[0] = KEYTOOL_CMD;
93                 System.arraycopy(mCmdStrings, 0, newArgs, 1, mCmdStrings.length);
94                 mCmdStrings = newArgs;
95             }
96         }
97         
98         public void execute(String JavaDoc keystoreErrorMsg, File JavaDoc keystoreName) throws RepositoryException
99         {
100             try {
101                 super.execute();
102                 if (getProcessExitValue() != 0) {
103                     throw new RepositoryException(_strMgr.getString(keystoreErrorMsg, keystoreName) +
104                         getLastExecutionError() + " " + getLastExecutionOutput());
105                 }
106             } catch (ExecException ex) {
107                 throw new RepositoryException(_strMgr.getString(keystoreErrorMsg,
108                     keystoreName) + getLastExecutionError() + " " + getLastExecutionOutput(), ex);
109             }
110         }
111     }
112
113     protected PEFileLayout _fileLayout = null;
114           
115     private static final StringManager _strMgr =
116         StringManager.getManager(KeystoreManager.class);
117        
118     /** Creates a new instance of RepositoryManager */
119     public KeystoreManager() {
120     }
121    
122     protected String JavaDoc getCertificateDN(String JavaDoc domainName)
123     {
124         if (_certificateDN == null) {
125             String JavaDoc hostName = null;
126             try {
127                 hostName = NetUtils.getCanonicalHostName();
128             } catch (Exception JavaDoc ex) {
129                 hostName = "localhost";
130             }
131             _certificateDN = CERTIFICATE_DN_PREFIX + hostName + CERTIFICATE_DN_SUFFIX;
132         }
133         return _certificateDN;
134     }
135      
136     protected PEFileLayout getFileLayout(RepositoryConfig config)
137     {
138         if (_fileLayout == null) {
139             _fileLayout = new PEFileLayout(config);
140         }
141         return _fileLayout;
142     }
143
144     /**
145      * Creates the SSL certificate database. In the case of PE this is a keystore.jks
146      * and a truststore.jks. In the case of SE/EE, this will be overridden to create
147      * the NSS certificate database.
148      * @param config
149      * @param masterPassword
150      * @throws RepositoryException
151      */

152     protected void createSSLCertificateDatabase(RepositoryConfig config,
153         String JavaDoc masterPassword) throws RepositoryException
154     {
155         createKeyStore(config, masterPassword);
156         createTrustStore(config, masterPassword);
157     }
158     
159     /**
160      * Create the default SSL key store using keytool to generate a self signed certificate.
161      * @param config
162      * @param masterPassword
163      * @throws RepositoryException
164      */

165     protected void createKeyStore(
166         RepositoryConfig config, String JavaDoc masterPassword) throws RepositoryException
167     {
168         //Generate a new self signed certificate with s1as as the alias
169
final PEFileLayout layout = getFileLayout(config);
170         final File JavaDoc keystore = layout.getKeyStore();
171         //Create the default self signed cert
172
final String JavaDoc[] keytoolCmd = {
173             "-genkey",
174             "-keyalg", "RSA",
175             "-keystore", keystore.getAbsolutePath(),
176             "-alias", CERTIFICATE_ALIAS,
177             "-dname", getCertificateDN(config.getDisplayName()),
178             "-validity", "3650",
179             "-keypass", masterPassword,
180             "-storepass", masterPassword
181         };
182
183         KeytoolExecutor p = new KeytoolExecutor(keytoolCmd, 60);
184         p.execute("keystoreNotCreated", keystore);
185     }
186     
187     
188     protected void addToAsadminTrustStore(
189         RepositoryConfig config, File JavaDoc certFile) throws RepositoryException
190     {
191         boolean newTruststore = false;
192         final PEFileLayout layout = getFileLayout(config);
193         //import the newly created certificate into the asadmin truststore
194
final File JavaDoc asadminTruststore = AsadminTruststore.getAsadminTruststore();
195         
196         if (!asadminTruststore.exists()) {
197             newTruststore = true;
198         }
199       
200         //The keystore alias name is the repository name. We want to avoid alias
201
//name conflicts since multiple domains are likely to live on the same
202
//machine.
203
String JavaDoc aliasName = layout.getRepositoryDir().getAbsolutePath();
204         
205         //first delete the alias in case it already exists. This can happen for
206
//example if a domain is created, deleted, and re-created again.
207
String JavaDoc[] keytoolCmd = new String JavaDoc[] {
208             "-delete",
209             "-keystore", asadminTruststore.getAbsolutePath(),
210             "-alias", aliasName,
211         };
212         
213         final String JavaDoc[] input = {AsadminTruststore.getAsadminTruststorePassword(),
214             AsadminTruststore.getAsadminTruststorePassword()}; // twice in case we are creating
215
KeytoolExecutor p = new KeytoolExecutor(keytoolCmd, 30, input);
216         try {
217             p.execute("trustStoreNotCreated", asadminTruststore);
218         } catch (RepositoryException ex) {
219             //ignore all exceptions. The alias most likely does not exist.
220
}
221             
222         keytoolCmd = new String JavaDoc[] {
223             "-import",
224             "-noprompt",
225             "-keystore", asadminTruststore.getAbsolutePath(),
226             "-alias", aliasName, //alias is the domain name
227
"-file", certFile.getAbsolutePath(),
228         };
229         
230         p = new KeytoolExecutor(keytoolCmd, 30, input);
231         p.execute("trustStoreNotCreated", asadminTruststore);
232         
233         //If this is a newly created truststore, lock it down.
234
if (newTruststore) {
235             try {
236                 chmod("600", asadminTruststore);
237             } catch (IOException JavaDoc ex) {
238                 throw new RepositoryException(_strMgr.getString(
239                     "trustStoreNotCreated", asadminTruststore), ex);
240             }
241         }
242     }
243     
244     /**
245      * Create the default SSL trust store. We take throws template cacerts.jks, change its password
246      * to the master password, and then add in the self signed s1as certificate created earlier.
247      * All this is done my exec'ing keytool
248      * @param config
249      * @param masterPassword
250      * @throws RepositoryException
251      */

252     protected void createTrustStore(
253         RepositoryConfig config, String JavaDoc masterPassword) throws RepositoryException
254     {
255         //copy the default truststore from the installation template directory
256
final PEFileLayout layout = getFileLayout(config);
257         final File JavaDoc src = layout.getTrustStoreTemplate();
258         final File JavaDoc truststore = layout.getTrustStore();
259         File JavaDoc certFile = null;
260         
261         try {
262             FileUtils.copy(src, truststore);
263         } catch (IOException JavaDoc ioe) {
264             throw new RepositoryException(
265                 _strMgr.getString("trustStoreNotCreated", truststore), ioe);
266         }
267                 
268         try {
269             String JavaDoc[] input = {masterPassword};
270             String JavaDoc[] keytoolCmd = null;
271             KeytoolExecutor p = null;
272             
273             changeKeystorePassword(DEFAULT_MASTER_PASSWORD, masterPassword, truststore);
274             
275             //export the newly created certificate from the keystore
276
certFile = new File JavaDoc(layout.getConfigRoot(), CERTIFICATE_ALIAS + ".cer");
277             keytoolCmd = new String JavaDoc[] {
278                 "-export",
279                 "-keystore", layout.getKeyStore().getAbsolutePath(),
280                 "-alias", CERTIFICATE_ALIAS,
281                 "-file", certFile.getAbsolutePath(),
282             };
283             
284             p = new KeytoolExecutor(keytoolCmd, 30, input);
285             p.execute("trustStoreNotCreated", truststore);
286                        
287             //import the newly created certificate into the truststore
288
keytoolCmd = new String JavaDoc[] {
289                 "-import",
290                 "-noprompt",
291                 "-keystore", truststore.getAbsolutePath(),
292                 "-alias", CERTIFICATE_ALIAS,
293                 "-file", certFile.getAbsolutePath(),
294             };
295             
296             p = new KeytoolExecutor(keytoolCmd, 30, input);
297             p.execute("trustStoreNotCreated", truststore);
298              
299             //import the newly created certificate into the asadmin truststore
300
addToAsadminTrustStore(config, certFile);
301             
302             //clean up the exported cert file
303
certFile.delete();
304             certFile = null;
305         } finally {
306             if (certFile != null) {
307                 certFile.delete();
308             }
309         }
310     }
311
312     /**
313      * Changes the keystore password
314      * @param oldPassword the old keystore password
315      * @param newPassword the new keystore password
316      * @param keystore the keystore whose password is to be changed.
317      * @throws RepositoryException
318      */

319     protected void changeKeystorePassword(String JavaDoc oldPassword, String JavaDoc newPassword,
320         File JavaDoc keystore) throws RepositoryException
321     {
322         if (!oldPassword.equals(newPassword)) {
323             //change truststore password from the default
324
String JavaDoc[] keytoolCmd = {
325                 "-storepasswd",
326                 "-keystore", keystore.getAbsolutePath(),
327             };
328
329             KeytoolExecutor p = new KeytoolExecutor(keytoolCmd, 30,
330                 new String JavaDoc[] {oldPassword, newPassword, newPassword});
331             p.execute("keyStorePasswordNotChanged", keystore);
332         }
333     }
334     
335     
336     /**
337      * Changes the key password for the default cert whose alias is s1as. The assumption
338      * here is that the keystore password is not the same as the key password. This is
339      * due to the fact that the keystore password should first be changed followed next
340      * by the key password. The end result is that the keystore and s1as key both have
341      * the same passwords. This function will tolerate deletion of the s1as alias, but
342      * it will not tolerate changing the s1as key from something other than the
343      * database password.
344      * @param config
345      * @param storePassword the keystore password
346      * @param oldKeyPassword the old password for the s1as alias
347      * @param newKeyPassword the new password for the s1as alias
348      * @throws RepositoryException
349      */

350     protected void changeS1ASAliasPassword(RepositoryConfig config,
351         String JavaDoc storePassword, String JavaDoc oldKeyPassword, String JavaDoc newKeyPassword)
352         throws RepositoryException
353     {
354         if (!storePassword.equals(oldKeyPassword) && !oldKeyPassword.equals(newKeyPassword)) {
355             final PEFileLayout layout = getFileLayout(config);
356             final File JavaDoc src = layout.getTrustStoreTemplate();
357             final File JavaDoc keystore = layout.getKeyStore();
358             //First see if the alias exists. The user could have deleted it. Any failure in the
359
//command indicates that the alias does not exist, so we return without error.
360
String JavaDoc[] keytoolCmd = {
361                 "-list",
362                 "-keystore", keystore.getAbsolutePath(),
363                 "-alias", CERTIFICATE_ALIAS,
364             };
365             KeytoolExecutor p = new KeytoolExecutor(keytoolCmd, 30,
366                 new String JavaDoc[] {storePassword});
367             try {
368                 p.execute("s1asKeyPasswordNotChanged", keystore);
369             } catch (RepositoryException ex) {
370                 return;
371             }
372             
373             //change truststore password from the default
374
keytoolCmd = new String JavaDoc[] {
375                 "-keypasswd",
376                 "-keystore", keystore.getAbsolutePath(),
377                 "-alias", CERTIFICATE_ALIAS,
378             };
379             p = new KeytoolExecutor(keytoolCmd, 30,
380                 new String JavaDoc[] {storePassword, oldKeyPassword, newKeyPassword, newKeyPassword});
381             p.execute("s1asKeyPasswordNotChanged", keystore);
382         }
383     }
384     
385     /**
386      * Changes the password of the keystore, truststore and the key password
387      * of the s1as alias. It is expected that the key / truststores may not exist.
388      * This is due to the fact that the user may have deleted them and wishes to set
389      * up their own key/truststore
390      * @param config
391      * @param storePassword
392      * @param oldKeyPassword
393      * @param newKeyPassword
394      */

395     protected void changeSSLCertificateDatabasePassword(RepositoryConfig config,
396         String JavaDoc oldPassword, String JavaDoc newPassword) throws RepositoryException
397     {
398         final PEFileLayout layout = getFileLayout(config);
399         File JavaDoc keystore = layout.getKeyStore();
400         File JavaDoc truststore = layout.getTrustStore();
401
402         if (keystore.exists()) {
403             //Change the password on the keystore
404
changeKeystorePassword(oldPassword, newPassword, keystore);
405             //Change the s1as alias password in the keystore...The assumption
406
//here is that the keystore password is not the same as the key password. This is
407
//due to the fact that the keystore password should first be changed followed next
408
//by the key password. The end result is that the keystore and s1as key both have
409
//the same passwords. This function will tolerate deletion of the s1as alias, but
410
//it will not tolerate changing the s1as key from something other than the
411
//database password.
412
try {
413                 changeS1ASAliasPassword(config, newPassword, oldPassword, newPassword);
414             } catch (Exception JavaDoc ex) {
415                 //For now we eat all exceptions and dump to stderr if the password
416
//alias could not be changed.
417
ex.printStackTrace();
418             }
419         }
420
421         if (truststore.exists()) {
422             //Change the password on the truststore
423
changeKeystorePassword(oldPassword, newPassword, truststore);
424         }
425     }
426     
427     protected void chmod(String JavaDoc args, File JavaDoc file) throws IOException JavaDoc
428     {
429         if (OS.isUNIX()) {
430             Runtime.getRuntime().exec("/bin/chmod " + args + " " +
431                 file.getAbsolutePath());
432         }
433     }
434 }
435
Popular Tags