blob: da36fa3f5c68045826330e9db12c5ea24f003b24 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.ssl;
27
28import java.net.Socket;
29
30import java.security.*;
31import java.security.cert.*;
32
33import javax.net.ssl.*;
34
35public class SSLContextImpl extends SSLContextSpi {
36
37 private static final Debug debug = Debug.getInstance("ssl");
38
39 private final EphemeralKeyManager ephemeralKeyManager;
40 private final SSLSessionContextImpl clientCache;
41 private final SSLSessionContextImpl serverCache;
42
43 private boolean isInitialized;
44
45 private X509ExtendedKeyManager keyManager;
46 private X509TrustManager trustManager;
47 private SecureRandom secureRandom;
48
49 public SSLContextImpl() {
50 this(null);
51 }
52
53 SSLContextImpl(SSLContextImpl other) {
54 if (other == null) {
55 ephemeralKeyManager = new EphemeralKeyManager();
56 clientCache = new SSLSessionContextImpl();
57 serverCache = new SSLSessionContextImpl();
58 } else {
59 ephemeralKeyManager = other.ephemeralKeyManager;
60 clientCache = other.clientCache;
61 serverCache = other.serverCache;
62 }
63 }
64
65 protected void engineInit(KeyManager[] km, TrustManager[] tm,
66 SecureRandom sr) throws KeyManagementException {
67 isInitialized = false;
68 keyManager = chooseKeyManager(km);
69
70 if (tm == null) {
71 try {
72 TrustManagerFactory tmf = TrustManagerFactory.getInstance(
73 TrustManagerFactory.getDefaultAlgorithm());
74 tmf.init((KeyStore)null);
75 tm = tmf.getTrustManagers();
76 } catch (Exception e) {
77 // eat
78 }
79 }
80 trustManager = chooseTrustManager(tm);
81
82 if (sr == null) {
83 secureRandom = JsseJce.getSecureRandom();
84 } else {
85 if (SunJSSE.isFIPS() && (sr.getProvider() != SunJSSE.cryptoProvider)) {
86 throw new KeyManagementException
87 ("FIPS mode: SecureRandom must be from provider "
88 + SunJSSE.cryptoProvider.getName());
89 }
90 secureRandom = sr;
91 }
92
93 /*
94 * The initial delay of seeding the random number generator
95 * could be long enough to cause the initial handshake on our
96 * first connection to timeout and fail. Make sure it is
97 * primed and ready by getting some initial output from it.
98 */
99 if (debug != null && Debug.isOn("sslctx")) {
100 System.out.println("trigger seeding of SecureRandom");
101 }
102 secureRandom.nextInt();
103 if (debug != null && Debug.isOn("sslctx")) {
104 System.out.println("done seeding SecureRandom");
105 }
106 isInitialized = true;
107 }
108
109 private X509TrustManager chooseTrustManager(TrustManager[] tm)
110 throws KeyManagementException {
111 // We only use the first instance of X509TrustManager passed to us.
112 for (int i = 0; tm != null && i < tm.length; i++) {
113 if (tm[i] instanceof X509TrustManager) {
114 if (SunJSSE.isFIPS() && !(tm[i] instanceof X509TrustManagerImpl)) {
115 throw new KeyManagementException
116 ("FIPS mode: only SunJSSE TrustManagers may be used");
117 }
118 return (X509TrustManager)tm[i];
119 }
120 }
121
122 // nothing found, return a dummy X509TrustManager.
123 return DummyX509TrustManager.INSTANCE;
124 }
125
126 private X509ExtendedKeyManager chooseKeyManager(KeyManager[] kms)
127 throws KeyManagementException {
128 for (int i = 0; kms != null && i < kms.length; i++) {
129 KeyManager km = kms[i];
130 if (km instanceof X509KeyManager == false) {
131 continue;
132 }
133 if (SunJSSE.isFIPS()) {
134 // In FIPS mode, require that one of SunJSSE's own keymanagers
135 // is used. Otherwise, we cannot be sure that only keys from
136 // the FIPS token are used.
137 if ((km instanceof X509KeyManagerImpl)
138 || (km instanceof SunX509KeyManagerImpl)) {
139 return (X509ExtendedKeyManager)km;
140 } else {
141 // throw exception, we don't want to silently use the
142 // dummy keymanager without telling the user.
143 throw new KeyManagementException
144 ("FIPS mode: only SunJSSE KeyManagers may be used");
145 }
146 }
147 if (km instanceof X509ExtendedKeyManager) {
148 return (X509ExtendedKeyManager)km;
149 }
150 if (debug != null && Debug.isOn("sslctx")) {
151 System.out.println(
152 "X509KeyManager passed to " +
153 "SSLContext.init(): need an " +
154 "X509ExtendedKeyManager for SSLEngine use");
155 }
156 return new AbstractWrapper((X509KeyManager)km);
157 }
158
159 // nothing found, return a dummy X509ExtendedKeyManager
160 return DummyX509KeyManager.INSTANCE;
161 }
162
163 protected SSLSocketFactory engineGetSocketFactory() {
164 if (!isInitialized) {
165 throw new IllegalStateException(
166 "SSLContextImpl is not initialized");
167 }
168 return new SSLSocketFactoryImpl(this);
169 }
170
171 protected SSLServerSocketFactory engineGetServerSocketFactory() {
172 if (!isInitialized) {
173 throw new IllegalStateException("SSLContext is not initialized");
174 }
175 return new SSLServerSocketFactoryImpl(this);
176 }
177
178 protected SSLEngine engineCreateSSLEngine() {
179 if (!isInitialized) {
180 throw new IllegalStateException(
181 "SSLContextImpl is not initialized");
182 }
183 return new SSLEngineImpl(this);
184 }
185
186 protected SSLEngine engineCreateSSLEngine(String host, int port) {
187 if (!isInitialized) {
188 throw new IllegalStateException(
189 "SSLContextImpl is not initialized");
190 }
191 return new SSLEngineImpl(this, host, port);
192 }
193
194 protected SSLSessionContext engineGetClientSessionContext() {
195 return clientCache;
196 }
197
198 protected SSLSessionContext engineGetServerSessionContext() {
199 return serverCache;
200 }
201
202 SecureRandom getSecureRandom() {
203 return secureRandom;
204 }
205
206 X509ExtendedKeyManager getX509KeyManager() {
207 return keyManager;
208 }
209
210 X509TrustManager getX509TrustManager() {
211 return trustManager;
212 }
213
214 EphemeralKeyManager getEphemeralKeyManager() {
215 return ephemeralKeyManager;
216 }
217
218}
219
220// Dummy X509TrustManager implementation, rejects all peer certificates.
221// Used if the application did not specify a proper X509TrustManager.
222final class DummyX509TrustManager implements X509TrustManager {
223
224 static final X509TrustManager INSTANCE = new DummyX509TrustManager();
225
226 private DummyX509TrustManager() {
227 // empty
228 }
229
230 /*
231 * Given the partial or complete certificate chain
232 * provided by the peer, build a certificate path
233 * to a trusted root and return if it can be
234 * validated and is trusted for client SSL authentication.
235 * If not, it throws an exception.
236 */
237 public void checkClientTrusted(X509Certificate[] chain, String authType)
238 throws CertificateException {
239 throw new CertificateException(
240 "No X509TrustManager implementation avaiable");
241 }
242
243 /*
244 * Given the partial or complete certificate chain
245 * provided by the peer, build a certificate path
246 * to a trusted root and return if it can be
247 * validated and is trusted for server SSL authentication.
248 * If not, it throws an exception.
249 */
250 public void checkServerTrusted(X509Certificate[] chain, String authType)
251 throws CertificateException {
252 throw new CertificateException(
253 "No X509TrustManager implementation available");
254 }
255
256 /*
257 * Return an array of issuer certificates which are trusted
258 * for authenticating peers.
259 */
260 public X509Certificate[] getAcceptedIssuers() {
261 return new X509Certificate[0];
262 }
263}
264
265/*
266 * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
267 */
268final class AbstractWrapper extends X509ExtendedKeyManager {
269
270 private final X509KeyManager km;
271
272 AbstractWrapper(X509KeyManager km) {
273 this.km = km;
274 }
275
276 public String[] getClientAliases(String keyType, Principal[] issuers) {
277 return km.getClientAliases(keyType, issuers);
278 }
279
280 public String chooseClientAlias(String[] keyType, Principal[] issuers,
281 Socket socket) {
282 return km.chooseClientAlias(keyType, issuers, socket);
283 }
284
285 public String[] getServerAliases(String keyType, Principal[] issuers) {
286 return km.getServerAliases(keyType, issuers);
287 }
288
289 public String chooseServerAlias(String keyType, Principal[] issuers,
290 Socket socket) {
291 return km.chooseServerAlias(keyType, issuers, socket);
292 }
293
294 public X509Certificate[] getCertificateChain(String alias) {
295 return km.getCertificateChain(alias);
296 }
297
298 public PrivateKey getPrivateKey(String alias) {
299 return km.getPrivateKey(alias);
300 }
301
302 // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
303 // X509ExtendedKeymanager. It defines them to return null;
304}
305
306
307// Dummy X509KeyManager implementation, never returns any certificates/keys.
308// Used if the application did not specify a proper X509TrustManager.
309final class DummyX509KeyManager extends X509ExtendedKeyManager {
310
311 static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
312
313 private DummyX509KeyManager() {
314 // empty
315 }
316
317 /*
318 * Get the matching aliases for authenticating the client side of a secure
319 * socket given the public key type and the list of
320 * certificate issuer authorities recognized by the peer (if any).
321 */
322 public String[] getClientAliases(String keyType, Principal[] issuers) {
323 return null;
324 }
325
326 /*
327 * Choose an alias to authenticate the client side of a secure
328 * socket given the public key type and the list of
329 * certificate issuer authorities recognized by the peer (if any).
330 */
331 public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
332 Socket socket) {
333 return null;
334 }
335
336 /*
337 * Choose an alias to authenticate the client side of an
338 * engine given the public key type and the list of
339 * certificate issuer authorities recognized by the peer (if any).
340 */
341 public String chooseEngineClientAlias(
342 String[] keyTypes, Principal[] issuers, SSLEngine engine) {
343 return null;
344 }
345
346 /*
347 * Get the matching aliases for authenticating the server side of a secure
348 * socket given the public key type and the list of
349 * certificate issuer authorities recognized by the peer (if any).
350 */
351 public String[] getServerAliases(String keyType, Principal[] issuers) {
352 return null;
353 }
354
355 /*
356 * Choose an alias to authenticate the server side of a secure
357 * socket given the public key type and the list of
358 * certificate issuer authorities recognized by the peer (if any).
359 */
360 public String chooseServerAlias(String keyType, Principal[] issuers,
361 Socket socket) {
362 return null;
363 }
364
365 /*
366 * Choose an alias to authenticate the server side of an engine
367 * given the public key type and the list of
368 * certificate issuer authorities recognized by the peer (if any).
369 */
370 public String chooseEngineServerAlias(
371 String keyType, Principal[] issuers, SSLEngine engine) {
372 return null;
373 }
374
375 /**
376 * Returns the certificate chain associated with the given alias.
377 *
378 * @param alias the alias name
379 *
380 * @return the certificate chain (ordered with the user's certificate first
381 * and the root certificate authority last)
382 */
383 public X509Certificate[] getCertificateChain(String alias) {
384 return null;
385 }
386
387 /*
388 * Returns the key associated with the given alias, using the given
389 * password to recover it.
390 *
391 * @param alias the alias name
392 *
393 * @return the requested key
394 */
395 public PrivateKey getPrivateKey(String alias) {
396 return null;
397 }
398}