KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > admin > jmx > remote > https > SunOneBasicX509TrustManager


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 /* SunOneBasicX509TrustManager.java
25  * $Id: SunOneBasicX509TrustManager.java,v 1.4 2005/12/25 04:26:33 tcfujii Exp $
26  * $Revision: 1.4 $
27  * $Date: 2005/12/25 04:26:33 $
28  * Indentation Information:
29  * 0. Please (try to) preserve these settings.
30  * 1. Tabs are preferred over spaces.
31  * 2. In vi/vim -
32  * :set tabstop=4 :set shiftwidth=4 :set softtabstop=4
33  * 3. In S1 Studio -
34  * 1. Tools->Options->Editor Settings->Java Editor->Tab Size = 4
35  * 2. Tools->Options->Indentation Engines->Java Indentation Engine->Expand Tabs to Spaces = False.
36  * 3. Tools->Options->Indentation Engines->Java Indentation Engine->Number of Spaces per Tab = 4.
37  */

38
39 package com.sun.enterprise.admin.jmx.remote.https;
40
41 import javax.net.ssl.X509TrustManager;
42 import java.security.cert.X509Certificate JavaDoc;
43 import java.security.cert.CertificateException JavaDoc;
44 import com.sun.enterprise.admin.jmx.remote.https.AsadminTruststore;
45 import com.sun.enterprise.admin.jmx.remote.IStringManager;
46 import com.sun.enterprise.admin.jmx.remote.StringManagerFactory;
47
48 import java.io.BufferedReader JavaDoc;
49 import java.io.InputStreamReader JavaDoc;
50 import java.io.IOException JavaDoc;
51
52 import java.util.Date JavaDoc;
53 import java.util.Map JavaDoc;
54 import java.text.DateFormat JavaDoc;
55
56 /**
57  * An implementation of {@link X509TrustManager} that provides basic support for Trust Management.
58  * As of $Revision: 1.4 $ it checks if the server is trusted and displays the certificate chain
59  * that was received from the server. The user is then prompted to confirm the certificate. If
60  * confirmed the certificate is entered into the client side asadmintruststore (whose default
61  * name is ~/.asadmintruststore). Once in the truststore, the user is never prompted to confirm
62  * a second time.
63  * @author <a HREF="mailto:Kedar.Mhaswade@sun.com">Kedar Mhaswade</a>
64  * @since S1AS8.0
65  * @version $Revision: 1.4 $
66  */

67 public class SunOneBasicX509TrustManager implements X509TrustManager {
68         
69     private final Object JavaDoc _alias;
70     private boolean _alreadyInvoked;
71     private CertificateException JavaDoc _lastCertException;
72     private RuntimeException JavaDoc _lastRuntimeException;
73     
74     private static IStringManager _strMgr = null;
75         
76     /**
77      * Creates an instance of the SunOneBasicX509TrustManager
78      * @param alias The toString() of the alias object concatenated with a date/time stamp is used as
79      * the alias of the trusted server certificate in the client side .asadmintruststore. When null
80      * only a date / timestamp is used as an alias.
81      */

82     public SunOneBasicX509TrustManager (Object JavaDoc alias, Map JavaDoc env) {
83         if (_strMgr == null)
84             _strMgr = StringManagerFactory.getClientStringManager(SunOneBasicX509TrustManager.class, env);
85         _alias = alias;
86         _alreadyInvoked = false;
87         _lastCertException = null;
88         _lastRuntimeException = null;
89     }
90     
91     /**
92      * Creates an instance of the SunOneBasicX509TrustManager
93      * A date/time stamp is used of the trusted server certificate in the client side
94      *.asadmintruststore
95      */

96     public SunOneBasicX509TrustManager () {
97         this (null, null);
98     }
99     
100     /** Checks if client is trusted given the certificate chain and authorization type string,
101      * e.g. "RSA".
102      * @throws {@link CertificateException}
103      * @throws {@link UnsupportedOperationException}
104      */

105     public void checkClientTrusted(X509Certificate JavaDoc[] x509Certificate, String JavaDoc authType)
106         throws CertificateException JavaDoc
107     {
108         throw new UnsupportedOperationException JavaDoc("Not Implemented for Client Trust Management");
109     }
110     
111     /**
112      * Checs if the server is trusted.
113      * @param chain The server certificate to be validated.
114      * @param authType
115      * @throws CertificateException
116      */

117     public void checkServerTrusted(X509Certificate JavaDoc[] chain, String JavaDoc authType)
118         throws CertificateException JavaDoc
119     {
120         //The alreadyInvoked flag keeps track of whether we have already prompted the
121
//user. Unfortunately, checkServerTrusted is called 2x and we want to avoid
122
//prompting the user twice. I'm not sure of the root cause of this problem (i.e.
123
//why it is called twice. In addition, we keep track of any exception that occurred
124
//on the first invocation and propagate that back.
125
if (!_alreadyInvoked) {
126             _alreadyInvoked = true;
127             try {
128                 checkCertificate(chain);
129             } catch (RuntimeException JavaDoc ex) {
130                 _lastRuntimeException = ex;
131                 throw ex;
132             } catch (CertificateException JavaDoc ex) {
133                 _lastCertException = ex;
134                 throw ex;
135             }
136         } else {
137             if (_lastRuntimeException != null) {
138                 throw _lastRuntimeException;
139             } else if (_lastCertException != null) {
140                 throw _lastCertException;
141             }
142         }
143     }
144     
145     public X509Certificate JavaDoc[] getAcceptedIssuers()
146     {
147         return ( new X509Certificate JavaDoc[0] );
148     }
149
150     /**
151      * @return true if the cert should be displayed and the user asked to confirm it. A
152      * return valie of false indicates that the cert will be implicitly trusted and
153      * added to the asadmin truststore.
154      */

155     protected boolean promptForConfirmation()
156     {
157         return true;
158     }
159     
160     /**
161      * If we fail to open the client database using the default password (changeit) or
162      * the password found in "javax.net.ssl.trustStorePassword" system property,
163      * then the fallback behavior is to prompt the user for the password by calling
164      * this method.
165      * @return the password to the client side truststore
166      */

167     protected String JavaDoc promptForPassword() throws IOException JavaDoc
168     {
169         if (promptForConfirmation()) {
170             System.out.print(_strMgr.getString("certificateDbPrompt"));
171             BufferedReader JavaDoc r = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(System.in));
172             return r.readLine();
173         } else {
174             return null;
175         }
176     }
177
178     /**
179      * Displays the certificate and prompts the user whether or
180      * not it is trusted.
181      * @param c
182      * @throws IOException
183      * @return true if the user trusts the certificate
184      */

