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