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