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