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