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