1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server.ssl;
15
16 import java.io.ByteArrayInputStream;
17 import java.io.File;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.InetAddress;
21 import java.net.ServerSocket;
22 import java.net.Socket;
23 import java.net.SocketAddress;
24 import java.security.KeyStore;
25 import java.security.SecureRandom;
26 import java.security.Security;
27 import java.security.cert.X509Certificate;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Iterator;
31 import java.util.List;
32
33 import javax.net.ssl.KeyManager;
34 import javax.net.ssl.KeyManagerFactory;
35 import javax.net.ssl.SSLContext;
36 import javax.net.ssl.SSLException;
37 import javax.net.ssl.SSLPeerUnverifiedException;
38 import javax.net.ssl.SSLServerSocket;
39 import javax.net.ssl.SSLServerSocketFactory;
40 import javax.net.ssl.SSLSession;
41 import javax.net.ssl.SSLSocket;
42 import javax.net.ssl.TrustManager;
43 import javax.net.ssl.TrustManagerFactory;
44
45 import org.eclipse.jetty.http.HttpSchemes;
46 import org.eclipse.jetty.http.security.Password;
47 import org.eclipse.jetty.io.EndPoint;
48 import org.eclipse.jetty.io.bio.SocketEndPoint;
49 import org.eclipse.jetty.server.Request;
50 import org.eclipse.jetty.server.bio.SocketConnector;
51 import org.eclipse.jetty.util.TypeUtil;
52 import org.eclipse.jetty.util.log.Log;
53 import org.eclipse.jetty.util.resource.Resource;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class SslSocketConnector extends SocketConnector implements SslConnector
71 {
72
73
74
75 static final String CACHED_INFO_ATTR = CachedInfo.class.getName();
76
77
78
79
80
81
82
83
84
85
86
87
88 private static X509Certificate[] getCertChain(SSLSession sslSession)
89 {
90 try
91 {
92 javax.security.cert.X509Certificate javaxCerts[] = sslSession.getPeerCertificateChain();
93 if (javaxCerts == null || javaxCerts.length == 0)
94 return null;
95
96 int length = javaxCerts.length;
97 X509Certificate[] javaCerts = new X509Certificate[length];
98
99 java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
100 for (int i = 0; i < length; i++)
101 {
102 byte bytes[] = javaxCerts[i].getEncoded();
103 ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
104 javaCerts[i] = (X509Certificate) cf.generateCertificate(stream);
105 }
106
107 return javaCerts;
108 }
109 catch (SSLPeerUnverifiedException pue)
110 {
111 return null;
112 }
113 catch (Exception e)
114 {
115 Log.warn(Log.EXCEPTION, e);
116 return null;
117 }
118 }
119
120
121
122
123 private String _excludeCipherSuites[] = null;
124
125
126 private String _keystorePath=DEFAULT_KEYSTORE ;
127 private String _keystoreType = "JKS";
128
129
130 private boolean _needClientAuth = false;
131 private transient Password _password;
132 private transient Password _keyPassword;
133 private transient Password _trustPassword;
134 private String _protocol= "TLS";
135 private String _provider;
136 private String _secureRandomAlgorithm;
137 private String _sslKeyManagerFactoryAlgorithm = (Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.KeyManagerFactory.algorithm"));
138 private String _sslTrustManagerFactoryAlgorithm = (Security.getProperty("ssl.TrustManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.TrustManagerFactory.algorithm"));
139
140 private String _truststorePath;
141 private String _truststoreType = "JKS";
142
143
144 private boolean _wantClientAuth = false;
145 private int _handshakeTimeout = 0;
146
147 private SSLContext _context;
148
149
150
151
152
153
154 public SslSocketConnector()
155 {
156 super();
157 }
158
159
160
161 public void accept(int acceptorID)
162 throws IOException, InterruptedException
163 {
164 Socket socket = _serverSocket.accept();
165 configure(socket);
166
167 Connection connection=new SslConnection(socket);
168 connection.dispatch();
169 }
170
171
172 protected void configure(Socket socket)
173 throws IOException
174 {
175 super.configure(socket);
176 }
177
178
179 protected SSLContext createSSLContext() throws Exception
180 {
181 KeyManager[] keyManagers = getKeyManagers();
182 TrustManager[] trustManagers = getTrustManagers();
183 SecureRandom secureRandom = _secureRandomAlgorithm==null?null:SecureRandom.getInstance(_secureRandomAlgorithm);
184 SSLContext context = _provider==null?SSLContext.getInstance(_protocol):SSLContext.getInstance(_protocol, _provider);
185 context.init(keyManagers, trustManagers, secureRandom);
186 return context;
187 }
188
189
190 protected SSLServerSocketFactory createFactory()
191 throws Exception
192 {
193 if (_context==null)
194 _context=createSSLContext();
195
196 return _context.getServerSocketFactory();
197 }
198
199
200
201 protected KeyManager[] getKeyManagers() throws Exception
202 {
203 KeyStore keyStore = getKeyStore(_keystorePath, _keystoreType, _password==null?null:_password.toString());
204
205 KeyManagerFactory keyManagerFactory=KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm);
206 keyManagerFactory.init(keyStore,_keyPassword==null?(_password==null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray());
207 return keyManagerFactory.getKeyManagers();
208 }
209
210 protected TrustManager[] getTrustManagers() throws Exception
211 {
212 if (_truststorePath==null)
213 {
214 _truststorePath=_keystorePath;
215 _truststoreType=_keystoreType;
216
217 _trustPassword = _password;
218 _sslTrustManagerFactoryAlgorithm = _sslKeyManagerFactoryAlgorithm;
219 }
220 KeyStore trustStore = getKeyStore(_truststorePath, _truststoreType, _trustPassword==null?null:_trustPassword.toString());
221
222 TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm);
223 trustManagerFactory.init(trustStore);
224 return trustManagerFactory.getTrustManagers();
225 }
226
227 protected KeyStore getKeyStore(String keystorePath, String keystoreType, String keystorePassword) throws Exception
228 {
229 KeyStore keystore;
230 InputStream keystoreInputStream = null;
231 try
232 {
233 if (keystorePath!=null)
234 {
235 keystoreInputStream = Resource.newResource(keystorePath).getInputStream();
236 keystore=KeyStore.getInstance(keystoreType);
237 keystore.load(keystoreInputStream,keystorePassword==null?null:keystorePassword.toString().toCharArray());
238 return keystore;
239 }
240
241 return null;
242 }
243 finally
244 {
245 if (keystoreInputStream != null)
246 keystoreInputStream.close();
247 }
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270 public void customize(EndPoint endpoint, Request request)
271 throws IOException
272 {
273 super.customize(endpoint, request);
274 request.setScheme(HttpSchemes.HTTPS);
275
276 SocketEndPoint socket_end_point = (SocketEndPoint)endpoint;
277 SSLSocket sslSocket = (SSLSocket)socket_end_point.getTransport();
278
279 try
280 {
281 SSLSession sslSession = sslSocket.getSession();
282 String cipherSuite = sslSession.getCipherSuite();
283 Integer keySize;
284 String idStr;
285 X509Certificate[] certs;
286
287 CachedInfo cachedInfo = (CachedInfo) sslSession.getValue(CACHED_INFO_ATTR);
288 if (cachedInfo != null)
289 {
290 keySize = cachedInfo.getKeySize();
291 certs = cachedInfo.getCerts();
292 idStr = cachedInfo.getIdStr();
293 }
294 else
295 {
296 keySize = new Integer(ServletSSL.deduceKeyLength(cipherSuite));
297 certs = getCertChain(sslSession);
298 byte[] idBytes = sslSession.getId();
299 idStr = TypeUtil.toHexString(idBytes);
300 cachedInfo = new CachedInfo(keySize, certs,idStr);
301 sslSession.putValue(CACHED_INFO_ATTR, cachedInfo);
302 }
303
304 if (certs != null)
305 request.setAttribute("javax.servlet.request.X509Certificate", certs);
306 else if (_needClientAuth)
307 throw new IllegalStateException("no client auth");
308
309 request.setAttribute("javax.servlet.request.ssl_session_id", idStr);
310 request.setAttribute("javax.servlet.request.cipher_suite", cipherSuite);
311 request.setAttribute("javax.servlet.request.key_size", keySize);
312 }
313 catch (Exception e)
314 {
315 Log.warn(Log.EXCEPTION, e);
316 }
317 }
318
319
320 public String[] getExcludeCipherSuites() {
321 return _excludeCipherSuites;
322 }
323
324
325 public String getKeystore()
326 {
327 return _keystorePath;
328 }
329
330
331 public String getKeystoreType()
332 {
333 return (_keystoreType);
334 }
335
336
337 public boolean getNeedClientAuth()
338 {
339 return _needClientAuth;
340 }
341
342
343 public String getProtocol()
344 {
345 return _protocol;
346 }
347
348
349 public String getProvider() {
350 return _provider;
351 }
352
353
354 public String getSecureRandomAlgorithm()
355 {
356 return (this._secureRandomAlgorithm);
357 }
358
359
360 public String getSslKeyManagerFactoryAlgorithm()
361 {
362 return (this._sslKeyManagerFactoryAlgorithm);
363 }
364
365
366 public String getSslTrustManagerFactoryAlgorithm()
367 {
368 return (this._sslTrustManagerFactoryAlgorithm);
369 }
370
371
372 public String getTruststore()
373 {
374 return _truststorePath;
375 }
376
377
378 public String getTruststoreType()
379 {
380 return _truststoreType;
381 }
382
383
384 public boolean getWantClientAuth()
385 {
386 return _wantClientAuth;
387 }
388
389
390
391
392
393
394
395
396
397 public boolean isConfidential(Request request)
398 {
399 final int confidentialPort = getConfidentialPort();
400 return confidentialPort == 0 || confidentialPort == request.getServerPort();
401 }
402
403
404
405
406
407
408
409
410
411 public boolean isIntegral(Request request)
412 {
413 final int integralPort = getIntegralPort();
414 return integralPort == 0 || integralPort == request.getServerPort();
415 }
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
431 {
432 SSLServerSocketFactory factory = null;
433 SSLServerSocket socket = null;
434
435 try
436 {
437 factory = createFactory();
438
439 socket = (SSLServerSocket) (host==null?
440 factory.createServerSocket(port,backlog):
441 factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
442
443 if (_wantClientAuth)
444 socket.setWantClientAuth(_wantClientAuth);
445 if (_needClientAuth)
446 socket.setNeedClientAuth(_needClientAuth);
447
448 if (_excludeCipherSuites != null && _excludeCipherSuites.length >0)
449 {
450 List excludedCSList = Arrays.asList(_excludeCipherSuites);
451 String[] enabledCipherSuites = socket.getEnabledCipherSuites();
452 List enabledCSList = new ArrayList(Arrays.asList(enabledCipherSuites));
453 Iterator exIter = excludedCSList.iterator();
454
455 while (exIter.hasNext())
456 {
457 String cipherName = (String)exIter.next();
458 if (enabledCSList.contains(cipherName))
459 {
460 enabledCSList.remove(cipherName);
461 }
462 }
463 enabledCipherSuites = (String[])enabledCSList.toArray(new String[enabledCSList.size()]);
464
465 socket.setEnabledCipherSuites(enabledCipherSuites);
466 }
467
468 }
469 catch (IOException e)
470 {
471 throw e;
472 }
473 catch (Exception e)
474 {
475 Log.warn(e.toString());
476 Log.debug(e);
477 throw new IOException("!JsseListener: " + e);
478 }
479 return socket;
480 }
481
482
483
484
485
486 public void setExcludeCipherSuites(String[] cipherSuites) {
487 this._excludeCipherSuites = cipherSuites;
488 }
489
490
491 public void setKeyPassword(String password)
492 {
493 _keyPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
494 }
495
496
497
498
499
500 public void setKeystore(String keystore)
501 {
502 _keystorePath = keystore;
503 }
504
505
506 public void setKeystoreType(String keystoreType)
507 {
508 _keystoreType = keystoreType;
509 }
510
511
512
513
514
515
516
517 public void setNeedClientAuth(boolean needClientAuth)
518 {
519 _needClientAuth = needClientAuth;
520 }
521
522
523 public void setPassword(String password)
524 {
525 _password = Password.getPassword(PASSWORD_PROPERTY,password,null);
526 }
527
528
529 public void setTrustPassword(String password)
530 {
531 _trustPassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
532 }
533
534
535 public void setProtocol(String protocol)
536 {
537 _protocol = protocol;
538 }
539
540
541 public void setProvider(String _provider) {
542 this._provider = _provider;
543 }
544
545
546 public void setSecureRandomAlgorithm(String algorithm)
547 {
548 this._secureRandomAlgorithm = algorithm;
549 }
550
551
552 public void setSslKeyManagerFactoryAlgorithm(String algorithm)
553 {
554 this._sslKeyManagerFactoryAlgorithm = algorithm;
555 }
556
557
558 public void setSslTrustManagerFactoryAlgorithm(String algorithm)
559 {
560 this._sslTrustManagerFactoryAlgorithm = algorithm;
561 }
562
563
564 public void setTruststore(String truststore)
565 {
566 _truststorePath = truststore;
567 }
568
569
570 public void setTruststoreType(String truststoreType)
571 {
572 _truststoreType = truststoreType;
573 }
574
575 public void setSslContext(SSLContext sslContext)
576 {
577 _context = sslContext;
578 }
579
580
581
582
583
584
585 public SSLContext getSslContext()
586 {
587 try
588 {
589 if (_context == null)
590 _context=createSSLContext();
591 }
592 catch(Exception e)
593 {
594 throw new RuntimeException(e);
595 }
596
597 return _context;
598 }
599
600
601
602
603
604
605
606
607
608 public void setWantClientAuth(boolean wantClientAuth)
609 {
610 _wantClientAuth = wantClientAuth;
611 }
612
613
614
615
616
617
618
619 public void setHandshakeTimeout (int msec)
620 {
621 _handshakeTimeout = msec;
622 }
623
624
625
626 public int getHandshakeTimeout ()
627 {
628 return _handshakeTimeout;
629 }
630
631
632
633
634
635
636 private class CachedInfo
637 {
638 private final X509Certificate[] _certs;
639 private final Integer _keySize;
640 private final String _idStr;
641
642
643 CachedInfo(Integer keySize, X509Certificate[] certs,String id)
644 {
645 this._keySize = keySize;
646 this._certs = certs;
647 this._idStr = id;
648 }
649
650 X509Certificate[] getCerts()
651 {
652 return _certs;
653 }
654
655 Integer getKeySize()
656 {
657 return _keySize;
658 }
659
660 String getIdStr ()
661 {
662 return _idStr;
663 }
664 }
665
666
667
668 public class SslConnection extends Connection
669 {
670 public SslConnection(Socket socket) throws IOException
671 {
672 super(socket);
673 }
674
675 public void run()
676 {
677 try
678 {
679 int handshakeTimeout = getHandshakeTimeout();
680 int oldTimeout = _socket.getSoTimeout();
681 if (handshakeTimeout > 0)
682 _socket.setSoTimeout(handshakeTimeout);
683
684 ((SSLSocket)_socket).startHandshake();
685
686 if (handshakeTimeout>0)
687 _socket.setSoTimeout(oldTimeout);
688
689 super.run();
690 }
691 catch (SSLException e)
692 {
693 Log.debug(e);
694 try{close();}
695 catch(IOException e2){Log.ignore(e2);}
696 }
697 catch (IOException e)
698 {
699 Log.debug(e);
700 try{close();}
701 catch(IOException e2){Log.ignore(e2);}
702 }
703 }
704 }
705
706
707
708
709
710
711 public String getAlgorithm()
712 {
713 throw new UnsupportedOperationException();
714 }
715
716
717
718
719
720
721 public void setAlgorithm(String algorithm)
722 {
723 throw new UnsupportedOperationException();
724 }
725 }