OSDN Git Service

Exposed default trust manager.
[android-x86/dalvik.git] / libcore / x-net / src / main / java / org / apache / harmony / xnet / provider / jsse / SSLParameters.java
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 /**
19  * @author Alexander Y. Kleymenov
20  * @version $Revision$
21  */
22
23 package org.apache.harmony.xnet.provider.jsse;
24
25 import java.security.KeyManagementException;
26 import java.security.KeyStore;
27 import java.security.KeyStoreException;
28 import java.security.NoSuchAlgorithmException;
29 import java.security.SecureRandom;
30 import java.security.UnrecoverableKeyException;
31 import javax.net.ssl.KeyManager;
32 import javax.net.ssl.KeyManagerFactory;
33 import javax.net.ssl.TrustManager;
34 import javax.net.ssl.TrustManagerFactory;
35 import javax.net.ssl.X509KeyManager;
36 import javax.net.ssl.X509TrustManager;
37
38 /**
39  * The instances of this class incapsulate all the info
40  * about enabled cipher suites and protocols,
41  * as well as the information about client/server mode of
42  * ssl socket, whether it require/want client authentication or not,
43  * and controls whether new SSL sessions may be established by this
44  * socket or not.
45  */
46 // BEGIN android-changed
47 public class SSLParameters implements Cloneable {
48 // END android-changed
49
50     // default source of authentication keys
51     private static X509KeyManager defaultKeyManager;
52     // default source of authentication trust decisions
53     private static X509TrustManager defaultTrustManager;
54     // default source of random numbers
55     private static SecureRandom defaultSecureRandom;
56     // default SSL parameters
57     private static SSLParameters defaultParameters;
58
59     // client session context contains the set of reusable
60     // client-side SSL sessions
61 // BEGIN android-changed
62     private final ClientSessionContext clientSessionContext;
63     // server session context contains the set of reusable
64     // server-side SSL sessions
65     private final ServerSessionContext serverSessionContext;
66 // END android-changed
67     // source of authentication keys
68     private X509KeyManager keyManager;
69     // source of authentication trust decisions
70     private X509TrustManager trustManager;
71     // source of random numbers
72     private SecureRandom secureRandom;
73
74     // cipher suites available for SSL connection
75     // BEGIN android-changed
76     private CipherSuite[] enabledCipherSuites;
77     // END android-changed
78     // string representations of available cipher suites
79     private String[] enabledCipherSuiteNames = null;
80
81     // protocols available for SSL connection
82     private String[] enabledProtocols = ProtocolVersion.supportedProtocols;
83     
84     // if the peer with this parameters tuned to work in client mode
85     private boolean client_mode = true;
86     // if the peer with this parameters tuned to require client authentication
87     private boolean need_client_auth = false;
88     // if the peer with this parameters tuned to request client authentication
89     private boolean want_client_auth = false;
90     // if the peer with this parameters allowed to cteate new SSL session
91     private boolean enable_session_creation = true;
92
93 // BEGIN android-changed
94     protected CipherSuite[] getEnabledCipherSuitesMember() {
95         if (enabledCipherSuites == null) this.enabledCipherSuites = CipherSuite.defaultCipherSuites;
96         return enabledCipherSuites;
97     }
98
99     /**
100      * Holds a pointer to our native SSL context.
101      */
102     private int ssl_ctx = 0;
103     
104     /**
105      * Initializes our native SSL context.
106      */
107     private native int nativeinitsslctx();
108
109     /**
110      * Returns the native SSL context, creating it on-the-fly, if necessary.
111      */
112     protected synchronized int getSSLCTX() {
113         if (ssl_ctx == 0) ssl_ctx = nativeinitsslctx();
114         return ssl_ctx;
115     }
116 // END android-changed
117
118     /**
119      * Initializes the parameters. Naturally this constructor is used
120      * in SSLContextImpl.engineInit method which dirrectly passes its 
121      * parameters. In other words this constructor holds all
122      * the functionality provided by SSLContext.init method.
123      * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[],
124      * SecureRandom)} for more information
125      */
126     protected SSLParameters(KeyManager[] kms, TrustManager[] tms,
127 // BEGIN android-changed
128             SecureRandom sr, SSLClientSessionCache clientCache,
129             SSLServerSessionCache serverCache)
130             throws KeyManagementException {
131         this.serverSessionContext
132                 = new ServerSessionContext(this, serverCache);
133         this.clientSessionContext
134                 = new ClientSessionContext(this, clientCache);
135 // END android-changed
136         try {
137             // initialize key manager
138             boolean initialize_default = false;
139             // It's not described by the spec of SSLContext what should happen 
140             // if the arrays of length 0 are specified. This implementation
141             // behave as for null arrays (i.e. use installed security providers)
142             if ((kms == null) || (kms.length == 0)) {
143                 if (defaultKeyManager == null) {
144                     KeyManagerFactory kmf = KeyManagerFactory.getInstance(
145                             KeyManagerFactory.getDefaultAlgorithm());
146                     kmf.init(null, null);                
147                     kms = kmf.getKeyManagers();
148                     // tell that we are trying to initialize defaultKeyManager
149                     initialize_default = true;
150                 } else {
151                     keyManager = defaultKeyManager;
152                 }
153             }
154             if (keyManager == null) { // was not initialized by default
155                 for (int i = 0; i < kms.length; i++) {
156                     if (kms[i] instanceof X509KeyManager) {
157                         keyManager = (X509KeyManager)kms[i];
158                         break;
159                     }
160                 }
161                 if (keyManager == null) {
162                     throw new KeyManagementException("No X509KeyManager found");
163                 }
164                 if (initialize_default) {
165                     // found keyManager is default key manager
166                     defaultKeyManager = keyManager;
167                 }
168             }
169             
170             // initialize trust manager
171             initialize_default = false;
172             if ((tms == null) || (tms.length == 0)) {
173                 if (defaultTrustManager == null) {
174                     TrustManagerFactory tmf = TrustManagerFactory
175                         .getInstance(TrustManagerFactory.getDefaultAlgorithm());
176                     tmf.init((KeyStore)null);
177                     tms = tmf.getTrustManagers();
178                     initialize_default = true;
179                 } else {
180                     trustManager = defaultTrustManager;
181                 }
182             }
183             if (trustManager == null) { // was not initialized by default
184                 for (int i = 0; i < tms.length; i++) {
185                     if (tms[i] instanceof X509TrustManager) {
186                         trustManager = (X509TrustManager)tms[i];
187                         break;
188                     }
189                 }
190                 if (trustManager == null) {
191                     throw new KeyManagementException("No X509TrustManager found");
192                 }
193                 if (initialize_default) {
194                     // found trustManager is default trust manager
195                     defaultTrustManager = trustManager;
196                 }
197             }
198         } catch (NoSuchAlgorithmException e) {
199             throw new KeyManagementException(e);
200         } catch (KeyStoreException e) {
201             throw new KeyManagementException(e);
202         } catch (UnrecoverableKeyException e) {
203             throw new KeyManagementException(e);            
204         }
205         // initialize secure random
206         // BEGIN android-removed
207         // if (sr == null) {
208         //     if (defaultSecureRandom == null) {
209         //         defaultSecureRandom = new SecureRandom();
210         //     }
211         //     secureRandom = defaultSecureRandom;
212         // } else {
213         //     secureRandom = sr;
214         // }
215         // END android-removed
216         // BEGIN android-added
217         // We simply use the SecureRandom passed in by the caller. If it's
218         // null, we don't replace it by a new instance. The native code below
219         // then directly accesses /dev/urandom. Not the most elegant solution,
220         // but faster than going through the SecureRandom object. 
221             secureRandom = sr;
222         // END android-added
223     }
224
225     protected static SSLParameters getDefault() throws KeyManagementException {
226         if (defaultParameters == null) {
227 // BEGIN android-changed
228             defaultParameters = new SSLParameters(null, null, null, null, null);
229 // END android-changed
230         }
231         return (SSLParameters) defaultParameters.clone();
232     }
233     
234     /**
235      * @return server session context
236      */
237 // BEGIN android-changed
238     protected ServerSessionContext getServerSessionContext() {
239 // END android-changed
240         return serverSessionContext;
241     }
242
243     /**
244      * @return client session context
245      */
246 // BEGIN android-changed
247     protected ClientSessionContext getClientSessionContext() {
248 // END android-changed
249         return clientSessionContext;
250     }
251
252     /**
253      * @return key manager
254      */
255     protected X509KeyManager getKeyManager() {
256         return keyManager;
257     }
258
259     /**
260      * @return trust manager
261      */
262     protected X509TrustManager getTrustManager() {
263         return trustManager;
264     }
265
266     /**
267      * @return secure random
268      */
269     protected SecureRandom getSecureRandom() {
270         // BEGIN android-removed
271         // return secureRandom;
272         // END android-removed
273         // BEGIN android-added
274         if (secureRandom != null) return secureRandom;
275         if (defaultSecureRandom == null)
276         {
277             defaultSecureRandom = new SecureRandom();
278         }
279         secureRandom = defaultSecureRandom;
280         // END android-added
281         return secureRandom;
282     }
283
284     // BEGIN android-added
285     /**
286      * @return the secure random member reference, even it is null
287      */
288     protected SecureRandom getSecureRandomMember() {
289         return secureRandom;
290     }
291     // END android-added
292     
293     /**
294      * @return the names of enabled cipher suites
295      */
296     protected String[] getEnabledCipherSuites() {
297         if (enabledCipherSuiteNames == null) {
298             // BEGIN android-added
299             CipherSuite[] enabledCipherSuites = getEnabledCipherSuitesMember();
300             // END android-added
301             enabledCipherSuiteNames = new String[enabledCipherSuites.length];
302             for (int i = 0; i< enabledCipherSuites.length; i++) {
303                 enabledCipherSuiteNames[i] = enabledCipherSuites[i].getName();
304             }
305         }
306         return (String[]) enabledCipherSuiteNames.clone();
307     }
308
309     /**
310      * Sets the set of available cipher suites for use in SSL connection.
311      * @param   suites: String[]
312      * @return
313      */
314     protected void setEnabledCipherSuites(String[] suites) {
315         if (suites == null) {
316             throw new IllegalArgumentException("Provided parameter is null");
317         }
318         CipherSuite[] cipherSuites = new CipherSuite[suites.length];
319         for (int i=0; i<suites.length; i++) {
320             cipherSuites[i] = CipherSuite.getByName(suites[i]);
321             if (cipherSuites[i] == null || !cipherSuites[i].supported) {
322                 throw new IllegalArgumentException(suites[i] +
323                         " is not supported.");
324             }
325         }
326         enabledCipherSuites = cipherSuites;
327         enabledCipherSuiteNames = suites;
328     }
329
330     /**
331      * @return the set of enabled protocols
332      */
333     protected String[] getEnabledProtocols() {
334         return (String[]) enabledProtocols.clone();
335     }
336
337     /**
338      * Sets the set of available protocols for use in SSL connection.
339      * @param protocols String[]
340      */
341     protected void setEnabledProtocols(String[] protocols) {
342         if (protocols == null) {
343             throw new IllegalArgumentException("Provided parameter is null");
344         }
345         for (int i=0; i<protocols.length; i++) {
346             if (!ProtocolVersion.isSupported(protocols[i])) {
347                 throw new IllegalArgumentException("Protocol " + protocols[i] +
348                         " is not supported.");
349             }
350         }
351         enabledProtocols = protocols;
352     }
353
354     /**
355      * Tunes the peer holding this parameters to work in client mode.
356      * @param   mode if the peer is configured to work in client mode
357      */
358     protected void setUseClientMode(boolean mode) {
359         client_mode = mode;
360     }
361
362     /**
363      * Returns the value indicating if the parameters configured to work
364      * in client mode.
365      */
366     protected boolean getUseClientMode() {
367         return client_mode;
368     }
369
370     /**
371      * Tunes the peer holding this parameters to require client authentication
372      */
373     protected void setNeedClientAuth(boolean need) {
374         need_client_auth = need;
375         // reset the want_client_auth setting
376         want_client_auth = false;
377     }
378
379     /**
380      * Returns the value indicating if the peer with this parameters tuned
381      * to require client authentication
382      */
383     protected boolean getNeedClientAuth() {
384         return need_client_auth;
385     }
386
387     /**
388      * Tunes the peer holding this parameters to request client authentication
389      */
390     protected void setWantClientAuth(boolean want) {
391         want_client_auth = want;
392         // reset the need_client_auth setting
393         need_client_auth = false;
394     }
395
396     /**
397      * Returns the value indicating if the peer with this parameters
398      * tuned to request client authentication
399      * @return
400      */
401     protected boolean getWantClientAuth() {
402         return want_client_auth;
403     }
404
405     /**
406      * Allows/disallows the peer holding this parameters to
407      * create new SSL session
408      */
409     protected void setEnableSessionCreation(boolean flag) {
410         enable_session_creation = flag;
411     }
412
413     /**
414      * Returns the value indicating if the peer with this parameters
415      * allowed to cteate new SSL session
416      */
417     protected boolean getEnableSessionCreation() {
418         return enable_session_creation;
419     }
420
421     /**
422      * Returns the clone of this object.
423      * @return the clone.
424      */
425     protected Object clone() {
426 // BEGIN android-changed
427         try {
428             return super.clone();
429         } catch (CloneNotSupportedException e) {
430             throw new AssertionError(e);
431         }
432 // END android-changed
433     }
434
435     /**
436      * Gets the default trust manager.
437      *
438      * TODO: Move this to a published API under dalvik.system.
439      */
440     public static X509TrustManager getDefaultTrustManager() {
441         return defaultTrustManager;
442     }
443 }