185     protected boolean isItOKToAddCertToTrustStore(X509Certificate JavaDoc c) throws IOException JavaDoc
186     {
187         if (promptForConfirmation()) {
188             System.out.println(c.toString());
189             System.out.print(_strMgr.getString("certificateTrustPrompt"));
190             BufferedReader JavaDoc r = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(System.in));
191             String JavaDoc result = r.readLine();
192             if (result != null && result.equalsIgnoreCase("y")) {
193                 return true;
194             } else {
195                 return false;
196             }
197         } else {
198             return true;
199         }
200     }
201     
202     private String JavaDoc getAliasName()
203     {
204         String JavaDoc aliasName = _alias != null ? _alias.toString() : "";
205         //We append a timestamp to the alias to ensure that it is unqiue.
206
DateFormat JavaDoc f = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
207         aliasName += ":" + f.format(new Date JavaDoc());
208         return aliasName;
209     }
210    
211
212     /**
213      * This function validates the cert and ensures that it is trusted.
214      * @param chain
215      * @throws RuntimeException
216      * @throws CertificateException
217      */

218     protected void checkCertificate(X509Certificate JavaDoc[] chain) throws RuntimeException JavaDoc,
219         CertificateException JavaDoc, IllegalArgumentException JavaDoc
220     {
221         if (chain == null || chain.length == 0) {
222             throw new IllegalArgumentException JavaDoc (_strMgr.getString(
223                 "emptyServerCertificate"));
224         }
225         //First ensure that the certificate is valid.
226
for (int i = 0 ; i < chain.length ; i ++) {
227             chain[i].checkValidity();
228         }
229         try {
230             AsadminTruststore truststore = null;
231             try {
232                 truststore = new AsadminTruststore();
233             } catch (IOException JavaDoc ex) {
234                 //An IOException is thrown when an invalid keystore password is entered.
235
//In this case, we prompt the user for the truststore password.
236
String JavaDoc password = promptForPassword();
237                 if (password != null) {
238                     truststore = new AsadminTruststore(password);
239                 } else {
240                     throw ex;
241                 }
242             }
243             //if the certificate already exists in the truststore, it is implicitly trusted
244
if (!truststore.certificateExists(chain[0])) {
245                 //if the certificate does not exist in the truststore, then we prompt the
246
//user. Upon confirmation from the user, the certificate is added to the
247
//truststore.
248
if (isItOKToAddCertToTrustStore(chain[0])) {
249                     truststore.addCertificate(getAliasName(), chain[0]);
250                 } else {
251                     throw new CertificateException JavaDoc(_strMgr.getString(
252                         "serverCertificateNotTrusted"));
253                 }
254             }
255         } catch (CertificateException JavaDoc ex) {
256             throw ex;
257         } catch (Exception JavaDoc e) {
258             throw new RuntimeException JavaDoc(e);
259         }
260     }
261 }
262
Popular Tags